From 82fd65665f997924adbfeaacb640495716a064f2 Mon Sep 17 00:00:00 2001 From: 6543 <6543@obermui.de> Date: Tue, 16 Nov 2021 21:07:53 +0100 Subject: [PATCH] Add linter bidichk to prevent malicios utf8 chars (#516) bidichk checks for dangerous unicode character sequences (https://github.com/golangci/golangci-lint/pull/2330) --- .golangci.yml | 4 + go.mod | 3 +- go.sum | 258 +- .../checknoglobals/check_no_globals.go | 41 +- vendor/github.com/Antonboom/nilnil/LICENSE | 21 + .../Antonboom/nilnil/pkg/analyzer/analyzer.go | 148 + .../Antonboom/nilnil/pkg/analyzer/config.go | 77 + .../nilnil/pkg/analyzer/func_type_stack.go | 29 + .../blizzy78/varnamelen/.editorconfig | 9 + .../github.com/blizzy78/varnamelen/.gitignore | 1 + .../blizzy78/varnamelen/.golangci.yml | 20 + .../blizzy78/varnamelen/.travis.yml | 7 + vendor/github.com/blizzy78/varnamelen/LICENSE | 18 + .../github.com/blizzy78/varnamelen/README.md | 89 + vendor/github.com/blizzy78/varnamelen/go.mod | 10 + vendor/github.com/blizzy78/varnamelen/go.sum | 31 + .../varnamelen/varnamelen.code-workspace | 13 + .../blizzy78/varnamelen/varnamelen.go | 342 +++ vendor/github.com/breml/bidichk/LICENSE | 21 + .../breml/bidichk/pkg/bidichk/bidichk.go | 67 + vendor/github.com/butuzov/ireturn/LICENSE | 21 + .../butuzov/ireturn/analyzer/analyzer.go | 193 ++ .../butuzov/ireturn/analyzer/disallow.go | 45 + .../butuzov/ireturn/analyzer/std.go | 186 ++ .../butuzov/ireturn/config/allow.go | 17 + .../butuzov/ireturn/config/config.go | 66 + .../github.com/butuzov/ireturn/config/new.go | 74 + .../butuzov/ireturn/config/reject.go | 17 + .../github.com/butuzov/ireturn/types/iface.go | 7 + .../github.com/butuzov/ireturn/types/names.go | 8 + .../github.com/butuzov/ireturn/types/types.go | 11 + .../charithe/durationcheck/README.md | 23 +- .../charithe/durationcheck/durationcheck.go | 3 + .../esimonov/ifshort/pkg/analyzer/analyzer.go | 38 +- vendor/github.com/fatih/color/README.md | 2 +- vendor/github.com/fatih/color/go.mod | 4 +- vendor/github.com/fatih/color/go.sum | 10 +- vendor/github.com/fsnotify/fsnotify/.mailmap | 2 + .../github.com/fsnotify/fsnotify/.travis.yml | 36 - vendor/github.com/fsnotify/fsnotify/AUTHORS | 16 +- .../github.com/fsnotify/fsnotify/CHANGELOG.md | 116 +- vendor/github.com/fsnotify/fsnotify/README.md | 6 +- vendor/github.com/fsnotify/fsnotify/fen.go | 1 + .../github.com/fsnotify/fsnotify/fsnotify.go | 1 + vendor/github.com/fsnotify/fsnotify/go.mod | 4 +- vendor/github.com/fsnotify/fsnotify/go.sum | 4 +- .../github.com/fsnotify/fsnotify/inotify.go | 3 +- .../fsnotify/fsnotify/inotify_poller.go | 1 + vendor/github.com/fsnotify/fsnotify/kqueue.go | 1 + .../fsnotify/fsnotify/open_mode_bsd.go | 1 + .../fsnotify/fsnotify/open_mode_darwin.go | 1 + .../github.com/fsnotify/fsnotify/windows.go | 1 + vendor/github.com/go-critic/go-critic/LICENSE | 3 +- .../checkers/appendCombine_checker.go | 2 +- .../go-critic/checkers/argOrder_checker.go | 97 - .../go-critic/checkers/assignOp_checker.go | 102 - .../go-critic/checkers/badCall_checker.go | 63 - .../go-critic/checkers/badLock_checker.go | 116 - .../go-critic/go-critic/checkers/checkers.go | 96 + .../checkers/commentFormatting_checker.go | 1 + .../checkers/deferUnlambda_checker.go | 94 - .../go-critic/checkers/dupArg_checker.go | 133 - .../go-critic/checkers/dupCase_checker.go | 17 +- .../go-critic/checkers/elseif_checker.go | 2 +- .../checkers/emptyStringTest_checker.go | 58 - .../go-critic/checkers/equalFold_checker.go | 87 - .../go-critic/checkers/flagDeref_checker.go | 65 - .../go-critic/checkers/indexAlloc_checker.go | 50 - .../internal/astwalk/local_def_visitor.go | 2 +- .../internal/astwalk/stmt_list_walker.go | 6 +- .../internal/astwalk/type_expr_walker.go | 2 + .../checkers/internal/astwalk/visitor.go | 2 +- .../checkers/octalLiteral_checker.go | 67 +- .../go-critic/checkers/offBy1_checker.go | 66 - .../go-critic/checkers/regexpMust_checker.go | 47 - .../go-critic/checkers/ruleguard_checker.go | 155 +- .../go-critic/checkers/rulesdata/rulesdata.go | 2680 +++++++++++++++++ .../go-critic/checkers/sloppyLen_checker.go | 72 - .../checkers/sloppyTypeAssert_checker.go | 22 +- .../checkers/stringXbytes_checker.go | 47 - .../go-critic/checkers/switchTrue_checker.go | 49 - .../go-critic/checkers/typeUnparen_checker.go | 87 +- .../checkers/unnecessaryBlock_checker.go | 10 +- .../go-critic/checkers/unslice_checker.go | 59 - .../go-critic/checkers/valSwap_checker.go | 64 - .../go-critic/checkers/wrapperFunc_checker.go | 229 -- .../checkers/yodaStyleExpr_checker.go | 66 - .../go-critic/framework/linter/go_version.go | 51 + .../go-critic/framework/linter/lintpack.go | 50 + .../go-toolsmith/astequal/astequal.go | 8 + .../github.com/go-toolsmith/astequal/go.mod | 2 + .../github.com/go-toolsmith/astequal/go.sum | 2 + vendor/github.com/golang/snappy/AUTHORS | 2 + vendor/github.com/golang/snappy/CONTRIBUTORS | 2 + vendor/github.com/golang/snappy/decode.go | 4 + .../github.com/golang/snappy/decode_arm64.s | 494 +++ .../snappy/{decode_amd64.go => decode_asm.go} | 1 + .../github.com/golang/snappy/decode_other.go | 24 +- vendor/github.com/golang/snappy/encode.go | 4 + .../github.com/golang/snappy/encode_arm64.s | 722 +++++ .../snappy/{encode_amd64.go => encode_asm.go} | 1 + .../github.com/golang/snappy/encode_other.go | 2 +- vendor/github.com/golang/snappy/go.mod | 1 + .../golangci-lint/internal/cache/cache.go | 2 +- .../golangci-lint/internal/cache/default.go | 3 +- .../internal/renameio/renameio.go | 4 +- .../internal/robustio/robustio.go | 2 +- .../internal/robustio/robustio_flaky.go | 5 +- .../internal/robustio/robustio_other.go | 3 +- .../golangci-lint/pkg/commands/config.go | 2 + .../golangci-lint/pkg/commands/executor.go | 3 +- .../golangci-lint/pkg/commands/help.go | 2 +- .../golangci-lint/pkg/commands/linters.go | 1 + .../golangci-lint/pkg/commands/run.go | 11 +- .../golangci-lint/pkg/config/config.go | 9 +- .../golangci-lint/pkg/config/issues.go | 1 + .../pkg/config/linters_settings.go | 53 +- .../pkg/config/linters_settings_gocritic.go | 2 +- .../golangci-lint/pkg/config/reader.go | 5 + .../golangci/golangci-lint/pkg/config/run.go | 3 +- .../golangci-lint/pkg/fsutils/filecache.go | 4 +- .../golangci-lint/pkg/golinters/bidichk.go | 17 + .../pkg/golinters/contextcheck.go | 18 + .../golangci-lint/pkg/golinters/errcheck.go | 7 +- .../goanalysis/runner_loadingpackage.go | 2 +- .../golangci-lint/pkg/golinters/gocritic.go | 16 +- .../golangci-lint/pkg/golinters/gofumpt.go | 4 +- .../golangci-lint/pkg/golinters/gosec.go | 42 +- .../golangci-lint/pkg/golinters/ireturn.go | 30 + .../golangci-lint/pkg/golinters/nilnil.go | 30 + .../golangci-lint/pkg/golinters/nlreturn.go | 20 +- .../golangci-lint/pkg/golinters/revive.go | 4 +- .../golangci-lint/pkg/golinters/tenv.go | 33 + .../golangci-lint/pkg/golinters/varnamelen.go | 41 + .../golangci-lint/pkg/golinters/wsl.go | 2 +- .../pkg/lint/lintersdb/manager.go | 93 +- .../golangci/golangci-lint/pkg/lint/runner.go | 2 +- .../golangci-lint/pkg/printers/codeclimate.go | 2 +- .../golangci-lint/pkg/printers/github.go | 2 +- .../golangci-lint/pkg/result/issue.go | 2 +- .../pkg/result/processors/diff.go | 8 +- .../pkg/result/processors/nolint.go | 2 +- .../golangci-lint/pkg/timeutils/stopwatch.go | 12 +- vendor/github.com/golangci/revgrep/revgrep.go | 7 + .../gostaticanalysis/analysisutil/file.go | 12 + .../gostaticanalysis/analysisutil/go.mod | 8 +- .../gostaticanalysis/analysisutil/go.sum | 62 +- .../gostaticanalysis/analysisutil/ssa.go | 14 +- .../analysisutil/ssainspect.go | 10 + .../gostaticanalysis/analysisutil/types.go | 32 +- .../gostaticanalysis/comment/comment.go | 35 +- .../gostaticanalysis/comment/go.mod | 7 +- .../gostaticanalysis/comment/go.sum | 46 +- .../comment/passes/commentmap/commentmap.go | 3 +- .../rowserrcheck/passes/rowserr/rowserr.go | 89 +- .../pkg/paralleltest/paralleltest.go | 85 +- .../github.com/mattn/go-colorable/.travis.yml | 15 - .../github.com/mattn/go-colorable/README.md | 2 +- .../mattn/go-colorable/colorable_appengine.go | 1 + .../mattn/go-colorable/colorable_others.go | 4 +- .../mattn/go-colorable/colorable_windows.go | 14 +- vendor/github.com/mattn/go-colorable/go.mod | 4 +- vendor/github.com/mattn/go-colorable/go.sum | 10 +- .../mattn/go-colorable/noncolorable.go | 10 +- vendor/github.com/mattn/go-isatty/.travis.yml | 14 - vendor/github.com/mattn/go-isatty/go.mod | 2 +- .../github.com/mattn/go-isatty/isatty_bsd.go | 1 + .../mattn/go-isatty/isatty_others.go | 3 +- .../mattn/go-isatty/isatty_plan9.go | 1 + .../mattn/go-isatty/isatty_solaris.go | 9 +- .../mattn/go-isatty/isatty_tcgets.go | 3 +- .../mattn/go-isatty/isatty_windows.go | 6 +- .../github.com/mattn/go-isatty/renovate.json | 8 - vendor/github.com/mgechev/dots/resolve.go | 16 +- .../mgechev/revive/config/config.go | 44 +- vendor/github.com/mgechev/revive/lint/file.go | 5 +- .../mgechev/revive/rule/add-constant.go | 2 +- .../mgechev/revive/rule/empty-block.go | 2 +- .../mgechev/revive/rule/file-header.go | 6 +- .../mgechev/revive/rule/max-public-structs.go | 1 - .../mgechev/revive/rule/time-naming.go | 8 +- .../mitchellh/mapstructure/CHANGELOG.md | 10 +- .../mitchellh/mapstructure/decode_hooks.go | 3 +- .../mitchellh/mapstructure/mapstructure.go | 13 +- vendor/github.com/nakabonne/nestif/README.md | 8 +- vendor/github.com/nakabonne/nestif/go.mod | 2 +- vendor/github.com/nakabonne/nestif/nestif.go | 6 +- .../go-ruleguard/internal/goenv/goenv.go | 54 + .../go-ruleguard/internal/gogrep/compile.go | 220 +- .../internal/gogrep/gen_operations.go | 43 +- .../go-ruleguard/internal/gogrep/gogrep.go | 50 +- .../internal/gogrep/instructions.go | 9 + .../go-ruleguard/internal/gogrep/match.go | 417 ++- .../internal/gogrep/operation_string.go | 215 +- .../internal/gogrep/operations.gen.go | 452 ++- .../go-ruleguard/internal/gogrep/parse.go | 33 +- .../go-ruleguard/internal/gogrep/slices.go | 51 +- .../go-ruleguard/internal/stdinfo/stdinfo.go | 151 + .../internal/xsrcimporter/xsrcimporter.go | 29 + .../quasilyte/go-ruleguard/nodetag/nodetag.go | 1 + .../go-ruleguard/ruleguard/ast_walker.go | 322 ++ .../go-ruleguard/ruleguard/bundle.go | 2 +- .../go-ruleguard/ruleguard/engine.go | 129 +- .../go-ruleguard/ruleguard/filters.go | 257 +- .../go-ruleguard/ruleguard/go_version.go | 58 + .../go-ruleguard/ruleguard/gorule.go | 33 +- .../go-ruleguard/ruleguard/goutil/goutil.go | 46 + .../go-ruleguard/ruleguard/importer.go | 67 +- .../ruleguard/ir/filter_op.gen.go | 224 ++ .../ruleguard/ir/gen_filter_op.go | 136 + .../quasilyte/go-ruleguard/ruleguard/ir/ir.go | 112 + .../go-ruleguard/ruleguard/ir_loader.go | 720 +++++ .../go-ruleguard/ruleguard/ir_utils.go | 41 + .../go-ruleguard/ruleguard/irconv/irconv.go | 630 ++++ .../go-ruleguard/ruleguard/nodepath.go | 49 + .../go-ruleguard/ruleguard/parser.go | 988 ------ .../go-ruleguard/ruleguard/ruleguard.go | 93 +- .../go-ruleguard/ruleguard/runner.go | 63 +- .../ruleguard/textmatch/compile.go | 84 + .../ruleguard/textmatch/matchers.go | 72 + .../ruleguard/textmatch/textmatch.go | 26 + .../ruleguard/typematch/patternop_string.go | 7 +- .../ruleguard/typematch/typematch.go | 15 + .../quasilyte/go-ruleguard/ruleguard/utils.go | 46 +- .../github.com/securego/gosec/v2/.gitignore | 4 + .../securego/gosec/v2/.golangci.yml | 12 +- .../securego/gosec/v2/.goreleaser.yml | 2 + vendor/github.com/securego/gosec/v2/Makefile | 5 +- vendor/github.com/securego/gosec/v2/README.md | 26 +- vendor/github.com/securego/gosec/v2/USERS.md | 1 + .../github.com/securego/gosec/v2/analyzer.go | 94 +- vendor/github.com/securego/gosec/v2/config.go | 2 + .../securego/gosec/v2/entrypoint.sh | 2 +- vendor/github.com/securego/gosec/v2/go.mod | 12 +- vendor/github.com/securego/gosec/v2/go.sum | 35 +- .../github.com/securego/gosec/v2/helpers.go | 4 +- vendor/github.com/securego/gosec/v2/issue.go | 1 + .../securego/gosec/v2/renovate.json | 1 + .../securego/gosec/v2/rules/bad_defer.go | 45 +- .../securego/gosec/v2/rules/errors.go | 1 + .../securego/gosec/v2/rules/fileperms.go | 6 +- .../gosec/v2/rules/hardcoded_credentials.go | 2 +- .../securego/gosec/v2/rules/readfile.go | 1 + .../securego/gosec/v2/rules/subproc.go | 32 +- .../github.com/securego/gosec/v2/rules/tls.go | 26 +- vendor/github.com/sivchari/tenv/.gitignore | 15 + vendor/github.com/sivchari/tenv/.golangci.yml | 38 + vendor/github.com/sivchari/tenv/LICENSE | 21 + vendor/github.com/sivchari/tenv/README.md | 112 + vendor/github.com/sivchari/tenv/go.mod | 19 + vendor/github.com/sivchari/tenv/go.sum | 60 + vendor/github.com/sivchari/tenv/tenv.go | 199 ++ vendor/github.com/spf13/cast/.travis.yml | 16 - vendor/github.com/spf13/cast/README.md | 2 +- vendor/github.com/spf13/cast/cast.go | 5 + vendor/github.com/spf13/cast/caste.go | 148 +- .../spf13/cast/timeformattype_string.go | 27 + vendor/github.com/spf13/viper/README.md | 87 +- vendor/github.com/spf13/viper/go.mod | 13 +- vendor/github.com/spf13/viper/go.sum | 200 +- .../spf13/viper/internal/encoding/decoder.go | 61 + .../spf13/viper/internal/encoding/encoder.go | 60 + .../spf13/viper/internal/encoding/error.go | 7 + .../viper/internal/encoding/hcl/codec.go | 40 + .../viper/internal/encoding/json/codec.go | 17 + .../viper/internal/encoding/toml/codec.go | 45 + .../viper/internal/encoding/yaml/codec.go | 14 + vendor/github.com/spf13/viper/util.go | 14 +- vendor/github.com/spf13/viper/viper.go | 133 +- .../nlreturn/v2/pkg/nlreturn/nlreturn.go | 13 +- .../sylvia7788/contextcheck/.gitignore | 18 + .../sylvia7788/contextcheck/LICENSE | 201 ++ .../sylvia7788/contextcheck/Makefile | 5 + .../sylvia7788/contextcheck/README.md | 61 + .../sylvia7788/contextcheck/contextcheck.go | 507 ++++ .../github.com/sylvia7788/contextcheck/go.mod | 8 + .../github.com/sylvia7788/contextcheck/go.sum | 62 + vendor/github.com/tetafro/godot/.gitignore | 1 + vendor/github.com/tetafro/godot/README.md | 2 +- vendor/github.com/tetafro/godot/checks.go | 68 +- vendor/github.com/tetafro/godot/godot.go | 6 +- .../wrapcheck/v2/wrapcheck/wrapcheck.go | 36 +- vendor/golang.org/x/mod/modfile/read.go | 7 +- vendor/golang.org/x/mod/modfile/rule.go | 487 ++- vendor/golang.org/x/mod/module/module.go | 54 +- vendor/golang.org/x/mod/module/pseudo.go | 250 ++ vendor/golang.org/x/mod/semver/semver.go | 20 + .../go/analysis/passes/asmdecl/asmdecl.go | 37 +- .../go/analysis/passes/nilness/nilness.go | 29 + .../tools/go/analysis/passes/printf/printf.go | 7 +- .../testinggoroutine/testinggoroutine.go | 30 +- .../x/tools/go/analysis/passes/tests/tests.go | 60 +- .../x/tools/go/ast/astutil/rewrite.go | 6 +- .../x/tools/go/internal/gcimporter/bexport.go | 20 +- .../x/tools/go/internal/gcimporter/bimport.go | 1 + .../x/tools/go/internal/gcimporter/iexport.go | 198 +- .../x/tools/go/internal/gcimporter/iimport.go | 211 +- .../go/internal/gcimporter/support_go117.go | 16 + .../go/internal/gcimporter/support_go118.go | 20 + vendor/golang.org/x/tools/go/ssa/builder.go | 2 + vendor/golang.org/x/tools/go/ssa/doc.go | 89 +- vendor/golang.org/x/tools/go/ssa/emit.go | 4 +- vendor/golang.org/x/tools/go/ssa/print.go | 9 +- vendor/golang.org/x/tools/go/ssa/sanity.go | 8 +- vendor/golang.org/x/tools/go/ssa/ssa.go | 21 +- .../x/tools/go/types/objectpath/objectpath.go | 2 +- .../x/tools/internal/imports/zstdlib.go | 23 + .../x/tools/internal/lsp/fuzzy/input.go | 37 +- .../x/tools/internal/lsp/fuzzy/matcher.go | 23 +- .../x/tools/internal/lsp/fuzzy/symbol.go | 224 ++ .../internal/typeparams/{doc.go => common.go} | 14 + .../internal/typeparams/enabled_go117.go | 12 + .../internal/typeparams/enabled_go118.go | 15 + .../tools/internal/typeparams/notypeparams.go | 90 - .../x/tools/internal/typeparams/typeparams.go | 105 - .../internal/typeparams/typeparams_go117.go | 177 ++ .../internal/typeparams/typeparams_go118.go | 165 + .../x/tools/internal/typesinternal/types.go | 9 +- vendor/gopkg.in/ini.v1/.golangci.yml | 21 + vendor/gopkg.in/ini.v1/codecov.yml | 2 +- vendor/gopkg.in/ini.v1/ini.go | 4 +- vendor/gopkg.in/ini.v1/key.go | 17 +- vendor/gopkg.in/ini.v1/parser.go | 12 +- vendor/gopkg.in/ini.v1/section.go | 2 +- vendor/modules.txt | 91 +- 325 files changed, 15839 insertions(+), 4755 deletions(-) create mode 100644 vendor/github.com/Antonboom/nilnil/LICENSE create mode 100644 vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go create mode 100644 vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go create mode 100644 vendor/github.com/Antonboom/nilnil/pkg/analyzer/func_type_stack.go create mode 100644 vendor/github.com/blizzy78/varnamelen/.editorconfig create mode 100644 vendor/github.com/blizzy78/varnamelen/.gitignore create mode 100644 vendor/github.com/blizzy78/varnamelen/.golangci.yml create mode 100644 vendor/github.com/blizzy78/varnamelen/.travis.yml create mode 100644 vendor/github.com/blizzy78/varnamelen/LICENSE create mode 100644 vendor/github.com/blizzy78/varnamelen/README.md create mode 100644 vendor/github.com/blizzy78/varnamelen/go.mod create mode 100644 vendor/github.com/blizzy78/varnamelen/go.sum create mode 100644 vendor/github.com/blizzy78/varnamelen/varnamelen.code-workspace create mode 100644 vendor/github.com/blizzy78/varnamelen/varnamelen.go create mode 100644 vendor/github.com/breml/bidichk/LICENSE create mode 100644 vendor/github.com/breml/bidichk/pkg/bidichk/bidichk.go create mode 100644 vendor/github.com/butuzov/ireturn/LICENSE create mode 100644 vendor/github.com/butuzov/ireturn/analyzer/analyzer.go create mode 100644 vendor/github.com/butuzov/ireturn/analyzer/disallow.go create mode 100644 vendor/github.com/butuzov/ireturn/analyzer/std.go create mode 100644 vendor/github.com/butuzov/ireturn/config/allow.go create mode 100644 vendor/github.com/butuzov/ireturn/config/config.go create mode 100644 vendor/github.com/butuzov/ireturn/config/new.go create mode 100644 vendor/github.com/butuzov/ireturn/config/reject.go create mode 100644 vendor/github.com/butuzov/ireturn/types/iface.go create mode 100644 vendor/github.com/butuzov/ireturn/types/names.go create mode 100644 vendor/github.com/butuzov/ireturn/types/types.go create mode 100644 vendor/github.com/fsnotify/fsnotify/.mailmap delete mode 100644 vendor/github.com/fsnotify/fsnotify/.travis.yml delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/badLock_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/deferUnlambda_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go delete mode 100644 vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go create mode 100644 vendor/github.com/go-critic/go-critic/framework/linter/go_version.go create mode 100644 vendor/github.com/go-toolsmith/astequal/go.sum create mode 100644 vendor/github.com/golang/snappy/decode_arm64.s rename vendor/github.com/golang/snappy/{decode_amd64.go => decode_asm.go} (93%) create mode 100644 vendor/github.com/golang/snappy/encode_arm64.s rename vendor/github.com/golang/snappy/{encode_amd64.go => encode_asm.go} (97%) create mode 100644 vendor/github.com/golang/snappy/go.mod create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/bidichk.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/contextcheck.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/ireturn.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/nilnil.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/tenv.go create mode 100644 vendor/github.com/golangci/golangci-lint/pkg/golinters/varnamelen.go delete mode 100644 vendor/github.com/mattn/go-colorable/.travis.yml delete mode 100644 vendor/github.com/mattn/go-isatty/.travis.yml delete mode 100644 vendor/github.com/mattn/go-isatty/renovate.json create mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/stdinfo/stdinfo.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go delete mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/parser.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go create mode 100644 vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go create mode 100644 vendor/github.com/sivchari/tenv/.gitignore create mode 100644 vendor/github.com/sivchari/tenv/.golangci.yml create mode 100644 vendor/github.com/sivchari/tenv/LICENSE create mode 100644 vendor/github.com/sivchari/tenv/README.md create mode 100644 vendor/github.com/sivchari/tenv/go.mod create mode 100644 vendor/github.com/sivchari/tenv/go.sum create mode 100644 vendor/github.com/sivchari/tenv/tenv.go delete mode 100644 vendor/github.com/spf13/cast/.travis.yml create mode 100644 vendor/github.com/spf13/cast/timeformattype_string.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/decoder.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/encoder.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/error.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/json/codec.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/toml/codec.go create mode 100644 vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go create mode 100644 vendor/github.com/sylvia7788/contextcheck/.gitignore create mode 100644 vendor/github.com/sylvia7788/contextcheck/LICENSE create mode 100644 vendor/github.com/sylvia7788/contextcheck/Makefile create mode 100644 vendor/github.com/sylvia7788/contextcheck/README.md create mode 100644 vendor/github.com/sylvia7788/contextcheck/contextcheck.go create mode 100644 vendor/github.com/sylvia7788/contextcheck/go.mod create mode 100644 vendor/github.com/sylvia7788/contextcheck/go.sum create mode 100644 vendor/golang.org/x/mod/module/pseudo.go create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go create mode 100644 vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go create mode 100644 vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go rename vendor/golang.org/x/tools/internal/typeparams/{doc.go => common.go} (59%) create mode 100644 vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/notypeparams.go delete mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go create mode 100644 vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go create mode 100644 vendor/gopkg.in/ini.v1/.golangci.yml diff --git a/.golangci.yml b/.golangci.yml index f7da4ab8c..839d0eaed 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -8,3 +8,7 @@ linters: - gofmt - goimports - govet + - bidichk + +run: + timeout: 5m diff --git a/go.mod b/go.mod index 5191c08f5..bb3994ee6 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/go-sql-driver/mysql v1.6.0 github.com/gogits/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85 github.com/golang-jwt/jwt/v4 v4.1.0 - github.com/golangci/golangci-lint v1.42.1 + github.com/golangci/golangci-lint v1.43.0 github.com/google/go-github/v39 v39.2.0 github.com/gorilla/securecookie v1.1.1 github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -51,7 +51,6 @@ require ( golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 // indirect - golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca // indirect google.golang.org/grpc v1.41.0 diff --git a/go.sum b/go.sum index aac950201..194c43b36 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw= -4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= +4d63.com/gochecknoglobals v0.1.0 h1:zeZSRqj5yCg28tCkIV/z/lWbwvNm5qnKVS15PI8nhD0= +4d63.com/gochecknoglobals v0.1.0/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -23,6 +23,11 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= 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= @@ -32,6 +37,7 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 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/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= 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= @@ -50,8 +56,10 @@ contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EU dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s= gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU= -github.com/Antonboom/errname v0.1.4 h1:lGSlI42Gm4bI1e+IITtXJXvxFM8N7naWimVFKcb0McY= -github.com/Antonboom/errname v0.1.4/go.mod h1:jRXo3m0E0EuCnK3wbsSVH3X55Z4iTDLl6ZfCxwFj4TM= +github.com/Antonboom/errname v0.1.5 h1:IM+A/gz0pDhKmlt5KSNTVAvfLMb+65RxavBXpRtCUEg= +github.com/Antonboom/errname v0.1.5/go.mod h1:DugbBstvPFQbv/5uLcRRzfrNqKE9tVdVCqWCLp6Cifo= +github.com/Antonboom/nilnil v0.1.0 h1:DLDavmg0a6G/F4Lt9t7Enrbgb3Oph6LnDE6YVsmTt74= +github.com/Antonboom/nilnil v0.1.0/go.mod h1:PhHLvRPSghY5Y7mX4TW+BHZQYo1A8flE5H20D3IPZBo= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= @@ -120,7 +128,8 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/aokoli/goutils v1.0.1/go.mod h1:SijmP0QR8LtwsmDs8Yii5Z/S4trXFGFC2oO5g9DP+DQ= @@ -130,6 +139,7 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/ashanbrown/forbidigo v1.2.0 h1:RMlEFupPCxQ1IogYOQUnIQwGEUGK8g5vAPMRyJoSxbc= @@ -151,22 +161,27 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= -github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= github.com/bkielbasa/cyclop v1.2.0/go.mod h1:qOI0yy6A7dYC4Zgsa72Ppm9kONl0RoIlPbzot9mhmeI= github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= +github.com/blizzy78/varnamelen v0.3.0 h1:80mYO7Y5ppeEefg1Jzu+NBg16iwToOQVnDnNIoWSShs= +github.com/blizzy78/varnamelen v0.3.0/go.mod h1:hbwRdBvoBqxk34XyQ6HA0UH3G0/1TKuv5AC4eaBT0Ec= github.com/bmatcuk/doublestar/v4 v4.0.2 h1:X0krlUVAVmtr2cRoTqR8aDMrDqnB36ht8wpWTiQ3jsA= github.com/bmatcuk/doublestar/v4 v4.0.2/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/breml/bidichk v0.1.1 h1:Qpy8Rmgos9qdJxhka0K7ADEE5bQZX9PQUthkgggHpFM= +github.com/breml/bidichk v0.1.1/go.mod h1:zbfeitpevDUGI7V91Uzzuwrn4Vls8MoBMrwtt78jmso= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/butuzov/ireturn v0.1.1 h1:QvrO2QF2+/Cx1WA/vETCIYBKtRjc30vesdoPUNo1EbY= +github.com/butuzov/ireturn v0.1.1/go.mod h1:Wh6Zl3IMtTpaIKbmwzqi6olnM9ptYQxxVacMsOEFPoc= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -174,8 +189,8 @@ github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/charithe/durationcheck v0.0.8 h1:cnZrThioNW9gSV5JsRIXmkyHUbcDH7Y9hkzFDVc9/j0= -github.com/charithe/durationcheck v0.0.8/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= +github.com/charithe/durationcheck v0.0.9 h1:mPP4ucLrf/rKZiIG/a9IPXHGlh8p4CzgpyTy6EEutYk= +github.com/charithe/durationcheck v0.0.9/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af h1:spmv8nSH9h5oCQf40jt/ufBCt9j0/58u4G+rkeMqXGI= github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af/go.mod h1:Qjyv4H3//PWVzTeCezG2b9IRn6myJxJSr4TD/xo6ojU= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= @@ -283,7 +298,6 @@ github.com/containers/ocicrypt v1.1.0/go.mod h1:b8AOe0YR67uU8OqfVNcznfFpAzu3rdgU github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.5.0/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= @@ -373,16 +387,16 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/esimonov/ifshort v1.0.2 h1:K5s1W2fGfkoWXsFlxBNqT6J0ZCncPaKrGM5qe0bni68= -github.com/esimonov/ifshort v1.0.2/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= +github.com/esimonov/ifshort v1.0.3 h1:JD6x035opqGec5fZ0TLjXeROD2p5H7oLGn8MKfy9HTM= +github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= github.com/ettle/strcase v0.1.1 h1:htFueZyVeE1XNnMEfbqp5r67qAN/4r6ya1ysq8Q+Zcw= github.com/ettle/strcase v0.1.1/go.mod h1:hzDLsPC7/lwKyBOywSHEP89nt2pDgdy+No1NBA9o9VY= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= -github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 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/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= @@ -394,8 +408,9 @@ github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf/go.mod h1:VzmDKDJVZ github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/fzipp/gocyclo v0.3.1 h1:A9UeX3HJSXTBzvHzhqoYVuE0eAhe+aM8XBCCwsPMZOc= @@ -408,8 +423,8 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= -github.com/go-critic/go-critic v0.5.6 h1:siUR1+322iVikWXoV75I1YRfNaC/yaLzhdF9Zwd8Tus= -github.com/go-critic/go-critic v0.5.6/go.mod h1:cVjj0DfqewQVIlIAGexPCaGaZDAqGE29PYDDADIVNEo= +github.com/go-critic/go-critic v0.6.1 h1:lS8B9LH/VVsvQQP7Ao5TJyQqteVKVs3E4dXiHMyubtI= +github.com/go-critic/go-critic v0.6.1/go.mod h1:SdNCfU0yF3UBjtaZGw6586/WocupMOJuiqgom5DsQxM= 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= @@ -424,6 +439,7 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= @@ -453,8 +469,9 @@ github.com/go-toolsmith/astcast v1.0.0 h1:JojxlmI6STnFVG9yOImLeGREv8W2ocNUM+iOhR github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4= github.com/go-toolsmith/astcopy v1.0.0 h1:OMgl1b1MEpjFQ1m5ztEO06rz5CUd3oBv9RF7+DyvdG8= github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ= -github.com/go-toolsmith/astequal v1.0.0 h1:4zxD8j3JRFNyLN46lodQuqz3xdKSrur7U/sr0SDS/gQ= github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY= +github.com/go-toolsmith/astequal v1.0.1 h1:JbSszi42Jiqu36Gnf363HWS9MTEAz67vTQLponh3Moc= +github.com/go-toolsmith/astequal v1.0.1/go.mod h1:4oGA3EZXTVItV/ipGiOx7NWkY5veFfcsOJVS2YxltLw= github.com/go-toolsmith/astfmt v1.0.0 h1:A0vDDXt+vsvLEdbMFJAUBI/uTbRw1ffOPnxsILnFL6k= github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw= github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU= @@ -512,6 +529,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt 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/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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= @@ -531,8 +549,9 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.3 h1:fHPg5GQYlCeLIPB9BZqMVR5nR9A+IM5zcgeTdjMYmLA= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 h1:23T5iq8rbUYlhpt5DB4XJkc6BU31uODLD1o1gKvZmD0= github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4= github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a h1:w8hkcTqaFpzKqonE9uMCefW1WDie15eSP/4MssdenaM= @@ -541,16 +560,16 @@ github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613 h1:9kfjN3AdxcbsZB github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8= github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a h1:iR3fYXUjHCR97qWS8ch1y9zPNsgXThGwjKPrYfqMPks= github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU= -github.com/golangci/golangci-lint v1.42.1 h1:nC4WyrbdnNdohDVUoNKjy/4N4FTM1gCFaVeXecy6vzM= -github.com/golangci/golangci-lint v1.42.1/go.mod h1:MuInrVlgg2jq4do6XI1jbkErbVHVbwdrLLtGv6p2wPI= +github.com/golangci/golangci-lint v1.43.0 h1:SLwZFEmDgopqZpfP495zCtV9REUf551JJlJ51Ql7NZA= +github.com/golangci/golangci-lint v1.43.0/go.mod h1:VIFlUqidx5ggxDfQagdvd9E67UjMXtTHBkBQ7sHoC5Q= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0 h1:MfyDlzVjl1hoaPzPD4Gpb/QgoRfSBR0jdhwGyAWwMSA= github.com/golangci/lint-1 v0.0.0-20191013205115-297bf364a8e0/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca h1:kNY3/svz5T29MYHubXix4aDDuE3RWHkPvopM/EDv/MA= github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o= github.com/golangci/misspell v0.3.5 h1:pLzmVdl3VxTOncgzHcvLOKirdvcx/TydsClUQXTehjo= github.com/golangci/misspell v0.3.5/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA= -github.com/golangci/revgrep v0.0.0-20210208091834-cd28932614b5 h1:c9Mqqrm/Clj5biNaG7rABrmwUq88nHh0uABo2b/WYmc= -github.com/golangci/revgrep v0.0.0-20210208091834-cd28932614b5/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= +github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2 h1:SgM7GDZTxtTTQPU84heOxy34iG5Du7F2jcoZnvp+fXI= +github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2/go.mod h1:LK+zW4MpyytAWQRz0M4xnzEk50lSvqDQKfx304apFkY= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 h1:zwtduBRr5SSWhqsYNgcuWO2kFlpdOZbP0+yRjmvPGys= github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -580,6 +599,7 @@ github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ 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/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= 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= @@ -592,6 +612,9 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEivX+9mPgw= github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -599,11 +622,12 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254 h1:Nb2aRlC404yz7gQIfRZxX9/MLvQiqXyiBTJtgAy6yrI= @@ -625,15 +649,20 @@ github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.0.3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE= github.com/gostaticanalysis/analysisutil v0.1.0/go.mod h1:dMhHRU9KTiDcuLGdy87/2gTR8WruwYZrKdRq9m1O6uw= -github.com/gostaticanalysis/analysisutil v0.4.1 h1:/7clKqrVfiVwiBQLM0Uke4KvXnO6JcCTS7HwF2D6wG8= github.com/gostaticanalysis/analysisutil v0.4.1/go.mod h1:18U/DLpRgIUd459wGxVHE0fRgmo1UgHDcbw7F5idXu0= +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.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= -github.com/gostaticanalysis/comment v1.4.1 h1:xHopR5L2lRz6OsjH4R2HG5wRhW9ySl3FsHIvi5pcXwc= 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.0.0-20200621232751-01d4955beaa5 h1:rx8127mFPqXXsfPSo8BwnIU97MKFZc89WHAHt8PwDVY= github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/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/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -646,25 +675,30 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -680,8 +714,11 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= @@ -748,8 +785,8 @@ github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= -github.com/jingyugao/rowserrcheck v1.1.0 h1:u6h4eiNuCLqk73Ic5TXQq9yZS+uEXTdusn7c3w1Mr6A= -github.com/jingyugao/rowserrcheck v1.1.0/go.mod h1:TOQpc2SLx6huPfoFGK3UOnEG+u02D3C1GeosjupAKCA= +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/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -762,6 +799,7 @@ github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= 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.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -772,7 +810,6 @@ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMW github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -789,10 +826,10 @@ github.com/kisielk/errcheck v1.6.0 h1:YTDO4pNy7AUN/021p+JGHycQyYNIyMoenM1YDVK6Rl github.com/kisielk/errcheck v1.6.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= 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.2/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= @@ -811,8 +848,8 @@ 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.4.0 h1:2Nx7XbdbE/BYZeoip2mURKUdtHQRuy6Ug+wR7K9ywNM= github.com/kulti/thelper v0.4.0/go.mod h1:vMu2Cizjy/grP+jmsvOFDx1kYP6+PD1lqg4Yu5exl2U= -github.com/kunwardeep/paralleltest v1.0.2 h1:/jJRv0TiqPoEy/Y8dQxCFJhD56uS/pnvtatgTZBHokU= -github.com/kunwardeep/paralleltest v1.0.2/go.mod h1:ZPqNm1fVHPllh5LPVujzbVz1JN2GhLxSfY+oqUsvG30= +github.com/kunwardeep/paralleltest v1.0.3 h1:UdKIkImEAXjR1chUWLn+PNXqWUGs//7tzMeWuP7NhmI= +github.com/kunwardeep/paralleltest v1.0.3/go.mod h1:vLydzomDFpk7yu5UX02RmP0H8QfRPOV/oFhWN85Mjb4= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= @@ -836,9 +873,9 @@ github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -849,13 +886,17 @@ github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpAp github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/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.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.11 h1:nQ+aFkoE2TMGc0b68U2OKSexC+eq46+XwZzWXHRmPYs= +github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= @@ -864,8 +905,9 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -883,16 +925,18 @@ github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182aff github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mbilski/exhaustivestruct v1.2.0 h1:wCBmUnSYufAHO6J4AVWY6ff+oxWxsVFrwgOdMUQePUo= github.com/mbilski/exhaustivestruct v1.2.0/go.mod h1:OeTBVxQWoEmB2J2JCHmXWPJ0aksxSUOUy+nvtVEfzXc= -github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 h1:QASJXOGm2RZ5Ardbc86qNFvby9AqkLDibfChMtAg5QM= -github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= -github.com/mgechev/revive v1.1.1 h1:mkXNHP14Y6tfq+ocnQaiKEtgJDM41yaoyQq4qn6TD/4= -github.com/mgechev/revive v1.1.1/go.mod h1:PKqk4L74K6wVNwY2b6fr+9Qqr/3hIsHVfZCJdbvozrY= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 h1:zpIH83+oKzcpryru8ceC6BxnoG8TBrhgAvRg8obzup0= +github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517/go.mod h1:KQ7+USdGKfpPjXk4Ga+5XxQM4Lm4e3gAogrreFAYpOg= +github.com/mgechev/revive v1.1.2 h1:MiYA/o9M7REjvOF20QN43U8OtXDDHQFKLCtJnxLGLog= +github.com/mgechev/revive v1.1.2/go.mod h1:bnXsMr+ZTH09V5rssEI+jHAZ4z+ZdyhgO/zsy3EhK+0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -903,8 +947,9 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4 github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -940,8 +985,8 @@ github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRW github.com/mwitkow/go-proto-validators v0.0.0-20180403085117-0950a7990007/go.mod h1:m2XC9Qq0AlmmVksL6FktJCdTYyLk7V3fKyp0sl1yWQo= github.com/mwitkow/go-proto-validators v0.2.0/go.mod h1:ZfA1hW+UH/2ZHOWvQ3HnQaU0DtnpXu850MZiy+YUgcc= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/nakabonne/nestif v0.3.0 h1:+yOViDGhg8ygGrmII72nV9B/zGxY188TYpfolntsaPw= -github.com/nakabonne/nestif v0.3.0/go.mod h1:dI314BppzXjJ4HsCnbo7XzrJHPszZsjnk5wEBSYHI2c= +github.com/nakabonne/nestif v0.3.1 h1:wm28nZjhQY5HyYPx+weN3Q65k6ilSBxDb8v5S81B81U= +github.com/nakabonne/nestif v0.3.1/go.mod h1:9EtoZochLn5iUprVDmDjqGKPofoUEBL8U4Ngq6aY7OE= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= @@ -977,7 +1022,6 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -987,8 +1031,8 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1023,13 +1067,20 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +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/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= @@ -1050,6 +1101,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349 h1:Kq/3kL0k033ds3tyez5lFPrfQ74fNJ+OqCclRipubwA= github.com/polyfloyd/go-errorlint v0.0.0-20210722154253-910bb7978349/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= @@ -1097,12 +1149,12 @@ github.com/pseudomuto/protoc-gen-doc v1.3.2/go.mod h1:y5+P6n3iGrbKG+9O04V5ld71in github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q= github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI= github.com/quasilyte/go-ruleguard v0.3.1-0.20210203134552-1b5a410e1cc8/go.mod h1:KsAh3x0e7Fkpgs+Q9pNLS5XpFSvYCEVl5gP9Pp1xp30= -github.com/quasilyte/go-ruleguard v0.3.4 h1:F6l5p6+7WBcTKS7foNQ4wqA39zjn2+RbdbyzGxIq1B0= -github.com/quasilyte/go-ruleguard v0.3.4/go.mod h1:57FZgMnoo6jqxkYKmVj5Fc8vOt0rVzoE/UNAmFFIPqA= +github.com/quasilyte/go-ruleguard v0.3.13 h1:O1G41cq1jUr3cJmqp7vOUT0SokqjzmS9aESWJuIDRaY= +github.com/quasilyte/go-ruleguard v0.3.13/go.mod h1:Ul8wwdqR6kBVOCt2dipDBkE+T6vAV/iixkrKuRTN1oQ= github.com/quasilyte/go-ruleguard/dsl v0.3.0/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= -github.com/quasilyte/go-ruleguard/dsl v0.3.2/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/quasilyte/go-ruleguard/dsl v0.3.10/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/quasilyte/go-ruleguard/rules v0.0.0-20201231183845-9e62ed36efe1/go.mod h1:7JTjp89EGyU1d6XfBiXihJNG37wB2VRkd125Q1u7Plc= -github.com/quasilyte/go-ruleguard/rules v0.0.0-20210203162857-b223e0831f88/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= +github.com/quasilyte/go-ruleguard/rules v0.0.0-20210428214800-545e0d2e0bf7/go.mod h1:4cgAphtvu7Ftv7vOT2ZOYhC6CvBxZixcasr8qIOTA50= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 h1:L8QM9bvf68pVdQ3bCFZMDmnt9yqcMBro1pC7F+IPYMY= github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95/go.mod h1:rlzQ04UMyJXu/aOvhd8qT+hvDrFpiwqp8MRXDY9szc0= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -1133,18 +1185,19 @@ github.com/ryanrolds/sqlclosecheck v0.3.0 h1:AZx+Bixh8zdUBxUA1NxbxVAS78vTPq4rCb8 github.com/ryanrolds/sqlclosecheck v0.3.0/go.mod h1:1gREqxyTGR3lVtpngyFo3hZAgk0KCtEdgEkHwDbigdA= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanposhiho/wastedassign/v2 v2.0.6 h1:+6/hQIHKNJAUixEj6EmOngGIisyeI+T3335lYTyxRoA= github.com/sanposhiho/wastedassign/v2 v2.0.6/go.mod h1:KyZ0MWTwxxBmfwn33zh3k1dmsbF2ud9pAAGfoLfjhtI= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= -github.com/securego/gosec/v2 v2.8.1 h1:Tyy/nsH39TYCOkqf5HAgRE+7B5D8sHDwPdXRgFWokh8= -github.com/securego/gosec/v2 v2.8.1/go.mod h1:pUmsq6+VyFEElJMUX+QB3p3LWNHXg1R3xh2ssVJPs8Q= +github.com/securego/gosec/v2 v2.9.1 h1:anHKLS/ApTYU6NZkKa/5cQqqcbKZURjvc+MtR++S4EQ= +github.com/securego/gosec/v2 v2.9.1/go.mod h1:oDcDLcatOJxkCGaCaq8lua1jTnYf6Sou4wdiJ1n4iHc= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 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/shirou/gopsutil/v3 v3.21.7/go.mod h1:RGl11Y7XMTQPmHh8F0ayC6haKNBgH4PXMJuTAcMOlz4= +github.com/shirou/gopsutil/v3 v3.21.10/go.mod h1:t75NhzCZ/dYyPQjyQmrAYP6c8+LCdFANeBMdLPCNnew= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -1160,10 +1213,10 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/sivchari/tenv v1.4.7 h1:FdTpgRlTue5eb5nXIYgS/lyVXSjugU8UUVDwhP1NLU8= +github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/sonatard/noctx v0.0.1 h1:VC1Qhl6Oxx9vvWo3UDgrGXYCeKCe3Wbw7qAWL6FrmTY= @@ -1177,8 +1230,9 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= @@ -1196,11 +1250,11 @@ 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.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= -github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/ssgreg/nlreturn/v2 v2.1.0 h1:6/s4Rc49L6Uo6RLjhWZGBpWWjfzk2yrf1nIW8m4wgVA= -github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= +github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= +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/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1223,6 +1277,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/sylvia7788/contextcheck v1.0.4 h1:MsiVqROAdr0efZc/fOCt0c235qm9XJqHtWwM+2h2B04= +github.com/sylvia7788/contextcheck v1.0.4/go.mod h1:vuPKJMQ7MQ91ZTqfdyreNKwZjyUg6KO+IebVyQDedZQ= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1231,19 +1287,23 @@ github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpP github.com/tchap/go-patricia v2.2.6+incompatible/go.mod h1:bmLyhP68RS6kStMGxByiQ23RP/odRBOTVjwp2cDyi6I= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b h1:HxLVTlqcHhFAz3nWUcuvpH7WuOMv8LQoCWmruLfFH2U= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= -github.com/tetafro/godot v1.4.9 h1:wsNd0RuUxISqqudFqchsSsMqsM188DoZVPBeKl87tP0= -github.com/tetafro/godot v1.4.9/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= +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.11 h1:BVoBIqAf/2QdbFmSwAWnaIqDivZdOV0ZRwEm6jivLKw= +github.com/tetafro/godot v1.4.11/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/tevino/abool v1.2.0 h1:heAkClL8H6w+mK5md9dzsuohKeXHUpY7Vw0ZCKW+huA= github.com/tevino/abool v1.2.0/go.mod h1:qc66Pna1RiIsPa7O4Egxxs9OqkuxDX55zznh9K07Tzg= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94 h1:ig99OeTyDwQWhPe2iw9lwfQVF1KB3Q4fpP3X7/2VBG8= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk= -github.com/tklauser/go-sysconf v0.3.7/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4= -github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= +github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= +github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20200427203606-3cfed13b9966/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/tomarrell/wrapcheck/v2 v2.3.0 h1:i3DNjtyyL1xwaBQOsPPk8LAcpayWfQv2rxNi9b/eEx4= -github.com/tomarrell/wrapcheck/v2 v2.3.0/go.mod h1:aF5rnkdtqNWP/gC7vPUO5pKsB0Oac2FDTQP4F+dpZMU= +github.com/tomarrell/wrapcheck/v2 v2.4.0 h1:mU4H9KsqqPZUALOUbVOpjy8qNQbWLoLI9fV68/1tq30= +github.com/tomarrell/wrapcheck/v2 v2.4.0/go.mod h1:68bQ/eJg55BROaRTbMjC7vuhL2OgfoG8bLp9ZyoBfyY= github.com/tomasen/realip v0.0.0-20180522021738-f0c99a92ddce/go.mod h1:o8v6yHRoik09Xen7gje4m9ERNah1d1PPsVq1VEx9vE4= github.com/tommy-muehle/go-mnd/v2 v2.4.0 h1:1t0f8Uiaq+fqKteUR4N9Umr6E99R+lDnLnq7PwX2PPE= github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= @@ -1269,9 +1329,9 @@ github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/X github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= -github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY= -github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= +github.com/valyala/fasthttp v1.30.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/quicktemplate v1.7.0/go.mod h1:sqKJnoaOF88V07vkO+9FL8fb9uZg/VPSJnLYn+LmLk8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/viki-org/dnscache v0.0.0-20130720023526-c70c1f23c5d8/go.mod h1:dniwbG03GafCjFohMDmz6Zc6oCuiqgH6tGNyXTkHzXE= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= @@ -1306,6 +1366,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de 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.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= @@ -1363,6 +1424,7 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1412,8 +1474,9 @@ 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.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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 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-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1454,7 +1517,6 @@ golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/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-20200602114024-627f9648deb9/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= @@ -1469,6 +1531,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI= golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1484,6 +1549,10 @@ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1 h1:B333XXssMuKQeBwiNODx4TupZy7bf4sxFZnN2ZOcvUE= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1530,6 +1599,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1560,7 +1630,6 @@ golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7w 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-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1592,11 +1661,20 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/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-20210514084401-e8d321eab015/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-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359 h1:2B5p2L5IfGiD7+b9BOoRMC6DgObAVZV+Fsp050NqXik= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1646,6 +1724,7 @@ golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgw 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-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/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-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1718,11 +1797,16 @@ golang.org/x/tools v0.0.0-20210104081019-d8d6ddbec6ee/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/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.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1755,6 +1839,12 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1817,7 +1907,18 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca h1:+e+aQDO4/c9KaG8PXWHTc6/+Du6kz+BKcXCSnV4SSTE= google.golang.org/genproto v0.0.0-20211027162914-98a5263abeca/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= @@ -1848,10 +1949,15 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= @@ -1883,9 +1989,9 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= +gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= diff --git a/vendor/4d63.com/gochecknoglobals/checknoglobals/check_no_globals.go b/vendor/4d63.com/gochecknoglobals/checknoglobals/check_no_globals.go index 5b6325dd9..9ae889d4b 100644 --- a/vendor/4d63.com/gochecknoglobals/checknoglobals/check_no_globals.go +++ b/vendor/4d63.com/gochecknoglobals/checknoglobals/check_no_globals.go @@ -48,10 +48,12 @@ func flags() flag.FlagSet { return *flags } -func isAllowed(v ast.Node) bool { +func isAllowed(cm ast.CommentMap, v ast.Node) bool { switch i := v.(type) { + case *ast.GenDecl: + return hasEmbedComment(cm, i) case *ast.Ident: - return i.Name == "_" || i.Name == "version" || looksLikeError(i) + return i.Name == "_" || i.Name == "version" || looksLikeError(i) || identHasEmbedComment(cm, i) case *ast.CallExpr: if expr, ok := i.Fun.(*ast.SelectorExpr); ok { return isAllowedSelectorExpression(expr) @@ -96,6 +98,32 @@ func looksLikeError(i *ast.Ident) bool { return strings.HasPrefix(i.Name, prefix) } +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) @@ -108,6 +136,8 @@ func checkNoGlobals(pass *analysis.Pass) (interface{}, error) { continue } + fileCommentMap := ast.NewCommentMap(pass.Fset, file, file.Comments) + for _, decl := range file.Decls { genDecl, ok := decl.(*ast.GenDecl) if !ok { @@ -116,12 +146,15 @@ func checkNoGlobals(pass *analysis.Pass) (interface{}, error) { if genDecl.Tok != token.VAR { continue } + if isAllowed(fileCommentMap, genDecl) { + continue + } for _, spec := range genDecl.Specs { valueSpec := spec.(*ast.ValueSpec) onlyAllowedValues := false for _, vn := range valueSpec.Values { - if isAllowed(vn) { + if isAllowed(fileCommentMap, vn) { onlyAllowedValues = true continue } @@ -135,7 +168,7 @@ func checkNoGlobals(pass *analysis.Pass) (interface{}, error) { } for _, vn := range valueSpec.Names { - if isAllowed(vn) { + if isAllowed(fileCommentMap, vn) { continue } diff --git a/vendor/github.com/Antonboom/nilnil/LICENSE b/vendor/github.com/Antonboom/nilnil/LICENSE new file mode 100644 index 000000000..e2002e4d4 --- /dev/null +++ b/vendor/github.com/Antonboom/nilnil/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go new file mode 100644 index 000000000..3cbd3ffc2 --- /dev/null +++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/analyzer.go @@ -0,0 +1,148 @@ +package analyzer + +import ( + "go/ast" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +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 ( + types = []ast.Node{(*ast.TypeSpec)(nil)} + + funcAndReturns = []ast.Node{ + (*ast.FuncDecl)(nil), + (*ast.FuncLit)(nil), + (*ast.ReturnStmt)(nil), + } +) + +type typeSpecByName map[string]*ast.TypeSpec + +func (n *nilNil) run(pass *analysis.Pass) (interface{}, error) { + insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + typeSpecs := typeSpecByName{} + insp.Preorder(types, func(node ast.Node) { + t := node.(*ast.TypeSpec) + typeSpecs[t.Name.Name] = t + }) + + 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 + } + + fRes1, fRes2 := ft.Results.List[0], ft.Results.List[1] + if !(n.isDangerNilField(fRes1, typeSpecs) && n.isErrorField(fRes2)) { + return + } + + rRes1, rRes2 := v.Results[0], v.Results[1] + if isNil(rRes1) && isNil(rRes2) { + pass.Reportf(v.Pos(), reportMsg) + } + } + + return true + }) + + return nil, nil +} + +func (n *nilNil) isDangerNilField(f *ast.Field, typeSpecs typeSpecByName) bool { + return n.isDangerNilType(f.Type, typeSpecs) +} + +func (n *nilNil) isDangerNilType(t ast.Expr, typeSpecs typeSpecByName) bool { + switch v := t.(type) { + case *ast.StarExpr: + return n.checkedTypes.Contains(ptrType) + + case *ast.FuncType: + return n.checkedTypes.Contains(funcType) + + case *ast.InterfaceType: + return n.checkedTypes.Contains(ifaceType) + + case *ast.MapType: + return n.checkedTypes.Contains(mapType) + + case *ast.ChanType: + return n.checkedTypes.Contains(chanType) + + case *ast.Ident: + if t, ok := typeSpecs[v.Name]; ok { + return n.isDangerNilType(t.Type, nil) + } + } + return false +} + +func (n *nilNil) isErrorField(f *ast.Field) bool { + return isIdent(f.Type, "error") +} + +func isNil(e ast.Expr) bool { + return isIdent(e, "nil") +} + +func isIdent(n ast.Node, name string) bool { + i, ok := n.(*ast.Ident) + if !ok { + return false + } + return i.Name == name +} diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go new file mode 100644 index 000000000..520b813a5 --- /dev/null +++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/config.go @@ -0,0 +1,77 @@ +package analyzer + +import ( + "fmt" + "sort" + "strings" +) + +func newDefaultCheckedTypes() checkedTypes { + return checkedTypes{ + ptrType: struct{}{}, + funcType: struct{}{}, + ifaceType: struct{}{}, + mapType: struct{}{}, + chanType: struct{}{}, + } +} + +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" +) + +var knownTypes = []typeName{ptrType, funcType, ifaceType, mapType, chanType} + +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: + 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) + } +} diff --git a/vendor/github.com/Antonboom/nilnil/pkg/analyzer/func_type_stack.go b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/func_type_stack.go new file mode 100644 index 000000000..081761547 --- /dev/null +++ b/vendor/github.com/Antonboom/nilnil/pkg/analyzer/func_type_stack.go @@ -0,0 +1,29 @@ +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] +} diff --git a/vendor/github.com/blizzy78/varnamelen/.editorconfig b/vendor/github.com/blizzy78/varnamelen/.editorconfig new file mode 100644 index 000000000..bf1663fb2 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[**] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = tab +indent_size = 4 +trim_trailing_whitespace = true diff --git a/vendor/github.com/blizzy78/varnamelen/.gitignore b/vendor/github.com/blizzy78/varnamelen/.gitignore new file mode 100644 index 000000000..1a4a71669 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/.gitignore @@ -0,0 +1 @@ +/cmd/__debug_bin diff --git a/vendor/github.com/blizzy78/varnamelen/.golangci.yml b/vendor/github.com/blizzy78/varnamelen/.golangci.yml new file mode 100644 index 000000000..2b52fc63e --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/.golangci.yml @@ -0,0 +1,20 @@ +linters: + enable: + - gocognit + - gocritic + - gocyclo + - goerr113 + - golint + - interfacer + - nakedret + - prealloc + - unconvert + - unparam + +linters-settings: + gocognit: + min-complexity: 15 + gocyclo: + min-complexity: 10 + nakedret: + max-func-lines: 0 diff --git a/vendor/github.com/blizzy78/varnamelen/.travis.yml b/vendor/github.com/blizzy78/varnamelen/.travis.yml new file mode 100644 index 000000000..c3ea88740 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/.travis.yml @@ -0,0 +1,7 @@ +language: go +go: + - "1.15" +before_script: + - go get github.com/mattn/goveralls +after_script: + - goveralls -service=travis-ci diff --git a/vendor/github.com/blizzy78/varnamelen/LICENSE b/vendor/github.com/blizzy78/varnamelen/LICENSE new file mode 100644 index 000000000..810693c84 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/LICENSE @@ -0,0 +1,18 @@ +Copyright 2021 Maik Schreiber + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/blizzy78/varnamelen/README.md b/vendor/github.com/blizzy78/varnamelen/README.md new file mode 100644 index 000000000..7e507a90b --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/README.md @@ -0,0 +1,89 @@ +[![Build Status](https://api.travis-ci.com/blizzy78/varnamelen.svg?branch=master)](https://app.travis-ci.com/github/blizzy78/varnamelen) [![Coverage Status](https://coveralls.io/repos/github/blizzy78/varnamelen/badge.svg?branch=master)](https://coveralls.io/github/blizzy78/varnamelen?branch=master) [![GoDoc](https://pkg.go.dev/badge/github.com/blizzy78/varnamelen)](https://pkg.go.dev/github.com/blizzy78/varnamelen) + + +varnamelen +========== + +A Go Analyzer checking that the length of a variable's name matches its usage scope. + +A variable with a short name can be hard to use if the variable is used over a longer span of lines of code. +A longer variable name may be easier to comprehend. + +The analyzer can check variable names, method receiver names, as well as named return values. + +Conventional Go parameters such as `ctx context.Context` or `t *testing.T` will always be ignored. + +**Example output** + +``` +test.go:4:2: variable name 'x' is too short for the scope of its usage (varnamelen) + x := 123 + ^ +test.go:6:2: variable name 'i' is too short for the scope of its usage (varnamelen) + i := 10 + ^ +``` + + +Standalone Usage +---------------- + +The `cmd/` folder provides a standalone command line utility. You can build it like this: + +``` +go build -o varnamelen ./cmd/ +``` + +**Usage** + +``` +varnamelen: checks that the length of a variable's name matches its scope + +Usage: varnamelen [-flag] [package] + +A variable with a short name can be hard to use if the variable is used +over a longer span of lines of code. A longer variable name may be easier +to comprehend. + +Flags: + -V print version and exit + -all + no effect (deprecated) + -c int + display offending line with this many lines of context (default -1) + -checkReceiver + check method receiver names + -checkReturn + check named return values + -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 + -ignoreNames value + comma-separated list of ignored variable names + -json + emit JSON output + -maxDistance int + maximum number of lines of variable usage scope considered 'short' (default 5) + -memprofile string + write memory profile to this file + -minNameLength int + minimum length of variable name considered 'long' (default 3) + -source + no effect (deprecated) + -tags string + no effect (deprecated) + -trace string + write trace log to this file + -v no effect (deprecated) +``` + + +License +------- + +This package is licensed under the MIT license. diff --git a/vendor/github.com/blizzy78/varnamelen/go.mod b/vendor/github.com/blizzy78/varnamelen/go.mod new file mode 100644 index 000000000..0a6b16e63 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/go.mod @@ -0,0 +1,10 @@ +module github.com/blizzy78/varnamelen + +go 1.15 + +require ( + github.com/matryer/is v1.4.0 + golang.org/x/mod v0.5.0 // indirect + golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 // indirect + golang.org/x/tools v0.1.6 +) diff --git a/vendor/github.com/blizzy78/varnamelen/go.sum b/vendor/github.com/blizzy78/varnamelen/go.sum new file mode 100644 index 000000000..96264f219 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/go.sum @@ -0,0 +1,31 @@ +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= +github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw= +golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4= +golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +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-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/blizzy78/varnamelen/varnamelen.code-workspace b/vendor/github.com/blizzy78/varnamelen/varnamelen.code-workspace new file mode 100644 index 000000000..68c485c96 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/varnamelen.code-workspace @@ -0,0 +1,13 @@ +{ + "folders": [ + { + "path": "." + } + ], + "extensions": { + "recommendations": [ + "EditorConfig.EditorConfig", + "golang.go" + ] + } +} diff --git a/vendor/github.com/blizzy78/varnamelen/varnamelen.go b/vendor/github.com/blizzy78/varnamelen/varnamelen.go new file mode 100644 index 000000000..9c1959644 --- /dev/null +++ b/vendor/github.com/blizzy78/varnamelen/varnamelen.go @@ -0,0 +1,342 @@ +package varnamelen + +import ( + "go/ast" + "strings" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +// varNameLen is an analyzer that checks that the length of a variable's name matches its usage scope. +// It will create a report for a variable's assignment if that variable has a short name, but its +// usage scope is not considered "small." +type varNameLen struct { + // maxDistance is the longest distance, in source lines, that is being considered a "small scope." + maxDistance int + + // minNameLength is the minimum length of a variable's name that is considered "long." + minNameLength int + + // ignoreNames is an optional list of variable names that should be ignored completely. + ignoreNames stringsValue + + // checkReceiver determines whether a method receiver's name should be checked. + checkReceiver bool + + // checkReturn determines whether named return values should be checked. + checkReturn bool +} + +// stringsValue is the value of a list-of-strings flag. +type stringsValue struct { + Values []string +} + +// variable represents a declared variable. +type variable struct { + // name is the name of the variable. + name string + + // assign is the assign statement that declares the variable. + assign *ast.AssignStmt +} + +// parameter represents a declared function or method parameter. +type parameter struct { + // name is the name of the parameter. + name string + + // field is the declaration of the parameter. + field *ast.Field +} + +const ( + // defaultMaxDistance is the default value for the maximum distance between the declaration of a variable and its usage + // that is considered a "small scope." + defaultMaxDistance = 5 + + // defaultMinNameLength is the default value for the minimum length of a variable's name that is considered "long." + defaultMinNameLength = 3 +) + +// NewAnalyzer returns a new analyzer that checks variable name length. +func NewAnalyzer() *analysis.Analyzer { + vnl := varNameLen{ + maxDistance: defaultMaxDistance, + minNameLength: defaultMinNameLength, + ignoreNames: stringsValue{}, + } + + analyzer := analysis.Analyzer{ + Name: "varnamelen", + Doc: "checks that the length of a variable's name matches its scope\n\n" + + "A variable with a short name can be hard to use if the variable is used\n" + + "over a longer span of lines of code. A longer variable name may be easier\n" + + "to comprehend.", + + Run: func(pass *analysis.Pass) (interface{}, error) { + vnl.run(pass) + return nil, nil + }, + + Requires: []*analysis.Analyzer{ + inspect.Analyzer, + }, + } + + analyzer.Flags.IntVar(&vnl.maxDistance, "maxDistance", defaultMaxDistance, "maximum number of lines of variable usage scope considered 'short'") + analyzer.Flags.IntVar(&vnl.minNameLength, "minNameLength", defaultMinNameLength, "minimum length of variable name considered 'long'") + analyzer.Flags.Var(&vnl.ignoreNames, "ignoreNames", "comma-separated list of ignored variable names") + analyzer.Flags.BoolVar(&vnl.checkReceiver, "checkReceiver", false, "check method receiver names") + analyzer.Flags.BoolVar(&vnl.checkReturn, "checkReturn", false, "check named return values") + + return &analyzer +} + +// Run applies v to a package, according to pass. +func (v *varNameLen) run(pass *analysis.Pass) { + varToDist, paramToDist, returnToDist := v.distances(pass) + + for variable, dist := range varToDist { + if v.checkNameAndDistance(variable.name, dist) { + continue + } + pass.Reportf(variable.assign.Pos(), "variable name '%s' is too short for the scope of its usage", variable.name) + } + + for param, dist := range paramToDist { + if param.isConventional() { + continue + } + if v.checkNameAndDistance(param.name, dist) { + continue + } + pass.Reportf(param.field.Pos(), "parameter name '%s' is too short for the scope of its usage", param.name) + } + + for param, dist := range returnToDist { + if v.checkNameAndDistance(param.name, dist) { + continue + } + pass.Reportf(param.field.Pos(), "return value name '%s' is too short for the scope of its usage", param.name) + } +} + +// checkNameAndDistance returns true when name or dist are considered "short", or when name is to be ignored. +func (v *varNameLen) checkNameAndDistance(name string, dist int) bool { + if len(name) >= v.minNameLength { + return true + } + if dist <= v.maxDistance { + return true + } + if v.ignoreNames.contains(name) { + return true + } + return false +} + +// distances maps of variables or parameters and their longest usage distances. +func (v *varNameLen) distances(pass *analysis.Pass) (map[variable]int, map[parameter]int, map[parameter]int) { + assignIdents, paramIdents, returnIdents := v.idents(pass) + + varToDist := map[variable]int{} + + for _, ident := range assignIdents { + assign := ident.Obj.Decl.(*ast.AssignStmt) + variable := variable{ + name: ident.Name, + assign: assign, + } + + useLine := pass.Fset.Position(ident.NamePos).Line + declLine := pass.Fset.Position(assign.Pos()).Line + varToDist[variable] = useLine - declLine + } + + paramToDist := map[parameter]int{} + + for _, ident := range paramIdents { + field := ident.Obj.Decl.(*ast.Field) + param := parameter{ + name: ident.Name, + field: field, + } + + useLine := pass.Fset.Position(ident.NamePos).Line + declLine := pass.Fset.Position(field.Pos()).Line + paramToDist[param] = useLine - declLine + } + + returnToDist := map[parameter]int{} + + for _, ident := range returnIdents { + field := ident.Obj.Decl.(*ast.Field) + param := parameter{ + name: ident.Name, + field: field, + } + + useLine := pass.Fset.Position(ident.NamePos).Line + declLine := pass.Fset.Position(field.Pos()).Line + returnToDist[param] = useLine - declLine + } + + return varToDist, paramToDist, returnToDist +} + +// idents returns Idents referencing assign statements, parameters, and return values, respectively. +func (v *varNameLen) idents(pass *analysis.Pass) ([]*ast.Ident, []*ast.Ident, []*ast.Ident) { //nolint:gocognit + inspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + filter := []ast.Node{ + (*ast.Ident)(nil), + (*ast.FuncDecl)(nil), + } + + funcs := []*ast.FuncDecl{} + methods := []*ast.FuncDecl{} + assignIdents := []*ast.Ident{} + paramIdents := []*ast.Ident{} + returnIdents := []*ast.Ident{} + + inspector.Preorder(filter, func(node ast.Node) { + if f, ok := node.(*ast.FuncDecl); ok { + funcs = append(funcs, f) + if f.Recv != nil { + methods = append(methods, f) + } + return + } + + ident := node.(*ast.Ident) + if ident.Obj == nil { + return + } + + if _, ok := ident.Obj.Decl.(*ast.AssignStmt); ok { + assignIdents = append(assignIdents, ident) + return + } + + if field, ok := ident.Obj.Decl.(*ast.Field); ok { + if isReceiver(field, methods) && !v.checkReceiver { + return + } + + if isReturn(field, funcs) { + if !v.checkReturn { + return + } + returnIdents = append(returnIdents, ident) + return + } + + paramIdents = append(paramIdents, ident) + } + }) + + return assignIdents, paramIdents, returnIdents +} + +// isReceiver returns true when field is a receiver parameter of any of the given methods. +func isReceiver(field *ast.Field, methods []*ast.FuncDecl) bool { + for _, m := range methods { + for _, recv := range m.Recv.List { + if recv == field { + return true + } + } + } + return false +} + +// isReturn returns true when field is a return value of any of the given funcs. +func isReturn(field *ast.Field, funcs []*ast.FuncDecl) bool { + for _, f := range funcs { + if f.Type.Results == nil { + continue + } + for _, r := range f.Type.Results.List { + if r == field { + return true + } + } + } + return false +} + +// Set implements Value. +func (sv *stringsValue) Set(s string) error { + sv.Values = strings.Split(s, ",") + return nil +} + +// String implements Value. +func (sv *stringsValue) String() string { + return strings.Join(sv.Values, ",") +} + +// contains returns true when sv contains s. +func (sv *stringsValue) contains(s string) bool { + for _, v := range sv.Values { + if v == s { + return true + } + } + return false +} + +// isConventional returns true when p is a conventional Go parameter, such as "ctx context.Context" or +// "t *testing.T". +func (p parameter) isConventional() bool { //nolint:gocyclo,gocognit + switch { + case p.name == "t" && p.isPointerType("testing.T"): + return true + case p.name == "b" && p.isPointerType("testing.B"): + return true + case p.name == "tb" && p.isType("testing.TB"): + return true + case p.name == "pb" && p.isPointerType("testing.PB"): + return true + case p.name == "m" && p.isPointerType("testing.M"): + return true + case p.name == "ctx" && p.isType("context.Context"): + return true + default: + return false + } +} + +// isType returns true when p is of type typeName. +func (p parameter) isType(typeName string) bool { + sel, ok := p.field.Type.(*ast.SelectorExpr) + if !ok { + return false + } + return isType(sel, typeName) +} + +// isPointerType returns true when p is a pointer type of type typeName. +func (p parameter) isPointerType(typeName string) bool { + star, ok := p.field.Type.(*ast.StarExpr) + if !ok { + return false + } + sel, ok := star.X.(*ast.SelectorExpr) + if !ok { + return false + } + return isType(sel, typeName) +} + +// isType returns true when sel is a selector for type typeName. +func isType(sel *ast.SelectorExpr, typeName string) bool { + ident, ok := sel.X.(*ast.Ident) + if !ok { + return false + } + return typeName == ident.Name+"."+sel.Sel.Name +} diff --git a/vendor/github.com/breml/bidichk/LICENSE b/vendor/github.com/breml/bidichk/LICENSE new file mode 100644 index 000000000..47a8419ce --- /dev/null +++ b/vendor/github.com/breml/bidichk/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Lucas Bremgartner + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/breml/bidichk/pkg/bidichk/bidichk.go b/vendor/github.com/breml/bidichk/pkg/bidichk/bidichk.go new file mode 100644 index 000000000..17c36d4cd --- /dev/null +++ b/vendor/github.com/breml/bidichk/pkg/bidichk/bidichk.go @@ -0,0 +1,67 @@ +package bidichk + +import ( + "bytes" + "go/token" + "os" + "strings" + "unicode/utf8" + + "golang.org/x/tools/go/analysis" +) + +var Analyzer = &analysis.Analyzer{ + Name: "bidichk", + Doc: "Checks for dangerous unicode character sequences", + Run: run, +} + +func run(pass *analysis.Pass) (interface{}, error) { + var err error + + pass.Fset.Iterate(func(f *token.File) bool { + if strings.HasPrefix(f.Name(), "$GOROOT") { + return true + } + + return check(f.Name(), f.Pos(0), pass) == nil + }) + + return nil, err +} + +var disallowedRunes = map[string]rune{ + "LEFT-TO-RIGHT-EMBEDDING": '\u202A', + "RIGHT-TO-LEFT-EMBEDDING": '\u202B', + "POP-DIRECTIONAL-FORMATTING": '\u202C', + "LEFT-TO-RIGHT-OVERRIDE": '\u202D', + "RIGHT-TO-LEFT-OVERRIDE": '\u202E', + "LEFT-TO-RIGHT-ISOLATE": '\u2066', + "RIGHT-TO-LEFT-ISOLATE": '\u2067', + "FIRST-STRONG-ISOLATE": '\u2068', + "POP-DIRECTIONAL-ISOLATE": '\u2069', +} + +func check(filename string, pos token.Pos, pass *analysis.Pass) error { + body, err := os.ReadFile(filename) + if err != nil { + return err + } + + for name, r := range disallowedRunes { + start := 0 + for { + idx := bytes.IndexRune(body[start:], r) + if idx == -1 { + break + } + start += idx + + pass.Reportf(pos+token.Pos(start), "found dangerous unicode character sequence %s", name) + + start += utf8.RuneLen(r) + } + } + + return nil +} diff --git a/vendor/github.com/butuzov/ireturn/LICENSE b/vendor/github.com/butuzov/ireturn/LICENSE new file mode 100644 index 000000000..a9752e972 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Oleg Butuzov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/butuzov/ireturn/analyzer/analyzer.go b/vendor/github.com/butuzov/ireturn/analyzer/analyzer.go new file mode 100644 index 000000000..f4fdaaed6 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/analyzer/analyzer.go @@ -0,0 +1,193 @@ +package analyzer + +import ( + "flag" + "fmt" + "go/ast" + gotypes "go/types" + "strings" + "sync" + + "github.com/butuzov/ireturn/config" + "github.com/butuzov/ireturn/types" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const name string = "ireturn" // linter name + +type validator interface { + IsValid(types.IFace) bool +} + +type analyzer struct { + once sync.Once + handler validator + err error + + found []analysis.Diagnostic +} + +func (a *analyzer) run(pass *analysis.Pass) (interface{}, error) { + // 00. Part 1. Handling Configuration Only Once. + a.once.Do(func() { a.readConfiguration(&pass.Analyzer.Flags) }) + + // 00. Part 2. Handling Errors + if a.err != nil { + return nil, a.err + } + + // 01. Running Inspection. + ins, _ := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + ins.Preorder([]ast.Node{(*ast.FuncDecl)(nil)}, func(node ast.Node) { + // 001. Casting to funcdecl + f, _ := node.(*ast.FuncDecl) + + // 002. Does it return any results ? + if f.Type == nil || f.Type.Results == nil { + return + } + + // 003. Is it allowed to be checked? + // TODO(butuzov): add inline comment + if hasDisallowDirective(f.Doc) { + return + } + + // 004. Filtering Results. + for _, i := range filterInterfaces(pass, f.Type.Results) { + + if a.handler.IsValid(i) { + continue + } + + a.found = append(a.found, analysis.Diagnostic{ //nolint: exhaustivestruct + Pos: f.Pos(), + Message: fmt.Sprintf("%s returns interface (%s)", f.Name.Name, i.Name), + }) + } + }) + + // 02. Printing reports. + for i := range a.found { + pass.Report(a.found[i]) + } + + return nil, nil +} + +func (a *analyzer) readConfiguration(fs *flag.FlagSet) { + cnf, err := config.New(fs) + if err != nil { + a.err = err + return + } + + if validatorImpl, ok := cnf.(validator); ok { + a.handler = validatorImpl + return + } + + a.handler = config.DefaultValidatorConfig() +} + +func NewAnalyzer() *analysis.Analyzer { + a := analyzer{} //nolint: exhaustivestruct + + return &analysis.Analyzer{ + Name: name, + Doc: "Accept Interfaces, Return Concrete Types", + Run: a.run, + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Flags: flags(), + } +} + +func flags() flag.FlagSet { + set := flag.NewFlagSet("", flag.PanicOnError) + set.String("allow", "", "accept-list of the comma-separated interfaces") + set.String("reject", "", "reject-list of the comma-separated interfaces") + return *set +} + +func filterInterfaces(pass *analysis.Pass, fl *ast.FieldList) []types.IFace { + var results []types.IFace + + for pos, el := range fl.List { + switch v := el.Type.(type) { + // ----- empty or anonymous interfaces + case *ast.InterfaceType: + + if len(v.Methods.List) == 0 { + results = append(results, issue("interface{}", pos, types.EmptyInterface)) + continue + } + + results = append(results, issue("anonymous interface", pos, types.AnonInterface)) + + // ------ Errors and interfaces from same package + case *ast.Ident: + + t1 := pass.TypesInfo.TypeOf(el.Type) + if !gotypes.IsInterface(t1.Underlying()) { + continue + } + + word := t1.String() + // only build in interface is error + if obj := gotypes.Universe.Lookup(word); obj != nil { + results = append(results, issue(obj.Name(), pos, types.ErrorInterface)) + + continue + } + + results = append(results, issue(word, pos, types.NamedInterface)) + + // ------- standard library and 3rd party interfaces + case *ast.SelectorExpr: + + t1 := pass.TypesInfo.TypeOf(el.Type) + if !gotypes.IsInterface(t1.Underlying()) { + continue + } + + word := t1.String() + if isStdLib(word) { + results = append(results, issue(word, pos, types.NamedStdInterface)) + + continue + } + + results = append(results, issue(word, pos, types.NamedInterface)) + } + } + + return results +} + +// isStdLib will run small checks against pkg to find out if named interface +// we lookling on comes from a standard library or not. +func isStdLib(named string) bool { + // find last dot index. + idx := strings.LastIndex(named, ".") + if idx == -1 { + return false + } + + if _, ok := std[named[0:idx]]; ok { + return true + } + + return false +} + +// issue is shortcut that creates issue for next filtering. +func issue(name string, pos int, interfaceType types.IType) types.IFace { + return types.IFace{ + Name: name, + Pos: pos, + Type: interfaceType, + } +} diff --git a/vendor/github.com/butuzov/ireturn/analyzer/disallow.go b/vendor/github.com/butuzov/ireturn/analyzer/disallow.go new file mode 100644 index 000000000..36b6fcb4f --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/analyzer/disallow.go @@ -0,0 +1,45 @@ +package analyzer + +import ( + "go/ast" + "strings" +) + +const nolintPrefix = "//nolint" + +func hasDisallowDirective(cg *ast.CommentGroup) bool { + if cg == nil { + return false + } + + return directiveFound(cg) +} + +func directiveFound(cg *ast.CommentGroup) bool { + for i := len(cg.List) - 1; i >= 0; i-- { + comment := cg.List[i] + if !strings.HasPrefix(comment.Text, nolintPrefix) { + continue + } + + startingIdx := len(nolintPrefix) + for { + idx := strings.Index(comment.Text[startingIdx:], name) + if idx == -1 { + break + } + + if len(comment.Text[startingIdx+idx:]) == len(name) { + return true + } + + c := comment.Text[startingIdx+idx+len(name)] + if c == '.' || c == ',' || c == ' ' || c == ' ' { + return true + } + startingIdx += idx + 1 + } + } + + return false +} diff --git a/vendor/github.com/butuzov/ireturn/analyzer/std.go b/vendor/github.com/butuzov/ireturn/analyzer/std.go new file mode 100644 index 000000000..2af5284a3 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/analyzer/std.go @@ -0,0 +1,186 @@ +// Code generated using std.sh; DO NOT EDIT. + +// We will ignore that fact that some of packages +// were removed from stdlib. + +package analyzer + +var std = map[string]struct{}{ + // added in Go v1.2 in compare to v1.1 (docker image) + "archive/tar": {}, + "archive/zip": {}, + "bufio": {}, + "bytes": {}, + "cmd/cgo": {}, + "cmd/fix": {}, + "cmd/go": {}, + "cmd/gofmt": {}, + "cmd/yacc": {}, + "compress/bzip2": {}, + "compress/flate": {}, + "compress/gzip": {}, + "compress/lzw": {}, + "compress/zlib": {}, + "container/heap": {}, + "container/list": {}, + "container/ring": {}, + "crypto": {}, + "crypto/aes": {}, + "crypto/cipher": {}, + "crypto/des": {}, + "crypto/dsa": {}, + "crypto/ecdsa": {}, + "crypto/elliptic": {}, + "crypto/hmac": {}, + "crypto/md5": {}, + "crypto/rand": {}, + "crypto/rc4": {}, + "crypto/rsa": {}, + "crypto/sha1": {}, + "crypto/sha256": {}, + "crypto/sha512": {}, + "crypto/subtle": {}, + "crypto/tls": {}, + "crypto/x509": {}, + "crypto/x509/pkix": {}, + "database/sql": {}, + "database/sql/driver": {}, + "debug/dwarf": {}, + "debug/elf": {}, + "debug/gosym": {}, + "debug/macho": {}, + "debug/pe": {}, + "encoding": {}, + "encoding/ascii85": {}, + "encoding/asn1": {}, + "encoding/base32": {}, + "encoding/base64": {}, + "encoding/binary": {}, + "encoding/csv": {}, + "encoding/gob": {}, + "encoding/hex": {}, + "encoding/json": {}, + "encoding/pem": {}, + "encoding/xml": {}, + "errors": {}, + "expvar": {}, + "flag": {}, + "fmt": {}, + "go/ast": {}, + "go/build": {}, + "go/doc": {}, + "go/format": {}, + "go/parser": {}, + "go/printer": {}, + "go/scanner": {}, + "go/token": {}, + "hash": {}, + "hash/adler32": {}, + "hash/crc32": {}, + "hash/crc64": {}, + "hash/fnv": {}, + "html": {}, + "html/template": {}, + "image": {}, + "image/color": {}, + "image/color/palette": {}, + "image/draw": {}, + "image/gif": {}, + "image/jpeg": {}, + "image/png": {}, + "index/suffixarray": {}, + "io": {}, + "io/ioutil": {}, + "log": {}, + "log/syslog": {}, + "math": {}, + "math/big": {}, + "math/cmplx": {}, + "math/rand": {}, + "mime": {}, + "mime/multipart": {}, + "net": {}, + "net/http": {}, + "net/http/cgi": {}, + "net/http/cookiejar": {}, + "net/http/fcgi": {}, + "net/http/httptest": {}, + "net/http/httputil": {}, + "net/http/pprof": {}, + "net/mail": {}, + "net/rpc": {}, + "net/rpc/jsonrpc": {}, + "net/smtp": {}, + "net/textproto": {}, + "net/url": {}, + "os": {}, + "os/exec": {}, + "os/signal": {}, + "os/user": {}, + "path": {}, + "path/filepath": {}, + "reflect": {}, + "regexp": {}, + "regexp/syntax": {}, + "runtime": {}, + "runtime/cgo": {}, + "runtime/debug": {}, + "runtime/pprof": {}, + "runtime/race": {}, + "sort": {}, + "strconv": {}, + "strings": {}, + "sync": {}, + "sync/atomic": {}, + "syscall": {}, + "testing": {}, + "testing/iotest": {}, + "testing/quick": {}, + "text/scanner": {}, + "text/tabwriter": {}, + "text/template": {}, + "text/template/parse": {}, + "time": {}, + "unicode": {}, + "unicode/utf16": {}, + "unicode/utf8": {}, + "unsafe": {}, + // added in Go v1.3 in compare to v1.2 (docker image) + "cmd/addr2line": {}, + "cmd/nm": {}, + "cmd/objdump": {}, + "cmd/pack": {}, + "debug/plan9obj": {}, + // added in Go v1.4 in compare to v1.3 (docker image) + "cmd/pprof": {}, + // added in Go v1.5 in compare to v1.4 (docker image) + "go/constant": {}, + "go/importer": {}, + "go/types": {}, + "mime/quotedprintable": {}, + "runtime/trace": {}, + // added in Go v1.6 in compare to v1.5 (docker image) + // added in Go v1.7 in compare to v1.6 (docker image) + "context": {}, + "net/http/httptrace": {}, + // added in Go v1.8 in compare to v1.7 (docker image) + "plugin": {}, + // added in Go v1.9 in compare to v1.8 (docker image) + "math/bits": {}, + // added in Go v1.10 in compare to v1.9 (docker image) + // added in Go v1.11 in compare to v1.10 (docker image) + // added in Go v1.12 in compare to v1.11 (docker image) + // added in Go v1.13 in compare to v1.12 (docker image) + "crypto/ed25519": {}, + // added in Go v1.14 in compare to v1.13 (docker image) + "hash/maphash": {}, + // added in Go v1.15 in compare to v1.14 (docker image) + "time/tzdata": {}, + // added in Go v1.16 in compare to v1.15 (docker image) + "embed": {}, + "go/build/constraint": {}, + "io/fs": {}, + "runtime/metrics": {}, + "testing/fstest": {}, + // added in Go v1.17 in compare to v1.16 (docker image) +} diff --git a/vendor/github.com/butuzov/ireturn/config/allow.go b/vendor/github.com/butuzov/ireturn/config/allow.go new file mode 100644 index 000000000..c171a255d --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/config/allow.go @@ -0,0 +1,17 @@ +package config + +import "github.com/butuzov/ireturn/types" + +// allowConfig specifies a list of interfaces (keywords, patters and regular expressions) +// that are allowed by ireturn as valid to return, any non listed interface are rejected. +type allowConfig struct { + *defaultConfig +} + +func allowAll(patterns []string) *allowConfig { + return &allowConfig{&defaultConfig{List: patterns}} +} + +func (ac *allowConfig) IsValid(i types.IFace) bool { + return ac.Has(i) +} diff --git a/vendor/github.com/butuzov/ireturn/config/config.go b/vendor/github.com/butuzov/ireturn/config/config.go new file mode 100644 index 000000000..7307ab3ea --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/config/config.go @@ -0,0 +1,66 @@ +package config + +import ( + "regexp" + + "github.com/butuzov/ireturn/types" +) + +// defaultConfig is core of the validation, ... +// todo(butuzov): write proper intro... + +type defaultConfig struct { + List []string + + // private fields (for search optimization look ups) + init bool + quick uint8 + list []*regexp.Regexp +} + +func (config *defaultConfig) Has(i types.IFace) bool { + if !config.init { + config.compileList() + config.init = true + } + + if config.quick&uint8(i.Type) > 0 { + return true + } + + // not a named interface (because error, interface{}, anon interface has keywords.) + if i.Type&types.NamedInterface == 0 && i.Type&types.NamedStdInterface == 0 { + return false + } + + for _, re := range config.list { + if re.MatchString(i.Name) { + return true + } + } + + return false +} + +// compileList will transform text list into a bitmask for quick searches and +// slice of regular expressions for quick searches. +func (config *defaultConfig) compileList() { + for _, str := range config.List { + switch str { + case types.NameError: + config.quick |= uint8(types.ErrorInterface) + case types.NameEmpty: + config.quick |= uint8(types.EmptyInterface) + case types.NameAnon: + config.quick |= uint8(types.AnonInterface) + case types.NameStdLib: + config.quick |= uint8(types.NamedStdInterface) + } + + // allow to parse regular expressions + // todo(butuzov): how can we log error in golangci-lint? + if re, err := regexp.Compile(str); err == nil { + config.list = append(config.list, re) + } + } +} diff --git a/vendor/github.com/butuzov/ireturn/config/new.go b/vendor/github.com/butuzov/ireturn/config/new.go new file mode 100644 index 000000000..cfaa274a1 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/config/new.go @@ -0,0 +1,74 @@ +package config + +import ( + "errors" + "flag" + "strings" + + "github.com/butuzov/ireturn/types" +) + +var ErrCollisionOfInterests = errors.New("can't have both `-accept` and `-reject` specified at same time") + +//nolint: exhaustivestruct +func DefaultValidatorConfig() *allowConfig { + return allowAll([]string{ + types.NameEmpty, // "empty": empty interfaces (interface{}) + types.NameError, // "error": for all error's + types.NameAnon, // "anon": for all empty interfaces with methods (interface {Method()}) + types.NameStdLib, // "std": for all standard library packages + }) +} + +// New is factory function that return allowConfig or rejectConfig depending +// on provided arguments. +func New(fs *flag.FlagSet) (interface{}, error) { + var ( + allowList = toSlice(getFlagVal(fs, "allow")) + rejectList = toSlice(getFlagVal(fs, "reject")) + ) + + // can't have both at same time. + if len(allowList) != 0 && len(rejectList) != 0 { + return nil, ErrCollisionOfInterests + } + + switch { + case len(allowList) > 0: + return allowAll(allowList), nil + case len(rejectList) > 0: + return rejectAll(rejectList), nil + } + + // can have none at same time. + return nil, nil +} + +// both constants used to cleanup items provided in comma separated list. +const ( + SepTab string = " " + SepSpace string = " " +) + +func toSlice(s string) []string { + var results []string + + for _, pattern := range strings.Split(s, ",") { + pattern = strings.Trim(pattern, SepTab+SepSpace) + if pattern != "" { + results = append(results, pattern) + } + } + + return results +} + +func getFlagVal(fs *flag.FlagSet, name string) string { + flg := fs.Lookup(name) + + if flg == nil { + return "" + } + + return flg.Value.String() +} diff --git a/vendor/github.com/butuzov/ireturn/config/reject.go b/vendor/github.com/butuzov/ireturn/config/reject.go new file mode 100644 index 000000000..21e50114b --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/config/reject.go @@ -0,0 +1,17 @@ +package config + +import "github.com/butuzov/ireturn/types" + +// rejectConfig specifies a list of interfaces (keywords, patters and regular expressions) +// that are rejected by ireturn as valid to return, any non listed interface are allowed. +type rejectConfig struct { + *defaultConfig +} + +func rejectAll(patterns []string) *rejectConfig { + return &rejectConfig{&defaultConfig{List: patterns}} +} + +func (rc *rejectConfig) IsValid(i types.IFace) bool { + return !rc.Has(i) +} diff --git a/vendor/github.com/butuzov/ireturn/types/iface.go b/vendor/github.com/butuzov/ireturn/types/iface.go new file mode 100644 index 000000000..e9baa37c0 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/types/iface.go @@ -0,0 +1,7 @@ +package types + +type IFace struct { + Name string // Preserved for named interfaces + Pos int // Position in return tuple + Type IType // Type of the interface +} diff --git a/vendor/github.com/butuzov/ireturn/types/names.go b/vendor/github.com/butuzov/ireturn/types/names.go new file mode 100644 index 000000000..0b286c4c8 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/types/names.go @@ -0,0 +1,8 @@ +package types + +const ( + NameEmpty = "empty" + NameAnon = "anon" + NameError = "error" + NameStdLib = "stdlib" +) diff --git a/vendor/github.com/butuzov/ireturn/types/types.go b/vendor/github.com/butuzov/ireturn/types/types.go new file mode 100644 index 000000000..837570db4 --- /dev/null +++ b/vendor/github.com/butuzov/ireturn/types/types.go @@ -0,0 +1,11 @@ +package types + +type IType uint8 + +const ( + EmptyInterface IType = 1 << iota // ref as empty + AnonInterface // ref as anon + ErrorInterface // ref as error + NamedInterface // ref as named + NamedStdInterface // ref as named stdlib +) diff --git a/vendor/github.com/charithe/durationcheck/README.md b/vendor/github.com/charithe/durationcheck/README.md index 122edb745..6f4279bd3 100644 --- a/vendor/github.com/charithe/durationcheck/README.md +++ b/vendor/github.com/charithe/durationcheck/README.md @@ -7,22 +7,25 @@ Duration Check A Go linter to detect cases where two `time.Duration` values are being multiplied in possibly erroneous ways. -For example, consider the following (highly contrived) function: +Consider the following (highly contrived) code: ```go -func waitFor(someDuration time.Duration) { - timeToWait := someDuration * time.Second - time.Sleep(timeToWait) +func waitForSeconds(someDuration time.Duration) { + timeToWait := someDuration * time.Second + fmt.Printf("Waiting for %s\n", timeToWait) +} + +func main() { + waitForSeconds(5) // waits for 5 seconds + waitForSeconds(5 * time.Second) // waits for 1388888h 53m 20s } ``` -Although the above code would compile without any errors, its runtime behaviour would almost certainly be incorrect. -A caller would reasonably expect `waitFor(5 * time.Seconds)` to wait for ~5 seconds but they would actually end up -waiting for ~1,388,889 hours. +Both invocations of the function are syntactically correct but the second one is probably not what most people want. +In this contrived example it is quite easy to spot the mistake. However, if the incorrect `waitForSeconds` invocation is +nested deep within a complex piece of code that runs in the background, the mistake could go unnoticed for months (which +is exactly what happened in a production backend system of fairly well-known software service). -The above example is just for illustration purposes only. The problem is glaringly obvious in such a simple function -and even the greenest Gopher would discover the issue immediately. However, imagine a much more complicated function -with many more lines and it is not inconceivable that such logic errors could go unnoticed. See the [test cases](testdata/src/a/a.go) for more examples of the types of errors detected by the linter. diff --git a/vendor/github.com/charithe/durationcheck/durationcheck.go b/vendor/github.com/charithe/durationcheck/durationcheck.go index 7f7008e91..c47b3a761 100644 --- a/vendor/github.com/charithe/durationcheck/durationcheck.go +++ b/vendor/github.com/charithe/durationcheck/durationcheck.go @@ -150,6 +150,9 @@ func isAcceptableNestedExpr(pass *analysis.Pass, n ast.Expr) bool { case *ast.Ident: return isAcceptableIdent(pass, e) case *ast.CallExpr: + if isAcceptableCast(pass, e) { + return true + } t := pass.TypesInfo.TypeOf(e) return !isDuration(t) case *ast.SelectorExpr: diff --git a/vendor/github.com/esimonov/ifshort/pkg/analyzer/analyzer.go b/vendor/github.com/esimonov/ifshort/pkg/analyzer/analyzer.go index 7e4df7da1..397a17424 100644 --- a/vendor/github.com/esimonov/ifshort/pkg/analyzer/analyzer.go +++ b/vendor/github.com/esimonov/ifshort/pkg/analyzer/analyzer.go @@ -85,8 +85,9 @@ func (nom namedOccurrenceMap) checkStatement(stmt ast.Stmt, ifPos token.Pos) { nom.checkExpression(a, ifPos) } case *ast.ExprStmt: - if callExpr, ok := v.X.(*ast.CallExpr); ok { - nom.checkExpression(callExpr, ifPos) + switch v.X.(type) { + case *ast.CallExpr, *ast.UnaryExpr: + nom.checkExpression(v.X, ifPos) } case *ast.ForStmt: for _, el := range v.Body.List { @@ -157,12 +158,11 @@ func (nom namedOccurrenceMap) checkStatement(stmt ast.Stmt, ifPos token.Pos) { } for _, c := range clauses.Body { - if est, ok := c.(*ast.ExprStmt); ok { - nom.checkExpression(est.X, ifPos) - } - switch v := c.(type) { case *ast.AssignStmt: + for _, el := range v.Lhs { + nom.checkExpression(el, ifPos) + } for _, el := range v.Rhs { nom.checkExpression(el, ifPos) } @@ -171,6 +171,28 @@ func (nom namedOccurrenceMap) checkStatement(stmt ast.Stmt, ifPos token.Pos) { } } } + case *ast.SelectStmt: + for _, el := range v.Body.List { + clause := el.(*ast.CommClause) + + nom.checkStatement(clause.Comm, ifPos) + + for _, c := range clause.Body { + switch v := c.(type) { + case *ast.AssignStmt: + for _, el := range v.Lhs { + nom.checkExpression(el, ifPos) + } + for _, el := range v.Rhs { + nom.checkExpression(el, ifPos) + } + case *ast.ExprStmt: + nom.checkExpression(v.X, ifPos) + } + } + } + case *ast.LabeledStmt: + nom.checkStatement(v.Stmt, ifPos) } } @@ -190,7 +212,7 @@ func (nom namedOccurrenceMap) checkExpression(candidate ast.Expr, ifPos token.Po case *ast.CompositeLit: for _, el := range v.Elts { switch v := el.(type) { - case *ast.Ident: + case *ast.Ident, *ast.CompositeLit: nom.checkExpression(v, ifPos) case *ast.KeyValueExpr: nom.checkExpression(v.Key, ifPos) @@ -217,6 +239,8 @@ func (nom namedOccurrenceMap) checkExpression(candidate ast.Expr, ifPos token.Po } } } + case *ast.StarExpr: + nom.checkExpression(v.X, ifPos) case *ast.IndexExpr: nom.checkExpression(v.X, ifPos) switch index := v.Index.(type) { diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md index 5c751f215..5152bf59b 100644 --- a/vendor/github.com/fatih/color/README.md +++ b/vendor/github.com/fatih/color/README.md @@ -78,7 +78,7 @@ notice("Don't forget this...") ### Custom fprint functions (FprintFunc) ```go -blue := color.New(FgBlue).FprintfFunc() +blue := color.New(color.FgBlue).FprintfFunc() blue(myWriter, "important notice: %s", stars) // Mix up with multiple attributes diff --git a/vendor/github.com/fatih/color/go.mod b/vendor/github.com/fatih/color/go.mod index 78872815e..c9b3cd59a 100644 --- a/vendor/github.com/fatih/color/go.mod +++ b/vendor/github.com/fatih/color/go.mod @@ -3,6 +3,6 @@ module github.com/fatih/color go 1.13 require ( - github.com/mattn/go-colorable v0.1.8 - github.com/mattn/go-isatty v0.0.12 + github.com/mattn/go-colorable v0.1.9 + github.com/mattn/go-isatty v0.0.14 ) diff --git a/vendor/github.com/fatih/color/go.sum b/vendor/github.com/fatih/color/go.sum index 54f7c46e8..cbbcfb644 100644 --- a/vendor/github.com/fatih/color/go.sum +++ b/vendor/github.com/fatih/color/go.sum @@ -1,7 +1,9 @@ -github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= -github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/fsnotify/fsnotify/.mailmap b/vendor/github.com/fsnotify/fsnotify/.mailmap new file mode 100644 index 000000000..a04f2907f --- /dev/null +++ b/vendor/github.com/fsnotify/fsnotify/.mailmap @@ -0,0 +1,2 @@ +Chris Howey +Nathan Youngman <4566+nathany@users.noreply.github.com> diff --git a/vendor/github.com/fsnotify/fsnotify/.travis.yml b/vendor/github.com/fsnotify/fsnotify/.travis.yml deleted file mode 100644 index a9c30165c..000000000 --- a/vendor/github.com/fsnotify/fsnotify/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -sudo: false -language: go - -go: - - "stable" - - "1.11.x" - - "1.10.x" - - "1.9.x" - -matrix: - include: - - go: "stable" - env: GOLINT=true - allow_failures: - - go: tip - fast_finish: true - - -before_install: - - if [ ! -z "${GOLINT}" ]; then go get -u golang.org/x/lint/golint; fi - -script: - - go test --race ./... - -after_script: - - test -z "$(gofmt -s -l -w . | tee /dev/stderr)" - - if [ ! -z "${GOLINT}" ]; then echo running golint; golint --set_exit_status ./...; else echo skipping golint; fi - - go vet ./... - -os: - - linux - - osx - - windows - -notifications: - email: false diff --git a/vendor/github.com/fsnotify/fsnotify/AUTHORS b/vendor/github.com/fsnotify/fsnotify/AUTHORS index 5ab5d41c5..6cbabe5ef 100644 --- a/vendor/github.com/fsnotify/fsnotify/AUTHORS +++ b/vendor/github.com/fsnotify/fsnotify/AUTHORS @@ -4,35 +4,44 @@ # You can update this list using the following command: # -# $ git shortlog -se | awk '{print $2 " " $3 " " $4}' +# $ (head -n10 AUTHORS && git shortlog -se | sed -E 's/^\s+[0-9]+\t//') | tee AUTHORS # Please keep the list sorted. Aaron L Adrien Bustany +Alexey Kazakov Amit Krishnan Anmol Sethi Bjørn Erik Pedersen +Brian Goff Bruno Bigras Caleb Spare Case Nelson -Chris Howey +Chris Howey Christoffer Buchholz Daniel Wagner-Hall Dave Cheney +Eric Lin Evan Phoenix Francisco Souza +Gautam Dey Hari haran -John C Barstow +Ichinose Shogo +Johannes Ebke +John C Barstow Kelvin Fo Ken-ichirou MATSUZAWA Matt Layher +Matthias Stone Nathan Youngman Nickolai Zeldovich +Oliver Bristow Patrick Paul Hammond Pawel Knap Pieter Droogendijk +Pratik Shinde Pursuit92 Riku Voipio Rob Figueiredo @@ -41,6 +50,7 @@ Slawek Ligus Soge Zhang Tiffany Jernigan Tilak Sharma +Tobias Klauser Tom Payne Travis Cline Tudor Golubenco diff --git a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md index be4d7ea2c..a438fe4b4 100644 --- a/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md +++ b/vendor/github.com/fsnotify/fsnotify/CHANGELOG.md @@ -1,6 +1,28 @@ # Changelog -## v1.4.7 / 2018-01-09 +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +## [1.5.1] - 2021-08-24 + +* Revert Add AddRaw to not follow symlinks + +## [1.5.0] - 2021-08-20 + +* Go: Increase minimum required version to Go 1.12 [#381](https://github.com/fsnotify/fsnotify/pull/381) +* Feature: Add AddRaw method which does not follow symlinks when adding a watch [#289](https://github.com/fsnotify/fsnotify/pull/298) +* Windows: Follow symlinks by default like on all other systems [#289](https://github.com/fsnotify/fsnotify/pull/289) +* CI: Use GitHub Actions for CI and cover go 1.12-1.17 + [#378](https://github.com/fsnotify/fsnotify/pull/378) + [#381](https://github.com/fsnotify/fsnotify/pull/381) + [#385](https://github.com/fsnotify/fsnotify/pull/385) +* Go 1.14+: Fix unsafe pointer conversion [#325](https://github.com/fsnotify/fsnotify/pull/325) + +## [1.4.7] - 2018-01-09 * BSD/macOS: Fix possible deadlock on closing the watcher on kqueue (thanks @nhooyr and @glycerine) * Tests: Fix missing verb on format string (thanks @rchiossi) @@ -10,62 +32,62 @@ * Linux: Properly handle inotify's IN_Q_OVERFLOW event (thanks @zeldovich) * Docs: replace references to OS X with macOS -## v1.4.2 / 2016-10-10 +## [1.4.2] - 2016-10-10 * Linux: use InotifyInit1 with IN_CLOEXEC to stop leaking a file descriptor to a child process when using fork/exec [#178](https://github.com/fsnotify/fsnotify/pull/178) (thanks @pattyshack) -## v1.4.1 / 2016-10-04 +## [1.4.1] - 2016-10-04 * Fix flaky inotify stress test on Linux [#177](https://github.com/fsnotify/fsnotify/pull/177) (thanks @pattyshack) -## v1.4.0 / 2016-10-01 +## [1.4.0] - 2016-10-01 * add a String() method to Event.Op [#165](https://github.com/fsnotify/fsnotify/pull/165) (thanks @oozie) -## v1.3.1 / 2016-06-28 +## [1.3.1] - 2016-06-28 * Windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc) -## v1.3.0 / 2016-04-19 +## [1.3.0] - 2016-04-19 * Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135) -## v1.2.10 / 2016-03-02 +## [1.2.10] - 2016-03-02 * Fix golint errors in windows.go [#121](https://github.com/fsnotify/fsnotify/pull/121) (thanks @tiffanyfj) -## v1.2.9 / 2016-01-13 +## [1.2.9] - 2016-01-13 kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsnotify/pull/111) (thanks @bep) -## v1.2.8 / 2015-12-17 +## [1.2.8] - 2015-12-17 * kqueue: fix race condition in Close [#105](https://github.com/fsnotify/fsnotify/pull/105) (thanks @djui for reporting the issue and @ppknap for writing a failing test) * inotify: fix race in test * enable race detection for continuous integration (Linux, Mac, Windows) -## v1.2.5 / 2015-10-17 +## [1.2.5] - 2015-10-17 * inotify: use epoll_create1 for arm64 support (requires Linux 2.6.27 or later) [#100](https://github.com/fsnotify/fsnotify/pull/100) (thanks @suihkulokki) * inotify: fix path leaks [#73](https://github.com/fsnotify/fsnotify/pull/73) (thanks @chamaken) * kqueue: watch for rename events on subdirectories [#83](https://github.com/fsnotify/fsnotify/pull/83) (thanks @guotie) * kqueue: avoid infinite loops from symlinks cycles [#101](https://github.com/fsnotify/fsnotify/pull/101) (thanks @illicitonion) -## v1.2.1 / 2015-10-14 +## [1.2.1] - 2015-10-14 * kqueue: don't watch named pipes [#98](https://github.com/fsnotify/fsnotify/pull/98) (thanks @evanphx) -## v1.2.0 / 2015-02-08 +## [1.2.0] - 2015-02-08 * inotify: use epoll to wake up readEvents [#66](https://github.com/fsnotify/fsnotify/pull/66) (thanks @PieterD) * inotify: closing watcher should now always shut down goroutine [#63](https://github.com/fsnotify/fsnotify/pull/63) (thanks @PieterD) * kqueue: close kqueue after removing watches, fixes [#59](https://github.com/fsnotify/fsnotify/issues/59) -## v1.1.1 / 2015-02-05 +## [1.1.1] - 2015-02-05 * inotify: Retry read on EINTR [#61](https://github.com/fsnotify/fsnotify/issues/61) (thanks @PieterD) -## v1.1.0 / 2014-12-12 +## [1.1.0] - 2014-12-12 * kqueue: rework internals [#43](https://github.com/fsnotify/fsnotify/pull/43) * add low-level functions @@ -77,22 +99,22 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn * kqueue: fix regression in rework causing subdirectories to be watched [#48](https://github.com/fsnotify/fsnotify/issues/48) * kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) -## v1.0.4 / 2014-09-07 +## [1.0.4] - 2014-09-07 * kqueue: add dragonfly to the build tags. * Rename source code files, rearrange code so exported APIs are at the top. * Add done channel to example code. [#37](https://github.com/fsnotify/fsnotify/pull/37) (thanks @chenyukang) -## v1.0.3 / 2014-08-19 +## [1.0.3] - 2014-08-19 * [Fix] Windows MOVED_TO now translates to Create like on BSD and Linux. [#36](https://github.com/fsnotify/fsnotify/issues/36) -## v1.0.2 / 2014-08-17 +## [1.0.2] - 2014-08-17 * [Fix] Missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) * [Fix] Make ./path and path equivalent. (thanks @zhsso) -## v1.0.0 / 2014-08-15 +## [1.0.0] - 2014-08-15 * [API] Remove AddWatch on Windows, use Add. * Improve documentation for exported identifiers. [#30](https://github.com/fsnotify/fsnotify/issues/30) @@ -146,51 +168,51 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn * no tests for the current implementation * not fully implemented on Windows [#93](https://github.com/howeyc/fsnotify/issues/93#issuecomment-39285195) -## v0.9.3 / 2014-12-31 +## [0.9.3] - 2014-12-31 * kqueue: cleanup internal watch before sending remove event [#51](https://github.com/fsnotify/fsnotify/issues/51) -## v0.9.2 / 2014-08-17 +## [0.9.2] - 2014-08-17 * [Backport] Fix missing create events on macOS. [#14](https://github.com/fsnotify/fsnotify/issues/14) (thanks @zhsso) -## v0.9.1 / 2014-06-12 +## [0.9.1] - 2014-06-12 * Fix data race on kevent buffer (thanks @tilaks) [#98](https://github.com/howeyc/fsnotify/pull/98) -## v0.9.0 / 2014-01-17 +## [0.9.0] - 2014-01-17 * IsAttrib() for events that only concern a file's metadata [#79][] (thanks @abustany) * [Fix] kqueue: fix deadlock [#77][] (thanks @cespare) * [NOTICE] Development has moved to `code.google.com/p/go.exp/fsnotify` in preparation for inclusion in the Go standard library. -## v0.8.12 / 2013-11-13 +## [0.8.12] - 2013-11-13 * [API] Remove FD_SET and friends from Linux adapter -## v0.8.11 / 2013-11-02 +## [0.8.11] - 2013-11-02 * [Doc] Add Changelog [#72][] (thanks @nathany) * [Doc] Spotlight and double modify events on macOS [#62][] (reported by @paulhammond) -## v0.8.10 / 2013-10-19 +## [0.8.10] - 2013-10-19 * [Fix] kqueue: remove file watches when parent directory is removed [#71][] (reported by @mdwhatcott) * [Fix] kqueue: race between Close and readEvents [#70][] (reported by @bernerdschaefer) * [Doc] specify OS-specific limits in README (thanks @debrando) -## v0.8.9 / 2013-09-08 +## [0.8.9] - 2013-09-08 * [Doc] Contributing (thanks @nathany) * [Doc] update package path in example code [#63][] (thanks @paulhammond) * [Doc] GoCI badge in README (Linux only) [#60][] * [Doc] Cross-platform testing with Vagrant [#59][] (thanks @nathany) -## v0.8.8 / 2013-06-17 +## [0.8.8] - 2013-06-17 * [Fix] Windows: handle `ERROR_MORE_DATA` on Windows [#49][] (thanks @jbowtie) -## v0.8.7 / 2013-06-03 +## [0.8.7] - 2013-06-03 * [API] Make syscall flags internal * [Fix] inotify: ignore event changes @@ -198,74 +220,74 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn * [Fix] tests on Windows * lower case error messages -## v0.8.6 / 2013-05-23 +## [0.8.6] - 2013-05-23 * kqueue: Use EVT_ONLY flag on Darwin * [Doc] Update README with full example -## v0.8.5 / 2013-05-09 +## [0.8.5] - 2013-05-09 * [Fix] inotify: allow monitoring of "broken" symlinks (thanks @tsg) -## v0.8.4 / 2013-04-07 +## [0.8.4] - 2013-04-07 * [Fix] kqueue: watch all file events [#40][] (thanks @ChrisBuchholz) -## v0.8.3 / 2013-03-13 +## [0.8.3] - 2013-03-13 * [Fix] inoitfy/kqueue memory leak [#36][] (reported by @nbkolchin) * [Fix] kqueue: use fsnFlags for watching a directory [#33][] (reported by @nbkolchin) -## v0.8.2 / 2013-02-07 +## [0.8.2] - 2013-02-07 * [Doc] add Authors * [Fix] fix data races for map access [#29][] (thanks @fsouza) -## v0.8.1 / 2013-01-09 +## [0.8.1] - 2013-01-09 * [Fix] Windows path separators * [Doc] BSD License -## v0.8.0 / 2012-11-09 +## [0.8.0] - 2012-11-09 * kqueue: directory watching improvements (thanks @vmirage) * inotify: add `IN_MOVED_TO` [#25][] (requested by @cpisto) * [Fix] kqueue: deleting watched directory [#24][] (reported by @jakerr) -## v0.7.4 / 2012-10-09 +## [0.7.4] - 2012-10-09 * [Fix] inotify: fixes from https://codereview.appspot.com/5418045/ (ugorji) * [Fix] kqueue: preserve watch flags when watching for delete [#21][] (reported by @robfig) * [Fix] kqueue: watch the directory even if it isn't a new watch (thanks @robfig) * [Fix] kqueue: modify after recreation of file -## v0.7.3 / 2012-09-27 +## [0.7.3] - 2012-09-27 * [Fix] kqueue: watch with an existing folder inside the watched folder (thanks @vmirage) * [Fix] kqueue: no longer get duplicate CREATE events -## v0.7.2 / 2012-09-01 +## [0.7.2] - 2012-09-01 * kqueue: events for created directories -## v0.7.1 / 2012-07-14 +## [0.7.1] - 2012-07-14 * [Fix] for renaming files -## v0.7.0 / 2012-07-02 +## [0.7.0] - 2012-07-02 * [Feature] FSNotify flags * [Fix] inotify: Added file name back to event path -## v0.6.0 / 2012-06-06 +## [0.6.0] - 2012-06-06 * kqueue: watch files after directory created (thanks @tmc) -## v0.5.1 / 2012-05-22 +## [0.5.1] - 2012-05-22 * [Fix] inotify: remove all watches before Close() -## v0.5.0 / 2012-05-03 +## [0.5.0] - 2012-05-03 * [API] kqueue: return errors during watch instead of sending over channel * kqueue: match symlink behavior on Linux @@ -273,22 +295,22 @@ kqueue: Fix logic for CREATE after REMOVE [#111](https://github.com/fsnotify/fsn * [Fix] kqueue: handle EINTR (reported by @robfig) * [Doc] Godoc example [#1][] (thanks @davecheney) -## v0.4.0 / 2012-03-30 +## [0.4.0] - 2012-03-30 * Go 1 released: build with go tool * [Feature] Windows support using winfsnotify * Windows does not have attribute change notifications * Roll attribute notifications into IsModify -## v0.3.0 / 2012-02-19 +## [0.3.0] - 2012-02-19 * kqueue: add files when watch directory -## v0.2.0 / 2011-12-30 +## [0.2.0] - 2011-12-30 * update to latest Go weekly code -## v0.1.0 / 2011-10-19 +## [0.1.0] - 2011-10-19 * kqueue: add watch on file creation to match inotify * kqueue: create file event diff --git a/vendor/github.com/fsnotify/fsnotify/README.md b/vendor/github.com/fsnotify/fsnotify/README.md index b2629e522..df57b1b28 100644 --- a/vendor/github.com/fsnotify/fsnotify/README.md +++ b/vendor/github.com/fsnotify/fsnotify/README.md @@ -12,9 +12,9 @@ Cross platform: Windows, Linux, BSD and macOS. | Adapter | OS | Status | | --------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | -| inotify | Linux 2.6.27 or later, Android\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) | -| kqueue | BSD, macOS, iOS\* | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) | -| ReadDirectoryChangesW | Windows | Supported [![Build Status](https://travis-ci.org/fsnotify/fsnotify.svg?branch=master)](https://travis-ci.org/fsnotify/fsnotify) | +| inotify | Linux 2.6.27 or later, Android\* | Supported | +| kqueue | BSD, macOS, iOS\* | Supported | +| ReadDirectoryChangesW | Windows | Supported | | FSEvents | macOS | [Planned](https://github.com/fsnotify/fsnotify/issues/11) | | FEN | Solaris 11 | [In Progress](https://github.com/fsnotify/fsnotify/issues/12) | | fanotify | Linux 2.6.37+ | [Planned](https://github.com/fsnotify/fsnotify/issues/114) | diff --git a/vendor/github.com/fsnotify/fsnotify/fen.go b/vendor/github.com/fsnotify/fsnotify/fen.go index ced39cb88..b3ac3d8f5 100644 --- a/vendor/github.com/fsnotify/fsnotify/fen.go +++ b/vendor/github.com/fsnotify/fsnotify/fen.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build solaris // +build solaris package fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/fsnotify.go b/vendor/github.com/fsnotify/fsnotify/fsnotify.go index 89cab046d..0f4ee52e8 100644 --- a/vendor/github.com/fsnotify/fsnotify/fsnotify.go +++ b/vendor/github.com/fsnotify/fsnotify/fsnotify.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build !plan9 // +build !plan9 // Package fsnotify provides a platform-independent interface for file system notifications. diff --git a/vendor/github.com/fsnotify/fsnotify/go.mod b/vendor/github.com/fsnotify/fsnotify/go.mod index ff11e13f2..54089e48b 100644 --- a/vendor/github.com/fsnotify/fsnotify/go.mod +++ b/vendor/github.com/fsnotify/fsnotify/go.mod @@ -2,4 +2,6 @@ module github.com/fsnotify/fsnotify go 1.13 -require golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 +require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c + +retract v1.5.0 diff --git a/vendor/github.com/fsnotify/fsnotify/go.sum b/vendor/github.com/fsnotify/fsnotify/go.sum index f60af9855..0f478630c 100644 --- a/vendor/github.com/fsnotify/fsnotify/go.sum +++ b/vendor/github.com/fsnotify/fsnotify/go.sum @@ -1,2 +1,2 @@ -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/fsnotify/fsnotify/inotify.go b/vendor/github.com/fsnotify/fsnotify/inotify.go index d9fd1b88a..eb87699b5 100644 --- a/vendor/github.com/fsnotify/fsnotify/inotify.go +++ b/vendor/github.com/fsnotify/fsnotify/inotify.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package fsnotify @@ -272,7 +273,7 @@ func (w *Watcher) readEvents() { if nameLen > 0 { // Point "bytes" at the first byte of the filename - bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent])) + bytes := (*[unix.PathMax]byte)(unsafe.Pointer(&buf[offset+unix.SizeofInotifyEvent]))[:nameLen:nameLen] // The filename is padded with NULL bytes. TrimRight() gets rid of those. name += "/" + strings.TrimRight(string(bytes[0:nameLen]), "\000") } diff --git a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go index b33f2b4d4..e9ff9439f 100644 --- a/vendor/github.com/fsnotify/fsnotify/inotify_poller.go +++ b/vendor/github.com/fsnotify/fsnotify/inotify_poller.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build linux // +build linux package fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/kqueue.go b/vendor/github.com/fsnotify/fsnotify/kqueue.go index 86e76a3d6..368f5b790 100644 --- a/vendor/github.com/fsnotify/fsnotify/kqueue.go +++ b/vendor/github.com/fsnotify/fsnotify/kqueue.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build freebsd || openbsd || netbsd || dragonfly || darwin // +build freebsd openbsd netbsd dragonfly darwin package fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go index 2306c4620..36cc3845b 100644 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_bsd.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build freebsd || openbsd || netbsd || dragonfly // +build freebsd openbsd netbsd dragonfly package fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go index 870c4d6d1..98cd8476f 100644 --- a/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go +++ b/vendor/github.com/fsnotify/fsnotify/open_mode_darwin.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build darwin // +build darwin package fsnotify diff --git a/vendor/github.com/fsnotify/fsnotify/windows.go b/vendor/github.com/fsnotify/fsnotify/windows.go index 09436f31d..c02b75f7c 100644 --- a/vendor/github.com/fsnotify/fsnotify/windows.go +++ b/vendor/github.com/fsnotify/fsnotify/windows.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build windows // +build windows package fsnotify diff --git a/vendor/github.com/go-critic/go-critic/LICENSE b/vendor/github.com/go-critic/go-critic/LICENSE index b944b4bbd..5198a4a94 100644 --- a/vendor/github.com/go-critic/go-critic/LICENSE +++ b/vendor/github.com/go-critic/go-critic/LICENSE @@ -1,7 +1,6 @@ MIT License -Copyright (c) 2018-2019 Alekseev Artem -Copyright (c) 2018-2019 Ravil Bikbulatov +Copyright (c) 2018-2021 go-critic team Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go b/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go index 03662fc21..3c81449e9 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/appendCombine_checker.go @@ -30,7 +30,7 @@ type appendCombineChecker struct { ctx *linter.CheckerContext } -func (c *appendCombineChecker) VisitStmtList(list []ast.Stmt) { +func (c *appendCombineChecker) VisitStmtList(_ ast.Node, list []ast.Stmt) { var cause ast.Node // First append var slice ast.Expr // Slice being appended to chain := 0 // How much appends in a row we've seen diff --git a/vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go b/vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go deleted file mode 100644 index 98cabc54f..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/argOrder_checker.go +++ /dev/null @@ -1,97 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/types" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/astp" - "github.com/go-toolsmith/typep" -) - -func init() { - var info linter.CheckerInfo - info.Name = "argOrder" - info.Tags = []string{"diagnostic"} - info.Summary = "Detects suspicious arguments order" - info.Before = `strings.HasPrefix("#", userpass)` - info.After = `strings.HasPrefix(userpass, "#")` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&argOrderChecker{ctx: ctx}), nil - }) -} - -type argOrderChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *argOrderChecker) VisitExpr(expr ast.Expr) { - call := astcast.ToCallExpr(expr) - - // For now only handle functions of 2 args. - // TODO(quasilyte): generalize the algorithm and add more patterns. - if len(call.Args) != 2 { - return - } - - calledExpr := astcast.ToSelectorExpr(call.Fun) - obj, ok := c.ctx.TypesInfo.ObjectOf(astcast.ToIdent(calledExpr.X)).(*types.PkgName) - if !ok || !isStdlibPkg(obj.Imported()) { - return - } - - x := call.Args[0] - y := call.Args[1] - switch calledExpr.Sel.Name { - case "HasPrefix", "HasSuffix", "Contains", "TrimPrefix", "TrimSuffix", "Split": - if obj.Name() != "bytes" && obj.Name() != "strings" { - return - } - if c.isConstLiteral(x) && !c.isConstLiteral(y) { - c.warn(call) - } - } -} - -func (c *argOrderChecker) isConstLiteral(x ast.Expr) bool { - // Also permit byte slices. - switch x := x.(type) { - case *ast.BasicLit: - return true - - case *ast.CallExpr: - // Handle `[]byte("abc")` as well. - if len(x.Args) != 1 || !astp.IsBasicLit(x.Args[0]) { - return false - } - typ, ok := c.ctx.TypeOf(x.Fun).(*types.Slice) - return ok && typep.HasUint8Kind(typ.Elem()) - - case *ast.CompositeLit: - // Check if it's a const byte slice. - typ, ok := c.ctx.TypeOf(x).(*types.Slice) - if !ok || !typep.HasUint8Kind(typ.Elem()) { - return false - } - for _, elt := range x.Elts { - if !astp.IsBasicLit(elt) { - return false - } - } - return true - - default: - return false - } -} - -func (c *argOrderChecker) warn(call *ast.CallExpr) { - fixed := astcopy.CallExpr(call) - fixed.Args[0], fixed.Args[1] = fixed.Args[1], fixed.Args[0] - c.ctx.Warn(call, "probably meant `%s`", fixed) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go b/vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go deleted file mode 100644 index d0bf64417..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/assignOp_checker.go +++ /dev/null @@ -1,102 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/astequal" - "github.com/go-toolsmith/typep" -) - -func init() { - var info linter.CheckerInfo - info.Name = "assignOp" - info.Tags = []string{"style"} - info.Summary = "Detects assignments that can be simplified by using assignment operators" - info.Before = `x = x * 2` - info.After = `x *= 2` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForStmt(&assignOpChecker{ctx: ctx}), nil - }) -} - -type assignOpChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *assignOpChecker) VisitStmt(stmt ast.Stmt) { - assign, ok := stmt.(*ast.AssignStmt) - cond := ok && - assign.Tok == token.ASSIGN && - len(assign.Lhs) == 1 && - len(assign.Rhs) == 1 && - typep.SideEffectFree(c.ctx.TypesInfo, assign.Lhs[0]) - if !cond { - return - } - - // TODO(quasilyte): can take commutativity into account. - expr, ok := assign.Rhs[0].(*ast.BinaryExpr) - if !ok || !astequal.Expr(assign.Lhs[0], expr.X) { - return - } - - // TODO(quasilyte): perform unparen? - switch expr.Op { - case token.MUL: - c.warn(assign, token.MUL_ASSIGN, expr.Y) - case token.QUO: - c.warn(assign, token.QUO_ASSIGN, expr.Y) - case token.REM: - c.warn(assign, token.REM_ASSIGN, expr.Y) - case token.ADD: - c.warn(assign, token.ADD_ASSIGN, expr.Y) - case token.SUB: - c.warn(assign, token.SUB_ASSIGN, expr.Y) - case token.AND: - c.warn(assign, token.AND_ASSIGN, expr.Y) - case token.OR: - c.warn(assign, token.OR_ASSIGN, expr.Y) - case token.XOR: - c.warn(assign, token.XOR_ASSIGN, expr.Y) - case token.SHL: - c.warn(assign, token.SHL_ASSIGN, expr.Y) - case token.SHR: - c.warn(assign, token.SHR_ASSIGN, expr.Y) - case token.AND_NOT: - c.warn(assign, token.AND_NOT_ASSIGN, expr.Y) - } -} - -func (c *assignOpChecker) warn(cause *ast.AssignStmt, op token.Token, rhs ast.Expr) { - suggestion := c.simplify(cause, op, rhs) - c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion) -} - -func (c *assignOpChecker) simplify(cause *ast.AssignStmt, op token.Token, rhs ast.Expr) ast.Stmt { - if lit, ok := rhs.(*ast.BasicLit); ok && lit.Kind == token.INT && lit.Value == "1" { - switch op { - case token.ADD_ASSIGN: - return &ast.IncDecStmt{ - X: cause.Lhs[0], - TokPos: cause.TokPos, - Tok: token.INC, - } - case token.SUB_ASSIGN: - return &ast.IncDecStmt{ - X: cause.Lhs[0], - TokPos: cause.TokPos, - Tok: token.DEC, - } - } - } - suggestion := astcopy.AssignStmt(cause) - suggestion.Tok = op - suggestion.Rhs[0] = rhs - return suggestion -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go deleted file mode 100644 index 7435ee57b..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/badCall_checker.go +++ /dev/null @@ -1,63 +0,0 @@ -package checkers - -import ( - "go/ast" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astcopy" -) - -func init() { - var info linter.CheckerInfo - info.Name = "badCall" - info.Tags = []string{"diagnostic"} - info.Summary = "Detects suspicious function calls" - info.Before = `strings.Replace(s, from, to, 0)` - info.After = `strings.Replace(s, from, to, -1)` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&badCallChecker{ctx: ctx}), nil - }) -} - -type badCallChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *badCallChecker) VisitExpr(expr ast.Expr) { - call := astcast.ToCallExpr(expr) - if len(call.Args) == 0 { - return - } - - // TODO(quasilyte): handle methods. - - switch qualifiedName(call.Fun) { - case "strings.Replace", "bytes.Replace": - if n := astcast.ToBasicLit(call.Args[3]); n.Value == "0" { - c.warnBadArg(n, "-1") - } - case "strings.SplitN", "bytes.SplitN": - if n := astcast.ToBasicLit(call.Args[2]); n.Value == "0" { - c.warnBadArg(n, "-1") - } - case "append": - if len(call.Args) == 1 { - c.warnAppend(call) - } - } -} - -func (c *badCallChecker) warnBadArg(badArg *ast.BasicLit, correction string) { - goodArg := astcopy.BasicLit(badArg) - goodArg.Value = correction - c.ctx.Warn(badArg, "suspicious arg %s, probably meant %s", - badArg, goodArg) -} - -func (c *badCallChecker) warnAppend(call *ast.CallExpr) { - c.ctx.Warn(call, "no-op append call, probably missing arguments") -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/badLock_checker.go b/vendor/github.com/go-critic/go-critic/checkers/badLock_checker.go deleted file mode 100644 index 8628ff2d7..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/badLock_checker.go +++ /dev/null @@ -1,116 +0,0 @@ -package checkers - -import ( - "go/ast" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astequal" -) - -func init() { - var info linter.CheckerInfo - info.Name = "badLock" - info.Tags = []string{"diagnostic", "experimental"} - info.Summary = "Detects suspicious mutex lock/unlock operations" - info.Before = ` -mu.Lock() -mu.Unlock()` - info.After = ` -mu.Lock() -defer mu.Unlock()` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForStmtList(&badLockChecker{ctx: ctx}), nil - }) -} - -type badLockChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *badLockChecker) VisitStmtList(list []ast.Stmt) { - if len(list) < 2 { - return - } - - for i := 0; i < len(list)-1; i++ { - current, ok := list[i].(*ast.ExprStmt) - if !ok { - continue - } - deferred := false - var next ast.Expr - switch x := list[i+1].(type) { - case *ast.ExprStmt: - next = x.X - case *ast.DeferStmt: - next = x.Call - deferred = true - default: - continue - } - - mutex1, lockFunc, ok := c.asLockedMutex(current.X) - if !ok { - continue - } - mutex2, unlockFunc, ok := c.asUnlockedMutex(next) - if !ok { - continue - } - if !astequal.Expr(mutex1, mutex2) { - continue - } - - switch { - case !deferred: - c.warnImmediateUnlock(mutex2) - case lockFunc == "Lock" && unlockFunc == "RUnlock": - c.warnMismatchingUnlock(mutex2, "Unlock") - case lockFunc == "RLock" && unlockFunc == "Unlock": - c.warnMismatchingUnlock(mutex2, "RUnlock") - } - } -} - -func (c *badLockChecker) asLockedMutex(e ast.Expr) (ast.Expr, string, bool) { - call, ok := e.(*ast.CallExpr) - if !ok || len(call.Args) != 0 { - return nil, "", false - } - switch fn := call.Fun.(type) { - case *ast.SelectorExpr: - if fn.Sel.Name == "Lock" || fn.Sel.Name == "RLock" { - return fn.X, fn.Sel.Name, true - } - return nil, "", false - default: - return nil, "", false - } -} - -func (c *badLockChecker) asUnlockedMutex(e ast.Expr) (ast.Expr, string, bool) { - call, ok := e.(*ast.CallExpr) - if !ok || len(call.Args) != 0 { - return nil, "", false - } - switch fn := call.Fun.(type) { - case *ast.SelectorExpr: - if fn.Sel.Name == "Unlock" || fn.Sel.Name == "RUnlock" { - return fn.X, fn.Sel.Name, true - } - return nil, "", false - default: - return nil, "", false - } -} - -func (c *badLockChecker) warnImmediateUnlock(cause ast.Node) { - c.ctx.Warn(cause, "defer is missing, mutex is unlocked immediately") -} - -func (c *badLockChecker) warnMismatchingUnlock(cause ast.Node, suggestion string) { - c.ctx.Warn(cause, "suspicious unlock, maybe %s was intended?", suggestion) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/checkers.go b/vendor/github.com/go-critic/go-critic/checkers/checkers.go index 0c2ebc00c..7ce829d36 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/checkers.go +++ b/vendor/github.com/go-critic/go-critic/checkers/checkers.go @@ -2,9 +2,15 @@ package checkers import ( + "fmt" + "go/ast" + "go/build" + "go/token" "os" + "github.com/go-critic/go-critic/checkers/rulesdata" "github.com/go-critic/go-critic/framework/linter" + "github.com/quasilyte/go-ruleguard/ruleguard" ) var collection = &linter.CheckerCollection{ @@ -17,3 +23,93 @@ var debug = func() func() bool { return v } }() + +//go:generate go run ./rules/precompile.go -rules ./rules/rules.go -o ./rulesdata/rulesdata.go + +func init() { + filename := "rules/rules.go" + + fset := token.NewFileSet() + var groups []ruleguard.GoRuleGroup + + var buildContext *build.Context + + ruleguardDebug := os.Getenv("GOCRITIC_RULEGUARD_DEBUG") != "" + + // First we create an Engine to parse all rules. + // We need it to get the structured info about our rules + // that will be used to generate checkers. + // We introduce an extra scope in hope that rootEngine + // will be garbage-collected after we don't need it. + // LoadedGroups() returns a slice copy and that's all what we need. + { + rootEngine := ruleguard.NewEngine() + rootEngine.InferBuildContext() + buildContext = rootEngine.BuildContext + + loadContext := &ruleguard.LoadContext{ + Fset: fset, + DebugImports: ruleguardDebug, + DebugPrint: func(s string) { + fmt.Println("debug:", s) + }, + } + if err := rootEngine.LoadFromIR(loadContext, filename, rulesdata.PrecompiledRules); err != nil { + panic(fmt.Sprintf("load embedded ruleguard rules: %v", err)) + } + groups = rootEngine.LoadedGroups() + } + + // For every rules group we create a new checker and a separate engine. + // That dedicated ruleguard engine will contain rules only from one group. + for i := range groups { + g := groups[i] + info := &linter.CheckerInfo{ + Name: g.Name, + Summary: g.DocSummary, + Before: g.DocBefore, + After: g.DocAfter, + Note: g.DocNote, + Tags: g.DocTags, + + EmbeddedRuleguard: true, + } + collection.AddChecker(info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { + parseContext := &ruleguard.LoadContext{ + Fset: fset, + GroupFilter: func(name string) bool { + return name == g.Name + }, + DebugImports: ruleguardDebug, + DebugPrint: func(s string) { + fmt.Println("debug:", s) + }, + } + engine := ruleguard.NewEngine() + engine.BuildContext = buildContext + err := engine.LoadFromIR(parseContext, filename, rulesdata.PrecompiledRules) + if err != nil { + return nil, err + } + c := &embeddedRuleguardChecker{ + ctx: ctx, + engine: engine, + } + return c, nil + }) + } +} + +type embeddedRuleguardChecker struct { + ctx *linter.CheckerContext + engine *ruleguard.Engine +} + +func (c *embeddedRuleguardChecker) WalkFile(f *ast.File) { + runRuleguardEngine(c.ctx, f, c.engine, &ruleguard.RunContext{ + Pkg: c.ctx.Pkg, + Types: c.ctx.TypesInfo, + Sizes: c.ctx.SizesInfo, + Fset: c.ctx.FileSet, + }) +} diff --git a/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go b/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go index d4939f3f6..513eb246d 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/commentFormatting_checker.go @@ -26,6 +26,7 @@ func init() { `^//nolint\b`, // e.g.: nolint `^//line /.*:\d+`, // e.g.: line /path/to/file:123 `^//export \w+$`, // e.g.: export Foo + `^//[/+#-]+.*$`, // e.g.: vertical breaker ///////////// } pat := "(?m)" + strings.Join(parts, "|") pragmaRE := regexp.MustCompile(pat) diff --git a/vendor/github.com/go-critic/go-critic/checkers/deferUnlambda_checker.go b/vendor/github.com/go-critic/go-critic/checkers/deferUnlambda_checker.go deleted file mode 100644 index b312bfb68..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/deferUnlambda_checker.go +++ /dev/null @@ -1,94 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/types" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" -) - -func init() { - var info linter.CheckerInfo - info.Name = "deferUnlambda" - info.Tags = []string{"style", "experimental"} - info.Summary = "Detects deferred function literals that can be simplified" - info.Before = `defer func() { f() }()` - info.After = `f()` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForStmt(&deferUnlambdaChecker{ctx: ctx}), nil - }) -} - -type deferUnlambdaChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *deferUnlambdaChecker) VisitStmt(x ast.Stmt) { - def, ok := x.(*ast.DeferStmt) - if !ok { - return - } - - // We don't analyze deferred function args. - // Most deferred calls don't have them, so it's not a big deal to skip them. - if len(def.Call.Args) != 0 { - return - } - - fn, ok := def.Call.Fun.(*ast.FuncLit) - if !ok { - return - } - - if len(fn.Body.List) != 1 { - return - } - - call, ok := astcast.ToExprStmt(fn.Body.List[0]).X.(*ast.CallExpr) - if !ok || !c.isFunctionCall(call) { - return - } - - // Skip recover() as it can't be moved outside of the lambda. - // Skip panic() to avoid affecting the stack trace. - switch qualifiedName(call.Fun) { - case "recover", "panic": - return - } - - for _, arg := range call.Args { - if !c.isConstExpr(arg) { - return - } - } - - c.warn(def, call) -} - -func (c *deferUnlambdaChecker) isFunctionCall(e *ast.CallExpr) bool { - switch fnExpr := e.Fun.(type) { - case *ast.Ident: - return true - case *ast.SelectorExpr: - x, ok := fnExpr.X.(*ast.Ident) - if !ok { - return false - } - _, ok = c.ctx.TypesInfo.ObjectOf(x).(*types.PkgName) - return ok - default: - return false - } -} - -func (c *deferUnlambdaChecker) isConstExpr(e ast.Expr) bool { - return c.ctx.TypesInfo.Types[e].Value != nil -} - -func (c *deferUnlambdaChecker) warn(cause, suggestion ast.Node) { - c.ctx.Warn(cause, "can rewrite as `defer %s`", suggestion) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go deleted file mode 100644 index 9f116d781..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/dupArg_checker.go +++ /dev/null @@ -1,133 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/types" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astequal" -) - -func init() { - var info linter.CheckerInfo - info.Name = "dupArg" - info.Tags = []string{"diagnostic"} - info.Summary = "Detects suspicious duplicated arguments" - info.Before = `copy(dst, dst)` - info.After = `copy(dst, src)` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - c := &dupArgChecker{ctx: ctx} - // newMatcherFunc returns a function that matches a call if - // args[xIndex] and args[yIndex] are equal. - newMatcherFunc := func(xIndex, yIndex int) func(*ast.CallExpr) bool { - return func(call *ast.CallExpr) bool { - if len(call.Args) <= xIndex || len(call.Args) <= yIndex { - return false - } - x := call.Args[xIndex] - y := call.Args[yIndex] - return astequal.Expr(x, y) - } - } - - // m maps pattern string to a matching function. - // String patterns are used for documentation purposes (readability). - m := map[string]func(*ast.CallExpr) bool{ - "(x, x, ...)": newMatcherFunc(0, 1), - "(x, _, x, ...)": newMatcherFunc(0, 2), - "(_, x, x, ...)": newMatcherFunc(1, 2), - } - - // TODO(quasilyte): handle x.Equal(x) cases. - // Example: *math/Big.Int.Cmp method. - - // TODO(quasilyte): more perky mode that will also - // report things like io.Copy(x, x). - // Probably safe thing to do even without that option - // if `x` is not interface (requires type checks - // that are not incorporated into this checker yet). - - c.matchers = map[string]func(*ast.CallExpr) bool{ - "copy": m["(x, x, ...)"], - - "math.Max": m["(x, x, ...)"], - "math.Min": m["(x, x, ...)"], - - "reflect.Copy": m["(x, x, ...)"], - "reflect.DeepEqual": m["(x, x, ...)"], - - "strings.Contains": m["(x, x, ...)"], - "strings.Compare": m["(x, x, ...)"], - "strings.EqualFold": m["(x, x, ...)"], - "strings.HasPrefix": m["(x, x, ...)"], - "strings.HasSuffix": m["(x, x, ...)"], - "strings.Index": m["(x, x, ...)"], - "strings.LastIndex": m["(x, x, ...)"], - "strings.Split": m["(x, x, ...)"], - "strings.SplitAfter": m["(x, x, ...)"], - "strings.SplitAfterN": m["(x, x, ...)"], - "strings.SplitN": m["(x, x, ...)"], - "strings.Replace": m["(_, x, x, ...)"], - "strings.ReplaceAll": m["(_, x, x, ...)"], - - "bytes.Contains": m["(x, x, ...)"], - "bytes.Compare": m["(x, x, ...)"], - "bytes.Equal": m["(x, x, ...)"], - "bytes.EqualFold": m["(x, x, ...)"], - "bytes.HasPrefix": m["(x, x, ...)"], - "bytes.HasSuffix": m["(x, x, ...)"], - "bytes.Index": m["(x, x, ...)"], - "bytes.LastIndex": m["(x, x, ...)"], - "bytes.Split": m["(x, x, ...)"], - "bytes.SplitAfter": m["(x, x, ...)"], - "bytes.SplitAfterN": m["(x, x, ...)"], - "bytes.SplitN": m["(x, x, ...)"], - "bytes.Replace": m["(_, x, x, ...)"], - "bytes.ReplaceAll": m["(_, x, x, ...)"], - - "types.Identical": m["(x, x, ...)"], - "types.IdenticalIgnoreTags": m["(x, x, ...)"], - - "draw.Draw": m["(x, _, x, ...)"], - - // TODO(quasilyte): more of these. - } - return astwalk.WalkerForExpr(c), nil - }) -} - -type dupArgChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext - - matchers map[string]func(*ast.CallExpr) bool -} - -func (c *dupArgChecker) VisitExpr(expr ast.Expr) { - call, ok := expr.(*ast.CallExpr) - if !ok { - return - } - - // TODO(quasilyte): this kind of check is needed in multiple - // places and the code is somewhat duplicated around. - // We probably need to stop using qualifiedName for non-experimental checkers. - if calledExpr, ok := call.Fun.(*ast.SelectorExpr); ok { - obj, ok := c.ctx.TypesInfo.ObjectOf(astcast.ToIdent(calledExpr.X)).(*types.PkgName) - if !ok || !isStdlibPkg(obj.Imported()) { - return - } - } - - m := c.matchers[qualifiedName(call.Fun)] - if m != nil && m(call) { - c.warn(call) - } -} - -func (c *dupArgChecker) warn(cause ast.Node) { - c.ctx.Warn(cause, "suspicious duplicated args in `%s`", cause) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go b/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go index 0c1962682..a56500760 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/dupCase_checker.go @@ -12,7 +12,7 @@ func init() { var info linter.CheckerInfo info.Name = "dupCase" info.Tags = []string{"diagnostic"} - info.Summary = "Detects duplicated case clauses inside switch statements" + info.Summary = "Detects duplicated case clauses inside switch or select statements" info.Before = ` switch x { case ys[0], ys[1], ys[2], ys[0], ys[4]: @@ -35,8 +35,11 @@ type dupCaseChecker struct { } func (c *dupCaseChecker) VisitStmt(stmt ast.Stmt) { - if stmt, ok := stmt.(*ast.SwitchStmt); ok { + switch stmt := stmt.(type) { + case *ast.SwitchStmt: c.checkSwitch(stmt) + case *ast.SelectStmt: + c.checkSelect(stmt) } } @@ -52,6 +55,16 @@ func (c *dupCaseChecker) checkSwitch(stmt *ast.SwitchStmt) { } } +func (c *dupCaseChecker) checkSelect(stmt *ast.SelectStmt) { + c.astSet.Clear() + for i := range stmt.Body.List { + x := stmt.Body.List[i].(*ast.CommClause).Comm + if !c.astSet.Insert(x) { + c.warn(x) + } + } +} + func (c *dupCaseChecker) warn(cause ast.Node) { c.ctx.Warn(cause, "'case %s' is duplicated", cause) } diff --git a/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go b/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go index d017ee6ca..dcc964846 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/elseif_checker.go @@ -59,7 +59,7 @@ func (c *elseifChecker) VisitStmt(stmt ast.Stmt) { if balanced && c.skipBalanced { return // Configured to skip balanced statements } - if innerIfStmt.Else != nil { + if innerIfStmt.Else != nil || innerIfStmt.Init != nil { return } c.warn(stmt.Else) diff --git a/vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go b/vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go deleted file mode 100644 index 27ccbd2f2..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/emptyStringTest_checker.go +++ /dev/null @@ -1,58 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/typep" -) - -func init() { - var info linter.CheckerInfo - info.Name = "emptyStringTest" - info.Tags = []string{"style", "experimental"} - info.Summary = "Detects empty string checks that can be written more idiomatically" - info.Before = `len(s) == 0` - info.After = `s == ""` - info.Note = "See https://dmitri.shuralyov.com/idiomatic-go#empty-string-check." - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&emptyStringTestChecker{ctx: ctx}), nil - }) -} - -type emptyStringTestChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *emptyStringTestChecker) VisitExpr(e ast.Expr) { - cmp := astcast.ToBinaryExpr(e) - if cmp.Op != token.EQL && cmp.Op != token.NEQ { - return - } - lenCall := astcast.ToCallExpr(cmp.X) - if astcast.ToIdent(lenCall.Fun).Name != "len" { - return - } - s := lenCall.Args[0] - if !typep.HasStringProp(c.ctx.TypeOf(s)) { - return - } - zero := astcast.ToBasicLit(cmp.Y) - if zero.Value != "0" { - return - } - c.warn(cmp, s) -} - -func (c *emptyStringTestChecker) warn(cmp *ast.BinaryExpr, s ast.Expr) { - suggest := astcopy.BinaryExpr(cmp) - suggest.X = s - suggest.Y = &ast.BasicLit{Value: `""`} - c.ctx.Warn(cmp, "replace `%s` with `%s`", cmp, suggest) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go b/vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go deleted file mode 100644 index 13f7fdbe2..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/equalFold_checker.go +++ /dev/null @@ -1,87 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astequal" -) - -func init() { - var info linter.CheckerInfo - info.Name = "equalFold" - info.Tags = []string{"performance", "experimental"} - info.Summary = "Detects unoptimal strings/bytes case-insensitive comparison" - info.Before = `strings.ToLower(x) == strings.ToLower(y)` - info.After = `strings.EqualFold(x, y)` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&equalFoldChecker{ctx: ctx}), nil - }) -} - -type equalFoldChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *equalFoldChecker) VisitExpr(e ast.Expr) { - switch e := e.(type) { - case *ast.CallExpr: - c.checkBytes(e) - case *ast.BinaryExpr: - c.checkStrings(e) - } -} - -// uncaseCall simplifies lower(x) or upper(x) to x. -// If no simplification is applied, second return value is false. -func (c *equalFoldChecker) uncaseCall(x ast.Expr, lower, upper string) (ast.Expr, bool) { - call := astcast.ToCallExpr(x) - name := qualifiedName(call.Fun) - if name != lower && name != upper { - return x, false - } - return call.Args[0], true -} - -func (c *equalFoldChecker) checkBytes(expr *ast.CallExpr) { - if qualifiedName(expr.Fun) != "bytes.Equal" { - return - } - - x, ok1 := c.uncaseCall(expr.Args[0], "bytes.ToLower", "bytes.ToUpper") - y, ok2 := c.uncaseCall(expr.Args[1], "bytes.ToLower", "bytes.ToUpper") - if !ok1 && !ok2 { - return - } - if !astequal.Expr(x, y) { - c.warnBytes(expr, x, y) - } -} - -func (c *equalFoldChecker) checkStrings(expr *ast.BinaryExpr) { - if expr.Op != token.EQL && expr.Op != token.NEQ { - return - } - - x, ok1 := c.uncaseCall(expr.X, "strings.ToLower", "strings.ToUpper") - y, ok2 := c.uncaseCall(expr.Y, "strings.ToLower", "strings.ToUpper") - if !ok1 && !ok2 { - return - } - if !astequal.Expr(x, y) { - c.warnStrings(expr, x, y) - } -} - -func (c *equalFoldChecker) warnStrings(cause ast.Node, x, y ast.Expr) { - c.ctx.Warn(cause, "consider replacing with strings.EqualFold(%s, %s)", x, y) -} - -func (c *equalFoldChecker) warnBytes(cause ast.Node, x, y ast.Expr) { - c.ctx.Warn(cause, "consider replacing with bytes.EqualFold(%s, %s)", x, y) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go b/vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go deleted file mode 100644 index 3fe5e52fb..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/flagDeref_checker.go +++ /dev/null @@ -1,65 +0,0 @@ -package checkers - -import ( - "go/ast" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" -) - -func init() { - var info linter.CheckerInfo - info.Name = "flagDeref" - info.Tags = []string{"diagnostic"} - info.Summary = "Detects immediate dereferencing of `flag` package pointers" - info.Details = "Suggests to use pointer to array to avoid the copy using `&` on range expression." - info.Before = `b := *flag.Bool("b", false, "b docs")` - info.After = ` -var b bool -flag.BoolVar(&b, "b", false, "b docs")` - info.Note = ` -Dereferencing returned pointers will lead to hard to find errors -where flag values are not updated after flag.Parse().` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - c := &flagDerefChecker{ - ctx: ctx, - flagPtrFuncs: map[string]bool{ - "flag.Bool": true, - "flag.Duration": true, - "flag.Float64": true, - "flag.Int": true, - "flag.Int64": true, - "flag.String": true, - "flag.Uint": true, - "flag.Uint64": true, - }, - } - return astwalk.WalkerForExpr(c), nil - }) -} - -type flagDerefChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext - - flagPtrFuncs map[string]bool -} - -func (c *flagDerefChecker) VisitExpr(expr ast.Expr) { - if expr, ok := expr.(*ast.StarExpr); ok { - call, ok := expr.X.(*ast.CallExpr) - if !ok { - return - } - called := qualifiedName(call.Fun) - if c.flagPtrFuncs[called] { - c.warn(expr, called+"Var") - } - } -} - -func (c *flagDerefChecker) warn(x ast.Node, suggestion string) { - c.ctx.Warn(x, "immediate deref in %s is most likely an error; consider using %s", - x, suggestion) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go b/vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go deleted file mode 100644 index 908285c03..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/indexAlloc_checker.go +++ /dev/null @@ -1,50 +0,0 @@ -package checkers - -import ( - "go/ast" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/typep" -) - -func init() { - var info linter.CheckerInfo - info.Name = "indexAlloc" - info.Tags = []string{"performance"} - info.Summary = "Detects strings.Index calls that may cause unwanted allocs" - info.Before = `strings.Index(string(x), y)` - info.After = `bytes.Index(x, []byte(y))` - info.Note = `See Go issue for details: https://github.com/golang/go/issues/25864` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&indexAllocChecker{ctx: ctx}), nil - }) -} - -type indexAllocChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *indexAllocChecker) VisitExpr(e ast.Expr) { - call := astcast.ToCallExpr(e) - if qualifiedName(call.Fun) != "strings.Index" { - return - } - stringConv := astcast.ToCallExpr(call.Args[0]) - if qualifiedName(stringConv.Fun) != "string" { - return - } - x := stringConv.Args[0] - y := call.Args[1] - if typep.SideEffectFree(c.ctx.TypesInfo, x) && typep.SideEffectFree(c.ctx.TypesInfo, y) { - c.warn(e, x, y) - } -} - -func (c *indexAllocChecker) warn(cause ast.Node, x, y ast.Expr) { - c.ctx.Warn(cause, "consider replacing %s with bytes.Index(%s, []byte(%s))", - cause, x, y) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go index bed0f44ab..47de589a4 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/local_def_visitor.go @@ -42,7 +42,7 @@ const ( // Initializing expression is always nil. NameParam NameKind = iota // NameVar is var or ":=" declared name. - // Initizlizing expression may be nil for var-declared names + // Initializing expression may be nil for var-declared names // without explicit initializing expression. NameVar // NameConst is const-declared name. diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go index 45c406e7e..403292f66 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/stmt_list_walker.go @@ -21,11 +21,11 @@ func (w *stmtListWalker) WalkFile(f *ast.File) { ast.Inspect(decl.Body, func(x ast.Node) bool { switch x := x.(type) { case *ast.BlockStmt: - w.visitor.VisitStmtList(x.List) + w.visitor.VisitStmtList(x, x.List) case *ast.CaseClause: - w.visitor.VisitStmtList(x.Body) + w.visitor.VisitStmtList(x, x.Body) case *ast.CommClause: - w.visitor.VisitStmtList(x.Body) + w.visitor.VisitStmtList(x, x.Body) } return !w.visitor.skipChilds() }) diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go index 24c150084..9c198e733 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/type_expr_walker.go @@ -48,6 +48,8 @@ func (w *typeExprWalker) visit(x ast.Expr) bool { func (w *typeExprWalker) walk(x ast.Node) bool { switch x := x.(type) { + case *ast.ChanType: + return w.visit(x) case *ast.ParenExpr: if typep.IsTypeExpr(w.info, x.X) { return w.visit(x) diff --git a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go index 9f973a2b3..e5031a909 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go +++ b/vendor/github.com/go-critic/go-critic/checkers/internal/astwalk/visitor.go @@ -36,7 +36,7 @@ type ( // introduced by case clauses and alike. StmtListVisitor interface { walkerEvents - VisitStmtList([]ast.Stmt) + VisitStmtList(ast.Node, []ast.Stmt) } // StmtVisitor visits every statement inside function body. diff --git a/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go b/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go index 486940452..bed227ac3 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/octalLiteral_checker.go @@ -3,7 +3,8 @@ package checkers import ( "go/ast" "go/token" - "go/types" + "strings" + "unicode" "github.com/go-critic/go-critic/checkers/internal/astwalk" "github.com/go-critic/go-critic/framework/linter" @@ -13,70 +14,34 @@ import ( func init() { var info linter.CheckerInfo info.Name = "octalLiteral" - info.Tags = []string{"diagnostic", "experimental"} - info.Summary = "Detects octal literals passed to functions" + info.Tags = []string{"style", "experimental", "opinionated"} + info.Summary = "Detects old-style octal literals" info.Before = `foo(02)` - info.After = `foo(2)` + info.After = `foo(0o2)` collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - c := &octalLiteralChecker{ - ctx: ctx, - octFriendlyPkg: map[string]bool{ - "os": true, - "io/ioutil": true, - }, - } - return astwalk.WalkerForExpr(c), nil + return astwalk.WalkerForExpr(&octalLiteralChecker{ctx: ctx}), nil }) } type octalLiteralChecker struct { astwalk.WalkHandler ctx *linter.CheckerContext - - octFriendlyPkg map[string]bool } func (c *octalLiteralChecker) VisitExpr(expr ast.Expr) { - call := astcast.ToCallExpr(expr) - calledExpr := astcast.ToSelectorExpr(call.Fun) - ident := astcast.ToIdent(calledExpr.X) - - if obj, ok := c.ctx.TypesInfo.ObjectOf(ident).(*types.PkgName); ok { - pkg := obj.Imported() - if c.octFriendlyPkg[pkg.Path()] { - return - } + lit := astcast.ToBasicLit(expr) + if lit.Kind != token.INT { + return } - - for _, arg := range call.Args { - if lit := astcast.ToBasicLit(c.unsign(arg)); len(lit.Value) > 1 && - c.isIntLiteral(lit) && - c.isOctalLiteral(lit) { - c.warn(call) - return - } + if !strings.HasPrefix(lit.Value, "0") || len(lit.Value) == 1 { + return + } + if unicode.IsDigit(rune(lit.Value[1])) { + c.warn(lit) } } -func (c *octalLiteralChecker) unsign(e ast.Expr) ast.Expr { - u, ok := e.(*ast.UnaryExpr) - if !ok { - return e - } - return u.X -} - -func (c *octalLiteralChecker) isIntLiteral(lit *ast.BasicLit) bool { - return lit.Kind == token.INT -} - -func (c *octalLiteralChecker) isOctalLiteral(lit *ast.BasicLit) bool { - return lit.Value[0] == '0' && - lit.Value[1] != 'x' && - lit.Value[1] != 'X' -} - -func (c *octalLiteralChecker) warn(expr ast.Expr) { - c.ctx.Warn(expr, "suspicious octal args in `%s`", expr) +func (c *octalLiteralChecker) warn(lit *ast.BasicLit) { + c.ctx.Warn(lit, "use new octal literal style, 0o%s", lit.Value[len("0"):]) } diff --git a/vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go b/vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go deleted file mode 100644 index ece3fdfdb..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/offBy1_checker.go +++ /dev/null @@ -1,66 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/astequal" - "github.com/go-toolsmith/typep" -) - -func init() { - var info linter.CheckerInfo - info.Name = "offBy1" - info.Tags = []string{"diagnostic"} - info.Summary = "Detects various off-by-one kind of errors" - info.Before = `xs[len(xs)]` - info.After = `xs[len(xs)-1]` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&offBy1Checker{ctx: ctx}), nil - }) -} - -type offBy1Checker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *offBy1Checker) VisitExpr(e ast.Expr) { - // TODO(quasilyte): handle more off-by-1 patterns. - // TODO(quasilyte): check whether go/analysis can help here. - - // Detect s[len(s)] expressions that always panic. - // The correct form is s[len(s)-1]. - - indexExpr := astcast.ToIndexExpr(e) - indexed := indexExpr.X - if !typep.IsSlice(c.ctx.TypeOf(indexed)) { - return - } - if !typep.SideEffectFree(c.ctx.TypesInfo, indexed) { - return - } - call := astcast.ToCallExpr(indexExpr.Index) - if astcast.ToIdent(call.Fun).Name != "len" { - return - } - if len(call.Args) != 1 || !astequal.Expr(call.Args[0], indexed) { - return - } - c.warnLenIndex(indexExpr) -} - -func (c *offBy1Checker) warnLenIndex(cause *ast.IndexExpr) { - suggest := astcopy.IndexExpr(cause) - suggest.Index = &ast.BinaryExpr{ - Op: token.SUB, - X: cause.Index, - Y: &ast.BasicLit{Value: "1"}, - } - c.ctx.Warn(cause, "index expr always panics; maybe you wanted %s?", suggest) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go b/vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go deleted file mode 100644 index 600aa73d0..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/regexpMust_checker.go +++ /dev/null @@ -1,47 +0,0 @@ -package checkers - -import ( - "go/ast" - "strings" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astp" - "golang.org/x/tools/go/ast/astutil" -) - -func init() { - var info linter.CheckerInfo - info.Name = "regexpMust" - info.Tags = []string{"style"} - info.Summary = "Detects `regexp.Compile*` that can be replaced with `regexp.MustCompile*`" - info.Before = `re, _ := regexp.Compile("const pattern")` - info.After = `re := regexp.MustCompile("const pattern")` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(®expMustChecker{ctx: ctx}), nil - }) -} - -type regexpMustChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *regexpMustChecker) VisitExpr(x ast.Expr) { - if x, ok := x.(*ast.CallExpr); ok { - switch name := qualifiedName(x.Fun); name { - case "regexp.Compile", "regexp.CompilePOSIX": - // Only check for trivial string args, permit parenthesis. - if !astp.IsBasicLit(astutil.Unparen(x.Args[0])) { - return - } - c.warn(x, strings.Replace(name, "Compile", "MustCompile", 1)) - } - } -} - -func (c *regexpMustChecker) warn(cause *ast.CallExpr, suggestion string) { - c.ctx.Warn(cause, "for const patterns like %s, use %s", - cause.Args[0], suggestion) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go b/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go index ecb3dc9ee..d65669fdd 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/ruleguard_checker.go @@ -2,10 +2,10 @@ package checkers import ( "bytes" + "errors" "fmt" "go/ast" "go/token" - "io/ioutil" "log" "os" "path/filepath" @@ -31,7 +31,15 @@ func init() { }, "failOnError": { Value: false, - Usage: "If true, panic when the gorule files contain a syntax error. If false, log and skip rules that contain an error", + Usage: "deprecated, use failOn param; if set to true, identical to failOn='all', otherwise failOn=''", + }, + "failOn": { + Value: "", + Usage: `Determines the behavior when an error occurs while parsing ruleguard files. +If flag is not set, log error and skip rule files that contain an error. +If flag is set, the value must be a comma-separated list of error conditions. +* 'import': rule refers to a package that cannot be loaded. +* 'dsl': gorule file does not comply with the ruleguard DSL.`, }, } info.Summary = "Runs user-defined rules using ruleguard linter" @@ -45,6 +53,52 @@ func init() { }) } +// parseErrorHandler is used to determine whether to ignore or fail ruleguard parsing errors. +type parseErrorHandler struct { + // failureConditions is a map of predicates which are evaluated against a ruleguard parsing error. + // If at least one predicate returns true, then an error is returned. + // Otherwise, the ruleguard file is skipped. + failureConditions map[string]func(err error) bool +} + +// failOnParseError returns true if a parseError occurred and that error should be not be ignored. +func (e parseErrorHandler) failOnParseError(parseError error) bool { + for _, p := range e.failureConditions { + if p(parseError) { + return true + } + } + return false +} + +func newErrorHandler(failOnErrorFlag string) (*parseErrorHandler, error) { + h := parseErrorHandler{ + failureConditions: make(map[string]func(err error) bool), + } + var failOnErrorPredicates = map[string]func(error) bool{ + "dsl": func(err error) bool { var e *ruleguard.ImportError; return !errors.As(err, &e) }, + "import": func(err error) bool { var e *ruleguard.ImportError; return errors.As(err, &e) }, + "all": func(err error) bool { return true }, + } + for _, k := range strings.Split(failOnErrorFlag, ",") { + if k == "" { + continue + } + if p, ok := failOnErrorPredicates[k]; ok { + h.failureConditions[k] = p + } else { + // Wrong flag value. + supportedValues := []string{} + for key := range failOnErrorPredicates { + supportedValues = append(supportedValues, key) + } + return nil, fmt.Errorf("ruleguard init error: 'failOnError' flag '%s' is invalid. It must be a comma-separated list and supported values are '%s'", + k, strings.Join(supportedValues, ",")) + } + } + return &h, nil +} + func newRuleguardChecker(info *linter.CheckerInfo, ctx *linter.CheckerContext) (*ruleguardChecker, error) { c := &ruleguardChecker{ ctx: ctx, @@ -54,20 +108,30 @@ func newRuleguardChecker(info *linter.CheckerInfo, ctx *linter.CheckerContext) ( if rulesFlag == "" { return c, nil } - failOnErrorFlag := info.Params.Bool("failOnError") - - // TODO(quasilyte): handle initialization errors better when we make - // a transition to the go/analysis framework. - // - // For now, we log error messages and return a ruleguard checker - // with an empty rules set. + failOn := info.Params.String("failOn") + if failOn == "" { + if info.Params.Bool("failOnError") { + failOn = "all" + } + } + h, err := newErrorHandler(failOn) + if err != nil { + return nil, err + } engine := ruleguard.NewEngine() + engine.InferBuildContext() fset := token.NewFileSet() filePatterns := strings.Split(rulesFlag, ",") - parseContext := &ruleguard.ParseContext{ - Fset: fset, + ruleguardDebug := os.Getenv("GOCRITIC_RULEGUARD_DEBUG") != "" + + loadContext := &ruleguard.LoadContext{ + Fset: fset, + DebugImports: ruleguardDebug, + DebugPrint: func(s string) { + fmt.Println("debug:", s) + }, } loaded := 0 @@ -78,21 +142,22 @@ func newRuleguardChecker(info *linter.CheckerInfo, ctx *linter.CheckerContext) ( log.Printf("ruleguard init error: %+v", err) continue } + if len(filenames) == 0 { + return nil, fmt.Errorf("ruleguard init error: no file matching '%s'", strings.TrimSpace(filePattern)) + } for _, filename := range filenames { - data, err := ioutil.ReadFile(filename) + data, err := os.ReadFile(filename) if err != nil { - if failOnErrorFlag { + if h.failOnParseError(err) { return nil, fmt.Errorf("ruleguard init error: %+v", err) } - log.Printf("ruleguard init error: %+v", err) - continue + log.Printf("ruleguard init error, skip %s: %+v", filename, err) } - if err := engine.Load(parseContext, filename, bytes.NewReader(data)); err != nil { - if failOnErrorFlag { + if err := engine.Load(loadContext, filename, bytes.NewReader(data)); err != nil { + if h.failOnParseError(err) { return nil, fmt.Errorf("ruleguard init error: %+v", err) } - log.Printf("ruleguard init error: %+v", err) - continue + log.Printf("ruleguard init error, skip %s: %+v", filename, err) } loaded++ } @@ -116,13 +181,7 @@ func (c *ruleguardChecker) WalkFile(f *ast.File) { return } - type ruleguardReport struct { - node ast.Node - message string - } - var reports []ruleguardReport - - ctx := &ruleguard.RunContext{ + runRuleguardEngine(c.ctx, f, c.engine, &ruleguard.RunContext{ Debug: c.debugGroup, DebugPrint: func(s string) { fmt.Fprintln(os.Stderr, s) @@ -131,27 +190,49 @@ func (c *ruleguardChecker) WalkFile(f *ast.File) { Types: c.ctx.TypesInfo, Sizes: c.ctx.SizesInfo, Fset: c.ctx.FileSet, - Report: func(_ ruleguard.GoRuleInfo, n ast.Node, msg string, _ *ruleguard.Suggestion) { - // TODO(quasilyte): investigate whether we should add a rule name as - // a message prefix here. - reports = append(reports, ruleguardReport{ - node: n, - message: msg, - }) - }, + }) +} + +func runRuleguardEngine(ctx *linter.CheckerContext, f *ast.File, e *ruleguard.Engine, runCtx *ruleguard.RunContext) { + type ruleguardReport struct { + node ast.Node + message string + fix linter.QuickFix + } + var reports []ruleguardReport + + runCtx.Report = func(_ ruleguard.GoRuleInfo, n ast.Node, msg string, fix *ruleguard.Suggestion) { + // TODO(quasilyte): investigate whether we should add a rule name as + // a message prefix here. + r := ruleguardReport{ + node: n, + message: msg, + } + if fix != nil { + r.fix = linter.QuickFix{ + From: fix.From, + To: fix.To, + Replacement: fix.Replacement, + } + } + reports = append(reports, r) } - if err := c.engine.Run(ctx, f); err != nil { + if err := e.Run(runCtx, f); err != nil { // Normally this should never happen, but since // we don't have a better mechanism to report errors, // emit a warning. - c.ctx.Warn(f, "execution error: %v", err) + ctx.Warn(f, "execution error: %v", err) } sort.Slice(reports, func(i, j int) bool { return reports[i].message < reports[j].message }) for _, report := range reports { - c.ctx.Warn(report.node, report.message) + if report.fix.Replacement != nil { + ctx.WarnFixable(report.node, report.fix, "%s", report.message) + } else { + ctx.Warn(report.node, "%s", report.message) + } } } diff --git a/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go b/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go new file mode 100644 index 000000000..c53265e31 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/checkers/rulesdata/rulesdata.go @@ -0,0 +1,2680 @@ +// Code generated by "precompile.go". DO NOT EDIT. + +package rulesdata + +import "github.com/quasilyte/go-ruleguard/ruleguard/ir" + +var PrecompiledRules = &ir.File{ + PkgPath: "gorules", + CustomDecls: []string{}, + BundleImports: []ir.BundleImport{}, + RuleGroups: []ir.RuleGroup{ + ir.RuleGroup{ + Line: 11, + Name: "redundantSprint", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects redundant fmt.Sprint calls", + DocBefore: "fmt.Sprint(x)", + DocAfter: "x.String()", + Rules: []ir.Rule{ + ir.Rule{ + Line: 12, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 12, Value: "fmt.Sprint($x)"}, + ir.PatternString{Line: 12, Value: "fmt.Sprintf(\"%s\", $x)"}, + ir.PatternString{Line: 12, Value: "fmt.Sprintf(\"%v\", $x)"}, + }, + ReportTemplate: "use $x.String() instead", + SuggestTemplate: "$x.String()", + WhereExpr: ir.FilterExpr{ + Line: 13, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"x\"].Type.Implements(`fmt.Stringer`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 13, Op: ir.FilterStringOp, Src: "`fmt.Stringer`", Value: "fmt.Stringer"}, + }, + }, + }, + ir.Rule{ + Line: 17, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 17, Value: "fmt.Sprint($x)"}, + ir.PatternString{Line: 17, Value: "fmt.Sprintf(\"%s\", $x)"}, + ir.PatternString{Line: 17, Value: "fmt.Sprintf(\"%v\", $x)"}, + }, + ReportTemplate: "use $x.Error() instead", + SuggestTemplate: "$x.Error()", + WhereExpr: ir.FilterExpr{ + Line: 18, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"x\"].Type.Implements(`error`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 18, Op: ir.FilterStringOp, Src: "`error`", Value: "error"}, + }, + }, + }, + ir.Rule{ + Line: 22, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 22, Value: "fmt.Sprint($x)"}, + ir.PatternString{Line: 22, Value: "fmt.Sprintf(\"%s\", $x)"}, + ir.PatternString{Line: 22, Value: "fmt.Sprintf(\"%v\", $x)"}, + }, + ReportTemplate: "$x is already string", + SuggestTemplate: "$x", + WhereExpr: ir.FilterExpr{ + Line: 23, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`string`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 23, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 32, + Name: "deferUnlambda", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects deferred function literals that can be simplified", + DocBefore: "defer func() { f() }()", + DocAfter: "defer f()", + Rules: []ir.Rule{ + ir.Rule{ + Line: 33, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 33, Value: "defer func() { $f($*args) }()"}, + }, + ReportTemplate: "can rewrite as `defer $f($args)`", + WhereExpr: ir.FilterExpr{ + Line: 34, + Op: ir.FilterAndOp, + Src: "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\" && m[\"f\"].Text != \"recover\" && m[\"args\"].Const", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 34, + Op: ir.FilterAndOp, + Src: "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\" && m[\"f\"].Text != \"recover\"", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 34, + Op: ir.FilterAndOp, + Src: "m[\"f\"].Node.Is(`Ident`) && m[\"f\"].Text != \"panic\"", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 34, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"f\"].Node.Is(`Ident`)", + Value: "f", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 34, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}, + }, + }, + ir.FilterExpr{ + Line: 34, + Op: ir.FilterNeqOp, + Src: "m[\"f\"].Text != \"panic\"", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 34, Op: ir.FilterVarTextOp, Src: "m[\"f\"].Text", Value: "f"}, + ir.FilterExpr{Line: 34, Op: ir.FilterStringOp, Src: "\"panic\"", Value: "panic"}, + }, + }, + }, + }, + ir.FilterExpr{ + Line: 34, + Op: ir.FilterNeqOp, + Src: "m[\"f\"].Text != \"recover\"", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 34, Op: ir.FilterVarTextOp, Src: "m[\"f\"].Text", Value: "f"}, + ir.FilterExpr{Line: 34, Op: ir.FilterStringOp, Src: "\"recover\"", Value: "recover"}, + }, + }, + }, + }, + ir.FilterExpr{ + Line: 34, + Op: ir.FilterVarConstOp, + Src: "m[\"args\"].Const", + Value: "args", + }, + }, + }, + }, + ir.Rule{ + Line: 37, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 37, Value: "defer func() { $pkg.$f($*args) }()"}, + }, + ReportTemplate: "can rewrite as `defer $pkg.$f($args)`", + WhereExpr: ir.FilterExpr{ + Line: 38, + Op: ir.FilterAndOp, + Src: "m[\"f\"].Node.Is(`Ident`) && m[\"args\"].Const && m[\"pkg\"].Object.Is(`PkgName`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 38, + Op: ir.FilterAndOp, + Src: "m[\"f\"].Node.Is(`Ident`) && m[\"args\"].Const", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 38, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"f\"].Node.Is(`Ident`)", + Value: "f", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 38, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}, + }, + }, + ir.FilterExpr{ + Line: 38, + Op: ir.FilterVarConstOp, + Src: "m[\"args\"].Const", + Value: "args", + }, + }, + }, + ir.FilterExpr{ + Line: 38, + Op: ir.FilterVarObjectIsOp, + Src: "m[\"pkg\"].Object.Is(`PkgName`)", + Value: "pkg", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 38, Op: ir.FilterStringOp, Src: "`PkgName`", Value: "PkgName"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 46, + Name: "ioutilDeprecated", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects deprecated io/ioutil package usages", + DocBefore: "ioutil.ReadAll(r)", + DocAfter: "io.ReadAll(r)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 47, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 47, Value: "ioutil.ReadAll($_)"}, + }, + ReportTemplate: "ioutil.ReadAll is deprecated, use io.ReadAll instead", + WhereExpr: ir.FilterExpr{ + Line: 48, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.16\")", + Value: "1.16", + }, + }, + ir.Rule{ + Line: 51, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 51, Value: "ioutil.ReadFile($_)"}, + }, + ReportTemplate: "ioutil.ReadFile is deprecated, use os.ReadFile instead", + WhereExpr: ir.FilterExpr{ + Line: 52, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.16\")", + Value: "1.16", + }, + }, + ir.Rule{ + Line: 55, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 55, Value: "ioutil.WriteFile($_, $_, $_)"}, + }, + ReportTemplate: "ioutil.WriteFile is deprecated, use os.WriteFile instead", + WhereExpr: ir.FilterExpr{ + Line: 56, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.16\")", + Value: "1.16", + }, + }, + ir.Rule{ + Line: 59, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 59, Value: "ioutil.ReadDir($_)"}, + }, + ReportTemplate: "ioutil.ReadDir is deprecated, use os.ReadDir instead", + WhereExpr: ir.FilterExpr{ + Line: 60, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.16\")", + Value: "1.16", + }, + }, + ir.Rule{ + Line: 63, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 63, Value: "ioutil.NopCloser($_)"}, + }, + ReportTemplate: "ioutil.NopCloser is deprecated, use io.NopCloser instead", + WhereExpr: ir.FilterExpr{ + Line: 64, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.16\")", + Value: "1.16", + }, + }, + ir.Rule{ + Line: 67, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 67, Value: "ioutil.Discard"}, + }, + ReportTemplate: "ioutil.Discard is deprecated, use io.Discard instead", + WhereExpr: ir.FilterExpr{ + Line: 68, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.16\")", + Value: "1.16", + }, + }, + }, + }, + ir.RuleGroup{ + Line: 76, + Name: "badLock", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects suspicious mutex lock/unlock operations", + DocBefore: "mu.Lock(); mu.Unlock()", + DocAfter: "mu.Lock(); defer mu.Unlock()", + Rules: []ir.Rule{ + ir.Rule{ + Line: 80, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 80, Value: "$mu1.Lock(); $mu2.Unlock()"}, + }, + ReportTemplate: "defer is missing, mutex is unlocked immediately", + WhereExpr: ir.FilterExpr{ + Line: 81, + Op: ir.FilterEqOp, + Src: "m[\"mu1\"].Text == m[\"mu2\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 81, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"}, + ir.FilterExpr{Line: 81, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"}, + }, + }, + LocationVar: "mu2", + }, + ir.Rule{ + Line: 85, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 85, Value: "$mu1.RLock(); $mu2.RUnlock()"}, + }, + ReportTemplate: "defer is missing, mutex is unlocked immediately", + WhereExpr: ir.FilterExpr{ + Line: 86, + Op: ir.FilterEqOp, + Src: "m[\"mu1\"].Text == m[\"mu2\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 86, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"}, + ir.FilterExpr{Line: 86, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"}, + }, + }, + LocationVar: "mu2", + }, + ir.Rule{ + Line: 91, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 91, Value: "$mu1.Lock(); defer $mu2.RUnlock()"}, + }, + ReportTemplate: "suspicious unlock, maybe Unlock was intended?", + WhereExpr: ir.FilterExpr{ + Line: 92, + Op: ir.FilterEqOp, + Src: "m[\"mu1\"].Text == m[\"mu2\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 92, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"}, + ir.FilterExpr{Line: 92, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"}, + }, + }, + LocationVar: "mu2", + }, + ir.Rule{ + Line: 96, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 96, Value: "$mu1.RLock(); defer $mu2.Unlock()"}, + }, + ReportTemplate: "suspicious unlock, maybe RUnlock was intended?", + WhereExpr: ir.FilterExpr{ + Line: 97, + Op: ir.FilterEqOp, + Src: "m[\"mu1\"].Text == m[\"mu2\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 97, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"}, + ir.FilterExpr{Line: 97, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"}, + }, + }, + LocationVar: "mu2", + }, + ir.Rule{ + Line: 102, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 102, Value: "$mu1.Lock(); defer $mu2.Lock()"}, + }, + ReportTemplate: "maybe defer $mu1.Unlock() was intended?", + WhereExpr: ir.FilterExpr{ + Line: 103, + Op: ir.FilterEqOp, + Src: "m[\"mu1\"].Text == m[\"mu2\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 103, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"}, + ir.FilterExpr{Line: 103, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"}, + }, + }, + LocationVar: "mu2", + }, + ir.Rule{ + Line: 107, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 107, Value: "$mu1.RLock(); defer $mu2.RLock()"}, + }, + ReportTemplate: "maybe defer $mu1.RUnlock() was intended?", + WhereExpr: ir.FilterExpr{ + Line: 108, + Op: ir.FilterEqOp, + Src: "m[\"mu1\"].Text == m[\"mu2\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 108, Op: ir.FilterVarTextOp, Src: "m[\"mu1\"].Text", Value: "mu1"}, + ir.FilterExpr{Line: 108, Op: ir.FilterVarTextOp, Src: "m[\"mu2\"].Text", Value: "mu2"}, + }, + }, + LocationVar: "mu2", + }, + }, + }, + ir.RuleGroup{ + Line: 117, + Name: "httpNoBody", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects nil usages in http.NewRequest calls, suggesting http.NoBody as an alternative", + DocBefore: "http.NewRequest(\"GET\", url, nil)", + DocAfter: "http.NewRequest(\"GET\", url, http.NoBody)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 118, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 118, Value: "http.NewRequest($method, $url, $nil)"}, + }, + ReportTemplate: "http.NoBody should be preferred to the nil request body", + SuggestTemplate: "http.NewRequest($method, $url, http.NoBody)", + WhereExpr: ir.FilterExpr{ + Line: 119, + Op: ir.FilterEqOp, + Src: "m[\"nil\"].Text == \"nil\"", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 119, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"}, + ir.FilterExpr{Line: 119, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"}, + }, + }, + }, + ir.Rule{ + Line: 123, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 123, Value: "http.NewRequestWithContext($ctx, $method, $url, $nil)"}, + }, + ReportTemplate: "http.NoBody should be preferred to the nil request body", + SuggestTemplate: "http.NewRequestWithContext($ctx, $method, $url, http.NoBody)", + WhereExpr: ir.FilterExpr{ + Line: 124, + Op: ir.FilterEqOp, + Src: "m[\"nil\"].Text == \"nil\"", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 124, Op: ir.FilterVarTextOp, Src: "m[\"nil\"].Text", Value: "nil"}, + ir.FilterExpr{Line: 124, Op: ir.FilterStringOp, Src: "\"nil\"", Value: "nil"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 134, + Name: "preferDecodeRune", + MatcherName: "m", + DocTags: []string{ + "performance", + "experimental", + }, + DocSummary: "Detects expressions like []rune(s)[0] that may cause unwanted rune slice allocation", + DocBefore: "r := []rune(s)[0]", + DocAfter: "r, _ := utf8.DecodeRuneInString(s)", + DocNote: "See Go issue for details: https://github.com/golang/go/issues/45260", + Rules: []ir.Rule{ + ir.Rule{ + Line: 135, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 135, Value: "[]rune($s)[0]"}, + }, + ReportTemplate: "consider replacing $$ with utf8.DecodeRuneInString($s)", + WhereExpr: ir.FilterExpr{ + Line: 136, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 136, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 144, + Name: "sloppyLen", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects usage of `len` when result is obvious or doesn't make sense", + DocBefore: "len(arr) <= 0", + DocAfter: "len(arr) == 0", + Rules: []ir.Rule{ + ir.Rule{ + Line: 145, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 145, Value: "len($_) >= 0"}, + }, + ReportTemplate: "$$ is always true", + }, + ir.Rule{ + Line: 146, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 146, Value: "len($_) < 0"}, + }, + ReportTemplate: "$$ is always false", + }, + ir.Rule{ + Line: 147, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 147, Value: "len($x) <= 0"}, + }, + ReportTemplate: "$$ can be len($x) == 0", + }, + }, + }, + ir.RuleGroup{ + Line: 154, + Name: "valSwap", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects value swapping code that are not using parallel assignment", + DocBefore: "*tmp = *x; *x = *y; *y = *tmp", + DocAfter: "*x, *y = *y, *x", + Rules: []ir.Rule{ + ir.Rule{ + Line: 155, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 155, Value: "$tmp := $y; $y = $x; $x = $tmp"}, + }, + ReportTemplate: "can re-write as `$y, $x = $x, $y`", + }, + }, + }, + ir.RuleGroup{ + Line: 163, + Name: "switchTrue", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects switch-over-bool statements that use explicit `true` tag value", + DocBefore: "switch true {...}", + DocAfter: "switch {...}", + Rules: []ir.Rule{ + ir.Rule{ + Line: 164, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 164, Value: "switch true { $*_ }"}, + }, + ReportTemplate: "replace 'switch true {}' with 'switch {}'", + }, + ir.Rule{ + Line: 166, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 166, Value: "switch $x; true { $*_ }"}, + }, + ReportTemplate: "replace 'switch $x; true {}' with 'switch $x; {}'", + }, + }, + }, + ir.RuleGroup{ + Line: 174, + Name: "flagDeref", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + }, + DocSummary: "Detects immediate dereferencing of `flag` package pointers", + DocBefore: "b := *flag.Bool(\"b\", false, \"b docs\")", + DocAfter: "var b bool; flag.BoolVar(&b, \"b\", false, \"b docs\")", + Rules: []ir.Rule{ + ir.Rule{ + Line: 175, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 175, Value: "*flag.Bool($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.BoolVar", + }, + ir.Rule{ + Line: 176, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 176, Value: "*flag.Duration($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.DurationVar", + }, + ir.Rule{ + Line: 177, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 177, Value: "*flag.Float64($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Float64Var", + }, + ir.Rule{ + Line: 178, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 178, Value: "*flag.Int($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.IntVar", + }, + ir.Rule{ + Line: 179, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 179, Value: "*flag.Int64($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Int64Var", + }, + ir.Rule{ + Line: 180, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 180, Value: "*flag.String($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.StringVar", + }, + ir.Rule{ + Line: 181, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 181, Value: "*flag.Uint($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.UintVar", + }, + ir.Rule{ + Line: 182, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 182, Value: "*flag.Uint64($*_)"}, + }, + ReportTemplate: "immediate deref in $$ is most likely an error; consider using flag.Uint64Var", + }, + }, + }, + ir.RuleGroup{ + Line: 189, + Name: "emptyStringTest", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects empty string checks that can be written more idiomatically", + DocBefore: "len(s) == 0", + DocAfter: "s == \"\"", + Rules: []ir.Rule{ + ir.Rule{ + Line: 190, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 190, Value: "len($s) != 0"}, + }, + ReportTemplate: "replace `$$` with `$s != \"\"`", + WhereExpr: ir.FilterExpr{ + Line: 191, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 191, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + ir.Rule{ + Line: 194, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 194, Value: "len($s) == 0"}, + }, + ReportTemplate: "replace `$$` with `$s == \"\"`", + WhereExpr: ir.FilterExpr{ + Line: 195, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 195, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 203, + Name: "stringXbytes", + MatcherName: "m", + DocTags: []string{ + "performance", + }, + DocSummary: "Detects redundant conversions between string and []byte", + DocBefore: "copy(b, []byte(s))", + DocAfter: "copy(b, s)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 204, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 204, Value: "copy($_, []byte($s))"}, + }, + ReportTemplate: "can simplify `[]byte($s)` to `$s`", + }, + ir.Rule{ + Line: 206, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 206, Value: "string($b) == \"\""}, + }, + ReportTemplate: "suggestion: len($b) == 0", + SuggestTemplate: "len($b) == 0", + WhereExpr: ir.FilterExpr{ + Line: 206, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"b\"].Type.Is(`[]byte`)", + Value: "b", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 206, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + }, + ir.Rule{ + Line: 207, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 207, Value: "string($b) != \"\""}, + }, + ReportTemplate: "suggestion: len($b) != 0", + SuggestTemplate: "len($b) != 0", + WhereExpr: ir.FilterExpr{ + Line: 207, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"b\"].Type.Is(`[]byte`)", + Value: "b", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 207, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + }, + ir.Rule{ + Line: 209, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 209, Value: "len(string($b))"}, + }, + ReportTemplate: "suggestion: len($b)", + SuggestTemplate: "len($b)", + WhereExpr: ir.FilterExpr{ + Line: 209, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"b\"].Type.Is(`[]byte`)", + Value: "b", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 209, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + }, + ir.Rule{ + Line: 211, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 211, Value: "string($x) == string($y)"}, + }, + ReportTemplate: "suggestion: bytes.Equal($x, $y)", + SuggestTemplate: "bytes.Equal($x, $y)", + WhereExpr: ir.FilterExpr{ + Line: 212, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Type.Is(`[]byte`) && m[\"y\"].Type.Is(`[]byte`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 212, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`[]byte`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 212, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + ir.FilterExpr{ + Line: 212, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"y\"].Type.Is(`[]byte`)", + Value: "y", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 212, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 215, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 215, Value: "string($x) != string($y)"}, + }, + ReportTemplate: "suggestion: !bytes.Equal($x, $y)", + SuggestTemplate: "!bytes.Equal($x, $y)", + WhereExpr: ir.FilterExpr{ + Line: 216, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Type.Is(`[]byte`) && m[\"y\"].Type.Is(`[]byte`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 216, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`[]byte`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 216, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + ir.FilterExpr{ + Line: 216, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"y\"].Type.Is(`[]byte`)", + Value: "y", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 216, Op: ir.FilterStringOp, Src: "`[]byte`", Value: "[]byte"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 219, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 219, Value: "$re.Match([]byte($s))"}, + }, + ReportTemplate: "suggestion: $re.MatchString($s)", + SuggestTemplate: "$re.MatchString($s)", + WhereExpr: ir.FilterExpr{ + Line: 220, + Op: ir.FilterAndOp, + Src: "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 220, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"re\"].Type.Is(`*regexp.Regexp`)", + Value: "re", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 220, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}, + }, + }, + ir.FilterExpr{ + Line: 220, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 220, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 223, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 223, Value: "$re.FindIndex([]byte($s))"}, + }, + ReportTemplate: "suggestion: $re.FindStringIndex($s)", + SuggestTemplate: "$re.FindStringIndex($s)", + WhereExpr: ir.FilterExpr{ + Line: 224, + Op: ir.FilterAndOp, + Src: "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 224, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"re\"].Type.Is(`*regexp.Regexp`)", + Value: "re", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 224, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}, + }, + }, + ir.FilterExpr{ + Line: 224, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 224, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 227, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 227, Value: "$re.FindAllIndex([]byte($s), $n)"}, + }, + ReportTemplate: "suggestion: $re.FindAllStringIndex($s, $n)", + SuggestTemplate: "$re.FindAllStringIndex($s, $n)", + WhereExpr: ir.FilterExpr{ + Line: 228, + Op: ir.FilterAndOp, + Src: "m[\"re\"].Type.Is(`*regexp.Regexp`) && m[\"s\"].Type.Is(`string`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 228, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"re\"].Type.Is(`*regexp.Regexp`)", + Value: "re", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 228, Op: ir.FilterStringOp, Src: "`*regexp.Regexp`", Value: "*regexp.Regexp"}, + }, + }, + ir.FilterExpr{ + Line: 228, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 228, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 237, + Name: "indexAlloc", + MatcherName: "m", + DocTags: []string{ + "performance", + }, + DocSummary: "Detects strings.Index calls that may cause unwanted allocs", + DocBefore: "strings.Index(string(x), y)", + DocAfter: "bytes.Index(x, []byte(y))", + DocNote: "See Go issue for details: https://github.com/golang/go/issues/25864", + Rules: []ir.Rule{ + ir.Rule{ + Line: 238, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 238, Value: "strings.Index(string($x), $y)"}, + }, + ReportTemplate: "consider replacing $$ with bytes.Index($x, []byte($y))", + WhereExpr: ir.FilterExpr{ + Line: 239, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 239, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + ir.FilterExpr{Line: 239, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 247, + Name: "wrapperFunc", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects function calls that can be replaced with convenience wrappers", + DocBefore: "wg.Add(-1)", + DocAfter: "wg.Done()", + Rules: []ir.Rule{ + ir.Rule{ + Line: 248, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 248, Value: "$wg.Add(-1)"}, + }, + ReportTemplate: "use WaitGroup.Done method in `$$`", + WhereExpr: ir.FilterExpr{ + Line: 249, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"wg\"].Type.Is(`sync.WaitGroup`)", + Value: "wg", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 249, Op: ir.FilterStringOp, Src: "`sync.WaitGroup`", Value: "sync.WaitGroup"}, + }, + }, + }, + ir.Rule{ + Line: 252, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 252, Value: "$buf.Truncate(0)"}, + }, + ReportTemplate: "use Buffer.Reset method in `$$`", + WhereExpr: ir.FilterExpr{ + Line: 253, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"buf\"].Type.Is(`bytes.Buffer`)", + Value: "buf", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 253, Op: ir.FilterStringOp, Src: "`bytes.Buffer`", Value: "bytes.Buffer"}, + }, + }, + }, + ir.Rule{ + Line: 256, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 256, Value: "http.HandlerFunc(http.NotFound)"}, + }, + ReportTemplate: "use http.NotFoundHandler method in `$$`", + }, + ir.Rule{ + Line: 258, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 258, Value: "strings.SplitN($_, $_, -1)"}, + }, + ReportTemplate: "use strings.Split method in `$$`", + }, + ir.Rule{ + Line: 259, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 259, Value: "strings.Replace($_, $_, $_, -1)"}, + }, + ReportTemplate: "use strings.ReplaceAll method in `$$`", + }, + ir.Rule{ + Line: 260, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 260, Value: "strings.Map(unicode.ToTitle, $_)"}, + }, + ReportTemplate: "use strings.ToTitle method in `$$`", + }, + ir.Rule{ + Line: 262, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 262, Value: "bytes.SplitN(b, []byte(\".\"), -1)"}, + }, + ReportTemplate: "use bytes.Split method in `$$`", + }, + ir.Rule{ + Line: 263, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 263, Value: "bytes.Replace($_, $_, $_, -1)"}, + }, + ReportTemplate: "use bytes.ReplaceAll method in `$$`", + }, + ir.Rule{ + Line: 264, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 264, Value: "bytes.Map(unicode.ToUpper, $_)"}, + }, + ReportTemplate: "use bytes.ToUpper method in `$$`", + }, + ir.Rule{ + Line: 265, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 265, Value: "bytes.Map(unicode.ToLower, $_)"}, + }, + ReportTemplate: "use bytes.ToLower method in `$$`", + }, + ir.Rule{ + Line: 266, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 266, Value: "bytes.Map(unicode.ToTitle, $_)"}, + }, + ReportTemplate: "use bytes.ToTitle method in `$$`", + }, + ir.Rule{ + Line: 268, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 268, Value: "draw.DrawMask($_, $_, $_, $_, nil, image.Point{}, $_)"}, + }, + ReportTemplate: "use draw.Draw method in `$$`", + }, + }, + }, + ir.RuleGroup{ + Line: 276, + Name: "regexpMust", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects `regexp.Compile*` that can be replaced with `regexp.MustCompile*`", + DocBefore: "re, _ := regexp.Compile(\"const pattern\")", + DocAfter: "re := regexp.MustCompile(\"const pattern\")", + Rules: []ir.Rule{ + ir.Rule{ + Line: 277, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 277, Value: "regexp.Compile($pat)"}, + }, + ReportTemplate: "for const patterns like $pat, use regexp.MustCompile", + WhereExpr: ir.FilterExpr{ + Line: 278, + Op: ir.FilterVarConstOp, + Src: "m[\"pat\"].Const", + Value: "pat", + }, + }, + ir.Rule{ + Line: 281, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 281, Value: "regexp.CompilePOSIX($pat)"}, + }, + ReportTemplate: "for const patterns like $pat, use regexp.MustCompilePOSIX", + WhereExpr: ir.FilterExpr{ + Line: 282, + Op: ir.FilterVarConstOp, + Src: "m[\"pat\"].Const", + Value: "pat", + }, + }, + }, + }, + ir.RuleGroup{ + Line: 290, + Name: "badCall", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + }, + DocSummary: "Detects suspicious function calls", + DocBefore: "strings.Replace(s, from, to, 0)", + DocAfter: "strings.Replace(s, from, to, -1)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 291, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 291, Value: "strings.Replace($_, $_, $_, $zero)"}, + }, + ReportTemplate: "suspicious arg 0, probably meant -1", + WhereExpr: ir.FilterExpr{ + Line: 292, + Op: ir.FilterEqOp, + Src: "m[\"zero\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 292, + Op: ir.FilterVarValueIntOp, + Src: "m[\"zero\"].Value.Int()", + Value: "zero", + }, + ir.FilterExpr{ + Line: 292, + Op: ir.FilterIntOp, + Src: "0", + Value: int64(0), + }, + }, + }, + LocationVar: "zero", + }, + ir.Rule{ + Line: 294, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 294, Value: "bytes.Replace($_, $_, $_, $zero)"}, + }, + ReportTemplate: "suspicious arg 0, probably meant -1", + WhereExpr: ir.FilterExpr{ + Line: 295, + Op: ir.FilterEqOp, + Src: "m[\"zero\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 295, + Op: ir.FilterVarValueIntOp, + Src: "m[\"zero\"].Value.Int()", + Value: "zero", + }, + ir.FilterExpr{ + Line: 295, + Op: ir.FilterIntOp, + Src: "0", + Value: int64(0), + }, + }, + }, + LocationVar: "zero", + }, + ir.Rule{ + Line: 298, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 298, Value: "strings.SplitN($_, $_, $zero)"}, + }, + ReportTemplate: "suspicious arg 0, probably meant -1", + WhereExpr: ir.FilterExpr{ + Line: 299, + Op: ir.FilterEqOp, + Src: "m[\"zero\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 299, + Op: ir.FilterVarValueIntOp, + Src: "m[\"zero\"].Value.Int()", + Value: "zero", + }, + ir.FilterExpr{ + Line: 299, + Op: ir.FilterIntOp, + Src: "0", + Value: int64(0), + }, + }, + }, + LocationVar: "zero", + }, + ir.Rule{ + Line: 301, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 301, Value: "bytes.SplitN($_, $_, $zero)"}, + }, + ReportTemplate: "suspicious arg 0, probably meant -1", + WhereExpr: ir.FilterExpr{ + Line: 302, + Op: ir.FilterEqOp, + Src: "m[\"zero\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 302, + Op: ir.FilterVarValueIntOp, + Src: "m[\"zero\"].Value.Int()", + Value: "zero", + }, + ir.FilterExpr{ + Line: 302, + Op: ir.FilterIntOp, + Src: "0", + Value: int64(0), + }, + }, + }, + LocationVar: "zero", + }, + ir.Rule{ + Line: 305, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 305, Value: "append($_)"}, + }, + ReportTemplate: "no-op append call, probably missing arguments", + }, + ir.Rule{ + Line: 307, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 307, Value: "filepath.Join($_)"}, + }, + ReportTemplate: "suspicious Join on 1 argument", + }, + }, + }, + ir.RuleGroup{ + Line: 314, + Name: "assignOp", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects assignments that can be simplified by using assignment operators", + DocBefore: "x = x * 2", + DocAfter: "x *= 2", + Rules: []ir.Rule{ + ir.Rule{ + Line: 315, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 315, Value: "$x = $x + 1"}, + }, + ReportTemplate: "replace `$$` with `$x++`", + WhereExpr: ir.FilterExpr{Line: 315, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 316, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 316, Value: "$x = $x - 1"}, + }, + ReportTemplate: "replace `$$` with `$x--`", + WhereExpr: ir.FilterExpr{Line: 316, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 318, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 318, Value: "$x = $x + $y"}, + }, + ReportTemplate: "replace `$$` with `$x += $y`", + WhereExpr: ir.FilterExpr{Line: 318, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 319, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 319, Value: "$x = $x - $y"}, + }, + ReportTemplate: "replace `$$` with `$x -= $y`", + WhereExpr: ir.FilterExpr{Line: 319, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 321, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 321, Value: "$x = $x * $y"}, + }, + ReportTemplate: "replace `$$` with `$x *= $y`", + WhereExpr: ir.FilterExpr{Line: 321, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 322, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 322, Value: "$x = $x / $y"}, + }, + ReportTemplate: "replace `$$` with `$x /= $y`", + WhereExpr: ir.FilterExpr{Line: 322, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 323, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 323, Value: "$x = $x % $y"}, + }, + ReportTemplate: "replace `$$` with `$x %= $y`", + WhereExpr: ir.FilterExpr{Line: 323, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 324, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 324, Value: "$x = $x & $y"}, + }, + ReportTemplate: "replace `$$` with `$x &= $y`", + WhereExpr: ir.FilterExpr{Line: 324, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 325, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 325, Value: "$x = $x | $y"}, + }, + ReportTemplate: "replace `$$` with `$x |= $y`", + WhereExpr: ir.FilterExpr{Line: 325, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 326, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 326, Value: "$x = $x ^ $y"}, + }, + ReportTemplate: "replace `$$` with `$x ^= $y`", + WhereExpr: ir.FilterExpr{Line: 326, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 327, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 327, Value: "$x = $x << $y"}, + }, + ReportTemplate: "replace `$$` with `$x <<= $y`", + WhereExpr: ir.FilterExpr{Line: 327, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 328, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 328, Value: "$x = $x >> $y"}, + }, + ReportTemplate: "replace `$$` with `$x >>= $y`", + WhereExpr: ir.FilterExpr{Line: 328, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 329, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 329, Value: "$x = $x &^ $y"}, + }, + ReportTemplate: "replace `$$` with `$x &^= $y`", + WhereExpr: ir.FilterExpr{Line: 329, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + }, + }, + ir.RuleGroup{ + Line: 336, + Name: "preferWriteByte", + MatcherName: "m", + DocTags: []string{ + "performance", + "experimental", + }, + DocSummary: "Detects WriteRune calls with byte literal argument and reports to use WriteByte instead", + DocBefore: "w.WriteRune('\\n')", + DocAfter: "w.WriteByte('\\n')", + Rules: []ir.Rule{ + ir.Rule{ + Line: 337, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 337, Value: "$w.WriteRune($c)"}, + }, + ReportTemplate: "consider replacing $$ with $w.WriteByte($c)", + WhereExpr: ir.FilterExpr{ + Line: 338, + Op: ir.FilterAndOp, + Src: "m[\"w\"].Type.Implements(\"io.ByteWriter\") && (m[\"c\"].Const && m[\"c\"].Value.Int() < 256)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 338, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"w\"].Type.Implements(\"io.ByteWriter\")", + Value: "w", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 338, Op: ir.FilterStringOp, Src: "\"io.ByteWriter\"", Value: "io.ByteWriter"}, + }, + }, + ir.FilterExpr{ + Line: 338, + Op: ir.FilterAndOp, + Src: "(m[\"c\"].Const && m[\"c\"].Value.Int() < 256)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 338, + Op: ir.FilterVarConstOp, + Src: "m[\"c\"].Const", + Value: "c", + }, + ir.FilterExpr{ + Line: 338, + Op: ir.FilterLtOp, + Src: "m[\"c\"].Value.Int() < 256", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 338, + Op: ir.FilterVarValueIntOp, + Src: "m[\"c\"].Value.Int()", + Value: "c", + }, + ir.FilterExpr{ + Line: 338, + Op: ir.FilterIntOp, + Src: "256", + Value: int64(256), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 346, + Name: "preferFprint", + MatcherName: "m", + DocTags: []string{ + "performance", + "experimental", + }, + DocSummary: "Detects fmt.Sprint(f|ln) calls which can be replaced with fmt.Fprint(f|ln)", + DocBefore: "w.Write([]byte(fmt.Sprintf(\"%x\", 10)))", + DocAfter: "fmt.Fprintf(w, \"%x\", 10)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 347, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 347, Value: "$w.Write([]byte(fmt.Sprint($*args)))"}, + }, + ReportTemplate: "fmt.Fprint($w, $args) should be preferred to the $$", + SuggestTemplate: "fmt.Fprint($w, $args)", + WhereExpr: ir.FilterExpr{ + Line: 348, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"w\"].Type.Implements(\"io.Writer\")", + Value: "w", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 348, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}, + }, + }, + }, + ir.Rule{ + Line: 352, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 352, Value: "$w.Write([]byte(fmt.Sprintf($*args)))"}, + }, + ReportTemplate: "fmt.Fprintf($w, $args) should be preferred to the $$", + SuggestTemplate: "fmt.Fprintf($w, $args)", + WhereExpr: ir.FilterExpr{ + Line: 353, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"w\"].Type.Implements(\"io.Writer\")", + Value: "w", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 353, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}, + }, + }, + }, + ir.Rule{ + Line: 357, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 357, Value: "$w.Write([]byte(fmt.Sprintln($*args)))"}, + }, + ReportTemplate: "fmt.Fprintln($w, $args) should be preferred to the $$", + SuggestTemplate: "fmt.Fprintln($w, $args)", + WhereExpr: ir.FilterExpr{ + Line: 358, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"w\"].Type.Implements(\"io.Writer\")", + Value: "w", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 358, Op: ir.FilterStringOp, Src: "\"io.Writer\"", Value: "io.Writer"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 367, + Name: "dupArg", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + }, + DocSummary: "Detects suspicious duplicated arguments", + DocBefore: "copy(dst, dst)", + DocAfter: "copy(dst, src)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 368, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 368, Value: "$x.Equal($x)"}, + ir.PatternString{Line: 368, Value: "$x.Equals($x)"}, + ir.PatternString{Line: 368, Value: "$x.Compare($x)"}, + ir.PatternString{Line: 368, Value: "$x.Cmp($x)"}, + }, + ReportTemplate: "suspicious method call with the same argument and receiver", + WhereExpr: ir.FilterExpr{Line: 369, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + ir.Rule{ + Line: 372, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 372, Value: "copy($x, $x)"}, + ir.PatternString{Line: 373, Value: "math.Max($x, $x)"}, + ir.PatternString{Line: 374, Value: "math.Min($x, $x)"}, + ir.PatternString{Line: 375, Value: "reflect.Copy($x, $x)"}, + ir.PatternString{Line: 376, Value: "reflect.DeepEqual($x, $x)"}, + ir.PatternString{Line: 377, Value: "strings.Contains($x, $x)"}, + ir.PatternString{Line: 378, Value: "strings.Compare($x, $x)"}, + ir.PatternString{Line: 379, Value: "strings.EqualFold($x, $x)"}, + ir.PatternString{Line: 380, Value: "strings.HasPrefix($x, $x)"}, + ir.PatternString{Line: 381, Value: "strings.HasSuffix($x, $x)"}, + ir.PatternString{Line: 382, Value: "strings.Index($x, $x)"}, + ir.PatternString{Line: 383, Value: "strings.LastIndex($x, $x)"}, + ir.PatternString{Line: 384, Value: "strings.Split($x, $x)"}, + ir.PatternString{Line: 385, Value: "strings.SplitAfter($x, $x)"}, + ir.PatternString{Line: 386, Value: "strings.SplitAfterN($x, $x, $_)"}, + ir.PatternString{Line: 387, Value: "strings.SplitN($x, $x, $_)"}, + ir.PatternString{Line: 388, Value: "strings.Replace($_, $x, $x, $_)"}, + ir.PatternString{Line: 389, Value: "strings.ReplaceAll($_, $x, $x)"}, + ir.PatternString{Line: 390, Value: "bytes.Contains($x, $x)"}, + ir.PatternString{Line: 391, Value: "bytes.Compare($x, $x)"}, + ir.PatternString{Line: 392, Value: "bytes.Equal($x, $x)"}, + ir.PatternString{Line: 393, Value: "bytes.EqualFold($x, $x)"}, + ir.PatternString{Line: 394, Value: "bytes.HasPrefix($x, $x)"}, + ir.PatternString{Line: 395, Value: "bytes.HasSuffix($x, $x)"}, + ir.PatternString{Line: 396, Value: "bytes.Index($x, $x)"}, + ir.PatternString{Line: 397, Value: "bytes.LastIndex($x, $x)"}, + ir.PatternString{Line: 398, Value: "bytes.Split($x, $x)"}, + ir.PatternString{Line: 399, Value: "bytes.SplitAfter($x, $x)"}, + ir.PatternString{Line: 400, Value: "bytes.SplitAfterN($x, $x, $_)"}, + ir.PatternString{Line: 401, Value: "bytes.SplitN($x, $x, $_)"}, + ir.PatternString{Line: 402, Value: "bytes.Replace($_, $x, $x, $_)"}, + ir.PatternString{Line: 403, Value: "bytes.ReplaceAll($_, $x, $x)"}, + ir.PatternString{Line: 404, Value: "types.Identical($x, $x)"}, + ir.PatternString{Line: 405, Value: "types.IdenticalIgnoreTags($x, $x)"}, + ir.PatternString{Line: 406, Value: "draw.Draw($x, $_, $x, $_, $_)"}, + }, + ReportTemplate: "suspicious duplicated args in $$", + WhereExpr: ir.FilterExpr{Line: 407, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + }, + }, + }, + ir.RuleGroup{ + Line: 415, + Name: "returnAfterHttpError", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects suspicious http.Error call without following return", + DocBefore: "if err != nil { http.Error(...); }", + DocAfter: "if err != nil { http.Error(...); return; }", + Rules: []ir.Rule{ + ir.Rule{ + Line: 416, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 416, Value: "if $_ { $*_; http.Error($w, $err, $code) }"}, + }, + ReportTemplate: "Possibly return is missed after the http.Error call", + LocationVar: "w", + }, + }, + }, + ir.RuleGroup{ + Line: 425, + Name: "preferFilepathJoin", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects concatenation with os.PathSeparator which can be replaced with filepath.Join", + DocBefore: "x + string(os.PathSeparator) + y", + DocAfter: "filepath.Join(x, y)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 426, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 426, Value: "$x + string(os.PathSeparator) + $y"}, + }, + ReportTemplate: "filepath.Join($x, $y) should be preferred to the $$", + SuggestTemplate: "filepath.Join($x, $y)", + WhereExpr: ir.FilterExpr{ + Line: 427, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Type.Is(`string`) && m[\"y\"].Type.Is(`string`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 427, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`string`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 427, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + ir.FilterExpr{ + Line: 427, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"y\"].Type.Is(`string`)", + Value: "y", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 427, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 436, + Name: "preferStringWriter", + MatcherName: "m", + DocTags: []string{ + "performance", + "experimental", + }, + DocSummary: "Detects w.Write or io.WriteString calls which can be replaced with w.WriteString", + DocBefore: "w.Write([]byte(\"foo\"))", + DocAfter: "w.WriteString(\"foo\")", + Rules: []ir.Rule{ + ir.Rule{ + Line: 437, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 437, Value: "$w.Write([]byte($s))"}, + }, + ReportTemplate: "$w.WriteString($s) should be preferred to the $$", + SuggestTemplate: "$w.WriteString($s)", + WhereExpr: ir.FilterExpr{ + Line: 438, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")", + Value: "w", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 438, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}, + }, + }, + }, + ir.Rule{ + Line: 442, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 442, Value: "io.WriteString($w, $s)"}, + }, + ReportTemplate: "$w.WriteString($s) should be preferred to the $$", + SuggestTemplate: "$w.WriteString($s)", + WhereExpr: ir.FilterExpr{ + Line: 443, + Op: ir.FilterVarTypeImplementsOp, + Src: "m[\"w\"].Type.Implements(\"io.StringWriter\")", + Value: "w", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 443, Op: ir.FilterStringOp, Src: "\"io.StringWriter\"", Value: "io.StringWriter"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 452, + Name: "sliceClear", + MatcherName: "m", + DocTags: []string{ + "performance", + "experimental", + }, + DocSummary: "Detects slice clear loops, suggests an idiom that is recognized by the Go compiler", + DocBefore: "for i := 0; i < len(buf); i++ { buf[i] = 0 }", + DocAfter: "for i := range buf { buf[i] = 0 }", + Rules: []ir.Rule{ + ir.Rule{ + Line: 453, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 453, Value: "for $i := 0; $i < len($xs); $i++ { $xs[$i] = $zero }"}, + }, + ReportTemplate: "rewrite as for-range so compiler can recognize this pattern", + WhereExpr: ir.FilterExpr{ + Line: 454, + Op: ir.FilterEqOp, + Src: "m[\"zero\"].Value.Int() == 0", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 454, + Op: ir.FilterVarValueIntOp, + Src: "m[\"zero\"].Value.Int()", + Value: "zero", + }, + ir.FilterExpr{ + Line: 454, + Op: ir.FilterIntOp, + Src: "0", + Value: int64(0), + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 462, + Name: "syncMapLoadAndDelete", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects sync.Map load+delete operations that can be replaced with LoadAndDelete", + DocBefore: "v, ok := m.Load(k); if ok { m.Delete($k); f(v); }", + DocAfter: "v, deleted := m.LoadAndDelete(k); if deleted { f(v) }", + Rules: []ir.Rule{ + ir.Rule{ + Line: 463, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 463, Value: "$_, $ok := $m.Load($k); if $ok { $m.Delete($k); $*_ }"}, + }, + ReportTemplate: "use $m.LoadAndDelete to perform load+delete operations atomically", + WhereExpr: ir.FilterExpr{ + Line: 464, + Op: ir.FilterAndOp, + Src: "m.GoVersion().GreaterEqThan(\"1.15\") &&\n\tm[\"m\"].Type.Is(`*sync.Map`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 464, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.15\")", + Value: "1.15", + }, + ir.FilterExpr{ + Line: 465, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"m\"].Type.Is(`*sync.Map`)", + Value: "m", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 465, Op: ir.FilterStringOp, Src: "`*sync.Map`", Value: "*sync.Map"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 473, + Name: "sprintfQuotedString", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects \"%s\" formatting directives that can be replaced with %q", + DocBefore: "fmt.Sprintf(`\"%s\"`, s)", + DocAfter: "fmt.Sprintf(`%q`, s)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 474, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 474, Value: "fmt.Sprintf($s, $*_)"}, + }, + ReportTemplate: "use %q instead of \"%s\" for quoted strings", + WhereExpr: ir.FilterExpr{ + Line: 475, + Op: ir.FilterOrOp, + Src: "m[\"s\"].Text.Matches(\"^`.*\\\"%s\\\".*`$\") ||\n\tm[\"s\"].Text.Matches(`^\".*\\\\\"%s\\\\\".*\"$`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 475, + Op: ir.FilterVarTextMatchesOp, + Src: "m[\"s\"].Text.Matches(\"^`.*\\\"%s\\\".*`$\")", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 475, Op: ir.FilterStringOp, Src: "\"^`.*\\\"%s\\\".*`$\"", Value: "^`.*\"%s\".*`$"}, + }, + }, + ir.FilterExpr{ + Line: 476, + Op: ir.FilterVarTextMatchesOp, + Src: "m[\"s\"].Text.Matches(`^\".*\\\\\"%s\\\\\".*\"$`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 476, Op: ir.FilterStringOp, Src: "`^\".*\\\\\"%s\\\\\".*\"$`", Value: "^\".*\\\\\"%s\\\\\".*\"$"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 484, + Name: "offBy1", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + }, + DocSummary: "Detects various off-by-one kind of errors", + DocBefore: "xs[len(xs)]", + DocAfter: "xs[len(xs)-1]", + Rules: []ir.Rule{ + ir.Rule{ + Line: 485, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 485, Value: "$x[len($x)]"}, + }, + ReportTemplate: "index expr always panics; maybe you wanted $x[len($x)-1]?", + SuggestTemplate: "$x[len($x)-1]", + WhereExpr: ir.FilterExpr{ + Line: 486, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"x\"].Type.Is(`[]$_`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 486, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + ir.FilterExpr{ + Line: 486, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`[]$_`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 486, Op: ir.FilterStringOp, Src: "`[]$_`", Value: "[]$_"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 493, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 494, Value: "$i := strings.Index($s, $_); $_ := $slicing[$i:]"}, + ir.PatternString{Line: 495, Value: "$i := strings.Index($s, $_); $_ = $slicing[$i:]"}, + ir.PatternString{Line: 496, Value: "$i := bytes.Index($s, $_); $_ := $slicing[$i:]"}, + ir.PatternString{Line: 497, Value: "$i := bytes.Index($s, $_); $_ = $slicing[$i:]"}, + }, + ReportTemplate: "Index() can return -1; maybe you wanted to do $s[$i+1:]", + WhereExpr: ir.FilterExpr{ + Line: 498, + Op: ir.FilterEqOp, + Src: "m[\"s\"].Text == m[\"slicing\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 498, Op: ir.FilterVarTextOp, Src: "m[\"s\"].Text", Value: "s"}, + ir.FilterExpr{Line: 498, Op: ir.FilterVarTextOp, Src: "m[\"slicing\"].Text", Value: "slicing"}, + }, + }, + LocationVar: "slicing", + }, + ir.Rule{ + Line: 502, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 503, Value: "$i := strings.Index($s, $_); $_ := $slicing[:$i]"}, + ir.PatternString{Line: 504, Value: "$i := strings.Index($s, $_); $_ = $slicing[:$i]"}, + ir.PatternString{Line: 505, Value: "$i := bytes.Index($s, $_); $_ := $slicing[:$i]"}, + ir.PatternString{Line: 506, Value: "$i := bytes.Index($s, $_); $_ = $slicing[:$i]"}, + }, + ReportTemplate: "Index() can return -1; maybe you wanted to do $s[:$i+1]", + WhereExpr: ir.FilterExpr{ + Line: 507, + Op: ir.FilterEqOp, + Src: "m[\"s\"].Text == m[\"slicing\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 507, Op: ir.FilterVarTextOp, Src: "m[\"s\"].Text", Value: "s"}, + ir.FilterExpr{Line: 507, Op: ir.FilterVarTextOp, Src: "m[\"slicing\"].Text", Value: "slicing"}, + }, + }, + LocationVar: "slicing", + }, + ir.Rule{ + Line: 511, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 512, Value: "$s[strings.Index($s, $_):]"}, + ir.PatternString{Line: 513, Value: "$s[:strings.Index($s, $_)]"}, + ir.PatternString{Line: 514, Value: "$s[bytes.Index($s, $_):]"}, + ir.PatternString{Line: 515, Value: "$s[:bytes.Index($s, $_)]"}, + }, + ReportTemplate: "Index() can return -1; maybe you wanted to do Index()+1", + }, + }, + }, + ir.RuleGroup{ + Line: 523, + Name: "unslice", + MatcherName: "m", + DocTags: []string{ + "style", + }, + DocSummary: "Detects slice expressions that can be simplified to sliced expression itself", + DocBefore: "copy(b[:], values...)", + DocAfter: "copy(b, values...)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 524, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 524, Value: "$s[:]"}, + }, + ReportTemplate: "could simplify $$ to $s", + SuggestTemplate: "$s", + WhereExpr: ir.FilterExpr{ + Line: 525, + Op: ir.FilterOrOp, + Src: "m[\"s\"].Type.Is(`string`) || m[\"s\"].Type.Is(`[]$_`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 525, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`string`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 525, Op: ir.FilterStringOp, Src: "`string`", Value: "string"}, + }, + }, + ir.FilterExpr{ + Line: 525, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"s\"].Type.Is(`[]$_`)", + Value: "s", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 525, Op: ir.FilterStringOp, Src: "`[]$_`", Value: "[]$_"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 534, + Name: "yodaStyleExpr", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects Yoda style expressions and suggests to replace them", + DocBefore: "return nil != ptr", + DocAfter: "return ptr != nil", + Rules: []ir.Rule{ + ir.Rule{ + Line: 535, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 535, Value: "$constval != $x"}, + }, + ReportTemplate: "consider to change order in expression to $x != $constval", + WhereExpr: ir.FilterExpr{ + Line: 535, + Op: ir.FilterAndOp, + Src: "m[\"constval\"].Node.Is(`BasicLit`) && !m[\"x\"].Node.Is(`BasicLit`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 535, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"constval\"].Node.Is(`BasicLit`)", + Value: "constval", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 535, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}, + }, + }, + ir.FilterExpr{ + Line: 535, + Op: ir.FilterNotOp, + Src: "!m[\"x\"].Node.Is(`BasicLit`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 535, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"x\"].Node.Is(`BasicLit`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 535, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}, + }, + }, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 537, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 537, Value: "$constval == $x"}, + }, + ReportTemplate: "consider to change order in expression to $x == $constval", + WhereExpr: ir.FilterExpr{ + Line: 537, + Op: ir.FilterAndOp, + Src: "m[\"constval\"].Node.Is(`BasicLit`) && !m[\"x\"].Node.Is(`BasicLit`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 537, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"constval\"].Node.Is(`BasicLit`)", + Value: "constval", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 537, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}, + }, + }, + ir.FilterExpr{ + Line: 537, + Op: ir.FilterNotOp, + Src: "!m[\"x\"].Node.Is(`BasicLit`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 537, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"x\"].Node.Is(`BasicLit`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 537, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}, + }, + }, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 540, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 540, Value: "nil != $x"}, + }, + ReportTemplate: "consider to change order in expression to $x != nil", + WhereExpr: ir.FilterExpr{ + Line: 540, + Op: ir.FilterNotOp, + Src: "!m[\"x\"].Node.Is(`BasicLit`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 540, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"x\"].Node.Is(`BasicLit`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 540, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 542, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 542, Value: "nil == $x"}, + }, + ReportTemplate: "consider to change order in expression to $x == nil", + WhereExpr: ir.FilterExpr{ + Line: 542, + Op: ir.FilterNotOp, + Src: "!m[\"x\"].Node.Is(`BasicLit`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 542, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"x\"].Node.Is(`BasicLit`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 542, Op: ir.FilterStringOp, Src: "`BasicLit`", Value: "BasicLit"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 550, + Name: "equalFold", + MatcherName: "m", + DocTags: []string{ + "performance", + "experimental", + }, + DocSummary: "Detects unoptimal strings/bytes case-insensitive comparison", + DocBefore: "strings.ToLower(x) == strings.ToLower(y)", + DocAfter: "strings.EqualFold(x, y)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 559, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 560, Value: "strings.ToLower($x) == $y"}, + ir.PatternString{Line: 561, Value: "strings.ToLower($x) == strings.ToLower($y)"}, + ir.PatternString{Line: 562, Value: "$x == strings.ToLower($y)"}, + ir.PatternString{Line: 563, Value: "strings.ToUpper($x) == $y"}, + ir.PatternString{Line: 564, Value: "strings.ToUpper($x) == strings.ToUpper($y)"}, + ir.PatternString{Line: 565, Value: "$x == strings.ToUpper($y)"}, + }, + ReportTemplate: "consider replacing with strings.EqualFold($x, $y)", + SuggestTemplate: "strings.EqualFold($x, $y)]", + WhereExpr: ir.FilterExpr{ + Line: 566, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 566, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 566, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + ir.FilterExpr{Line: 566, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"}, + }, + }, + ir.FilterExpr{ + Line: 566, + Op: ir.FilterNeqOp, + Src: "m[\"x\"].Text != m[\"y\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 566, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"}, + ir.FilterExpr{Line: 566, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 571, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 572, Value: "strings.ToLower($x) != $y"}, + ir.PatternString{Line: 573, Value: "strings.ToLower($x) != strings.ToLower($y)"}, + ir.PatternString{Line: 574, Value: "$x != strings.ToLower($y)"}, + ir.PatternString{Line: 575, Value: "strings.ToUpper($x) != $y"}, + ir.PatternString{Line: 576, Value: "strings.ToUpper($x) != strings.ToUpper($y)"}, + ir.PatternString{Line: 577, Value: "$x != strings.ToUpper($y)"}, + }, + ReportTemplate: "consider replacing with !strings.EqualFold($x, $y)", + SuggestTemplate: "!strings.EqualFold($x, $y)]", + WhereExpr: ir.FilterExpr{ + Line: 578, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 578, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 578, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + ir.FilterExpr{Line: 578, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"}, + }, + }, + ir.FilterExpr{ + Line: 578, + Op: ir.FilterNeqOp, + Src: "m[\"x\"].Text != m[\"y\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 578, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"}, + ir.FilterExpr{Line: 578, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"}, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 583, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 584, Value: "bytes.Equal(bytes.ToLower($x), $y)"}, + ir.PatternString{Line: 585, Value: "bytes.Equal(bytes.ToLower($x), bytes.ToLower($y))"}, + ir.PatternString{Line: 586, Value: "bytes.Equal($x, bytes.ToLower($y))"}, + ir.PatternString{Line: 587, Value: "bytes.Equal(bytes.ToUpper($x), $y)"}, + ir.PatternString{Line: 588, Value: "bytes.Equal(bytes.ToUpper($x), bytes.ToUpper($y))"}, + ir.PatternString{Line: 589, Value: "bytes.Equal($x, bytes.ToUpper($y))"}, + }, + ReportTemplate: "consider replacing with bytes.EqualFold($x, $y)", + SuggestTemplate: "bytes.EqualFold($x, $y)]", + WhereExpr: ir.FilterExpr{ + Line: 590, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure && m[\"x\"].Text != m[\"y\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 590, + Op: ir.FilterAndOp, + Src: "m[\"x\"].Pure && m[\"y\"].Pure", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 590, Op: ir.FilterVarPureOp, Src: "m[\"x\"].Pure", Value: "x"}, + ir.FilterExpr{Line: 590, Op: ir.FilterVarPureOp, Src: "m[\"y\"].Pure", Value: "y"}, + }, + }, + ir.FilterExpr{ + Line: 590, + Op: ir.FilterNeqOp, + Src: "m[\"x\"].Text != m[\"y\"].Text", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 590, Op: ir.FilterVarTextOp, Src: "m[\"x\"].Text", Value: "x"}, + ir.FilterExpr{Line: 590, Op: ir.FilterVarTextOp, Src: "m[\"y\"].Text", Value: "y"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 599, + Name: "argOrder", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + }, + DocSummary: "Detects suspicious arguments order", + DocBefore: "strings.HasPrefix(\"#\", userpass)", + DocAfter: "strings.HasPrefix(userpass, \"#\")", + Rules: []ir.Rule{ + ir.Rule{ + Line: 600, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 601, Value: "strings.HasPrefix($lit, $s)"}, + ir.PatternString{Line: 602, Value: "bytes.HasPrefix($lit, $s)"}, + ir.PatternString{Line: 603, Value: "strings.HasSuffix($lit, $s)"}, + ir.PatternString{Line: 604, Value: "bytes.HasSuffix($lit, $s)"}, + ir.PatternString{Line: 605, Value: "strings.Contains($lit, $s)"}, + ir.PatternString{Line: 606, Value: "bytes.Contains($lit, $s)"}, + ir.PatternString{Line: 607, Value: "strings.TrimPrefix($lit, $s)"}, + ir.PatternString{Line: 608, Value: "bytes.TrimPrefix($lit, $s)"}, + ir.PatternString{Line: 609, Value: "strings.TrimSuffix($lit, $s)"}, + ir.PatternString{Line: 610, Value: "bytes.TrimSuffix($lit, $s)"}, + ir.PatternString{Line: 611, Value: "strings.Split($lit, $s)"}, + ir.PatternString{Line: 612, Value: "bytes.Split($lit, $s)"}, + }, + ReportTemplate: "$lit and $s arguments order looks reversed", + WhereExpr: ir.FilterExpr{ + Line: 613, + Op: ir.FilterAndOp, + Src: "(m[\"lit\"].Const || m[\"lit\"].ConstSlice) &&\n\t!(m[\"s\"].Const || m[\"s\"].ConstSlice) &&\n\t!m[\"lit\"].Node.Is(`Ident`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 613, + Op: ir.FilterAndOp, + Src: "(m[\"lit\"].Const || m[\"lit\"].ConstSlice) &&\n\t!(m[\"s\"].Const || m[\"s\"].ConstSlice)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 613, + Op: ir.FilterOrOp, + Src: "(m[\"lit\"].Const || m[\"lit\"].ConstSlice)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 613, + Op: ir.FilterVarConstOp, + Src: "m[\"lit\"].Const", + Value: "lit", + }, + ir.FilterExpr{ + Line: 613, + Op: ir.FilterVarConstSliceOp, + Src: "m[\"lit\"].ConstSlice", + Value: "lit", + }, + }, + }, + ir.FilterExpr{ + Line: 614, + Op: ir.FilterNotOp, + Src: "!(m[\"s\"].Const || m[\"s\"].ConstSlice)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 614, + Op: ir.FilterOrOp, + Src: "(m[\"s\"].Const || m[\"s\"].ConstSlice)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 614, + Op: ir.FilterVarConstOp, + Src: "m[\"s\"].Const", + Value: "s", + }, + ir.FilterExpr{ + Line: 614, + Op: ir.FilterVarConstSliceOp, + Src: "m[\"s\"].ConstSlice", + Value: "s", + }, + }, + }, + }, + }, + }, + }, + ir.FilterExpr{ + Line: 615, + Op: ir.FilterNotOp, + Src: "!m[\"lit\"].Node.Is(`Ident`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 615, + Op: ir.FilterVarNodeIsOp, + Src: "m[\"lit\"].Node.Is(`Ident`)", + Value: "lit", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 615, Op: ir.FilterStringOp, Src: "`Ident`", Value: "Ident"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 623, + Name: "stringConcatSimplify", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects string concat operations that can be simplified", + DocBefore: "strings.Join([]string{x, y}, \"_\")", + DocAfter: "x + \"_\" + y", + Rules: []ir.Rule{ + ir.Rule{ + Line: 624, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 624, Value: "strings.Join([]string{$x, $y}, \"\")"}, + }, + ReportTemplate: "suggestion: $x + $y", + SuggestTemplate: "$x + $y", + }, + ir.Rule{ + Line: 625, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 625, Value: "strings.Join([]string{$x, $y, $z}, \"\")"}, + }, + ReportTemplate: "suggestion: $x + $y + $z", + SuggestTemplate: "$x + $y + $z", + }, + ir.Rule{ + Line: 626, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 626, Value: "strings.Join([]string{$x, $y}, $glue)"}, + }, + ReportTemplate: "suggestion: $x + $glue + $y", + SuggestTemplate: "$x + $glue + $y", + }, + }, + }, + ir.RuleGroup{ + Line: 633, + Name: "timeExprSimplify", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects manual conversion to milli- or microseconds", + DocBefore: "t.Unix() / 1000", + DocAfter: "t.UnixMilli()", + Rules: []ir.Rule{ + ir.Rule{ + Line: 634, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 634, Value: "$t.Unix() / 1000"}, + }, + ReportTemplate: "use $t.UnixMilli() instead of $$", + SuggestTemplate: "$t.UnixMilli()", + WhereExpr: ir.FilterExpr{ + Line: 635, + Op: ir.FilterAndOp, + Src: "m.GoVersion().GreaterEqThan(\"1.17\") &&\n\t(m[\"t\"].Type.Is(`time.Time`) || m[\"t\"].Type.Is(`*time.Time`))", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 635, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.17\")", + Value: "1.17", + }, + ir.FilterExpr{ + Line: 636, + Op: ir.FilterOrOp, + Src: "(m[\"t\"].Type.Is(`time.Time`) || m[\"t\"].Type.Is(`*time.Time`))", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 636, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"t\"].Type.Is(`time.Time`)", + Value: "t", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 636, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}, + }, + }, + ir.FilterExpr{ + Line: 636, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"t\"].Type.Is(`*time.Time`)", + Value: "t", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 636, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}, + }, + }, + }, + }, + }, + }, + }, + ir.Rule{ + Line: 640, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 640, Value: "$t.UnixNano() * 1000"}, + }, + ReportTemplate: "use $t.UnixMicro() instead of $$", + SuggestTemplate: "$t.UnixMicro()", + WhereExpr: ir.FilterExpr{ + Line: 641, + Op: ir.FilterAndOp, + Src: "m.GoVersion().GreaterEqThan(\"1.17\") &&\n\t(m[\"t\"].Type.Is(`time.Time`) || m[\"t\"].Type.Is(`*time.Time`))", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 641, + Op: ir.FilterGoVersionGreaterEqThanOp, + Src: "m.GoVersion().GreaterEqThan(\"1.17\")", + Value: "1.17", + }, + ir.FilterExpr{ + Line: 642, + Op: ir.FilterOrOp, + Src: "(m[\"t\"].Type.Is(`time.Time`) || m[\"t\"].Type.Is(`*time.Time`))", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 642, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"t\"].Type.Is(`time.Time`)", + Value: "t", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 642, Op: ir.FilterStringOp, Src: "`time.Time`", Value: "time.Time"}, + }, + }, + ir.FilterExpr{ + Line: 642, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"t\"].Type.Is(`*time.Time`)", + Value: "t", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 642, Op: ir.FilterStringOp, Src: "`*time.Time`", Value: "*time.Time"}, + }, + }, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 651, + Name: "exposedSyncMutex", + MatcherName: "m", + DocTags: []string{ + "style", + "experimental", + }, + DocSummary: "Detects exposed methods from sync.Mutex and sync.RWMutex", + DocBefore: "type Foo struct{ ...; sync.Mutex; ... }", + DocAfter: "type Foo struct{ ...; mu sync.Mutex; ... }", + Rules: []ir.Rule{ + ir.Rule{ + Line: 652, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 652, Value: "type $x struct { $*_; sync.Mutex; $*_ }"}, + }, + ReportTemplate: "don't embed sync.Mutex", + WhereExpr: ir.FilterExpr{ + Line: 653, + Op: ir.FilterVarTextMatchesOp, + Src: "m[\"x\"].Text.Matches(`^\\p{Lu}`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 653, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}, + }, + }, + }, + ir.Rule{ + Line: 656, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 656, Value: "type $x struct { $*_; *sync.Mutex; $*_ }"}, + }, + ReportTemplate: "don't embed *sync.Mutex", + WhereExpr: ir.FilterExpr{ + Line: 657, + Op: ir.FilterVarTextMatchesOp, + Src: "m[\"x\"].Text.Matches(`^\\p{Lu}`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 657, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}, + }, + }, + }, + ir.Rule{ + Line: 660, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 660, Value: "type $x struct { $*_; sync.RWMutex; $*_ }"}, + }, + ReportTemplate: "don't embed sync.RWMutex", + WhereExpr: ir.FilterExpr{ + Line: 661, + Op: ir.FilterVarTextMatchesOp, + Src: "m[\"x\"].Text.Matches(`^\\p{Lu}`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 661, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}, + }, + }, + }, + ir.Rule{ + Line: 664, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 664, Value: "type $x struct { $*_; *sync.RWMutex; $*_ }"}, + }, + ReportTemplate: "don't embed *sync.RWMutex", + WhereExpr: ir.FilterExpr{ + Line: 665, + Op: ir.FilterVarTextMatchesOp, + Src: "m[\"x\"].Text.Matches(`^\\p{Lu}`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 665, Op: ir.FilterStringOp, Src: "`^\\p{Lu}`", Value: "^\\p{Lu}"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 673, + Name: "badSorting", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects bad usage of sort package", + DocBefore: "xs = sort.StringSlice(xs)", + DocAfter: "sort.Strings(xs)", + Rules: []ir.Rule{ + ir.Rule{ + Line: 674, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 674, Value: "$x = sort.IntSlice($x)"}, + }, + ReportTemplate: "suspicious sort.IntSlice usage, maybe sort.Ints was intended?", + SuggestTemplate: "sort.Ints($x)", + WhereExpr: ir.FilterExpr{ + Line: 675, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`[]int`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 675, Op: ir.FilterStringOp, Src: "`[]int`", Value: "[]int"}, + }, + }, + }, + ir.Rule{ + Line: 679, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 679, Value: "$x = sort.Float64Slice($x)"}, + }, + ReportTemplate: "suspicious sort.Float64s usage, maybe sort.Float64s was intended?", + SuggestTemplate: "sort.Float64s($x)", + WhereExpr: ir.FilterExpr{ + Line: 680, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`[]float64`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 680, Op: ir.FilterStringOp, Src: "`[]float64`", Value: "[]float64"}, + }, + }, + }, + ir.Rule{ + Line: 684, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 684, Value: "$x = sort.StringSlice($x)"}, + }, + ReportTemplate: "suspicious sort.StringSlice usage, maybe sort.Strings was intended?", + SuggestTemplate: "sort.Strings($x)", + WhereExpr: ir.FilterExpr{ + Line: 685, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"x\"].Type.Is(`[]string`)", + Value: "x", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 685, Op: ir.FilterStringOp, Src: "`[]string`", Value: "[]string"}, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 694, + Name: "externalErrorReassign", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects suspicious reassigment of error from another package", + DocBefore: "io.EOF = nil", + DocAfter: "/* don't do it */", + Rules: []ir.Rule{ + ir.Rule{ + Line: 695, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 695, Value: "$pkg.$err = $x"}, + }, + ReportTemplate: "suspicious reassigment of error from another package", + WhereExpr: ir.FilterExpr{ + Line: 696, + Op: ir.FilterAndOp, + Src: "m[\"err\"].Type.Is(`error`) && m[\"pkg\"].Object.Is(`PkgName`)", + Args: []ir.FilterExpr{ + ir.FilterExpr{ + Line: 696, + Op: ir.FilterVarTypeIsOp, + Src: "m[\"err\"].Type.Is(`error`)", + Value: "err", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 696, Op: ir.FilterStringOp, Src: "`error`", Value: "error"}, + }, + }, + ir.FilterExpr{ + Line: 696, + Op: ir.FilterVarObjectIsOp, + Src: "m[\"pkg\"].Object.Is(`PkgName`)", + Value: "pkg", + Args: []ir.FilterExpr{ + ir.FilterExpr{Line: 696, Op: ir.FilterStringOp, Src: "`PkgName`", Value: "PkgName"}, + }, + }, + }, + }, + }, + }, + }, + ir.RuleGroup{ + Line: 704, + Name: "emptyDecl", + MatcherName: "m", + DocTags: []string{ + "diagnostic", + "experimental", + }, + DocSummary: "Detects suspicious empty declarations blocks", + DocBefore: "var()", + DocAfter: "/* nothing */", + Rules: []ir.Rule{ + ir.Rule{ + Line: 705, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 705, Value: "var()"}, + }, + ReportTemplate: "empty var() block", + }, + ir.Rule{ + Line: 706, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 706, Value: "const()"}, + }, + ReportTemplate: "empty const() block", + }, + ir.Rule{ + Line: 707, + SyntaxPatterns: []ir.PatternString{ + ir.PatternString{Line: 707, Value: "type()"}, + }, + ReportTemplate: "empty type() block", + }, + }, + }, + }, +} + diff --git a/vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go deleted file mode 100644 index a08ef0a5c..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/sloppyLen_checker.go +++ /dev/null @@ -1,72 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/astfmt" -) - -func init() { - var info linter.CheckerInfo - info.Name = "sloppyLen" - info.Tags = []string{"style"} - info.Summary = "Detects usage of `len` when result is obvious or doesn't make sense" - info.Before = ` -len(arr) >= 0 // Sloppy -len(arr) <= 0 // Sloppy -len(arr) < 0 // Doesn't make sense at all` - info.After = ` -len(arr) > 0 -len(arr) == 0` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&sloppyLenChecker{ctx: ctx}), nil - }) -} - -type sloppyLenChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *sloppyLenChecker) VisitExpr(x ast.Expr) { - expr, ok := x.(*ast.BinaryExpr) - if !ok { - return - } - - if expr.Op == token.LSS || expr.Op == token.GEQ || expr.Op == token.LEQ { - if c.isLenCall(expr.X) && c.isZero(expr.Y) { - c.warn(expr) - } - } -} - -func (c *sloppyLenChecker) isLenCall(x ast.Expr) bool { - call, ok := x.(*ast.CallExpr) - return ok && qualifiedName(call.Fun) == "len" && len(call.Args) == 1 -} - -func (c *sloppyLenChecker) isZero(x ast.Expr) bool { - value, ok := x.(*ast.BasicLit) - return ok && value.Value == "0" -} - -func (c *sloppyLenChecker) warn(cause *ast.BinaryExpr) { - info := "" - switch cause.Op { - case token.LSS: - info = "is always false" - case token.GEQ: - info = "is always true" - case token.LEQ: - expr := astcopy.BinaryExpr(cause) - expr.Op = token.EQL - info = astfmt.Sprintf("can be %s", expr) - } - c.ctx.Warn(cause, "%s %s", cause, info) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go b/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go index 243925368..554197768 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/sloppyTypeAssert_checker.go @@ -12,7 +12,7 @@ import ( func init() { var info linter.CheckerInfo info.Name = "sloppyTypeAssert" - info.Tags = []string{"diagnostic", "experimental"} + info.Tags = []string{"diagnostic"} info.Summary = "Detects redundant type assertions" info.Before = ` func f(r io.Reader) interface{} { @@ -48,28 +48,8 @@ func (c *sloppyTypeAssertChecker) VisitExpr(expr ast.Expr) { c.warnIdentical(expr) return } - - toIface, ok := toType.Underlying().(*types.Interface) - if !ok { - return - } - - switch { - case toIface.Empty(): - c.warnEmpty(expr) - case types.Implements(fromType, toIface): - c.warnImplements(expr, assert.X) - } } func (c *sloppyTypeAssertChecker) warnIdentical(cause ast.Expr) { c.ctx.Warn(cause, "type assertion from/to types are identical") } - -func (c *sloppyTypeAssertChecker) warnEmpty(cause ast.Expr) { - c.ctx.Warn(cause, "type assertion to interface{} may be redundant") -} - -func (c *sloppyTypeAssertChecker) warnImplements(cause, val ast.Expr) { - c.ctx.Warn(cause, "type assertion may be redundant as %s always implements selected interface", val) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go b/vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go deleted file mode 100644 index bb9f16c07..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/stringXbytes_checker.go +++ /dev/null @@ -1,47 +0,0 @@ -package checkers - -import ( - "go/ast" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/typep" -) - -func init() { - var info linter.CheckerInfo - info.Name = "stringXbytes" - info.Tags = []string{"style"} - info.Summary = "Detects redundant conversions between string and []byte" - info.Before = `copy(b, []byte(s))` - info.After = `copy(b, s)` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&stringXbytes{ctx: ctx}), nil - }) -} - -type stringXbytes struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *stringXbytes) VisitExpr(expr ast.Expr) { - x, ok := expr.(*ast.CallExpr) - if !ok || qualifiedName(x.Fun) != "copy" || len(x.Args) != 2 { - return - } - - src := x.Args[1] - - byteCast, ok := src.(*ast.CallExpr) - if ok && typep.IsTypeExpr(c.ctx.TypesInfo, byteCast.Fun) && - typep.HasStringProp(c.ctx.TypeOf(byteCast.Args[0])) { - - c.warn(byteCast, byteCast.Args[0]) - } -} - -func (c *stringXbytes) warn(cause *ast.CallExpr, suggestion ast.Expr) { - c.ctx.Warn(cause, "can simplify `%s` to `%s`", cause, suggestion) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go b/vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go deleted file mode 100644 index 0501a0ba1..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/switchTrue_checker.go +++ /dev/null @@ -1,49 +0,0 @@ -package checkers - -import ( - "go/ast" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" -) - -func init() { - var info linter.CheckerInfo - info.Name = "switchTrue" - info.Tags = []string{"style"} - info.Summary = "Detects switch-over-bool statements that use explicit `true` tag value" - info.Before = ` -switch true { -case x > y: -}` - info.After = ` -switch { -case x > y: -}` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForStmt(&switchTrueChecker{ctx: ctx}), nil - }) -} - -type switchTrueChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *switchTrueChecker) VisitStmt(stmt ast.Stmt) { - if stmt, ok := stmt.(*ast.SwitchStmt); ok { - if qualifiedName(stmt.Tag) == "true" { - c.warn(stmt) - } - } -} - -func (c *switchTrueChecker) warn(cause *ast.SwitchStmt) { - if cause.Init == nil { - c.ctx.Warn(cause, "replace 'switch true {}' with 'switch {}'") - } else { - c.ctx.Warn(cause, "replace 'switch %s; true {}' with 'switch %s; {}'", - cause.Init, cause.Init) - } -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go b/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go index a3f02e14c..cd8e04337 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/typeUnparen_checker.go @@ -4,11 +4,9 @@ import ( "go/ast" "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/checkers/internal/lintutil" "github.com/go-critic/go-critic/framework/linter" "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/astp" - "golang.org/x/tools/go/ast/astutil" + "github.com/go-toolsmith/astequal" ) func init() { @@ -29,58 +27,69 @@ type typeUnparenChecker struct { ctx *linter.CheckerContext } -func (c *typeUnparenChecker) VisitTypeExpr(x ast.Expr) { - switch x := x.(type) { +func (c *typeUnparenChecker) VisitTypeExpr(e ast.Expr) { + switch e := e.(type) { case *ast.ParenExpr: - switch x.X.(type) { + switch e.X.(type) { case *ast.StructType: - c.ctx.Warn(x, "could simplify (struct{...}) to struct{...}") + c.ctx.Warn(e, "could simplify (struct{...}) to struct{...}") case *ast.InterfaceType: - c.ctx.Warn(x, "could simplify (interface{...}) to interface{...}") + c.ctx.Warn(e, "could simplify (interface{...}) to interface{...}") default: - c.warn(x, c.unparenExpr(astcopy.Expr(x))) + c.checkType(e) } - default: - c.checkTypeExpr(x) - } -} - -func (c *typeUnparenChecker) checkTypeExpr(x ast.Expr) { - switch x := x.(type) { - case *ast.ArrayType: - // Arrays require extra care: we don't want to unparen - // length expression as they are not type expressions. - if !c.hasParens(x.Elt) { - return - } - noParens := astcopy.ArrayType(x) - noParens.Elt = c.unparenExpr(noParens.Elt) - c.warn(x, noParens) case *ast.StructType, *ast.InterfaceType: // Only nested fields are to be reported. default: - if !c.hasParens(x) { - return - } - c.warn(x, c.unparenExpr(astcopy.Expr(x))) + c.checkType(e) } } -func (c *typeUnparenChecker) hasParens(x ast.Expr) bool { - return lintutil.ContainsNode(x, astp.IsParenExpr) +func (c *typeUnparenChecker) checkType(e ast.Expr) { + noParens := c.removeRedundantParens(astcopy.Expr(e)) + if !astequal.Expr(e, noParens) { + c.warn(e, noParens) + } + c.SkipChilds = true } -func (c *typeUnparenChecker) unparenExpr(x ast.Expr) ast.Expr { - // Replace every paren expr with expression it encloses. - return astutil.Apply(x, nil, func(cur *astutil.Cursor) bool { - if paren, ok := cur.Node().(*ast.ParenExpr); ok { - cur.Replace(paren.X) +func (c *typeUnparenChecker) removeRedundantParens(e ast.Expr) ast.Expr { + switch e := e.(type) { + case *ast.ParenExpr: + return c.removeRedundantParens(e.X) + case *ast.ArrayType: + e.Elt = c.removeRedundantParens(e.Elt) + case *ast.StarExpr: + e.X = c.removeRedundantParens(e.X) + case *ast.TypeAssertExpr: + e.Type = c.removeRedundantParens(e.Type) + case *ast.FuncType: + for _, field := range e.Params.List { + field.Type = c.removeRedundantParens(field.Type) } - return true - }).(ast.Expr) + if e.Results != nil { + for _, field := range e.Results.List { + field.Type = c.removeRedundantParens(field.Type) + } + } + case *ast.MapType: + e.Key = c.removeRedundantParens(e.Key) + e.Value = c.removeRedundantParens(e.Value) + case *ast.ChanType: + if valueWithParens, ok := e.Value.(*ast.ParenExpr); ok { + if nestedChan, ok := valueWithParens.X.(*ast.ChanType); ok { + const anyDir = ast.SEND | ast.RECV + if nestedChan.Dir != anyDir || e.Dir != anyDir { + valueWithParens.X = c.removeRedundantParens(valueWithParens.X) + return e + } + } + } + e.Value = c.removeRedundantParens(e.Value) + } + return e } func (c *typeUnparenChecker) warn(cause, noParens ast.Expr) { - c.SkipChilds = true c.ctx.Warn(cause, "could simplify %s to %s", cause, noParens) } diff --git a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go index 72807ddbf..6cbdfdfd0 100644 --- a/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go +++ b/vendor/github.com/go-critic/go-critic/checkers/unnecessaryBlock_checker.go @@ -6,6 +6,7 @@ import ( "github.com/go-critic/go-critic/checkers/internal/astwalk" "github.com/go-critic/go-critic/framework/linter" + "github.com/go-toolsmith/astp" ) func init() { @@ -32,12 +33,19 @@ type unnecessaryBlockChecker struct { ctx *linter.CheckerContext } -func (c *unnecessaryBlockChecker) VisitStmtList(statements []ast.Stmt) { +func (c *unnecessaryBlockChecker) VisitStmtList(x ast.Node, statements []ast.Stmt) { // Using StmtListVisitor instead of StmtVisitor makes it easier to avoid // false positives on IfStmt, RangeStmt, ForStmt and alike. // We only inspect BlockStmt inside statement lists, so this method is not // called for IfStmt itself, for example. + if (astp.IsCaseClause(x) || astp.IsCommClause(x)) && len(statements) == 1 { + if _, ok := statements[0].(*ast.BlockStmt); ok { + c.ctx.Warn(statements[0], "case statement doesn't require a block statement") + return + } + } + for _, stmt := range statements { stmt, ok := stmt.(*ast.BlockStmt) if ok && !c.hasDefinitions(stmt) { diff --git a/vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go b/vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go deleted file mode 100644 index 26a4de061..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/unslice_checker.go +++ /dev/null @@ -1,59 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/types" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astequal" -) - -func init() { - var info linter.CheckerInfo - info.Name = "unslice" - info.Tags = []string{"style"} - info.Summary = "Detects slice expressions that can be simplified to sliced expression itself" - info.Before = ` -f(s[:]) // s is string -copy(b[:], values...) // b is []byte` - info.After = ` -f(s) -copy(b, values...)` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForExpr(&unsliceChecker{ctx: ctx}), nil - }) -} - -type unsliceChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *unsliceChecker) VisitExpr(expr ast.Expr) { - unsliced := c.unslice(expr) - if !astequal.Expr(expr, unsliced) { - c.warn(expr, unsliced) - c.SkipChilds = true - } -} - -func (c *unsliceChecker) unslice(expr ast.Expr) ast.Expr { - slice, ok := expr.(*ast.SliceExpr) - if !ok || slice.Low != nil || slice.High != nil { - // No need to worry about 3-index slicing, - // because it's only permitted if expr.High is not nil. - return expr - } - switch c.ctx.TypeOf(slice.X).(type) { - case *types.Slice, *types.Basic: - // Basic kind catches strings, Slice cathes everything else. - return c.unslice(slice.X) - } - return expr -} - -func (c *unsliceChecker) warn(cause, unsliced ast.Expr) { - c.ctx.Warn(cause, "could simplify %s to %s", cause, unsliced) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go b/vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go deleted file mode 100644 index d03e11223..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/valSwap_checker.go +++ /dev/null @@ -1,64 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" - "github.com/go-toolsmith/astequal" -) - -func init() { - var info linter.CheckerInfo - info.Name = "valSwap" - info.Tags = []string{"style"} - info.Summary = "Detects value swapping code that are not using parallel assignment" - info.Before = ` -tmp := *x -*x = *y -*y = tmp` - info.After = `*x, *y = *y, *x` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForStmtList(&valSwapChecker{ctx: ctx}), nil - }) -} - -type valSwapChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *valSwapChecker) VisitStmtList(list []ast.Stmt) { - for len(list) >= 3 { - tmpAssign := astcast.ToAssignStmt(list[0]) - assignX := astcast.ToAssignStmt(list[1]) - assignY := astcast.ToAssignStmt(list[2]) - - cond := c.isSimpleAssign(tmpAssign) && - c.isSimpleAssign(assignX) && - c.isSimpleAssign(assignY) && - assignX.Tok == token.ASSIGN && - assignY.Tok == token.ASSIGN && - astequal.Expr(assignX.Lhs[0], tmpAssign.Rhs[0]) && - astequal.Expr(assignX.Rhs[0], assignY.Lhs[0]) && - astequal.Expr(assignY.Rhs[0], tmpAssign.Lhs[0]) - if cond { - c.warn(tmpAssign, assignX.Lhs[0], assignY.Lhs[0]) - list = list[3:] - } else { - list = list[1:] - } - } -} - -func (c *valSwapChecker) isSimpleAssign(x *ast.AssignStmt) bool { - return len(x.Lhs) == 1 && len(x.Rhs) == 1 -} - -func (c *valSwapChecker) warn(cause, x, y ast.Node) { - c.ctx.Warn(cause, "can re-write as `%s, %s = %s, %s`", - x, y, y, x) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go b/vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go deleted file mode 100644 index d474989d0..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/wrapperFunc_checker.go +++ /dev/null @@ -1,229 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - "go/types" - "strings" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcast" -) - -func init() { - var info linter.CheckerInfo - info.Name = "wrapperFunc" - info.Tags = []string{"style"} - info.Summary = "Detects function calls that can be replaced with convenience wrappers" - info.Before = `wg.Add(-1)` - info.After = `wg.Done()` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - type arg struct { - index int - value string - } - type pattern struct { - pkg string - typ string // Only for typ patterns - args []arg - suggestion string - } - type matcher struct { - pkgPatterns []pattern - typPatterns []pattern - } - - typPatterns := map[string][]arg{ - "sync.WaitGroup.Add => WaitGroup.Done": { - {0, "-1"}, - }, - - "bytes.Buffer.Truncate => Buffer.Reset": { - {0, "0"}, - }, - } - - pkgPatterns := map[string][]arg{ - "http.HandlerFunc => http.NotFoundHandler": { - {0, "http.NotFound"}, - }, - - "strings.SplitN => strings.Split": { - {2, "-1"}, - }, - "strings.Replace => strings.ReplaceAll": { - {3, "-1"}, - }, - "strings.TrimFunc => strings.TrimSpace": { - {1, "unicode.IsSpace"}, - }, - "strings.Map => strings.ToTitle": { - {0, "unicode.ToTitle"}, - }, - - "bytes.SplitN => bytes.Split": { - {2, "-1"}, - }, - "bytes.Replace => bytes.ReplaceAll": { - {3, "-1"}, - }, - "bytes.TrimFunc => bytes.TrimSpace": { - {1, "unicode.IsSpace"}, - }, - "bytes.Map => bytes.ToUpper": { - {0, "unicode.ToUpper"}, - }, - "bytes.Map => bytes.ToLower": { - {0, "unicode.ToLower"}, - }, - "bytes.Map => bytes.ToTitle": { - {0, "unicode.ToTitle"}, - }, - - "draw.DrawMask => draw.Draw": { - {4, "nil"}, - {5, "image.Point{}"}, - }, - } - - matchers := make(map[string]*matcher) - - type templateKey struct { - from string - to string - } - decodeKey := func(key string) templateKey { - parts := strings.Split(key, " => ") - return templateKey{from: parts[0], to: parts[1]} - } - - // Expand pkg patterns. - for key, args := range pkgPatterns { - key := decodeKey(key) - parts := strings.Split(key.from, ".") - fn := parts[1] - m := matchers[fn] - if m == nil { - m = &matcher{} - matchers[fn] = m - } - m.pkgPatterns = append(m.pkgPatterns, pattern{ - pkg: parts[0], - args: args, - suggestion: key.to, - }) - } - // Expand typ patterns. - for key, args := range typPatterns { - key := decodeKey(key) - parts := strings.Split(key.from, ".") - fn := parts[2] - m := matchers[fn] - if m == nil { - m = &matcher{} - matchers[fn] = m - } - m.typPatterns = append(m.typPatterns, pattern{ - pkg: parts[0], - typ: parts[1], - args: args, - suggestion: key.to, - }) - } - - var valueOf func(x ast.Expr) string - valueOf = func(x ast.Expr) string { - switch x := x.(type) { - case *ast.Ident: - return x.Name - case *ast.SelectorExpr: - id, ok := x.X.(*ast.Ident) - if ok { - return id.Name + "." + x.Sel.Name - } - case *ast.BasicLit: - return x.Value - case *ast.UnaryExpr: - switch x.Op { - case token.SUB: - return "-" + valueOf(x.X) - case token.ADD: - return valueOf(x.X) - } - } - return "" - } - - findSuggestion := func(call *ast.CallExpr, pkg, typ string, patterns []pattern) string { - for _, pat := range patterns { - if pat.pkg != pkg || pat.typ != typ { - continue - } - for _, arg := range pat.args { - if arg.value == valueOf(call.Args[arg.index]) { - return pat.suggestion - } - } - } - return "" - } - - c := &wrapperFuncChecker{ctx: ctx} - c.findSuggestion = func(call *ast.CallExpr) string { - sel := astcast.ToSelectorExpr(call.Fun).Sel - if sel == nil { - return "" - } - x := astcast.ToSelectorExpr(call.Fun).X - - m := matchers[sel.Name] - if m == nil { - return "" - } - - if x, ok := x.(*ast.Ident); ok { - obj, ok := c.ctx.TypesInfo.ObjectOf(x).(*types.PkgName) - if ok { - return findSuggestion(call, obj.Name(), "", m.pkgPatterns) - } - } - - typ := c.ctx.TypeOf(x) - tn, ok := typ.(*types.Named) - if !ok { - return "" - } - return findSuggestion( - call, - tn.Obj().Pkg().Name(), - tn.Obj().Name(), - m.typPatterns) - } - - return astwalk.WalkerForExpr(c), nil - }) -} - -type wrapperFuncChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext - - findSuggestion func(*ast.CallExpr) string -} - -func (c *wrapperFuncChecker) VisitExpr(expr ast.Expr) { - call := astcast.ToCallExpr(expr) - if len(call.Args) == 0 { - return - } - - if suggest := c.findSuggestion(call); suggest != "" { - c.warn(call, suggest) - } -} - -func (c *wrapperFuncChecker) warn(cause ast.Node, suggest string) { - c.ctx.Warn(cause, "use %s method in `%s`", suggest, cause) -} diff --git a/vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go b/vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go deleted file mode 100644 index c533d143b..000000000 --- a/vendor/github.com/go-critic/go-critic/checkers/yodaStyleExpr_checker.go +++ /dev/null @@ -1,66 +0,0 @@ -package checkers - -import ( - "go/ast" - "go/token" - - "github.com/go-critic/go-critic/checkers/internal/astwalk" - "github.com/go-critic/go-critic/framework/linter" - "github.com/go-toolsmith/astcopy" - "github.com/go-toolsmith/astp" -) - -func init() { - var info linter.CheckerInfo - info.Name = "yodaStyleExpr" - info.Tags = []string{"style", "experimental"} - info.Summary = "Detects Yoda style expressions and suggests to replace them" - info.Before = `return nil != ptr` - info.After = `return ptr != nil` - - collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) { - return astwalk.WalkerForLocalExpr(&yodaStyleExprChecker{ctx: ctx}), nil - }) -} - -type yodaStyleExprChecker struct { - astwalk.WalkHandler - ctx *linter.CheckerContext -} - -func (c *yodaStyleExprChecker) VisitLocalExpr(expr ast.Expr) { - binexpr, ok := expr.(*ast.BinaryExpr) - if !ok { - return - } - switch binexpr.Op { - case token.EQL, token.NEQ, token.LSS, token.LEQ, token.GEQ, token.GTR: - if c.isConstExpr(binexpr.X) && !c.isConstExpr(binexpr.Y) { - c.warn(binexpr) - } - } -} - -func (c *yodaStyleExprChecker) isConstExpr(expr ast.Expr) bool { - return qualifiedName(expr) == "nil" || astp.IsBasicLit(expr) -} - -func (c *yodaStyleExprChecker) invert(expr *ast.BinaryExpr) { - expr.X, expr.Y = expr.Y, expr.X - switch expr.Op { - case token.LSS: - expr.Op = token.GEQ - case token.LEQ: - expr.Op = token.GTR - case token.GEQ: - expr.Op = token.LSS - case token.GTR: - expr.Op = token.LEQ - } -} - -func (c *yodaStyleExprChecker) warn(expr *ast.BinaryExpr) { - e := astcopy.BinaryExpr(expr) - c.invert(e) - c.ctx.Warn(expr, "consider to change order in expression to %s", e) -} diff --git a/vendor/github.com/go-critic/go-critic/framework/linter/go_version.go b/vendor/github.com/go-critic/go-critic/framework/linter/go_version.go new file mode 100644 index 000000000..61e5590f3 --- /dev/null +++ b/vendor/github.com/go-critic/go-critic/framework/linter/go_version.go @@ -0,0 +1,51 @@ +package linter + +import ( + "fmt" + "strconv" + "strings" +) + +type GoVersion struct { + Major int + Minor int +} + +// GreaterOrEqual performs $v >= $other operation. +// +// In other words, it reports whether $v version constraint can use +// a feature from the $other Go version. +// +// As a special case, Major=0 covers all versions. +func (v GoVersion) GreaterOrEqual(other GoVersion) bool { + if v.Major == 0 { + return true + } + if v.Major == other.Major { + return v.Minor >= other.Minor + } + return v.Major >= other.Major +} + +func parseGoVersion(version string) GoVersion { + version = strings.TrimPrefix(version, "go") + if version == "" { + return GoVersion{} + } + parts := strings.Split(version, ".") + if len(parts) != 2 { + panic(fmt.Sprintf("invalid Go version format: %s", version)) + } + major, err := strconv.Atoi(parts[0]) + if err != nil { + panic(fmt.Sprintf("invalid major version part: %s: %s", parts[0], err)) + } + minor, err := strconv.Atoi(parts[1]) + if err != nil { + panic(fmt.Sprintf("invalid minor version part: %s: %s", parts[1], err)) + } + return GoVersion{ + Major: major, + Minor: minor, + } +} diff --git a/vendor/github.com/go-critic/go-critic/framework/linter/lintpack.go b/vendor/github.com/go-critic/go-critic/framework/linter/lintpack.go index 5c8662c69..8e5bba728 100644 --- a/vendor/github.com/go-critic/go-critic/framework/linter/lintpack.go +++ b/vendor/github.com/go-critic/go-critic/framework/linter/lintpack.go @@ -87,6 +87,10 @@ type CheckerInfo struct { // Note is an optional caution message or advice. Note string + // EmbeddedRuleguard tells whether this checker is auto-generated + // from the embedded ruleguard rules. + EmbeddedRuleguard bool + // Collection establishes a checker-to-collection relationship. Collection *CheckerCollection } @@ -126,6 +130,14 @@ func (c *Checker) Check(f *ast.File) []Warning { return c.ctx.warnings } +// QuickFix is our analysis.TextEdit; we're using it here to avoid +// direct analysis package dependency for now. +type QuickFix struct { + From token.Pos + To token.Pos + Replacement []byte +} + // Warning represents issue that is found by checker. type Warning struct { // Node is an AST node that caused warning to trigger. @@ -134,6 +146,19 @@ type Warning struct { // Text is warning message without source location info. Text string + + // Suggestion is a quick fix for a given problem. + // QuickFix is analysis.TextEdit and can be used to + // construct an analysis.SuggestedFix object. + // + // For convenience, there is Warning.HasQuickFix() method + // that reports whether Suggestion has something meaningful. + Suggestion QuickFix +} + +// HasQuickFix reports whether this warning has a suggested fix. +func (warn Warning) HasQuickFix() bool { + return warn.Suggestion.Replacement != nil } // NewChecker returns initialized checker identified by an info. @@ -153,6 +178,9 @@ type Context struct { // Arch-dependent. SizesInfo types.Sizes + // GoVersion is a target Go version. + GoVersion GoVersion + // FileSet is a file set that was used during the program loading. FileSet *token.FileSet @@ -194,6 +222,19 @@ func NewContext(fset *token.FileSet, sizes types.Sizes) *Context { } } +// SetGoVersion adjust the target Go language version. +// +// The format is like "1.5", "1.8", etc. +// It's permitted to have "go" prefix (e.g. "go1.5"). +// +// Empty string (the default) means that we make no +// Go version assumptions and (like gocritic does) behave +// like all features are available. To make gocritic +// more conservative, the upper Go version level should be adjusted. +func (c *Context) SetGoVersion(version string) { + c.GoVersion = parseGoVersion(version) +} + // SetPackageInfo sets package-related metadata. // // Must be called for every package being checked. @@ -239,6 +280,15 @@ func (ctx *CheckerContext) Warn(node ast.Node, format string, args ...interface{ }) } +// WarnFixable emits a warning with a fix suggestion provided by the caller. +func (ctx *CheckerContext) WarnFixable(node ast.Node, fix QuickFix, format string, args ...interface{}) { + ctx.warnings = append(ctx.warnings, Warning{ + Text: ctx.printer.Sprintf(format, args...), + Node: node, + Suggestion: fix, + }) +} + // UnknownType is a special sentinel value that is returned from the CheckerContext.TypeOf // method instead of the nil type. var UnknownType types.Type = types.Typ[types.Invalid] diff --git a/vendor/github.com/go-toolsmith/astequal/astequal.go b/vendor/github.com/go-toolsmith/astequal/astequal.go index 6a32d7218..6253fb498 100644 --- a/vendor/github.com/go-toolsmith/astequal/astequal.go +++ b/vendor/github.com/go-toolsmith/astequal/astequal.go @@ -60,6 +60,14 @@ func astNodeEq(x, y ast.Node) bool { case ast.Decl: y, ok := y.(ast.Decl) return ok && astDeclEq(x, y) + + case *ast.Field: + y, ok := y.(*ast.Field) + return ok && astFieldEq(x, y) + case *ast.FieldList: + y, ok := y.(*ast.FieldList) + return ok && astFieldListEq(x, y) + default: return false } diff --git a/vendor/github.com/go-toolsmith/astequal/go.mod b/vendor/github.com/go-toolsmith/astequal/go.mod index 86fa40772..21231a1f1 100644 --- a/vendor/github.com/go-toolsmith/astequal/go.mod +++ b/vendor/github.com/go-toolsmith/astequal/go.mod @@ -1 +1,3 @@ module github.com/go-toolsmith/astequal + +require github.com/go-toolsmith/strparse v1.0.0 diff --git a/vendor/github.com/go-toolsmith/astequal/go.sum b/vendor/github.com/go-toolsmith/astequal/go.sum new file mode 100644 index 000000000..b1ce42adf --- /dev/null +++ b/vendor/github.com/go-toolsmith/astequal/go.sum @@ -0,0 +1,2 @@ +github.com/go-toolsmith/strparse v1.0.0 h1:Vcw78DnpCAKlM20kSbAyO4mPfJn/lyYA4BJUDxe2Jb4= +github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= diff --git a/vendor/github.com/golang/snappy/AUTHORS b/vendor/github.com/golang/snappy/AUTHORS index bcfa19520..203e84eba 100644 --- a/vendor/github.com/golang/snappy/AUTHORS +++ b/vendor/github.com/golang/snappy/AUTHORS @@ -8,8 +8,10 @@ # Please keep the list sorted. +Amazon.com, Inc Damian Gryski Google Inc. Jan Mercl <0xjnml@gmail.com> +Klaus Post Rodolfo Carvalho Sebastien Binet diff --git a/vendor/github.com/golang/snappy/CONTRIBUTORS b/vendor/github.com/golang/snappy/CONTRIBUTORS index 931ae3160..d9914732b 100644 --- a/vendor/github.com/golang/snappy/CONTRIBUTORS +++ b/vendor/github.com/golang/snappy/CONTRIBUTORS @@ -28,7 +28,9 @@ Damian Gryski Jan Mercl <0xjnml@gmail.com> +Jonathan Swinney Kai Backman +Klaus Post Marc-Antoine Ruel Nigel Tao Rob Pike diff --git a/vendor/github.com/golang/snappy/decode.go b/vendor/github.com/golang/snappy/decode.go index 72efb0353..f1e04b172 100644 --- a/vendor/github.com/golang/snappy/decode.go +++ b/vendor/github.com/golang/snappy/decode.go @@ -52,6 +52,8 @@ const ( // Otherwise, a newly allocated slice will be returned. // // The dst and src must not overlap. It is valid to pass a nil dst. +// +// Decode handles the Snappy block format, not the Snappy stream format. func Decode(dst, src []byte) ([]byte, error) { dLen, s, err := decodedLen(src) if err != nil { @@ -83,6 +85,8 @@ func NewReader(r io.Reader) *Reader { } // Reader is an io.Reader that can read Snappy-compressed bytes. +// +// Reader handles the Snappy stream format, not the Snappy block format. type Reader struct { r io.Reader err error diff --git a/vendor/github.com/golang/snappy/decode_arm64.s b/vendor/github.com/golang/snappy/decode_arm64.s new file mode 100644 index 000000000..7a3ead17e --- /dev/null +++ b/vendor/github.com/golang/snappy/decode_arm64.s @@ -0,0 +1,494 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The asm code generally follows the pure Go code in decode_other.go, except +// where marked with a "!!!". + +// func decode(dst, src []byte) int +// +// All local variables fit into registers. The non-zero stack size is only to +// spill registers and push args when issuing a CALL. The register allocation: +// - R2 scratch +// - R3 scratch +// - R4 length or x +// - R5 offset +// - R6 &src[s] +// - R7 &dst[d] +// + R8 dst_base +// + R9 dst_len +// + R10 dst_base + dst_len +// + R11 src_base +// + R12 src_len +// + R13 src_base + src_len +// - R14 used by doCopy +// - R15 used by doCopy +// +// The registers R8-R13 (marked with a "+") are set at the start of the +// function, and after a CALL returns, and are not otherwise modified. +// +// The d variable is implicitly R7 - R8, and len(dst)-d is R10 - R7. +// The s variable is implicitly R6 - R11, and len(src)-s is R13 - R6. +TEXT ·decode(SB), NOSPLIT, $56-56 + // Initialize R6, R7 and R8-R13. + MOVD dst_base+0(FP), R8 + MOVD dst_len+8(FP), R9 + MOVD R8, R7 + MOVD R8, R10 + ADD R9, R10, R10 + MOVD src_base+24(FP), R11 + MOVD src_len+32(FP), R12 + MOVD R11, R6 + MOVD R11, R13 + ADD R12, R13, R13 + +loop: + // for s < len(src) + CMP R13, R6 + BEQ end + + // R4 = uint32(src[s]) + // + // switch src[s] & 0x03 + MOVBU (R6), R4 + MOVW R4, R3 + ANDW $3, R3 + MOVW $1, R1 + CMPW R1, R3 + BGE tagCopy + + // ---------------------------------------- + // The code below handles literal tags. + + // case tagLiteral: + // x := uint32(src[s] >> 2) + // switch + MOVW $60, R1 + LSRW $2, R4, R4 + CMPW R4, R1 + BLS tagLit60Plus + + // case x < 60: + // s++ + ADD $1, R6, R6 + +doLit: + // This is the end of the inner "switch", when we have a literal tag. + // + // We assume that R4 == x and x fits in a uint32, where x is the variable + // used in the pure Go decode_other.go code. + + // length = int(x) + 1 + // + // Unlike the pure Go code, we don't need to check if length <= 0 because + // R4 can hold 64 bits, so the increment cannot overflow. + ADD $1, R4, R4 + + // Prepare to check if copying length bytes will run past the end of dst or + // src. + // + // R2 = len(dst) - d + // R3 = len(src) - s + MOVD R10, R2 + SUB R7, R2, R2 + MOVD R13, R3 + SUB R6, R3, R3 + + // !!! Try a faster technique for short (16 or fewer bytes) copies. + // + // if length > 16 || len(dst)-d < 16 || len(src)-s < 16 { + // goto callMemmove // Fall back on calling runtime·memmove. + // } + // + // The C++ snappy code calls this TryFastAppend. It also checks len(src)-s + // against 21 instead of 16, because it cannot assume that all of its input + // is contiguous in memory and so it needs to leave enough source bytes to + // read the next tag without refilling buffers, but Go's Decode assumes + // contiguousness (the src argument is a []byte). + CMP $16, R4 + BGT callMemmove + CMP $16, R2 + BLT callMemmove + CMP $16, R3 + BLT callMemmove + + // !!! Implement the copy from src to dst as a 16-byte load and store. + // (Decode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only length bytes, but that's + // OK. If the input is a valid Snappy encoding then subsequent iterations + // will fix up the overrun. Otherwise, Decode returns a nil []byte (and a + // non-nil error), so the overrun will be ignored. + // + // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + LDP 0(R6), (R14, R15) + STP (R14, R15), 0(R7) + + // d += length + // s += length + ADD R4, R7, R7 + ADD R4, R6, R6 + B loop + +callMemmove: + // if length > len(dst)-d || length > len(src)-s { etc } + CMP R2, R4 + BGT errCorrupt + CMP R3, R4 + BGT errCorrupt + + // copy(dst[d:], src[s:s+length]) + // + // This means calling runtime·memmove(&dst[d], &src[s], length), so we push + // R7, R6 and R4 as arguments. Coincidentally, we also need to spill those + // three registers to the stack, to save local variables across the CALL. + MOVD R7, 8(RSP) + MOVD R6, 16(RSP) + MOVD R4, 24(RSP) + MOVD R7, 32(RSP) + MOVD R6, 40(RSP) + MOVD R4, 48(RSP) + CALL runtime·memmove(SB) + + // Restore local variables: unspill registers from the stack and + // re-calculate R8-R13. + MOVD 32(RSP), R7 + MOVD 40(RSP), R6 + MOVD 48(RSP), R4 + MOVD dst_base+0(FP), R8 + MOVD dst_len+8(FP), R9 + MOVD R8, R10 + ADD R9, R10, R10 + MOVD src_base+24(FP), R11 + MOVD src_len+32(FP), R12 + MOVD R11, R13 + ADD R12, R13, R13 + + // d += length + // s += length + ADD R4, R7, R7 + ADD R4, R6, R6 + B loop + +tagLit60Plus: + // !!! This fragment does the + // + // s += x - 58; if uint(s) > uint(len(src)) { etc } + // + // checks. In the asm version, we code it once instead of once per switch case. + ADD R4, R6, R6 + SUB $58, R6, R6 + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // case x == 60: + MOVW $61, R1 + CMPW R1, R4 + BEQ tagLit61 + BGT tagLit62Plus + + // x = uint32(src[s-1]) + MOVBU -1(R6), R4 + B doLit + +tagLit61: + // case x == 61: + // x = uint32(src[s-2]) | uint32(src[s-1])<<8 + MOVHU -2(R6), R4 + B doLit + +tagLit62Plus: + CMPW $62, R4 + BHI tagLit63 + + // case x == 62: + // x = uint32(src[s-3]) | uint32(src[s-2])<<8 | uint32(src[s-1])<<16 + MOVHU -3(R6), R4 + MOVBU -1(R6), R3 + ORR R3<<16, R4 + B doLit + +tagLit63: + // case x == 63: + // x = uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24 + MOVWU -4(R6), R4 + B doLit + + // The code above handles literal tags. + // ---------------------------------------- + // The code below handles copy tags. + +tagCopy4: + // case tagCopy4: + // s += 5 + ADD $5, R6, R6 + + // if uint(s) > uint(len(src)) { etc } + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // length = 1 + int(src[s-5])>>2 + MOVD $1, R1 + ADD R4>>2, R1, R4 + + // offset = int(uint32(src[s-4]) | uint32(src[s-3])<<8 | uint32(src[s-2])<<16 | uint32(src[s-1])<<24) + MOVWU -4(R6), R5 + B doCopy + +tagCopy2: + // case tagCopy2: + // s += 3 + ADD $3, R6, R6 + + // if uint(s) > uint(len(src)) { etc } + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // length = 1 + int(src[s-3])>>2 + MOVD $1, R1 + ADD R4>>2, R1, R4 + + // offset = int(uint32(src[s-2]) | uint32(src[s-1])<<8) + MOVHU -2(R6), R5 + B doCopy + +tagCopy: + // We have a copy tag. We assume that: + // - R3 == src[s] & 0x03 + // - R4 == src[s] + CMP $2, R3 + BEQ tagCopy2 + BGT tagCopy4 + + // case tagCopy1: + // s += 2 + ADD $2, R6, R6 + + // if uint(s) > uint(len(src)) { etc } + MOVD R6, R3 + SUB R11, R3, R3 + CMP R12, R3 + BGT errCorrupt + + // offset = int(uint32(src[s-2])&0xe0<<3 | uint32(src[s-1])) + MOVD R4, R5 + AND $0xe0, R5 + MOVBU -1(R6), R3 + ORR R5<<3, R3, R5 + + // length = 4 + int(src[s-2])>>2&0x7 + MOVD $7, R1 + AND R4>>2, R1, R4 + ADD $4, R4, R4 + +doCopy: + // This is the end of the outer "switch", when we have a copy tag. + // + // We assume that: + // - R4 == length && R4 > 0 + // - R5 == offset + + // if offset <= 0 { etc } + MOVD $0, R1 + CMP R1, R5 + BLE errCorrupt + + // if d < offset { etc } + MOVD R7, R3 + SUB R8, R3, R3 + CMP R5, R3 + BLT errCorrupt + + // if length > len(dst)-d { etc } + MOVD R10, R3 + SUB R7, R3, R3 + CMP R3, R4 + BGT errCorrupt + + // forwardCopy(dst[d:d+length], dst[d-offset:]); d += length + // + // Set: + // - R14 = len(dst)-d + // - R15 = &dst[d-offset] + MOVD R10, R14 + SUB R7, R14, R14 + MOVD R7, R15 + SUB R5, R15, R15 + + // !!! Try a faster technique for short (16 or fewer bytes) forward copies. + // + // First, try using two 8-byte load/stores, similar to the doLit technique + // above. Even if dst[d:d+length] and dst[d-offset:] can overlap, this is + // still OK if offset >= 8. Note that this has to be two 8-byte load/stores + // and not one 16-byte load/store, and the first store has to be before the + // second load, due to the overlap if offset is in the range [8, 16). + // + // if length > 16 || offset < 8 || len(dst)-d < 16 { + // goto slowForwardCopy + // } + // copy 16 bytes + // d += length + CMP $16, R4 + BGT slowForwardCopy + CMP $8, R5 + BLT slowForwardCopy + CMP $16, R14 + BLT slowForwardCopy + MOVD 0(R15), R2 + MOVD R2, 0(R7) + MOVD 8(R15), R3 + MOVD R3, 8(R7) + ADD R4, R7, R7 + B loop + +slowForwardCopy: + // !!! If the forward copy is longer than 16 bytes, or if offset < 8, we + // can still try 8-byte load stores, provided we can overrun up to 10 extra + // bytes. As above, the overrun will be fixed up by subsequent iterations + // of the outermost loop. + // + // The C++ snappy code calls this technique IncrementalCopyFastPath. Its + // commentary says: + // + // ---- + // + // The main part of this loop is a simple copy of eight bytes at a time + // until we've copied (at least) the requested amount of bytes. However, + // if d and d-offset are less than eight bytes apart (indicating a + // repeating pattern of length < 8), we first need to expand the pattern in + // order to get the correct results. For instance, if the buffer looks like + // this, with the eight-byte and patterns marked as + // intervals: + // + // abxxxxxxxxxxxx + // [------] d-offset + // [------] d + // + // a single eight-byte copy from to will repeat the pattern + // once, after which we can move two bytes without moving : + // + // ababxxxxxxxxxx + // [------] d-offset + // [------] d + // + // and repeat the exercise until the two no longer overlap. + // + // This allows us to do very well in the special case of one single byte + // repeated many times, without taking a big hit for more general cases. + // + // The worst case of extra writing past the end of the match occurs when + // offset == 1 and length == 1; the last copy will read from byte positions + // [0..7] and write to [4..11], whereas it was only supposed to write to + // position 1. Thus, ten excess bytes. + // + // ---- + // + // That "10 byte overrun" worst case is confirmed by Go's + // TestSlowForwardCopyOverrun, which also tests the fixUpSlowForwardCopy + // and finishSlowForwardCopy algorithm. + // + // if length > len(dst)-d-10 { + // goto verySlowForwardCopy + // } + SUB $10, R14, R14 + CMP R14, R4 + BGT verySlowForwardCopy + +makeOffsetAtLeast8: + // !!! As above, expand the pattern so that offset >= 8 and we can use + // 8-byte load/stores. + // + // for offset < 8 { + // copy 8 bytes from dst[d-offset:] to dst[d:] + // length -= offset + // d += offset + // offset += offset + // // The two previous lines together means that d-offset, and therefore + // // R15, is unchanged. + // } + CMP $8, R5 + BGE fixUpSlowForwardCopy + MOVD (R15), R3 + MOVD R3, (R7) + SUB R5, R4, R4 + ADD R5, R7, R7 + ADD R5, R5, R5 + B makeOffsetAtLeast8 + +fixUpSlowForwardCopy: + // !!! Add length (which might be negative now) to d (implied by R7 being + // &dst[d]) so that d ends up at the right place when we jump back to the + // top of the loop. Before we do that, though, we save R7 to R2 so that, if + // length is positive, copying the remaining length bytes will write to the + // right place. + MOVD R7, R2 + ADD R4, R7, R7 + +finishSlowForwardCopy: + // !!! Repeat 8-byte load/stores until length <= 0. Ending with a negative + // length means that we overrun, but as above, that will be fixed up by + // subsequent iterations of the outermost loop. + MOVD $0, R1 + CMP R1, R4 + BLE loop + MOVD (R15), R3 + MOVD R3, (R2) + ADD $8, R15, R15 + ADD $8, R2, R2 + SUB $8, R4, R4 + B finishSlowForwardCopy + +verySlowForwardCopy: + // verySlowForwardCopy is a simple implementation of forward copy. In C + // parlance, this is a do/while loop instead of a while loop, since we know + // that length > 0. In Go syntax: + // + // for { + // dst[d] = dst[d - offset] + // d++ + // length-- + // if length == 0 { + // break + // } + // } + MOVB (R15), R3 + MOVB R3, (R7) + ADD $1, R15, R15 + ADD $1, R7, R7 + SUB $1, R4, R4 + CBNZ R4, verySlowForwardCopy + B loop + + // The code above handles copy tags. + // ---------------------------------------- + +end: + // This is the end of the "for s < len(src)". + // + // if d != len(dst) { etc } + CMP R10, R7 + BNE errCorrupt + + // return 0 + MOVD $0, ret+48(FP) + RET + +errCorrupt: + // return decodeErrCodeCorrupt + MOVD $1, R2 + MOVD R2, ret+48(FP) + RET diff --git a/vendor/github.com/golang/snappy/decode_amd64.go b/vendor/github.com/golang/snappy/decode_asm.go similarity index 93% rename from vendor/github.com/golang/snappy/decode_amd64.go rename to vendor/github.com/golang/snappy/decode_asm.go index fcd192b84..7082b3491 100644 --- a/vendor/github.com/golang/snappy/decode_amd64.go +++ b/vendor/github.com/golang/snappy/decode_asm.go @@ -5,6 +5,7 @@ // +build !appengine // +build gc // +build !noasm +// +build amd64 arm64 package snappy diff --git a/vendor/github.com/golang/snappy/decode_other.go b/vendor/github.com/golang/snappy/decode_other.go index 8c9f2049b..2f672be55 100644 --- a/vendor/github.com/golang/snappy/decode_other.go +++ b/vendor/github.com/golang/snappy/decode_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine !gc noasm +// +build !amd64,!arm64 appengine !gc noasm package snappy @@ -85,14 +85,28 @@ func decode(dst, src []byte) int { if offset <= 0 || d < offset || length > len(dst)-d { return decodeErrCodeCorrupt } - // Copy from an earlier sub-slice of dst to a later sub-slice. Unlike - // the built-in copy function, this byte-by-byte copy always runs + // Copy from an earlier sub-slice of dst to a later sub-slice. + // If no overlap, use the built-in copy: + if offset >= length { + copy(dst[d:d+length], dst[d-offset:]) + d += length + continue + } + + // Unlike the built-in copy function, this byte-by-byte copy always runs // forwards, even if the slices overlap. Conceptually, this is: // // d += forwardCopy(dst[d:d+length], dst[d-offset:]) - for end := d + length; d != end; d++ { - dst[d] = dst[d-offset] + // + // We align the slices into a and b and show the compiler they are the same size. + // This allows the loop to run without bounds checks. + a := dst[d : d+length] + b := dst[d-offset:] + b = b[:len(a)] + for i := range a { + a[i] = b[i] } + d += length } if d != len(dst) { return decodeErrCodeCorrupt diff --git a/vendor/github.com/golang/snappy/encode.go b/vendor/github.com/golang/snappy/encode.go index 8d393e904..7f2365707 100644 --- a/vendor/github.com/golang/snappy/encode.go +++ b/vendor/github.com/golang/snappy/encode.go @@ -15,6 +15,8 @@ import ( // Otherwise, a newly allocated slice will be returned. // // The dst and src must not overlap. It is valid to pass a nil dst. +// +// Encode handles the Snappy block format, not the Snappy stream format. func Encode(dst, src []byte) []byte { if n := MaxEncodedLen(len(src)); n < 0 { panic(ErrTooLarge) @@ -139,6 +141,8 @@ func NewBufferedWriter(w io.Writer) *Writer { } // Writer is an io.Writer that can write Snappy-compressed bytes. +// +// Writer handles the Snappy stream format, not the Snappy block format. type Writer struct { w io.Writer err error diff --git a/vendor/github.com/golang/snappy/encode_arm64.s b/vendor/github.com/golang/snappy/encode_arm64.s new file mode 100644 index 000000000..bf83667d7 --- /dev/null +++ b/vendor/github.com/golang/snappy/encode_arm64.s @@ -0,0 +1,722 @@ +// Copyright 2020 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build !appengine +// +build gc +// +build !noasm + +#include "textflag.h" + +// The asm code generally follows the pure Go code in encode_other.go, except +// where marked with a "!!!". + +// ---------------------------------------------------------------------------- + +// func emitLiteral(dst, lit []byte) int +// +// All local variables fit into registers. The register allocation: +// - R3 len(lit) +// - R4 n +// - R6 return value +// - R8 &dst[i] +// - R10 &lit[0] +// +// The 32 bytes of stack space is to call runtime·memmove. +// +// The unusual register allocation of local variables, such as R10 for the +// source pointer, matches the allocation used at the call site in encodeBlock, +// which makes it easier to manually inline this function. +TEXT ·emitLiteral(SB), NOSPLIT, $32-56 + MOVD dst_base+0(FP), R8 + MOVD lit_base+24(FP), R10 + MOVD lit_len+32(FP), R3 + MOVD R3, R6 + MOVW R3, R4 + SUBW $1, R4, R4 + + CMPW $60, R4 + BLT oneByte + CMPW $256, R4 + BLT twoBytes + +threeBytes: + MOVD $0xf4, R2 + MOVB R2, 0(R8) + MOVW R4, 1(R8) + ADD $3, R8, R8 + ADD $3, R6, R6 + B memmove + +twoBytes: + MOVD $0xf0, R2 + MOVB R2, 0(R8) + MOVB R4, 1(R8) + ADD $2, R8, R8 + ADD $2, R6, R6 + B memmove + +oneByte: + LSLW $2, R4, R4 + MOVB R4, 0(R8) + ADD $1, R8, R8 + ADD $1, R6, R6 + +memmove: + MOVD R6, ret+48(FP) + + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // R8, R10 and R3 as arguments. + MOVD R8, 8(RSP) + MOVD R10, 16(RSP) + MOVD R3, 24(RSP) + CALL runtime·memmove(SB) + RET + +// ---------------------------------------------------------------------------- + +// func emitCopy(dst []byte, offset, length int) int +// +// All local variables fit into registers. The register allocation: +// - R3 length +// - R7 &dst[0] +// - R8 &dst[i] +// - R11 offset +// +// The unusual register allocation of local variables, such as R11 for the +// offset, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·emitCopy(SB), NOSPLIT, $0-48 + MOVD dst_base+0(FP), R8 + MOVD R8, R7 + MOVD offset+24(FP), R11 + MOVD length+32(FP), R3 + +loop0: + // for length >= 68 { etc } + CMPW $68, R3 + BLT step1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVD $0xfe, R2 + MOVB R2, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUB $64, R3, R3 + B loop0 + +step1: + // if length > 64 { etc } + CMP $64, R3 + BLE step2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVD $0xee, R2 + MOVB R2, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUB $60, R3, R3 + +step2: + // if length >= 12 || offset >= 2048 { goto step3 } + CMP $12, R3 + BGE step3 + CMPW $2048, R11 + BGE step3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(R8) + LSRW $3, R11, R11 + AND $0xe0, R11, R11 + SUB $4, R3, R3 + LSLW $2, R3 + AND $0xff, R3, R3 + ORRW R3, R11, R11 + ORRW $1, R11, R11 + MOVB R11, 0(R8) + ADD $2, R8, R8 + + // Return the number of bytes written. + SUB R7, R8, R8 + MOVD R8, ret+40(FP) + RET + +step3: + // Emit the remaining copy, encoded as 3 bytes. + SUB $1, R3, R3 + AND $0xff, R3, R3 + LSLW $2, R3, R3 + ORRW $2, R3, R3 + MOVB R3, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + + // Return the number of bytes written. + SUB R7, R8, R8 + MOVD R8, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func extendMatch(src []byte, i, j int) int +// +// All local variables fit into registers. The register allocation: +// - R6 &src[0] +// - R7 &src[j] +// - R13 &src[len(src) - 8] +// - R14 &src[len(src)] +// - R15 &src[i] +// +// The unusual register allocation of local variables, such as R15 for a source +// pointer, matches the allocation used at the call site in encodeBlock, which +// makes it easier to manually inline this function. +TEXT ·extendMatch(SB), NOSPLIT, $0-48 + MOVD src_base+0(FP), R6 + MOVD src_len+8(FP), R14 + MOVD i+24(FP), R15 + MOVD j+32(FP), R7 + ADD R6, R14, R14 + ADD R6, R15, R15 + ADD R6, R7, R7 + MOVD R14, R13 + SUB $8, R13, R13 + +cmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMP R13, R7 + BHI cmp1 + MOVD (R15), R3 + MOVD (R7), R4 + CMP R4, R3 + BNE bsf + ADD $8, R15, R15 + ADD $8, R7, R7 + B cmp8 + +bsf: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. + // RBIT reverses the bit order, then CLZ counts the leading zeros, the + // combination of which finds the least significant bit which is set. + // The arm64 architecture is little-endian, and the shift by 3 converts + // a bit index to a byte index. + EOR R3, R4, R4 + RBIT R4, R4 + CLZ R4, R4 + ADD R4>>3, R7, R7 + + // Convert from &src[ret] to ret. + SUB R6, R7, R7 + MOVD R7, ret+40(FP) + RET + +cmp1: + // In src's tail, compare 1 byte at a time. + CMP R7, R14 + BLS extendMatchEnd + MOVB (R15), R3 + MOVB (R7), R4 + CMP R4, R3 + BNE extendMatchEnd + ADD $1, R15, R15 + ADD $1, R7, R7 + B cmp1 + +extendMatchEnd: + // Convert from &src[ret] to ret. + SUB R6, R7, R7 + MOVD R7, ret+40(FP) + RET + +// ---------------------------------------------------------------------------- + +// func encodeBlock(dst, src []byte) (d int) +// +// All local variables fit into registers, other than "var table". The register +// allocation: +// - R3 . . +// - R4 . . +// - R5 64 shift +// - R6 72 &src[0], tableSize +// - R7 80 &src[s] +// - R8 88 &dst[d] +// - R9 96 sLimit +// - R10 . &src[nextEmit] +// - R11 104 prevHash, currHash, nextHash, offset +// - R12 112 &src[base], skip +// - R13 . &src[nextS], &src[len(src) - 8] +// - R14 . len(src), bytesBetweenHashLookups, &src[len(src)], x +// - R15 120 candidate +// - R16 . hash constant, 0x1e35a7bd +// - R17 . &table +// - . 128 table +// +// The second column (64, 72, etc) is the stack offset to spill the registers +// when calling other functions. We could pack this slightly tighter, but it's +// simpler to have a dedicated spill map independent of the function called. +// +// "var table [maxTableSize]uint16" takes up 32768 bytes of stack space. An +// extra 64 bytes, to call other functions, and an extra 64 bytes, to spill +// local variables (registers) during calls gives 32768 + 64 + 64 = 32896. +TEXT ·encodeBlock(SB), 0, $32896-56 + MOVD dst_base+0(FP), R8 + MOVD src_base+24(FP), R7 + MOVD src_len+32(FP), R14 + + // shift, tableSize := uint32(32-8), 1<<8 + MOVD $24, R5 + MOVD $256, R6 + MOVW $0xa7bd, R16 + MOVKW $(0x1e35<<16), R16 + +calcShift: + // for ; tableSize < maxTableSize && tableSize < len(src); tableSize *= 2 { + // shift-- + // } + MOVD $16384, R2 + CMP R2, R6 + BGE varTable + CMP R14, R6 + BGE varTable + SUB $1, R5, R5 + LSL $1, R6, R6 + B calcShift + +varTable: + // var table [maxTableSize]uint16 + // + // In the asm code, unlike the Go code, we can zero-initialize only the + // first tableSize elements. Each uint16 element is 2 bytes and each + // iterations writes 64 bytes, so we can do only tableSize/32 writes + // instead of the 2048 writes that would zero-initialize all of table's + // 32768 bytes. This clear could overrun the first tableSize elements, but + // it won't overrun the allocated stack size. + ADD $128, RSP, R17 + MOVD R17, R4 + + // !!! R6 = &src[tableSize] + ADD R6<<1, R17, R6 + +memclr: + STP.P (ZR, ZR), 64(R4) + STP (ZR, ZR), -48(R4) + STP (ZR, ZR), -32(R4) + STP (ZR, ZR), -16(R4) + CMP R4, R6 + BHI memclr + + // !!! R6 = &src[0] + MOVD R7, R6 + + // sLimit := len(src) - inputMargin + MOVD R14, R9 + SUB $15, R9, R9 + + // !!! Pre-emptively spill R5, R6 and R9 to the stack. Their values don't + // change for the rest of the function. + MOVD R5, 64(RSP) + MOVD R6, 72(RSP) + MOVD R9, 96(RSP) + + // nextEmit := 0 + MOVD R6, R10 + + // s := 1 + ADD $1, R7, R7 + + // nextHash := hash(load32(src, s), shift) + MOVW 0(R7), R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + +outer: + // for { etc } + + // skip := 32 + MOVD $32, R12 + + // nextS := s + MOVD R7, R13 + + // candidate := 0 + MOVD $0, R15 + +inner0: + // for { etc } + + // s := nextS + MOVD R13, R7 + + // bytesBetweenHashLookups := skip >> 5 + MOVD R12, R14 + LSR $5, R14, R14 + + // nextS = s + bytesBetweenHashLookups + ADD R14, R13, R13 + + // skip += bytesBetweenHashLookups + ADD R14, R12, R12 + + // if nextS > sLimit { goto emitRemainder } + MOVD R13, R3 + SUB R6, R3, R3 + CMP R9, R3 + BHI emitRemainder + + // candidate = int(table[nextHash]) + MOVHU 0(R17)(R11<<1), R15 + + // table[nextHash] = uint16(s) + MOVD R7, R3 + SUB R6, R3, R3 + + MOVH R3, 0(R17)(R11<<1) + + // nextHash = hash(load32(src, nextS), shift) + MOVW 0(R13), R11 + MULW R16, R11 + LSRW R5, R11, R11 + + // if load32(src, s) != load32(src, candidate) { continue } break + MOVW 0(R7), R3 + MOVW (R6)(R15*1), R4 + CMPW R4, R3 + BNE inner0 + +fourByteMatch: + // As per the encode_other.go code: + // + // A 4-byte match has been found. We'll later see etc. + + // !!! Jump to a fast path for short (<= 16 byte) literals. See the comment + // on inputMargin in encode.go. + MOVD R7, R3 + SUB R10, R3, R3 + CMP $16, R3 + BLE emitLiteralFastPath + + // ---------------------------------------- + // Begin inline of the emitLiteral call. + // + // d += emitLiteral(dst[d:], src[nextEmit:s]) + + MOVW R3, R4 + SUBW $1, R4, R4 + + MOVW $60, R2 + CMPW R2, R4 + BLT inlineEmitLiteralOneByte + MOVW $256, R2 + CMPW R2, R4 + BLT inlineEmitLiteralTwoBytes + +inlineEmitLiteralThreeBytes: + MOVD $0xf4, R1 + MOVB R1, 0(R8) + MOVW R4, 1(R8) + ADD $3, R8, R8 + B inlineEmitLiteralMemmove + +inlineEmitLiteralTwoBytes: + MOVD $0xf0, R1 + MOVB R1, 0(R8) + MOVB R4, 1(R8) + ADD $2, R8, R8 + B inlineEmitLiteralMemmove + +inlineEmitLiteralOneByte: + LSLW $2, R4, R4 + MOVB R4, 0(R8) + ADD $1, R8, R8 + +inlineEmitLiteralMemmove: + // Spill local variables (registers) onto the stack; call; unspill. + // + // copy(dst[i:], lit) + // + // This means calling runtime·memmove(&dst[i], &lit[0], len(lit)), so we push + // R8, R10 and R3 as arguments. + MOVD R8, 8(RSP) + MOVD R10, 16(RSP) + MOVD R3, 24(RSP) + + // Finish the "d +=" part of "d += emitLiteral(etc)". + ADD R3, R8, R8 + MOVD R7, 80(RSP) + MOVD R8, 88(RSP) + MOVD R15, 120(RSP) + CALL runtime·memmove(SB) + MOVD 64(RSP), R5 + MOVD 72(RSP), R6 + MOVD 80(RSP), R7 + MOVD 88(RSP), R8 + MOVD 96(RSP), R9 + MOVD 120(RSP), R15 + ADD $128, RSP, R17 + MOVW $0xa7bd, R16 + MOVKW $(0x1e35<<16), R16 + B inner1 + +inlineEmitLiteralEnd: + // End inline of the emitLiteral call. + // ---------------------------------------- + +emitLiteralFastPath: + // !!! Emit the 1-byte encoding "uint8(len(lit)-1)<<2". + MOVB R3, R4 + SUBW $1, R4, R4 + AND $0xff, R4, R4 + LSLW $2, R4, R4 + MOVB R4, (R8) + ADD $1, R8, R8 + + // !!! Implement the copy from lit to dst as a 16-byte load and store. + // (Encode's documentation says that dst and src must not overlap.) + // + // This always copies 16 bytes, instead of only len(lit) bytes, but that's + // OK. Subsequent iterations will fix up the overrun. + // + // Note that on arm64, it is legal and cheap to issue unaligned 8-byte or + // 16-byte loads and stores. This technique probably wouldn't be as + // effective on architectures that are fussier about alignment. + LDP 0(R10), (R0, R1) + STP (R0, R1), 0(R8) + ADD R3, R8, R8 + +inner1: + // for { etc } + + // base := s + MOVD R7, R12 + + // !!! offset := base - candidate + MOVD R12, R11 + SUB R15, R11, R11 + SUB R6, R11, R11 + + // ---------------------------------------- + // Begin inline of the extendMatch call. + // + // s = extendMatch(src, candidate+4, s+4) + + // !!! R14 = &src[len(src)] + MOVD src_len+32(FP), R14 + ADD R6, R14, R14 + + // !!! R13 = &src[len(src) - 8] + MOVD R14, R13 + SUB $8, R13, R13 + + // !!! R15 = &src[candidate + 4] + ADD $4, R15, R15 + ADD R6, R15, R15 + + // !!! s += 4 + ADD $4, R7, R7 + +inlineExtendMatchCmp8: + // As long as we are 8 or more bytes before the end of src, we can load and + // compare 8 bytes at a time. If those 8 bytes are equal, repeat. + CMP R13, R7 + BHI inlineExtendMatchCmp1 + MOVD (R15), R3 + MOVD (R7), R4 + CMP R4, R3 + BNE inlineExtendMatchBSF + ADD $8, R15, R15 + ADD $8, R7, R7 + B inlineExtendMatchCmp8 + +inlineExtendMatchBSF: + // If those 8 bytes were not equal, XOR the two 8 byte values, and return + // the index of the first byte that differs. + // RBIT reverses the bit order, then CLZ counts the leading zeros, the + // combination of which finds the least significant bit which is set. + // The arm64 architecture is little-endian, and the shift by 3 converts + // a bit index to a byte index. + EOR R3, R4, R4 + RBIT R4, R4 + CLZ R4, R4 + ADD R4>>3, R7, R7 + B inlineExtendMatchEnd + +inlineExtendMatchCmp1: + // In src's tail, compare 1 byte at a time. + CMP R7, R14 + BLS inlineExtendMatchEnd + MOVB (R15), R3 + MOVB (R7), R4 + CMP R4, R3 + BNE inlineExtendMatchEnd + ADD $1, R15, R15 + ADD $1, R7, R7 + B inlineExtendMatchCmp1 + +inlineExtendMatchEnd: + // End inline of the extendMatch call. + // ---------------------------------------- + + // ---------------------------------------- + // Begin inline of the emitCopy call. + // + // d += emitCopy(dst[d:], base-candidate, s-base) + + // !!! length := s - base + MOVD R7, R3 + SUB R12, R3, R3 + +inlineEmitCopyLoop0: + // for length >= 68 { etc } + MOVW $68, R2 + CMPW R2, R3 + BLT inlineEmitCopyStep1 + + // Emit a length 64 copy, encoded as 3 bytes. + MOVD $0xfe, R1 + MOVB R1, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUBW $64, R3, R3 + B inlineEmitCopyLoop0 + +inlineEmitCopyStep1: + // if length > 64 { etc } + MOVW $64, R2 + CMPW R2, R3 + BLE inlineEmitCopyStep2 + + // Emit a length 60 copy, encoded as 3 bytes. + MOVD $0xee, R1 + MOVB R1, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + SUBW $60, R3, R3 + +inlineEmitCopyStep2: + // if length >= 12 || offset >= 2048 { goto inlineEmitCopyStep3 } + MOVW $12, R2 + CMPW R2, R3 + BGE inlineEmitCopyStep3 + MOVW $2048, R2 + CMPW R2, R11 + BGE inlineEmitCopyStep3 + + // Emit the remaining copy, encoded as 2 bytes. + MOVB R11, 1(R8) + LSRW $8, R11, R11 + LSLW $5, R11, R11 + SUBW $4, R3, R3 + AND $0xff, R3, R3 + LSLW $2, R3, R3 + ORRW R3, R11, R11 + ORRW $1, R11, R11 + MOVB R11, 0(R8) + ADD $2, R8, R8 + B inlineEmitCopyEnd + +inlineEmitCopyStep3: + // Emit the remaining copy, encoded as 3 bytes. + SUBW $1, R3, R3 + LSLW $2, R3, R3 + ORRW $2, R3, R3 + MOVB R3, 0(R8) + MOVW R11, 1(R8) + ADD $3, R8, R8 + +inlineEmitCopyEnd: + // End inline of the emitCopy call. + // ---------------------------------------- + + // nextEmit = s + MOVD R7, R10 + + // if s >= sLimit { goto emitRemainder } + MOVD R7, R3 + SUB R6, R3, R3 + CMP R3, R9 + BLS emitRemainder + + // As per the encode_other.go code: + // + // We could immediately etc. + + // x := load64(src, s-1) + MOVD -1(R7), R14 + + // prevHash := hash(uint32(x>>0), shift) + MOVW R14, R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + + // table[prevHash] = uint16(s-1) + MOVD R7, R3 + SUB R6, R3, R3 + SUB $1, R3, R3 + + MOVHU R3, 0(R17)(R11<<1) + + // currHash := hash(uint32(x>>8), shift) + LSR $8, R14, R14 + MOVW R14, R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + + // candidate = int(table[currHash]) + MOVHU 0(R17)(R11<<1), R15 + + // table[currHash] = uint16(s) + ADD $1, R3, R3 + MOVHU R3, 0(R17)(R11<<1) + + // if uint32(x>>8) == load32(src, candidate) { continue } + MOVW (R6)(R15*1), R4 + CMPW R4, R14 + BEQ inner1 + + // nextHash = hash(uint32(x>>16), shift) + LSR $8, R14, R14 + MOVW R14, R11 + MULW R16, R11, R11 + LSRW R5, R11, R11 + + // s++ + ADD $1, R7, R7 + + // break out of the inner1 for loop, i.e. continue the outer loop. + B outer + +emitRemainder: + // if nextEmit < len(src) { etc } + MOVD src_len+32(FP), R3 + ADD R6, R3, R3 + CMP R3, R10 + BEQ encodeBlockEnd + + // d += emitLiteral(dst[d:], src[nextEmit:]) + // + // Push args. + MOVD R8, 8(RSP) + MOVD $0, 16(RSP) // Unnecessary, as the callee ignores it, but conservative. + MOVD $0, 24(RSP) // Unnecessary, as the callee ignores it, but conservative. + MOVD R10, 32(RSP) + SUB R10, R3, R3 + MOVD R3, 40(RSP) + MOVD R3, 48(RSP) // Unnecessary, as the callee ignores it, but conservative. + + // Spill local variables (registers) onto the stack; call; unspill. + MOVD R8, 88(RSP) + CALL ·emitLiteral(SB) + MOVD 88(RSP), R8 + + // Finish the "d +=" part of "d += emitLiteral(etc)". + MOVD 56(RSP), R1 + ADD R1, R8, R8 + +encodeBlockEnd: + MOVD dst_base+0(FP), R3 + SUB R3, R8, R8 + MOVD R8, d+48(FP) + RET diff --git a/vendor/github.com/golang/snappy/encode_amd64.go b/vendor/github.com/golang/snappy/encode_asm.go similarity index 97% rename from vendor/github.com/golang/snappy/encode_amd64.go rename to vendor/github.com/golang/snappy/encode_asm.go index 150d91bc8..107c1e714 100644 --- a/vendor/github.com/golang/snappy/encode_amd64.go +++ b/vendor/github.com/golang/snappy/encode_asm.go @@ -5,6 +5,7 @@ // +build !appengine // +build gc // +build !noasm +// +build amd64 arm64 package snappy diff --git a/vendor/github.com/golang/snappy/encode_other.go b/vendor/github.com/golang/snappy/encode_other.go index dbcae905e..296d7f0be 100644 --- a/vendor/github.com/golang/snappy/encode_other.go +++ b/vendor/github.com/golang/snappy/encode_other.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// +build !amd64 appengine !gc noasm +// +build !amd64,!arm64 appengine !gc noasm package snappy diff --git a/vendor/github.com/golang/snappy/go.mod b/vendor/github.com/golang/snappy/go.mod new file mode 100644 index 000000000..f6406bb2c --- /dev/null +++ b/vendor/github.com/golang/snappy/go.mod @@ -0,0 +1 @@ +module github.com/golang/snappy diff --git a/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go b/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go index 51c75a77d..5c3fda705 100644 --- a/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go +++ b/vendor/github.com/golangci/golangci-lint/internal/cache/cache.go @@ -370,7 +370,7 @@ func (c *Cache) putIndexEntry(id ActionID, out OutputID, size int64, allowVerify // Truncate the file only *after* writing it. // (This should be a no-op, but truncate just in case of previous corruption.) // - // This differs from ioutil.WriteFile, which truncates to 0 *before* writing + // This differs from os.WriteFile, which truncates to 0 *before* writing // via os.O_TRUNC. Truncating only after writing ensures that a second write // of the same content to the same file is idempotent, and does not — even // temporarily! — undo the effect of the first write. diff --git a/vendor/github.com/golangci/golangci-lint/internal/cache/default.go b/vendor/github.com/golangci/golangci-lint/internal/cache/default.go index e8866cb30..669500629 100644 --- a/vendor/github.com/golangci/golangci-lint/internal/cache/default.go +++ b/vendor/github.com/golangci/golangci-lint/internal/cache/default.go @@ -6,7 +6,6 @@ package cache import ( "fmt" - "io/ioutil" "log" "os" "path/filepath" @@ -39,7 +38,7 @@ func initDefaultCache() { } if _, err := os.Stat(filepath.Join(dir, "README")); err != nil { // Best effort. - if wErr := ioutil.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666); wErr != nil { + if wErr := os.WriteFile(filepath.Join(dir, "README"), []byte(cacheREADME), 0666); wErr != nil { log.Fatalf("Failed to write README file to cache dir %s: %s", dir, err) } } diff --git a/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go b/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go index fa9d93bf7..2f88f4f7c 100644 --- a/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go +++ b/vendor/github.com/golangci/golangci-lint/internal/renameio/renameio.go @@ -24,7 +24,7 @@ func Pattern(filename string) string { return filepath.Join(filepath.Dir(filename), filepath.Base(filename)+patternSuffix) } -// WriteFile is like ioutil.WriteFile, but first writes data to an arbitrary +// WriteFile is like os.WriteFile, but first writes data to an arbitrary // file in the same directory as filename, then renames it atomically to the // final name. // @@ -79,7 +79,7 @@ func tempFile(dir, prefix string, perm os.FileMode) (f *os.File, err error) { return } -// ReadFile is like ioutil.ReadFile, but on Windows retries spurious errors that +// ReadFile is like os.ReadFile, but on Windows retries spurious errors that // may occur if the file is concurrently replaced. // // Errors are classified heuristically and retries are bounded, so even this diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go index 76e47ad1f..ce3dbbde6 100644 --- a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio.go @@ -22,7 +22,7 @@ func Rename(oldpath, newpath string) error { return rename(oldpath, newpath) } -// ReadFile is like ioutil.ReadFile, but on Windows retries errors that may +// ReadFile is like os.ReadFile, but on Windows retries errors that may // occur if the file is concurrently replaced. // // (See golang.org/issue/31247 and golang.org/issue/32188.) diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go index e0bf5b9b3..5963027ee 100644 --- a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_flaky.go @@ -7,7 +7,6 @@ package robustio import ( - "io/ioutil" "math/rand" "os" "syscall" @@ -70,11 +69,11 @@ func rename(oldpath, newpath string) (err error) { }) } -// readFile is like ioutil.ReadFile, but retries ephemeral errors. +// readFile is like os.ReadFile, but retries ephemeral errors. func readFile(filename string) ([]byte, error) { var b []byte err := retry(func() (err error, mayRetry bool) { - b, err = ioutil.ReadFile(filename) + b, err = os.ReadFile(filename) // Unlike in rename, we do not retry errFileNotFound here: it can occur // as a spurious error, but the file may also genuinely not exist, so the diff --git a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go index a2428856f..b7d01b340 100644 --- a/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go +++ b/vendor/github.com/golangci/golangci-lint/internal/robustio/robustio_other.go @@ -7,7 +7,6 @@ package robustio import ( - "io/ioutil" "os" ) @@ -16,7 +15,7 @@ func rename(oldpath, newpath string) error { } func readFile(filename string) ([]byte, error) { - return ioutil.ReadFile(filename) + return os.ReadFile(filename) } func removeAll(path string) error { diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go index 4b63e2e52..0f2205970 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/config.go @@ -35,6 +35,8 @@ func (e *Executor) initConfig() { cmd.AddCommand(pathCmd) } +// getUsedConfig returns the resolved path to the golangci config file, or the empty string +// if no configuration could be found. func (e *Executor) getUsedConfig() string { usedConfigFile := viper.ConfigFileUsed() if usedConfigFile == "" { diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go index 3edb6e4b0..0ad37dde6 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/executor.go @@ -38,7 +38,7 @@ type Executor struct { exitCode int version, commit, date string - cfg *config.Config + cfg *config.Config // cfg is the unmarshaled data from the golangci config file. log logutils.Log reportData report.Data DBManager *lintersdb.Manager @@ -55,6 +55,7 @@ type Executor struct { flock *flock.Flock } +// NewExecutor creates and initializes a new command executor. func NewExecutor(version, commit, date string) *Executor { startedAt := time.Now() e := &Executor{ diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go index ef276481c..dc3bb4731 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/help.go @@ -80,7 +80,7 @@ func (e *Executor) executeLintersHelp(_ *cobra.Command, args []string) { color.Green("\nLinters presets:") for _, p := range e.DBManager.AllPresets() { linters := e.DBManager.GetAllLinterConfigsForPreset(p) - linterNames := []string{} + linterNames := make([]string, 0, len(linters)) for _, lc := range linters { linterNames = append(linterNames, lc.Name()) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go index 873dab817..bb096942f 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/linters.go @@ -20,6 +20,7 @@ func (e *Executor) initLinters() { e.initRunConfiguration(e.lintersCmd) } +// executeLinters runs the 'linters' CLI command, which displays the supported linters. func (e *Executor) executeLinters(_ *cobra.Command, args []string) { if len(args) != 0 { e.log.Fatalf("Usage: golangci-lint linters") diff --git a/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go b/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go index 271fffe94..23a9b064a 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/commands/run.go @@ -3,7 +3,7 @@ package commands import ( "context" "fmt" - "io/ioutil" + "io" "log" "os" "runtime" @@ -200,9 +200,6 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is fs.StringSliceVarP(&lc.Enable, "enable", "E", nil, wh("Enable specific linter")) fs.StringSliceVarP(&lc.Disable, "disable", "D", nil, wh("Disable specific linter")) fs.BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters")) - if err := fs.MarkHidden("enable-all"); err != nil { - panic(err) - } fs.BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters")) fs.StringSliceVarP(&lc.Presets, "presets", "p", nil, @@ -233,6 +230,8 @@ func initFlagSet(fs *pflag.FlagSet, cfg *config.Config, m *lintersdb.Manager, is wh("Show only new issues created after git revision `REV`")) fs.StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", wh("Show only new issues created in git patch with file path `PATH`")) + fs.BoolVar(&ic.WholeFiles, "whole-files", false, + wh("Show issues in any part of update files (requires new-from-rev or new-from-patch)")) fs.BoolVar(&ic.NeedFix, "fix", false, "Fix found issues (if it's supported by the linter)") } @@ -324,6 +323,7 @@ func fixSlicesFlags(fs *pflag.FlagSet) { }) } +// runAnalysis executes the linters that have been enabled in the configuration. func (e *Executor) runAnalysis(ctx context.Context, args []string) ([]result.Issue, error) { e.cfg.Run.Args = args @@ -388,7 +388,7 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error { if !logutils.HaveDebugTag("linters_output") { // Don't allow linters and loader to print anything - log.SetOutput(ioutil.Discard) + log.SetOutput(io.Discard) savedStdout, savedStderr := e.setOutputToDevNull() defer func() { os.Stdout, os.Stderr = savedStdout, savedStderr @@ -445,6 +445,7 @@ func (e *Executor) createPrinter() (printers.Printer, error) { return p, nil } +// executeRun executes the 'run' CLI command, which runs the linters. func (e *Executor) executeRun(_ *cobra.Command, args []string) { needTrackResources := e.cfg.Run.IsVerbose || e.cfg.Run.PrintResourcesUsage trackResourcesEndCh := make(chan struct{}) diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/config.go b/vendor/github.com/golangci/golangci-lint/pkg/config/config.go index 931ddbbbe..f41705c89 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/config/config.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/config.go @@ -1,7 +1,9 @@ package config +// Config encapsulates the config data specified in the golangci yaml config file. type Config struct { - Run Run + cfgDir string // The directory containing the golangci config file. + Run Run Output Output @@ -15,6 +17,11 @@ type Config struct { InternalTest bool // Option is used only for testing golangci-lint code, don't use it } +// getConfigDir returns the directory that contains golangci config file. +func (c *Config) GetConfigDir() string { + return c.cfgDir +} + func NewDefault() *Config { return &Config{ LintersSettings: defaultLintersSettings, diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/issues.go b/vendor/github.com/golangci/golangci-lint/pkg/config/issues.go index 71bf2a90e..0f9ac5f61 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/config/issues.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/issues.go @@ -115,6 +115,7 @@ type Issues struct { DiffFromRevision string `mapstructure:"new-from-rev"` DiffPatchFilePath string `mapstructure:"new-from-patch"` + WholeFiles bool `mapstructure:"whole-files"` Diff bool `mapstructure:"new"` NeedFix bool `mapstructure:"fix"` diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings.go b/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings.go index fd5f41318..840b283fe 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings.go @@ -110,6 +110,7 @@ type LintersSettings struct { Gosimple StaticCheckSettings Govet GovetSettings Ifshort IfshortSettings + Ireturn IreturnSettings ImportAs ImportAsSettings Lll LllSettings Makezero MakezeroSettings @@ -117,6 +118,8 @@ type LintersSettings struct { Misspell MisspellSettings Nakedret NakedretSettings Nestif NestifSettings + NilNil NilNilSettings + Nlreturn NlreturnSettings NoLintLint NoLintLintSettings Prealloc PreallocSettings Predeclared PredeclaredSettings @@ -129,9 +132,11 @@ type LintersSettings struct { Tagliatelle TagliatelleSettings Testpackage TestpackageSettings Thelper ThelperSettings + Tenv TenvSettings Unparam UnparamSettings Unused StaticCheckSettings Varcheck VarCheckSettings + Varnamelen VarnamelenSettings Whitespace WhitespaceSettings Wrapcheck WrapcheckSettings WSL WSLSettings @@ -186,6 +191,11 @@ type ExhaustiveStructSettings struct { StructPatterns []string `mapstructure:"struct-patterns"` } +type IreturnSettings struct { + Allow []string `mapstructure:"allow"` + Reject []string `mapstructure:"reject"` +} + type ForbidigoSettings struct { Forbid []string `mapstructure:"forbid"` ExcludeGodocExamples bool `mapstructure:"exclude-godoc-examples"` @@ -285,9 +295,12 @@ type GoModGuardSettings struct { } type GoSecSettings struct { - Includes []string - Excludes []string - Config map[string]interface{} `mapstructure:"config"` + Includes []string + Excludes []string + Severity string + Confidence string + ExcludeGenerated bool `mapstructure:"exclude-generated"` + Config map[string]interface{} `mapstructure:"config"` } type GovetSettings struct { @@ -354,6 +367,14 @@ type NestifSettings struct { MinComplexity int `mapstructure:"min-complexity"` } +type NilNilSettings struct { + CheckedTypes []string `mapstructure:"checked-types"` +} + +type NlreturnSettings struct { + BlockSize int `mapstructure:"block-size"` +} + type NoLintLintSettings struct { RequireExplanation bool `mapstructure:"require-explanation"` AllowLeadingSpace bool `mapstructure:"allow-leading-space"` @@ -447,6 +468,10 @@ type ThelperSettings struct { } `mapstructure:"tb"` } +type TenvSettings struct { + All bool `mapstructure:"all"` +} + type UnparamSettings struct { CheckExported bool `mapstructure:"check-exported"` Algo string @@ -456,6 +481,14 @@ type VarCheckSettings struct { CheckExportedFields bool `mapstructure:"exported-fields"` } +type VarnamelenSettings struct { + MaxDistance int `mapstructure:"max-distance"` + MinNameLength int `mapstructure:"min-name-length"` + CheckReceiver bool `mapstructure:"check-receiver"` + CheckReturn bool `mapstructure:"check-return"` + IgnoreNames []string `mapstructure:"ignore-names"` +} + type WhitespaceSettings struct { MultiIf bool `mapstructure:"multi-if"` MultiFunc bool `mapstructure:"multi-func"` @@ -479,8 +512,20 @@ type WSLSettings struct { ForceCaseTrailingWhitespaceLimit int `mapstructure:"force-case-trailing-whitespace"` } +// CustomLinterSettings encapsulates the meta-data of a private linter. +// For example, a private linter may be added to the golangci config file as shown below. +// +// linters-settings: +// custom: +// example: +// path: /example.so +// description: The description of the linter +// original-url: github.com/golangci/example-linter type CustomLinterSettings struct { - Path string + // Path to a plugin *.so file that implements the private linter. + Path string + // Description describes the purpose of the private linter. Description string + // The URL containing the source code for the private linter. OriginalURL string `mapstructure:"original-url"` } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings_gocritic.go b/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings_gocritic.go index 34f850758..cd68ef82a 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings_gocritic.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/linters_settings_gocritic.go @@ -156,7 +156,7 @@ func (s *GocriticSettings) InferEnabledChecks(log logutils.Log) { enabledChecksSet := stringsSliceToSet(enabledChecks) for _, disabledCheck := range s.DisabledChecks { if !enabledChecksSet[disabledCheck] { - log.Warnf("Gocritic check %q was explicitly disabled via config. However, as this check"+ + log.Warnf("Gocritic check %q was explicitly disabled via config. However, as this check "+ "is disabled by default, there is no need to explicitly disable it via config.", disabledCheck) continue } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go b/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go index 6e97277da..9f368341b 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/reader.go @@ -71,6 +71,11 @@ func (r *FileReader) parseConfig() error { r.log.Warnf("Can't pretty print config file path: %s", err) } r.log.Infof("Used config file %s", usedConfigFile) + usedConfigDir := filepath.Dir(usedConfigFile) + if usedConfigDir, err = filepath.Abs(usedConfigDir); err != nil { + return fmt.Errorf("can't get config directory") + } + r.cfg.cfgDir = usedConfigDir if err := viper.Unmarshal(r.cfg); err != nil { return fmt.Errorf("can't unmarshal config by viper: %s", err) diff --git a/vendor/github.com/golangci/golangci-lint/pkg/config/run.go b/vendor/github.com/golangci/golangci-lint/pkg/config/run.go index ff6347945..c091ee843 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/config/run.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/config/run.go @@ -2,6 +2,7 @@ package config import "time" +// Run encapsulates the config options for running the linter analysis. type Run struct { IsVerbose bool `mapstructure:"verbose"` Silent bool @@ -11,7 +12,7 @@ type Run struct { Concurrency int PrintResourcesUsage bool `mapstructure:"print-resources-usage"` - Config string + Config string // The path to the golangci config file, as specified with the --config argument. NoConfig bool Args []string diff --git a/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go index 2b17a0398..04c66823d 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/fsutils/filecache.go @@ -2,7 +2,7 @@ package fsutils import ( "fmt" - "io/ioutil" + "os" "sync" "github.com/pkg/errors" @@ -24,7 +24,7 @@ func (fc *FileCache) GetFileBytes(filePath string) ([]byte, error) { return cachedBytes.([]byte), nil } - fileBytes, err := ioutil.ReadFile(filePath) + fileBytes, err := os.ReadFile(filePath) if err != nil { return nil, errors.Wrapf(err, "can't read file %s", filePath) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/bidichk.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/bidichk.go new file mode 100644 index 000000000..e1b467cc1 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/bidichk.go @@ -0,0 +1,17 @@ +package golinters + +import ( + "github.com/breml/bidichk/pkg/bidichk" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewBiDiChkFuncName() *goanalysis.Linter { + return goanalysis.NewLinter( + "bidichk", + "Checks for dangerous unicode character sequences", + []*analysis.Analyzer{bidichk.Analyzer}, + nil, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/contextcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/contextcheck.go new file mode 100644 index 000000000..eb12ed4ef --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/contextcheck.go @@ -0,0 +1,18 @@ +package golinters + +import ( + "github.com/sylvia7788/contextcheck" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewContextCheck() *goanalysis.Linter { + analyzer := contextcheck.NewAnalyzer() + return goanalysis.NewLinter( + "contextcheck", + "check the function whether use a non-inherited context", + []*analysis.Analyzer{analyzer}, + nil, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go index 2d9a4fc4c..0499c54ad 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/errcheck.go @@ -66,9 +66,14 @@ func NewErrcheck() *goanalysis.Linter { for i, err := range errcheckIssues.UncheckedErrors { var text string if err.FuncName != "" { + code := err.SelectorName + if err.SelectorName == "" { + code = err.FuncName + } + text = fmt.Sprintf( "Error return value of %s is not checked", - formatCode(err.SelectorName, lintCtx.Cfg), + formatCode(code, lintCtx.Cfg), ) } else { text = "Error return value is not checked" diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go index 9fa396854..f9a43f3f5 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/goanalysis/runner_loadingpackage.go @@ -492,6 +492,6 @@ func sizeOfReflectValueTreeBytes(rv reflect.Value, visitedPtrs map[uintptr]struc case reflect.Invalid: return 0 default: - panic("unknown rv of type " + fmt.Sprint(rv)) + panic("unknown rv of type " + rv.String()) } } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go index e98f23445..0c32a8562 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gocritic.go @@ -34,7 +34,7 @@ func NewGocritic() *goanalysis.Linter { } return goanalysis.NewLinter( gocriticName, - `Provides many diagnostics that check for bugs, performance and style issues. + `Provides diagnostics that check for bugs, performance and style issues. Extensible without recompilation through dynamic rules. Dynamic rules are written declaratively with AST patterns, filters, report message and optional suggestion.`, []*analysis.Analyzer{analyzer}, @@ -78,7 +78,10 @@ func normalizeCheckerInfoParams(info *gocriticlinter.CheckerInfo) gocriticlinter return ret } -func configureCheckerInfo(info *gocriticlinter.CheckerInfo, allParams map[string]config.GocriticCheckSettings) error { +func configureCheckerInfo( + lintCtx *linter.Context, + info *gocriticlinter.CheckerInfo, + allParams map[string]config.GocriticCheckSettings) error { params := allParams[strings.ToLower(info.Name)] if params == nil { // no config for this checker return nil @@ -88,7 +91,7 @@ func configureCheckerInfo(info *gocriticlinter.CheckerInfo, allParams map[string for k, p := range params { v, ok := infoParams[k] if ok { - v.Value = normalizeCheckerParamsValue(p) + v.Value = normalizeCheckerParamsValue(lintCtx, p) continue } @@ -117,7 +120,7 @@ func configureCheckerInfo(info *gocriticlinter.CheckerInfo, allParams map[string // then we have to convert value types into the expected value types. // Maybe in the future, this kind of conversion will be done in go-critic itself. //nolint:exhaustive // only 3 types (int, bool, and string) are supported by CheckerParam.Value -func normalizeCheckerParamsValue(p interface{}) interface{} { +func normalizeCheckerParamsValue(lintCtx *linter.Context, p interface{}) interface{} { rv := reflect.ValueOf(p) switch rv.Type().Kind() { case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: @@ -125,7 +128,8 @@ func normalizeCheckerParamsValue(p interface{}) interface{} { case reflect.Bool: return rv.Bool() case reflect.String: - return rv.String() + // Perform variable substitution. + return strings.ReplaceAll(rv.String(), "${configDir}", lintCtx.Cfg.GetConfigDir()) default: return p } @@ -141,7 +145,7 @@ func buildEnabledCheckers(lintCtx *linter.Context, linterCtx *gocriticlinter.Con continue } - if err := configureCheckerInfo(info, allParams); err != nil { + if err := configureCheckerInfo(lintCtx, info, allParams); err != nil { return nil, err } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofumpt.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofumpt.go index 75c088144..455572d6e 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofumpt.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gofumpt.go @@ -3,7 +3,7 @@ package golinters import ( "bytes" "fmt" - "io/ioutil" + "os" "sync" "github.com/pkg/errors" @@ -50,7 +50,7 @@ func NewGofumpt() *goanalysis.Linter { var issues []goanalysis.Issue for _, f := range fileNames { - input, err := ioutil.ReadFile(f) + input, err := os.ReadFile(f) if err != nil { return nil, fmt.Errorf("unable to open file %s: %w", f, err) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go index 328ba5ccc..9610b3e83 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/gosec.go @@ -3,12 +3,13 @@ package golinters import ( "fmt" "go/token" - "io/ioutil" + "io" "log" "strconv" "strings" "sync" + "github.com/pkg/errors" "github.com/securego/gosec/v2" "github.com/securego/gosec/v2/rules" "golang.org/x/tools/go/analysis" @@ -41,7 +42,7 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter { ruleDefinitions := rules.Generate(filters...) - logger := log.New(ioutil.Discard, "", 0) + logger := log.New(io.Discard, "", 0) analyzer := &analysis.Analyzer{ Name: gosecName, @@ -54,7 +55,7 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter { nil, ).WithContextSetter(func(lintCtx *linter.Context) { analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { - gosecAnalyzer := gosec.NewAnalyzer(gasConfig, true, logger) + gosecAnalyzer := gosec.NewAnalyzer(gasConfig, true, settings.ExcludeGenerated, logger) gosecAnalyzer.LoadRules(ruleDefinitions.Builders()) pkg := &packages.Package{ @@ -68,7 +69,16 @@ func NewGosec(settings *config.GoSecSettings) *goanalysis.Linter { if len(issues) == 0 { return nil, nil } + severity, err := convertToScore(settings.Severity) + if err != nil { + lintCtx.Log.Warnf("The provided severity %v", err) + } + confidence, err := convertToScore(settings.Confidence) + if err != nil { + lintCtx.Log.Warnf("The provided confidence %v", err) + } + issues = filterIssues(issues, severity, confidence) res := make([]goanalysis.Issue, 0, len(issues)) for _, i := range issues { text := fmt.Sprintf("%s: %s", i.RuleID, i.What) // TODO: use severity and confidence @@ -126,3 +136,29 @@ func gosecRuleFilters(includes, excludes []string) []rules.RuleFilter { return filters } + +// code borrowed from https://github.com/securego/gosec/blob/69213955dacfd560562e780f723486ef1ca6d486/cmd/gosec/main.go#L250-L262 +func convertToScore(str string) (gosec.Score, error) { + str = strings.ToLower(str) + switch str { + case "", "low": + return gosec.Low, nil + case "medium": + return gosec.Medium, nil + case "high": + return gosec.High, nil + default: + return gosec.Low, errors.Errorf("'%s' is invalid, use low instead. Valid options: low, medium, high", str) + } +} + +// code borrowed from https://github.com/securego/gosec/blob/69213955dacfd560562e780f723486ef1ca6d486/cmd/gosec/main.go#L264-L276 +func filterIssues(issues []*gosec.Issue, severity, confidence gosec.Score) []*gosec.Issue { + res := make([]*gosec.Issue, 0) + for _, issue := range issues { + if issue.Severity >= severity && issue.Confidence >= confidence { + res = append(res, issue) + } + } + return res +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/ireturn.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/ireturn.go new file mode 100644 index 000000000..3b5df66da --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/ireturn.go @@ -0,0 +1,30 @@ +package golinters + +import ( + "strings" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" + + "github.com/butuzov/ireturn/analyzer" + "golang.org/x/tools/go/analysis" +) + +func NewIreturn(settings *config.IreturnSettings) *goanalysis.Linter { + a := analyzer.NewAnalyzer() + + cfg := map[string]map[string]interface{}{} + if settings != nil { + cfg[a.Name] = map[string]interface{}{ + "allow": strings.Join(settings.Allow, ","), + "reject": strings.Join(settings.Reject, ","), + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nilnil.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nilnil.go new file mode 100644 index 000000000..739b4d4fc --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nilnil.go @@ -0,0 +1,30 @@ +package golinters + +import ( + "strings" + + "github.com/Antonboom/nilnil/pkg/analyzer" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewNilNil(cfg *config.NilNilSettings) *goanalysis.Linter { + a := analyzer.New() + + cfgMap := make(map[string]map[string]interface{}) + if cfg != nil && len(cfg.CheckedTypes) != 0 { + cfgMap[a.Name] = map[string]interface{}{ + "checked-types": strings.Join(cfg.CheckedTypes, ","), + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + []*analysis.Analyzer{a}, + cfgMap, + ). + WithLoadMode(goanalysis.LoadModeTypesInfo) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nlreturn.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nlreturn.go index 3b661c64c..fb4919f8a 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/nlreturn.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/nlreturn.go @@ -4,16 +4,24 @@ import ( "github.com/ssgreg/nlreturn/v2/pkg/nlreturn" "golang.org/x/tools/go/analysis" + "github.com/golangci/golangci-lint/pkg/config" "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" ) -func NewNLReturn() *goanalysis.Linter { +func NewNLReturn(settings *config.NlreturnSettings) *goanalysis.Linter { + a := nlreturn.NewAnalyzer() + + cfg := map[string]map[string]interface{}{} + if settings != nil { + cfg[a.Name] = map[string]interface{}{ + "block-size": settings.BlockSize, + } + } + return goanalysis.NewLinter( - "nlreturn", + a.Name, "nlreturn checks for a new line before return and branch statements to increase code clarity", - []*analysis.Analyzer{ - nlreturn.NewAnalyzer(), - }, - nil, + []*analysis.Analyzer{a}, + cfg, ).WithLoadMode(goanalysis.LoadModeSyntax) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/revive.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/revive.go index 590332e66..061c9b475 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/revive.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/revive.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" "go/token" - "io/ioutil" + "os" "reflect" "github.com/BurntSushi/toml" @@ -65,7 +65,7 @@ func NewRevive(cfg *config.ReviveSettings) *goanalysis.Linter { return nil, err } - revive := lint.New(ioutil.ReadFile) + revive := lint.New(os.ReadFile) lintingRules, err := reviveConfig.GetLintingRules(conf) if err != nil { diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/tenv.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/tenv.go new file mode 100644 index 000000000..8e3e9c61f --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/tenv.go @@ -0,0 +1,33 @@ +package golinters + +import ( + "github.com/sivchari/tenv" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewTenv(settings *config.TenvSettings) *goanalysis.Linter { + a := tenv.Analyzer + + analyzers := []*analysis.Analyzer{ + a, + } + + var cfg map[string]map[string]interface{} + if settings != nil { + cfg = map[string]map[string]interface{}{ + a.Name: { + tenv.A: settings.All, + }, + } + } + + return goanalysis.NewLinter( + a.Name, + a.Doc, + analyzers, + cfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/varnamelen.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/varnamelen.go new file mode 100644 index 000000000..168c881c4 --- /dev/null +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/varnamelen.go @@ -0,0 +1,41 @@ +package golinters + +import ( + "strconv" + "strings" + + "github.com/blizzy78/varnamelen" + "golang.org/x/tools/go/analysis" + + "github.com/golangci/golangci-lint/pkg/config" + "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" +) + +func NewVarnamelen(settings *config.VarnamelenSettings) *goanalysis.Linter { + a := varnamelen.NewAnalyzer() + + cfg := map[string]map[string]interface{}{} + if settings != nil { + vnlCfg := map[string]interface{}{ + "checkReceiver": strconv.FormatBool(settings.CheckReceiver), + "checkReturn": strconv.FormatBool(settings.CheckReturn), + "ignoreNames": strings.Join(settings.IgnoreNames, ","), + } + + if settings.MaxDistance > 0 { + vnlCfg["maxDistance"] = strconv.Itoa(settings.MaxDistance) + } + if settings.MinNameLength > 0 { + vnlCfg["minNameLength"] = strconv.Itoa(settings.MinNameLength) + } + + cfg[a.Name] = vnlCfg + } + + return goanalysis.NewLinter( + a.Name, + "checks that the length of a variable's name matches its scope", + []*analysis.Analyzer{a}, + cfg, + ).WithLoadMode(goanalysis.LoadModeSyntax) +} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go b/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go index 29d00faea..b5961cc1f 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/golinters/wsl.go @@ -34,7 +34,7 @@ func NewWSL() *goanalysis.Linter { ).WithContextSetter(func(lintCtx *linter.Context) { analyzer.Run = func(pass *analysis.Pass) (interface{}, error) { var ( - files = []string{} + files = make([]string, 0, len(pass.Files)) linterCfg = lintCtx.Cfg.LintersSettings.WSL processorCfg = wsl.Configuration{ StrictAppend: linterCfg.StrictAppend, diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go index a69a6ec38..7d5695747 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/lintersdb/manager.go @@ -35,6 +35,7 @@ func NewManager(cfg *config.Config, log logutils.Log) *Manager { return m } +// WithCustomLinters loads private linters that are specified in the golangci config file. func (m *Manager) WithCustomLinters() *Manager { if m.log == nil { m.log = report.NewLogWrapper(logutils.NewStderrLog(""), &report.Data{}) @@ -99,46 +100,56 @@ func enableLinterConfigs(lcs []*linter.Config, isEnabled func(lc *linter.Config) //nolint:funlen func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { - var govetCfg *config.GovetSettings - var testpackageCfg *config.TestpackageSettings + var cyclopCfg *config.Cyclop + var errorlintCfg *config.ErrorLintSettings var exhaustiveCfg *config.ExhaustiveSettings var exhaustiveStructCfg *config.ExhaustiveStructSettings - var errorlintCfg *config.ErrorLintSettings - var thelperCfg *config.ThelperSettings - var predeclaredCfg *config.PredeclaredSettings - var ifshortCfg *config.IfshortSettings - var reviveCfg *config.ReviveSettings - var cyclopCfg *config.Cyclop - var importAsCfg *config.ImportAsSettings var goModDirectivesCfg *config.GoModDirectivesSettings - var tagliatelleCfg *config.TagliatelleSettings var gosecCfg *config.GoSecSettings var gosimpleCfg *config.StaticCheckSettings + var govetCfg *config.GovetSettings + var ifshortCfg *config.IfshortSettings + var importAsCfg *config.ImportAsSettings + var ireturnCfg *config.IreturnSettings + var nilNilCfg *config.NilNilSettings + var predeclaredCfg *config.PredeclaredSettings + var reviveCfg *config.ReviveSettings var staticcheckCfg *config.StaticCheckSettings var stylecheckCfg *config.StaticCheckSettings + var tagliatelleCfg *config.TagliatelleSettings + var tenvCfg *config.TenvSettings + var testpackageCfg *config.TestpackageSettings + var thelperCfg *config.ThelperSettings var unusedCfg *config.StaticCheckSettings + var varnamelenCfg *config.VarnamelenSettings var wrapcheckCfg *config.WrapcheckSettings + var nlreturnCfg *config.NlreturnSettings if m.cfg != nil { - govetCfg = &m.cfg.LintersSettings.Govet - testpackageCfg = &m.cfg.LintersSettings.Testpackage + cyclopCfg = &m.cfg.LintersSettings.Cyclop + errorlintCfg = &m.cfg.LintersSettings.ErrorLint exhaustiveCfg = &m.cfg.LintersSettings.Exhaustive exhaustiveStructCfg = &m.cfg.LintersSettings.ExhaustiveStruct - errorlintCfg = &m.cfg.LintersSettings.ErrorLint - thelperCfg = &m.cfg.LintersSettings.Thelper - predeclaredCfg = &m.cfg.LintersSettings.Predeclared - ifshortCfg = &m.cfg.LintersSettings.Ifshort - reviveCfg = &m.cfg.LintersSettings.Revive - cyclopCfg = &m.cfg.LintersSettings.Cyclop - importAsCfg = &m.cfg.LintersSettings.ImportAs goModDirectivesCfg = &m.cfg.LintersSettings.GoModDirectives - tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle gosecCfg = &m.cfg.LintersSettings.Gosec gosimpleCfg = &m.cfg.LintersSettings.Gosimple + govetCfg = &m.cfg.LintersSettings.Govet + ifshortCfg = &m.cfg.LintersSettings.Ifshort + importAsCfg = &m.cfg.LintersSettings.ImportAs + ireturnCfg = &m.cfg.LintersSettings.Ireturn + nilNilCfg = &m.cfg.LintersSettings.NilNil + predeclaredCfg = &m.cfg.LintersSettings.Predeclared + reviveCfg = &m.cfg.LintersSettings.Revive staticcheckCfg = &m.cfg.LintersSettings.Staticcheck stylecheckCfg = &m.cfg.LintersSettings.Stylecheck + tagliatelleCfg = &m.cfg.LintersSettings.Tagliatelle + tenvCfg = &m.cfg.LintersSettings.Tenv + testpackageCfg = &m.cfg.LintersSettings.Testpackage + thelperCfg = &m.cfg.LintersSettings.Thelper unusedCfg = &m.cfg.LintersSettings.Unused + varnamelenCfg = &m.cfg.LintersSettings.Varnamelen wrapcheckCfg = &m.cfg.LintersSettings.Wrapcheck + nlreturnCfg = &m.cfg.LintersSettings.Nlreturn } const megacheckName = "megacheck" @@ -410,7 +421,7 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetBugs, linter.PresetSQL). WithLoadForGoAnalysis(). WithURL("https://github.com/ryanrolds/sqlclosecheck"), - linter.NewConfig(golinters.NewNLReturn()). + linter.NewConfig(golinters.NewNLReturn(nlreturnCfg)). WithSince("v1.30.0"). WithPresets(linter.PresetStyle). WithURL("https://github.com/ssgreg/nlreturn"), @@ -502,10 +513,39 @@ func (m Manager) GetAllSupportedLinterConfigs() []*linter.Config { WithPresets(linter.PresetStyle). WithURL("https://github.com/ldez/tagliatelle"), linter.NewConfig(golinters.NewErrName()). + WithSince("v1.42.0"). WithPresets(linter.PresetStyle). WithLoadForGoAnalysis(). - WithURL("https://github.com/Antonboom/errname"). - WithSince("v1.42.0"), + WithURL("https://github.com/Antonboom/errname"), + linter.NewConfig(golinters.NewIreturn(ireturnCfg)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/butuzov/ireturn"), + linter.NewConfig(golinters.NewNilNil(nilNilCfg)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/Antonboom/nilnil"), + linter.NewConfig(golinters.NewTenv(tenvCfg)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/sivchari/tenv"), + linter.NewConfig(golinters.NewContextCheck()). + WithSince("v1.43.0"). + WithPresets(linter.PresetBugs). + WithLoadForGoAnalysis(). + WithURL("https://github.com/sylvia7788/contextcheck"), + linter.NewConfig(golinters.NewVarnamelen(varnamelenCfg)). + WithSince("v1.43.0"). + WithPresets(linter.PresetStyle). + WithLoadForGoAnalysis(). + WithURL("https://github.com/blizzy78/varnamelen"), + linter.NewConfig(golinters.NewBiDiChkFuncName()). + WithSince("1.43.0"). + WithPresets(linter.PresetBugs). + WithURL("https://github.com/breml/bidichk"), // nolintlint must be last because it looks at the results of all the previous linters for unused nolint directives linter.NewConfig(golinters.NewNoLintLint()). @@ -566,6 +606,8 @@ func (m Manager) GetAllLinterConfigsForPreset(p string) []*linter.Config { return ret } +// loadCustomLinterConfig loads the configuration of private linters. +// Private linters are dynamically loaded from .so plugin files. func (m Manager) loadCustomLinterConfig(name string, settings config.CustomLinterSettings) (*linter.Config, error) { analyzer, err := m.getAnalyzerPlugin(settings.Path) if err != nil { @@ -588,6 +630,11 @@ type AnalyzerPlugin interface { GetAnalyzers() []*analysis.Analyzer } +// getAnalyzerPlugin loads a private linter as specified in the config file, +// loads the plugin from a .so file, and returns the 'AnalyzerPlugin' interface +// implemented by the private plugin. +// An error is returned if the private linter cannot be loaded or the linter +// does not implement the AnalyzerPlugin interface. func (m Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) { if !filepath.IsAbs(path) { // resolve non-absolute paths relative to config file's directory diff --git a/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go b/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go index 8882b9300..856eec6b6 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/lint/runner.go @@ -86,7 +86,7 @@ func NewRunner(cfg *config.Config, log logutils.Log, goenv *goutil.Env, es *lint processors.NewNolint(log.Child("nolint"), dbManager, enabledLinters), processors.NewUniqByLine(cfg), - processors.NewDiff(cfg.Issues.Diff, cfg.Issues.DiffFromRevision, cfg.Issues.DiffPatchFilePath), + processors.NewDiff(cfg.Issues.Diff, cfg.Issues.DiffFromRevision, cfg.Issues.DiffPatchFilePath, cfg.Issues.WholeFiles), processors.NewMaxPerFileFromLinter(cfg), processors.NewMaxSameIssues(cfg.Issues.MaxSameIssues, log.Child("max_same_issues"), cfg), processors.NewMaxFromLinter(cfg.Issues.MaxIssuesPerLinter, log.Child("max_from_linter"), cfg), diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go index 35a22ce99..d4e5b5e05 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/codeclimate.go @@ -31,7 +31,7 @@ func NewCodeClimate() *CodeClimate { } func (p CodeClimate) Print(ctx context.Context, issues []result.Issue) error { - codeClimateIssues := []CodeClimateIssue{} + codeClimateIssues := make([]CodeClimateIssue, 0, len(issues)) for i := range issues { issue := &issues[i] codeClimateIssue := CodeClimateIssue{} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go b/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go index 4ebc26685..c7186ac27 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/printers/github.go @@ -13,7 +13,7 @@ type github struct { const defaultGithubSeverity = "error" -// NewGithub output format outputs issues according to Github actions format: +// NewGithub output format outputs issues according to GitHub actions format: // https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message func NewGithub() Printer { return &github{} diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go b/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go index 707a2b17c..1e8cd3052 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/issue.go @@ -92,7 +92,7 @@ func (i *Issue) Fingerprint() string { } hash := md5.New() //nolint:gosec - _, _ = hash.Write([]byte(fmt.Sprintf("%s%s%s", i.Pos.Filename, i.Text, firstLine))) + _, _ = fmt.Fprintf(hash, "%s%s%s", i.Pos.Filename, i.Text, firstLine) return fmt.Sprintf("%X", hash.Sum(nil)) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go index fc4aba4b9..65e01785b 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/diff.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io" - "io/ioutil" "os" "strings" @@ -17,16 +16,18 @@ type Diff struct { onlyNew bool fromRev string patchFilePath string + wholeFiles bool patch string } var _ Processor = Diff{} -func NewDiff(onlyNew bool, fromRev, patchFilePath string) *Diff { +func NewDiff(onlyNew bool, fromRev, patchFilePath string, wholeFiles bool) *Diff { return &Diff{ onlyNew: onlyNew, fromRev: fromRev, patchFilePath: patchFilePath, + wholeFiles: wholeFiles, patch: os.Getenv("GOLANGCI_DIFF_PROCESSOR_PATCH"), } } @@ -42,7 +43,7 @@ func (p Diff) Process(issues []result.Issue) ([]result.Issue, error) { var patchReader io.Reader if p.patchFilePath != "" { - patch, err := ioutil.ReadFile(p.patchFilePath) + patch, err := os.ReadFile(p.patchFilePath) if err != nil { return nil, fmt.Errorf("can't read from patch file %s: %s", p.patchFilePath, err) } @@ -54,6 +55,7 @@ func (p Diff) Process(issues []result.Issue) ([]result.Issue, error) { c := revgrep.Checker{ Patch: patchReader, RevisionFrom: p.fromRev, + WholeFiles: p.wholeFiles, } if err := c.Prepare(); err != nil { return nil, fmt.Errorf("can't prepare diff by revgrep: %s", err) diff --git a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go index 0788a7160..8576b22db 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/result/processors/nolint.go @@ -284,7 +284,7 @@ func (p Nolint) Finish() { return } - unknownLinters := []string{} + unknownLinters := make([]string, 0, len(p.unknownLintersSet)) for name := range p.unknownLintersSet { unknownLinters = append(unknownLinters, name) } diff --git a/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go b/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go index 9628bd80f..b973bbc21 100644 --- a/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go +++ b/vendor/github.com/golangci/golangci-lint/pkg/timeutils/stopwatch.go @@ -15,10 +15,10 @@ const noStagesText = "no stages" type Stopwatch struct { name string startedAt time.Time - stages map[string]time.Duration log logutils.Log - sync.Mutex + stages map[string]time.Duration + mu sync.Mutex } func NewStopwatch(name string, log logutils.Log) *Stopwatch { @@ -36,7 +36,7 @@ type stageDuration struct { } func (s *Stopwatch) stageDurationsSorted() []stageDuration { - stageDurations := []stageDuration{} + stageDurations := make([]stageDuration, 0, len(s.stages)) for n, d := range s.stages { stageDurations = append(stageDurations, stageDuration{ name: n, @@ -56,7 +56,7 @@ func (s *Stopwatch) sprintStages() string { stageDurations := s.stageDurationsSorted() - stagesStrings := []string{} + stagesStrings := make([]string, 0, len(stageDurations)) for _, s := range stageDurations { stagesStrings = append(stagesStrings, fmt.Sprintf("%s: %s", s.name, s.d)) } @@ -110,7 +110,7 @@ func (s *Stopwatch) TrackStage(name string, f func()) { startedAt := time.Now() f() - s.Lock() + s.mu.Lock() s.stages[name] += time.Since(startedAt) - s.Unlock() + s.mu.Unlock() } diff --git a/vendor/github.com/golangci/revgrep/revgrep.go b/vendor/github.com/golangci/revgrep/revgrep.go index d0940d300..f15d601a2 100644 --- a/vendor/github.com/golangci/revgrep/revgrep.go +++ b/vendor/github.com/golangci/revgrep/revgrep.go @@ -31,6 +31,9 @@ type Checker struct { // RevisionFrom check revision starting at, leave blank for auto detection // ignored if patch is set. RevisionFrom string + // WholeFiles indicates that the user wishes to see all issues that comes up + // anywhere in any file that has been changed in this revision or patch. + WholeFiles bool // RevisionTo checks revision finishing at, leave blank for auto detection // ignored if patch is set. RevisionTo string @@ -113,6 +116,10 @@ func (c Checker) IsNewIssue(i InputIssue) (hunkPos int, isNew bool) { return 0, false } + if c.WholeFiles { + return i.Line(), true + } + var ( fpos pos changed bool diff --git a/vendor/github.com/gostaticanalysis/analysisutil/file.go b/vendor/github.com/gostaticanalysis/analysisutil/file.go index 2aeca1d9e..b9b295530 100644 --- a/vendor/github.com/gostaticanalysis/analysisutil/file.go +++ b/vendor/github.com/gostaticanalysis/analysisutil/file.go @@ -3,6 +3,7 @@ package analysisutil import ( "go/ast" "go/token" + "regexp" "golang.org/x/tools/go/analysis" ) @@ -16,3 +17,14 @@ func File(pass *analysis.Pass, pos token.Pos) *ast.File { } return nil } + +var genCommentRegexp = regexp.MustCompile(`^// Code generated .* DO NOT EDIT\.$`) + +// IsGeneratedFile reports whether the file has been generated automatically. +// If file is nil, IsGeneratedFile will return false. +func IsGeneratedFile(file *ast.File) bool { + if file == nil || len(file.Comments) == 0 { + return false + } + return genCommentRegexp.MatchString(file.Comments[0].List[0].Text) +} diff --git a/vendor/github.com/gostaticanalysis/analysisutil/go.mod b/vendor/github.com/gostaticanalysis/analysisutil/go.mod index 5ca7c62b8..94016146b 100644 --- a/vendor/github.com/gostaticanalysis/analysisutil/go.mod +++ b/vendor/github.com/gostaticanalysis/analysisutil/go.mod @@ -1,8 +1,10 @@ module github.com/gostaticanalysis/analysisutil -go 1.12 +go 1.16 require ( - github.com/gostaticanalysis/comment v1.4.1 - golang.org/x/tools v0.0.0-20200820010801-b793a1359eac + github.com/gostaticanalysis/comment v1.4.2 + golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a ) + +retract v0.6.3 diff --git a/vendor/github.com/gostaticanalysis/analysisutil/go.sum b/vendor/github.com/gostaticanalysis/analysisutil/go.sum index 134e67dbd..ebc32d29f 100644 --- a/vendor/github.com/gostaticanalysis/analysisutil/go.sum +++ b/vendor/github.com/gostaticanalysis/analysisutil/go.sum @@ -1,37 +1,51 @@ -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/gostaticanalysis/comment v1.3.0 h1:wTVgynbFu8/nz6SGgywA0TcyIoAVsYc7ai/Zp5xNGlw= -github.com/gostaticanalysis/comment v1.3.0/go.mod h1:xMicKDx7XRXYdVwY9f9wQpDJVnqWxw9wCauCMKp+IBI= -github.com/gostaticanalysis/comment v1.4.1 h1:xHopR5L2lRz6OsjH4R2HG5wRhW9ySl3FsHIvi5pcXwc= -github.com/gostaticanalysis/comment v1.4.1/go.mod h1:ih6ZxzTHLdadaiSnF5WY3dxUoXfXAlTaRzuaNDlSado= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4 h1:d2/eIbH9XjD1fFwD5SHv8x168fjbQ9PB8hvs8DSEC08= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= +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 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3 h1:2oZsfYnKfYzL4I57uYiRFsUf0bqlLkiuw8nnj3+voUA= -golang.org/x/tools v0.0.0-20190307163923-6a08e3108db3/go.mod h1:25r3+/G6/xytQM8iWZKq3Hn0kr0rgFKPUNVEL/dr3z4= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff h1:foic6oVZ4MKltJC6MXzuFZFswE7NCjjtc0Hxbyblawc= -golang.org/x/tools v0.0.0-20200624225443-88f3c62a19ff/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac h1:DugppSxw0LSF8lcjaODPJZoDzq0ElTGskTst3ZaBkHI= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +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 h1:wcmQQeIPy0fYbQMsfxwcnzKbuBLMGaHcN0nbzHbIjdo= +golang.org/x/tools v0.1.1-0.20210302220138-2ac05c832e1a/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= 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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/gostaticanalysis/analysisutil/ssa.go b/vendor/github.com/gostaticanalysis/analysisutil/ssa.go index 517f6b9b4..2e22bbe79 100644 --- a/vendor/github.com/gostaticanalysis/analysisutil/ssa.go +++ b/vendor/github.com/gostaticanalysis/analysisutil/ssa.go @@ -20,7 +20,8 @@ func IfInstr(b *ssa.BasicBlock) *ssa.If { } // Phi returns phi values which are contained in the block b. -func Phi(b *ssa.BasicBlock) (phis []*ssa.Phi) { +func Phi(b *ssa.BasicBlock) []*ssa.Phi { + var phis []*ssa.Phi for _, instr := range b.Instrs { if phi, ok := instr.(*ssa.Phi); ok { phis = append(phis, phi) @@ -29,7 +30,7 @@ func Phi(b *ssa.BasicBlock) (phis []*ssa.Phi) { break } } - return + return phis } // Returns returns a slice of *ssa.Return in the function. @@ -54,10 +55,14 @@ func Returns(v ssa.Value) []*ssa.Return { func returnsInBlock(b *ssa.BasicBlock, done map[*ssa.BasicBlock]bool) (rets []*ssa.Return) { if done[b] { - return + return nil } done[b] = true + if b.Index != 0 && len(b.Preds) == 0 { + return nil + } + if len(b.Instrs) != 0 { switch instr := b.Instrs[len(b.Instrs)-1].(type) { case *ssa.Return: @@ -68,7 +73,8 @@ func returnsInBlock(b *ssa.BasicBlock, done map[*ssa.BasicBlock]bool) (rets []*s for _, s := range b.Succs { rets = append(rets, returnsInBlock(s, done)...) } - return + + return rets } // BinOp returns binary operator values which are contained in the block b. diff --git a/vendor/github.com/gostaticanalysis/analysisutil/ssainspect.go b/vendor/github.com/gostaticanalysis/analysisutil/ssainspect.go index 2f8a16576..b2ae75f24 100644 --- a/vendor/github.com/gostaticanalysis/analysisutil/ssainspect.go +++ b/vendor/github.com/gostaticanalysis/analysisutil/ssainspect.go @@ -2,6 +2,16 @@ package analysisutil import "golang.org/x/tools/go/ssa" +// InspectFuncs inspects functions. +func InspectFuncs(funcs []*ssa.Function, f func(i int, instr ssa.Instruction) bool) { + for _, fun := range funcs { + if len(fun.Blocks) == 0 { + continue + } + new(instrInspector).block(fun.Blocks[0], 0, f) + } +} + // InspectInstr inspects from i-th instruction of start block to succsessor blocks. func InspectInstr(start *ssa.BasicBlock, i int, f func(i int, instr ssa.Instruction) bool) { new(instrInspector).block(start, i, f) diff --git a/vendor/github.com/gostaticanalysis/analysisutil/types.go b/vendor/github.com/gostaticanalysis/analysisutil/types.go index 46b970621..8265efc8e 100644 --- a/vendor/github.com/gostaticanalysis/analysisutil/types.go +++ b/vendor/github.com/gostaticanalysis/analysisutil/types.go @@ -131,6 +131,30 @@ func HasField(s *types.Struct, f *types.Var) bool { return false } +// Field returns field of the struct type. +// If the type is not struct or has not the field, +// Field returns -1, nil. +// If the type is a named type or a pointer type, +// Field calls itself recursively with +// an underlying type or an element type of pointer. +func Field(t types.Type, name string) (int, *types.Var) { + switch t := t.(type) { + case *types.Pointer: + return Field(t.Elem(), name) + case *types.Named: + return Field(t.Underlying(), name) + case *types.Struct: + for i := 0; i < t.NumFields(); i++ { + f := t.Field(i) + if f.Name() == name { + return i, f + } + } + } + + return -1, nil +} + func TypesInfo(info ...*types.Info) *types.Info { if len(info) == 0 { return nil @@ -198,11 +222,7 @@ func mergeTypesInfo(i1, i2 *types.Info) { } // Under returns the most bottom underlying type. +// Deprecated: (types.Type).Underlying returns same value of it. func Under(t types.Type) types.Type { - switch t := t.(type) { - case *types.Named: - return Under(t.Underlying()) - default: - return t - } + return t.Underlying() } diff --git a/vendor/github.com/gostaticanalysis/comment/comment.go b/vendor/github.com/gostaticanalysis/comment/comment.go index 2fe67fa96..79cb09382 100644 --- a/vendor/github.com/gostaticanalysis/comment/comment.go +++ b/vendor/github.com/gostaticanalysis/comment/comment.go @@ -123,25 +123,30 @@ func (maps Maps) IgnoreLine(fset *token.FileSet, line int, check string) bool { // hasIgnoreCheck returns true if the provided CommentGroup starts with a comment // of the form "//lint:ignore Check1[,Check2,...,CheckN] reason" and one of the -// checks matches the provided check. The *ast.CommentGroup is checked directly -// rather than using "cg.Text()" because, starting in Go 1.15, the "cg.Text()" call -// no longer returns directive-style comments (see https://github.com/golang/go/issues/37974). +// checks matches the provided check. +// +// The *ast.CommentGroup is checked directly rather than using "cg.Text()" because, +// starting in Go 1.15, the "cg.Text()" call no longer returns directive-style +// comments (see https://github.com/golang/go/issues/37974). func hasIgnoreCheck(cg *ast.CommentGroup, check string) bool { - if !strings.HasPrefix(cg.List[0].Text, "//") { - return false - } + for _, list := range cg.List { + if !strings.HasPrefix(list.Text, "//") { + continue + } - s := strings.TrimSpace(cg.List[0].Text[2:]) - txt := strings.Split(s, " ") - if len(txt) < 3 || txt[0] != "lint:ignore" { - return false - } + s := strings.TrimSpace(list.Text[2:]) // list.Text[2:]: trim "//" + txt := strings.Split(s, " ") + if len(txt) < 3 || txt[0] != "lint:ignore" { + continue + } - checks := strings.Split(txt[1], ",") - for i := range checks { - if check == checks[i] { - return true + checks := strings.Split(txt[1], ",") // txt[1]: trim "lint:ignore" + for i := range checks { + if check == checks[i] { + return true + } } } + return false } diff --git a/vendor/github.com/gostaticanalysis/comment/go.mod b/vendor/github.com/gostaticanalysis/comment/go.mod index 275568113..501f786a5 100644 --- a/vendor/github.com/gostaticanalysis/comment/go.mod +++ b/vendor/github.com/gostaticanalysis/comment/go.mod @@ -1,8 +1,9 @@ module github.com/gostaticanalysis/comment -go 1.12 +go 1.15 require ( - github.com/google/go-cmp v0.5.1 - golang.org/x/tools v0.0.0-20200820010801-b793a1359eac + github.com/google/go-cmp v0.5.4 + github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4 + golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d ) diff --git a/vendor/github.com/gostaticanalysis/comment/go.sum b/vendor/github.com/gostaticanalysis/comment/go.sum index 425807ce1..b0670acd6 100644 --- a/vendor/github.com/gostaticanalysis/comment/go.sum +++ b/vendor/github.com/gostaticanalysis/comment/go.sum @@ -1,24 +1,48 @@ -github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4 h1:d2/eIbH9XjD1fFwD5SHv8x168fjbQ9PB8hvs8DSEC08= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= +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 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/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/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac h1:DugppSxw0LSF8lcjaODPJZoDzq0ElTGskTst3ZaBkHI= -golang.org/x/tools v0.0.0-20200820010801-b793a1359eac/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d h1:TWciQgVQK3rhquuBn8vdgrXzMaeTaRd/DVJyTONxE7I= +golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d/go.mod h1:9bzcO0MWcOuT0tm1iBGzDVPshzfwoVvREIui8C+MHqU= 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 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/gostaticanalysis/comment/passes/commentmap/commentmap.go b/vendor/github.com/gostaticanalysis/comment/passes/commentmap/commentmap.go index 9266d9895..1b60a160c 100644 --- a/vendor/github.com/gostaticanalysis/comment/passes/commentmap/commentmap.go +++ b/vendor/github.com/gostaticanalysis/comment/passes/commentmap/commentmap.go @@ -3,8 +3,9 @@ package commentmap import ( "reflect" - "github.com/gostaticanalysis/comment" "golang.org/x/tools/go/analysis" + + "github.com/gostaticanalysis/comment" ) var Analyzer = &analysis.Analyzer{ diff --git a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go b/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go index ac0177f6e..a142a6744 100644 --- a/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go +++ b/vendor/github.com/jingyugao/rowserrcheck/passes/rowserr/rowserr.go @@ -3,9 +3,7 @@ package rowserr import ( "go/ast" "go/types" - "strconv" - "github.com/gostaticanalysis/analysisutil" "golang.org/x/tools/go/analysis" "golang.org/x/tools/go/analysis/passes/buildssa" "golang.org/x/tools/go/ssa" @@ -29,11 +27,12 @@ const ( ) type runner struct { - pass *analysis.Pass - rowsTyp *types.Pointer - rowsObj types.Object - skipFile map[*ast.File]bool - sqlPkgs []string + pass *analysis.Pass + rowsTyp *types.Pointer + rowsInterface *types.Interface + rowsObj types.Object + skipFile map[*ast.File]bool + sqlPkgs []string } func NewRun(pkgs ...string) func(pass *analysis.Pass) (interface{}, error) { @@ -66,7 +65,6 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) { // skip checking return } - r.rowsObj = rowsType.Object() if r.rowsObj == nil { // skip checking @@ -78,15 +76,15 @@ func (r runner) run(pass *analysis.Pass, pkgPath string) { return } + rowsInterface, ok := r.rowsObj.Type().Underlying().(*types.Interface) + if ok { + r.rowsInterface = rowsInterface + } + r.rowsTyp = types.NewPointer(resNamed) r.skipFile = map[*ast.File]bool{} for _, f := range funcs { - if r.noImportedDBSQL(f) { - // skip this - continue - } - // skip if the function is just referenced var isRefFunc bool @@ -139,10 +137,6 @@ func (r *runner) errCallMissing(b *ssa.BasicBlock, i int) (ret bool) { switch c := aref.(type) { case *ssa.MakeClosure: f := c.Fn.(*ssa.Function) - if r.noImportedDBSQL(f) { - // skip this - continue - } called := r.isClosureCalled(c) if r.calledInFunc(f, called) { return true @@ -203,17 +197,18 @@ func (r *runner) getCallReturnsRow(instr ssa.Instruction) (*ssa.Call, bool) { } res := call.Call.Signature().Results() - flag := false for i := 0; i < res.Len(); i++ { - flag = flag || types.Identical(res.At(i).Type(), r.rowsTyp) + typeToCheck := res.At(i).Type() + if types.Identical(typeToCheck, r.rowsTyp) { + return call, true + } + if r.rowsInterface != nil && types.Implements(typeToCheck, r.rowsInterface) { + return call, true + } } - if !flag { - return nil, false - } - - return call, true + return nil, false } func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) { @@ -222,10 +217,16 @@ func (r *runner) getRowsVal(instr ssa.Instruction) (ssa.Value, bool) { if len(instr.Call.Args) == 1 && types.Identical(instr.Call.Args[0].Type(), r.rowsTyp) { return instr.Call.Args[0], true } + if len(instr.Call.Args) == 1 && r.rowsInterface != nil && types.Implements(instr.Call.Args[0].Type(), r.rowsInterface) { + return instr.Call.Args[0], true + } case ssa.Value: if types.Identical(instr.Type(), r.rowsTyp) { return instr, true } + if r.rowsInterface != nil && types.Implements(instr.Type(), r.rowsInterface) { + return instr, true + } default: } @@ -250,10 +251,16 @@ func (r *runner) isErrCall(ccall ssa.Instruction) bool { if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod { return true } + if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod { + return true + } case *ssa.Call: if ccall.Call.Value != nil && ccall.Call.Value.Name() == errMethod { return true } + if ccall.Call.Method != nil && ccall.Call.Method.Name() == errMethod { + return true + } } return false @@ -270,40 +277,6 @@ func (r *runner) isClosureCalled(c *ssa.MakeClosure) bool { return false } -func (r *runner) noImportedDBSQL(f *ssa.Function) (ret bool) { - obj := f.Object() - if obj == nil { - return false - } - - file := analysisutil.File(r.pass, obj.Pos()) - if file == nil { - return false - } - - if skip, has := r.skipFile[file]; has { - return skip - } - defer func() { - r.skipFile[file] = ret - }() - - for _, impt := range file.Imports { - path, err := strconv.Unquote(impt.Path.Value) - if err != nil { - continue - } - path = analysisutil.RemoveVendor(path) - for _, pkg := range r.sqlPkgs { - if pkg == path { - return false - } - } - } - - return true -} - func (r *runner) calledInFunc(f *ssa.Function, called bool) bool { for _, b := range f.Blocks { for i, instr := range b.Instrs { diff --git a/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go b/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go index 31f6f2946..0e359f76d 100644 --- a/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go +++ b/vendor/github.com/kunwardeep/paralleltest/pkg/paralleltest/paralleltest.go @@ -42,7 +42,8 @@ func run(pass *analysis.Pass) (interface{}, error) { var rangeNode ast.Node // Check runs for test functions only - if !isTestFunction(funcDecl) { + isTest, testVar := isTestFunction(funcDecl) + if !isTest { return } @@ -53,16 +54,19 @@ func run(pass *analysis.Pass) (interface{}, error) { ast.Inspect(v, func(n ast.Node) bool { // Check if the test method is calling t.parallel if !funcHasParallelMethod { - funcHasParallelMethod = methodParallelIsCalledInTestFunction(n) + funcHasParallelMethod = methodParallelIsCalledInTestFunction(n, testVar) } // Check if the t.Run within the test function is calling t.parallel - if methodRunIsCalledInTestFunction(n) { + if methodRunIsCalledInTestFunction(n, testVar) { + // n is a call to t.Run; find out the name of the subtest's *testing.T parameter. + innerTestVar := getRunCallbackParameterName(n) + hasParallel := false numberOfTestRun++ ast.Inspect(v, func(p ast.Node) bool { if !hasParallel { - hasParallel = methodParallelIsCalledInTestFunction(p) + hasParallel = methodParallelIsCalledInTestFunction(p, innerTestVar) } return true }) @@ -81,12 +85,15 @@ func run(pass *analysis.Pass) (interface{}, error) { // nolint: gocritic switch r := n.(type) { case *ast.ExprStmt: - if methodRunIsCalledInRangeStatement(r.X) { + if methodRunIsCalledInRangeStatement(r.X, testVar) { + // r.X is a call to t.Run; find out the name of the subtest's *testing.T parameter. + innerTestVar := getRunCallbackParameterName(r.X) + rangeStatementOverTestCasesExists = true testRunLoopIdentifier = methodRunFirstArgumentObjectName(r.X) if !rangeStatementHasParallelMethod { - rangeStatementHasParallelMethod = methodParallelIsCalledInMethodRun(r.X) + rangeStatementHasParallelMethod = methodParallelIsCalledInMethodRun(r.X, innerTestVar) } } } @@ -165,7 +172,7 @@ func getLeftAndRightIdentifier(s ast.Stmt) (string, string) { return leftIdentifier, rightIdentifier } -func methodParallelIsCalledInMethodRun(node ast.Node) bool { +func methodParallelIsCalledInMethodRun(node ast.Node, testVar string) bool { var methodParallelCalled bool // nolint: gocritic switch callExp := node.(type) { @@ -174,7 +181,7 @@ func methodParallelIsCalledInMethodRun(node ast.Node) bool { if !methodParallelCalled { ast.Inspect(arg, func(n ast.Node) bool { if !methodParallelCalled { - methodParallelCalled = methodParallelIsCalledInRunMethod(n) + methodParallelCalled = methodParallelIsCalledInRunMethod(n, testVar) return true } return false @@ -185,32 +192,61 @@ func methodParallelIsCalledInMethodRun(node ast.Node) bool { return methodParallelCalled } -func methodParallelIsCalledInRunMethod(node ast.Node) bool { - return exprCallHasMethod(node, "Parallel") +func methodParallelIsCalledInRunMethod(node ast.Node, testVar string) bool { + return exprCallHasMethod(node, testVar, "Parallel") } -func methodParallelIsCalledInTestFunction(node ast.Node) bool { - return exprCallHasMethod(node, "Parallel") +func methodParallelIsCalledInTestFunction(node ast.Node, testVar string) bool { + return exprCallHasMethod(node, testVar, "Parallel") } -func methodRunIsCalledInRangeStatement(node ast.Node) bool { - return exprCallHasMethod(node, "Run") +func methodRunIsCalledInRangeStatement(node ast.Node, testVar string) bool { + return exprCallHasMethod(node, testVar, "Run") } -func methodRunIsCalledInTestFunction(node ast.Node) bool { - return exprCallHasMethod(node, "Run") +func methodRunIsCalledInTestFunction(node ast.Node, testVar string) bool { + return exprCallHasMethod(node, testVar, "Run") } -func exprCallHasMethod(node ast.Node, methodName string) bool { +func exprCallHasMethod(node ast.Node, receiverName, methodName string) bool { // nolint: gocritic switch n := node.(type) { case *ast.CallExpr: if fun, ok := n.Fun.(*ast.SelectorExpr); ok { - return fun.Sel.Name == methodName + if receiver, ok := fun.X.(*ast.Ident); ok { + return receiver.Name == receiverName && fun.Sel.Name == methodName + } } } return false } +// In an expression of the form t.Run(x, func(q *testing.T) {...}), return the +// value "q". In _most_ code, the name is probably t, but we shouldn't just +// assume. +func getRunCallbackParameterName(node ast.Node) string { + if n, ok := node.(*ast.CallExpr); ok { + if len(n.Args) < 2 { + // We want argument #2, but this call doesn't have two + // arguments. Maybe it's not really t.Run. + return "" + } + funcArg := n.Args[1] + if fun, ok := funcArg.(*ast.FuncLit); ok { + if len(fun.Type.Params.List) < 1 { + // Subtest function doesn't have any parameters. + return "" + } + firstArg := fun.Type.Params.List[0] + // We'll assume firstArg.Type is *testing.T. + if len(firstArg.Names) < 1 { + return "" + } + return firstArg.Names[0].Name + } + } + return "" +} + // Gets the object name `tc` from method t.Run(tc.Foo, func(t *testing.T) func methodRunFirstArgumentObjectName(node ast.Node) string { // nolint: gocritic @@ -227,18 +263,19 @@ func methodRunFirstArgumentObjectName(node ast.Node) string { return "" } -// Checks if the function has the param type *testing.T) -func isTestFunction(funcDecl *ast.FuncDecl) bool { +// Checks if the function has the param type *testing.T; if it does, then the +// parameter name is returned, too. +func isTestFunction(funcDecl *ast.FuncDecl) (bool, string) { testMethodPackageType := "testing" testMethodStruct := "T" testPrefix := "Test" if !strings.HasPrefix(funcDecl.Name.Name, testPrefix) { - return false + return false, "" } if funcDecl.Type.Params != nil && len(funcDecl.Type.Params.List) != 1 { - return false + return false, "" } param := funcDecl.Type.Params.List[0] @@ -246,11 +283,11 @@ func isTestFunction(funcDecl *ast.FuncDecl) bool { if selectExpr, ok := starExp.X.(*ast.SelectorExpr); ok { if selectExpr.Sel.Name == testMethodStruct { if s, ok := selectExpr.X.(*ast.Ident); ok { - return s.Name == testMethodPackageType + return s.Name == testMethodPackageType, param.Names[0].Name } } } } - return false + return false, "" } diff --git a/vendor/github.com/mattn/go-colorable/.travis.yml b/vendor/github.com/mattn/go-colorable/.travis.yml deleted file mode 100644 index 7942c565c..000000000 --- a/vendor/github.com/mattn/go-colorable/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) - diff --git a/vendor/github.com/mattn/go-colorable/README.md b/vendor/github.com/mattn/go-colorable/README.md index e055952b6..ca0483711 100644 --- a/vendor/github.com/mattn/go-colorable/README.md +++ b/vendor/github.com/mattn/go-colorable/README.md @@ -1,6 +1,6 @@ # go-colorable -[![Build Status](https://travis-ci.org/mattn/go-colorable.svg?branch=master)](https://travis-ci.org/mattn/go-colorable) +[![Build Status](https://github.com/mattn/go-colorable/workflows/test/badge.svg)](https://github.com/mattn/go-colorable/actions?query=workflow%3Atest) [![Codecov](https://codecov.io/gh/mattn/go-colorable/branch/master/graph/badge.svg)](https://codecov.io/gh/mattn/go-colorable) [![GoDoc](https://godoc.org/github.com/mattn/go-colorable?status.svg)](http://godoc.org/github.com/mattn/go-colorable) [![Go Report Card](https://goreportcard.com/badge/mattn/go-colorable)](https://goreportcard.com/report/mattn/go-colorable) diff --git a/vendor/github.com/mattn/go-colorable/colorable_appengine.go b/vendor/github.com/mattn/go-colorable/colorable_appengine.go index 1f7806fe1..416d1bbbf 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_appengine.go +++ b/vendor/github.com/mattn/go-colorable/colorable_appengine.go @@ -1,3 +1,4 @@ +//go:build appengine // +build appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_others.go b/vendor/github.com/mattn/go-colorable/colorable_others.go index 08cbd1e0f..766d94603 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_others.go +++ b/vendor/github.com/mattn/go-colorable/colorable_others.go @@ -1,5 +1,5 @@ -// +build !windows -// +build !appengine +//go:build !windows && !appengine +// +build !windows,!appengine package colorable diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index 41215d7fc..1846ad5ab 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package colorable @@ -452,18 +452,22 @@ func (w *Writer) Write(data []byte) (n int, err error) { } else { er = bytes.NewReader(data) } - var bw [1]byte + var plaintext bytes.Buffer loop: for { c1, err := er.ReadByte() if err != nil { + plaintext.WriteTo(w.out) break loop } if c1 != 0x1b { - bw[0] = c1 - w.out.Write(bw[:]) + plaintext.WriteByte(c1) continue } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } c2, err := er.ReadByte() if err != nil { break loop diff --git a/vendor/github.com/mattn/go-colorable/go.mod b/vendor/github.com/mattn/go-colorable/go.mod index 1e590b819..27351c027 100644 --- a/vendor/github.com/mattn/go-colorable/go.mod +++ b/vendor/github.com/mattn/go-colorable/go.mod @@ -1,8 +1,8 @@ module github.com/mattn/go-colorable require ( - github.com/mattn/go-isatty v0.0.12 - golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae // indirect + github.com/mattn/go-isatty v0.0.14 + golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 // indirect ) go 1.13 diff --git a/vendor/github.com/mattn/go-colorable/go.sum b/vendor/github.com/mattn/go-colorable/go.sum index cf5b95d97..40c33b333 100644 --- a/vendor/github.com/mattn/go-colorable/go.sum +++ b/vendor/github.com/mattn/go-colorable/go.sum @@ -1,5 +1,5 @@ -github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6 h1:foEbQz/B0Oz6YIqu/69kfXPYeFQAuuMYFkjaqXzl5Wo= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/vendor/github.com/mattn/go-colorable/noncolorable.go b/vendor/github.com/mattn/go-colorable/noncolorable.go index 95f2c6be2..3df68f360 100644 --- a/vendor/github.com/mattn/go-colorable/noncolorable.go +++ b/vendor/github.com/mattn/go-colorable/noncolorable.go @@ -18,18 +18,22 @@ func NewNonColorable(w io.Writer) io.Writer { // Write writes data on console func (w *NonColorable) Write(data []byte) (n int, err error) { er := bytes.NewReader(data) - var bw [1]byte + var plaintext bytes.Buffer loop: for { c1, err := er.ReadByte() if err != nil { + plaintext.WriteTo(w.out) break loop } if c1 != 0x1b { - bw[0] = c1 - w.out.Write(bw[:]) + plaintext.WriteByte(c1) continue } + _, err = plaintext.WriteTo(w.out) + if err != nil { + break loop + } c2, err := er.ReadByte() if err != nil { break loop diff --git a/vendor/github.com/mattn/go-isatty/.travis.yml b/vendor/github.com/mattn/go-isatty/.travis.yml deleted file mode 100644 index 604314dd4..000000000 --- a/vendor/github.com/mattn/go-isatty/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip - -before_install: - - go get -t -v ./... - -script: - - ./go.test.sh - -after_success: - - bash <(curl -s https://codecov.io/bash) diff --git a/vendor/github.com/mattn/go-isatty/go.mod b/vendor/github.com/mattn/go-isatty/go.mod index 605c4c221..c9a20b7f3 100644 --- a/vendor/github.com/mattn/go-isatty/go.mod +++ b/vendor/github.com/mattn/go-isatty/go.mod @@ -2,4 +2,4 @@ module github.com/mattn/go-isatty go 1.12 -require golang.org/x/sys v0.0.0-20200116001909-b77594299b42 +require golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c diff --git a/vendor/github.com/mattn/go-isatty/isatty_bsd.go b/vendor/github.com/mattn/go-isatty/isatty_bsd.go index 711f28808..39bbcf00f 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_bsd.go +++ b/vendor/github.com/mattn/go-isatty/isatty_bsd.go @@ -1,3 +1,4 @@ +//go:build (darwin || freebsd || openbsd || netbsd || dragonfly) && !appengine // +build darwin freebsd openbsd netbsd dragonfly // +build !appengine diff --git a/vendor/github.com/mattn/go-isatty/isatty_others.go b/vendor/github.com/mattn/go-isatty/isatty_others.go index ff714a376..31503226f 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_others.go +++ b/vendor/github.com/mattn/go-isatty/isatty_others.go @@ -1,4 +1,5 @@ -// +build appengine js nacl +//go:build appengine || js || nacl || wasm +// +build appengine js nacl wasm package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_plan9.go b/vendor/github.com/mattn/go-isatty/isatty_plan9.go index c5b6e0c08..bae7f9bb3 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_plan9.go +++ b/vendor/github.com/mattn/go-isatty/isatty_plan9.go @@ -1,3 +1,4 @@ +//go:build plan9 // +build plan9 package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_solaris.go b/vendor/github.com/mattn/go-isatty/isatty_solaris.go index bdd5c79a0..0c3acf2dc 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_solaris.go +++ b/vendor/github.com/mattn/go-isatty/isatty_solaris.go @@ -1,5 +1,5 @@ -// +build solaris -// +build !appengine +//go:build solaris && !appengine +// +build solaris,!appengine package isatty @@ -8,10 +8,9 @@ import ( ) // IsTerminal returns true if the given file descriptor is a terminal. -// see: http://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libbc/libc/gen/common/isatty.c +// see: https://src.illumos.org/source/xref/illumos-gate/usr/src/lib/libc/port/gen/isatty.c func IsTerminal(fd uintptr) bool { - var termio unix.Termio - err := unix.IoctlSetTermio(int(fd), unix.TCGETA, &termio) + _, err := unix.IoctlGetTermio(int(fd), unix.TCGETA) return err == nil } diff --git a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go index 31a1ca973..67787657f 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_tcgets.go +++ b/vendor/github.com/mattn/go-isatty/isatty_tcgets.go @@ -1,4 +1,5 @@ -// +build linux aix +//go:build (linux || aix || zos) && !appengine +// +build linux aix zos // +build !appengine package isatty diff --git a/vendor/github.com/mattn/go-isatty/isatty_windows.go b/vendor/github.com/mattn/go-isatty/isatty_windows.go index 1fa869154..8e3c99171 100644 --- a/vendor/github.com/mattn/go-isatty/isatty_windows.go +++ b/vendor/github.com/mattn/go-isatty/isatty_windows.go @@ -1,5 +1,5 @@ -// +build windows -// +build !appengine +//go:build windows && !appengine +// +build windows,!appengine package isatty @@ -76,7 +76,7 @@ func isCygwinPipeName(name string) bool { } // getFileNameByHandle use the undocomented ntdll NtQueryObject to get file full name from file handler -// since GetFileInformationByHandleEx is not avilable under windows Vista and still some old fashion +// since GetFileInformationByHandleEx is not available under windows Vista and still some old fashion // guys are using Windows XP, this is a workaround for those guys, it will also work on system from // Windows vista to 10 // see https://stackoverflow.com/a/18792477 for details diff --git a/vendor/github.com/mattn/go-isatty/renovate.json b/vendor/github.com/mattn/go-isatty/renovate.json deleted file mode 100644 index 5ae9d96b7..000000000 --- a/vendor/github.com/mattn/go-isatty/renovate.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": [ - "config:base" - ], - "postUpdateOptions": [ - "gomodTidy" - ] -} diff --git a/vendor/github.com/mgechev/dots/resolve.go b/vendor/github.com/mgechev/dots/resolve.go index 309ba18ad..114534be8 100644 --- a/vendor/github.com/mgechev/dots/resolve.go +++ b/vendor/github.com/mgechev/dots/resolve.go @@ -29,7 +29,7 @@ func flatten(arr [][]string) []string { // The final result is the set of all files from the selected directories subtracted with // the files in the skip slice. func Resolve(includePatterns, skipPatterns []string) ([]string, error) { - skip, err := resolvePatterns(skipPatterns) + skip, err := resolvePatternsIgnoringErrors(skipPatterns) filter := newPathFilter(flatten(skip)) if err != nil { return nil, err @@ -57,7 +57,7 @@ func Resolve(includePatterns, skipPatterns []string) ([]string, error) { // the files in the skip slice. The difference between `Resolve` and `ResolvePackages` // is that `ResolvePackages` preserves the package structure in the nested slices. func ResolvePackages(includePatterns, skipPatterns []string) ([][]string, error) { - skip, err := resolvePatterns(skipPatterns) + skip, err := resolvePatternsIgnoringErrors(skipPatterns) filter := newPathFilter(flatten(skip)) if err != nil { return nil, err @@ -136,6 +136,18 @@ func resolvePatterns(patterns []string) ([][]string, error) { return files, nil } +func resolvePatternsIgnoringErrors(patterns []string) ([][]string, error) { + var files [][]string + for _, pattern := range patterns { + f, err := resolvePattern(pattern) + if err != nil { + continue + } + files = append(files, f...) + } + return files, nil +} + func resolvePattern(pattern string) ([][]string, error) { // dirsRun, filesRun, and pkgsRun indicate whether golint is applied to // directory, file or package targets. The distinction affects which diff --git a/vendor/github.com/mgechev/revive/config/config.go b/vendor/github.com/mgechev/revive/config/config.go index 298c0bdf5..e98aaf0a0 100644 --- a/vendor/github.com/mgechev/revive/config/config.go +++ b/vendor/github.com/mgechev/revive/config/config.go @@ -105,30 +105,6 @@ func getFormatters() map[string]lint.Formatter { // GetLintingRules yields the linting rules that must be applied by the linter func GetLintingRules(config *lint.Config) ([]lint.Rule, error) { - if config.EnableAllRules { - return getAllRules(config) - } - - return getEnabledRules(config) -} - -// getAllRules yields the list of all available rules except those disabled by configuration -func getAllRules(config *lint.Config) ([]lint.Rule, error) { - lintingRules := []lint.Rule{} - for _, r := range allRules { - ruleConf := config.Rules[r.Name()] - if ruleConf.Disabled { - continue // skip disabled rules - } - - lintingRules = append(lintingRules, r) - } - - return lintingRules, nil -} - -// getEnabledRules yields the list of rules that are enabled by configuration -func getEnabledRules(config *lint.Config) ([]lint.Rule, error) { rulesMap := map[string]lint.Rule{} for _, r := range allRules { rulesMap[r.Name()] = r @@ -165,9 +141,27 @@ func parseConfig(path string) (*lint.Config, error) { } func normalizeConfig(config *lint.Config) { + const defaultConfidence = 0.8 if config.Confidence == 0 { - config.Confidence = 0.8 + config.Confidence = defaultConfidence } + + if len(config.Rules) == 0 { + config.Rules = map[string]lint.RuleConfig{} + } + if config.EnableAllRules { + // Add to the configuration all rules not yet present in it + for _, rule := range allRules { + ruleName := rule.Name() + _, alreadyInConf := config.Rules[ruleName] + if alreadyInConf { + continue + } + // Add the rule with an empty conf for + config.Rules[ruleName] = lint.RuleConfig{} + } + } + severity := config.Severity if severity != "" { for k, v := range config.Rules { diff --git a/vendor/github.com/mgechev/revive/lint/file.go b/vendor/github.com/mgechev/revive/lint/file.go index ee29c1dae..7396f2859 100644 --- a/vendor/github.com/mgechev/revive/lint/file.go +++ b/vendor/github.com/mgechev/revive/lint/file.go @@ -91,10 +91,7 @@ func (f *File) IsUntypedConst(expr ast.Expr) (defType string, ok bool) { } func (f *File) isMain() bool { - if f.AST.Name.Name == "main" { - return true - } - return false + return f.AST.Name.Name == "main" } const directiveSpecifyDisableReason = "specify-disable-reason" diff --git a/vendor/github.com/mgechev/revive/rule/add-constant.go b/vendor/github.com/mgechev/revive/rule/add-constant.go index bc6268ee1..4d1579053 100644 --- a/vendor/github.com/mgechev/revive/rule/add-constant.go +++ b/vendor/github.com/mgechev/revive/rule/add-constant.go @@ -82,7 +82,7 @@ func (r *AddConstantRule) Apply(file *lint.File, arguments lint.Arguments) []lin failures = append(failures, failure) } - w := lintAddConstantRule{onFailure: onFailure, strLits: make(map[string]int, 0), strLitLimit: strLitLimit, whiteLst: whiteList} + w := lintAddConstantRule{onFailure: onFailure, strLits: make(map[string]int), strLitLimit: strLitLimit, whiteLst: whiteList} ast.Walk(w, file.AST) diff --git a/vendor/github.com/mgechev/revive/rule/empty-block.go b/vendor/github.com/mgechev/revive/rule/empty-block.go index fbec4d93c..e505fde6e 100644 --- a/vendor/github.com/mgechev/revive/rule/empty-block.go +++ b/vendor/github.com/mgechev/revive/rule/empty-block.go @@ -17,7 +17,7 @@ func (r *EmptyBlockRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure failures = append(failures, failure) } - w := lintEmptyBlock{make(map[*ast.BlockStmt]bool, 0), onFailure} + w := lintEmptyBlock{make(map[*ast.BlockStmt]bool), onFailure} ast.Walk(w, file.AST) return failures } diff --git a/vendor/github.com/mgechev/revive/rule/file-header.go b/vendor/github.com/mgechev/revive/rule/file-header.go index 7855c85ad..8fc89e84e 100644 --- a/vendor/github.com/mgechev/revive/rule/file-header.go +++ b/vendor/github.com/mgechev/revive/rule/file-header.go @@ -42,9 +42,9 @@ func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint comment := "" for _, c := range g.List { text := c.Text - if multiRegexp.Match([]byte(text)) { + if multiRegexp.MatchString(text) { text = text[2 : len(text)-2] - } else if singleRegexp.Match([]byte(text)) { + } else if singleRegexp.MatchString(text) { text = text[2:] } comment += text @@ -55,7 +55,7 @@ func (r *FileHeaderRule) Apply(file *lint.File, arguments lint.Arguments) []lint panic(err.Error()) } - if !regex.Match([]byte(comment)) { + if !regex.MatchString(comment) { return failure } return nil diff --git a/vendor/github.com/mgechev/revive/rule/max-public-structs.go b/vendor/github.com/mgechev/revive/rule/max-public-structs.go index aa15628f0..b38c8b745 100644 --- a/vendor/github.com/mgechev/revive/rule/max-public-structs.go +++ b/vendor/github.com/mgechev/revive/rule/max-public-structs.go @@ -63,7 +63,6 @@ func (w *lintMaxPublicStructs) Visit(n ast.Node) ast.Visitor { if strings.ToUpper(first) == first { w.current++ } - break } return w } diff --git a/vendor/github.com/mgechev/revive/rule/time-naming.go b/vendor/github.com/mgechev/revive/rule/time-naming.go index a93f4b5ae..24a612e4d 100644 --- a/vendor/github.com/mgechev/revive/rule/time-naming.go +++ b/vendor/github.com/mgechev/revive/rule/time-naming.go @@ -76,10 +76,12 @@ func (w *lintTimeNames) Visit(node ast.Node) ast.Visitor { // timeSuffixes is a list of name suffixes that imply a time unit. // This is not an exhaustive list. var timeSuffixes = []string{ - "Sec", "Secs", "Seconds", + "Hour", "Hours", + "Min", "Mins", "Minutes", "Minute", + "Sec", "Secs", "Seconds", "Second", "Msec", "Msecs", - "Milli", "Millis", "Milliseconds", - "Usec", "Usecs", "Microseconds", + "Milli", "Millis", "Milliseconds", "Millisecond", + "Usec", "Usecs", "Microseconds", "Microsecond", "MS", "Ms", } diff --git a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md index 1955f2878..9fe803a5e 100644 --- a/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md +++ b/vendor/github.com/mitchellh/mapstructure/CHANGELOG.md @@ -1,6 +1,12 @@ -## unreleased +## 1.4.2 -* Fix regression where `*time.Time` value would be set to empty and not be sent +* Custom name matchers to support any sort of casing, formatting, etc. for + field names. [GH-250] +* Fix possible panic in ComposeDecodeHookFunc [GH-251] + +## 1.4.1 + +* Fix regression where `*time.Time` value would be set to empty and not be sent to decode hooks properly [GH-232] ## 1.4.0 diff --git a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go index 92e6f76ff..4d4bbc733 100644 --- a/vendor/github.com/mitchellh/mapstructure/decode_hooks.go +++ b/vendor/github.com/mitchellh/mapstructure/decode_hooks.go @@ -62,7 +62,8 @@ func DecodeHookExec( func ComposeDecodeHookFunc(fs ...DecodeHookFunc) DecodeHookFunc { return func(f reflect.Value, t reflect.Value) (interface{}, error) { var err error - var data interface{} + data := f.Interface() + newFrom := f for _, f1 := range fs { data, err = DecodeHookExec(f1, newFrom, t) diff --git a/vendor/github.com/mitchellh/mapstructure/mapstructure.go b/vendor/github.com/mitchellh/mapstructure/mapstructure.go index 3643901f5..dcee0f2d6 100644 --- a/vendor/github.com/mitchellh/mapstructure/mapstructure.go +++ b/vendor/github.com/mitchellh/mapstructure/mapstructure.go @@ -192,7 +192,7 @@ type DecodeHookFuncType func(reflect.Type, reflect.Type, interface{}) (interface // source and target types. type DecodeHookFuncKind func(reflect.Kind, reflect.Kind, interface{}) (interface{}, error) -// DecodeHookFuncRaw is a DecodeHookFunc which has complete access to both the source and target +// DecodeHookFuncValue is a DecodeHookFunc which has complete access to both the source and target // values. type DecodeHookFuncValue func(from reflect.Value, to reflect.Value) (interface{}, error) @@ -258,6 +258,11 @@ type DecoderConfig struct { // The tag name that mapstructure reads for field names. This // defaults to "mapstructure" TagName string + + // MatchName is the function used to match the map key to the struct + // field name or tag. Defaults to `strings.EqualFold`. This can be used + // to implement case-sensitive tag values, support snake casing, etc. + MatchName func(mapKey, fieldName string) bool } // A Decoder takes a raw interface value and turns it into structured @@ -376,6 +381,10 @@ func NewDecoder(config *DecoderConfig) (*Decoder, error) { config.TagName = "mapstructure" } + if config.MatchName == nil { + config.MatchName = strings.EqualFold + } + result := &Decoder{ config: config, } @@ -1340,7 +1349,7 @@ func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) e continue } - if strings.EqualFold(mK, fieldName) { + if d.config.MatchName(mK, fieldName) { rawMapKey = dataValKey rawMapVal = dataVal.MapIndex(dataValKey) break diff --git a/vendor/github.com/nakabonne/nestif/README.md b/vendor/github.com/nakabonne/nestif/README.md index ede411f73..37d370175 100644 --- a/vendor/github.com/nakabonne/nestif/README.md +++ b/vendor/github.com/nakabonne/nestif/README.md @@ -2,16 +2,22 @@ [![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](http://godoc.org/github.com/nakabonne/nestif) -Reports deeply nested if statements in Go code, by calculating its complexities based on the rules defined by the [Cognitive Complexity white paper by G. Ann Campbell](https://www.sonarsource.com/docs/CognitiveComplexity.pdf). +Reports complex nested if statements in Go code, by calculating its complexities based on the rules defined by the [Cognitive Complexity white paper by G. Ann Campbell](https://www.sonarsource.com/docs/CognitiveComplexity.pdf). It helps you find if statements that make your code hard to read, and clarifies which parts to refactor. ## Installation +### By go get + ``` go get github.com/nakabonne/nestif/cmd/nestif ``` +### By golangci-lint + +`nestif` is already integrated with [golangci-lint](https://github.com/golangci/golangci-lint). Please refer to the instructions there and enable it. + ## Usage ### Quick Start diff --git a/vendor/github.com/nakabonne/nestif/go.mod b/vendor/github.com/nakabonne/nestif/go.mod index 325901d59..0d5b1f721 100644 --- a/vendor/github.com/nakabonne/nestif/go.mod +++ b/vendor/github.com/nakabonne/nestif/go.mod @@ -1,6 +1,6 @@ module github.com/nakabonne/nestif -go 1.13 +go 1.15 require ( github.com/spf13/pflag v1.0.5 diff --git a/vendor/github.com/nakabonne/nestif/nestif.go b/vendor/github.com/nakabonne/nestif/nestif.go index d458022fb..c4bad7f2d 100644 --- a/vendor/github.com/nakabonne/nestif/nestif.go +++ b/vendor/github.com/nakabonne/nestif/nestif.go @@ -1,10 +1,10 @@ -// Copyright 2020 Ryo Nakao . +// Copyright 2020 Ryo Nakao . // // All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Package nestif provides an API to detect deeply nested if statements. +// Package nestif provides an API to detect complex nested if statements. package nestif import ( @@ -133,7 +133,7 @@ func (c *Checker) makeMessage(complexity int, cond ast.Expr, fset *token.FileSet if err := p.Fprint(b, fset, cond); err != nil { c.debug("failed to convert condition into string: %v", err) } - return fmt.Sprintf("`if %s` is deeply nested (complexity: %d)", b.String(), complexity) + return fmt.Sprintf("`if %s` has complex nested blocks (complexity: %d)", b.String(), complexity) } // DebugMode makes it possible to emit debug logs. diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go b/vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go new file mode 100644 index 000000000..2f207aa07 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/goenv/goenv.go @@ -0,0 +1,54 @@ +package goenv + +import ( + "errors" + "os/exec" + "runtime" + "strconv" + "strings" +) + +func Read() (map[string]string, error) { + out, err := exec.Command("go", "env").CombinedOutput() + if err != nil { + return nil, err + } + return parseGoEnv(out, runtime.GOOS) +} + +func parseGoEnv(data []byte, goos string) (map[string]string, error) { + vars := make(map[string]string) + + lines := strings.Split(strings.ReplaceAll(string(data), "\r\n", "\n"), "\n") + + if goos == "windows" { + // Line format is: `set $name=$value` + for _, l := range lines { + l = strings.TrimPrefix(l, "set ") + parts := strings.Split(l, "=") + if len(parts) != 2 { + continue + } + vars[parts[0]] = parts[1] + } + } else { + // Line format is: `$name="$value"` + for _, l := range lines { + parts := strings.Split(strings.TrimSpace(l), "=") + if len(parts) != 2 { + continue + } + val, err := strconv.Unquote(parts[1]) + if err != nil { + continue + } + vars[parts[0]] = val + } + } + + if len(vars) == 0 { + return nil, errors.New("empty env set") + } + + return vars, nil +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/compile.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/compile.go index d6e1b1e65..7e267a530 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/compile.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/compile.go @@ -4,6 +4,8 @@ import ( "fmt" "go/ast" "go/token" + + "github.com/quasilyte/go-ruleguard/internal/stdinfo" ) type compileError string @@ -16,9 +18,13 @@ type compiler struct { ifaceIndexes map[interface{}]uint8 strict bool fset *token.FileSet + + info *PatternInfo + + insideStmtList bool } -func (c *compiler) Compile(fset *token.FileSet, root ast.Node, strict bool) (p *program, err error) { +func (c *compiler) Compile(fset *token.FileSet, root ast.Node, info *PatternInfo, strict bool) (p *program, err error) { defer func() { if err != nil { return @@ -34,6 +40,7 @@ func (c *compiler) Compile(fset *token.FileSet, root ast.Node, strict bool) (p * panic(rv) // Not our panic }() + c.info = info c.fset = fset c.strict = strict c.prog = &program{ @@ -64,6 +71,12 @@ func (c *compiler) toUint8(n ast.Node, v int) uint8 { return uint8(v) } +func (c *compiler) internVar(n ast.Node, s string) uint8 { + c.info.Vars[s] = struct{}{} + index := c.internString(n, s) + return index +} + func (c *compiler) internString(n ast.Node, s string) uint8 { if index, ok := c.stringIndexes[s]; ok { return index @@ -112,7 +125,9 @@ func (c *compiler) compileNode(n ast.Node) { c.compileValueSpec(n) case stmtSlice: c.compileStmtSlice(n) - case exprSlice: + case declSlice: + c.compileDeclSlice(n) + case ExprSlice: c.compileExprSlice(n) default: panic(c.errorf(n, "compileNode: unexpected %T", n)) @@ -137,6 +152,28 @@ func (c *compiler) compileOptExpr(n ast.Expr) { c.compileExpr(n) } +func (c *compiler) compileOptFieldList(n *ast.FieldList) { + if len(n.List) == 1 { + if ident, ok := n.List[0].Type.(*ast.Ident); ok && isWildName(ident.Name) && len(n.List[0].Names) == 0 { + // `func (...) $*result` - result could be anything + // `func (...) $result` - result is a field list of 1 element + info := decodeWildName(ident.Name) + if info.Seq { + c.compileWildIdent(ident, true) + } else if info.Name == "_" { + c.emitInstOp(opFieldNode) + } else { + c.emitInst(instruction{ + op: opNamedFieldNode, + valueIndex: c.internVar(n, info.Name), + }) + } + return + } + } + c.compileFieldList(n) +} + func (c *compiler) compileFieldList(n *ast.FieldList) { c.emitInstOp(opFieldList) for _, x := range n.List { @@ -148,6 +185,10 @@ func (c *compiler) compileFieldList(n *ast.FieldList) { func (c *compiler) compileField(n *ast.Field) { switch { case len(n.Names) == 0: + if ident, ok := n.Type.(*ast.Ident); ok && isWildName(ident.Name) { + c.compileWildIdent(ident, false) + return + } c.emitInstOp(opUnnamedField) case len(n.Names) == 1: name := n.Names[0] @@ -172,6 +213,12 @@ func (c *compiler) compileField(n *ast.Field) { func (c *compiler) compileValueSpec(spec *ast.ValueSpec) { switch { + case spec.Type == nil && len(spec.Values) == 0: + if isWildName(spec.Names[0].String()) { + c.compileIdent(spec.Names[0]) + return + } + c.emitInstOp(opValueSpec) case spec.Type == nil: c.emitInstOp(opValueInitSpec) case len(spec.Values) == 0: @@ -240,6 +287,10 @@ func (c *compiler) compileFuncDecl(n *ast.FuncDecl) { } func (c *compiler) compileGenDecl(n *ast.GenDecl) { + if c.insideStmtList { + c.emitInstOp(opDeclStmt) + } + switch n.Tok { case token.CONST, token.VAR: c.emitInstOp(pickOp(n.Tok == token.CONST, opConstDecl, opVarDecl)) @@ -279,6 +330,10 @@ func (c *compiler) compileExpr(n ast.Expr) { c.compileParenExpr(n) case *ast.SliceExpr: c.compileSliceExpr(n) + case *ast.StructType: + c.compileStructType(n) + case *ast.InterfaceType: + c.compileInterfaceType(n) case *ast.FuncType: c.compileFuncType(n) case *ast.ArrayType: @@ -360,10 +415,10 @@ func (c *compiler) compileWildIdent(n *ast.Ident, optional bool) { inst.op = pickOp(optional, opOptNode, opNodeSeq) case info.Name != "_" && !info.Seq: inst.op = opNamedNode - inst.valueIndex = c.internString(n, info.Name) + inst.valueIndex = c.internVar(n, info.Name) default: inst.op = pickOp(optional, opNamedOptNode, opNamedNodeSeq) - inst.valueIndex = c.internString(n, info.Name) + inst.valueIndex = c.internVar(n, info.Name) } c.prog.insts = append(c.prog.insts, inst) } @@ -380,17 +435,81 @@ func (c *compiler) compileIdent(n *ast.Ident) { }) } +func (c *compiler) compileExprMembers(list []ast.Expr) { + isSimple := len(list) <= 255 + if isSimple { + for _, x := range list { + if decodeWildNode(x).Seq { + isSimple = false + break + } + } + } + + if isSimple { + c.emitInst(instruction{ + op: opSimpleArgList, + value: uint8(len(list)), + }) + for _, x := range list { + c.compileExpr(x) + } + } else { + c.emitInstOp(opArgList) + for _, x := range list { + c.compileExpr(x) + } + c.emitInstOp(opEnd) + } +} + func (c *compiler) compileCallExpr(n *ast.CallExpr) { - op := opCallExpr + canBeVariadic := func(n *ast.CallExpr) bool { + if len(n.Args) == 0 { + return false + } + lastArg, ok := n.Args[len(n.Args)-1].(*ast.Ident) + if !ok { + return false + } + return isWildName(lastArg.Name) && decodeWildName(lastArg.Name).Seq + } + + op := opNonVariadicCallExpr if n.Ellipsis.IsValid() { op = opVariadicCallExpr + } else if canBeVariadic(n) { + op = opCallExpr } + c.emitInstOp(op) - c.compileExpr(n.Fun) - for _, arg := range n.Args { - c.compileExpr(arg) + c.compileSymbol(n.Fun) + c.compileExprMembers(n.Args) +} + +// compileSymbol is mostly like a normal compileExpr, but it's used +// in places where we can find a type/function symbol. +// +// For example, in function call expressions a called function expression +// can look like `fmt.Sprint`. It will be compiled as a special +// selector expression that requires `fmt` to be a package as opposed +// to only check that it's an identifier with "fmt" value. +func (c *compiler) compileSymbol(fn ast.Expr) { + if e, ok := fn.(*ast.SelectorExpr); ok { + if ident, ok := e.X.(*ast.Ident); ok && stdinfo.Packages[ident.Name] != "" { + c.emitInst(instruction{ + op: opSimpleSelectorExpr, + valueIndex: c.internString(e.Sel, e.Sel.String()), + }) + c.emitInst(instruction{ + op: opStdlibPkg, + valueIndex: c.internString(ident, ident.Name), + }) + return + } } - c.emitInstOp(opEnd) + + c.compileExpr(fn) } func (c *compiler) compileUnaryExpr(n *ast.UnaryExpr) { @@ -415,36 +534,46 @@ func (c *compiler) compileSliceExpr(n *ast.SliceExpr) { switch { case n.Low == nil && n.High == nil && !n.Slice3: c.emitInstOp(opSliceExpr) - c.compileExpr(n.X) + c.compileOptExpr(n.X) case n.Low != nil && n.High == nil && !n.Slice3: c.emitInstOp(opSliceFromExpr) - c.compileExpr(n.X) - c.compileExpr(n.Low) + c.compileOptExpr(n.X) + c.compileOptExpr(n.Low) case n.Low == nil && n.High != nil && !n.Slice3: c.emitInstOp(opSliceToExpr) - c.compileExpr(n.X) - c.compileExpr(n.High) + c.compileOptExpr(n.X) + c.compileOptExpr(n.High) case n.Low != nil && n.High != nil && !n.Slice3: c.emitInstOp(opSliceFromToExpr) - c.compileExpr(n.X) - c.compileExpr(n.Low) - c.compileExpr(n.High) + c.compileOptExpr(n.X) + c.compileOptExpr(n.Low) + c.compileOptExpr(n.High) case n.Low == nil && n.Slice3: c.emitInstOp(opSliceToCapExpr) - c.compileExpr(n.X) - c.compileExpr(n.High) - c.compileExpr(n.Max) + c.compileOptExpr(n.X) + c.compileOptExpr(n.High) + c.compileOptExpr(n.Max) case n.Low != nil && n.Slice3: c.emitInstOp(opSliceFromToCapExpr) - c.compileExpr(n.X) - c.compileExpr(n.Low) - c.compileExpr(n.High) - c.compileExpr(n.Max) + c.compileOptExpr(n.X) + c.compileOptExpr(n.Low) + c.compileOptExpr(n.High) + c.compileOptExpr(n.Max) default: panic(c.errorf(n, "unexpected slice expr")) } } +func (c *compiler) compileStructType(n *ast.StructType) { + c.emitInstOp(opStructType) + c.compileOptFieldList(n.Fields) +} + +func (c *compiler) compileInterfaceType(n *ast.InterfaceType) { + c.emitInstOp(opInterfaceType) + c.compileOptFieldList(n.Methods) +} + func (c *compiler) compileFuncType(n *ast.FuncType) { void := n.Results == nil || len(n.Results.List) == 0 if void { @@ -452,9 +581,9 @@ func (c *compiler) compileFuncType(n *ast.FuncType) { } else { c.emitInstOp(opFuncType) } - c.compileFieldList(n.Params) + c.compileOptFieldList(n.Params) if !void { - c.compileFieldList(n.Results) + c.compileOptFieldList(n.Results) } } @@ -648,15 +777,17 @@ func (c *compiler) compileIfStmt(n *ast.IfStmt) { return } // Named $* is harder and slower. - c.prog.insts = append(c.prog.insts, instruction{ - op: pickOp(n.Else == nil, opIfNamedOptStmt, opIfNamedOptElseStmt), - valueIndex: c.internString(ident, info.Name), - }) - c.compileStmt(n.Body) - if n.Else != nil { - c.compileStmt(n.Else) + if info.Seq { + c.prog.insts = append(c.prog.insts, instruction{ + op: pickOp(n.Else == nil, opIfNamedOptStmt, opIfNamedOptElseStmt), + valueIndex: c.internVar(ident, info.Name), + }) + c.compileStmt(n.Body) + if n.Else != nil { + c.compileStmt(n.Else) + } + return } - return } switch { @@ -948,15 +1079,26 @@ func (c *compiler) compileSendStmt(n *ast.SendStmt) { c.compileExpr(n.Value) } -func (c *compiler) compileStmtSlice(stmts stmtSlice) { - c.emitInstOp(opMultiStmt) - for _, n := range stmts { - c.compileStmt(n) +func (c *compiler) compileDeclSlice(decls declSlice) { + c.emitInstOp(opMultiDecl) + for _, n := range decls { + c.compileDecl(n) } c.emitInstOp(opEnd) } -func (c *compiler) compileExprSlice(exprs exprSlice) { +func (c *compiler) compileStmtSlice(stmts stmtSlice) { + c.emitInstOp(opMultiStmt) + insideStmtList := c.insideStmtList + c.insideStmtList = true + for _, n := range stmts { + c.compileStmt(n) + } + c.insideStmtList = insideStmtList + c.emitInstOp(opEnd) +} + +func (c *compiler) compileExprSlice(exprs ExprSlice) { c.emitInstOp(opMultiExpr) for _, n := range exprs { c.compileExpr(n) diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gen_operations.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gen_operations.go index dbf2ae9a7..d01d55b45 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gen_operations.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gen_operations.go @@ -20,8 +20,12 @@ var opPrototypes = []operationProto{ {name: "OptNode"}, {name: "NamedOptNode", valueIndex: "strings | wildcard name"}, + {name: "FieldNode", tag: "Node"}, + {name: "NamedFieldNode", tag: "Node", valueIndex: "strings | wildcard name"}, + {name: "MultiStmt", tag: "StmtList", args: "stmts...", example: "f(); g()"}, {name: "MultiExpr", tag: "ExprList", args: "exprs...", example: "f(), g()"}, + {name: "MultiDecl", tag: "DeclList", args: "exprs...", example: "f(), g()"}, {name: "End"}, @@ -33,6 +37,7 @@ var opPrototypes = []operationProto{ {name: "StrictComplexLit", tag: "BasicLit", valueIndex: "strings | raw literal value"}, {name: "Ident", tag: "Ident", valueIndex: "strings | ident name"}, + {name: "StdlibPkg", tag: "Ident", valueIndex: "strings | package name"}, {name: "IndexExpr", tag: "IndexExpr", args: "x expr"}, @@ -53,6 +58,8 @@ var opPrototypes = []operationProto{ {name: "TypeAssertExpr", tag: "TypeAssertExpr", args: "x typ"}, {name: "TypeSwitchAssertExpr", tag: "TypeAssertExpr", args: "x"}, + {name: "StructType", tag: "StructType", args: "fields"}, + {name: "InterfaceType", tag: "StructType", args: "fields"}, {name: "VoidFuncType", tag: "FuncType", args: "params"}, {name: "FuncType", tag: "FuncType", args: "params results"}, {name: "ArrayType", tag: "ArrayType", args: "length elem"}, @@ -69,8 +76,22 @@ var opPrototypes = []operationProto{ {name: "BinaryExpr", tag: "BinaryExpr", args: "x y", value: "token.Token | binary operator"}, {name: "ParenExpr", tag: "ParenExpr", args: "x"}, - {name: "VariadicCallExpr", tag: "CallExpr", args: "fn args...", example: "f(1, xs...)"}, - {name: "CallExpr", tag: "CallExpr", args: "fn args...", example: "f(1, xs)"}, + { + name: "ArgList", + args: "exprs...", + example: "1, 2, 3", + }, + { + name: "SimpleArgList", + note: "Like ArgList, but pattern contains no $*", + args: "exprs[]", + value: "int | slice len", + example: "1, 2, 3", + }, + + {name: "VariadicCallExpr", tag: "CallExpr", args: "fn args", example: "f(1, xs...)"}, + {name: "NonVariadicCallExpr", tag: "CallExpr", args: "fn args", example: "f(1, xs)"}, + {name: "CallExpr", tag: "CallExpr", args: "fn args", example: "f(1, xs) or f(1, xs...)"}, {name: "AssignStmt", tag: "AssignStmt", args: "lhs rhs", value: "token.Token | ':=' or '='", example: "lhs := rhs()"}, {name: "MultiAssignStmt", tag: "AssignStmt", args: "lhs... rhs...", value: "token.Token | ':=' or '='", example: "lhs1, lhs2 := rhs()"}, @@ -135,6 +156,7 @@ var opPrototypes = []operationProto{ {name: "Field", args: "name typ", example: "$name type"}, {name: "MultiField", args: "names... typ", example: "name1, name2 type"}, + {name: "ValueSpec", tag: "ValueSpec", args: "value"}, {name: "ValueInitSpec", tag: "ValueSpec", args: "lhs... rhs...", example: "lhs = rhs"}, {name: "TypedValueInitSpec", tag: "ValueSpec", args: "lhs... type rhs...", example: "lhs typ = rhs"}, {name: "TypedValueSpec", tag: "ValueSpec", args: "lhs... type", example: "lhs typ"}, @@ -147,6 +169,7 @@ var opPrototypes = []operationProto{ {name: "FuncProtoDecl", tag: "FuncDecl", args: "name type"}, {name: "MethodProtoDecl", tag: "FuncDecl", args: "recv name type"}, + {name: "DeclStmt", tag: "DeclStmt", args: "decl"}, {name: "ConstDecl", tag: "GenDecl", args: "valuespecs..."}, {name: "VarDecl", tag: "GenDecl", args: "valuespecs..."}, {name: "TypeDecl", tag: "GenDecl", args: "typespecs..."}, @@ -161,10 +184,12 @@ type operationProto struct { tag string example string args string + note string } type operationInfo struct { Example string + Note string Args string Enum uint8 TagName string @@ -175,6 +200,7 @@ type operationInfo struct { ValueKindName string VariadicMap uint64 NumArgs int + SliceIndex int } const stackUnchanged = "" @@ -194,6 +220,7 @@ const ( opInvalid operation = 0 {{ range .Operations }} // Tag: {{.TagName}} + {{- if .Note}}{{print "\n"}}// {{.Note}}{{end}} {{- if .Args}}{{print "\n"}}// Args: {{.Args}}{{end}} {{- if .Example}}{{print "\n"}}// Example: {{.Example}}{{end}} {{- if .ValueDoc}}{{print "\n"}}// Value: {{.ValueDoc}}{{end}} @@ -208,6 +235,7 @@ type operationInfo struct { ValueKind valueKind ExtraValueKind valueKind VariadicMap bitmap64 + SliceIndex int } var operationInfoTable = [256]operationInfo{ @@ -220,6 +248,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: {{.ValueKindName}}, ExtraValueKind: {{.ExtraValueKindName}}, VariadicMap: {{.VariadicMap}}, // {{printf "%b" .VariadicMap}} + SliceIndex: {{.SliceIndex}}, }, {{ end }} } @@ -237,6 +266,7 @@ func main() { variadicMap := uint64(0) numArgs := 0 + sliceLenIndex := -1 if proto.args != "" { args := strings.Split(proto.args, " ") numArgs = len(args) @@ -245,6 +275,9 @@ func main() { if isVariadic { variadicMap |= 1 << i } + if strings.HasSuffix(arg, "[]") { + sliceLenIndex = i + } } } @@ -270,6 +303,8 @@ func main() { valueKindName = "tokenValue" case "ast.ChanDir": valueKindName = "chandirValue" + case "int": + valueKindName = "intValue" default: panic(fmt.Sprintf("%s: unexpected %s type", proto.name, typ)) } @@ -277,6 +312,7 @@ func main() { operations[i] = operationInfo{ Example: proto.example, + Note: proto.note, Args: proto.args, Enum: enum, TagName: tagName, @@ -284,9 +320,10 @@ func main() { ValueDoc: proto.value, ValueIndexDoc: proto.valueIndex, NumArgs: numArgs, - VariadicMap: variadicMap, + VariadicMap: variadicMap, ExtraValueKindName: extraValueKindName, ValueKindName: valueKindName, + SliceIndex: sliceLenIndex, } } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gogrep.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gogrep.go index e0d3d0696..ea054f334 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gogrep.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/gogrep.go @@ -3,13 +3,14 @@ package gogrep import ( "go/ast" "go/token" + "go/types" "github.com/quasilyte/go-ruleguard/nodetag" ) func IsEmptyNodeSlice(n ast.Node) bool { - if list, ok := n.(nodeSlice); ok { - return list.len() == 0 + if list, ok := n.(NodeSlice); ok { + return list.Len() == 0 } return false } @@ -26,20 +27,43 @@ type CapturedNode struct { } func (data MatchData) CapturedByName(name string) (ast.Node, bool) { + if name == "$$" { + return data.Node, true + } return findNamed(data.Capture, name) } +type MatcherState struct { + Types *types.Info + + // node values recorded by name, excluding "_" (used only by the + // actual matching phase) + capture []CapturedNode + + pc int +} + +func NewMatcherState() MatcherState { + return MatcherState{ + capture: make([]CapturedNode, 0, 8), + } +} + type Pattern struct { m *matcher } +type PatternInfo struct { + Vars map[string]struct{} +} + func (p *Pattern) NodeTag() nodetag.Value { return operationInfoTable[p.m.prog.insts[0].op].Tag } // MatchNode calls cb if n matches a pattern. -func (p *Pattern) MatchNode(n ast.Node, cb func(MatchData)) { - p.m.MatchNode(n, cb) +func (p *Pattern) MatchNode(state *MatcherState, n ast.Node, cb func(MatchData)) { + p.m.MatchNode(state, n, cb) } // Clone creates a pattern copy. @@ -47,20 +71,26 @@ func (p *Pattern) Clone() *Pattern { clone := *p clone.m = &matcher{} *clone.m = *p.m - clone.m.capture = make([]CapturedNode, 0, 8) return &clone } -func Compile(fset *token.FileSet, src string, strict bool) (*Pattern, error) { +func Compile(fset *token.FileSet, src string, strict bool) (*Pattern, PatternInfo, error) { + info := newPatternInfo() n, err := parseExpr(fset, src) if err != nil { - return nil, err + return nil, info, err } var c compiler - prog, err := c.Compile(fset, n, strict) + prog, err := c.Compile(fset, n, &info, strict) if err != nil { - return nil, err + return nil, info, err } m := newMatcher(prog) - return &Pattern{m: m}, nil + return &Pattern{m: m}, info, nil +} + +func newPatternInfo() PatternInfo { + return PatternInfo{ + Vars: map[string]struct{}{}, + } } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/instructions.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/instructions.go index 5d286eaec..9f4f72d88 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/instructions.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/instructions.go @@ -21,6 +21,7 @@ const ( ifaceValue // Extra values only; value is stored in program.ifaces tokenValue // token.Token chandirValue // ast.CharDir + intValue // int ) type program struct { @@ -54,6 +55,12 @@ func formatProgram(p *program) []string { info := operationInfoTable[inst.op] for i := 0; i < info.NumArgs; i++ { + if i == info.SliceIndex { + for j := 0; j < int(inst.value); j++ { + walk(depth + 1) + } + continue + } if !info.VariadicMap.IsSet(i) { walk(depth + 1) continue @@ -88,6 +95,8 @@ func formatInstruction(p *program, inst instruction) string { } case tokenValue: parts = append(parts, token.Token(inst.value).String()) + case intValue: + parts = append(parts, fmt.Sprint(inst.value)) } switch info.ExtraValueKind { diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/match.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/match.go index 1baad5a4d..39b71c467 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/match.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/match.go @@ -4,33 +4,29 @@ import ( "fmt" "go/ast" "go/token" + "go/types" "strconv" "github.com/go-toolsmith/astequal" + "github.com/quasilyte/go-ruleguard/internal/stdinfo" ) type matcher struct { prog *program insts []instruction - pc int - - // node values recorded by name, excluding "_" (used only by the - // actual matching phase) - capture []CapturedNode } func newMatcher(prog *program) *matcher { return &matcher{ - prog: prog, - insts: prog.insts, - capture: make([]CapturedNode, 0, 8), + prog: prog, + insts: prog.insts, } } -func (m *matcher) nextInst() instruction { - inst := m.insts[m.pc] - m.pc++ +func (m *matcher) nextInst(state *MatcherState) instruction { + inst := m.insts[state.pc] + state.pc++ return inst } @@ -42,59 +38,68 @@ func (m *matcher) ifaceValue(inst instruction) interface{} { return m.prog.ifaces[inst.valueIndex] } -func (m *matcher) MatchNode(n ast.Node, accept func(MatchData)) { - m.pc = 0 - inst := m.nextInst() +func (m *matcher) MatchNode(state *MatcherState, n ast.Node, accept func(MatchData)) { + state.pc = 0 + inst := m.nextInst(state) switch inst.op { case opMultiStmt: switch n := n.(type) { case *ast.BlockStmt: - m.walkStmtSlice(n.List, accept) + m.walkStmtSlice(state, n.List, accept) case *ast.CaseClause: - m.walkStmtSlice(n.Body, accept) + m.walkStmtSlice(state, n.Body, accept) case *ast.CommClause: - m.walkStmtSlice(n.Body, accept) + m.walkStmtSlice(state, n.Body, accept) } case opMultiExpr: switch n := n.(type) { case *ast.CallExpr: - m.walkExprSlice(n.Args, accept) + m.walkExprSlice(state, n.Args, accept) case *ast.CompositeLit: - m.walkExprSlice(n.Elts, accept) + m.walkExprSlice(state, n.Elts, accept) case *ast.ReturnStmt: - m.walkExprSlice(n.Results, accept) + m.walkExprSlice(state, n.Results, accept) + } + case opMultiDecl: + switch n := n.(type) { + case *ast.File: + m.walkDeclSlice(state, n.Decls, accept) } default: - m.capture = m.capture[:0] - if m.matchNodeWithInst(inst, n) { + state.capture = state.capture[:0] + if m.matchNodeWithInst(state, inst, n) { accept(MatchData{ - Capture: m.capture, + Capture: state.capture, Node: n, }) } } } -func (m *matcher) walkExprSlice(exprs []ast.Expr, accept func(MatchData)) { - m.walkNodeSlice(exprSlice(exprs), accept) +func (m *matcher) walkDeclSlice(state *MatcherState, decls []ast.Decl, accept func(MatchData)) { + m.walkNodeSlice(state, declSlice(decls), accept) } -func (m *matcher) walkStmtSlice(stmts []ast.Stmt, accept func(MatchData)) { - m.walkNodeSlice(stmtSlice(stmts), accept) +func (m *matcher) walkExprSlice(state *MatcherState, exprs []ast.Expr, accept func(MatchData)) { + m.walkNodeSlice(state, ExprSlice(exprs), accept) } -func (m *matcher) walkNodeSlice(nodes nodeSlice, accept func(MatchData)) { - sliceLen := nodes.len() +func (m *matcher) walkStmtSlice(state *MatcherState, stmts []ast.Stmt, accept func(MatchData)) { + m.walkNodeSlice(state, stmtSlice(stmts), accept) +} + +func (m *matcher) walkNodeSlice(state *MatcherState, nodes NodeSlice, accept func(MatchData)) { + sliceLen := nodes.Len() from := 0 for { - m.pc = 1 // FIXME: this is a kludge - m.capture = m.capture[:0] - matched, offset := m.matchNodeList(nodes.slice(from, sliceLen), true) + state.pc = 1 // FIXME: this is a kludge + state.capture = state.capture[:0] + matched, offset := m.matchNodeList(state, nodes.slice(from, sliceLen), true) if matched == nil { break } accept(MatchData{ - Capture: m.capture, + Capture: state.capture, Node: matched, }) from += offset - 1 @@ -104,17 +109,43 @@ func (m *matcher) walkNodeSlice(nodes nodeSlice, accept func(MatchData)) { } } -func (m *matcher) matchNamed(name string, n ast.Node) bool { - prev, ok := findNamed(m.capture, name) +func (m *matcher) matchNamed(state *MatcherState, name string, n ast.Node) bool { + prev, ok := findNamed(state.capture, name) if !ok { // First occurrence, record value. - m.capture = append(m.capture, CapturedNode{Name: name, Node: n}) + state.capture = append(state.capture, CapturedNode{Name: name, Node: n}) return true } return equalNodes(prev, n) } -func (m *matcher) matchNodeWithInst(inst instruction, n ast.Node) bool { +func (m *matcher) matchNamedField(state *MatcherState, name string, n ast.Node) bool { + prev, ok := findNamed(state.capture, name) + if !ok { + // First occurrence, record value. + unwrapped := m.unwrapNode(n) + state.capture = append(state.capture, CapturedNode{Name: name, Node: unwrapped}) + return true + } + n = m.unwrapNode(n) + return equalNodes(prev, n) +} + +func (m *matcher) unwrapNode(x ast.Node) ast.Node { + switch x := x.(type) { + case *ast.Field: + if len(x.Names) == 0 { + return x.Type + } + case *ast.FieldList: + if x != nil && len(x.List) == 1 && len(x.List[0].Names) == 0 { + return x.List[0].Type + } + } + return x +} + +func (m *matcher) matchNodeWithInst(state *MatcherState, inst instruction, n ast.Node) bool { switch inst.op { case opNode: return n != nil @@ -122,9 +153,15 @@ func (m *matcher) matchNodeWithInst(inst instruction, n ast.Node) bool { return true case opNamedNode: - return n != nil && m.matchNamed(m.stringValue(inst), n) + return n != nil && m.matchNamed(state, m.stringValue(inst), n) case opNamedOptNode: - return m.matchNamed(m.stringValue(inst), n) + return m.matchNamed(state, m.stringValue(inst), n) + + case opFieldNode: + n, ok := n.(*ast.FieldList) + return ok && n != nil && len(n.List) == 1 && len(n.List[0].Names) == 0 + case opNamedFieldNode: + return n != nil && m.matchNamedField(state, m.stringValue(inst), n) case opBasicLit: n, ok := n.(*ast.BasicLit) @@ -150,284 +187,306 @@ func (m *matcher) matchNodeWithInst(inst instruction, n ast.Node) bool { n, ok := n.(*ast.Ident) return ok && m.stringValue(inst) == n.Name + case opStdlibPkg: + n, ok := n.(*ast.Ident) + if !ok { + return false + } + obj := state.Types.ObjectOf(n) + if obj == nil { + return false + } + pkgName, ok := obj.(*types.PkgName) + return ok && m.stringValue(inst) == pkgName.Imported().Name() && + pkgName.Imported().Path() == stdinfo.Packages[pkgName.Imported().Name()] + case opBinaryExpr: n, ok := n.(*ast.BinaryExpr) return ok && n.Op == token.Token(inst.value) && - m.matchNode(n.X) && m.matchNode(n.Y) + m.matchNode(state, n.X) && m.matchNode(state, n.Y) case opUnaryExpr: n, ok := n.(*ast.UnaryExpr) - return ok && n.Op == token.Token(inst.value) && m.matchNode(n.X) + return ok && n.Op == token.Token(inst.value) && m.matchNode(state, n.X) case opStarExpr: n, ok := n.(*ast.StarExpr) - return ok && m.matchNode(n.X) + return ok && m.matchNode(state, n.X) case opVariadicCallExpr: n, ok := n.(*ast.CallExpr) - return ok && n.Ellipsis.IsValid() && m.matchNode(n.Fun) && m.matchExprSlice(n.Args) + return ok && n.Ellipsis.IsValid() && m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) + case opNonVariadicCallExpr: + n, ok := n.(*ast.CallExpr) + return ok && !n.Ellipsis.IsValid() && m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) case opCallExpr: n, ok := n.(*ast.CallExpr) - return ok && !n.Ellipsis.IsValid() && m.matchNode(n.Fun) && m.matchExprSlice(n.Args) + return ok && m.matchNode(state, n.Fun) && m.matchArgList(state, n.Args) case opSimpleSelectorExpr: n, ok := n.(*ast.SelectorExpr) - return ok && m.stringValue(inst) == n.Sel.Name && m.matchNode(n.X) + return ok && m.stringValue(inst) == n.Sel.Name && m.matchNode(state, n.X) case opSelectorExpr: n, ok := n.(*ast.SelectorExpr) - return ok && m.matchNode(n.Sel) && m.matchNode(n.X) + return ok && m.matchNode(state, n.Sel) && m.matchNode(state, n.X) case opTypeAssertExpr: n, ok := n.(*ast.TypeAssertExpr) - return ok && m.matchNode(n.X) && m.matchNode(n.Type) + return ok && m.matchNode(state, n.X) && m.matchNode(state, n.Type) case opTypeSwitchAssertExpr: n, ok := n.(*ast.TypeAssertExpr) - return ok && n.Type == nil && m.matchNode(n.X) + return ok && n.Type == nil && m.matchNode(state, n.X) case opSliceExpr: n, ok := n.(*ast.SliceExpr) - return ok && n.Low == nil && n.High == nil && m.matchNode(n.X) + return ok && n.Low == nil && n.High == nil && m.matchNode(state, n.X) case opSliceFromExpr: n, ok := n.(*ast.SliceExpr) - return ok && n.Low != nil && n.High == nil && !n.Slice3 && - m.matchNode(n.X) && m.matchNode(n.Low) + return ok && n.High == nil && !n.Slice3 && + m.matchNode(state, n.X) && m.matchNode(state, n.Low) case opSliceToExpr: n, ok := n.(*ast.SliceExpr) - return ok && n.Low == nil && n.High != nil && !n.Slice3 && - m.matchNode(n.X) && m.matchNode(n.High) + return ok && n.Low == nil && !n.Slice3 && + m.matchNode(state, n.X) && m.matchNode(state, n.High) case opSliceFromToExpr: n, ok := n.(*ast.SliceExpr) - return ok && n.Low != nil && n.High != nil && !n.Slice3 && - m.matchNode(n.X) && m.matchNode(n.Low) && m.matchNode(n.High) + return ok && !n.Slice3 && + m.matchNode(state, n.X) && m.matchNode(state, n.Low) && m.matchNode(state, n.High) case opSliceToCapExpr: n, ok := n.(*ast.SliceExpr) - return ok && n.Low == nil && n.High != nil && n.Max != nil && - m.matchNode(n.X) && m.matchNode(n.High) && m.matchNode(n.Max) + return ok && n.Low == nil && + m.matchNode(state, n.X) && m.matchNode(state, n.High) && m.matchNode(state, n.Max) case opSliceFromToCapExpr: n, ok := n.(*ast.SliceExpr) - return ok && n.Low != nil && n.High != nil && n.Max != nil && - m.matchNode(n.X) && m.matchNode(n.Low) && m.matchNode(n.High) && m.matchNode(n.Max) + return ok && m.matchNode(state, n.X) && m.matchNode(state, n.Low) && m.matchNode(state, n.High) && m.matchNode(state, n.Max) case opIndexExpr: n, ok := n.(*ast.IndexExpr) - return ok && m.matchNode(n.X) && m.matchNode(n.Index) + return ok && m.matchNode(state, n.X) && m.matchNode(state, n.Index) case opKeyValueExpr: n, ok := n.(*ast.KeyValueExpr) - return ok && m.matchNode(n.Key) && m.matchNode(n.Value) + return ok && m.matchNode(state, n.Key) && m.matchNode(state, n.Value) case opParenExpr: n, ok := n.(*ast.ParenExpr) - return ok && m.matchNode(n.X) + return ok && m.matchNode(state, n.X) case opEllipsis: n, ok := n.(*ast.Ellipsis) return ok && n.Elt == nil case opTypedEllipsis: n, ok := n.(*ast.Ellipsis) - return ok && n.Elt != nil && m.matchNode(n.Elt) + return ok && n.Elt != nil && m.matchNode(state, n.Elt) case opSliceType: n, ok := n.(*ast.ArrayType) - return ok && n.Len == nil && m.matchNode(n.Elt) + return ok && n.Len == nil && m.matchNode(state, n.Elt) case opArrayType: n, ok := n.(*ast.ArrayType) - return ok && n.Len != nil && m.matchNode(n.Len) && m.matchNode(n.Elt) + return ok && n.Len != nil && m.matchNode(state, n.Len) && m.matchNode(state, n.Elt) case opMapType: n, ok := n.(*ast.MapType) - return ok && m.matchNode(n.Key) && m.matchNode(n.Value) + return ok && m.matchNode(state, n.Key) && m.matchNode(state, n.Value) case opChanType: n, ok := n.(*ast.ChanType) - return ok && ast.ChanDir(inst.value) == n.Dir && m.matchNode(n.Value) + return ok && ast.ChanDir(inst.value) == n.Dir && m.matchNode(state, n.Value) case opVoidFuncType: n, ok := n.(*ast.FuncType) - return ok && n.Results == nil && m.matchNode(n.Params) + return ok && n.Results == nil && m.matchNode(state, n.Params) case opFuncType: n, ok := n.(*ast.FuncType) - return ok && n.Results != nil && m.matchNode(n.Params) && m.matchNode(n.Results) + return ok && m.matchNode(state, n.Params) && m.matchNode(state, n.Results) + case opStructType: + n, ok := n.(*ast.StructType) + return ok && m.matchNode(state, n.Fields) + case opInterfaceType: + n, ok := n.(*ast.InterfaceType) + return ok && m.matchNode(state, n.Methods) case opCompositeLit: n, ok := n.(*ast.CompositeLit) - return ok && n.Type == nil && m.matchExprSlice(n.Elts) + return ok && n.Type == nil && m.matchExprSlice(state, n.Elts) case opTypedCompositeLit: n, ok := n.(*ast.CompositeLit) - return ok && n.Type != nil && m.matchNode(n.Type) && m.matchExprSlice(n.Elts) + return ok && n.Type != nil && m.matchNode(state, n.Type) && m.matchExprSlice(state, n.Elts) case opUnnamedField: n, ok := n.(*ast.Field) - return ok && len(n.Names) == 0 && m.matchNode(n.Type) + return ok && len(n.Names) == 0 && m.matchNode(state, n.Type) case opSimpleField: n, ok := n.(*ast.Field) - return ok && len(n.Names) == 1 && m.stringValue(inst) == n.Names[0].Name && m.matchNode(n.Type) + return ok && len(n.Names) == 1 && m.stringValue(inst) == n.Names[0].Name && m.matchNode(state, n.Type) case opField: n, ok := n.(*ast.Field) - return ok && len(n.Names) == 1 && m.matchNode(n.Names[0]) && m.matchNode(n.Type) + return ok && len(n.Names) == 1 && m.matchNode(state, n.Names[0]) && m.matchNode(state, n.Type) case opMultiField: n, ok := n.(*ast.Field) - return ok && len(n.Names) >= 2 && m.matchIdentSlice(n.Names) && m.matchNode(n.Type) + return ok && len(n.Names) >= 2 && m.matchIdentSlice(state, n.Names) && m.matchNode(state, n.Type) case opFieldList: + // FieldList could be nil in places like function return types. n, ok := n.(*ast.FieldList) - return ok && m.matchFieldSlice(n.List) + return ok && n != nil && m.matchFieldSlice(state, n.List) case opFuncLit: n, ok := n.(*ast.FuncLit) - return ok && m.matchNode(n.Type) && m.matchNode(n.Body) + return ok && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) case opAssignStmt: n, ok := n.(*ast.AssignStmt) return ok && token.Token(inst.value) == n.Tok && - len(n.Lhs) == 1 && m.matchNode(n.Lhs[0]) && - len(n.Rhs) == 1 && m.matchNode(n.Rhs[0]) + len(n.Lhs) == 1 && m.matchNode(state, n.Lhs[0]) && + len(n.Rhs) == 1 && m.matchNode(state, n.Rhs[0]) case opMultiAssignStmt: n, ok := n.(*ast.AssignStmt) return ok && token.Token(inst.value) == n.Tok && - m.matchExprSlice(n.Lhs) && m.matchExprSlice(n.Rhs) + m.matchExprSlice(state, n.Lhs) && m.matchExprSlice(state, n.Rhs) case opExprStmt: n, ok := n.(*ast.ExprStmt) - return ok && m.matchNode(n.X) + return ok && m.matchNode(state, n.X) case opGoStmt: n, ok := n.(*ast.GoStmt) - return ok && m.matchNode(n.Call) + return ok && m.matchNode(state, n.Call) case opDeferStmt: n, ok := n.(*ast.DeferStmt) - return ok && m.matchNode(n.Call) + return ok && m.matchNode(state, n.Call) case opSendStmt: n, ok := n.(*ast.SendStmt) - return ok && m.matchNode(n.Chan) && m.matchNode(n.Value) + return ok && m.matchNode(state, n.Chan) && m.matchNode(state, n.Value) case opBlockStmt: n, ok := n.(*ast.BlockStmt) - return ok && m.matchStmtSlice(n.List) + return ok && m.matchStmtSlice(state, n.List) case opIfStmt: n, ok := n.(*ast.IfStmt) return ok && n.Init == nil && n.Else == nil && - m.matchNode(n.Cond) && m.matchNode(n.Body) + m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) case opIfElseStmt: n, ok := n.(*ast.IfStmt) return ok && n.Init == nil && n.Else != nil && - m.matchNode(n.Cond) && m.matchNode(n.Body) && m.matchNode(n.Else) + m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) && m.matchNode(state, n.Else) case opIfInitStmt: n, ok := n.(*ast.IfStmt) return ok && n.Else == nil && - m.matchNode(n.Init) && m.matchNode(n.Cond) && m.matchNode(n.Body) + m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) case opIfInitElseStmt: n, ok := n.(*ast.IfStmt) return ok && n.Else != nil && - m.matchNode(n.Init) && m.matchNode(n.Cond) && m.matchNode(n.Body) && m.matchNode(n.Else) + m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) && m.matchNode(state, n.Else) case opIfNamedOptStmt: n, ok := n.(*ast.IfStmt) - return ok && n.Else == nil && m.matchNode(n.Body) && - m.matchNamed(m.stringValue(inst), toStmtSlice(n.Cond, n.Init)) + return ok && n.Else == nil && m.matchNode(state, n.Body) && + m.matchNamed(state, m.stringValue(inst), toStmtSlice(n.Cond, n.Init)) case opIfNamedOptElseStmt: n, ok := n.(*ast.IfStmt) - return ok && n.Else != nil && m.matchNode(n.Body) && m.matchNode(n.Else) && - m.matchNamed(m.stringValue(inst), toStmtSlice(n.Cond, n.Init)) + return ok && n.Else != nil && m.matchNode(state, n.Body) && m.matchNode(state, n.Else) && + m.matchNamed(state, m.stringValue(inst), toStmtSlice(n.Cond, n.Init)) case opCaseClause: n, ok := n.(*ast.CaseClause) - return ok && n.List != nil && m.matchExprSlice(n.List) && m.matchStmtSlice(n.Body) + return ok && n.List != nil && m.matchExprSlice(state, n.List) && m.matchStmtSlice(state, n.Body) case opDefaultCaseClause: n, ok := n.(*ast.CaseClause) - return ok && n.List == nil && m.matchStmtSlice(n.Body) + return ok && n.List == nil && m.matchStmtSlice(state, n.Body) case opSwitchStmt: n, ok := n.(*ast.SwitchStmt) - return ok && n.Init == nil && n.Tag == nil && m.matchStmtSlice(n.Body.List) + return ok && n.Init == nil && n.Tag == nil && m.matchStmtSlice(state, n.Body.List) case opSwitchTagStmt: n, ok := n.(*ast.SwitchStmt) - return ok && n.Init == nil && m.matchNode(n.Tag) && m.matchStmtSlice(n.Body.List) + return ok && n.Init == nil && m.matchNode(state, n.Tag) && m.matchStmtSlice(state, n.Body.List) case opSwitchInitStmt: n, ok := n.(*ast.SwitchStmt) - return ok && n.Tag == nil && m.matchNode(n.Init) && m.matchStmtSlice(n.Body.List) + return ok && n.Tag == nil && m.matchNode(state, n.Init) && m.matchStmtSlice(state, n.Body.List) case opSwitchInitTagStmt: n, ok := n.(*ast.SwitchStmt) - return ok && m.matchNode(n.Init) && m.matchNode(n.Tag) && m.matchStmtSlice(n.Body.List) + return ok && m.matchNode(state, n.Init) && m.matchNode(state, n.Tag) && m.matchStmtSlice(state, n.Body.List) case opTypeSwitchStmt: n, ok := n.(*ast.TypeSwitchStmt) - return ok && n.Init == nil && m.matchNode(n.Assign) && m.matchStmtSlice(n.Body.List) + return ok && n.Init == nil && m.matchNode(state, n.Assign) && m.matchStmtSlice(state, n.Body.List) case opTypeSwitchInitStmt: n, ok := n.(*ast.TypeSwitchStmt) - return ok && m.matchNode(n.Init) && - m.matchNode(n.Assign) && m.matchStmtSlice(n.Body.List) + return ok && m.matchNode(state, n.Init) && + m.matchNode(state, n.Assign) && m.matchStmtSlice(state, n.Body.List) case opCommClause: n, ok := n.(*ast.CommClause) - return ok && n.Comm != nil && m.matchNode(n.Comm) && m.matchStmtSlice(n.Body) + return ok && n.Comm != nil && m.matchNode(state, n.Comm) && m.matchStmtSlice(state, n.Body) case opDefaultCommClause: n, ok := n.(*ast.CommClause) - return ok && n.Comm == nil && m.matchStmtSlice(n.Body) + return ok && n.Comm == nil && m.matchStmtSlice(state, n.Body) case opSelectStmt: n, ok := n.(*ast.SelectStmt) - return ok && m.matchStmtSlice(n.Body.List) + return ok && m.matchStmtSlice(state, n.Body.List) case opRangeStmt: n, ok := n.(*ast.RangeStmt) - return ok && n.Key == nil && n.Value == nil && m.matchNode(n.X) && m.matchNode(n.Body) + return ok && n.Key == nil && n.Value == nil && m.matchNode(state, n.X) && m.matchNode(state, n.Body) case opRangeKeyStmt: n, ok := n.(*ast.RangeStmt) return ok && n.Key != nil && n.Value == nil && token.Token(inst.value) == n.Tok && - m.matchNode(n.Key) && m.matchNode(n.X) && m.matchNode(n.Body) + m.matchNode(state, n.Key) && m.matchNode(state, n.X) && m.matchNode(state, n.Body) case opRangeKeyValueStmt: n, ok := n.(*ast.RangeStmt) return ok && n.Key != nil && n.Value != nil && token.Token(inst.value) == n.Tok && - m.matchNode(n.Key) && m.matchNode(n.Value) && m.matchNode(n.X) && m.matchNode(n.Body) + m.matchNode(state, n.Key) && m.matchNode(state, n.Value) && m.matchNode(state, n.X) && m.matchNode(state, n.Body) case opForStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init == nil && n.Cond == nil && n.Post == nil && - m.matchNode(n.Body) + m.matchNode(state, n.Body) case opForPostStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init == nil && n.Cond == nil && n.Post != nil && - m.matchNode(n.Post) && m.matchNode(n.Body) + m.matchNode(state, n.Post) && m.matchNode(state, n.Body) case opForCondStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init == nil && n.Cond != nil && n.Post == nil && - m.matchNode(n.Cond) && m.matchNode(n.Body) + m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) case opForCondPostStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init == nil && n.Cond != nil && n.Post != nil && - m.matchNode(n.Cond) && m.matchNode(n.Post) && m.matchNode(n.Body) + m.matchNode(state, n.Cond) && m.matchNode(state, n.Post) && m.matchNode(state, n.Body) case opForInitStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init != nil && n.Cond == nil && n.Post == nil && - m.matchNode(n.Init) && m.matchNode(n.Body) + m.matchNode(state, n.Init) && m.matchNode(state, n.Body) case opForInitPostStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init != nil && n.Cond == nil && n.Post != nil && - m.matchNode(n.Init) && m.matchNode(n.Post) && m.matchNode(n.Body) + m.matchNode(state, n.Init) && m.matchNode(state, n.Post) && m.matchNode(state, n.Body) case opForInitCondStmt: n, ok := n.(*ast.ForStmt) return ok && n.Init != nil && n.Cond != nil && n.Post == nil && - m.matchNode(n.Init) && m.matchNode(n.Cond) && m.matchNode(n.Body) + m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Body) case opForInitCondPostStmt: n, ok := n.(*ast.ForStmt) - return ok && m.matchNode(n.Init) && m.matchNode(n.Cond) && m.matchNode(n.Post) && m.matchNode(n.Body) + return ok && m.matchNode(state, n.Init) && m.matchNode(state, n.Cond) && m.matchNode(state, n.Post) && m.matchNode(state, n.Body) case opIncDecStmt: n, ok := n.(*ast.IncDecStmt) - return ok && token.Token(inst.value) == n.Tok && m.matchNode(n.X) + return ok && token.Token(inst.value) == n.Tok && m.matchNode(state, n.X) case opReturnStmt: n, ok := n.(*ast.ReturnStmt) - return ok && m.matchExprSlice(n.Results) + return ok && m.matchExprSlice(state, n.Results) case opLabeledStmt: n, ok := n.(*ast.LabeledStmt) - return ok && m.matchNode(n.Label) && m.matchNode(n.Stmt) + return ok && m.matchNode(state, n.Label) && m.matchNode(state, n.Stmt) case opSimpleLabeledStmt: n, ok := n.(*ast.LabeledStmt) - return ok && m.stringValue(inst) == n.Label.Name && m.matchNode(n.Stmt) + return ok && m.stringValue(inst) == n.Label.Name && m.matchNode(state, n.Stmt) case opLabeledBranchStmt: n, ok := n.(*ast.BranchStmt) - return ok && n.Label != nil && token.Token(inst.value) == n.Tok && m.matchNode(n.Label) + return ok && n.Label != nil && token.Token(inst.value) == n.Tok && m.matchNode(state, n.Label) case opSimpleLabeledBranchStmt: n, ok := n.(*ast.BranchStmt) return ok && n.Label != nil && m.stringValue(inst) == n.Label.Name && token.Token(inst.value) == n.Tok @@ -442,100 +501,124 @@ func (m *matcher) matchNodeWithInst(inst instruction, n ast.Node) bool { case opFuncDecl: n, ok := n.(*ast.FuncDecl) return ok && n.Recv == nil && n.Body != nil && - m.matchNode(n.Name) && m.matchNode(n.Type) && m.matchNode(n.Body) + m.matchNode(state, n.Name) && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) case opFuncProtoDecl: n, ok := n.(*ast.FuncDecl) return ok && n.Recv == nil && n.Body == nil && - m.matchNode(n.Name) && m.matchNode(n.Type) + m.matchNode(state, n.Name) && m.matchNode(state, n.Type) case opMethodDecl: n, ok := n.(*ast.FuncDecl) return ok && n.Recv != nil && n.Body != nil && - m.matchNode(n.Recv) && m.matchNode(n.Name) && m.matchNode(n.Type) && m.matchNode(n.Body) + m.matchNode(state, n.Recv) && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) && m.matchNode(state, n.Body) case opMethodProtoDecl: n, ok := n.(*ast.FuncDecl) return ok && n.Recv != nil && n.Body == nil && - m.matchNode(n.Recv) && m.matchNode(n.Name) && m.matchNode(n.Type) + m.matchNode(state, n.Recv) && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) + case opValueSpec: + n, ok := n.(*ast.ValueSpec) + return ok && len(n.Values) == 0 && n.Type == nil && + len(n.Names) == 1 && m.matchNode(state, n.Names[0]) case opValueInitSpec: n, ok := n.(*ast.ValueSpec) return ok && len(n.Values) != 0 && n.Type == nil && - m.matchIdentSlice(n.Names) && m.matchExprSlice(n.Values) + m.matchIdentSlice(state, n.Names) && m.matchExprSlice(state, n.Values) case opTypedValueSpec: n, ok := n.(*ast.ValueSpec) return ok && len(n.Values) == 0 && n.Type != nil && - m.matchIdentSlice(n.Names) && m.matchNode(n.Type) + m.matchIdentSlice(state, n.Names) && m.matchNode(state, n.Type) case opTypedValueInitSpec: n, ok := n.(*ast.ValueSpec) return ok && len(n.Values) != 0 && n.Type != nil && - m.matchIdentSlice(n.Names) && m.matchNode(n.Type) && m.matchExprSlice(n.Values) + m.matchIdentSlice(state, n.Names) && m.matchNode(state, n.Type) && m.matchExprSlice(state, n.Values) case opTypeSpec: n, ok := n.(*ast.TypeSpec) - return ok && !n.Assign.IsValid() && m.matchNode(n.Name) && m.matchNode(n.Type) + return ok && !n.Assign.IsValid() && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) case opTypeAliasSpec: n, ok := n.(*ast.TypeSpec) - return ok && n.Assign.IsValid() && m.matchNode(n.Name) && m.matchNode(n.Type) + return ok && n.Assign.IsValid() && m.matchNode(state, n.Name) && m.matchNode(state, n.Type) + + case opDeclStmt: + n, ok := n.(*ast.DeclStmt) + return ok && m.matchNode(state, n.Decl) case opConstDecl: n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.CONST && m.matchSpecSlice(n.Specs) + return ok && n.Tok == token.CONST && m.matchSpecSlice(state, n.Specs) case opVarDecl: n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.VAR && m.matchSpecSlice(n.Specs) + return ok && n.Tok == token.VAR && m.matchSpecSlice(state, n.Specs) case opTypeDecl: n, ok := n.(*ast.GenDecl) - return ok && n.Tok == token.TYPE && m.matchSpecSlice(n.Specs) + return ok && n.Tok == token.TYPE && m.matchSpecSlice(state, n.Specs) case opEmptyPackage: n, ok := n.(*ast.File) - return ok && len(n.Imports) == 0 && len(n.Decls) == 0 && m.matchNode(n.Name) + return ok && len(n.Imports) == 0 && len(n.Decls) == 0 && m.matchNode(state, n.Name) default: panic(fmt.Sprintf("unexpected op %s", inst.op)) } } -func (m *matcher) matchNode(n ast.Node) bool { - return m.matchNodeWithInst(m.nextInst(), n) +func (m *matcher) matchNode(state *MatcherState, n ast.Node) bool { + return m.matchNodeWithInst(state, m.nextInst(state), n) } -func (m *matcher) matchStmtSlice(stmts []ast.Stmt) bool { - matched, _ := m.matchNodeList(stmtSlice(stmts), false) +func (m *matcher) matchArgList(state *MatcherState, exprs []ast.Expr) bool { + inst := m.nextInst(state) + if inst.op != opSimpleArgList { + return m.matchExprSlice(state, exprs) + } + if len(exprs) != int(inst.value) { + return false + } + for _, x := range exprs { + if !m.matchNode(state, x) { + return false + } + } + return true +} + +func (m *matcher) matchStmtSlice(state *MatcherState, stmts []ast.Stmt) bool { + matched, _ := m.matchNodeList(state, stmtSlice(stmts), false) return matched != nil } -func (m *matcher) matchExprSlice(exprs []ast.Expr) bool { - matched, _ := m.matchNodeList(exprSlice(exprs), false) +func (m *matcher) matchExprSlice(state *MatcherState, exprs []ast.Expr) bool { + matched, _ := m.matchNodeList(state, ExprSlice(exprs), false) return matched != nil } -func (m *matcher) matchFieldSlice(fields []*ast.Field) bool { - matched, _ := m.matchNodeList(fieldSlice(fields), false) +func (m *matcher) matchFieldSlice(state *MatcherState, fields []*ast.Field) bool { + matched, _ := m.matchNodeList(state, fieldSlice(fields), false) return matched != nil } -func (m *matcher) matchIdentSlice(idents []*ast.Ident) bool { - matched, _ := m.matchNodeList(identSlice(idents), false) +func (m *matcher) matchIdentSlice(state *MatcherState, idents []*ast.Ident) bool { + matched, _ := m.matchNodeList(state, identSlice(idents), false) return matched != nil } -func (m *matcher) matchSpecSlice(specs []ast.Spec) bool { - matched, _ := m.matchNodeList(specSlice(specs), false) +func (m *matcher) matchSpecSlice(state *MatcherState, specs []ast.Spec) bool { + matched, _ := m.matchNodeList(state, specSlice(specs), false) return matched != nil } // matchNodeList matches two lists of nodes. It uses a common algorithm to match // wildcard patterns with any number of nodes without recursion. -func (m *matcher) matchNodeList(nodes nodeSlice, partial bool) (ast.Node, int) { - sliceLen := nodes.len() - inst := m.nextInst() +func (m *matcher) matchNodeList(state *MatcherState, nodes NodeSlice, partial bool) (ast.Node, int) { + sliceLen := nodes.Len() + inst := m.nextInst(state) if inst.op == opEnd { if sliceLen == 0 { return nodes, 0 } return nil, -1 } - pcBase := m.pc + pcBase := state.pc pcNext := 0 j := 0 jNext := 0 @@ -560,14 +643,14 @@ func (m *matcher) matchNodeList(nodes nodeSlice, partial bool) (ast.Node, int) { if next > sliceLen { return // would be discarded anyway } - pcNext = m.pc - 1 + pcNext = state.pc - 1 jNext = next - stack = append(stack, restart{m.capture, pcNext, next, wildStart, wildName}) + stack = append(stack, restart{state.capture, pcNext, next, wildStart, wildName}) } pop := func() { j = jNext - m.pc = pcNext - m.capture = stack[len(stack)-1].matches + state.pc = pcNext + state.capture = stack[len(stack)-1].matches wildName = stack[len(stack)-1].wildName wildStart = stack[len(stack)-1].wildStart stack = stack[:len(stack)-1] @@ -586,9 +669,9 @@ func (m *matcher) matchNodeList(nodes nodeSlice, partial bool) (ast.Node, int) { case "", "_": return true } - return m.matchNamed(wildName, nodes.slice(wildStart, j)) + return m.matchNamed(state, wildName, nodes.slice(wildStart, j)) } - for ; inst.op != opEnd || j < sliceLen; inst = m.nextInst() { + for ; inst.op != opEnd || j < sliceLen; inst = m.nextInst(state) { if inst.op != opEnd { if inst.op == opNodeSeq || inst.op == opNamedNodeSeq { // keep track of where this wildcard @@ -608,13 +691,13 @@ func (m *matcher) matchNodeList(nodes nodeSlice, partial bool) (ast.Node, int) { push(j + 1) continue } - if partial && m.pc == pcBase { + if partial && state.pc == pcBase { // let "b; c" match "a; b; c" // (simulates a $*_ at the beginning) partialStart = j push(j + 1) } - if j < sliceLen && wouldMatch() && m.matchNodeWithInst(inst, nodes.at(j)) { + if j < sliceLen && wouldMatch() && m.matchNodeWithInst(state, inst, nodes.At(j)) { // ordinary match wildName = "" j++ @@ -626,7 +709,7 @@ func (m *matcher) matchNodeList(nodes nodeSlice, partial bool) (ast.Node, int) { break // let "b; c" match "b; c; d" } // mismatch, try to restart - if 0 < jNext && jNext <= sliceLen && (m.pc != pcNext || j != jNext) { + if 0 < jNext && jNext <= sliceLen && (state.pc != pcNext || j != jNext) { pop() continue } @@ -698,8 +781,8 @@ func equalNodes(x, y ast.Node) bool { } } return true - case exprSlice: - y, ok := y.(exprSlice) + case ExprSlice: + y, ok := y.(ExprSlice) if !ok || len(x) != len(y) { return false } @@ -709,6 +792,18 @@ func equalNodes(x, y ast.Node) bool { } } return true + case declSlice: + y, ok := y.(declSlice) + if !ok || len(x) != len(y) { + return false + } + for i := range x { + if !astequal.Decl(x[i], y[i]) { + return false + } + } + return true + default: return astequal.Node(x, y) } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operation_string.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operation_string.go index 9f50e2795..898cc8d56 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operation_string.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operation_string.go @@ -15,111 +15,122 @@ func _() { _ = x[opNamedNodeSeq-4] _ = x[opOptNode-5] _ = x[opNamedOptNode-6] - _ = x[opMultiStmt-7] - _ = x[opMultiExpr-8] - _ = x[opEnd-9] - _ = x[opBasicLit-10] - _ = x[opStrictIntLit-11] - _ = x[opStrictFloatLit-12] - _ = x[opStrictCharLit-13] - _ = x[opStrictStringLit-14] - _ = x[opStrictComplexLit-15] - _ = x[opIdent-16] - _ = x[opIndexExpr-17] - _ = x[opSliceExpr-18] - _ = x[opSliceFromExpr-19] - _ = x[opSliceToExpr-20] - _ = x[opSliceFromToExpr-21] - _ = x[opSliceToCapExpr-22] - _ = x[opSliceFromToCapExpr-23] - _ = x[opFuncLit-24] - _ = x[opCompositeLit-25] - _ = x[opTypedCompositeLit-26] - _ = x[opSimpleSelectorExpr-27] - _ = x[opSelectorExpr-28] - _ = x[opTypeAssertExpr-29] - _ = x[opTypeSwitchAssertExpr-30] - _ = x[opVoidFuncType-31] - _ = x[opFuncType-32] - _ = x[opArrayType-33] - _ = x[opSliceType-34] - _ = x[opMapType-35] - _ = x[opChanType-36] - _ = x[opKeyValueExpr-37] - _ = x[opEllipsis-38] - _ = x[opTypedEllipsis-39] - _ = x[opStarExpr-40] - _ = x[opUnaryExpr-41] - _ = x[opBinaryExpr-42] - _ = x[opParenExpr-43] - _ = x[opVariadicCallExpr-44] - _ = x[opCallExpr-45] - _ = x[opAssignStmt-46] - _ = x[opMultiAssignStmt-47] - _ = x[opBranchStmt-48] - _ = x[opSimpleLabeledBranchStmt-49] - _ = x[opLabeledBranchStmt-50] - _ = x[opSimpleLabeledStmt-51] - _ = x[opLabeledStmt-52] - _ = x[opBlockStmt-53] - _ = x[opExprStmt-54] - _ = x[opGoStmt-55] - _ = x[opDeferStmt-56] - _ = x[opSendStmt-57] - _ = x[opEmptyStmt-58] - _ = x[opIncDecStmt-59] - _ = x[opReturnStmt-60] - _ = x[opIfStmt-61] - _ = x[opIfInitStmt-62] - _ = x[opIfElseStmt-63] - _ = x[opIfInitElseStmt-64] - _ = x[opIfNamedOptStmt-65] - _ = x[opIfNamedOptElseStmt-66] - _ = x[opSwitchStmt-67] - _ = x[opSwitchTagStmt-68] - _ = x[opSwitchInitStmt-69] - _ = x[opSwitchInitTagStmt-70] - _ = x[opSelectStmt-71] - _ = x[opTypeSwitchStmt-72] - _ = x[opTypeSwitchInitStmt-73] - _ = x[opCaseClause-74] - _ = x[opDefaultCaseClause-75] - _ = x[opCommClause-76] - _ = x[opDefaultCommClause-77] - _ = x[opForStmt-78] - _ = x[opForPostStmt-79] - _ = x[opForCondStmt-80] - _ = x[opForCondPostStmt-81] - _ = x[opForInitStmt-82] - _ = x[opForInitPostStmt-83] - _ = x[opForInitCondStmt-84] - _ = x[opForInitCondPostStmt-85] - _ = x[opRangeStmt-86] - _ = x[opRangeKeyStmt-87] - _ = x[opRangeKeyValueStmt-88] - _ = x[opFieldList-89] - _ = x[opUnnamedField-90] - _ = x[opSimpleField-91] - _ = x[opField-92] - _ = x[opMultiField-93] - _ = x[opValueInitSpec-94] - _ = x[opTypedValueInitSpec-95] - _ = x[opTypedValueSpec-96] - _ = x[opTypeSpec-97] - _ = x[opTypeAliasSpec-98] - _ = x[opFuncDecl-99] - _ = x[opMethodDecl-100] - _ = x[opFuncProtoDecl-101] - _ = x[opMethodProtoDecl-102] - _ = x[opConstDecl-103] - _ = x[opVarDecl-104] - _ = x[opTypeDecl-105] - _ = x[opEmptyPackage-106] + _ = x[opFieldNode-7] + _ = x[opNamedFieldNode-8] + _ = x[opMultiStmt-9] + _ = x[opMultiExpr-10] + _ = x[opMultiDecl-11] + _ = x[opEnd-12] + _ = x[opBasicLit-13] + _ = x[opStrictIntLit-14] + _ = x[opStrictFloatLit-15] + _ = x[opStrictCharLit-16] + _ = x[opStrictStringLit-17] + _ = x[opStrictComplexLit-18] + _ = x[opIdent-19] + _ = x[opStdlibPkg-20] + _ = x[opIndexExpr-21] + _ = x[opSliceExpr-22] + _ = x[opSliceFromExpr-23] + _ = x[opSliceToExpr-24] + _ = x[opSliceFromToExpr-25] + _ = x[opSliceToCapExpr-26] + _ = x[opSliceFromToCapExpr-27] + _ = x[opFuncLit-28] + _ = x[opCompositeLit-29] + _ = x[opTypedCompositeLit-30] + _ = x[opSimpleSelectorExpr-31] + _ = x[opSelectorExpr-32] + _ = x[opTypeAssertExpr-33] + _ = x[opTypeSwitchAssertExpr-34] + _ = x[opStructType-35] + _ = x[opInterfaceType-36] + _ = x[opVoidFuncType-37] + _ = x[opFuncType-38] + _ = x[opArrayType-39] + _ = x[opSliceType-40] + _ = x[opMapType-41] + _ = x[opChanType-42] + _ = x[opKeyValueExpr-43] + _ = x[opEllipsis-44] + _ = x[opTypedEllipsis-45] + _ = x[opStarExpr-46] + _ = x[opUnaryExpr-47] + _ = x[opBinaryExpr-48] + _ = x[opParenExpr-49] + _ = x[opArgList-50] + _ = x[opSimpleArgList-51] + _ = x[opVariadicCallExpr-52] + _ = x[opNonVariadicCallExpr-53] + _ = x[opCallExpr-54] + _ = x[opAssignStmt-55] + _ = x[opMultiAssignStmt-56] + _ = x[opBranchStmt-57] + _ = x[opSimpleLabeledBranchStmt-58] + _ = x[opLabeledBranchStmt-59] + _ = x[opSimpleLabeledStmt-60] + _ = x[opLabeledStmt-61] + _ = x[opBlockStmt-62] + _ = x[opExprStmt-63] + _ = x[opGoStmt-64] + _ = x[opDeferStmt-65] + _ = x[opSendStmt-66] + _ = x[opEmptyStmt-67] + _ = x[opIncDecStmt-68] + _ = x[opReturnStmt-69] + _ = x[opIfStmt-70] + _ = x[opIfInitStmt-71] + _ = x[opIfElseStmt-72] + _ = x[opIfInitElseStmt-73] + _ = x[opIfNamedOptStmt-74] + _ = x[opIfNamedOptElseStmt-75] + _ = x[opSwitchStmt-76] + _ = x[opSwitchTagStmt-77] + _ = x[opSwitchInitStmt-78] + _ = x[opSwitchInitTagStmt-79] + _ = x[opSelectStmt-80] + _ = x[opTypeSwitchStmt-81] + _ = x[opTypeSwitchInitStmt-82] + _ = x[opCaseClause-83] + _ = x[opDefaultCaseClause-84] + _ = x[opCommClause-85] + _ = x[opDefaultCommClause-86] + _ = x[opForStmt-87] + _ = x[opForPostStmt-88] + _ = x[opForCondStmt-89] + _ = x[opForCondPostStmt-90] + _ = x[opForInitStmt-91] + _ = x[opForInitPostStmt-92] + _ = x[opForInitCondStmt-93] + _ = x[opForInitCondPostStmt-94] + _ = x[opRangeStmt-95] + _ = x[opRangeKeyStmt-96] + _ = x[opRangeKeyValueStmt-97] + _ = x[opFieldList-98] + _ = x[opUnnamedField-99] + _ = x[opSimpleField-100] + _ = x[opField-101] + _ = x[opMultiField-102] + _ = x[opValueSpec-103] + _ = x[opValueInitSpec-104] + _ = x[opTypedValueInitSpec-105] + _ = x[opTypedValueSpec-106] + _ = x[opTypeSpec-107] + _ = x[opTypeAliasSpec-108] + _ = x[opFuncDecl-109] + _ = x[opMethodDecl-110] + _ = x[opFuncProtoDecl-111] + _ = x[opMethodProtoDecl-112] + _ = x[opDeclStmt-113] + _ = x[opConstDecl-114] + _ = x[opVarDecl-115] + _ = x[opTypeDecl-116] + _ = x[opEmptyPackage-117] } -const _operation_name = "InvalidNodeNamedNodeNodeSeqNamedNodeSeqOptNodeNamedOptNodeMultiStmtMultiExprEndBasicLitStrictIntLitStrictFloatLitStrictCharLitStrictStringLitStrictComplexLitIdentIndexExprSliceExprSliceFromExprSliceToExprSliceFromToExprSliceToCapExprSliceFromToCapExprFuncLitCompositeLitTypedCompositeLitSimpleSelectorExprSelectorExprTypeAssertExprTypeSwitchAssertExprVoidFuncTypeFuncTypeArrayTypeSliceTypeMapTypeChanTypeKeyValueExprEllipsisTypedEllipsisStarExprUnaryExprBinaryExprParenExprVariadicCallExprCallExprAssignStmtMultiAssignStmtBranchStmtSimpleLabeledBranchStmtLabeledBranchStmtSimpleLabeledStmtLabeledStmtBlockStmtExprStmtGoStmtDeferStmtSendStmtEmptyStmtIncDecStmtReturnStmtIfStmtIfInitStmtIfElseStmtIfInitElseStmtIfNamedOptStmtIfNamedOptElseStmtSwitchStmtSwitchTagStmtSwitchInitStmtSwitchInitTagStmtSelectStmtTypeSwitchStmtTypeSwitchInitStmtCaseClauseDefaultCaseClauseCommClauseDefaultCommClauseForStmtForPostStmtForCondStmtForCondPostStmtForInitStmtForInitPostStmtForInitCondStmtForInitCondPostStmtRangeStmtRangeKeyStmtRangeKeyValueStmtFieldListUnnamedFieldSimpleFieldFieldMultiFieldValueInitSpecTypedValueInitSpecTypedValueSpecTypeSpecTypeAliasSpecFuncDeclMethodDeclFuncProtoDeclMethodProtoDeclConstDeclVarDeclTypeDeclEmptyPackage" +const _operation_name = "InvalidNodeNamedNodeNodeSeqNamedNodeSeqOptNodeNamedOptNodeFieldNodeNamedFieldNodeMultiStmtMultiExprMultiDeclEndBasicLitStrictIntLitStrictFloatLitStrictCharLitStrictStringLitStrictComplexLitIdentStdlibPkgIndexExprSliceExprSliceFromExprSliceToExprSliceFromToExprSliceToCapExprSliceFromToCapExprFuncLitCompositeLitTypedCompositeLitSimpleSelectorExprSelectorExprTypeAssertExprTypeSwitchAssertExprStructTypeInterfaceTypeVoidFuncTypeFuncTypeArrayTypeSliceTypeMapTypeChanTypeKeyValueExprEllipsisTypedEllipsisStarExprUnaryExprBinaryExprParenExprArgListSimpleArgListVariadicCallExprNonVariadicCallExprCallExprAssignStmtMultiAssignStmtBranchStmtSimpleLabeledBranchStmtLabeledBranchStmtSimpleLabeledStmtLabeledStmtBlockStmtExprStmtGoStmtDeferStmtSendStmtEmptyStmtIncDecStmtReturnStmtIfStmtIfInitStmtIfElseStmtIfInitElseStmtIfNamedOptStmtIfNamedOptElseStmtSwitchStmtSwitchTagStmtSwitchInitStmtSwitchInitTagStmtSelectStmtTypeSwitchStmtTypeSwitchInitStmtCaseClauseDefaultCaseClauseCommClauseDefaultCommClauseForStmtForPostStmtForCondStmtForCondPostStmtForInitStmtForInitPostStmtForInitCondStmtForInitCondPostStmtRangeStmtRangeKeyStmtRangeKeyValueStmtFieldListUnnamedFieldSimpleFieldFieldMultiFieldValueSpecValueInitSpecTypedValueInitSpecTypedValueSpecTypeSpecTypeAliasSpecFuncDeclMethodDeclFuncProtoDeclMethodProtoDeclDeclStmtConstDeclVarDeclTypeDeclEmptyPackage" -var _operation_index = [...]uint16{0, 7, 11, 20, 27, 39, 46, 58, 67, 76, 79, 87, 99, 113, 126, 141, 157, 162, 171, 180, 193, 204, 219, 233, 251, 258, 270, 287, 305, 317, 331, 351, 363, 371, 380, 389, 396, 404, 416, 424, 437, 445, 454, 464, 473, 489, 497, 507, 522, 532, 555, 572, 589, 600, 609, 617, 623, 632, 640, 649, 659, 669, 675, 685, 695, 709, 723, 741, 751, 764, 778, 795, 805, 819, 837, 847, 864, 874, 891, 898, 909, 920, 935, 946, 961, 976, 995, 1004, 1016, 1033, 1042, 1054, 1065, 1070, 1080, 1093, 1111, 1125, 1133, 1146, 1154, 1164, 1177, 1192, 1201, 1208, 1216, 1228} +var _operation_index = [...]uint16{0, 7, 11, 20, 27, 39, 46, 58, 67, 81, 90, 99, 108, 111, 119, 131, 145, 158, 173, 189, 194, 203, 212, 221, 234, 245, 260, 274, 292, 299, 311, 328, 346, 358, 372, 392, 402, 415, 427, 435, 444, 453, 460, 468, 480, 488, 501, 509, 518, 528, 537, 544, 557, 573, 592, 600, 610, 625, 635, 658, 675, 692, 703, 712, 720, 726, 735, 743, 752, 762, 772, 778, 788, 798, 812, 826, 844, 854, 867, 881, 898, 908, 922, 940, 950, 967, 977, 994, 1001, 1012, 1023, 1038, 1049, 1064, 1079, 1098, 1107, 1119, 1136, 1145, 1157, 1168, 1173, 1183, 1192, 1205, 1223, 1237, 1245, 1258, 1266, 1276, 1289, 1304, 1312, 1321, 1328, 1336, 1348} func (i operation) String() string { if i >= operation(len(_operation_index)-1) { diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operations.gen.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operations.gen.go index f4d7cff82..7f6471bb1 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operations.gen.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/operations.gen.go @@ -33,464 +33,513 @@ const ( // ValueIndex: strings | wildcard name opNamedOptNode operation = 6 + // Tag: Node + opFieldNode operation = 7 + + // Tag: Node + // ValueIndex: strings | wildcard name + opNamedFieldNode operation = 8 + // Tag: StmtList // Args: stmts... // Example: f(); g() - opMultiStmt operation = 7 + opMultiStmt operation = 9 // Tag: ExprList // Args: exprs... // Example: f(), g() - opMultiExpr operation = 8 + opMultiExpr operation = 10 + + // Tag: DeclList + // Args: exprs... + // Example: f(), g() + opMultiDecl operation = 11 // Tag: Unknown - opEnd operation = 9 + opEnd operation = 12 // Tag: BasicLit // ValueIndex: ifaces | parsed literal value - opBasicLit operation = 10 + opBasicLit operation = 13 // Tag: BasicLit // ValueIndex: strings | raw literal value - opStrictIntLit operation = 11 + opStrictIntLit operation = 14 // Tag: BasicLit // ValueIndex: strings | raw literal value - opStrictFloatLit operation = 12 + opStrictFloatLit operation = 15 // Tag: BasicLit // ValueIndex: strings | raw literal value - opStrictCharLit operation = 13 + opStrictCharLit operation = 16 // Tag: BasicLit // ValueIndex: strings | raw literal value - opStrictStringLit operation = 14 + opStrictStringLit operation = 17 // Tag: BasicLit // ValueIndex: strings | raw literal value - opStrictComplexLit operation = 15 + opStrictComplexLit operation = 18 // Tag: Ident // ValueIndex: strings | ident name - opIdent operation = 16 + opIdent operation = 19 + + // Tag: Ident + // ValueIndex: strings | package name + opStdlibPkg operation = 20 // Tag: IndexExpr // Args: x expr - opIndexExpr operation = 17 + opIndexExpr operation = 21 // Tag: SliceExpr // Args: x - opSliceExpr operation = 18 + opSliceExpr operation = 22 // Tag: SliceExpr // Args: x from // Example: x[from:] - opSliceFromExpr operation = 19 + opSliceFromExpr operation = 23 // Tag: SliceExpr // Args: x to // Example: x[:to] - opSliceToExpr operation = 20 + opSliceToExpr operation = 24 // Tag: SliceExpr // Args: x from to // Example: x[from:to] - opSliceFromToExpr operation = 21 + opSliceFromToExpr operation = 25 // Tag: SliceExpr // Args: x from cap // Example: x[:from:cap] - opSliceToCapExpr operation = 22 + opSliceToCapExpr operation = 26 // Tag: SliceExpr // Args: x from to cap // Example: x[from:to:cap] - opSliceFromToCapExpr operation = 23 + opSliceFromToCapExpr operation = 27 // Tag: FuncLit // Args: type block - opFuncLit operation = 24 + opFuncLit operation = 28 // Tag: CompositeLit // Args: elts... // Example: {elts...} - opCompositeLit operation = 25 + opCompositeLit operation = 29 // Tag: CompositeLit // Args: typ elts... // Example: typ{elts...} - opTypedCompositeLit operation = 26 + opTypedCompositeLit operation = 30 // Tag: SelectorExpr // Args: x // ValueIndex: strings | selector name - opSimpleSelectorExpr operation = 27 + opSimpleSelectorExpr operation = 31 // Tag: SelectorExpr // Args: x sel - opSelectorExpr operation = 28 + opSelectorExpr operation = 32 // Tag: TypeAssertExpr // Args: x typ - opTypeAssertExpr operation = 29 + opTypeAssertExpr operation = 33 // Tag: TypeAssertExpr // Args: x - opTypeSwitchAssertExpr operation = 30 + opTypeSwitchAssertExpr operation = 34 + + // Tag: StructType + // Args: fields + opStructType operation = 35 + + // Tag: StructType + // Args: fields + opInterfaceType operation = 36 // Tag: FuncType // Args: params - opVoidFuncType operation = 31 + opVoidFuncType operation = 37 // Tag: FuncType // Args: params results - opFuncType operation = 32 + opFuncType operation = 38 // Tag: ArrayType // Args: length elem - opArrayType operation = 33 + opArrayType operation = 39 // Tag: ArrayType // Args: elem - opSliceType operation = 34 + opSliceType operation = 40 // Tag: MapType // Args: key value - opMapType operation = 35 + opMapType operation = 41 // Tag: ChanType // Args: value // Value: ast.ChanDir | channel direction - opChanType operation = 36 + opChanType operation = 42 // Tag: KeyValueExpr // Args: key value - opKeyValueExpr operation = 37 + opKeyValueExpr operation = 43 // Tag: Ellipsis - opEllipsis operation = 38 + opEllipsis operation = 44 // Tag: Ellipsis // Args: type - opTypedEllipsis operation = 39 + opTypedEllipsis operation = 45 // Tag: StarExpr // Args: x - opStarExpr operation = 40 + opStarExpr operation = 46 // Tag: UnaryExpr // Args: x // Value: token.Token | unary operator - opUnaryExpr operation = 41 + opUnaryExpr operation = 47 // Tag: BinaryExpr // Args: x y // Value: token.Token | binary operator - opBinaryExpr operation = 42 + opBinaryExpr operation = 48 // Tag: ParenExpr // Args: x - opParenExpr operation = 43 + opParenExpr operation = 49 + + // Tag: Unknown + // Args: exprs... + // Example: 1, 2, 3 + opArgList operation = 50 + + // Tag: Unknown + // Like ArgList, but pattern contains no $* + // Args: exprs[] + // Example: 1, 2, 3 + // Value: int | slice len + opSimpleArgList operation = 51 // Tag: CallExpr - // Args: fn args... + // Args: fn args // Example: f(1, xs...) - opVariadicCallExpr operation = 44 + opVariadicCallExpr operation = 52 // Tag: CallExpr - // Args: fn args... + // Args: fn args // Example: f(1, xs) - opCallExpr operation = 45 + opNonVariadicCallExpr operation = 53 + + // Tag: CallExpr + // Args: fn args + // Example: f(1, xs) or f(1, xs...) + opCallExpr operation = 54 // Tag: AssignStmt // Args: lhs rhs // Example: lhs := rhs() // Value: token.Token | ':=' or '=' - opAssignStmt operation = 46 + opAssignStmt operation = 55 // Tag: AssignStmt // Args: lhs... rhs... // Example: lhs1, lhs2 := rhs() // Value: token.Token | ':=' or '=' - opMultiAssignStmt operation = 47 + opMultiAssignStmt operation = 56 // Tag: BranchStmt // Args: x // Value: token.Token | branch kind - opBranchStmt operation = 48 + opBranchStmt operation = 57 // Tag: BranchStmt // Args: x // Value: token.Token | branch kind // ValueIndex: strings | label name - opSimpleLabeledBranchStmt operation = 49 + opSimpleLabeledBranchStmt operation = 58 // Tag: BranchStmt // Args: label x // Value: token.Token | branch kind - opLabeledBranchStmt operation = 50 + opLabeledBranchStmt operation = 59 // Tag: LabeledStmt // Args: x // ValueIndex: strings | label name - opSimpleLabeledStmt operation = 51 + opSimpleLabeledStmt operation = 60 // Tag: LabeledStmt // Args: label x - opLabeledStmt operation = 52 + opLabeledStmt operation = 61 // Tag: BlockStmt // Args: body... - opBlockStmt operation = 53 + opBlockStmt operation = 62 // Tag: ExprStmt // Args: x - opExprStmt operation = 54 + opExprStmt operation = 63 // Tag: GoStmt // Args: x - opGoStmt operation = 55 + opGoStmt operation = 64 // Tag: DeferStmt // Args: x - opDeferStmt operation = 56 + opDeferStmt operation = 65 // Tag: SendStmt // Args: ch value - opSendStmt operation = 57 + opSendStmt operation = 66 // Tag: EmptyStmt - opEmptyStmt operation = 58 + opEmptyStmt operation = 67 // Tag: IncDecStmt // Args: x // Value: token.Token | '++' or '--' - opIncDecStmt operation = 59 + opIncDecStmt operation = 68 // Tag: ReturnStmt // Args: results... - opReturnStmt operation = 60 + opReturnStmt operation = 69 // Tag: IfStmt // Args: cond block // Example: if cond {} - opIfStmt operation = 61 + opIfStmt operation = 70 // Tag: IfStmt // Args: init cond block // Example: if init; cond {} - opIfInitStmt operation = 62 + opIfInitStmt operation = 71 // Tag: IfStmt // Args: cond block else // Example: if cond {} else ... - opIfElseStmt operation = 63 + opIfElseStmt operation = 72 // Tag: IfStmt // Args: init cond block else // Example: if init; cond {} else ... - opIfInitElseStmt operation = 64 + opIfInitElseStmt operation = 73 // Tag: IfStmt // Args: block // Example: if $*x {} // ValueIndex: strings | wildcard name - opIfNamedOptStmt operation = 65 + opIfNamedOptStmt operation = 74 // Tag: IfStmt // Args: block else // Example: if $*x {} else ... // ValueIndex: strings | wildcard name - opIfNamedOptElseStmt operation = 66 + opIfNamedOptElseStmt operation = 75 // Tag: SwitchStmt // Args: body... // Example: switch {} - opSwitchStmt operation = 67 + opSwitchStmt operation = 76 // Tag: SwitchStmt // Args: tag body... // Example: switch tag {} - opSwitchTagStmt operation = 68 + opSwitchTagStmt operation = 77 // Tag: SwitchStmt // Args: init body... // Example: switch init; {} - opSwitchInitStmt operation = 69 + opSwitchInitStmt operation = 78 // Tag: SwitchStmt // Args: init tag body... // Example: switch init; tag {} - opSwitchInitTagStmt operation = 70 + opSwitchInitTagStmt operation = 79 // Tag: SelectStmt // Args: body... - opSelectStmt operation = 71 + opSelectStmt operation = 80 // Tag: TypeSwitchStmt // Args: x block // Example: switch x.(type) {} - opTypeSwitchStmt operation = 72 + opTypeSwitchStmt operation = 81 // Tag: TypeSwitchStmt // Args: init x block // Example: switch init; x.(type) {} - opTypeSwitchInitStmt operation = 73 + opTypeSwitchInitStmt operation = 82 // Tag: CaseClause // Args: values... body... - opCaseClause operation = 74 + opCaseClause operation = 83 // Tag: CaseClause // Args: body... - opDefaultCaseClause operation = 75 + opDefaultCaseClause operation = 84 // Tag: CommClause // Args: comm body... - opCommClause operation = 76 + opCommClause operation = 85 // Tag: CommClause // Args: body... - opDefaultCommClause operation = 77 + opDefaultCommClause operation = 86 // Tag: ForStmt // Args: blocl // Example: for {} - opForStmt operation = 78 + opForStmt operation = 87 // Tag: ForStmt // Args: post block // Example: for ; ; post {} - opForPostStmt operation = 79 + opForPostStmt operation = 88 // Tag: ForStmt // Args: cond block // Example: for ; cond; {} - opForCondStmt operation = 80 + opForCondStmt operation = 89 // Tag: ForStmt // Args: cond post block // Example: for ; cond; post {} - opForCondPostStmt operation = 81 + opForCondPostStmt operation = 90 // Tag: ForStmt // Args: init block // Example: for init; ; {} - opForInitStmt operation = 82 + opForInitStmt operation = 91 // Tag: ForStmt // Args: init post block // Example: for init; ; post {} - opForInitPostStmt operation = 83 + opForInitPostStmt operation = 92 // Tag: ForStmt // Args: init cond block // Example: for init; cond; {} - opForInitCondStmt operation = 84 + opForInitCondStmt operation = 93 // Tag: ForStmt // Args: init cond post block // Example: for init; cond; post {} - opForInitCondPostStmt operation = 85 + opForInitCondPostStmt operation = 94 // Tag: RangeStmt // Args: x block // Example: for range x {} - opRangeStmt operation = 86 + opRangeStmt operation = 95 // Tag: RangeStmt // Args: key x block // Example: for key := range x {} // Value: token.Token | ':=' or '=' - opRangeKeyStmt operation = 87 + opRangeKeyStmt operation = 96 // Tag: RangeStmt // Args: key value x block // Example: for key, value := range x {} // Value: token.Token | ':=' or '=' - opRangeKeyValueStmt operation = 88 + opRangeKeyValueStmt operation = 97 // Tag: Unknown // Args: fields... - opFieldList operation = 89 + opFieldList operation = 98 // Tag: Unknown // Args: typ // Example: type - opUnnamedField operation = 90 + opUnnamedField operation = 99 // Tag: Unknown // Args: typ // Example: name type // ValueIndex: strings | field name - opSimpleField operation = 91 + opSimpleField operation = 100 // Tag: Unknown // Args: name typ // Example: $name type - opField operation = 92 + opField operation = 101 // Tag: Unknown // Args: names... typ // Example: name1, name2 type - opMultiField operation = 93 + opMultiField operation = 102 + + // Tag: ValueSpec + // Args: value + opValueSpec operation = 103 // Tag: ValueSpec // Args: lhs... rhs... // Example: lhs = rhs - opValueInitSpec operation = 94 + opValueInitSpec operation = 104 // Tag: ValueSpec // Args: lhs... type rhs... // Example: lhs typ = rhs - opTypedValueInitSpec operation = 95 + opTypedValueInitSpec operation = 105 // Tag: ValueSpec // Args: lhs... type // Example: lhs typ - opTypedValueSpec operation = 96 + opTypedValueSpec operation = 106 // Tag: TypeSpec // Args: name type // Example: name type - opTypeSpec operation = 97 + opTypeSpec operation = 107 // Tag: TypeSpec // Args: name type // Example: name = type - opTypeAliasSpec operation = 98 + opTypeAliasSpec operation = 108 // Tag: FuncDecl // Args: name type block - opFuncDecl operation = 99 + opFuncDecl operation = 109 // Tag: FuncDecl // Args: recv name type block - opMethodDecl operation = 100 + opMethodDecl operation = 110 // Tag: FuncDecl // Args: name type - opFuncProtoDecl operation = 101 + opFuncProtoDecl operation = 111 // Tag: FuncDecl // Args: recv name type - opMethodProtoDecl operation = 102 + opMethodProtoDecl operation = 112 + + // Tag: DeclStmt + // Args: decl + opDeclStmt operation = 113 // Tag: GenDecl // Args: valuespecs... - opConstDecl operation = 103 + opConstDecl operation = 114 // Tag: GenDecl // Args: valuespecs... - opVarDecl operation = 104 + opVarDecl operation = 115 // Tag: GenDecl // Args: typespecs... - opTypeDecl operation = 105 + opTypeDecl operation = 116 // Tag: File // Args: name - opEmptyPackage operation = 106 + opEmptyPackage operation = 117 ) type operationInfo struct { @@ -499,6 +548,7 @@ type operationInfo struct { ValueKind valueKind ExtraValueKind valueKind VariadicMap bitmap64 + SliceIndex int } var operationInfoTable = [256]operationInfo{ @@ -510,6 +560,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opNamedNode: { Tag: nodetag.Node, @@ -517,6 +568,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opNodeSeq: { Tag: nodetag.Unknown, @@ -524,6 +576,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opNamedNodeSeq: { Tag: nodetag.Unknown, @@ -531,6 +584,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opOptNode: { Tag: nodetag.Unknown, @@ -538,6 +592,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opNamedOptNode: { Tag: nodetag.Unknown, @@ -545,6 +600,23 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opFieldNode: { + Tag: nodetag.Node, + NumArgs: 0, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opNamedFieldNode: { + Tag: nodetag.Node, + NumArgs: 0, + ValueKind: emptyValue, + ExtraValueKind: stringValue, + VariadicMap: 0, // 0 + SliceIndex: -1, }, opMultiStmt: { Tag: nodetag.StmtList, @@ -552,6 +624,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opMultiExpr: { Tag: nodetag.ExprList, @@ -559,6 +632,15 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, + }, + opMultiDecl: { + Tag: nodetag.DeclList, + NumArgs: 1, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 1, // 1 + SliceIndex: -1, }, opEnd: { Tag: nodetag.Unknown, @@ -566,6 +648,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opBasicLit: { Tag: nodetag.BasicLit, @@ -573,6 +656,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: ifaceValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opStrictIntLit: { Tag: nodetag.BasicLit, @@ -580,6 +664,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opStrictFloatLit: { Tag: nodetag.BasicLit, @@ -587,6 +672,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opStrictCharLit: { Tag: nodetag.BasicLit, @@ -594,6 +680,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opStrictStringLit: { Tag: nodetag.BasicLit, @@ -601,6 +688,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opStrictComplexLit: { Tag: nodetag.BasicLit, @@ -608,6 +696,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIdent: { Tag: nodetag.Ident, @@ -615,6 +704,15 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opStdlibPkg: { + Tag: nodetag.Ident, + NumArgs: 0, + ValueKind: emptyValue, + ExtraValueKind: stringValue, + VariadicMap: 0, // 0 + SliceIndex: -1, }, opIndexExpr: { Tag: nodetag.IndexExpr, @@ -622,6 +720,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceExpr: { Tag: nodetag.SliceExpr, @@ -629,6 +728,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceFromExpr: { Tag: nodetag.SliceExpr, @@ -636,6 +736,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceToExpr: { Tag: nodetag.SliceExpr, @@ -643,6 +744,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceFromToExpr: { Tag: nodetag.SliceExpr, @@ -650,6 +752,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceToCapExpr: { Tag: nodetag.SliceExpr, @@ -657,6 +760,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceFromToCapExpr: { Tag: nodetag.SliceExpr, @@ -664,6 +768,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opFuncLit: { Tag: nodetag.FuncLit, @@ -671,6 +776,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opCompositeLit: { Tag: nodetag.CompositeLit, @@ -678,6 +784,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opTypedCompositeLit: { Tag: nodetag.CompositeLit, @@ -685,6 +792,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 2, // 10 + SliceIndex: -1, }, opSimpleSelectorExpr: { Tag: nodetag.SelectorExpr, @@ -692,6 +800,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSelectorExpr: { Tag: nodetag.SelectorExpr, @@ -699,6 +808,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opTypeAssertExpr: { Tag: nodetag.TypeAssertExpr, @@ -706,6 +816,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opTypeSwitchAssertExpr: { Tag: nodetag.TypeAssertExpr, @@ -713,6 +824,23 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opStructType: { + Tag: nodetag.StructType, + NumArgs: 1, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opInterfaceType: { + Tag: nodetag.StructType, + NumArgs: 1, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: -1, }, opVoidFuncType: { Tag: nodetag.FuncType, @@ -720,6 +848,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opFuncType: { Tag: nodetag.FuncType, @@ -727,6 +856,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opArrayType: { Tag: nodetag.ArrayType, @@ -734,6 +864,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSliceType: { Tag: nodetag.ArrayType, @@ -741,6 +872,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opMapType: { Tag: nodetag.MapType, @@ -748,6 +880,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opChanType: { Tag: nodetag.ChanType, @@ -755,6 +888,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: chandirValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opKeyValueExpr: { Tag: nodetag.KeyValueExpr, @@ -762,6 +896,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opEllipsis: { Tag: nodetag.Ellipsis, @@ -769,6 +904,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opTypedEllipsis: { Tag: nodetag.Ellipsis, @@ -776,6 +912,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opStarExpr: { Tag: nodetag.StarExpr, @@ -783,6 +920,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opUnaryExpr: { Tag: nodetag.UnaryExpr, @@ -790,6 +928,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opBinaryExpr: { Tag: nodetag.BinaryExpr, @@ -797,6 +936,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opParenExpr: { Tag: nodetag.ParenExpr, @@ -804,20 +944,47 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opArgList: { + Tag: nodetag.Unknown, + NumArgs: 1, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 1, // 1 + SliceIndex: -1, + }, + opSimpleArgList: { + Tag: nodetag.Unknown, + NumArgs: 1, + ValueKind: intValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: 0, }, opVariadicCallExpr: { Tag: nodetag.CallExpr, NumArgs: 2, ValueKind: emptyValue, ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 + VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opNonVariadicCallExpr: { + Tag: nodetag.CallExpr, + NumArgs: 2, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: -1, }, opCallExpr: { Tag: nodetag.CallExpr, NumArgs: 2, ValueKind: emptyValue, ExtraValueKind: emptyValue, - VariadicMap: 2, // 10 + VariadicMap: 0, // 0 + SliceIndex: -1, }, opAssignStmt: { Tag: nodetag.AssignStmt, @@ -825,6 +992,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opMultiAssignStmt: { Tag: nodetag.AssignStmt, @@ -832,6 +1000,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 3, // 11 + SliceIndex: -1, }, opBranchStmt: { Tag: nodetag.BranchStmt, @@ -839,6 +1008,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSimpleLabeledBranchStmt: { Tag: nodetag.BranchStmt, @@ -846,6 +1016,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opLabeledBranchStmt: { Tag: nodetag.BranchStmt, @@ -853,6 +1024,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSimpleLabeledStmt: { Tag: nodetag.LabeledStmt, @@ -860,6 +1032,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opLabeledStmt: { Tag: nodetag.LabeledStmt, @@ -867,6 +1040,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opBlockStmt: { Tag: nodetag.BlockStmt, @@ -874,6 +1048,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opExprStmt: { Tag: nodetag.ExprStmt, @@ -881,6 +1056,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opGoStmt: { Tag: nodetag.GoStmt, @@ -888,6 +1064,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opDeferStmt: { Tag: nodetag.DeferStmt, @@ -895,6 +1072,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSendStmt: { Tag: nodetag.SendStmt, @@ -902,6 +1080,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opEmptyStmt: { Tag: nodetag.EmptyStmt, @@ -909,6 +1088,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIncDecStmt: { Tag: nodetag.IncDecStmt, @@ -916,6 +1096,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opReturnStmt: { Tag: nodetag.ReturnStmt, @@ -923,6 +1104,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opIfStmt: { Tag: nodetag.IfStmt, @@ -930,6 +1112,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIfInitStmt: { Tag: nodetag.IfStmt, @@ -937,6 +1120,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIfElseStmt: { Tag: nodetag.IfStmt, @@ -944,6 +1128,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIfInitElseStmt: { Tag: nodetag.IfStmt, @@ -951,6 +1136,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIfNamedOptStmt: { Tag: nodetag.IfStmt, @@ -958,6 +1144,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opIfNamedOptElseStmt: { Tag: nodetag.IfStmt, @@ -965,6 +1152,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSwitchStmt: { Tag: nodetag.SwitchStmt, @@ -972,6 +1160,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opSwitchTagStmt: { Tag: nodetag.SwitchStmt, @@ -979,6 +1168,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 2, // 10 + SliceIndex: -1, }, opSwitchInitStmt: { Tag: nodetag.SwitchStmt, @@ -986,6 +1176,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 2, // 10 + SliceIndex: -1, }, opSwitchInitTagStmt: { Tag: nodetag.SwitchStmt, @@ -993,6 +1184,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 4, // 100 + SliceIndex: -1, }, opSelectStmt: { Tag: nodetag.SelectStmt, @@ -1000,6 +1192,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opTypeSwitchStmt: { Tag: nodetag.TypeSwitchStmt, @@ -1007,6 +1200,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opTypeSwitchInitStmt: { Tag: nodetag.TypeSwitchStmt, @@ -1014,6 +1208,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opCaseClause: { Tag: nodetag.CaseClause, @@ -1021,6 +1216,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 3, // 11 + SliceIndex: -1, }, opDefaultCaseClause: { Tag: nodetag.CaseClause, @@ -1028,6 +1224,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opCommClause: { Tag: nodetag.CommClause, @@ -1035,6 +1232,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 2, // 10 + SliceIndex: -1, }, opDefaultCommClause: { Tag: nodetag.CommClause, @@ -1042,6 +1240,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opForStmt: { Tag: nodetag.ForStmt, @@ -1049,6 +1248,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForPostStmt: { Tag: nodetag.ForStmt, @@ -1056,6 +1256,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForCondStmt: { Tag: nodetag.ForStmt, @@ -1063,6 +1264,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForCondPostStmt: { Tag: nodetag.ForStmt, @@ -1070,6 +1272,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForInitStmt: { Tag: nodetag.ForStmt, @@ -1077,6 +1280,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForInitPostStmt: { Tag: nodetag.ForStmt, @@ -1084,6 +1288,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForInitCondStmt: { Tag: nodetag.ForStmt, @@ -1091,6 +1296,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opForInitCondPostStmt: { Tag: nodetag.ForStmt, @@ -1098,6 +1304,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opRangeStmt: { Tag: nodetag.RangeStmt, @@ -1105,6 +1312,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opRangeKeyStmt: { Tag: nodetag.RangeStmt, @@ -1112,6 +1320,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opRangeKeyValueStmt: { Tag: nodetag.RangeStmt, @@ -1119,6 +1328,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: tokenValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opFieldList: { Tag: nodetag.Unknown, @@ -1126,6 +1336,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opUnnamedField: { Tag: nodetag.Unknown, @@ -1133,6 +1344,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opSimpleField: { Tag: nodetag.Unknown, @@ -1140,6 +1352,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: stringValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opField: { Tag: nodetag.Unknown, @@ -1147,6 +1360,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opMultiField: { Tag: nodetag.Unknown, @@ -1154,6 +1368,15 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, + }, + opValueSpec: { + Tag: nodetag.ValueSpec, + NumArgs: 1, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: -1, }, opValueInitSpec: { Tag: nodetag.ValueSpec, @@ -1161,6 +1384,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 3, // 11 + SliceIndex: -1, }, opTypedValueInitSpec: { Tag: nodetag.ValueSpec, @@ -1168,6 +1392,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 5, // 101 + SliceIndex: -1, }, opTypedValueSpec: { Tag: nodetag.ValueSpec, @@ -1175,6 +1400,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opTypeSpec: { Tag: nodetag.TypeSpec, @@ -1182,6 +1408,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opTypeAliasSpec: { Tag: nodetag.TypeSpec, @@ -1189,6 +1416,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opFuncDecl: { Tag: nodetag.FuncDecl, @@ -1196,6 +1424,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opMethodDecl: { Tag: nodetag.FuncDecl, @@ -1203,6 +1432,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opFuncProtoDecl: { Tag: nodetag.FuncDecl, @@ -1210,6 +1440,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, opMethodProtoDecl: { Tag: nodetag.FuncDecl, @@ -1217,6 +1448,15 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, + }, + opDeclStmt: { + Tag: nodetag.DeclStmt, + NumArgs: 1, + ValueKind: emptyValue, + ExtraValueKind: emptyValue, + VariadicMap: 0, // 0 + SliceIndex: -1, }, opConstDecl: { Tag: nodetag.GenDecl, @@ -1224,6 +1464,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opVarDecl: { Tag: nodetag.GenDecl, @@ -1231,6 +1472,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opTypeDecl: { Tag: nodetag.GenDecl, @@ -1238,6 +1480,7 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 1, // 1 + SliceIndex: -1, }, opEmptyPackage: { Tag: nodetag.File, @@ -1245,5 +1488,6 @@ var operationInfoTable = [256]operationInfo{ ValueKind: emptyValue, ExtraValueKind: emptyValue, VariadicMap: 0, // 0 + SliceIndex: -1, }, } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/parse.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/parse.go index e26a07212..2cd73934e 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/parse.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/parse.go @@ -137,21 +137,7 @@ func parseDetectingNode(fset *token.FileSet, src string) (ast.Node, *ast.File, e } var mainErr error - // first try as a whole file - if f, err := parser.ParseFile(fset, "", src, 0); err == nil && noBadNodes(f) { - return f, f, nil - } - - // then as a single declaration, or many - asDecl := execTmpl(tmplDecl, src) - if f, err := parser.ParseFile(fset, "", asDecl, 0); err == nil && noBadNodes(f) { - if len(f.Decls) == 1 { - return f.Decls[0], f, nil - } - return f, f, nil - } - - // then as a block; otherwise blocks might be mistaken for composite + // try as a block; otherwise blocks might be mistaken for composite // literals further below asBlock := execTmpl(tmplBlock, src) if f, err := parser.ParseFile(fset, "", asBlock, 0); err == nil && noBadNodes(f) { @@ -170,7 +156,7 @@ func parseDetectingNode(fset *token.FileSet, src string) (ast.Node, *ast.File, e if len(cl.Elts) == 1 { return cl.Elts[0], f, nil } - return exprSlice(cl.Elts), f, nil + return ExprSlice(cl.Elts), f, nil } // then try as statements @@ -189,6 +175,20 @@ func parseDetectingNode(fset *token.FileSet, src string) (ast.Node, *ast.File, e // template. mainErr = subPosOffsets(err, posOffset{1, 1, 22}) + // try as a single declaration, or many + asDecl := execTmpl(tmplDecl, src) + if f, err := parser.ParseFile(fset, "", asDecl, 0); err == nil && noBadNodes(f) { + if len(f.Decls) == 1 { + return f.Decls[0], f, nil + } + return declSlice(f.Decls), f, nil + } + + // try as a whole file + if f, err := parser.ParseFile(fset, "", src, 0); err == nil && noBadNodes(f) { + return f, f, nil + } + // type expressions not yet picked up, for e.g. chans and interfaces if typ, f, err := parseType(fset, src); err == nil && noBadNodes(f) { return typ, f, nil @@ -200,6 +200,7 @@ func parseDetectingNode(fset *token.FileSet, src string) (ast.Node, *ast.File, e vs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec) return vs, f, nil } + return nil, nil, mainErr } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/slices.go b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/slices.go index a9f6c0ae0..13775a818 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/slices.go +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/gogrep/slices.go @@ -5,47 +5,54 @@ import ( "go/token" ) -type nodeSlice interface { - at(i int) ast.Node - len() int - slice(from, to int) nodeSlice +type NodeSlice interface { + At(i int) ast.Node + Len() int + slice(from, to int) NodeSlice ast.Node } type ( - exprSlice []ast.Expr + ExprSlice []ast.Expr stmtSlice []ast.Stmt fieldSlice []*ast.Field identSlice []*ast.Ident specSlice []ast.Spec + declSlice []ast.Decl ) -func (l exprSlice) len() int { return len(l) } -func (l exprSlice) at(i int) ast.Node { return l[i] } -func (l exprSlice) slice(i, j int) nodeSlice { return l[i:j] } -func (l exprSlice) Pos() token.Pos { return l[0].Pos() } -func (l exprSlice) End() token.Pos { return l[len(l)-1].End() } +func (l ExprSlice) Len() int { return len(l) } +func (l ExprSlice) At(i int) ast.Node { return l[i] } +func (l ExprSlice) slice(i, j int) NodeSlice { return l[i:j] } +func (l ExprSlice) Pos() token.Pos { return l[0].Pos() } +func (l ExprSlice) End() token.Pos { return l[len(l)-1].End() } -func (l stmtSlice) len() int { return len(l) } -func (l stmtSlice) at(i int) ast.Node { return l[i] } -func (l stmtSlice) slice(i, j int) nodeSlice { return l[i:j] } +func (l stmtSlice) Len() int { return len(l) } +func (l stmtSlice) At(i int) ast.Node { return l[i] } +func (l stmtSlice) slice(i, j int) NodeSlice { return l[i:j] } func (l stmtSlice) Pos() token.Pos { return l[0].Pos() } func (l stmtSlice) End() token.Pos { return l[len(l)-1].End() } -func (l fieldSlice) len() int { return len(l) } -func (l fieldSlice) at(i int) ast.Node { return l[i] } -func (l fieldSlice) slice(i, j int) nodeSlice { return l[i:j] } +func (l fieldSlice) Len() int { return len(l) } +func (l fieldSlice) At(i int) ast.Node { return l[i] } +func (l fieldSlice) slice(i, j int) NodeSlice { return l[i:j] } func (l fieldSlice) Pos() token.Pos { return l[0].Pos() } func (l fieldSlice) End() token.Pos { return l[len(l)-1].End() } -func (l identSlice) len() int { return len(l) } -func (l identSlice) at(i int) ast.Node { return l[i] } -func (l identSlice) slice(i, j int) nodeSlice { return l[i:j] } +func (l identSlice) Len() int { return len(l) } +func (l identSlice) At(i int) ast.Node { return l[i] } +func (l identSlice) slice(i, j int) NodeSlice { return l[i:j] } func (l identSlice) Pos() token.Pos { return l[0].Pos() } func (l identSlice) End() token.Pos { return l[len(l)-1].End() } -func (l specSlice) len() int { return len(l) } -func (l specSlice) at(i int) ast.Node { return l[i] } -func (l specSlice) slice(i, j int) nodeSlice { return l[i:j] } +func (l specSlice) Len() int { return len(l) } +func (l specSlice) At(i int) ast.Node { return l[i] } +func (l specSlice) slice(i, j int) NodeSlice { return l[i:j] } func (l specSlice) Pos() token.Pos { return l[0].Pos() } func (l specSlice) End() token.Pos { return l[len(l)-1].End() } + +func (l declSlice) Len() int { return len(l) } +func (l declSlice) At(i int) ast.Node { return l[i] } +func (l declSlice) slice(i, j int) NodeSlice { return l[i:j] } +func (l declSlice) Pos() token.Pos { return l[0].Pos() } +func (l declSlice) End() token.Pos { return l[len(l)-1].End() } diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/stdinfo/stdinfo.go b/vendor/github.com/quasilyte/go-ruleguard/internal/stdinfo/stdinfo.go new file mode 100644 index 000000000..f00d66d46 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/stdinfo/stdinfo.go @@ -0,0 +1,151 @@ +package stdinfo + +var Packages = map[string]string{ + "adler32": "hash/adler32", + "aes": "crypto/aes", + "ascii85": "encoding/ascii85", + "asn1": "encoding/asn1", + "ast": "go/ast", + "atomic": "sync/atomic", + "base32": "encoding/base32", + "base64": "encoding/base64", + "big": "math/big", + "binary": "encoding/binary", + "bits": "math/bits", + "bufio": "bufio", + "build": "go/build", + "bytes": "bytes", + "bzip2": "compress/bzip2", + "cgi": "net/http/cgi", + "cgo": "runtime/cgo", + "cipher": "crypto/cipher", + "cmplx": "math/cmplx", + "color": "image/color", + "constant": "go/constant", + "constraint": "go/build/constraint", + "context": "context", + "cookiejar": "net/http/cookiejar", + "crc32": "hash/crc32", + "crc64": "hash/crc64", + "crypto": "crypto", + "csv": "encoding/csv", + "debug": "runtime/debug", + "des": "crypto/des", + "doc": "go/doc", + "draw": "image/draw", + "driver": "database/sql/driver", + "dsa": "crypto/dsa", + "dwarf": "debug/dwarf", + "ecdsa": "crypto/ecdsa", + "ed25519": "crypto/ed25519", + "elf": "debug/elf", + "elliptic": "crypto/elliptic", + "embed": "embed", + "encoding": "encoding", + "errors": "errors", + "exec": "os/exec", + "expvar": "expvar", + "fcgi": "net/http/fcgi", + "filepath": "path/filepath", + "flag": "flag", + "flate": "compress/flate", + "fmt": "fmt", + "fnv": "hash/fnv", + "format": "go/format", + "fs": "io/fs", + "fstest": "testing/fstest", + "gif": "image/gif", + "gob": "encoding/gob", + "gosym": "debug/gosym", + "gzip": "compress/gzip", + "hash": "hash", + "heap": "container/heap", + "hex": "encoding/hex", + "hmac": "crypto/hmac", + "html": "html", + "http": "net/http", + "httptest": "net/http/httptest", + "httptrace": "net/http/httptrace", + "httputil": "net/http/httputil", + "image": "image", + "importer": "go/importer", + "io": "io", + "iotest": "testing/iotest", + "ioutil": "io/ioutil", + "jpeg": "image/jpeg", + "json": "encoding/json", + "jsonrpc": "net/rpc/jsonrpc", + "list": "container/list", + "log": "log", + "lzw": "compress/lzw", + "macho": "debug/macho", + "mail": "net/mail", + "maphash": "hash/maphash", + "math": "math", + "md5": "crypto/md5", + "metrics": "runtime/metrics", + "mime": "mime", + "multipart": "mime/multipart", + "net": "net", + "os": "os", + "palette": "image/color/palette", + "parse": "text/template/parse", + "parser": "go/parser", + "path": "path", + "pe": "debug/pe", + "pem": "encoding/pem", + "pkix": "crypto/x509/pkix", + "plan9obj": "debug/plan9obj", + "plugin": "plugin", + "png": "image/png", + "pprof": "runtime/pprof", + "printer": "go/printer", + "quick": "testing/quick", + "quotedprintable": "mime/quotedprintable", + "race": "runtime/race", + "rand": "math/rand", + "rc4": "crypto/rc4", + "reflect": "reflect", + "regexp": "regexp", + "ring": "container/ring", + "rpc": "net/rpc", + "rsa": "crypto/rsa", + "runtime": "runtime", + "scanner": "text/scanner", + "sha1": "crypto/sha1", + "sha256": "crypto/sha256", + "sha512": "crypto/sha512", + "signal": "os/signal", + "smtp": "net/smtp", + "sort": "sort", + "sql": "database/sql", + "strconv": "strconv", + "strings": "strings", + "subtle": "crypto/subtle", + "suffixarray": "index/suffixarray", + "sync": "sync", + "syntax": "regexp/syntax", + "syscall": "syscall", + "syslog": "log/syslog", + "tabwriter": "text/tabwriter", + "tar": "archive/tar", + "template": "text/template", + "testing": "testing", + "textproto": "net/textproto", + "time": "time", + "tls": "crypto/tls", + "token": "go/token", + "trace": "runtime/trace", + "types": "go/types", + "tzdata": "time/tzdata", + "unicode": "unicode", + "unsafe": "unsafe", + "url": "net/url", + "user": "os/user", + "utf16": "unicode/utf16", + "utf8": "unicode/utf8", + "x509": "crypto/x509", + "xml": "encoding/xml", + "zip": "archive/zip", + "zlib": "compress/zlib", +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go b/vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go new file mode 100644 index 000000000..3b58f97c7 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/internal/xsrcimporter/xsrcimporter.go @@ -0,0 +1,29 @@ +package xsrcimporter + +import ( + "go/build" + "go/importer" + "go/token" + "go/types" + "unsafe" +) + +func New(ctxt *build.Context, fset *token.FileSet) types.Importer { + imp := importer.ForCompiler(fset, "source", nil) + ifaceVal := *(*iface)(unsafe.Pointer(&imp)) + srcImp := (*srcImporter)(ifaceVal.data) + srcImp.ctxt = ctxt + return imp +} + +type iface struct { + _ *byte + data unsafe.Pointer +} + +type srcImporter struct { + ctxt *build.Context + _ *token.FileSet + _ types.Sizes + _ map[string]*types.Package +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/nodetag/nodetag.go b/vendor/github.com/quasilyte/go-ruleguard/nodetag/nodetag.go index a9098c29f..7c0408b59 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/nodetag/nodetag.go +++ b/vendor/github.com/quasilyte/go-ruleguard/nodetag/nodetag.go @@ -59,6 +59,7 @@ const ( StmtList // gogrep stmt list ExprList // gogrep expr list + DeclList // gogrep decl list Node // ast.Node Expr // ast.Expr diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go new file mode 100644 index 000000000..e3d7ea70b --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ast_walker.go @@ -0,0 +1,322 @@ +package ruleguard + +import ( + "go/ast" + "go/constant" +) + +type astWalker struct { + nodePath *nodePath + + filterParams *filterParams + + visit func(ast.Node) +} + +func (w *astWalker) Walk(root ast.Node, visit func(ast.Node)) { + w.visit = visit + w.walk(root) +} + +func (w *astWalker) walkIdentList(list []*ast.Ident) { + for _, x := range list { + w.walk(x) + } +} + +func (w *astWalker) walkExprList(list []ast.Expr) { + for _, x := range list { + w.walk(x) + } +} + +func (w *astWalker) walkStmtList(list []ast.Stmt) { + for _, x := range list { + w.walk(x) + } +} + +func (w *astWalker) walkDeclList(list []ast.Decl) { + for _, x := range list { + w.walk(x) + } +} + +func (w *astWalker) walk(n ast.Node) { + w.nodePath.Push(n) + defer w.nodePath.Pop() + + w.visit(n) + + switch n := n.(type) { + case *ast.Field: + // TODO: handle field types. + // See #252 + w.walkIdentList(n.Names) + w.walk(n.Type) + + case *ast.FieldList: + for _, f := range n.List { + w.walk(f) + } + + case *ast.Ellipsis: + if n.Elt != nil { + w.walk(n.Elt) + } + + case *ast.FuncLit: + w.walk(n.Type) + w.walk(n.Body) + + case *ast.CompositeLit: + if n.Type != nil { + w.walk(n.Type) + } + w.walkExprList(n.Elts) + + case *ast.ParenExpr: + w.walk(n.X) + + case *ast.SelectorExpr: + w.walk(n.X) + w.walk(n.Sel) + + case *ast.IndexExpr: + w.walk(n.X) + w.walk(n.Index) + + case *ast.SliceExpr: + w.walk(n.X) + if n.Low != nil { + w.walk(n.Low) + } + if n.High != nil { + w.walk(n.High) + } + if n.Max != nil { + w.walk(n.Max) + } + + case *ast.TypeAssertExpr: + w.walk(n.X) + if n.Type != nil { + w.walk(n.Type) + } + + case *ast.CallExpr: + w.walk(n.Fun) + w.walkExprList(n.Args) + + case *ast.StarExpr: + w.walk(n.X) + + case *ast.UnaryExpr: + w.walk(n.X) + + case *ast.BinaryExpr: + w.walk(n.X) + w.walk(n.Y) + + case *ast.KeyValueExpr: + w.walk(n.Key) + w.walk(n.Value) + + case *ast.ArrayType: + if n.Len != nil { + w.walk(n.Len) + } + w.walk(n.Elt) + + case *ast.StructType: + w.walk(n.Fields) + + case *ast.FuncType: + if n.Params != nil { + w.walk(n.Params) + } + if n.Results != nil { + w.walk(n.Results) + } + + case *ast.InterfaceType: + w.walk(n.Methods) + + case *ast.MapType: + w.walk(n.Key) + w.walk(n.Value) + + case *ast.ChanType: + w.walk(n.Value) + + case *ast.DeclStmt: + w.walk(n.Decl) + + case *ast.LabeledStmt: + w.walk(n.Label) + w.walk(n.Stmt) + + case *ast.ExprStmt: + w.walk(n.X) + + case *ast.SendStmt: + w.walk(n.Chan) + w.walk(n.Value) + + case *ast.IncDecStmt: + w.walk(n.X) + + case *ast.AssignStmt: + w.walkExprList(n.Lhs) + w.walkExprList(n.Rhs) + + case *ast.GoStmt: + w.walk(n.Call) + + case *ast.DeferStmt: + w.walk(n.Call) + + case *ast.ReturnStmt: + w.walkExprList(n.Results) + + case *ast.BranchStmt: + if n.Label != nil { + w.walk(n.Label) + } + + case *ast.BlockStmt: + w.walkStmtList(n.List) + + case *ast.IfStmt: + if n.Init != nil { + w.walk(n.Init) + } + w.walk(n.Cond) + deadcode := w.filterParams.deadcode + if !deadcode { + cv := w.filterParams.ctx.Types.Types[n.Cond].Value + if cv != nil { + w.filterParams.deadcode = !deadcode && !constant.BoolVal(cv) + w.walk(n.Body) + w.filterParams.deadcode = !w.filterParams.deadcode + if n.Else != nil { + w.walk(n.Else) + } + w.filterParams.deadcode = deadcode + return + } + } + w.walk(n.Body) + if n.Else != nil { + w.walk(n.Else) + } + + case *ast.CaseClause: + w.walkExprList(n.List) + w.walkStmtList(n.Body) + + case *ast.SwitchStmt: + if n.Init != nil { + w.walk(n.Init) + } + if n.Tag != nil { + w.walk(n.Tag) + } + w.walk(n.Body) + + case *ast.TypeSwitchStmt: + if n.Init != nil { + w.walk(n.Init) + } + w.walk(n.Assign) + w.walk(n.Body) + + case *ast.CommClause: + if n.Comm != nil { + w.walk(n.Comm) + } + w.walkStmtList(n.Body) + + case *ast.SelectStmt: + w.walk(n.Body) + + case *ast.ForStmt: + if n.Init != nil { + w.walk(n.Init) + } + if n.Cond != nil { + w.walk(n.Cond) + } + if n.Post != nil { + w.walk(n.Post) + } + w.walk(n.Body) + + case *ast.RangeStmt: + if n.Key != nil { + w.walk(n.Key) + } + if n.Value != nil { + w.walk(n.Value) + } + w.walk(n.X) + w.walk(n.Body) + + case *ast.ImportSpec: + if n.Name != nil { + w.walk(n.Name) + } + w.walk(n.Path) + if n.Comment != nil { + w.walk(n.Comment) + } + + case *ast.ValueSpec: + if n.Doc != nil { + w.walk(n.Doc) + } + w.walkIdentList(n.Names) + if n.Type != nil { + w.walk(n.Type) + } + w.walkExprList(n.Values) + if n.Comment != nil { + w.walk(n.Comment) + } + + case *ast.TypeSpec: + if n.Doc != nil { + w.walk(n.Doc) + } + w.walk(n.Name) + w.walk(n.Type) + if n.Comment != nil { + w.walk(n.Comment) + } + + case *ast.GenDecl: + if n.Doc != nil { + w.walk(n.Doc) + } + for _, s := range n.Specs { + w.walk(s) + } + + case *ast.FuncDecl: + if n.Doc != nil { + w.walk(n.Doc) + } + if n.Recv != nil { + w.walk(n.Recv) + } + w.walk(n.Name) + w.walk(n.Type) + if n.Body != nil { + w.walk(n.Body) + } + + case *ast.File: + w.walk(n.Name) + w.walkDeclList(n.Decls) + } +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go index 950e3c410..72a334b9c 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/bundle.go @@ -6,7 +6,7 @@ import ( "github.com/quasilyte/go-ruleguard/internal/golist" ) -func findBundleFiles(pkgPath string) ([]string, error) { +func findBundleFiles(pkgPath string) ([]string, error) { // nolint pkg, err := golist.JSON(pkgPath) if err != nil { return nil, err diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go index 66a4fd58a..e00706c34 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/engine.go @@ -4,11 +4,19 @@ import ( "errors" "fmt" "go/ast" + "go/build" + "go/token" "go/types" "io" + "io/ioutil" + "os" + "sort" "strings" "sync" + "github.com/quasilyte/go-ruleguard/internal/goenv" + "github.com/quasilyte/go-ruleguard/internal/stdinfo" + "github.com/quasilyte/go-ruleguard/ruleguard/ir" "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" "github.com/quasilyte/go-ruleguard/ruleguard/typematch" ) @@ -25,19 +33,42 @@ func newEngine() *engine { } } -func (e *engine) Load(ctx *ParseContext, filename string, r io.Reader) error { - config := rulesParserConfig{ - state: e.state, - ctx: ctx, - importer: newGoImporter(e.state, goImporterConfig{ - fset: ctx.Fset, - debugImports: ctx.DebugImports, - debugPrint: ctx.DebugPrint, - }), - itab: typematch.NewImportsTab(stdlibPackages), +func (e *engine) LoadedGroups() []GoRuleGroup { + result := make([]GoRuleGroup, 0, len(e.ruleSet.groups)) + for _, g := range e.ruleSet.groups { + result = append(result, *g) } - p := newRulesParser(config) - rset, err := p.ParseFile(filename, r) + sort.Slice(result, func(i, j int) bool { + return result[i].Name < result[j].Name + }) + return result +} + +func (e *engine) Load(ctx *LoadContext, buildContext *build.Context, filename string, r io.Reader) error { + data, err := ioutil.ReadAll(r) + if err != nil { + return err + } + imp := newGoImporter(e.state, goImporterConfig{ + fset: ctx.Fset, + debugImports: ctx.DebugImports, + debugPrint: ctx.DebugPrint, + buildContext: buildContext, + }) + irfile, pkg, err := convertAST(ctx, imp, filename, data) + if err != nil { + return err + } + config := irLoaderConfig{ + state: e.state, + pkg: pkg, + ctx: ctx, + importer: imp, + itab: typematch.NewImportsTab(stdinfo.Packages), + gogrepFset: token.NewFileSet(), + } + l := newIRLoader(config) + rset, err := l.LoadFile(filename, irfile) if err != nil { return err } @@ -55,12 +86,45 @@ func (e *engine) Load(ctx *ParseContext, filename string, r io.Reader) error { return nil } -func (e *engine) Run(ctx *RunContext, f *ast.File) error { +func (e *engine) LoadFromIR(ctx *LoadContext, buildContext *build.Context, filename string, f *ir.File) error { + imp := newGoImporter(e.state, goImporterConfig{ + fset: ctx.Fset, + debugImports: ctx.DebugImports, + debugPrint: ctx.DebugPrint, + buildContext: buildContext, + }) + config := irLoaderConfig{ + state: e.state, + ctx: ctx, + importer: imp, + itab: typematch.NewImportsTab(stdinfo.Packages), + gogrepFset: token.NewFileSet(), + } + l := newIRLoader(config) + rset, err := l.LoadFile(filename, f) + if err != nil { + return err + } + + if e.ruleSet == nil { + e.ruleSet = rset + } else { + combinedRuleSet, err := mergeRuleSets([]*goRuleSet{e.ruleSet, rset}) + if err != nil { + return err + } + e.ruleSet = combinedRuleSet + } + + return nil +} + +func (e *engine) Run(ctx *RunContext, buildContext *build.Context, f *ast.File) error { if e.ruleSet == nil { return errors.New("used Run() with an empty rule set; forgot to call Load() first?") } - rset := cloneRuleSet(e.ruleSet) - return newRulesRunner(ctx, e.state, rset).run(f) + rset := e.ruleSet + return newRulesRunner(ctx, buildContext, e.state, rset).run(f) } // engineState is a shared state inside the engine. @@ -152,9 +216,12 @@ func (state *engineState) findTypeNoCache(importer *goImporter, currentPkg *type pkgPath := fqn[:pos] objectName := fqn[pos+1:] var pkg *types.Package - if directDep := findDependency(currentPkg, pkgPath); directDep != nil { - pkg = directDep - } else { + if currentPkg != nil { + if directDep := findDependency(currentPkg, pkgPath); directDep != nil { + pkg = directDep + } + } + if pkg == nil { loadedPkg, err := importer.Import(pkgPath) if err != nil { return nil, err @@ -169,3 +236,29 @@ func (state *engineState) findTypeNoCache(importer *goImporter, currentPkg *type state.typeByFQN[fqn] = typ return typ, nil } + +func inferBuildContext() *build.Context { + // Inherit most fields from the build.Default. + ctx := build.Default + + env, err := goenv.Read() + if err != nil { + return &ctx + } + + ctx.GOROOT = env["GOROOT"] + ctx.GOPATH = env["GOPATH"] + ctx.GOARCH = env["GOARCH"] + ctx.GOOS = env["GOOS"] + + switch os.Getenv("CGO_ENABLED") { + case "0": + ctx.CgoEnabled = false + case "1": + ctx.CgoEnabled = true + default: + ctx.CgoEnabled = env["CGO_ENABLED"] == "1" + } + + return &ctx +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go index 4918cbb3c..9bf50dab8 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/filters.go @@ -6,11 +6,12 @@ import ( "go/token" "go/types" "path/filepath" - "regexp" + "github.com/quasilyte/go-ruleguard/internal/gogrep" "github.com/quasilyte/go-ruleguard/internal/xtypes" "github.com/quasilyte/go-ruleguard/nodetag" "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" + "github.com/quasilyte/go-ruleguard/ruleguard/textmatch" "github.com/quasilyte/go-ruleguard/ruleguard/typematch" ) @@ -20,6 +21,15 @@ func filterFailure(reason string) matchFilterResult { return matchFilterResult(reason) } +func exprListFilterApply(src string, list gogrep.ExprSlice, fn func(ast.Expr) bool) matchFilterResult { + for i := 0; i < list.Len(); i++ { + if !fn(list.At(i).(ast.Expr)) { + return filterFailure(src) + } + } + return filterSuccess +} + func makeNotFilter(src string, x matchFilter) filterFunc { return func(params *filterParams) matchFilterResult { if x.fn(params).Matched() { @@ -47,6 +57,15 @@ func makeOrFilter(lhs, rhs matchFilter) filterFunc { } } +func makeDeadcodeFilter(src string) filterFunc { + return func(params *filterParams) matchFilterResult { + if params.deadcode { + return filterSuccess + } + return filterFailure(src) + } +} + func makeFileImportsFilter(src, pkgPath string) filterFunc { return func(params *filterParams) matchFilterResult { _, imported := params.imports[pkgPath] @@ -57,7 +76,7 @@ func makeFileImportsFilter(src, pkgPath string) filterFunc { } } -func makeFilePkgPathMatchesFilter(src string, re *regexp.Regexp) filterFunc { +func makeFilePkgPathMatchesFilter(src string, re textmatch.Pattern) filterFunc { return func(params *filterParams) matchFilterResult { pkgPath := params.ctx.Pkg.Path() if re.MatchString(pkgPath) { @@ -67,7 +86,7 @@ func makeFilePkgPathMatchesFilter(src string, re *regexp.Regexp) filterFunc { } } -func makeFileNameMatchesFilter(src string, re *regexp.Regexp) filterFunc { +func makeFileNameMatchesFilter(src string, re textmatch.Pattern) filterFunc { return func(params *filterParams) matchFilterResult { if re.MatchString(filepath.Base(params.filename)) { return filterSuccess @@ -78,6 +97,12 @@ func makeFileNameMatchesFilter(src string, re *regexp.Regexp) filterFunc { func makePureFilter(src, varname string) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return isPure(params.ctx.Types, x) + }) + } + n := params.subExpr(varname) if isPure(params.ctx.Types, n) { return filterSuccess @@ -88,6 +113,12 @@ func makePureFilter(src, varname string) filterFunc { func makeConstFilter(src, varname string) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return isConstant(params.ctx.Types, x) + }) + } + n := params.subExpr(varname) if isConstant(params.ctx.Types, n) { return filterSuccess @@ -96,8 +127,30 @@ func makeConstFilter(src, varname string) filterFunc { } } +func makeConstSliceFilter(src, varname string) filterFunc { + return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return isConstantSlice(params.ctx.Types, x) + }) + } + + n := params.subExpr(varname) + if isConstantSlice(params.ctx.Types, n) { + return filterSuccess + } + return filterFailure(src) + } +} + func makeAddressableFilter(src, varname string) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return isAddressable(params.ctx.Types, x) + }) + } + n := params.subExpr(varname) if isAddressable(params.ctx.Types, n) { return filterSuccess @@ -122,6 +175,12 @@ func makeCustomVarFilter(src, varname string, fn *quasigo.Func) filterFunc { func makeTypeImplementsFilter(src, varname string, iface *types.Interface) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return xtypes.Implements(params.typeofNode(x), iface) + }) + } + typ := params.typeofNode(params.subExpr(varname)) if xtypes.Implements(typ, iface) { return filterSuccess @@ -133,6 +192,11 @@ func makeTypeImplementsFilter(src, varname string, iface *types.Interface) filte func makeTypeIsFilter(src, varname string, underlying bool, pat *typematch.Pattern) filterFunc { if underlying { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return pat.MatchIdentical(params.typeofNode(x).Underlying()) + }) + } typ := params.typeofNode(params.subExpr(varname)).Underlying() if pat.MatchIdentical(typ) { return filterSuccess @@ -140,7 +204,13 @@ func makeTypeIsFilter(src, varname string, underlying bool, pat *typematch.Patte return filterFailure(src) } } + return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return pat.MatchIdentical(params.typeofNode(x)) + }) + } typ := params.typeofNode(params.subExpr(varname)) if pat.MatchIdentical(typ) { return filterSuccess @@ -151,6 +221,12 @@ func makeTypeIsFilter(src, varname string, underlying bool, pat *typematch.Patte func makeTypeConvertibleToFilter(src, varname string, dstType types.Type) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return types.ConvertibleTo(params.typeofNode(x), dstType) + }) + } + typ := params.typeofNode(params.subExpr(varname)) if types.ConvertibleTo(typ, dstType) { return filterSuccess @@ -161,6 +237,12 @@ func makeTypeConvertibleToFilter(src, varname string, dstType types.Type) filter func makeTypeAssignableToFilter(src, varname string, dstType types.Type) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + return types.AssignableTo(params.typeofNode(x), dstType) + }) + } + typ := params.typeofNode(params.subExpr(varname)) if types.AssignableTo(typ, dstType) { return filterSuccess @@ -169,8 +251,54 @@ func makeTypeAssignableToFilter(src, varname string, dstType types.Type) filterF } } +func makeLineFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { + // TODO(quasilyte): add variadic support. + return func(params *filterParams) matchFilterResult { + line1 := params.ctx.Fset.Position(params.subNode(varname).Pos()).Line + line2 := params.ctx.Fset.Position(params.subNode(rhsVarname).Pos()).Line + lhsValue := constant.MakeInt64(int64(line1)) + rhsValue := constant.MakeInt64(int64(line2)) + if constant.Compare(lhsValue, op, rhsValue) { + return filterSuccess + } + return filterFailure(src) + } +} + +func makeGoVersionFilter(src string, op token.Token, version GoVersion) filterFunc { + return func(params *filterParams) matchFilterResult { + if params.ctx.GoVersion.IsAny() { + return filterSuccess + } + if versionCompare(params.ctx.GoVersion, op, version) { + return filterSuccess + } + return filterFailure(src) + } +} + +func makeLineConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { + // TODO(quasilyte): add variadic support. + return func(params *filterParams) matchFilterResult { + n := params.subNode(varname) + lhsValue := constant.MakeInt64(int64(params.ctx.Fset.Position(n.Pos()).Line)) + if constant.Compare(lhsValue, op, rhsValue) { + return filterSuccess + } + return filterFailure(src) + } +} + func makeTypeSizeConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + typ := params.typeofNode(x) + lhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(typ)) + return constant.Compare(lhsValue, op, rhsValue) + }) + } + typ := params.typeofNode(params.subExpr(varname)) lhsValue := constant.MakeInt64(params.ctx.Sizes.Sizeof(typ)) if constant.Compare(lhsValue, op, rhsValue) { @@ -182,6 +310,13 @@ func makeTypeSizeConstFilter(src, varname string, op token.Token, rhsValue const func makeValueIntConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + lhsValue := intValueOf(params.ctx.Types, x) + return lhsValue != nil && constant.Compare(lhsValue, op, rhsValue) + }) + } + lhsValue := intValueOf(params.ctx.Types, params.subExpr(varname)) if lhsValue == nil { return filterFailure(src) // The value is unknown @@ -194,6 +329,7 @@ func makeValueIntConstFilter(src, varname string, op token.Token, rhsValue const } func makeValueIntFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { + // TODO(quasilyte): add variadic support. return func(params *filterParams) matchFilterResult { lhsValue := intValueOf(params.ctx.Types, params.subExpr(varname)) if lhsValue == nil { @@ -211,6 +347,7 @@ func makeValueIntFilter(src, varname string, op token.Token, rhsVarname string) } func makeTextConstFilter(src, varname string, op token.Token, rhsValue constant.Value) filterFunc { + // TODO(quasilyte): add variadic support. return func(params *filterParams) matchFilterResult { s := params.nodeText(params.subNode(varname)) lhsValue := constant.MakeString(string(s)) @@ -222,6 +359,7 @@ func makeTextConstFilter(src, varname string, op token.Token, rhsValue constant. } func makeTextFilter(src, varname string, op token.Token, rhsVarname string) filterFunc { + // TODO(quasilyte): add variadic support. return func(params *filterParams) matchFilterResult { s1 := params.nodeText(params.subNode(varname)) lhsValue := constant.MakeString(string(s1)) @@ -235,7 +373,8 @@ func makeTextFilter(src, varname string, op token.Token, rhsVarname string) filt } } -func makeTextMatchesFilter(src, varname string, re *regexp.Regexp) filterFunc { +func makeTextMatchesFilter(src, varname string, re textmatch.Pattern) filterFunc { + // TODO(quasilyte): add variadic support. return func(params *filterParams) matchFilterResult { if re.Match(params.nodeText(params.subNode(varname))) { return filterSuccess @@ -244,24 +383,104 @@ func makeTextMatchesFilter(src, varname string, re *regexp.Regexp) filterFunc { } } -func makeNodeIsFilter(src, varname string, tag nodetag.Value) filterFunc { - // TODO: add comment nodes support? +func makeRootParentNodeIsFilter(src string, tag nodetag.Value) filterFunc { return func(params *filterParams) matchFilterResult { - n := params.subExpr(varname) - var matched bool - switch tag { - case nodetag.Expr: - _, matched = n.(ast.Expr) - case nodetag.Stmt: - _, matched = n.(ast.Stmt) - case nodetag.Node: - _, matched = n.(ast.Node) - default: - matched = (tag == nodetag.FromNode(n)) - } - if matched { + parent := params.nodePath.Parent() + if nodeIs(parent, tag) { return filterSuccess } return filterFailure(src) } } + +func makeNodeIsFilter(src, varname string, tag nodetag.Value) filterFunc { + // TODO(quasilyte): add comment nodes support? + // TODO(quasilyte): add variadic support. + return func(params *filterParams) matchFilterResult { + n := params.subNode(varname) + if nodeIs(n, tag) { + return filterSuccess + } + return filterFailure(src) + } +} + +func makeObjectIsFilter(src, varname, objectName string) filterFunc { + var predicate func(types.Object) bool + switch objectName { + case "Func": + predicate = func(x types.Object) bool { + _, ok := x.(*types.Func) + return ok + } + case "Var": + predicate = func(x types.Object) bool { + _, ok := x.(*types.Var) + return ok + } + case "Const": + predicate = func(x types.Object) bool { + _, ok := x.(*types.Const) + return ok + } + case "TypeName": + predicate = func(x types.Object) bool { + _, ok := x.(*types.TypeName) + return ok + } + case "Label": + predicate = func(x types.Object) bool { + _, ok := x.(*types.Label) + return ok + } + case "PkgName": + predicate = func(x types.Object) bool { + _, ok := x.(*types.PkgName) + return ok + } + case "Builtin": + predicate = func(x types.Object) bool { + _, ok := x.(*types.Builtin) + return ok + } + case "Nil": + predicate = func(x types.Object) bool { + _, ok := x.(*types.Nil) + return ok + } + } + + return func(params *filterParams) matchFilterResult { + if list, ok := params.subNode(varname).(gogrep.ExprSlice); ok { + return exprListFilterApply(src, list, func(x ast.Expr) bool { + ident := identOf(x) + return ident != nil && predicate(params.ctx.Types.ObjectOf(ident)) + }) + } + + ident := identOf(params.subExpr(varname)) + if ident == nil { + return filterFailure(src) + } + object := params.ctx.Types.ObjectOf(ident) + if predicate(object) { + return filterSuccess + } + return filterFailure(src) + } +} + +func nodeIs(n ast.Node, tag nodetag.Value) bool { + var matched bool + switch tag { + case nodetag.Expr: + _, matched = n.(ast.Expr) + case nodetag.Stmt: + _, matched = n.(ast.Stmt) + case nodetag.Node: + matched = true + default: + matched = (tag == nodetag.FromNode(n)) + } + return matched +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go new file mode 100644 index 000000000..39e4a492d --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/go_version.go @@ -0,0 +1,58 @@ +package ruleguard + +import ( + "fmt" + "go/token" + "strconv" + "strings" +) + +type GoVersion struct { + Major int + Minor int +} + +func (ver GoVersion) IsAny() bool { return ver.Major == 0 } + +func ParseGoVersion(version string) (GoVersion, error) { + var result GoVersion + if version == "" { + return GoVersion{}, nil + } + parts := strings.Split(version, ".") + if len(parts) != 2 { + return result, fmt.Errorf("invalid format: %s", version) + } + major, err := strconv.Atoi(parts[0]) + if err != nil { + return result, fmt.Errorf("invalid major version part: %s: %s", parts[0], err) + } + minor, err := strconv.Atoi(parts[1]) + if err != nil { + return result, fmt.Errorf("invalid minor version part: %s: %s", parts[1], err) + } + result.Major = major + result.Minor = minor + return result, nil +} + +func versionCompare(x GoVersion, op token.Token, y GoVersion) bool { + switch op { + case token.EQL: // == + return x.Major == y.Major && x.Minor == y.Minor + case token.NEQ: // != + return !versionCompare(x, token.EQL, y) + + case token.GTR: // > + return x.Major > y.Major || (x.Major == y.Major && x.Minor > y.Minor) + case token.GEQ: // >= + return x.Major > y.Major || (x.Major == y.Major && x.Minor >= y.Minor) + case token.LSS: // < + return x.Major < y.Major || (x.Major == y.Major && x.Minor < y.Minor) + case token.LEQ: // <= + return x.Major < y.Major || (x.Major == y.Major && x.Minor <= y.Minor) + + default: + panic("unexpected version compare op") + } +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go index 08aee9132..cfc7b70d6 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/gorule.go @@ -3,7 +3,6 @@ package ruleguard import ( "fmt" "go/ast" - "go/token" "go/types" "regexp" @@ -15,7 +14,7 @@ import ( type goRuleSet struct { universal *scopedGoRuleSet - groups map[string]token.Position // To handle redefinitions + groups map[string]*GoRuleGroup // To handle redefinitions } type scopedGoRuleSet struct { @@ -31,8 +30,7 @@ type goCommentRule struct { } type goRule struct { - group string - filename string + group *GoRuleGroup line int pat *gogrep.Pattern msg string @@ -62,10 +60,13 @@ type filterParams struct { importer *goImporter - match matchData + match matchData + nodePath *nodePath nodeText func(n ast.Node) []byte + deadcode bool + // varname is set only for custom filters before bytecode function is called. varname string } @@ -97,29 +98,21 @@ func (params *filterParams) typeofNode(n ast.Node) types.Type { return types.Typ[types.Invalid] } -func cloneRuleSet(rset *goRuleSet) *goRuleSet { - out, err := mergeRuleSets([]*goRuleSet{rset}) - if err != nil { - panic(err) // Should never happen - } - return out -} - func mergeRuleSets(toMerge []*goRuleSet) (*goRuleSet, error) { out := &goRuleSet{ universal: &scopedGoRuleSet{}, - groups: make(map[string]token.Position), + groups: make(map[string]*GoRuleGroup), } for _, x := range toMerge { out.universal = appendScopedRuleSet(out.universal, x.universal) - for group, pos := range x.groups { - if prevPos, ok := out.groups[group]; ok { - newRef := fmt.Sprintf("%s:%d", pos.Filename, pos.Line) - oldRef := fmt.Sprintf("%s:%d", prevPos.Filename, prevPos.Line) - return nil, fmt.Errorf("%s: redefinition of %s(), previously defined at %s", newRef, group, oldRef) + for groupName, group := range x.groups { + if prevGroup, ok := out.groups[groupName]; ok { + newRef := fmt.Sprintf("%s:%d", group.Filename, group.Line) + oldRef := fmt.Sprintf("%s:%d", prevGroup.Filename, prevGroup.Line) + return nil, fmt.Errorf("%s: redefinition of %s(), previously defined at %s", newRef, groupName, oldRef) } - out.groups[group] = pos + out.groups[groupName] = group } } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go index 6cc4d9056..3f35b17e1 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/goutil/goutil.go @@ -1,9 +1,13 @@ package goutil import ( + "fmt" "go/ast" + "go/importer" + "go/parser" "go/printer" "go/token" + "go/types" "strings" ) @@ -19,3 +23,45 @@ func SprintNode(fset *token.FileSet, n ast.Node) string { } return buf.String() } + +type LoadConfig struct { + Fset *token.FileSet + Filename string + Data interface{} + Importer types.Importer +} + +type LoadResult struct { + Pkg *types.Package + Types *types.Info + Syntax *ast.File +} + +func LoadGoFile(config LoadConfig) (*LoadResult, error) { + imp := config.Importer + if imp == nil { + imp = importer.ForCompiler(config.Fset, "source", nil) + } + + parserFlags := parser.ParseComments + f, err := parser.ParseFile(config.Fset, config.Filename, config.Data, parserFlags) + if err != nil { + return nil, fmt.Errorf("parse file error: %w", err) + } + typechecker := types.Config{Importer: imp} + typesInfo := &types.Info{ + Types: map[ast.Expr]types.TypeAndValue{}, + Uses: map[*ast.Ident]types.Object{}, + Defs: map[*ast.Ident]types.Object{}, + } + pkg, err := typechecker.Check(f.Name.String(), config.Fset, []*ast.File{f}, typesInfo) + if err != nil { + return nil, fmt.Errorf("typechecker error: %w", err) + } + result := &LoadResult{ + Pkg: pkg, + Types: typesInfo, + Syntax: f, + } + return result, nil +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go index 06a0bbf9f..19494db9c 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/importer.go @@ -2,15 +2,13 @@ package ruleguard import ( "fmt" - "go/ast" + "go/build" "go/importer" - "go/parser" "go/token" "go/types" - "path/filepath" "runtime" - "github.com/quasilyte/go-ruleguard/internal/golist" + "github.com/quasilyte/go-ruleguard/internal/xsrcimporter" ) // goImporter is a `types.Importer` that tries to load a package no matter what. @@ -23,7 +21,8 @@ type goImporter struct { defaultImporter types.Importer srcImporter types.Importer - fset *token.FileSet + fset *token.FileSet + buildContext *build.Context debugImports bool debugPrint func(string) @@ -33,17 +32,20 @@ type goImporterConfig struct { fset *token.FileSet debugImports bool debugPrint func(string) + buildContext *build.Context } func newGoImporter(state *engineState, config goImporterConfig) *goImporter { - return &goImporter{ + imp := &goImporter{ state: state, fset: config.fset, debugImports: config.debugImports, debugPrint: config.debugPrint, defaultImporter: importer.Default(), - srcImporter: importer.ForCompiler(config.fset, "source", nil), + buildContext: config.buildContext, } + imp.initSourceImporter() + return imp } func (imp *goImporter) Import(path string) (*types.Package, error) { @@ -54,8 +56,8 @@ func (imp *goImporter) Import(path string) (*types.Package, error) { return pkg, nil } - pkg, err1 := imp.srcImporter.Import(path) - if err1 == nil { + pkg, srcErr := imp.srcImporter.Import(path) + if srcErr == nil { imp.state.AddCachedPackage(path, pkg) if imp.debugImports { imp.debugPrint(fmt.Sprintf(`imported "%s" from source importer`, path)) @@ -63,8 +65,8 @@ func (imp *goImporter) Import(path string) (*types.Package, error) { return pkg, nil } - pkg, err2 := imp.defaultImporter.Import(path) - if err2 == nil { + pkg, defaultErr := imp.defaultImporter.Import(path) + if defaultErr == nil { imp.state.AddCachedPackage(path, pkg) if imp.debugImports { imp.debugPrint(fmt.Sprintf(`imported "%s" from %s importer`, path, runtime.Compiler)) @@ -72,45 +74,22 @@ func (imp *goImporter) Import(path string) (*types.Package, error) { return pkg, nil } - // Fallback to `go list` as a last resort. - pkg, err3 := imp.golistImport(path) - if err3 == nil { - imp.state.AddCachedPackage(path, pkg) - if imp.debugImports { - imp.debugPrint(fmt.Sprintf(`imported "%s" from golist importer`, path)) - } - return pkg, nil - } - if imp.debugImports { imp.debugPrint(fmt.Sprintf(`failed to import "%s":`, path)) - imp.debugPrint(fmt.Sprintf(" source importer: %v", err1)) - imp.debugPrint(fmt.Sprintf(" %s importer: %v", runtime.Compiler, err2)) - imp.debugPrint(fmt.Sprintf(" golist importer: %v", err3)) + imp.debugPrint(fmt.Sprintf(" %s importer: %v", runtime.Compiler, defaultErr)) + imp.debugPrint(fmt.Sprintf(" source importer: %v", srcErr)) + imp.debugPrint(fmt.Sprintf(" GOROOT=%q GOPATH=%q", imp.buildContext.GOROOT, imp.buildContext.GOPATH)) } - return nil, err2 + return nil, defaultErr } -func (imp *goImporter) golistImport(path string) (*types.Package, error) { - golistPkg, err := golist.JSON(path) - if err != nil { - return nil, err - } - - files := make([]*ast.File, 0, len(golistPkg.GoFiles)) - for _, filename := range golistPkg.GoFiles { - fullname := filepath.Join(golistPkg.Dir, filename) - f, err := parser.ParseFile(imp.fset, fullname, nil, 0) - if err != nil { - return nil, err +func (imp *goImporter) initSourceImporter() { + if imp.buildContext == nil { + if imp.debugImports { + imp.debugPrint("using build.Default context") } - files = append(files, f) + imp.buildContext = &build.Default } - - // TODO: do we want to assign imp as importer for this nested typecherker? - // Otherwise it won't be able to resolve imports. - var typecheker types.Config - var info types.Info - return typecheker.Check(path, imp.fset, files, &info) + imp.srcImporter = xsrcimporter.New(imp.buildContext, imp.fset) } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go new file mode 100644 index 000000000..46feaf0b5 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/filter_op.gen.go @@ -0,0 +1,224 @@ +// Code generated "gen_filter_op.go"; DO NOT EDIT. + +package ir + +const ( + FilterInvalidOp FilterOp = 0 + + // !$Args[0] + FilterNotOp FilterOp = 1 + + // $Args[0] && $Args[1] + FilterAndOp FilterOp = 2 + + // $Args[0] || $Args[1] + FilterOrOp FilterOp = 3 + + // $Args[0] == $Args[1] + FilterEqOp FilterOp = 4 + + // $Args[0] != $Args[1] + FilterNeqOp FilterOp = 5 + + // $Args[0] > $Args[1] + FilterGtOp FilterOp = 6 + + // $Args[0] < $Args[1] + FilterLtOp FilterOp = 7 + + // $Args[0] >= $Args[1] + FilterGtEqOp FilterOp = 8 + + // $Args[0] <= $Args[1] + FilterLtEqOp FilterOp = 9 + + // m[$Value].Addressable + // $Value type: string + FilterVarAddressableOp FilterOp = 10 + + // m[$Value].Pure + // $Value type: string + FilterVarPureOp FilterOp = 11 + + // m[$Value].Const + // $Value type: string + FilterVarConstOp FilterOp = 12 + + // m[$Value].ConstSlice + // $Value type: string + FilterVarConstSliceOp FilterOp = 13 + + // m[$Value].Text + // $Value type: string + FilterVarTextOp FilterOp = 14 + + // m[$Value].Line + // $Value type: string + FilterVarLineOp FilterOp = 15 + + // m[$Value].Value.Int() + // $Value type: string + FilterVarValueIntOp FilterOp = 16 + + // m[$Value].Type.Size + // $Value type: string + FilterVarTypeSizeOp FilterOp = 17 + + // m[$Value].Filter($Args[0]) + // $Value type: string + FilterVarFilterOp FilterOp = 18 + + // m[$Value].Node.Is($Args[0]) + // $Value type: string + FilterVarNodeIsOp FilterOp = 19 + + // m[$Value].Object.Is($Args[0]) + // $Value type: string + FilterVarObjectIsOp FilterOp = 20 + + // m[$Value].Type.Is($Args[0]) + // $Value type: string + FilterVarTypeIsOp FilterOp = 21 + + // m[$Value].Type.Underlying().Is($Args[0]) + // $Value type: string + FilterVarTypeUnderlyingIsOp FilterOp = 22 + + // m[$Value].Type.ConvertibleTo($Args[0]) + // $Value type: string + FilterVarTypeConvertibleToOp FilterOp = 23 + + // m[$Value].Type.AssignableTo($Args[0]) + // $Value type: string + FilterVarTypeAssignableToOp FilterOp = 24 + + // m[$Value].Type.Implements($Args[0]) + // $Value type: string + FilterVarTypeImplementsOp FilterOp = 25 + + // m[$Value].Text.Matches($Args[0]) + // $Value type: string + FilterVarTextMatchesOp FilterOp = 26 + + // m.Deadcode() + FilterDeadcodeOp FilterOp = 27 + + // m.GoVersion().Eq($Value) + // $Value type: string + FilterGoVersionEqOp FilterOp = 28 + + // m.GoVersion().LessThan($Value) + // $Value type: string + FilterGoVersionLessThanOp FilterOp = 29 + + // m.GoVersion().GreaterThan($Value) + // $Value type: string + FilterGoVersionGreaterThanOp FilterOp = 30 + + // m.GoVersion().LessEqThan($Value) + // $Value type: string + FilterGoVersionLessEqThanOp FilterOp = 31 + + // m.GoVersion().GreaterEqThan($Value) + // $Value type: string + FilterGoVersionGreaterEqThanOp FilterOp = 32 + + // m.File.Imports($Value) + // $Value type: string + FilterFileImportsOp FilterOp = 33 + + // m.File.PkgPath.Matches($Value) + // $Value type: string + FilterFilePkgPathMatchesOp FilterOp = 34 + + // m.File.Name.Matches($Value) + // $Value type: string + FilterFileNameMatchesOp FilterOp = 35 + + // $Value holds a function name + // $Value type: string + FilterFilterFuncRefOp FilterOp = 36 + + // $Value holds a string constant + // $Value type: string + FilterStringOp FilterOp = 37 + + // $Value holds an int64 constant + // $Value type: int64 + FilterIntOp FilterOp = 38 + + // m[`$$`].Node.Parent().Is($Args[0]) + FilterRootNodeParentIsOp FilterOp = 39 +) + +var filterOpNames = map[FilterOp]string{ + FilterInvalidOp: `Invalid`, + FilterNotOp: `Not`, + FilterAndOp: `And`, + FilterOrOp: `Or`, + FilterEqOp: `Eq`, + FilterNeqOp: `Neq`, + FilterGtOp: `Gt`, + FilterLtOp: `Lt`, + FilterGtEqOp: `GtEq`, + FilterLtEqOp: `LtEq`, + FilterVarAddressableOp: `VarAddressable`, + FilterVarPureOp: `VarPure`, + FilterVarConstOp: `VarConst`, + FilterVarConstSliceOp: `VarConstSlice`, + FilterVarTextOp: `VarText`, + FilterVarLineOp: `VarLine`, + FilterVarValueIntOp: `VarValueInt`, + FilterVarTypeSizeOp: `VarTypeSize`, + FilterVarFilterOp: `VarFilter`, + FilterVarNodeIsOp: `VarNodeIs`, + FilterVarObjectIsOp: `VarObjectIs`, + FilterVarTypeIsOp: `VarTypeIs`, + FilterVarTypeUnderlyingIsOp: `VarTypeUnderlyingIs`, + FilterVarTypeConvertibleToOp: `VarTypeConvertibleTo`, + FilterVarTypeAssignableToOp: `VarTypeAssignableTo`, + FilterVarTypeImplementsOp: `VarTypeImplements`, + FilterVarTextMatchesOp: `VarTextMatches`, + FilterDeadcodeOp: `Deadcode`, + FilterGoVersionEqOp: `GoVersionEq`, + FilterGoVersionLessThanOp: `GoVersionLessThan`, + FilterGoVersionGreaterThanOp: `GoVersionGreaterThan`, + FilterGoVersionLessEqThanOp: `GoVersionLessEqThan`, + FilterGoVersionGreaterEqThanOp: `GoVersionGreaterEqThan`, + FilterFileImportsOp: `FileImports`, + FilterFilePkgPathMatchesOp: `FilePkgPathMatches`, + FilterFileNameMatchesOp: `FileNameMatches`, + FilterFilterFuncRefOp: `FilterFuncRef`, + FilterStringOp: `String`, + FilterIntOp: `Int`, + FilterRootNodeParentIsOp: `RootNodeParentIs`, +} +var filterOpFlags = map[FilterOp]uint64{ + FilterAndOp: flagIsBinaryExpr, + FilterOrOp: flagIsBinaryExpr, + FilterEqOp: flagIsBinaryExpr, + FilterNeqOp: flagIsBinaryExpr, + FilterGtOp: flagIsBinaryExpr, + FilterLtOp: flagIsBinaryExpr, + FilterGtEqOp: flagIsBinaryExpr, + FilterLtEqOp: flagIsBinaryExpr, + FilterVarAddressableOp: flagHasVar, + FilterVarPureOp: flagHasVar, + FilterVarConstOp: flagHasVar, + FilterVarConstSliceOp: flagHasVar, + FilterVarTextOp: flagHasVar, + FilterVarLineOp: flagHasVar, + FilterVarValueIntOp: flagHasVar, + FilterVarTypeSizeOp: flagHasVar, + FilterVarFilterOp: flagHasVar, + FilterVarNodeIsOp: flagHasVar, + FilterVarObjectIsOp: flagHasVar, + FilterVarTypeIsOp: flagHasVar, + FilterVarTypeUnderlyingIsOp: flagHasVar, + FilterVarTypeConvertibleToOp: flagHasVar, + FilterVarTypeAssignableToOp: flagHasVar, + FilterVarTypeImplementsOp: flagHasVar, + FilterVarTextMatchesOp: flagHasVar, + FilterStringOp: flagIsBasicLit, + FilterIntOp: flagIsBasicLit, +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go new file mode 100644 index 000000000..a5b7b07eb --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/gen_filter_op.go @@ -0,0 +1,136 @@ +// +build generate + +package main + +import ( + "bytes" + "fmt" + "go/format" + "io/ioutil" + "strings" +) + +type opInfo struct { + name string + comment string + valueType string + flags uint64 +} + +const ( + flagIsBinaryExpr uint64 = 1 << iota + flagIsBasicLit + flagHasVar +) + +func main() { + ops := []opInfo{ + {name: "Invalid"}, + + {name: "Not", comment: "!$Args[0]"}, + + // Binary expressions. + {name: "And", comment: "$Args[0] && $Args[1]", flags: flagIsBinaryExpr}, + {name: "Or", comment: "$Args[0] || $Args[1]", flags: flagIsBinaryExpr}, + {name: "Eq", comment: "$Args[0] == $Args[1]", flags: flagIsBinaryExpr}, + {name: "Neq", comment: "$Args[0] != $Args[1]", flags: flagIsBinaryExpr}, + {name: "Gt", comment: "$Args[0] > $Args[1]", flags: flagIsBinaryExpr}, + {name: "Lt", comment: "$Args[0] < $Args[1]", flags: flagIsBinaryExpr}, + {name: "GtEq", comment: "$Args[0] >= $Args[1]", flags: flagIsBinaryExpr}, + {name: "LtEq", comment: "$Args[0] <= $Args[1]", flags: flagIsBinaryExpr}, + + {name: "VarAddressable", comment: "m[$Value].Addressable", valueType: "string", flags: flagHasVar}, + {name: "VarPure", comment: "m[$Value].Pure", valueType: "string", flags: flagHasVar}, + {name: "VarConst", comment: "m[$Value].Const", valueType: "string", flags: flagHasVar}, + {name: "VarConstSlice", comment: "m[$Value].ConstSlice", valueType: "string", flags: flagHasVar}, + {name: "VarText", comment: "m[$Value].Text", valueType: "string", flags: flagHasVar}, + {name: "VarLine", comment: "m[$Value].Line", valueType: "string", flags: flagHasVar}, + {name: "VarValueInt", comment: "m[$Value].Value.Int()", valueType: "string", flags: flagHasVar}, + {name: "VarTypeSize", comment: "m[$Value].Type.Size", valueType: "string", flags: flagHasVar}, + + {name: "VarFilter", comment: "m[$Value].Filter($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarNodeIs", comment: "m[$Value].Node.Is($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarObjectIs", comment: "m[$Value].Object.Is($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarTypeIs", comment: "m[$Value].Type.Is($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarTypeUnderlyingIs", comment: "m[$Value].Type.Underlying().Is($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarTypeConvertibleTo", comment: "m[$Value].Type.ConvertibleTo($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarTypeAssignableTo", comment: "m[$Value].Type.AssignableTo($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarTypeImplements", comment: "m[$Value].Type.Implements($Args[0])", valueType: "string", flags: flagHasVar}, + {name: "VarTextMatches", comment: "m[$Value].Text.Matches($Args[0])", valueType: "string", flags: flagHasVar}, + + {name: "Deadcode", comment: "m.Deadcode()"}, + + {name: "GoVersionEq", comment: "m.GoVersion().Eq($Value)", valueType: "string"}, + {name: "GoVersionLessThan", comment: "m.GoVersion().LessThan($Value)", valueType: "string"}, + {name: "GoVersionGreaterThan", comment: "m.GoVersion().GreaterThan($Value)", valueType: "string"}, + {name: "GoVersionLessEqThan", comment: "m.GoVersion().LessEqThan($Value)", valueType: "string"}, + {name: "GoVersionGreaterEqThan", comment: "m.GoVersion().GreaterEqThan($Value)", valueType: "string"}, + + {name: "FileImports", comment: "m.File.Imports($Value)", valueType: "string"}, + {name: "FilePkgPathMatches", comment: "m.File.PkgPath.Matches($Value)", valueType: "string"}, + {name: "FileNameMatches", comment: "m.File.Name.Matches($Value)", valueType: "string"}, + + {name: "FilterFuncRef", comment: "$Value holds a function name", valueType: "string"}, + + {name: "String", comment: "$Value holds a string constant", valueType: "string", flags: flagIsBasicLit}, + {name: "Int", comment: "$Value holds an int64 constant", valueType: "int64", flags: flagIsBasicLit}, + + {name: "RootNodeParentIs", comment: "m[`$$`].Node.Parent().Is($Args[0])"}, + } + + var buf bytes.Buffer + + buf.WriteString(`// Code generated "gen_filter_op.go"; DO NOT EDIT.` + "\n") + buf.WriteString("\n") + buf.WriteString("package ir\n") + buf.WriteString("const (\n") + + for i, op := range ops { + if strings.Contains(op.comment, "$Value") && op.valueType == "" { + fmt.Printf("missing %s valueType\n", op.name) + } + if op.comment != "" { + buf.WriteString("// " + op.comment + "\n") + } + if op.valueType != "" { + buf.WriteString("// $Value type: " + op.valueType + "\n") + } + fmt.Fprintf(&buf, "Filter%sOp FilterOp = %d\n", op.name, i) + buf.WriteString("\n") + } + buf.WriteString(")\n") + + buf.WriteString("var filterOpNames = map[FilterOp]string{\n") + for _, op := range ops { + fmt.Fprintf(&buf, "Filter%sOp: `%s`,\n", op.name, op.name) + } + buf.WriteString("}\n") + + buf.WriteString("var filterOpFlags = map[FilterOp]uint64{\n") + for _, op := range ops { + if op.flags == 0 { + continue + } + parts := make([]string, 0, 1) + if op.flags&flagIsBinaryExpr != 0 { + parts = append(parts, "flagIsBinaryExpr") + } + if op.flags&flagIsBasicLit != 0 { + parts = append(parts, "flagIsBasicLit") + } + if op.flags&flagHasVar != 0 { + parts = append(parts, "flagHasVar") + } + fmt.Fprintf(&buf, "Filter%sOp: %s,\n", op.name, strings.Join(parts, " | ")) + } + buf.WriteString("}\n") + + pretty, err := format.Source(buf.Bytes()) + if err != nil { + panic(err) + } + + if err := ioutil.WriteFile("filter_op.gen.go", pretty, 0644); err != nil { + panic(err) + } +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go new file mode 100644 index 000000000..552ddd757 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir/ir.go @@ -0,0 +1,112 @@ +package ir + +import ( + "fmt" + "strings" +) + +type File struct { + PkgPath string + + RuleGroups []RuleGroup + + CustomDecls []string + + BundleImports []BundleImport +} + +type BundleImport struct { + Line int + + PkgPath string + Prefix string +} + +type RuleGroup struct { + Line int + Name string + MatcherName string + + DocTags []string + DocSummary string + DocBefore string + DocAfter string + DocNote string + + Imports []PackageImport + + Rules []Rule +} + +type PackageImport struct { + Path string + Name string +} + +type Rule struct { + Line int + + SyntaxPatterns []PatternString + CommentPatterns []PatternString + + ReportTemplate string + SuggestTemplate string + + WhereExpr FilterExpr + + LocationVar string +} + +type PatternString struct { + Line int + Value string +} + +// stringer -type=FilterOp -trimprefix=Filter + +//go:generate go run ./gen_filter_op.go +type FilterOp int + +func (op FilterOp) String() string { return filterOpNames[op] } + +type FilterExpr struct { + Line int + + Op FilterOp + Src string + Value interface{} + Args []FilterExpr +} + +func (e FilterExpr) IsValid() bool { return e.Op != FilterInvalidOp } + +func (e FilterExpr) IsBinaryExpr() bool { return filterOpFlags[e.Op]&flagIsBinaryExpr != 0 } +func (e FilterExpr) IsBasicLit() bool { return filterOpFlags[e.Op]&flagIsBasicLit != 0 } +func (e FilterExpr) HasVar() bool { return filterOpFlags[e.Op]&flagHasVar != 0 } + +func (e FilterExpr) String() string { + switch e.Op { + case FilterStringOp: + return `"` + e.Value.(string) + `"` + case FilterIntOp: + return fmt.Sprint(e.Value.(int64)) + } + parts := make([]string, 0, len(e.Args)+2) + parts = append(parts, e.Op.String()) + if e.Value != nil { + parts = append(parts, fmt.Sprintf("[%#v]", e.Value)) + } + for _, arg := range e.Args { + parts = append(parts, arg.String()) + } + if len(parts) == 1 { + return parts[0] + } + return "(" + strings.Join(parts, " ") + ")" +} + +const ( + flagIsBinaryExpr uint64 = 1 << iota + flagIsBasicLit + flagHasVar +) diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go new file mode 100644 index 000000000..272ab7fe2 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_loader.go @@ -0,0 +1,720 @@ +package ruleguard + +import ( + "bytes" + "fmt" + "go/ast" + "go/constant" + "go/parser" + "go/token" + "go/types" + "io/ioutil" + "regexp" + + "github.com/quasilyte/go-ruleguard/internal/gogrep" + "github.com/quasilyte/go-ruleguard/nodetag" + "github.com/quasilyte/go-ruleguard/ruleguard/goutil" + "github.com/quasilyte/go-ruleguard/ruleguard/ir" + "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" + "github.com/quasilyte/go-ruleguard/ruleguard/textmatch" + "github.com/quasilyte/go-ruleguard/ruleguard/typematch" +) + +type irLoaderConfig struct { + ctx *LoadContext + + state *engineState + + importer *goImporter + + itab *typematch.ImportsTab + + pkg *types.Package + + gogrepFset *token.FileSet + + prefix string + importedPkg string +} + +type irLoader struct { + state *engineState + ctx *LoadContext + itab *typematch.ImportsTab + + pkg *types.Package + + file *ir.File + gogrepFset *token.FileSet + + filename string + res *goRuleSet + + importer *goImporter + + group *GoRuleGroup + + prefix string // For imported packages, a prefix that is added to a rule group name + importedPkg string // Package path; only for imported packages + + imported []*goRuleSet +} + +func newIRLoader(config irLoaderConfig) *irLoader { + return &irLoader{ + state: config.state, + ctx: config.ctx, + importer: config.importer, + itab: config.itab, + pkg: config.pkg, + prefix: config.prefix, + gogrepFset: config.gogrepFset, + } +} + +func (l *irLoader) LoadFile(filename string, f *ir.File) (*goRuleSet, error) { + l.filename = filename + l.file = f + l.res = &goRuleSet{ + universal: &scopedGoRuleSet{}, + groups: make(map[string]*GoRuleGroup), + } + + for _, imp := range f.BundleImports { + if l.importedPkg != "" { + return nil, l.errorf(imp.Line, nil, "imports from imported packages are not supported yet") + } + if err := l.loadBundle(imp); err != nil { + return nil, err + } + } + + if err := l.compileFilterFuncs(filename, f); err != nil { + return nil, err + } + + for i := range f.RuleGroups { + if err := l.loadRuleGroup(&f.RuleGroups[i]); err != nil { + return nil, err + } + } + + if len(l.imported) != 0 { + toMerge := []*goRuleSet{l.res} + toMerge = append(toMerge, l.imported...) + merged, err := mergeRuleSets(toMerge) + if err != nil { + return nil, err + } + l.res = merged + } + + return l.res, nil +} + +func (l *irLoader) importErrorf(line int, wrapped error, format string, args ...interface{}) error { + return &ImportError{ + msg: fmt.Sprintf("%s:%d: %s", l.filename, line, fmt.Sprintf(format, args...)), + err: wrapped, + } +} + +func (l *irLoader) errorf(line int, wrapped error, format string, args ...interface{}) error { + if wrapped == nil { + return fmt.Errorf("%s:%d: %s", l.filename, line, fmt.Sprintf(format, args...)) + } + return fmt.Errorf("%s:%d: %s: %w", l.filename, line, fmt.Sprintf(format, args...), wrapped) +} + +func (l *irLoader) loadBundle(bundle ir.BundleImport) error { + files, err := findBundleFiles(bundle.PkgPath) + if err != nil { + return l.errorf(bundle.Line, err, "can't find imported bundle files") + } + for _, filename := range files { + rset, err := l.loadExternFile(bundle.Prefix, bundle.PkgPath, filename) + if err != nil { + return l.errorf(bundle.Line, err, "error during bundle file loading") + } + l.imported = append(l.imported, rset) + } + + return nil +} + +func (l *irLoader) loadExternFile(prefix, pkgPath, filename string) (*goRuleSet, error) { + src, err := ioutil.ReadFile(filename) + if err != nil { + return nil, err + } + irfile, pkg, err := convertAST(l.ctx, l.importer, filename, src) + if err != nil { + return nil, err + } + config := irLoaderConfig{ + state: l.state, + ctx: l.ctx, + importer: l.importer, + prefix: prefix, + pkg: pkg, + importedPkg: pkgPath, + itab: l.itab, + gogrepFset: l.gogrepFset, + } + rset, err := newIRLoader(config).LoadFile(filename, irfile) + if err != nil { + return nil, fmt.Errorf("%s: %w", l.importedPkg, err) + } + return rset, nil +} + +func (l *irLoader) compileFilterFuncs(filename string, irfile *ir.File) error { + if len(irfile.CustomDecls) == 0 { + return nil + } + + var buf bytes.Buffer + buf.WriteString("package gorules\n") + buf.WriteString("import \"github.com/quasilyte/go-ruleguard/dsl\"\n") + buf.WriteString("import \"github.com/quasilyte/go-ruleguard/dsl/types\"\n") + buf.WriteString("type _ = dsl.Matcher\n") + buf.WriteString("type _ = types.Type\n") + for _, src := range irfile.CustomDecls { + buf.WriteString(src) + buf.WriteString("\n") + } + + fset := token.NewFileSet() + f, err := goutil.LoadGoFile(goutil.LoadConfig{ + Fset: fset, + Filename: filename, + Data: &buf, + Importer: l.importer, + }) + if err != nil { + // If this ever happens, user will get unexpected error + // lines for it; but we should trust that 99.9% errors + // should be catched at irconv phase so we get a valid Go + // source here as well? + return fmt.Errorf("parse custom decls: %w", err) + } + + for _, decl := range f.Syntax.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + ctx := &quasigo.CompileContext{ + Env: l.state.env, + Types: f.Types, + Fset: fset, + } + compiled, err := quasigo.Compile(ctx, decl) + if err != nil { + return err + } + if l.ctx.DebugFilter == decl.Name.String() { + l.ctx.DebugPrint(quasigo.Disasm(l.state.env, compiled)) + } + ctx.Env.AddFunc(f.Pkg.Path(), decl.Name.String(), compiled) + } + + return nil +} + +func (l *irLoader) loadRuleGroup(group *ir.RuleGroup) error { + l.group = &GoRuleGroup{ + Line: group.Line, + Filename: l.filename, + Name: group.Name, + DocSummary: group.DocSummary, + DocBefore: group.DocBefore, + DocAfter: group.DocAfter, + DocNote: group.DocNote, + DocTags: group.DocTags, + } + if l.prefix != "" { + l.group.Name = l.prefix + "/" + l.group.Name + } + + if l.ctx.GroupFilter != nil && !l.ctx.GroupFilter(l.group.Name) { + return nil // Skip this group + } + if _, ok := l.res.groups[l.group.Name]; ok { + panic(fmt.Sprintf("duplicated function %s after the typecheck", l.group.Name)) // Should never happen + } + l.res.groups[l.group.Name] = l.group + + l.itab.EnterScope() + defer l.itab.LeaveScope() + + for _, imported := range group.Imports { + l.itab.Load(imported.Name, imported.Path) + } + + for _, rule := range group.Rules { + if err := l.loadRule(rule); err != nil { + return err + } + } + + return nil +} + +func (l *irLoader) loadRule(rule ir.Rule) error { + proto := goRule{ + line: rule.Line, + group: l.group, + suggestion: rule.SuggestTemplate, + msg: rule.ReportTemplate, + location: rule.LocationVar, + } + + info := filterInfo{ + Vars: make(map[string]struct{}), + } + if rule.WhereExpr.IsValid() { + filter, err := l.newFilter(rule.WhereExpr, &info) + if err != nil { + return err + } + proto.filter = filter + } + + for _, pat := range rule.SyntaxPatterns { + if err := l.loadSyntaxRule(proto, info, rule, pat.Value, pat.Line); err != nil { + return err + } + } + for _, pat := range rule.CommentPatterns { + if err := l.loadCommentRule(proto, rule, pat.Value, pat.Line); err != nil { + return err + } + } + return nil +} + +func (l *irLoader) loadCommentRule(resultProto goRule, rule ir.Rule, src string, line int) error { + dst := l.res.universal + pat, err := regexp.Compile(src) + if err != nil { + return l.errorf(rule.Line, err, "compile regexp") + } + resultBase := resultProto + resultBase.line = line + result := goCommentRule{ + base: resultProto, + pat: pat, + captureGroups: regexpHasCaptureGroups(src), + } + dst.commentRules = append(dst.commentRules, result) + + return nil +} + +func (l *irLoader) loadSyntaxRule(resultProto goRule, filterInfo filterInfo, rule ir.Rule, src string, line int) error { + result := resultProto + result.line = line + + pat, info, err := gogrep.Compile(l.gogrepFset, src, false) + if err != nil { + return l.errorf(rule.Line, err, "parse match pattern") + } + result.pat = pat + + for filterVar := range filterInfo.Vars { + if filterVar == "$$" { + continue // OK: a predefined var for the "entire match" + } + _, ok := info.Vars[filterVar] + if !ok { + return l.errorf(rule.Line, nil, "filter refers to a non-existing var %s", filterVar) + } + } + + dst := l.res.universal + var dstTags []nodetag.Value + switch tag := pat.NodeTag(); tag { + case nodetag.Unknown: + return l.errorf(rule.Line, nil, "can't infer a tag of %s", src) + case nodetag.Node: + return l.errorf(rule.Line, nil, "%s pattern is too general", src) + case nodetag.StmtList: + dstTags = []nodetag.Value{ + nodetag.BlockStmt, + nodetag.CaseClause, + nodetag.CommClause, + } + case nodetag.ExprList: + dstTags = []nodetag.Value{ + nodetag.CallExpr, + nodetag.CompositeLit, + nodetag.ReturnStmt, + } + default: + dstTags = []nodetag.Value{tag} + } + for _, tag := range dstTags { + dst.rulesByTag[tag] = append(dst.rulesByTag[tag], result) + } + dst.categorizedNum++ + + return nil +} + +func (l *irLoader) unwrapTypeExpr(filter ir.FilterExpr) (types.Type, error) { + typeString := l.unwrapStringExpr(filter) + if typeString == "" { + return nil, l.errorf(filter.Line, nil, "expected a non-empty type string") + } + typ, err := typeFromString(typeString) + if err != nil { + return nil, l.errorf(filter.Line, err, "parse type expr") + } + if typ == nil { + return nil, l.errorf(filter.Line, nil, "can't convert %s into a type constraint yet", typeString) + } + return typ, nil +} + +func (l *irLoader) unwrapInterfaceExpr(filter ir.FilterExpr) (*types.Interface, error) { + typeString := l.unwrapStringExpr(filter) + if typeString == "" { + return nil, l.errorf(filter.Line, nil, "expected a non-empty type name string") + } + + typ, err := l.state.FindType(l.importer, l.pkg, typeString) + if err == nil { + iface, ok := typ.Underlying().(*types.Interface) + if !ok { + return nil, l.errorf(filter.Line, nil, "%s is not an interface type", typeString) + } + return iface, nil + } + + n, err := parser.ParseExpr(typeString) + if err != nil { + return nil, l.errorf(filter.Line, err, "parse %s type expr", typeString) + } + qn, ok := n.(*ast.SelectorExpr) + if !ok { + return nil, l.errorf(filter.Line, nil, "can't resolve %s type; try a fully-qualified name", typeString) + } + pkgName, ok := qn.X.(*ast.Ident) + if !ok { + return nil, l.errorf(filter.Line, nil, "invalid package name") + } + pkgPath, ok := l.itab.Lookup(pkgName.Name) + if !ok { + return nil, l.errorf(filter.Line, nil, "package %s is not imported", pkgName.Name) + } + pkg, err := l.importer.Import(pkgPath) + if err != nil { + return nil, l.importErrorf(filter.Line, err, "can't load %s", pkgPath) + } + obj := pkg.Scope().Lookup(qn.Sel.Name) + if obj == nil { + return nil, l.errorf(filter.Line, nil, "%s is not found in %s", qn.Sel.Name, pkgPath) + } + iface, ok := obj.Type().Underlying().(*types.Interface) + if !ok { + return nil, l.errorf(filter.Line, nil, "%s is not an interface type", qn.Sel.Name) + } + return iface, nil +} + +func (l *irLoader) unwrapRegexpExpr(filter ir.FilterExpr) (textmatch.Pattern, error) { + patternString := l.unwrapStringExpr(filter) + if patternString == "" { + return nil, l.errorf(filter.Line, nil, "expected a non-empty regexp pattern argument") + } + re, err := textmatch.Compile(patternString) + if err != nil { + return nil, l.errorf(filter.Line, err, "compile regexp") + } + return re, nil +} + +func (l *irLoader) unwrapNodeTagExpr(filter ir.FilterExpr) (nodetag.Value, error) { + typeString := l.unwrapStringExpr(filter) + if typeString == "" { + return nodetag.Unknown, l.errorf(filter.Line, nil, "expected a non-empty string argument") + } + tag := nodetag.FromString(typeString) + if tag == nodetag.Unknown { + return tag, l.errorf(filter.Line, nil, "%s is not a valid go/ast type name", typeString) + } + return tag, nil +} + +func (l *irLoader) unwrapStringExpr(filter ir.FilterExpr) string { + if filter.Op == ir.FilterStringOp { + return filter.Value.(string) + } + return "" +} + +func (l *irLoader) newFilter(filter ir.FilterExpr, info *filterInfo) (matchFilter, error) { + if filter.HasVar() { + info.Vars[filter.Value.(string)] = struct{}{} + } + + if filter.IsBinaryExpr() { + return l.newBinaryExprFilter(filter, info) + } + + result := matchFilter{src: filter.Src} + + switch filter.Op { + case ir.FilterNotOp: + x, err := l.newFilter(filter.Args[0], info) + if err != nil { + return result, err + } + result.fn = makeNotFilter(result.src, x) + + case ir.FilterVarTextMatchesOp: + re, err := l.unwrapRegexpExpr(filter.Args[0]) + if err != nil { + return result, err + } + result.fn = makeTextMatchesFilter(result.src, filter.Value.(string), re) + + case ir.FilterVarObjectIsOp: + typeString := l.unwrapStringExpr(filter.Args[0]) + if typeString == "" { + return result, l.errorf(filter.Line, nil, "expected a non-empty string argument") + } + switch typeString { + case "Func", "Var", "Const", "TypeName", "Label", "PkgName", "Builtin", "Nil": + // OK. + default: + return result, l.errorf(filter.Line, nil, "%s is not a valid go/types object name", typeString) + } + result.fn = makeObjectIsFilter(result.src, filter.Value.(string), typeString) + + case ir.FilterRootNodeParentIsOp: + tag, err := l.unwrapNodeTagExpr(filter.Args[0]) + if err != nil { + return result, err + } + result.fn = makeRootParentNodeIsFilter(result.src, tag) + + case ir.FilterVarNodeIsOp: + tag, err := l.unwrapNodeTagExpr(filter.Args[0]) + if err != nil { + return result, err + } + result.fn = makeNodeIsFilter(result.src, filter.Value.(string), tag) + + case ir.FilterVarTypeIsOp, ir.FilterVarTypeUnderlyingIsOp: + typeString := l.unwrapStringExpr(filter.Args[0]) + if typeString == "" { + return result, l.errorf(filter.Line, nil, "expected a non-empty string argument") + } + ctx := typematch.Context{Itab: l.itab} + pat, err := typematch.Parse(&ctx, typeString) + if err != nil { + return result, l.errorf(filter.Line, err, "parse type expr") + } + underlying := filter.Op == ir.FilterVarTypeUnderlyingIsOp + result.fn = makeTypeIsFilter(result.src, filter.Value.(string), underlying, pat) + + case ir.FilterVarTypeConvertibleToOp: + dstType, err := l.unwrapTypeExpr(filter.Args[0]) + if err != nil { + return result, err + } + result.fn = makeTypeConvertibleToFilter(result.src, filter.Value.(string), dstType) + + case ir.FilterVarTypeAssignableToOp: + dstType, err := l.unwrapTypeExpr(filter.Args[0]) + if err != nil { + return result, err + } + result.fn = makeTypeAssignableToFilter(result.src, filter.Value.(string), dstType) + + case ir.FilterVarTypeImplementsOp: + iface, err := l.unwrapInterfaceExpr(filter.Args[0]) + if err != nil { + return result, err + } + result.fn = makeTypeImplementsFilter(result.src, filter.Value.(string), iface) + + case ir.FilterVarPureOp: + result.fn = makePureFilter(result.src, filter.Value.(string)) + case ir.FilterVarConstOp: + result.fn = makeConstFilter(result.src, filter.Value.(string)) + case ir.FilterVarConstSliceOp: + result.fn = makeConstSliceFilter(result.src, filter.Value.(string)) + case ir.FilterVarAddressableOp: + result.fn = makeAddressableFilter(result.src, filter.Value.(string)) + + case ir.FilterFileImportsOp: + result.fn = makeFileImportsFilter(result.src, filter.Value.(string)) + + case ir.FilterDeadcodeOp: + result.fn = makeDeadcodeFilter(result.src) + + case ir.FilterGoVersionEqOp: + version, err := ParseGoVersion(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "parse Go version") + } + result.fn = makeGoVersionFilter(result.src, token.EQL, version) + case ir.FilterGoVersionLessThanOp: + version, err := ParseGoVersion(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "parse Go version") + } + result.fn = makeGoVersionFilter(result.src, token.LSS, version) + case ir.FilterGoVersionGreaterThanOp: + version, err := ParseGoVersion(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "parse Go version") + } + result.fn = makeGoVersionFilter(result.src, token.GTR, version) + case ir.FilterGoVersionLessEqThanOp: + version, err := ParseGoVersion(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "parse Go version") + } + result.fn = makeGoVersionFilter(result.src, token.LEQ, version) + case ir.FilterGoVersionGreaterEqThanOp: + version, err := ParseGoVersion(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "parse Go version") + } + result.fn = makeGoVersionFilter(result.src, token.GEQ, version) + + case ir.FilterFilePkgPathMatchesOp: + re, err := regexp.Compile(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "compile regexp") + } + result.fn = makeFilePkgPathMatchesFilter(result.src, re) + + case ir.FilterFileNameMatchesOp: + re, err := regexp.Compile(filter.Value.(string)) + if err != nil { + return result, l.errorf(filter.Line, err, "compile regexp") + } + result.fn = makeFileNameMatchesFilter(result.src, re) + + case ir.FilterVarFilterOp: + funcName := filter.Args[0].Value.(string) + userFn := l.state.env.GetFunc(l.file.PkgPath, funcName) + if userFn == nil { + return result, l.errorf(filter.Line, nil, "can't find a compiled version of %s", funcName) + } + result.fn = makeCustomVarFilter(result.src, filter.Value.(string), userFn) + } + + if result.fn == nil { + return result, l.errorf(filter.Line, nil, "unsupported expr: %s (%s)", result.src, filter.Op) + } + + return result, nil +} + +func (l *irLoader) newBinaryExprFilter(filter ir.FilterExpr, info *filterInfo) (matchFilter, error) { + if filter.Op == ir.FilterAndOp || filter.Op == ir.FilterOrOp { + result := matchFilter{src: filter.Src} + lhs, err := l.newFilter(filter.Args[0], info) + if err != nil { + return result, err + } + rhs, err := l.newFilter(filter.Args[1], info) + if err != nil { + return result, err + } + if filter.Op == ir.FilterAndOp { + result.fn = makeAndFilter(lhs, rhs) + } else { + result.fn = makeOrFilter(lhs, rhs) + } + return result, nil + } + + // If constexpr is on the LHS, move it to the right, so the code below + // can imply constants being on the RHS all the time. + if filter.Args[0].IsBasicLit() && !filter.Args[1].IsBasicLit() { + // Just a precaution: if we ever have a float values here, + // we may not want to rearrange anything. + switch filter.Args[0].Value.(type) { + case string, int64: + switch filter.Op { + case ir.FilterEqOp, ir.FilterNeqOp: + // Simple commutative ops. Just swap the args. + newFilter := filter + newFilter.Args = []ir.FilterExpr{filter.Args[1], filter.Args[0]} + return l.newBinaryExprFilter(newFilter, info) + } + } + } + + result := matchFilter{src: filter.Src} + + var tok token.Token + switch filter.Op { + case ir.FilterEqOp: + tok = token.EQL + case ir.FilterNeqOp: + tok = token.NEQ + case ir.FilterGtOp: + tok = token.GTR + case ir.FilterGtEqOp: + tok = token.GEQ + case ir.FilterLtOp: + tok = token.LSS + case ir.FilterLtEqOp: + tok = token.LEQ + default: + return result, l.errorf(filter.Line, nil, "unsupported operator in binary expr: %s", result.src) + } + + lhs := filter.Args[0] + rhs := filter.Args[1] + var rhsValue constant.Value + switch rhs.Op { + case ir.FilterStringOp: + rhsValue = constant.MakeString(rhs.Value.(string)) + case ir.FilterIntOp: + rhsValue = constant.MakeInt64(rhs.Value.(int64)) + } + + switch lhs.Op { + case ir.FilterVarLineOp: + if rhsValue != nil { + result.fn = makeLineConstFilter(result.src, lhs.Value.(string), tok, rhsValue) + } else if rhs.Op == lhs.Op { + result.fn = makeLineFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) + } + case ir.FilterVarTypeSizeOp: + if rhsValue != nil { + result.fn = makeTypeSizeConstFilter(result.src, lhs.Value.(string), tok, rhsValue) + } + case ir.FilterVarValueIntOp: + if rhsValue != nil { + result.fn = makeValueIntConstFilter(result.src, lhs.Value.(string), tok, rhsValue) + } else if rhs.Op == lhs.Op { + result.fn = makeValueIntFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) + } + case ir.FilterVarTextOp: + if rhsValue != nil { + result.fn = makeTextConstFilter(result.src, lhs.Value.(string), tok, rhsValue) + } else if rhs.Op == lhs.Op { + result.fn = makeTextFilter(result.src, lhs.Value.(string), tok, rhs.Value.(string)) + } + } + + if result.fn == nil { + return result, l.errorf(filter.Line, nil, "unsupported binary expr: %s", result.src) + } + + return result, nil +} + +type filterInfo struct { + Vars map[string]struct{} +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go new file mode 100644 index 000000000..62c24bf15 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ir_utils.go @@ -0,0 +1,41 @@ +package ruleguard + +import ( + "fmt" + "go/ast" + "go/parser" + "go/types" + + "github.com/quasilyte/go-ruleguard/ruleguard/ir" + "github.com/quasilyte/go-ruleguard/ruleguard/irconv" +) + +func convertAST(ctx *LoadContext, imp *goImporter, filename string, src []byte) (*ir.File, *types.Package, error) { + parserFlags := parser.ParseComments + f, err := parser.ParseFile(ctx.Fset, filename, src, parserFlags) + if err != nil { + return nil, nil, fmt.Errorf("parse file error: %w", err) + } + + typechecker := types.Config{Importer: imp} + typesInfo := &types.Info{ + Types: map[ast.Expr]types.TypeAndValue{}, + Uses: map[*ast.Ident]types.Object{}, + Defs: map[*ast.Ident]types.Object{}, + } + pkg, err := typechecker.Check("gorules", ctx.Fset, []*ast.File{f}, typesInfo) + if err != nil { + return nil, nil, fmt.Errorf("typechecker error: %w", err) + } + irconvCtx := &irconv.Context{ + Pkg: pkg, + Types: typesInfo, + Fset: ctx.Fset, + Src: src, + } + irfile, err := irconv.ConvertFile(irconvCtx, f) + if err != nil { + return nil, nil, fmt.Errorf("irconv error: %w", err) + } + return irfile, pkg, nil +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go new file mode 100644 index 000000000..ceb6e816a --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/irconv/irconv.go @@ -0,0 +1,630 @@ +package irconv + +import ( + "fmt" + "go/ast" + "go/constant" + "go/token" + "go/types" + "path" + "strconv" + "strings" + + "github.com/quasilyte/go-ruleguard/ruleguard/goutil" + "github.com/quasilyte/go-ruleguard/ruleguard/ir" + "golang.org/x/tools/go/ast/astutil" +) + +type Context struct { + Pkg *types.Package + Types *types.Info + Fset *token.FileSet + Src []byte +} + +func ConvertFile(ctx *Context, f *ast.File) (result *ir.File, err error) { + defer func() { + if err != nil { + return + } + rv := recover() + if rv == nil { + return + } + if convErr, ok := rv.(convError); ok { + err = convErr.err + return + } + panic(rv) // not our panic + }() + + conv := &converter{ + types: ctx.Types, + pkg: ctx.Pkg, + fset: ctx.Fset, + src: ctx.Src, + } + result = conv.ConvertFile(f) + return result, nil +} + +type convError struct { + err error +} + +type converter struct { + types *types.Info + pkg *types.Package + fset *token.FileSet + src []byte + + group *ir.RuleGroup + + dslPkgname string // The local name of the "ruleguard/dsl" package (usually its just "dsl") +} + +func (conv *converter) errorf(n ast.Node, format string, args ...interface{}) convError { + loc := conv.fset.Position(n.Pos()) + msg := fmt.Sprintf(format, args...) + return convError{err: fmt.Errorf("%s:%d: %s", loc.Filename, loc.Line, msg)} +} + +func (conv *converter) ConvertFile(f *ast.File) *ir.File { + result := &ir.File{ + PkgPath: conv.pkg.Path(), + } + + conv.dslPkgname = "dsl" + + for _, imp := range f.Imports { + importPath, err := strconv.Unquote(imp.Path.Value) + if err != nil { + panic(conv.errorf(imp, "unquote %s import path: %s", imp.Path.Value, err)) + } + if importPath == "github.com/quasilyte/go-ruleguard/dsl" { + if imp.Name != nil { + conv.dslPkgname = imp.Name.Name + } + } + } + + for _, decl := range f.Decls { + funcDecl, ok := decl.(*ast.FuncDecl) + if !ok { + genDecl := decl.(*ast.GenDecl) + if genDecl.Tok != token.IMPORT { + conv.addCustomDecl(result, decl) + } + continue + } + + if funcDecl.Name.String() == "init" { + conv.convertInitFunc(result, funcDecl) + continue + } + + if conv.isMatcherFunc(funcDecl) { + result.RuleGroups = append(result.RuleGroups, *conv.convertRuleGroup(funcDecl)) + } else { + conv.addCustomDecl(result, funcDecl) + } + } + + return result +} + +func (conv *converter) convertInitFunc(dst *ir.File, decl *ast.FuncDecl) { + for _, stmt := range decl.Body.List { + exprStmt, ok := stmt.(*ast.ExprStmt) + if !ok { + panic(conv.errorf(stmt, "unsupported statement")) + } + call, ok := exprStmt.X.(*ast.CallExpr) + if !ok { + panic(conv.errorf(stmt, "unsupported expr")) + } + fn, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + panic(conv.errorf(stmt, "unsupported call")) + } + pkg, ok := fn.X.(*ast.Ident) + if !ok || pkg.Name != conv.dslPkgname { + panic(conv.errorf(stmt, "unsupported call")) + } + + switch fn.Sel.Name { + case "ImportRules": + prefix := conv.parseStringArg(call.Args[0]) + bundleSelector, ok := call.Args[1].(*ast.SelectorExpr) + if !ok { + panic(conv.errorf(call.Args[1], "expected a `pkgname.Bundle` argument")) + } + bundleObj := conv.types.ObjectOf(bundleSelector.Sel) + dst.BundleImports = append(dst.BundleImports, ir.BundleImport{ + Prefix: prefix, + PkgPath: bundleObj.Pkg().Path(), + Line: conv.fset.Position(exprStmt.Pos()).Line, + }) + + default: + panic(conv.errorf(stmt, "unsupported %s call", fn.Sel.Name)) + } + } +} + +func (conv *converter) addCustomDecl(dst *ir.File, decl ast.Decl) { + begin := conv.fset.Position(decl.Pos()) + end := conv.fset.Position(decl.End()) + src := conv.src[begin.Offset:end.Offset] + dst.CustomDecls = append(dst.CustomDecls, string(src)) +} + +func (conv *converter) isMatcherFunc(f *ast.FuncDecl) bool { + typ := conv.types.ObjectOf(f.Name).Type().(*types.Signature) + return typ.Results().Len() == 0 && + typ.Params().Len() == 1 && + typ.Params().At(0).Type().String() == "github.com/quasilyte/go-ruleguard/dsl.Matcher" +} + +func (conv *converter) convertRuleGroup(decl *ast.FuncDecl) *ir.RuleGroup { + result := &ir.RuleGroup{ + Line: conv.fset.Position(decl.Name.Pos()).Line, + } + conv.group = result + + result.Name = decl.Name.String() + result.MatcherName = decl.Type.Params.List[0].Names[0].String() + + if decl.Doc != nil { + conv.convertDocComments(decl.Doc) + } + + seenRules := false + for _, stmt := range decl.Body.List { + if _, ok := stmt.(*ast.DeclStmt); ok { + continue + } + stmtExpr, ok := stmt.(*ast.ExprStmt) + if !ok { + panic(conv.errorf(stmt, "expected a %s method call, found %s", result.MatcherName, goutil.SprintNode(conv.fset, stmt))) + } + call, ok := stmtExpr.X.(*ast.CallExpr) + if !ok { + panic(conv.errorf(stmt, "expected a %s method call, found %s", result.MatcherName, goutil.SprintNode(conv.fset, stmt))) + } + + switch conv.matcherMethodName(call) { + case "Import": + if seenRules { + panic(conv.errorf(call, "Import() should be used before any rules definitions")) + } + conv.doMatcherImport(call) + default: + seenRules = true + conv.convertRuleExpr(call) + } + } + + return result +} + +func (conv *converter) doMatcherImport(call *ast.CallExpr) { + pkgPath := conv.parseStringArg(call.Args[0]) + pkgName := path.Base(pkgPath) + conv.group.Imports = append(conv.group.Imports, ir.PackageImport{ + Path: pkgPath, + Name: pkgName, + }) +} + +func (conv *converter) matcherMethodName(call *ast.CallExpr) string { + selector, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return "" + } + id, ok := selector.X.(*ast.Ident) + if !ok || id.Name != conv.group.MatcherName { + return "" + } + return selector.Sel.Name +} + +func (conv *converter) convertDocComments(comment *ast.CommentGroup) { + knownPragmas := []string{ + "tags", + "summary", + "before", + "after", + "note", + } + + for _, c := range comment.List { + if !strings.HasPrefix(c.Text, "//doc:") { + continue + } + s := strings.TrimPrefix(c.Text, "//doc:") + var pragma string + for i := range knownPragmas { + if strings.HasPrefix(s, knownPragmas[i]) { + pragma = knownPragmas[i] + break + } + } + if pragma == "" { + panic(conv.errorf(c, "unrecognized 'doc' pragma in comment")) + } + s = strings.TrimPrefix(s, pragma) + s = strings.TrimSpace(s) + switch pragma { + case "summary": + conv.group.DocSummary = s + case "before": + conv.group.DocBefore = s + case "after": + conv.group.DocAfter = s + case "note": + conv.group.DocNote = s + case "tags": + conv.group.DocTags = strings.Fields(s) + default: + panic("unhandled 'doc' pragma: " + pragma) // Should never happen + } + } +} + +func (conv *converter) convertRuleExpr(call *ast.CallExpr) { + origCall := call + var ( + matchArgs *[]ast.Expr + matchCommentArgs *[]ast.Expr + whereArgs *[]ast.Expr + suggestArgs *[]ast.Expr + reportArgs *[]ast.Expr + atArgs *[]ast.Expr + ) + + for { + chain, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + break + } + switch chain.Sel.Name { + case "Match": + if matchArgs != nil { + panic(conv.errorf(chain.Sel, "Match() can't be repeated")) + } + if matchCommentArgs != nil { + panic(conv.errorf(chain.Sel, "Match() and MatchComment() can't be combined")) + } + matchArgs = &call.Args + case "MatchComment": + if matchCommentArgs != nil { + panic(conv.errorf(chain.Sel, "MatchComment() can't be repeated")) + } + if matchArgs != nil { + panic(conv.errorf(chain.Sel, "Match() and MatchComment() can't be combined")) + } + matchCommentArgs = &call.Args + case "Where": + if whereArgs != nil { + panic(conv.errorf(chain.Sel, "Where() can't be repeated")) + } + whereArgs = &call.Args + case "Suggest": + if suggestArgs != nil { + panic(conv.errorf(chain.Sel, "Suggest() can't be repeated")) + } + suggestArgs = &call.Args + case "Report": + if reportArgs != nil { + panic(conv.errorf(chain.Sel, "Report() can't be repeated")) + } + reportArgs = &call.Args + case "At": + if atArgs != nil { + panic(conv.errorf(chain.Sel, "At() can't be repeated")) + } + atArgs = &call.Args + default: + panic(conv.errorf(chain.Sel, "unexpected %s method", chain.Sel.Name)) + } + call, ok = chain.X.(*ast.CallExpr) + if !ok { + break + } + } + + // AST patterns for Match() or regexp patterns for MatchComment(). + var alternatives []string + var alternativeLines []int + + if matchArgs == nil && matchCommentArgs == nil { + panic(conv.errorf(origCall, "missing Match() or MatchComment() call")) + } + + if matchArgs != nil { + for _, arg := range *matchArgs { + alternatives = append(alternatives, conv.parseStringArg(arg)) + alternativeLines = append(alternativeLines, conv.fset.Position(arg.Pos()).Line) + } + } else { + for _, arg := range *matchCommentArgs { + alternatives = append(alternatives, conv.parseStringArg(arg)) + alternativeLines = append(alternativeLines, conv.fset.Position(arg.Pos()).Line) + } + } + + rule := ir.Rule{Line: conv.fset.Position(origCall.Pos()).Line} + + if atArgs != nil { + index, ok := (*atArgs)[0].(*ast.IndexExpr) + if !ok { + panic(conv.errorf((*atArgs)[0], "expected %s[`varname`] expression", conv.group.MatcherName)) + } + rule.LocationVar = conv.parseStringArg(index.Index) + } + + if whereArgs != nil { + rule.WhereExpr = conv.convertFilterExpr((*whereArgs)[0]) + } + + if suggestArgs != nil { + rule.SuggestTemplate = conv.parseStringArg((*suggestArgs)[0]) + } + + if suggestArgs == nil && reportArgs == nil { + panic(conv.errorf(origCall, "missing Report() or Suggest() call")) + } + if reportArgs == nil { + rule.ReportTemplate = "suggestion: " + rule.SuggestTemplate + } else { + rule.ReportTemplate = conv.parseStringArg((*reportArgs)[0]) + } + + for i, alt := range alternatives { + pat := ir.PatternString{ + Line: alternativeLines[i], + Value: alt, + } + if matchArgs != nil { + rule.SyntaxPatterns = append(rule.SyntaxPatterns, pat) + } else { + rule.CommentPatterns = append(rule.CommentPatterns, pat) + } + } + conv.group.Rules = append(conv.group.Rules, rule) +} + +func (conv *converter) convertFilterExpr(e ast.Expr) ir.FilterExpr { + result := conv.convertFilterExprImpl(e) + result.Src = goutil.SprintNode(conv.fset, e) + result.Line = conv.fset.Position(e.Pos()).Line + if !result.IsValid() { + panic(conv.errorf(e, "unsupported expr: %s (%T)", result.Src, e)) + } + return result +} + +func (conv *converter) convertFilterExprImpl(e ast.Expr) ir.FilterExpr { + if cv := conv.types.Types[e].Value; cv != nil { + switch cv.Kind() { + case constant.String: + v := constant.StringVal(cv) + return ir.FilterExpr{Op: ir.FilterStringOp, Value: v} + case constant.Int: + v, ok := constant.Int64Val(cv) + if ok { + return ir.FilterExpr{Op: ir.FilterIntOp, Value: v} + } + } + } + convertExprList := func(list []ast.Expr) []ir.FilterExpr { + if len(list) == 0 { + return nil + } + result := make([]ir.FilterExpr, len(list)) + for i, e := range list { + result[i] = conv.convertFilterExpr(e) + } + return result + } + + switch e := e.(type) { + case *ast.ParenExpr: + return conv.convertFilterExpr(e.X) + + case *ast.UnaryExpr: + x := conv.convertFilterExpr(e.X) + args := []ir.FilterExpr{x} + switch e.Op { + case token.NOT: + return ir.FilterExpr{Op: ir.FilterNotOp, Args: args} + } + + case *ast.BinaryExpr: + x := conv.convertFilterExpr(e.X) + y := conv.convertFilterExpr(e.Y) + args := []ir.FilterExpr{x, y} + switch e.Op { + case token.LAND: + return ir.FilterExpr{Op: ir.FilterAndOp, Args: args} + case token.LOR: + return ir.FilterExpr{Op: ir.FilterOrOp, Args: args} + case token.NEQ: + return ir.FilterExpr{Op: ir.FilterNeqOp, Args: args} + case token.EQL: + return ir.FilterExpr{Op: ir.FilterEqOp, Args: args} + case token.GTR: + return ir.FilterExpr{Op: ir.FilterGtOp, Args: args} + case token.LSS: + return ir.FilterExpr{Op: ir.FilterLtOp, Args: args} + case token.GEQ: + return ir.FilterExpr{Op: ir.FilterGtEqOp, Args: args} + case token.LEQ: + return ir.FilterExpr{Op: ir.FilterLtEqOp, Args: args} + default: + panic(conv.errorf(e, "unexpected binary op: %s", e.Op.String())) + } + + case *ast.SelectorExpr: + op := conv.inspectFilterSelector(e) + switch op.path { + case "Text": + return ir.FilterExpr{Op: ir.FilterVarTextOp, Value: op.varName} + case "Line": + return ir.FilterExpr{Op: ir.FilterVarLineOp, Value: op.varName} + case "Pure": + return ir.FilterExpr{Op: ir.FilterVarPureOp, Value: op.varName} + case "Const": + return ir.FilterExpr{Op: ir.FilterVarConstOp, Value: op.varName} + case "ConstSlice": + return ir.FilterExpr{Op: ir.FilterVarConstSliceOp, Value: op.varName} + case "Addressable": + return ir.FilterExpr{Op: ir.FilterVarAddressableOp, Value: op.varName} + case "Type.Size": + return ir.FilterExpr{Op: ir.FilterVarTypeSizeOp, Value: op.varName} + } + + case *ast.CallExpr: + op := conv.inspectFilterSelector(e) + switch op.path { + case "Deadcode": + return ir.FilterExpr{Op: ir.FilterDeadcodeOp} + case "GoVersion.Eq": + return ir.FilterExpr{Op: ir.FilterGoVersionEqOp, Value: conv.parseStringArg(e.Args[0])} + case "GoVersion.LessThan": + return ir.FilterExpr{Op: ir.FilterGoVersionLessThanOp, Value: conv.parseStringArg(e.Args[0])} + case "GoVersion.GreaterThan": + return ir.FilterExpr{Op: ir.FilterGoVersionGreaterThanOp, Value: conv.parseStringArg(e.Args[0])} + case "GoVersion.LessEqThan": + return ir.FilterExpr{Op: ir.FilterGoVersionLessEqThanOp, Value: conv.parseStringArg(e.Args[0])} + case "GoVersion.GreaterEqThan": + return ir.FilterExpr{Op: ir.FilterGoVersionGreaterEqThanOp, Value: conv.parseStringArg(e.Args[0])} + case "File.Imports": + return ir.FilterExpr{Op: ir.FilterFileImportsOp, Value: conv.parseStringArg(e.Args[0])} + case "File.PkgPath.Matches": + return ir.FilterExpr{Op: ir.FilterFilePkgPathMatchesOp, Value: conv.parseStringArg(e.Args[0])} + case "File.Name.Matches": + return ir.FilterExpr{Op: ir.FilterFileNameMatchesOp, Value: conv.parseStringArg(e.Args[0])} + + case "Filter": + funcName, ok := e.Args[0].(*ast.Ident) + if !ok { + panic(conv.errorf(e.Args[0], "only named function args are supported")) + } + args := []ir.FilterExpr{ + {Op: ir.FilterFilterFuncRefOp, Value: funcName.String()}, + } + return ir.FilterExpr{Op: ir.FilterVarFilterOp, Value: op.varName, Args: args} + } + + args := convertExprList(e.Args) + switch op.path { + case "Value.Int": + return ir.FilterExpr{Op: ir.FilterVarValueIntOp, Value: op.varName, Args: args} + case "Text.Matches": + return ir.FilterExpr{Op: ir.FilterVarTextMatchesOp, Value: op.varName, Args: args} + case "Node.Is": + return ir.FilterExpr{Op: ir.FilterVarNodeIsOp, Value: op.varName, Args: args} + case "Node.Parent.Is": + if op.varName != "$$" { + // TODO: remove this restriction. + panic(conv.errorf(e.Args[0], "only $$ parent nodes are implemented")) + } + return ir.FilterExpr{Op: ir.FilterRootNodeParentIsOp, Args: args} + case "Object.Is": + return ir.FilterExpr{Op: ir.FilterVarObjectIsOp, Value: op.varName, Args: args} + case "Type.Is": + return ir.FilterExpr{Op: ir.FilterVarTypeIsOp, Value: op.varName, Args: args} + case "Type.Underlying.Is": + return ir.FilterExpr{Op: ir.FilterVarTypeUnderlyingIsOp, Value: op.varName, Args: args} + case "Type.ConvertibleTo": + return ir.FilterExpr{Op: ir.FilterVarTypeConvertibleToOp, Value: op.varName, Args: args} + case "Type.AssignableTo": + return ir.FilterExpr{Op: ir.FilterVarTypeAssignableToOp, Value: op.varName, Args: args} + case "Type.Implements": + return ir.FilterExpr{Op: ir.FilterVarTypeImplementsOp, Value: op.varName, Args: args} + } + } + + return ir.FilterExpr{} +} + +func (conv *converter) parseStringArg(e ast.Expr) string { + s, ok := conv.toStringValue(e) + if !ok { + panic(conv.errorf(e, "expected a string literal argument")) + } + return s +} + +func (conv *converter) toStringValue(x ast.Node) (string, bool) { + switch x := x.(type) { + case *ast.BasicLit: + if x.Kind != token.STRING { + return "", false + } + s, err := strconv.Unquote(x.Value) + if err != nil { + return "", false + } + return s, true + case ast.Expr: + typ, ok := conv.types.Types[x] + if !ok || typ.Type.String() != "string" { + return "", false + } + str := constant.StringVal(typ.Value) + return str, true + } + return "", false +} + +func (conv *converter) inspectFilterSelector(e ast.Expr) filterExprSelector { + var o filterExprSelector + + if call, ok := e.(*ast.CallExpr); ok { + o.args = call.Args + e = call.Fun + } + var path string + for { + if call, ok := e.(*ast.CallExpr); ok { + e = call.Fun + continue + } + selector, ok := e.(*ast.SelectorExpr) + if !ok { + break + } + if path == "" { + path = selector.Sel.Name + } else { + path = selector.Sel.Name + "." + path + } + e = astutil.Unparen(selector.X) + } + + o.path = path + + indexing, ok := astutil.Unparen(e).(*ast.IndexExpr) + if !ok { + return o + } + mapIdent, ok := astutil.Unparen(indexing.X).(*ast.Ident) + if !ok { + return o + } + o.mapName = mapIdent.Name + indexString, _ := conv.toStringValue(indexing.Index) + o.varName = indexString + + return o +} + +type filterExprSelector struct { + mapName string + varName string + path string + args []ast.Expr +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go new file mode 100644 index 000000000..98bfb3999 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/nodepath.go @@ -0,0 +1,49 @@ +package ruleguard + +import ( + "fmt" + "go/ast" + "strings" +) + +type nodePath struct { + stack []ast.Node +} + +func newNodePath() nodePath { + return nodePath{stack: make([]ast.Node, 0, 32)} +} + +func (p nodePath) String() string { + parts := make([]string, len(p.stack)) + for i, n := range p.stack { + parts[i] = fmt.Sprintf("%T", n) + } + return strings.Join(parts, "/") +} + +func (p nodePath) Parent() ast.Node { + return p.NthParent(1) +} + +func (p nodePath) Current() ast.Node { + return p.NthParent(0) +} + +func (p nodePath) NthParent(n int) ast.Node { + index := len(p.stack) - n - 1 + if index >= 0 { + return p.stack[index] + } + return nil +} + +func (p *nodePath) Len() int { return len(p.stack) } + +func (p *nodePath) Push(n ast.Node) { + p.stack = append(p.stack, n) +} + +func (p *nodePath) Pop() { + p.stack = p.stack[:len(p.stack)-1] +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/parser.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/parser.go deleted file mode 100644 index 94826d497..000000000 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/parser.go +++ /dev/null @@ -1,988 +0,0 @@ -package ruleguard - -import ( - "bytes" - "errors" - "fmt" - "go/ast" - "go/parser" - "go/token" - "go/types" - "io" - "io/ioutil" - "path" - "regexp" - "strconv" - - "github.com/quasilyte/go-ruleguard/internal/gogrep" - "github.com/quasilyte/go-ruleguard/nodetag" - "github.com/quasilyte/go-ruleguard/ruleguard/goutil" - "github.com/quasilyte/go-ruleguard/ruleguard/quasigo" - "github.com/quasilyte/go-ruleguard/ruleguard/typematch" -) - -// TODO(quasilyte): use source code byte slicing instead of SprintNode? - -type parseError struct{ error } - -// ImportError is returned when a ruleguard file references a package that cannot be imported. -type ImportError struct { - msg string - err error -} - -func (e *ImportError) Error() string { return e.msg } -func (e *ImportError) Unwrap() error { return e.err } - -type rulesParser struct { - state *engineState - ctx *ParseContext - - prefix string // For imported packages, a prefix that is added to a rule group name - importedPkg string // Package path; only for imported packages - - filename string - group string - res *goRuleSet - pkg *types.Package - types *types.Info - - importer *goImporter - - itab *typematch.ImportsTab - - imported []*goRuleSet - - dslPkgname string // The local name of the "ruleguard/dsl" package (usually its just "dsl") -} - -type rulesParserConfig struct { - state *engineState - - ctx *ParseContext - - importer *goImporter - - prefix string - importedPkg string - - itab *typematch.ImportsTab -} - -func newRulesParser(config rulesParserConfig) *rulesParser { - return &rulesParser{ - state: config.state, - ctx: config.ctx, - importer: config.importer, - prefix: config.prefix, - importedPkg: config.importedPkg, - itab: config.itab, - } -} - -func (p *rulesParser) ParseFile(filename string, r io.Reader) (*goRuleSet, error) { - p.dslPkgname = "dsl" - p.filename = filename - p.res = &goRuleSet{ - universal: &scopedGoRuleSet{}, - groups: make(map[string]token.Position), - } - - parserFlags := parser.Mode(0) - f, err := parser.ParseFile(p.ctx.Fset, filename, r, parserFlags) - if err != nil { - return nil, fmt.Errorf("parse file error: %w", err) - } - - for _, imp := range f.Imports { - importPath, err := strconv.Unquote(imp.Path.Value) - if err != nil { - return nil, p.errorf(imp, fmt.Errorf("unquote %s import path: %w", imp.Path.Value, err)) - } - if importPath == "github.com/quasilyte/go-ruleguard/dsl" { - if imp.Name != nil { - p.dslPkgname = imp.Name.Name - } - } - } - - if f.Name.Name != "gorules" { - return nil, fmt.Errorf("expected a gorules package name, found %s", f.Name.Name) - } - - typechecker := types.Config{Importer: p.importer} - p.types = &types.Info{ - Types: map[ast.Expr]types.TypeAndValue{}, - Uses: map[*ast.Ident]types.Object{}, - Defs: map[*ast.Ident]types.Object{}, - } - pkg, err := typechecker.Check("gorules", p.ctx.Fset, []*ast.File{f}, p.types) - if err != nil { - return nil, fmt.Errorf("typechecker error: %w", err) - } - p.pkg = pkg - - var matcherFuncs []*ast.FuncDecl - var userFuncs []*ast.FuncDecl - for _, decl := range f.Decls { - decl, ok := decl.(*ast.FuncDecl) - if !ok { - continue - } - if decl.Name.String() == "init" { - if err := p.parseInitFunc(decl); err != nil { - return nil, err - } - continue - } - - if p.isMatcherFunc(decl) { - matcherFuncs = append(matcherFuncs, decl) - } else { - userFuncs = append(userFuncs, decl) - } - } - - for _, decl := range userFuncs { - if err := p.parseUserFunc(decl); err != nil { - return nil, err - } - } - for _, decl := range matcherFuncs { - if err := p.parseRuleGroup(decl); err != nil { - return nil, err - } - } - - if len(p.imported) != 0 { - toMerge := []*goRuleSet{p.res} - toMerge = append(toMerge, p.imported...) - merged, err := mergeRuleSets(toMerge) - if err != nil { - return nil, err - } - p.res = merged - } - - return p.res, nil -} - -func (p *rulesParser) parseUserFunc(f *ast.FuncDecl) error { - ctx := &quasigo.CompileContext{ - Env: p.state.env, - Types: p.types, - Fset: p.ctx.Fset, - } - compiled, err := quasigo.Compile(ctx, f) - if err != nil { - return err - } - if p.ctx.DebugFilter == f.Name.String() { - p.ctx.DebugPrint(quasigo.Disasm(p.state.env, compiled)) - } - ctx.Env.AddFunc(p.pkg.Path(), f.Name.String(), compiled) - return nil -} - -func (p *rulesParser) parseInitFunc(f *ast.FuncDecl) error { - type bundleImport struct { - node ast.Node - prefix string - pkgPath string - } - - var imported []bundleImport - - for _, stmt := range f.Body.List { - exprStmt, ok := stmt.(*ast.ExprStmt) - if !ok { - return p.errorf(stmt, errors.New("unsupported statement")) - } - call, ok := exprStmt.X.(*ast.CallExpr) - if !ok { - return p.errorf(stmt, errors.New("unsupported expr")) - } - fn, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - return p.errorf(stmt, errors.New("unsupported call")) - } - pkg, ok := fn.X.(*ast.Ident) - if !ok || pkg.Name != p.dslPkgname { - return p.errorf(stmt, errors.New("unsupported call")) - } - - switch fn.Sel.Name { - case "ImportRules": - if p.importedPkg != "" { - return p.errorf(call, errors.New("imports from imported packages are not supported yet")) - } - prefix := p.parseStringArg(call.Args[0]) - bundleSelector, ok := call.Args[1].(*ast.SelectorExpr) - if !ok { - return p.errorf(call.Args[1], errors.New("expected a `pkgname.Bundle` argument")) - } - bundleObj := p.types.ObjectOf(bundleSelector.Sel) - imported = append(imported, bundleImport{ - node: stmt, - prefix: prefix, - pkgPath: bundleObj.Pkg().Path(), - }) - - default: - return p.errorf(stmt, fmt.Errorf("unsupported %s call", fn.Sel.Name)) - } - } - - for _, imp := range imported { - files, err := findBundleFiles(imp.pkgPath) - if err != nil { - return p.errorf(imp.node, fmt.Errorf("import lookup error: %w", err)) - } - for _, filename := range files { - rset, err := p.importRules(imp.prefix, imp.pkgPath, filename) - if err != nil { - return p.errorf(imp.node, fmt.Errorf("import parsing error: %w", err)) - } - p.imported = append(p.imported, rset) - } - } - - return nil -} - -func (p *rulesParser) importRules(prefix, pkgPath, filename string) (*goRuleSet, error) { - data, err := ioutil.ReadFile(filename) - if err != nil { - return nil, err - } - config := rulesParserConfig{ - state: p.state, - ctx: p.ctx, - importer: p.importer, - prefix: prefix, - importedPkg: pkgPath, - itab: p.itab, - } - rset, err := newRulesParser(config).ParseFile(filename, bytes.NewReader(data)) - if err != nil { - return nil, fmt.Errorf("%s: %w", p.importedPkg, err) - } - return rset, nil -} - -func (p *rulesParser) isMatcherFunc(f *ast.FuncDecl) bool { - typ := p.types.ObjectOf(f.Name).Type().(*types.Signature) - return typ.Results().Len() == 0 && - typ.Params().Len() == 1 && - typ.Params().At(0).Type().String() == "github.com/quasilyte/go-ruleguard/dsl.Matcher" -} - -func (p *rulesParser) parseRuleGroup(f *ast.FuncDecl) (err error) { - defer func() { - if err != nil { - return - } - rv := recover() - if rv == nil { - return - } - if parseErr, ok := rv.(parseError); ok { - err = parseErr.error - return - } - panic(rv) // not our panic - }() - - if f.Name.String() == "_" { - return p.errorf(f.Name, errors.New("`_` is not a valid rule group function name")) - } - if f.Body == nil { - return p.errorf(f, errors.New("unexpected empty function body")) - } - params := f.Type.Params.List - matcher := params[0].Names[0].Name - - p.group = f.Name.Name - if p.prefix != "" { - p.group = p.prefix + "/" + f.Name.Name - } - - if p.ctx.GroupFilter != nil && !p.ctx.GroupFilter(p.group) { - return nil // Skip this group - } - if _, ok := p.res.groups[p.group]; ok { - panic(fmt.Sprintf("duplicated function %s after the typecheck", p.group)) // Should never happen - } - p.res.groups[p.group] = token.Position{ - Filename: p.filename, - Line: p.ctx.Fset.Position(f.Name.Pos()).Line, - } - - p.itab.EnterScope() - defer p.itab.LeaveScope() - - for _, stmt := range f.Body.List { - if _, ok := stmt.(*ast.DeclStmt); ok { - continue - } - stmtExpr, ok := stmt.(*ast.ExprStmt) - if !ok { - return p.errorf(stmt, fmt.Errorf("expected a %s method call, found %s", matcher, goutil.SprintNode(p.ctx.Fset, stmt))) - } - call, ok := stmtExpr.X.(*ast.CallExpr) - if !ok { - return p.errorf(stmt, fmt.Errorf("expected a %s method call, found %s", matcher, goutil.SprintNode(p.ctx.Fset, stmt))) - } - if err := p.parseCall(matcher, call); err != nil { - return err - } - - } - - return nil -} - -func (p *rulesParser) parseCall(matcher string, call *ast.CallExpr) error { - f := call.Fun.(*ast.SelectorExpr) - x, ok := f.X.(*ast.Ident) - if ok && x.Name == matcher { - return p.parseStmt(f.Sel, call.Args) - } - - return p.parseRule(matcher, call) -} - -func (p *rulesParser) parseStmt(fn *ast.Ident, args []ast.Expr) error { - switch fn.Name { - case "Import": - pkgPath, ok := p.toStringValue(args[0]) - if !ok { - return p.errorf(args[0], errors.New("expected a string literal argument")) - } - pkgName := path.Base(pkgPath) - p.itab.Load(pkgName, pkgPath) - return nil - default: - return p.errorf(fn, fmt.Errorf("unexpected %s method", fn.Name)) - } -} - -func (p *rulesParser) parseRule(matcher string, call *ast.CallExpr) error { - origCall := call - var ( - matchArgs *[]ast.Expr - matchCommentArgs *[]ast.Expr - whereArgs *[]ast.Expr - suggestArgs *[]ast.Expr - reportArgs *[]ast.Expr - atArgs *[]ast.Expr - ) - for { - chain, ok := call.Fun.(*ast.SelectorExpr) - if !ok { - break - } - switch chain.Sel.Name { - case "Match": - if matchArgs != nil { - return p.errorf(chain.Sel, errors.New("Match() can't be repeated")) - } - if matchCommentArgs != nil { - return p.errorf(chain.Sel, errors.New("Match() and MatchComment() can't be combined")) - } - matchArgs = &call.Args - case "MatchComment": - if matchCommentArgs != nil { - return p.errorf(chain.Sel, errors.New("MatchComment() can't be repeated")) - } - if matchArgs != nil { - return p.errorf(chain.Sel, errors.New("Match() and MatchComment() can't be combined")) - } - matchCommentArgs = &call.Args - case "Where": - if whereArgs != nil { - return p.errorf(chain.Sel, errors.New("Where() can't be repeated")) - } - whereArgs = &call.Args - case "Suggest": - if suggestArgs != nil { - return p.errorf(chain.Sel, errors.New("Suggest() can't be repeated")) - } - suggestArgs = &call.Args - case "Report": - if reportArgs != nil { - return p.errorf(chain.Sel, errors.New("Report() can't be repeated")) - } - reportArgs = &call.Args - case "At": - if atArgs != nil { - return p.errorf(chain.Sel, errors.New("At() can't be repeated")) - } - atArgs = &call.Args - default: - return p.errorf(chain.Sel, fmt.Errorf("unexpected %s method", chain.Sel.Name)) - } - call, ok = chain.X.(*ast.CallExpr) - if !ok { - break - } - } - - proto := goRule{ - filename: p.filename, - line: p.ctx.Fset.Position(origCall.Pos()).Line, - group: p.group, - } - - // AST patterns for Match() or regexp patterns for MatchComment(). - var alternatives []string - - if matchArgs == nil && matchCommentArgs == nil { - return p.errorf(origCall, errors.New("missing Match() or MatchComment() call")) - } - - if matchArgs != nil { - for _, arg := range *matchArgs { - alternatives = append(alternatives, p.parseStringArg(arg)) - } - } else { - for _, arg := range *matchCommentArgs { - alternatives = append(alternatives, p.parseStringArg(arg)) - } - } - - if whereArgs != nil { - proto.filter = p.parseFilter((*whereArgs)[0]) - } - - if suggestArgs != nil { - proto.suggestion = p.parseStringArg((*suggestArgs)[0]) - } - - if reportArgs == nil { - if suggestArgs == nil { - return p.errorf(origCall, errors.New("missing Report() or Suggest() call")) - } - proto.msg = "suggestion: " + proto.suggestion - } else { - proto.msg = p.parseStringArg((*reportArgs)[0]) - } - - if atArgs != nil { - index, ok := (*atArgs)[0].(*ast.IndexExpr) - if !ok { - return p.errorf((*atArgs)[0], fmt.Errorf("expected %s[`varname`] expression", matcher)) - } - arg, ok := p.toStringValue(index.Index) - if !ok { - return p.errorf(index.Index, errors.New("expected a string literal index")) - } - proto.location = arg - } - - if matchArgs != nil { - return p.loadGogrepRules(proto, *matchArgs, alternatives) - } - return p.loadCommentRules(proto, *matchCommentArgs, alternatives) -} - -func (p *rulesParser) loadCommentRules(proto goRule, matchArgs []ast.Expr, alternatives []string) error { - dst := p.res.universal - for i, alt := range alternatives { - pat, err := regexp.Compile(alt) - if err != nil { - return p.errorf(matchArgs[i], fmt.Errorf("parse match comment pattern: %w", err)) - } - rule := goCommentRule{ - base: proto, - pat: pat, - captureGroups: regexpHasCaptureGroups(alt), - } - dst.commentRules = append(dst.commentRules, rule) - } - - return nil -} - -func (p *rulesParser) loadGogrepRules(proto goRule, matchArgs []ast.Expr, alternatives []string) error { - dst := p.res.universal - for i, alt := range alternatives { - rule := proto - pat, err := gogrep.Compile(p.ctx.Fset, alt, false) - if err != nil { - return p.errorf(matchArgs[i], fmt.Errorf("parse match pattern: %w", err)) - } - rule.pat = pat - var dstTags []nodetag.Value - switch tag := pat.NodeTag(); tag { - case nodetag.Unknown: - return p.errorf(matchArgs[i], fmt.Errorf("can't infer a tag of %s", alt)) - case nodetag.Node: - // TODO: add to every bucket? - return p.errorf(matchArgs[i], fmt.Errorf("%s is too general", alt)) - case nodetag.StmtList: - dstTags = []nodetag.Value{ - nodetag.BlockStmt, - nodetag.CaseClause, - nodetag.CommClause, - } - case nodetag.ExprList: - dstTags = []nodetag.Value{ - nodetag.CallExpr, - nodetag.CompositeLit, - nodetag.ReturnStmt, - } - default: - dstTags = []nodetag.Value{tag} - } - for _, tag := range dstTags { - dst.rulesByTag[tag] = append(dst.rulesByTag[tag], rule) - } - dst.categorizedNum++ - } - - return nil -} - -func (p *rulesParser) parseFilter(root ast.Expr) matchFilter { - return p.parseFilterExpr(root) -} - -func (p *rulesParser) errorf(n ast.Node, err error) parseError { - loc := p.ctx.Fset.Position(n.Pos()) - return parseError{fmt.Errorf("%s:%d: %w", loc.Filename, loc.Line, err)} -} - -func (p *rulesParser) parseStringArg(e ast.Expr) string { - s, ok := p.toStringValue(e) - if !ok { - panic(p.errorf(e, errors.New("expected a string literal argument"))) - } - return s -} - -func (p *rulesParser) parseRegexpArg(e ast.Expr) *regexp.Regexp { - patternString, ok := p.toStringValue(e) - if !ok { - panic(p.errorf(e, errors.New("expected a regexp pattern argument"))) - } - re, err := regexp.Compile(patternString) - if err != nil { - panic(p.errorf(e, err)) - } - return re -} - -func (p *rulesParser) parseTypeStringArg(e ast.Expr) types.Type { - typeString, ok := p.toStringValue(e) - if !ok { - panic(p.errorf(e, errors.New("expected a type string argument"))) - } - typ, err := typeFromString(typeString) - if err != nil { - panic(p.errorf(e, fmt.Errorf("parse type expr: %w", err))) - } - if typ == nil { - panic(p.errorf(e, fmt.Errorf("can't convert %s into a type constraint yet", typeString))) - } - return typ -} - -func (p *rulesParser) parseFilterExpr(e ast.Expr) matchFilter { - result := matchFilter{src: goutil.SprintNode(p.ctx.Fset, e)} - - switch e := e.(type) { - case *ast.ParenExpr: - return p.parseFilterExpr(e.X) - - case *ast.UnaryExpr: - x := p.parseFilterExpr(e.X) - if e.Op == token.NOT { - result.fn = makeNotFilter(result.src, x) - return result - } - panic(p.errorf(e, fmt.Errorf("unsupported unary op: %s", result.src))) - - case *ast.BinaryExpr: - switch e.Op { - case token.LAND: - result.fn = makeAndFilter(p.parseFilterExpr(e.X), p.parseFilterExpr(e.Y)) - return result - case token.LOR: - result.fn = makeOrFilter(p.parseFilterExpr(e.X), p.parseFilterExpr(e.Y)) - return result - case token.GEQ, token.LEQ, token.LSS, token.GTR, token.EQL, token.NEQ: - operand := p.toFilterOperand(e.X) - rhs := p.toFilterOperand(e.Y) - rhsValue := p.types.Types[e.Y].Value - if operand.path == "Type.Size" && rhsValue != nil { - result.fn = makeTypeSizeConstFilter(result.src, operand.varName, e.Op, rhsValue) - return result - } - if operand.path == "Value.Int" && rhsValue != nil { - result.fn = makeValueIntConstFilter(result.src, operand.varName, e.Op, rhsValue) - return result - } - if operand.path == "Value.Int" && rhs.path == "Value.Int" && rhs.varName != "" { - result.fn = makeValueIntFilter(result.src, operand.varName, e.Op, rhs.varName) - return result - } - if operand.path == "Text" && rhsValue != nil { - result.fn = makeTextConstFilter(result.src, operand.varName, e.Op, rhsValue) - return result - } - if operand.path == "Text" && rhs.path == "Text" && rhs.varName != "" { - result.fn = makeTextFilter(result.src, operand.varName, e.Op, rhs.varName) - return result - } - } - panic(p.errorf(e, fmt.Errorf("unsupported binary op: %s", result.src))) - } - - operand := p.toFilterOperand(e) - args := operand.args - switch operand.path { - default: - panic(p.errorf(e, fmt.Errorf("unsupported expr: %s", result.src))) - - case "File.Imports": - pkgPath := p.parseStringArg(args[0]) - result.fn = makeFileImportsFilter(result.src, pkgPath) - - case "File.PkgPath.Matches": - re := p.parseRegexpArg(args[0]) - result.fn = makeFilePkgPathMatchesFilter(result.src, re) - - case "File.Name.Matches": - re := p.parseRegexpArg(args[0]) - result.fn = makeFileNameMatchesFilter(result.src, re) - - case "Pure": - result.fn = makePureFilter(result.src, operand.varName) - - case "Const": - result.fn = makeConstFilter(result.src, operand.varName) - - case "Addressable": - result.fn = makeAddressableFilter(result.src, operand.varName) - - case "Filter": - expr, fn := goutil.ResolveFunc(p.types, args[0]) - if expr != nil { - panic(p.errorf(expr, errors.New("expected a simple function name, found expression"))) - } - sig := fn.Type().(*types.Signature) - userFn := p.state.env.GetFunc(fn.Pkg().Path(), fn.Name()) - if userFn == nil { - panic(p.errorf(args[0], fmt.Errorf("can't find a compiled version of %s", sig.String()))) - } - result.fn = makeCustomVarFilter(result.src, operand.varName, userFn) - - case "Type.Is", "Type.Underlying.Is": - // TODO(quasilyte): add FQN support? - typeString, ok := p.toStringValue(args[0]) - if !ok { - panic(p.errorf(args[0], errors.New("expected a string literal argument"))) - } - ctx := typematch.Context{Itab: p.itab} - pat, err := typematch.Parse(&ctx, typeString) - if err != nil { - panic(p.errorf(args[0], fmt.Errorf("parse type expr: %w", err))) - } - underlying := operand.path == "Type.Underlying.Is" - result.fn = makeTypeIsFilter(result.src, operand.varName, underlying, pat) - - case "Type.ConvertibleTo": - dstType := p.parseTypeStringArg(args[0]) - result.fn = makeTypeConvertibleToFilter(result.src, operand.varName, dstType) - - case "Type.AssignableTo": - dstType := p.parseTypeStringArg(args[0]) - result.fn = makeTypeAssignableToFilter(result.src, operand.varName, dstType) - - case "Type.Implements": - iface := p.toInterfaceValue(args[0]) - result.fn = makeTypeImplementsFilter(result.src, operand.varName, iface) - - case "Text.Matches": - re := p.parseRegexpArg(args[0]) - result.fn = makeTextMatchesFilter(result.src, operand.varName, re) - - case "Node.Is": - typeString, ok := p.toStringValue(args[0]) - if !ok { - panic(p.errorf(args[0], errors.New("expected a string literal argument"))) - } - tag := nodetag.FromString(typeString) - if tag == nodetag.Unknown { - panic(p.errorf(args[0], fmt.Errorf("%s is not a valid go/ast type name", typeString))) - } - result.fn = makeNodeIsFilter(result.src, operand.varName, tag) - } - - if result.fn == nil { - panic("bug: nil func for the filter") // Should never happen - } - return result -} - -func (p *rulesParser) toInterfaceValue(x ast.Node) *types.Interface { - typeString, ok := p.toStringValue(x) - if !ok { - panic(p.errorf(x, errors.New("expected a string literal argument"))) - } - - typ, err := p.state.FindType(p.importer, p.pkg, typeString) - if err == nil { - iface, ok := typ.Underlying().(*types.Interface) - if !ok { - panic(p.errorf(x, fmt.Errorf("%s is not an interface type", typeString))) - } - return iface - } - - n, err := parser.ParseExpr(typeString) - if err != nil { - panic(p.errorf(x, fmt.Errorf("parse type expr: %w", err))) - } - qn, ok := n.(*ast.SelectorExpr) - if !ok { - panic(p.errorf(x, fmt.Errorf("can't resolve %s type; try a fully-qualified name", typeString))) - } - pkgName, ok := qn.X.(*ast.Ident) - if !ok { - panic(p.errorf(qn.X, errors.New("invalid package name"))) - } - pkgPath, ok := p.itab.Lookup(pkgName.Name) - if !ok { - panic(p.errorf(qn.X, fmt.Errorf("package %s is not imported", pkgName.Name))) - } - pkg, err := p.importer.Import(pkgPath) - if err != nil { - panic(p.errorf(n, &ImportError{msg: fmt.Sprintf("can't load %s", pkgPath), err: err})) - } - obj := pkg.Scope().Lookup(qn.Sel.Name) - if obj == nil { - panic(p.errorf(n, fmt.Errorf("%s is not found in %s", qn.Sel.Name, pkgPath))) - } - iface, ok := obj.Type().Underlying().(*types.Interface) - if !ok { - panic(p.errorf(n, fmt.Errorf("%s is not an interface type", qn.Sel.Name))) - } - return iface -} - -func (p *rulesParser) toStringValue(x ast.Node) (string, bool) { - switch x := x.(type) { - case *ast.BasicLit: - if x.Kind != token.STRING { - return "", false - } - s, err := strconv.Unquote(x.Value) - if err != nil { - return "", false - } - return s, true - case ast.Expr: - typ, ok := p.types.Types[x] - if !ok || typ.Type.String() != "string" { - return "", false - } - str := typ.Value.ExactString() - str = str[1 : len(str)-1] // remove quotes - return str, true - } - return "", false -} - -func (p *rulesParser) toFilterOperand(e ast.Expr) filterOperand { - var o filterOperand - - if call, ok := e.(*ast.CallExpr); ok { - o.args = call.Args - e = call.Fun - } - var path string - for { - if call, ok := e.(*ast.CallExpr); ok { - e = call.Fun - continue - } - selector, ok := e.(*ast.SelectorExpr) - if !ok { - break - } - if path == "" { - path = selector.Sel.Name - } else { - path = selector.Sel.Name + "." + path - } - e = selector.X - } - - o.path = path - - indexing, ok := e.(*ast.IndexExpr) - if !ok { - return o - } - mapIdent, ok := indexing.X.(*ast.Ident) - if !ok { - return o - } - o.mapName = mapIdent.Name - indexString, _ := p.toStringValue(indexing.Index) - o.varName = indexString - - return o -} - -type filterOperand struct { - mapName string - varName string - path string - args []ast.Expr -} - -var stdlibPackages = map[string]string{ - "adler32": "hash/adler32", - "aes": "crypto/aes", - "ascii85": "encoding/ascii85", - "asn1": "encoding/asn1", - "ast": "go/ast", - "atomic": "sync/atomic", - "base32": "encoding/base32", - "base64": "encoding/base64", - "big": "math/big", - "binary": "encoding/binary", - "bits": "math/bits", - "bufio": "bufio", - "build": "go/build", - "bytes": "bytes", - "bzip2": "compress/bzip2", - "cgi": "net/http/cgi", - "cgo": "runtime/cgo", - "cipher": "crypto/cipher", - "cmplx": "math/cmplx", - "color": "image/color", - "constant": "go/constant", - "context": "context", - "cookiejar": "net/http/cookiejar", - "crc32": "hash/crc32", - "crc64": "hash/crc64", - "crypto": "crypto", - "csv": "encoding/csv", - "debug": "runtime/debug", - "des": "crypto/des", - "doc": "go/doc", - "draw": "image/draw", - "driver": "database/sql/driver", - "dsa": "crypto/dsa", - "dwarf": "debug/dwarf", - "ecdsa": "crypto/ecdsa", - "ed25519": "crypto/ed25519", - "elf": "debug/elf", - "elliptic": "crypto/elliptic", - "encoding": "encoding", - "errors": "errors", - "exec": "os/exec", - "expvar": "expvar", - "fcgi": "net/http/fcgi", - "filepath": "path/filepath", - "flag": "flag", - "flate": "compress/flate", - "fmt": "fmt", - "fnv": "hash/fnv", - "format": "go/format", - "gif": "image/gif", - "gob": "encoding/gob", - "gosym": "debug/gosym", - "gzip": "compress/gzip", - "hash": "hash", - "heap": "container/heap", - "hex": "encoding/hex", - "hmac": "crypto/hmac", - "html": "html", - "http": "net/http", - "httptest": "net/http/httptest", - "httptrace": "net/http/httptrace", - "httputil": "net/http/httputil", - "image": "image", - "importer": "go/importer", - "io": "io", - "iotest": "testing/iotest", - "ioutil": "io/ioutil", - "jpeg": "image/jpeg", - "json": "encoding/json", - "jsonrpc": "net/rpc/jsonrpc", - "list": "container/list", - "log": "log", - "lzw": "compress/lzw", - "macho": "debug/macho", - "mail": "net/mail", - "math": "math", - "md5": "crypto/md5", - "mime": "mime", - "multipart": "mime/multipart", - "net": "net", - "os": "os", - "palette": "image/color/palette", - "parse": "text/template/parse", - "parser": "go/parser", - "path": "path", - "pe": "debug/pe", - "pem": "encoding/pem", - "pkix": "crypto/x509/pkix", - "plan9obj": "debug/plan9obj", - "plugin": "plugin", - "png": "image/png", - "pprof": "runtime/pprof", - "printer": "go/printer", - "quick": "testing/quick", - "quotedprintable": "mime/quotedprintable", - "race": "runtime/race", - "rand": "math/rand", - "rc4": "crypto/rc4", - "reflect": "reflect", - "regexp": "regexp", - "ring": "container/ring", - "rpc": "net/rpc", - "rsa": "crypto/rsa", - "runtime": "runtime", - "scanner": "text/scanner", - "sha1": "crypto/sha1", - "sha256": "crypto/sha256", - "sha512": "crypto/sha512", - "signal": "os/signal", - "smtp": "net/smtp", - "sort": "sort", - "sql": "database/sql", - "strconv": "strconv", - "strings": "strings", - "subtle": "crypto/subtle", - "suffixarray": "index/suffixarray", - "sync": "sync", - "syntax": "regexp/syntax", - "syscall": "syscall", - "syslog": "log/syslog", - "tabwriter": "text/tabwriter", - "tar": "archive/tar", - "template": "text/template", - "testing": "testing", - "textproto": "net/textproto", - "time": "time", - "tls": "crypto/tls", - "token": "go/token", - "trace": "runtime/trace", - "types": "go/types", - "unicode": "unicode", - "unsafe": "unsafe", - "url": "net/url", - "user": "os/user", - "utf16": "unicode/utf16", - "utf8": "unicode/utf8", - "x509": "crypto/x509", - "xml": "encoding/xml", - "zip": "archive/zip", - "zlib": "compress/zlib", -} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go index ba23861a2..7e0f40f3f 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/ruleguard.go @@ -2,9 +2,12 @@ package ruleguard import ( "go/ast" + "go/build" "go/token" "go/types" "io" + + "github.com/quasilyte/go-ruleguard/ruleguard/ir" ) // Engine is the main ruleguard package API object. @@ -18,6 +21,17 @@ import ( // An Engine must be created with NewEngine() function. type Engine struct { impl *engine + + // BuildContext can be used as an override for build.Default context. + // Used during the Go packages resolving. + // + // Use Engine.InferBuildContext() to create a sensible default + // for this field that is better than build.Default. + // We're not using this by default to avoid the excessive work + // if you already have a properly initialized build.Context object. + // + // nil will result in build.Default usage. + BuildContext *build.Context } // NewEngine creates an engine with empty rule set. @@ -25,13 +39,30 @@ func NewEngine() *Engine { return &Engine{impl: newEngine()} } +func (e *Engine) InferBuildContext() { + e.BuildContext = inferBuildContext() +} + // Load reads a ruleguard file from r and adds it to the engine rule set. // // Load() is not thread-safe, especially if used concurrently with Run() method. // It's advised to Load() all ruleguard files under a critical section (like sync.Once) // and then use Run() to execute all of them. -func (e *Engine) Load(ctx *ParseContext, filename string, r io.Reader) error { - return e.impl.Load(ctx, filename, r) +func (e *Engine) Load(ctx *LoadContext, filename string, r io.Reader) error { + return e.impl.Load(ctx, e.BuildContext, filename, r) +} + +// LoadFromIR is like Load(), but it takes already parsed IR file as an input. +// +// This method can be useful if you're trying to embed a precompiled rules file +// into your binary. +func (e *Engine) LoadFromIR(ctx *LoadContext, filename string, f *ir.File) error { + return e.impl.LoadFromIR(ctx, e.BuildContext, filename, f) +} + +// LoadedGroups returns information about all currently loaded rule groups. +func (e *Engine) LoadedGroups() []GoRuleGroup { + return e.impl.LoadedGroups() } // Run executes all loaded rules on a given file. @@ -40,10 +71,10 @@ func (e *Engine) Load(ctx *ParseContext, filename string, r io.Reader) error { // Run() is thread-safe, unless used in parallel with Load(), // which modifies the engine state. func (e *Engine) Run(ctx *RunContext, f *ast.File) error { - return e.impl.Run(ctx, f) + return e.impl.Run(ctx, e.BuildContext, f) } -type ParseContext struct { +type LoadContext struct { DebugFilter string DebugImports bool DebugPrint func(string) @@ -67,6 +98,8 @@ type RunContext struct { Fset *token.FileSet Report func(rule GoRuleInfo, n ast.Node, msg string, s *Suggestion) Pkg *types.Package + + GoVersion GoVersion } type Suggestion struct { @@ -76,12 +109,54 @@ type Suggestion struct { } type GoRuleInfo struct { - // Filename is a file that defined this rule. - Filename string - // Line is a line inside a file that defined this rule. Line int - // Group is a function name that contained this rule. - Group string + // Group is a function that contains this rule. + Group *GoRuleGroup } + +type GoRuleGroup struct { + // Name is a function name associated with this rule group. + Name string + + // Pos is a location where this rule group was defined. + Pos token.Position + + // Line is a source code line number inside associated file. + // A pair of Filename:Line form a conventional location string. + Line int + + // Filename is a file that defined this rule group. + Filename string + + // DocTags contains a list of keys from the `gorules:tags` comment. + DocTags []string + + // DocSummary is a short one sentence description. + // Filled from the `doc:summary` pragma content. + DocSummary string + + // DocBefore is a code snippet of code that will violate rule. + // Filled from the `doc:before` pragma content. + DocBefore string + + // DocAfter is a code snippet of fixed code that complies to the rule. + // Filled from the `doc:after` pragma content. + DocAfter string + + // DocNote is an optional caution message or advice. + // Usually, it's used to reference some external resource, like + // issue on the GitHub. + // Filled from the `doc:note` pragma content. + DocNote string +} + +// ImportError is returned when a ruleguard file references a package that cannot be imported. +type ImportError struct { + msg string + err error +} + +func (e *ImportError) Error() string { return e.msg } +func (e *ImportError) Unwrap() error { return e.err } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go index a5d254411..09cbd4060 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/runner.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "go/ast" + "go/build" "go/printer" "io/ioutil" "path/filepath" @@ -22,24 +23,46 @@ type rulesRunner struct { ctx *RunContext rules *goRuleSet + gogrepState gogrep.MatcherState + importer *goImporter filename string src []byte + // nodePath is a stack of ast.Nodes we visited to this point. + // When we enter a new node, it's placed on the top of the stack. + // When we leave that node, it's popped. + // The stack is a slice that is allocated only once and reused + // for the lifetime of the runner. + // The only overhead it has is a slice append and pop operations + // that are quire cheap. + // + // Note: we need this path to get a Node.Parent() for `$$` matches. + // So it's used to climb up the tree there. + // For named submatches we can't use it as the node can be located + // deeper into the tree than the current node. + // In those cases we need a more complicated algorithm. + nodePath nodePath + filterParams filterParams } -func newRulesRunner(ctx *RunContext, state *engineState, rules *goRuleSet) *rulesRunner { +func newRulesRunner(ctx *RunContext, buildContext *build.Context, state *engineState, rules *goRuleSet) *rulesRunner { importer := newGoImporter(state, goImporterConfig{ fset: ctx.Fset, debugImports: ctx.DebugImports, debugPrint: ctx.DebugPrint, + buildContext: buildContext, }) + gogrepState := gogrep.NewMatcherState() + gogrepState.Types = ctx.Types rr := &rulesRunner{ - ctx: ctx, - importer: importer, - rules: rules, + ctx: ctx, + importer: importer, + rules: rules, + gogrepState: gogrepState, + nodePath: newNodePath(), filterParams: filterParams{ env: state.env.GetEvalEnv(), importer: importer, @@ -47,6 +70,7 @@ func newRulesRunner(ctx *RunContext, state *engineState, rules *goRuleSet) *rule }, } rr.filterParams.nodeText = rr.nodeText + rr.filterParams.nodePath = &rr.nodePath return rr } @@ -93,19 +117,22 @@ func (rr *rulesRunner) fileBytes() []byte { } func (rr *rulesRunner) run(f *ast.File) error { - // TODO(quasilyte): run local rules as well. + // If it's not empty then we're leaking memory. + // For every Push() there should be a Pop() call. + if rr.nodePath.Len() != 0 { + panic("internal error: node path is not empty") + } rr.filename = rr.ctx.Fset.Position(f.Pos()).Filename rr.filterParams.filename = rr.filename rr.collectImports(f) if rr.rules.universal.categorizedNum != 0 { - ast.Inspect(f, func(n ast.Node) bool { - if n == nil { - return false - } + var inspector astWalker + inspector.nodePath = &rr.nodePath + inspector.filterParams = &rr.filterParams + inspector.Walk(f, func(n ast.Node) { rr.runRules(n) - return true }) } @@ -183,7 +210,7 @@ func (rr *rulesRunner) runRules(n ast.Node) { tag := nodetag.FromNode(n) for _, rule := range rr.rules.universal.rulesByTag[tag] { matched := false - rule.pat.MatchNode(n, func(m gogrep.MatchData) { + rule.pat.MatchNode(&rr.gogrepState, n, func(m gogrep.MatchData) { matched = rr.handleMatch(rule, m) }) if matched { @@ -193,13 +220,13 @@ func (rr *rulesRunner) runRules(n ast.Node) { } func (rr *rulesRunner) reject(rule goRule, reason string, m matchData) { - if rule.group != rr.ctx.Debug { + if rule.group.Name != rr.ctx.Debug { return // This rule is not being debugged } pos := rr.ctx.Fset.Position(m.Node().Pos()) rr.ctx.DebugPrint(fmt.Sprintf("%s:%d: [%s:%d] rejected by %s", - pos.Filename, pos.Line, filepath.Base(rule.filename), rule.line, reason)) + pos.Filename, pos.Line, filepath.Base(rule.group.Filename), rule.line, reason)) values := make([]gogrep.CapturedNode, len(m.CaptureList())) copy(values, m.CaptureList()) @@ -261,9 +288,8 @@ func (rr *rulesRunner) handleCommentMatch(rule goCommentRule, m commentMatchData } } info := GoRuleInfo{ - Group: rule.base.group, - Filename: rule.base.filename, - Line: rule.base.line, + Group: rule.base.group, + Line: rule.base.line, } rr.ctx.Report(info, node, message, suggestion) return true @@ -293,9 +319,8 @@ func (rr *rulesRunner) handleMatch(rule goRule, m gogrep.MatchData) bool { } } info := GoRuleInfo{ - Group: rule.group, - Filename: rule.filename, - Line: rule.line, + Group: rule.group, + Line: rule.line, } rr.ctx.Report(info, node, message, suggestion) return true diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go new file mode 100644 index 000000000..d320bf880 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/compile.go @@ -0,0 +1,84 @@ +package textmatch + +import ( + "regexp" + "regexp/syntax" + "unicode" +) + +func compile(s string) (Pattern, error) { + reSyntax, err := syntax.Parse(s, syntax.Perl) + if err == nil { + if optimized := compileOptimized(s, reSyntax); optimized != nil { + return optimized, nil + } + } + return regexp.Compile(s) +} + +func compileOptimized(s string, re *syntax.Regexp) Pattern { + // .* + isAny := func(re *syntax.Regexp) bool { + return re.Op == syntax.OpStar && re.Sub[0].Op == syntax.OpAnyCharNotNL + } + // "literal" + isLit := func(re *syntax.Regexp) bool { + return re.Op == syntax.OpLiteral + } + // ^ + isBegin := func(re *syntax.Regexp) bool { + return re.Op == syntax.OpBeginText + } + // $ + isEnd := func(re *syntax.Regexp) bool { + return re.Op == syntax.OpEndText + } + + // TODO: analyze what kind of regexps people use in rules + // more often and optimize those as well. + + // lit => strings.Contains($input, lit) + if re.Op == syntax.OpLiteral { + return &containsLiteralMatcher{value: newInputValue(string(re.Rune))} + } + + // `.*` lit `.*` => strings.Contains($input, lit) + if re.Op == syntax.OpConcat && len(re.Sub) == 3 { + if isAny(re.Sub[0]) && isLit(re.Sub[1]) && isAny(re.Sub[2]) { + return &containsLiteralMatcher{value: newInputValue(string(re.Sub[1].Rune))} + } + } + + // `^` lit => strings.HasPrefix($input, lit) + if re.Op == syntax.OpConcat && len(re.Sub) == 2 { + if isBegin(re.Sub[0]) && isLit(re.Sub[1]) { + return &prefixLiteralMatcher{value: newInputValue(string(re.Sub[1].Rune))} + } + } + + // lit `$` => strings.HasSuffix($input, lit) + if re.Op == syntax.OpConcat && len(re.Sub) == 2 { + if isLit(re.Sub[0]) && isEnd(re.Sub[1]) { + return &suffixLiteralMatcher{value: newInputValue(string(re.Sub[0].Rune))} + } + } + + // `^` lit `$` => $input == lit + if re.Op == syntax.OpConcat && len(re.Sub) == 3 { + if isBegin(re.Sub[0]) && isLit(re.Sub[1]) && isEnd(re.Sub[2]) { + return &eqLiteralMatcher{value: newInputValue(string(re.Sub[1].Rune))} + } + } + + // `^\p{Lu}` => prefixRunePredMatcher:unicode.IsUpper + // `^\p{Ll}` => prefixRunePredMatcher:unicode.IsLower + switch s { + case `^\p{Lu}`: + return &prefixRunePredMatcher{pred: unicode.IsUpper} + case `^\p{Ll}`: + return &prefixRunePredMatcher{pred: unicode.IsLower} + } + + // Can't optimize. + return nil +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go new file mode 100644 index 000000000..2f68c9aee --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/matchers.go @@ -0,0 +1,72 @@ +package textmatch + +import ( + "bytes" + "strings" + "unicode/utf8" +) + +// inputValue is a wrapper for string|[]byte. +// +// We hold both values to avoid string->[]byte and vice versa +// conversions when doing Match and MatchString. +type inputValue struct { + s string + b []byte +} + +func newInputValue(s string) inputValue { + return inputValue{s: s, b: []byte(s)} +} + +type containsLiteralMatcher struct{ value inputValue } + +func (m *containsLiteralMatcher) MatchString(s string) bool { + return strings.Contains(s, m.value.s) +} + +func (m *containsLiteralMatcher) Match(b []byte) bool { + return bytes.Contains(b, m.value.b) +} + +type prefixLiteralMatcher struct{ value inputValue } + +func (m *prefixLiteralMatcher) MatchString(s string) bool { + return strings.HasPrefix(s, m.value.s) +} + +func (m *prefixLiteralMatcher) Match(b []byte) bool { + return bytes.HasPrefix(b, m.value.b) +} + +type suffixLiteralMatcher struct{ value inputValue } + +func (m *suffixLiteralMatcher) MatchString(s string) bool { + return strings.HasSuffix(s, m.value.s) +} + +func (m *suffixLiteralMatcher) Match(b []byte) bool { + return bytes.HasSuffix(b, m.value.b) +} + +type eqLiteralMatcher struct{ value inputValue } + +func (m *eqLiteralMatcher) MatchString(s string) bool { + return m.value.s == s +} + +func (m *eqLiteralMatcher) Match(b []byte) bool { + return bytes.Equal(m.value.b, b) +} + +type prefixRunePredMatcher struct{ pred func(rune) bool } + +func (m *prefixRunePredMatcher) MatchString(s string) bool { + r, _ := utf8.DecodeRuneInString(s) + return m.pred(r) +} + +func (m *prefixRunePredMatcher) Match(b []byte) bool { + r, _ := utf8.DecodeRune(b) + return m.pred(r) +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go new file mode 100644 index 000000000..a3787e2c1 --- /dev/null +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/textmatch/textmatch.go @@ -0,0 +1,26 @@ +package textmatch + +import "regexp" + +// Pattern is a compiled regular expression. +type Pattern interface { + MatchString(s string) bool + Match(b []byte) bool +} + +// Compile parses a regular expression and returns a compiled +// pattern that can match inputs descriped by the regexp. +// +// Semantically it's close to the regexp.Compile, but +// it does recognize some common patterns and creates +// a more optimized matcher for them. +func Compile(re string) (Pattern, error) { + return compile(re) +} + +// IsRegexp reports whether p is implemented using regexp. +// False means that the underlying matcher is something optimized. +func IsRegexp(p Pattern) bool { + _, ok := p.(*regexp.Regexp) + return ok +} diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go index 1d739819d..a909e3e8c 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/patternop_string.go @@ -19,12 +19,13 @@ func _() { _ = x[opFunc-8] _ = x[opStructNoSeq-9] _ = x[opStruct-10] - _ = x[opNamed-11] + _ = x[opAnyInterface-11] + _ = x[opNamed-12] } -const _patternOp_name = "opBuiltinTypeopPointeropVaropVarSeqopSliceopArrayopMapopChanopFuncopStructNoSeqopStructopNamed" +const _patternOp_name = "opBuiltinTypeopPointeropVaropVarSeqopSliceopArrayopMapopChanopFuncopStructNoSeqopStructopAnyInterfaceopNamed" -var _patternOp_index = [...]uint8{0, 13, 22, 27, 35, 42, 49, 54, 60, 66, 79, 87, 94} +var _patternOp_index = [...]uint8{0, 13, 22, 27, 35, 42, 49, 54, 60, 66, 79, 87, 101, 108} func (i patternOp) String() string { if i < 0 || i >= patternOp(len(_patternOp_index)-1) { diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go index 19391ecd4..4749106ec 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/typematch/typematch.go @@ -27,6 +27,7 @@ const ( opFunc opStructNoSeq opStruct + opAnyInterface opNamed ) @@ -313,6 +314,16 @@ func parseExpr(ctx *Context, e ast.Expr) *pattern { if len(e.Methods.List) == 0 { return &pattern{op: opBuiltinType, value: efaceType} } + if len(e.Methods.List) == 1 { + p := parseExpr(ctx, e.Methods.List[0].Type) + if p == nil { + return nil + } + if p.op != opVarSeq { + return nil + } + return &pattern{op: opAnyInterface} + } } return nil @@ -525,6 +536,10 @@ func (p *Pattern) matchIdentical(sub *pattern, typ types.Type) bool { } return true + case opAnyInterface: + _, ok := typ.(*types.Interface) + return ok + default: return false } diff --git a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go index de3bb04c3..4e8adc85f 100644 --- a/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go +++ b/vendor/github.com/quasilyte/go-ruleguard/ruleguard/utils.go @@ -179,7 +179,7 @@ func isPure(info *types.Info, expr ast.Expr) bool { case *ast.UnaryExpr: return expr.Op != token.ARROW && isPure(info, expr.X) - case *ast.BasicLit, *ast.Ident: + case *ast.BasicLit, *ast.Ident, *ast.FuncLit: return true case *ast.IndexExpr: return isPure(info, expr.X) && @@ -220,6 +220,37 @@ func isConstant(info *types.Info, expr ast.Expr) bool { return ok && tv.Value != nil } +func isConstantSlice(info *types.Info, expr ast.Expr) bool { + switch expr := expr.(type) { + case *ast.CallExpr: + // Matches []byte("string"). + if len(expr.Args) != 1 { + return false + } + lit, ok := expr.Args[0].(*ast.BasicLit) + if !ok || lit.Kind != token.STRING { + return false + } + typ, ok := info.TypeOf(expr.Fun).(*types.Slice) + if !ok { + return false + } + basicType, ok := typ.Elem().(*types.Basic) + return ok && basicType.Kind() == types.Uint8 + + case *ast.CompositeLit: + for _, elt := range expr.Elts { + if !isConstant(info, elt) { + return false + } + } + return true + + default: + return false + } +} + // isTypeExpr reports whether x represents a type expression. // // Type expression does not evaluate to any run time value, @@ -249,3 +280,16 @@ func isTypeExpr(info *types.Info, x ast.Expr) bool { return false } } + +func identOf(e ast.Expr) *ast.Ident { + switch e := e.(type) { + case *ast.ParenExpr: + return identOf(e.X) + case *ast.Ident: + return e + case *ast.SelectorExpr: + return e.Sel + default: + return nil + } +} diff --git a/vendor/github.com/securego/gosec/v2/.gitignore b/vendor/github.com/securego/gosec/v2/.gitignore index f282cda24..f6c8065b4 100644 --- a/vendor/github.com/securego/gosec/v2/.gitignore +++ b/vendor/github.com/securego/gosec/v2/.gitignore @@ -33,3 +33,7 @@ _testmain.go .DS_Store .vscode +.idea + +# SBOMs generated during CI +/bom.json diff --git a/vendor/github.com/securego/gosec/v2/.golangci.yml b/vendor/github.com/securego/gosec/v2/.golangci.yml index dcda64666..64e4e4515 100644 --- a/vendor/github.com/securego/gosec/v2/.golangci.yml +++ b/vendor/github.com/securego/gosec/v2/.golangci.yml @@ -2,22 +2,32 @@ linters: enable: - asciicheck - bodyclose + - deadcode - depguard - dogsled - durationcheck - errcheck + - errorlint - exportloopref + - gci - gofmt - gofumpt - goimports - gosec + - gosimple - govet - importas + - ineffassign - megacheck - misspell - nakedret - nolintlint - revive + - staticcheck + - structcheck + - typecheck - unconvert - unparam - - wastedassign \ No newline at end of file + - unused + - varcheck + - wastedassign diff --git a/vendor/github.com/securego/gosec/v2/.goreleaser.yml b/vendor/github.com/securego/gosec/v2/.goreleaser.yml index 263e522bc..300f4b452 100644 --- a/vendor/github.com/securego/gosec/v2/.goreleaser.yml +++ b/vendor/github.com/securego/gosec/v2/.goreleaser.yml @@ -2,6 +2,8 @@ project_name: gosec release: + extra_files: + - glob: ./bom.json github: owner: securego name: gosec diff --git a/vendor/github.com/securego/gosec/v2/Makefile b/vendor/github.com/securego/gosec/v2/Makefile index 5974e5c08..e28818c64 100644 --- a/vendor/github.com/securego/gosec/v2/Makefile +++ b/vendor/github.com/securego/gosec/v2/Makefile @@ -2,7 +2,8 @@ GIT_TAG?= $(shell git describe --always --tags) BIN = gosec FMT_CMD = $(gofmt -s -l -w $(find . -type f -name '*.go' -not -path './vendor/*') | tee /dev/stderr) IMAGE_REPO = securego -BUILDFLAGS := '-w -s' +BUILD_DATE ?= $(shell date +%Y-%m-%d) +BUILDFLAGS := "-w -s -X 'main.Version=$(GIT_TAG)' -X 'main.GitTag=$(GIT_TAG)' -X 'main.BuildDate=$(BUILD_DATE)'" CGO_ENABLED = 0 GO := GO111MODULE=on go GO_NOMOD :=GO111MODULE=off go @@ -55,7 +56,7 @@ release: goreleaser release build-linux: - CGO_ENABLED=$(CGO_ENABLED) GOOS=linux GOARCH=amd64 go build -ldflags $(BUILDFLAGS) -o $(BIN) ./cmd/gosec/ + CGO_ENABLED=$(CGO_ENABLED) GOOS=linux GOARCH=amd64 go build -ldflags=$(BUILDFLAGS) -o $(BIN) ./cmd/gosec/ image: @echo "Building the Docker image..." diff --git a/vendor/github.com/securego/gosec/v2/README.md b/vendor/github.com/securego/gosec/v2/README.md index e69e41684..e6c969b22 100644 --- a/vendor/github.com/securego/gosec/v2/README.md +++ b/vendor/github.com/securego/gosec/v2/README.md @@ -113,6 +113,14 @@ jobs: ### Local Installation +#### Go 1.16+ + +```bash +go install github.com/securego/gosec/v2/cmd/gosec@latest +``` + +#### Go version < 1.16 + ```bash go get -u github.com/securego/gosec/v2/cmd/gosec ``` @@ -205,7 +213,7 @@ of functions which will be skipped when auditing the not checked errors: ```JSON { "G104": { - "io/ioutil": ["WriteFile"] + "ioutil": ["WriteFile"] } } ``` @@ -236,7 +244,6 @@ gosec will ignore test files across all packages and any dependencies in your ve The scanning of test files can be enabled with the following flag: ```bash - gosec -tests ./... ``` @@ -246,6 +253,19 @@ Also additional folders can be excluded as follows: gosec -exclude-dir=rules -exclude-dir=cmd ./... ``` +### Excluding generated files + +gosec can ignore generated go files with default generated code comment. + +``` +// Code generated by some generator DO NOT EDIT. +``` + +```bash +gosec -exclude-generated ./... +``` + + ### Annotating code As with all automated detection tools, there will be cases of false positives. In cases where gosec reports a failure that has been manually verified as being safe, @@ -288,7 +308,7 @@ gosec is able to pass your [Go build tags](https://golang.org/pkg/go/build/) to They can be provided as a comma separated list as follows: ```bash -gosec -tag debug,ignore ./... +gosec -tags debug,ignore ./... ``` ### Output formats diff --git a/vendor/github.com/securego/gosec/v2/USERS.md b/vendor/github.com/securego/gosec/v2/USERS.md index 73369ceec..ffc056081 100644 --- a/vendor/github.com/securego/gosec/v2/USERS.md +++ b/vendor/github.com/securego/gosec/v2/USERS.md @@ -14,6 +14,7 @@ This is a list of gosec's users. Please send a pull request with your organisati 8. [1Password](https://github.com/1Password/srp) 9. [PingCAP/tidb](https://github.com/pingcap/tidb) 10. [Checkmarx](https://www.checkmarx.com/) +11. [SeatGeek](https://www.seatgeek.com/) ## Projects diff --git a/vendor/github.com/securego/gosec/v2/analyzer.go b/vendor/github.com/securego/gosec/v2/analyzer.go index f669d5ae0..a2951683e 100644 --- a/vendor/github.com/securego/gosec/v2/analyzer.go +++ b/vendor/github.com/securego/gosec/v2/analyzer.go @@ -43,6 +43,8 @@ const LoadMode = packages.NeedName | packages.NeedTypesInfo | packages.NeedSyntax +var generatedCodePattern = regexp.MustCompile(`^// Code generated .* DO NOT EDIT\.$`) + // The Context is populated with data parsed from the source code as it is scanned. // It is passed through to all rule functions as they are called. Rules may use // this data in conjunction withe the encountered AST node. @@ -70,36 +72,44 @@ type Metrics struct { // Analyzer object is the main object of gosec. It has methods traverse an AST // and invoke the correct checking rules as on each node as required. type Analyzer struct { - ignoreNosec bool - ruleset RuleSet - context *Context - config Config - logger *log.Logger - issues []*Issue - stats *Metrics - errors map[string][]Error // keys are file paths; values are the golang errors in those files - tests bool + ignoreNosec bool + ruleset RuleSet + context *Context + config Config + logger *log.Logger + issues []*Issue + stats *Metrics + errors map[string][]Error // keys are file paths; values are the golang errors in those files + tests bool + excludeGenerated bool + showIgnored bool } // NewAnalyzer builds a new analyzer. -func NewAnalyzer(conf Config, tests bool, logger *log.Logger) *Analyzer { +func NewAnalyzer(conf Config, tests bool, excludeGenerated bool, logger *log.Logger) *Analyzer { ignoreNoSec := false if enabled, err := conf.IsGlobalEnabled(Nosec); err == nil { ignoreNoSec = enabled } + showIgnored := false + if enabled, err := conf.IsGlobalEnabled(ShowIgnored); err == nil { + showIgnored = enabled + } if logger == nil { logger = log.New(os.Stderr, "[gosec]", log.LstdFlags) } return &Analyzer{ - ignoreNosec: ignoreNoSec, - ruleset: make(RuleSet), - context: &Context{}, - config: conf, - logger: logger, - issues: make([]*Issue, 0, 16), - stats: &Metrics{}, - errors: make(map[string][]Error), - tests: tests, + ignoreNosec: ignoreNoSec, + showIgnored: showIgnored, + ruleset: make(RuleSet), + context: &Context{}, + config: conf, + logger: logger, + issues: make([]*Issue, 0, 16), + stats: &Metrics{}, + errors: make(map[string][]Error), + tests: tests, + excludeGenerated: excludeGenerated, } } @@ -139,7 +149,7 @@ func (gosec *Analyzer) Process(buildTags []string, packagePaths ...string) error if pkg.Name != "" { err := gosec.ParseErrors(pkg) if err != nil { - return fmt.Errorf("parsing errors in pkg %q: %v", pkg.Name, err) + return fmt.Errorf("parsing errors in pkg %q: %w", pkg.Name, err) } gosec.Check(pkg) } @@ -163,7 +173,7 @@ func (gosec *Analyzer) load(pkgPath string, conf *packages.Config) ([]*packages. buildD.BuildTags = conf.BuildFlags basePackage, err := buildD.ImportDir(pkgPath, build.ImportComment) if err != nil { - return []*packages.Package{}, fmt.Errorf("importing dir %q: %v", pkgPath, err) + return []*packages.Package{}, fmt.Errorf("importing dir %q: %w", pkgPath, err) } var packageFiles []string @@ -175,7 +185,7 @@ func (gosec *Analyzer) load(pkgPath string, conf *packages.Config) ([]*packages. } if gosec.tests { - testsFiles := []string{} + testsFiles := make([]string, 0) testsFiles = append(testsFiles, basePackage.TestGoFiles...) testsFiles = append(testsFiles, basePackage.XTestGoFiles...) for _, filename := range testsFiles { @@ -187,7 +197,7 @@ func (gosec *Analyzer) load(pkgPath string, conf *packages.Config) ([]*packages. conf.BuildFlags = nil pkgs, err := packages.Load(conf, packageFiles...) if err != nil { - return []*packages.Package{}, fmt.Errorf("loading files from package %q: %v", pkgPath, err) + return []*packages.Package{}, fmt.Errorf("loading files from package %q: %w", pkgPath, err) } return pkgs, nil } @@ -202,6 +212,11 @@ func (gosec *Analyzer) Check(pkg *packages.Package) { if filepath.Ext(checkedFile) != ".go" { continue } + if gosec.excludeGenerated && isGeneratedFile(file) { + gosec.logger.Println("Ignoring generated file:", checkedFile) + continue + } + gosec.logger.Println("Checking file:", checkedFile) gosec.context.FileSet = pkg.Fset gosec.context.Config = gosec.config @@ -219,6 +234,17 @@ func (gosec *Analyzer) Check(pkg *packages.Package) { } } +func isGeneratedFile(file *ast.File) bool { + for _, comment := range file.Comments { + for _, row := range comment.List { + if generatedCodePattern.MatchString(row.Text) { + return true + } + } + } + return false +} + // ParseErrors parses the errors from given package func (gosec *Analyzer) ParseErrors(pkg *packages.Package) error { if len(pkg.Errors) == 0 { @@ -231,13 +257,13 @@ func (gosec *Analyzer) ParseErrors(pkg *packages.Package) error { var line int if len(parts) > 1 { if line, err = strconv.Atoi(parts[1]); err != nil { - return fmt.Errorf("parsing line: %v", err) + return fmt.Errorf("parsing line: %w", err) } } var column int if len(parts) > 2 { if column, err = strconv.Atoi(parts[2]); err != nil { - return fmt.Errorf("parsing column: %v", err) + return fmt.Errorf("parsing column: %w", err) } } msg := strings.TrimSpace(pkgErr.Msg) @@ -259,7 +285,7 @@ func (gosec *Analyzer) AppendError(file string, err error) { if r.MatchString(err.Error()) { return } - errors := []Error{} + errors := make([]Error, 0) if ferrs, ok := gosec.errors[file]; ok { errors = ferrs } @@ -344,9 +370,8 @@ func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor { gosec.context.Imports.TrackImport(n) for _, rule := range gosec.ruleset.RegisteredFor(n) { - if _, ok := ignores[rule.ID()]; ok { - continue - } + _, ignored := ignores[rule.ID()] + issue, err := rule.Match(n, gosec.context) if err != nil { file, line := GetLocation(n, gosec.context) @@ -354,8 +379,15 @@ func (gosec *Analyzer) Visit(n ast.Node) ast.Visitor { gosec.logger.Printf("Rule error: %v => %s (%s:%d)\n", reflect.TypeOf(rule), err, file, line) } if issue != nil { - gosec.issues = append(gosec.issues, issue) - gosec.stats.NumFound++ + if gosec.showIgnored { + issue.NoSec = ignored + } + if !ignored || !gosec.showIgnored { + gosec.stats.NumFound++ + } + if !ignored || gosec.showIgnored || gosec.ignoreNosec { + gosec.issues = append(gosec.issues, issue) + } } } return gosec diff --git a/vendor/github.com/securego/gosec/v2/config.go b/vendor/github.com/securego/gosec/v2/config.go index 4af62b295..fe60b2f6d 100644 --- a/vendor/github.com/securego/gosec/v2/config.go +++ b/vendor/github.com/securego/gosec/v2/config.go @@ -20,6 +20,8 @@ type GlobalOption string const ( // Nosec global option for #nosec directive Nosec GlobalOption = "nosec" + // ShowIgnored defines whether nosec issues are counted as finding or not + ShowIgnored GlobalOption = "show-ignored" // Audit global option which indicates that gosec runs in audit mode Audit GlobalOption = "audit" // NoSecAlternative global option alternative for #nosec directive diff --git a/vendor/github.com/securego/gosec/v2/entrypoint.sh b/vendor/github.com/securego/gosec/v2/entrypoint.sh index 4dc046729..af2acd4b9 100644 --- a/vendor/github.com/securego/gosec/v2/entrypoint.sh +++ b/vendor/github.com/securego/gosec/v2/entrypoint.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Expand the arguments into an array of strings. This is requires because the GitHub action +# Expand the arguments into an array of strings. This is required because the GitHub action # provides all arguments concatenated as a single string. ARGS=("$@") diff --git a/vendor/github.com/securego/gosec/v2/go.mod b/vendor/github.com/securego/gosec/v2/go.mod index 1d08b1c74..c324841c4 100644 --- a/vendor/github.com/securego/gosec/v2/go.mod +++ b/vendor/github.com/securego/gosec/v2/go.mod @@ -1,17 +1,17 @@ module github.com/securego/gosec/v2 require ( - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/gookit/color v1.4.2 - github.com/lib/pq v1.10.2 + github.com/lib/pq v1.10.3 github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5 github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 github.com/onsi/ginkgo v1.16.4 - github.com/onsi/gomega v1.13.0 - golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a + github.com/onsi/gomega v1.16.0 + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 - golang.org/x/text v0.3.6 - golang.org/x/tools v0.1.3 + golang.org/x/text v0.3.7 + golang.org/x/tools v0.1.7 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/vendor/github.com/securego/gosec/v2/go.sum b/vendor/github.com/securego/gosec/v2/go.sum index bdf02fb39..8d81d7161 100644 --- a/vendor/github.com/securego/gosec/v2/go.sum +++ b/vendor/github.com/securego/gosec/v2/go.sum @@ -162,8 +162,8 @@ github.com/google/trillian v1.3.11/go.mod h1:0tPraVHrSDkA3BO6vKX67zgLXs6SsOAbHEi github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 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/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= @@ -219,8 +219,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+ github.com/letsencrypt/pkcs11key/v4 v4.0.0/go.mod h1:EFUvBDay26dErnNb70Nd0/VW3tJiIbETBPTl9ATXQag= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= -github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -264,13 +264,12 @@ github.com/olekukonko/tablewriter v0.0.2/go.mod h1:rSAaSIOAGT9odnlyGlUfAJaoc5w2f github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= +github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -344,7 +343,7 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= go.etcd.io/etcd v0.0.0-20200513171258-e048e166ab9c/go.mod h1:xCI7ZzBfRuGgBXyXO6yfWfDmlWd35khcWpUa4L0xI/k= @@ -372,8 +371,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U 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-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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= @@ -444,9 +443,9 @@ golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/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-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -510,8 +509,9 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210112080510-489259a85091/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 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -520,8 +520,9 @@ 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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 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= @@ -574,8 +575,8 @@ golang.org/x/tools v0.0.0-20200626171337-aa94e735be7f/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200630154851-b2d8b0336632/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200706234117-b22de6825cf7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.3 h1:L69ShwSZEyCsLKoAxDKeMvLDZkumEe8gXUZAjab0tX8= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= 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= diff --git a/vendor/github.com/securego/gosec/v2/helpers.go b/vendor/github.com/securego/gosec/v2/helpers.go index 50ce19859..e5f2218ef 100644 --- a/vendor/github.com/securego/gosec/v2/helpers.go +++ b/vendor/github.com/securego/gosec/v2/helpers.go @@ -402,7 +402,7 @@ func PackagePaths(root string, excludes []*regexp.Regexp) ([]string, error) { err := filepath.Walk(root, func(path string, f os.FileInfo, err error) error { if filepath.Ext(path) == ".go" { path = filepath.Dir(path) - if isExcluded(path, excludes) { + if isExcluded(filepath.ToSlash(path), excludes) { return nil } paths[path] = true @@ -437,7 +437,7 @@ func isExcluded(str string, excludes []*regexp.Regexp) bool { func ExcludedDirsRegExp(excludedDirs []string) []*regexp.Regexp { var exps []*regexp.Regexp for _, excludedDir := range excludedDirs { - str := fmt.Sprintf(`([\\/])?%s([\\/])?`, excludedDir) + str := fmt.Sprintf(`([\\/])?%s([\\/])?`, strings.ReplaceAll(filepath.ToSlash(excludedDir), "/", `\/`)) r := regexp.MustCompile(str) exps = append(exps, r) } diff --git a/vendor/github.com/securego/gosec/v2/issue.go b/vendor/github.com/securego/gosec/v2/issue.go index d5091fe97..00b193765 100644 --- a/vendor/github.com/securego/gosec/v2/issue.go +++ b/vendor/github.com/securego/gosec/v2/issue.go @@ -97,6 +97,7 @@ type Issue struct { Code string `json:"code"` // Impacted code line Line string `json:"line"` // Line number in file Col string `json:"column"` // Column number in line + NoSec bool `json:"nosec"` // true if the issue is nosec } // FileLocation point out the file path and line number in file diff --git a/vendor/github.com/securego/gosec/v2/renovate.json b/vendor/github.com/securego/gosec/v2/renovate.json index 95f2b7c1c..58ee1e0ea 100644 --- a/vendor/github.com/securego/gosec/v2/renovate.json +++ b/vendor/github.com/securego/gosec/v2/renovate.json @@ -1,5 +1,6 @@ { "dependencyDashboard": true, + "dependencyDashboardTitle" : "Renovate(bot) : dependency dashboard", "vulnerabilityAlerts": { "enabled": true }, diff --git a/vendor/github.com/securego/gosec/v2/rules/bad_defer.go b/vendor/github.com/securego/gosec/v2/rules/bad_defer.go index 13b42070d..f6ca0be81 100644 --- a/vendor/github.com/securego/gosec/v2/rules/bad_defer.go +++ b/vendor/github.com/securego/gosec/v2/rules/bad_defer.go @@ -38,10 +38,11 @@ func contains(methods []string, method string) bool { func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { if deferStmt, ok := n.(*ast.DeferStmt); ok { for _, deferTyp := range r.types { - if typ, method, err := gosec.GetCallInfo(deferStmt.Call, c); err == nil { - if normalize(typ) == deferTyp.typ && contains(deferTyp.methods, method) { - return gosec.NewIssue(c, n, r.ID(), fmt.Sprintf(r.What, method, typ), r.Severity, r.Confidence), nil - } + if issue := r.checkChild(n, c, deferStmt.Call, deferTyp); issue != nil { + return issue, nil + } + if issue := r.checkFunction(n, c, deferStmt, deferTyp); issue != nil { + return issue, nil } } } @@ -49,6 +50,42 @@ func (r *badDefer) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { return nil, nil } +func (r *badDefer) checkChild(n ast.Node, c *gosec.Context, callExp *ast.CallExpr, deferTyp deferType) *gosec.Issue { + if typ, method, err := gosec.GetCallInfo(callExp, c); err == nil { + if normalize(typ) == deferTyp.typ && contains(deferTyp.methods, method) { + return gosec.NewIssue(c, n, r.ID(), fmt.Sprintf(r.What, method, typ), r.Severity, r.Confidence) + } + } + return nil +} + +func (r *badDefer) checkFunction(n ast.Node, c *gosec.Context, deferStmt *ast.DeferStmt, deferTyp deferType) *gosec.Issue { + if anonFunc, isAnonFunc := deferStmt.Call.Fun.(*ast.FuncLit); isAnonFunc { + for _, subElem := range anonFunc.Body.List { + if issue := r.checkStmt(n, c, subElem, deferTyp); issue != nil { + return issue + } + } + } + return nil +} + +func (r *badDefer) checkStmt(n ast.Node, c *gosec.Context, subElem ast.Stmt, deferTyp deferType) *gosec.Issue { + switch stmt := subElem.(type) { + case *ast.AssignStmt: + for _, rh := range stmt.Rhs { + if e, isCallExp := rh.(*ast.CallExpr); isCallExp { + return r.checkChild(n, c, e, deferTyp) + } + } + case *ast.IfStmt: + if s, is := stmt.Init.(*ast.AssignStmt); is { + return r.checkStmt(n, c, s, deferTyp) + } + } + return nil +} + // NewDeferredClosing detects unsafe defer of error returning methods func NewDeferredClosing(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { return &badDefer{ diff --git a/vendor/github.com/securego/gosec/v2/rules/errors.go b/vendor/github.com/securego/gosec/v2/rules/errors.go index 7a34bc634..f3360ec69 100644 --- a/vendor/github.com/securego/gosec/v2/rules/errors.go +++ b/vendor/github.com/securego/gosec/v2/rules/errors.go @@ -87,6 +87,7 @@ func NewNoErrorCheck(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { whitelist.AddAll("strings.Builder", "Write", "WriteByte", "WriteRune", "WriteString") whitelist.Add("io.PipeWriter", "CloseWithError") whitelist.Add("hash.Hash", "Write") + whitelist.Add("os", "Unsetenv") if configured, ok := conf["G104"]; ok { if whitelisted, ok := configured.(map[string]interface{}); ok { diff --git a/vendor/github.com/securego/gosec/v2/rules/fileperms.go b/vendor/github.com/securego/gosec/v2/rules/fileperms.go index e6a80a5fb..93265dd38 100644 --- a/vendor/github.com/securego/gosec/v2/rules/fileperms.go +++ b/vendor/github.com/securego/gosec/v2/rules/fileperms.go @@ -64,7 +64,7 @@ func (r *filePermissions) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, err // NewWritePerms creates a rule to detect file Writes with bad permissions. func NewWritePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { - mode := getConfiguredMode(conf, "G306", 0600) + mode := getConfiguredMode(conf, "G306", 0o600) return &filePermissions{ mode: mode, pkgs: []string{"io/ioutil", "os"}, @@ -81,7 +81,7 @@ func NewWritePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { // NewFilePerms creates a rule to detect file creation with a more permissive than configured // permission mask. func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { - mode := getConfiguredMode(conf, "G302", 0600) + mode := getConfiguredMode(conf, "G302", 0o600) return &filePermissions{ mode: mode, pkgs: []string{"os"}, @@ -98,7 +98,7 @@ func NewFilePerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { // NewMkdirPerms creates a rule to detect directory creation with more permissive than // configured permission mask. func NewMkdirPerms(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { - mode := getConfiguredMode(conf, "G301", 0750) + mode := getConfiguredMode(conf, "G301", 0o750) return &filePermissions{ mode: mode, pkgs: []string{"os"}, diff --git a/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go b/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go index acdd583e4..791bb5dcd 100644 --- a/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go +++ b/vendor/github.com/securego/gosec/v2/rules/hardcoded_credentials.go @@ -117,7 +117,7 @@ func (r *credentials) matchEqualityCheck(binaryExpr *ast.BinaryExpr, ctx *gosec. // NewHardcodedCredentials attempts to find high entropy string constants being // assigned to variables that appear to be related to credentials. func NewHardcodedCredentials(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { - pattern := `(?i)passwd|pass|password|pwd|secret|token` + pattern := `(?i)passwd|pass|password|pwd|secret|token|pw|apiKey|bearer|cred` entropyThreshold := 80.0 perCharThreshold := 3.0 ignoreEntropy := false diff --git a/vendor/github.com/securego/gosec/v2/rules/readfile.go b/vendor/github.com/securego/gosec/v2/rules/readfile.go index 072b016e2..a4ccb720c 100644 --- a/vendor/github.com/securego/gosec/v2/rules/readfile.go +++ b/vendor/github.com/securego/gosec/v2/rules/readfile.go @@ -122,6 +122,7 @@ func NewReadFile(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { rule.clean.Add("path/filepath", "Clean") rule.clean.Add("path/filepath", "Rel") rule.Add("io/ioutil", "ReadFile") + rule.Add("os", "ReadFile") rule.Add("os", "Open") rule.Add("os", "OpenFile") return rule, []ast.Node{(*ast.CallExpr)(nil)} diff --git a/vendor/github.com/securego/gosec/v2/rules/subproc.go b/vendor/github.com/securego/gosec/v2/rules/subproc.go index 48a07269f..53f8eb854 100644 --- a/vendor/github.com/securego/gosec/v2/rules/subproc.go +++ b/vendor/github.com/securego/gosec/v2/rules/subproc.go @@ -48,12 +48,36 @@ func (r *subprocess) Match(n ast.Node, c *gosec.Context) (*gosec.Issue, error) { for _, arg := range args { if ident, ok := arg.(*ast.Ident); ok { obj := c.Info.ObjectOf(ident) - if _, ok := obj.(*types.Var); ok && !gosec.TryResolve(ident, c) { - return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil + + // need to cast and check whether it is for a variable ? + _, variable := obj.(*types.Var) + + // .. indeed it is a variable then processing is different than a normal + // field assignment + if variable { + switch ident.Obj.Decl.(type) { + case *ast.AssignStmt: + _, assignment := ident.Obj.Decl.(*ast.AssignStmt) + if variable && assignment { + if !gosec.TryResolve(ident, c) { + return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil + } + } + case *ast.Field: + _, field := ident.Obj.Decl.(*ast.Field) + if variable && field { + // check if the variable exist in the scope + vv, vvok := obj.(*types.Var) + + if vvok && vv.Parent().Lookup(ident.Name) == nil { + return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with variable", gosec.Medium, gosec.High), nil + } + } + } } } else if !gosec.TryResolve(arg, c) { // the arg is not a constant or a variable but instead a function call or os.Args[i] - return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with function call as argument or cmd arguments", gosec.Medium, gosec.High), nil + return gosec.NewIssue(c, n, r.ID(), "Subprocess launched with a potential tainted input or cmd arguments", gosec.Medium, gosec.High), nil } } } @@ -81,5 +105,7 @@ func NewSubproc(id string, conf gosec.Config) (gosec.Rule, []ast.Node) { rule.Add("syscall", "Exec") rule.Add("syscall", "ForkExec") rule.Add("syscall", "StartProcess") + rule.Add("golang.org/x/sys/execabs", "Command") + rule.Add("golang.org/x/sys/execabs", "CommandContext") return rule, []ast.Node{(*ast.CallExpr)(nil)} } diff --git a/vendor/github.com/securego/gosec/v2/rules/tls.go b/vendor/github.com/securego/gosec/v2/rules/tls.go index 219d8fcde..486b56e3c 100644 --- a/vendor/github.com/securego/gosec/v2/rules/tls.go +++ b/vendor/github.com/securego/gosec/v2/rules/tls.go @@ -20,6 +20,8 @@ import ( "crypto/tls" "fmt" "go/ast" + "go/types" + "strconv" "github.com/securego/gosec/v2" ) @@ -85,7 +87,29 @@ func (t *insecureConfigTLS) processTLSConfVal(n *ast.KeyValueExpr, c *gosec.Cont } case "MinVersion": - if ival, ierr := gosec.GetInt(n.Value); ierr == nil { + if d, ok := n.Value.(*ast.Ident); ok { + if vs, ok := d.Obj.Decl.(*ast.ValueSpec); ok { + if s, ok := vs.Values[0].(*ast.SelectorExpr); ok { + x := s.X.(*ast.Ident).Name + sel := s.Sel.Name + + for _, imp := range c.Pkg.Imports() { + if imp.Name() == x { + tObj := imp.Scope().Lookup(sel) + if cst, ok := tObj.(*types.Const); ok { + // ..got the value check if this can be translated + if minVersion, err := strconv.ParseInt(cst.Val().String(), 10, 64); err == nil { + t.actualMinVersion = minVersion + } + } + } + } + } + if ival, ierr := gosec.GetInt(vs.Values[0]); ierr == nil { + t.actualMinVersion = ival + } + } + } else if ival, ierr := gosec.GetInt(n.Value); ierr == nil { t.actualMinVersion = ival } else { if se, ok := n.Value.(*ast.SelectorExpr); ok { diff --git a/vendor/github.com/sivchari/tenv/.gitignore b/vendor/github.com/sivchari/tenv/.gitignore new file mode 100644 index 000000000..66fd13c90 --- /dev/null +++ b/vendor/github.com/sivchari/tenv/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/sivchari/tenv/.golangci.yml b/vendor/github.com/sivchari/tenv/.golangci.yml new file mode 100644 index 000000000..f687df836 --- /dev/null +++ b/vendor/github.com/sivchari/tenv/.golangci.yml @@ -0,0 +1,38 @@ +run: + timeout: 5m + skip-files: [] + +linters-settings: + govet: + enable-all: true + disable: + - fieldalignment + gocyclo: + min-complexity: 12 + misspell: + locale: US + godox: + keywords: + - FIXME + gofumpt: + extra-rules: true + +linters: + disable-all: true + enable: + - govet + - revive + - goimports + - staticcheck + - gosimple + - unused + - godox + - gofumpt + - misspell + - gocyclo + +issues: + exclude-use-default: true + max-per-linter: 0 + max-same-issues: 0 + exclude: [] diff --git a/vendor/github.com/sivchari/tenv/LICENSE b/vendor/github.com/sivchari/tenv/LICENSE new file mode 100644 index 000000000..5185ec09a --- /dev/null +++ b/vendor/github.com/sivchari/tenv/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 sivchari + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/sivchari/tenv/README.md b/vendor/github.com/sivchari/tenv/README.md new file mode 100644 index 000000000..120408940 --- /dev/null +++ b/vendor/github.com/sivchari/tenv/README.md @@ -0,0 +1,112 @@ +# tenv +tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17 + +[![test_and_lint](https://github.com/sivchari/tenv/actions/workflows/workflows.yml/badge.svg?branch=main)](https://github.com/sivchari/tenv/actions/workflows/workflows.yml) + +## Instruction + +```sh +go install github.com/sivchari/tenv/cmd/tenv +``` + +## Usage + +```go +package sandbox_test + +import ( + "os" + "testing" +) + +var ( + e = os.Setenv("a", "b") + _ = e +) + +func setup() { + os.Setenv("a", "b") + err := os.Setenv("a", "b") + if err != nil { + _ = err + } +} + +func TestF(t *testing.T) { + setup() + os.Setenv("a", "b") + if err := os.Setenv("a", "b"); err != nil { + _ = err + } +} +``` + +### fish + +```console +go vet -vettool=(which tenv) sandbox_test.go + +# command-line-arguments +./sandbox_test.go:9:2: variable e is not using t.Setenv +./sandbox_test.go:14:2: func setup is not using t.Setenv +./sandbox_test.go:15:2: func setup is not using t.Setenv +./sandbox_test.go:23:2: func TestF is not using t.Setenv +./sandbox_test.go:24:2: func TestF is not using t.Setenv +``` + +### bash + +```console +$ go vet -vettool=`which tenv` main.go + +# command-line-arguments +./sandbox_test.go:9:2: variable e is not using t.Setenv +./sandbox_test.go:14:2: func setup is not using t.Setenv +./sandbox_test.go:15:2: func setup is not using t.Setenv +./sandbox_test.go:23:2: func TestF is not using t.Setenv +./sandbox_test.go:24:2: func TestF is not using t.Setenv +``` + +### option + +t.Setenv can use since Go1.17. +This linter diagnostics, if Go version is since 1.17. +But, if you wanna exec this linter in prior Go1.17, you can use it that you set `-tenv.f` flag. + +e.g. + +### fish + +```console +go vet -vettool=(which tenv) -tenv.f sandbox_test.go +``` + +### bash + +```console +go vet -vettool=`which tenv` -tenv.f main.go +``` + +## CI + +### CircleCI + +```yaml +- run: + name: Install tenv + command: go install github.com/sivchari/tenv + +- run: + name: Run tenv + command: go vet -vettool=`which tenv` ./... +``` + +### GitHub Actions + +```yaml +- name: Install tenv + run: go install github.com/sivchari/tenv + +- name: Run tenv + run: go vet -vettool=`which tenv` ./... +``` diff --git a/vendor/github.com/sivchari/tenv/go.mod b/vendor/github.com/sivchari/tenv/go.mod new file mode 100644 index 000000000..8061c4b82 --- /dev/null +++ b/vendor/github.com/sivchari/tenv/go.mod @@ -0,0 +1,19 @@ +module github.com/sivchari/tenv + +go 1.17 + +require ( + github.com/gostaticanalysis/testutil v0.4.0 + golang.org/x/tools v0.1.5 +) + +require ( + github.com/hashicorp/go-version v1.2.1 // indirect + github.com/otiai10/copy v1.2.0 // indirect + github.com/tenntenn/modver v1.0.1 // indirect + github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 // indirect + golang.org/x/mod v0.4.2 // indirect + golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect + golang.org/x/text v0.3.3 // indirect + golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect +) diff --git a/vendor/github.com/sivchari/tenv/go.sum b/vendor/github.com/sivchari/tenv/go.sum new file mode 100644 index 000000000..bfa16eba2 --- /dev/null +++ b/vendor/github.com/sivchari/tenv/go.sum @@ -0,0 +1,60 @@ +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a h1:8NZHLa6Gp0hW6xJ0c3F1Kse7dJw30fOcDzHuF9sLbnE= +github.com/josharian/txtarfs v0.0.0-20210218200122-0702f000015a/go.mod h1:izVPOvVRsHiKkeGCT6tYBNWyDVuzj9wAaBb5R9qamfw= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +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 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.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-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.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.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/sivchari/tenv/tenv.go b/vendor/github.com/sivchari/tenv/tenv.go new file mode 100644 index 000000000..9dac6a411 --- /dev/null +++ b/vendor/github.com/sivchari/tenv/tenv.go @@ -0,0 +1,199 @@ +package tenv + +import ( + "go/ast" + "strings" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" +) + +const doc = "tenv is analyzer that detects using os.Setenv instead of t.Setenv since Go1.17" + +// Analyzer is tenv analyzer +var Analyzer = &analysis.Analyzer{ + Name: "tenv", + Doc: doc, + Run: run, + Requires: []*analysis.Analyzer{ + inspect.Analyzer, + }, +} + +var ( + A = "all" + aflag bool +) + +func init() { + Analyzer.Flags.BoolVar(&aflag, A, false, "the all option will run against all method in test file") +} + +func run(pass *analysis.Pass) (interface{}, error) { + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + + nodeFilter := []ast.Node{ + (*ast.File)(nil), + } + + inspect.Preorder(nodeFilter, func(n ast.Node) { + switch n := n.(type) { + case *ast.File: + for _, decl := range n.Decls { + + funcDecl, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + checkFunc(pass, funcDecl, pass.Fset.File(n.Pos()).Name()) + } + } + }) + + return nil, nil +} + +func checkFunc(pass *analysis.Pass, n *ast.FuncDecl, fileName string) { + argName, ok := targetRunner(n, fileName) + if ok { + for _, stmt := range n.Body.List { + switch stmt := stmt.(type) { + case *ast.ExprStmt: + if !checkExprStmt(pass, stmt, n, argName) { + continue + } + case *ast.IfStmt: + if !checkIfStmt(pass, stmt, n, argName) { + continue + } + case *ast.AssignStmt: + if !checkAssignStmt(pass, stmt, n, argName) { + continue + } + } + } + } +} + +func checkExprStmt(pass *analysis.Pass, stmt *ast.ExprStmt, n *ast.FuncDecl, argName string) bool { + callExpr, ok := stmt.X.(*ast.CallExpr) + if !ok { + return false + } + fun, ok := callExpr.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + x, ok := fun.X.(*ast.Ident) + if !ok { + return false + } + targetName := x.Name + "." + fun.Sel.Name + if targetName == "os.Setenv" { + if argName == "" { + argName = "testing" + } + pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, n.Name.Name) + } + return true +} + +func checkIfStmt(pass *analysis.Pass, stmt *ast.IfStmt, n *ast.FuncDecl, argName string) bool { + assignStmt, ok := stmt.Init.(*ast.AssignStmt) + if !ok { + return false + } + rhs, ok := assignStmt.Rhs[0].(*ast.CallExpr) + if !ok { + return false + } + fun, ok := rhs.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + x, ok := fun.X.(*ast.Ident) + if !ok { + return false + } + targetName := x.Name + "." + fun.Sel.Name + if targetName == "os.Setenv" { + if argName == "" { + argName = "testing" + } + pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, n.Name.Name) + } + return true +} + +func checkAssignStmt(pass *analysis.Pass, stmt *ast.AssignStmt, n *ast.FuncDecl, argName string) bool { + rhs, ok := stmt.Rhs[0].(*ast.CallExpr) + if !ok { + return false + } + fun, ok := rhs.Fun.(*ast.SelectorExpr) + if !ok { + return false + } + x, ok := fun.X.(*ast.Ident) + if !ok { + return false + } + targetName := x.Name + "." + fun.Sel.Name + if targetName == "os.Setenv" { + if argName == "" { + argName = "testing" + } + pass.Reportf(stmt.Pos(), "os.Setenv() can be replaced by `%s.Setenv()` in %s", argName, n.Name.Name) + } + return true +} + +func targetRunner(funcDecl *ast.FuncDecl, fileName string) (string, bool) { + params := funcDecl.Type.Params.List + for _, p := range params { + switch typ := p.Type.(type) { + case *ast.StarExpr: + if checkStarExprTarget(typ) { + argName := p.Names[0].Name + return argName, true + } + case *ast.SelectorExpr: + if checkSelectorExprTarget(typ) { + argName := p.Names[0].Name + return argName, true + } + } + } + if aflag && strings.HasSuffix(fileName, "_test.go") { + return "", true + } + return "", false +} + +func checkStarExprTarget(typ *ast.StarExpr) bool { + selector, ok := typ.X.(*ast.SelectorExpr) + if !ok { + return false + } + x, ok := selector.X.(*ast.Ident) + if !ok { + return false + } + targetName := x.Name + "." + selector.Sel.Name + switch targetName { + case "testing.T", "testing.B": + return true + default: + return false + } +} + +func checkSelectorExprTarget(typ *ast.SelectorExpr) bool { + x, ok := typ.X.(*ast.Ident) + if !ok { + return false + } + targetName := x.Name + "." + typ.Sel.Name + return targetName == "testing.TB" +} diff --git a/vendor/github.com/spf13/cast/.travis.yml b/vendor/github.com/spf13/cast/.travis.yml deleted file mode 100644 index 833a48799..000000000 --- a/vendor/github.com/spf13/cast/.travis.yml +++ /dev/null @@ -1,16 +0,0 @@ -language: go -env: - - GO111MODULE=on -sudo: required -go: - - "1.11.x" - - "1.12.x" - - tip -os: - - linux -matrix: - allow_failures: - - go: tip - fast_finish: true -script: - - make check diff --git a/vendor/github.com/spf13/cast/README.md b/vendor/github.com/spf13/cast/README.md index e6939397d..120a57342 100644 --- a/vendor/github.com/spf13/cast/README.md +++ b/vendor/github.com/spf13/cast/README.md @@ -1,7 +1,7 @@ cast ==== [![GoDoc](https://godoc.org/github.com/spf13/cast?status.svg)](https://godoc.org/github.com/spf13/cast) -[![Build Status](https://api.travis-ci.org/spf13/cast.svg?branch=master)](https://travis-ci.org/spf13/cast) +[![Build Status](https://github.com/spf13/cast/actions/workflows/go.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/go.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast) Easy and safe casting from one type to another in Go diff --git a/vendor/github.com/spf13/cast/cast.go b/vendor/github.com/spf13/cast/cast.go index 9fba638d4..0cfe9418d 100644 --- a/vendor/github.com/spf13/cast/cast.go +++ b/vendor/github.com/spf13/cast/cast.go @@ -20,6 +20,11 @@ func ToTime(i interface{}) time.Time { return v } +func ToTimeInDefaultLocation(i interface{}, location *time.Location) time.Time { + v, _ := ToTimeInDefaultLocationE(i, location) + return v +} + // ToDuration casts an interface to a time.Duration type. func ToDuration(i interface{}) time.Duration { v, _ := ToDurationE(i) diff --git a/vendor/github.com/spf13/cast/caste.go b/vendor/github.com/spf13/cast/caste.go index 70c7291be..c04af6a97 100644 --- a/vendor/github.com/spf13/cast/caste.go +++ b/vendor/github.com/spf13/cast/caste.go @@ -20,13 +20,20 @@ var errNegativeNotAllowed = errors.New("unable to cast negative value") // ToTimeE casts an interface to a time.Time type. func ToTimeE(i interface{}) (tim time.Time, err error) { + return ToTimeInDefaultLocationE(i, time.UTC) +} + +// ToTimeInDefaultLocationE casts an empty interface to time.Time, +// interpreting inputs without a timezone to be in the given location, +// or the local timezone if nil. +func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.Time, err error) { i = indirect(i) switch v := i.(type) { case time.Time: return v, nil case string: - return StringToDate(v) + return StringToDateInDefaultLocation(v, location) case int: return time.Unix(int64(v), 0), nil case int64: @@ -1129,8 +1136,43 @@ func ToStringSliceE(i interface{}) ([]string, error) { return a, nil case []string: return v, nil + case []int8: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int32: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []int64: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []float32: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil + case []float64: + for _, u := range v { + a = append(a, ToString(u)) + } + return a, nil case string: return strings.Fields(v), nil + case []error: + for _, err := range i.([]error) { + a = append(a, err.Error()) + } + return a, nil case interface{}: str, err := ToStringE(v) if err != nil { @@ -1204,37 +1246,83 @@ func ToDurationSliceE(i interface{}) ([]time.Duration, error) { // predefined list of formats. If no suitable format is found, an error is // returned. func StringToDate(s string) (time.Time, error) { - return parseDateWith(s, []string{ - time.RFC3339, - "2006-01-02T15:04:05", // iso8601 without timezone - time.RFC1123Z, - time.RFC1123, - time.RFC822Z, - time.RFC822, - time.RFC850, - time.ANSIC, - time.UnixDate, - time.RubyDate, - "2006-01-02 15:04:05.999999999 -0700 MST", // Time.String() - "2006-01-02", - "02 Jan 2006", - "2006-01-02T15:04:05-0700", // RFC3339 without timezone hh:mm colon - "2006-01-02 15:04:05 -07:00", - "2006-01-02 15:04:05 -0700", - "2006-01-02 15:04:05Z07:00", // RFC3339 without T - "2006-01-02 15:04:05Z0700", // RFC3339 without T or timezone hh:mm colon - "2006-01-02 15:04:05", - time.Kitchen, - time.Stamp, - time.StampMilli, - time.StampMicro, - time.StampNano, - }) + return parseDateWith(s, time.UTC, timeFormats) } -func parseDateWith(s string, dates []string) (d time.Time, e error) { - for _, dateType := range dates { - if d, e = time.Parse(dateType, s); e == nil { +// StringToDateInDefaultLocation casts an empty interface to a time.Time, +// interpreting inputs without a timezone to be in the given location, +// or the local timezone if nil. +func StringToDateInDefaultLocation(s string, location *time.Location) (time.Time, error) { + return parseDateWith(s, location, timeFormats) +} + +type timeFormatType int + +const ( + timeFormatNoTimezone timeFormatType = iota + timeFormatNamedTimezone + timeFormatNumericTimezone + timeFormatNumericAndNamedTimezone + timeFormatTimeOnly +) + +type timeFormat struct { + format string + typ timeFormatType +} + +func (f timeFormat) hasTimezone() bool { + // We don't include the formats with only named timezones, see + // https://github.com/golang/go/issues/19694#issuecomment-289103522 + return f.typ >= timeFormatNumericTimezone && f.typ <= timeFormatNumericAndNamedTimezone +} + +var ( + timeFormats = []timeFormat{ + timeFormat{time.RFC3339, timeFormatNumericTimezone}, + timeFormat{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone + timeFormat{time.RFC1123Z, timeFormatNumericTimezone}, + timeFormat{time.RFC1123, timeFormatNamedTimezone}, + timeFormat{time.RFC822Z, timeFormatNumericTimezone}, + timeFormat{time.RFC822, timeFormatNamedTimezone}, + timeFormat{time.RFC850, timeFormatNamedTimezone}, + timeFormat{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() + timeFormat{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon + timeFormat{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon + timeFormat{"2006-01-02 15:04:05", timeFormatNoTimezone}, + timeFormat{time.ANSIC, timeFormatNoTimezone}, + timeFormat{time.UnixDate, timeFormatNamedTimezone}, + timeFormat{time.RubyDate, timeFormatNumericTimezone}, + timeFormat{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, + timeFormat{"2006-01-02", timeFormatNoTimezone}, + timeFormat{"02 Jan 2006", timeFormatNoTimezone}, + timeFormat{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, + timeFormat{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, + timeFormat{time.Kitchen, timeFormatTimeOnly}, + timeFormat{time.Stamp, timeFormatTimeOnly}, + timeFormat{time.StampMilli, timeFormatTimeOnly}, + timeFormat{time.StampMicro, timeFormatTimeOnly}, + timeFormat{time.StampNano, timeFormatTimeOnly}, + } +) + +func parseDateWith(s string, location *time.Location, formats []timeFormat) (d time.Time, e error) { + + for _, format := range formats { + if d, e = time.Parse(format.format, s); e == nil { + + // Some time formats have a zone name, but no offset, so it gets + // put in that zone name (not the default one passed in to us), but + // without that zone's offset. So set the location manually. + if format.typ <= timeFormatNamedTimezone { + if location == nil { + location = time.Local + } + year, month, day := d.Date() + hour, min, sec := d.Clock() + d = time.Date(year, month, day, hour, min, sec, d.Nanosecond(), location) + } + return } } diff --git a/vendor/github.com/spf13/cast/timeformattype_string.go b/vendor/github.com/spf13/cast/timeformattype_string.go new file mode 100644 index 000000000..1524fc82c --- /dev/null +++ b/vendor/github.com/spf13/cast/timeformattype_string.go @@ -0,0 +1,27 @@ +// Code generated by "stringer -type timeFormatType"; DO NOT EDIT. + +package cast + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[timeFormatNoTimezone-0] + _ = x[timeFormatNamedTimezone-1] + _ = x[timeFormatNumericTimezone-2] + _ = x[timeFormatNumericAndNamedTimezone-3] + _ = x[timeFormatTimeOnly-4] +} + +const _timeFormatType_name = "timeFormatNoTimezonetimeFormatNamedTimezonetimeFormatNumericTimezonetimeFormatNumericAndNamedTimezonetimeFormatTimeOnly" + +var _timeFormatType_index = [...]uint8{0, 20, 43, 68, 101, 119} + +func (i timeFormatType) String() string { + if i < 0 || i >= timeFormatType(len(_timeFormatType_index)-1) { + return "timeFormatType(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _timeFormatType_name[_timeFormatType_index[i]:_timeFormatType_index[i+1]] +} diff --git a/vendor/github.com/spf13/viper/README.md b/vendor/github.com/spf13/viper/README.md index f409b1519..9712e7051 100644 --- a/vendor/github.com/spf13/viper/README.md +++ b/vendor/github.com/spf13/viper/README.md @@ -127,11 +127,11 @@ You can handle the specific case where no config file is found like this: ```go if err := viper.ReadInConfig(); err != nil { - if _, ok := err.(viper.ConfigFileNotFoundError); ok { - // Config file not found; ignore error if desired - } else { - // Config file was found but another error was produced - } + if _, ok := err.(viper.ConfigFileNotFoundError); ok { + // Config file not found; ignore error if desired + } else { + // Config file was found but another error was produced + } } // Config file found and successfully parsed @@ -175,10 +175,10 @@ Optionally you can provide a function for Viper to run each time a change occurs **Make sure you add all of the configPaths prior to calling `WatchConfig()`** ```go -viper.WatchConfig() viper.OnConfigChange(func(e fsnotify.Event) { fmt.Println("Config file changed:", e.Name) }) +viper.WatchConfig() ``` ### Reading Config from io.Reader @@ -354,7 +354,7 @@ func main() { i := viper.GetInt("flagname") // retrieve value from viper - ... + // ... } ``` @@ -503,18 +503,18 @@ runtime_viper.Unmarshal(&runtime_conf) // open a goroutine to watch remote changes forever go func(){ for { - time.Sleep(time.Second * 5) // delay after each request + time.Sleep(time.Second * 5) // delay after each request - // currently, only tested with etcd support - err := runtime_viper.WatchRemoteConfig() - if err != nil { - log.Errorf("unable to read remote config: %v", err) - continue - } + // currently, only tested with etcd support + err := runtime_viper.WatchRemoteConfig() + if err != nil { + log.Errorf("unable to read remote config: %v", err) + continue + } - // unmarshal new config into our runtime config struct. you can also use channel - // to implement a signal to notify the system of the changes - runtime_viper.Unmarshal(&runtime_conf) + // unmarshal new config into our runtime config struct. you can also use channel + // to implement a signal to notify the system of the changes + runtime_viper.Unmarshal(&runtime_conf) } }() ``` @@ -546,7 +546,7 @@ Example: ```go viper.GetString("logfile") // case-insensitive Setting & Getting if viper.GetBool("verbose") { - fmt.Println("verbose enabled") + fmt.Println("verbose enabled") } ``` ### Accessing nested keys @@ -669,7 +669,7 @@ So instead of doing that let's pass a Viper instance to the constructor that rep ```go cache1Config := viper.Sub("cache.cache1") if cache1Config == nil { // Sub returns nil if the key cannot be found - panic("cache configuration not found") + panic("cache configuration not found") } cache1 := NewCache(cache1Config) @@ -681,10 +681,10 @@ Internally, the `NewCache` function can address `max-items` and `item-size` keys ```go func NewCache(v *Viper) *Cache { - return &Cache{ - MaxItems: v.GetInt("max-items"), - ItemSize: v.GetInt("item-size"), - } + return &Cache{ + MaxItems: v.GetInt("max-items"), + ItemSize: v.GetInt("item-size"), + } } ``` @@ -726,18 +726,18 @@ you have to change the delimiter: v := viper.NewWithOptions(viper.KeyDelimiter("::")) v.SetDefault("chart::values", map[string]interface{}{ - "ingress": map[string]interface{}{ - "annotations": map[string]interface{}{ - "traefik.frontend.rule.type": "PathPrefix", - "traefik.ingress.kubernetes.io/ssl-redirect": "true", - }, - }, + "ingress": map[string]interface{}{ + "annotations": map[string]interface{}{ + "traefik.frontend.rule.type": "PathPrefix", + "traefik.ingress.kubernetes.io/ssl-redirect": "true", + }, + }, }) type config struct { Chart struct{ - Values map[string]interface{} - } + Values map[string]interface{} + } } var C config @@ -778,6 +778,15 @@ if err != nil { Viper uses [github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) under the hood for unmarshaling values which uses `mapstructure` tags by default. +### Decoding custom formats + +A frequently requested feature for Viper is adding more value formats and decoders. +For example, parsing character (dot, comma, semicolon, etc) separated strings into slices. + +This is already available in Viper using mapstructure decode hooks. + +Read more about the details in [this blog post](https://sagikazarmark.hu/blog/decoding-custom-formats-with-viper/). + ### Marshalling to string You may need to marshal all the settings held in viper into a string rather than write them to a file. @@ -785,17 +794,17 @@ You can use your favorite format's marshaller with the config returned by `AllSe ```go import ( - yaml "gopkg.in/yaml.v2" - // ... + yaml "gopkg.in/yaml.v2" + // ... ) func yamlStringSettings() string { - c := viper.AllSettings() - bs, err := yaml.Marshal(c) - if err != nil { - log.Fatalf("unable to marshal config to YAML: %v", err) - } - return string(bs) + c := viper.AllSettings() + bs, err := yaml.Marshal(c) + if err != nil { + log.Fatalf("unable to marshal config to YAML: %v", err) + } + return string(bs) } ``` diff --git a/vendor/github.com/spf13/viper/go.mod b/vendor/github.com/spf13/viper/go.mod index 145e0a100..fcc1a5d92 100644 --- a/vendor/github.com/spf13/viper/go.mod +++ b/vendor/github.com/spf13/viper/go.mod @@ -3,19 +3,18 @@ module github.com/spf13/viper go 1.12 require ( - github.com/bketelsen/crypt v0.0.4 - github.com/fsnotify/fsnotify v1.4.9 + github.com/fsnotify/fsnotify v1.5.1 github.com/hashicorp/hcl v1.0.0 github.com/magiconair/properties v1.8.5 - github.com/mitchellh/mapstructure v1.4.1 - github.com/pelletier/go-toml v1.9.3 - github.com/smartystreets/goconvey v1.6.4 // indirect + github.com/mitchellh/mapstructure v1.4.2 + github.com/pelletier/go-toml v1.9.4 + github.com/sagikazarmark/crypt v0.1.0 github.com/spf13/afero v1.6.0 - github.com/spf13/cast v1.3.1 + github.com/spf13/cast v1.4.1 github.com/spf13/jwalterweatherman v1.1.0 github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.7.0 github.com/subosito/gotenv v1.2.0 - gopkg.in/ini.v1 v1.62.0 + gopkg.in/ini.v1 v1.63.2 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/vendor/github.com/spf13/viper/go.sum b/vendor/github.com/spf13/viper/go.sum index 27730e2aa..3e0a13ea1 100644 --- a/vendor/github.com/spf13/viper/go.sum +++ b/vendor/github.com/spf13/viper/go.sum @@ -17,8 +17,13 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.93.3 h1:wPBktZFzYBcCZVARvwVKqH1uEj+aLXofJEtrb4oOsio= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= 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= @@ -27,8 +32,8 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g 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/firestore v1.1.0 h1:9x7Bx0A9R5/M9jibeJeZWqjeVEIxYW9fZYqB9a70/bY= -cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/firestore v1.6.0 h1:dMIWvm+3O0E3DM7kcZPH0FBQ94Xg/OMkdTNDaY9itbI= +cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= 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= @@ -41,15 +46,16 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/bketelsen/crypt v0.0.4 h1:w/jqZtC9YD4DS/Vp9GhWfWcCpuAL58oTnLoI8vE9YHU= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 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= @@ -57,6 +63,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= @@ -69,10 +76,13 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= +github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 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= @@ -92,6 +102,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt 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/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 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= @@ -110,6 +121,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -123,12 +135,14 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/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 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= 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= @@ -140,82 +154,91 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/consul/api v1.1.0 h1:BNQPM9ytxj6jbjjdRPioQ94T6YXriSopn0i8COv6SRA= -github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/sdk v0.1.1 h1:LnuDWGNsoajlhGyHJvuWW6FVqRl8JOTPqS6CPTsYjhY= -github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/consul/api v1.10.1 h1:MwZJp86nlnL+6+W1Zly4JUuVn9YHhMggBirMpHGD7kw= +github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= +github.com/hashicorp/consul/sdk v0.8.0 h1:OJtKBtEjboEZvG6AOUdh4Z1Zbyu0WcxQ0qatRrZHTVU= +github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= -github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= -github.com/hashicorp/go-rootcerts v1.0.0 h1:Rqb66Oo1X/eSV1x66xbDccZjhJigjg0+e82kpwzSwCI= -github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= 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/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= -github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= -github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M= -github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= -github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0= -github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY= +github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g= +github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= +github.com/hashicorp/serf v0.9.5 h1:EBWvyu9tcRszt3Bxp3KNssBMP1KuHWyO51lz9+786iM= +github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 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 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= +github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= -github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU= +github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso= +github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= -github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= -github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.2 h1:6h7AQ0yhTcIsmFmnAwQls75jp2Gzs4iB8W7pjMO+rqo= +github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -223,32 +246,33 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= +github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sagikazarmark/crypt v0.1.0 h1:AyO7PGna28P9TMH93Bsxd7m9QC4xE6zyGQTXCo7ZrA8= +github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= -github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= -github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= -github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 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/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= @@ -278,6 +302,7 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= @@ -286,9 +311,11 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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= @@ -312,7 +339,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu 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/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/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= @@ -324,12 +350,10 @@ 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.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 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/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= @@ -340,6 +364,7 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR 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-20190923162816-aa69164e4478/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= @@ -361,8 +386,9 @@ golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= -golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420 h1:a8jGStKg0XqKDlKqjLrXn0ioF5MH36pT7Z0BRTqLhbk= +golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 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= @@ -374,8 +400,11 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/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= @@ -392,6 +421,7 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20190222072716-a9d3bda3a223/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-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -399,12 +429,17 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w 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-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/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-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/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= @@ -428,8 +463,16 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +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-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/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-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf h1:2ucpDCmfkl8Bd/FsLtiD653Wf96cW37s+iGx93zsu4k= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= @@ -437,8 +480,9 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 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.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 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= @@ -448,7 +492,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 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-20190328211700-ab21143f2384/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= @@ -456,9 +499,9 @@ golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgw 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-20190907020128-2ca718005c18/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-20191112195655-aa38f8e97acc/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= @@ -492,8 +535,11 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 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= @@ -520,8 +566,13 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.56.0 h1:08F9XVYTLOGeSQb3xI9C0gXMuQanhdGed0cWFhDozbI= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= 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= @@ -570,8 +621,19 @@ google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71 h1:z+ErRPu0+KS02Td3fOAgdX+lnPDh/VyaABEJPD4JRQs= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= 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= @@ -591,8 +653,14 @@ google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA5 google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= 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= @@ -604,14 +672,16 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD 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 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.63.2 h1:tGK/CyBg7SMzb60vP1M03vNZ3VDu3wGQJwn7Sxi9r3c= +gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/spf13/viper/internal/encoding/decoder.go b/vendor/github.com/spf13/viper/internal/encoding/decoder.go new file mode 100644 index 000000000..08b1bb66b --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/decoder.go @@ -0,0 +1,61 @@ +package encoding + +import ( + "sync" +) + +// Decoder decodes the contents of b into a v representation. +// It's primarily used for decoding contents of a file into a map[string]interface{}. +type Decoder interface { + Decode(b []byte, v interface{}) error +} + +const ( + // ErrDecoderNotFound is returned when there is no decoder registered for a format. + ErrDecoderNotFound = encodingError("decoder not found for this format") + + // ErrDecoderFormatAlreadyRegistered is returned when an decoder is already registered for a format. + ErrDecoderFormatAlreadyRegistered = encodingError("decoder already registered for this format") +) + +// DecoderRegistry can choose an appropriate Decoder based on the provided format. +type DecoderRegistry struct { + decoders map[string]Decoder + + mu sync.RWMutex +} + +// NewDecoderRegistry returns a new, initialized DecoderRegistry. +func NewDecoderRegistry() *DecoderRegistry { + return &DecoderRegistry{ + decoders: make(map[string]Decoder), + } +} + +// RegisterDecoder registers a Decoder for a format. +// Registering a Decoder for an already existing format is not supported. +func (e *DecoderRegistry) RegisterDecoder(format string, enc Decoder) error { + e.mu.Lock() + defer e.mu.Unlock() + + if _, ok := e.decoders[format]; ok { + return ErrDecoderFormatAlreadyRegistered + } + + e.decoders[format] = enc + + return nil +} + +// Decode calls the underlying Decoder based on the format. +func (e *DecoderRegistry) Decode(format string, b []byte, v interface{}) error { + e.mu.RLock() + decoder, ok := e.decoders[format] + e.mu.RUnlock() + + if !ok { + return ErrDecoderNotFound + } + + return decoder.Decode(b, v) +} diff --git a/vendor/github.com/spf13/viper/internal/encoding/encoder.go b/vendor/github.com/spf13/viper/internal/encoding/encoder.go new file mode 100644 index 000000000..82c7996cb --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/encoder.go @@ -0,0 +1,60 @@ +package encoding + +import ( + "sync" +) + +// Encoder encodes the contents of v into a byte representation. +// It's primarily used for encoding a map[string]interface{} into a file format. +type Encoder interface { + Encode(v interface{}) ([]byte, error) +} + +const ( + // ErrEncoderNotFound is returned when there is no encoder registered for a format. + ErrEncoderNotFound = encodingError("encoder not found for this format") + + // ErrEncoderFormatAlreadyRegistered is returned when an encoder is already registered for a format. + ErrEncoderFormatAlreadyRegistered = encodingError("encoder already registered for this format") +) + +// EncoderRegistry can choose an appropriate Encoder based on the provided format. +type EncoderRegistry struct { + encoders map[string]Encoder + + mu sync.RWMutex +} + +// NewEncoderRegistry returns a new, initialized EncoderRegistry. +func NewEncoderRegistry() *EncoderRegistry { + return &EncoderRegistry{ + encoders: make(map[string]Encoder), + } +} + +// RegisterEncoder registers an Encoder for a format. +// Registering a Encoder for an already existing format is not supported. +func (e *EncoderRegistry) RegisterEncoder(format string, enc Encoder) error { + e.mu.Lock() + defer e.mu.Unlock() + + if _, ok := e.encoders[format]; ok { + return ErrEncoderFormatAlreadyRegistered + } + + e.encoders[format] = enc + + return nil +} + +func (e *EncoderRegistry) Encode(format string, v interface{}) ([]byte, error) { + e.mu.RLock() + encoder, ok := e.encoders[format] + e.mu.RUnlock() + + if !ok { + return nil, ErrEncoderNotFound + } + + return encoder.Encode(v) +} diff --git a/vendor/github.com/spf13/viper/internal/encoding/error.go b/vendor/github.com/spf13/viper/internal/encoding/error.go new file mode 100644 index 000000000..e4cde02d7 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/error.go @@ -0,0 +1,7 @@ +package encoding + +type encodingError string + +func (e encodingError) Error() string { + return string(e) +} diff --git a/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go b/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go new file mode 100644 index 000000000..f3e4ab122 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/hcl/codec.go @@ -0,0 +1,40 @@ +package hcl + +import ( + "bytes" + "encoding/json" + + "github.com/hashicorp/hcl" + "github.com/hashicorp/hcl/hcl/printer" +) + +// Codec implements the encoding.Encoder and encoding.Decoder interfaces for HCL encoding. +// TODO: add printer config to the codec? +type Codec struct{} + +func (Codec) Encode(v interface{}) ([]byte, error) { + b, err := json.Marshal(v) + if err != nil { + return nil, err + } + + // TODO: use printer.Format? Is the trailing newline an issue? + + ast, err := hcl.Parse(string(b)) + if err != nil { + return nil, err + } + + var buf bytes.Buffer + + err = printer.Fprint(&buf, ast.Node) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func (Codec) Decode(b []byte, v interface{}) error { + return hcl.Unmarshal(b, v) +} diff --git a/vendor/github.com/spf13/viper/internal/encoding/json/codec.go b/vendor/github.com/spf13/viper/internal/encoding/json/codec.go new file mode 100644 index 000000000..dff9ec982 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/json/codec.go @@ -0,0 +1,17 @@ +package json + +import ( + "encoding/json" +) + +// Codec implements the encoding.Encoder and encoding.Decoder interfaces for JSON encoding. +type Codec struct{} + +func (Codec) Encode(v interface{}) ([]byte, error) { + // TODO: expose prefix and indent in the Codec as setting? + return json.MarshalIndent(v, "", " ") +} + +func (Codec) Decode(b []byte, v interface{}) error { + return json.Unmarshal(b, v) +} diff --git a/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go b/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go new file mode 100644 index 000000000..c043802b9 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/toml/codec.go @@ -0,0 +1,45 @@ +package toml + +import ( + "github.com/pelletier/go-toml" +) + +// Codec implements the encoding.Encoder and encoding.Decoder interfaces for TOML encoding. +type Codec struct{} + +func (Codec) Encode(v interface{}) ([]byte, error) { + if m, ok := v.(map[string]interface{}); ok { + t, err := toml.TreeFromMap(m) + if err != nil { + return nil, err + } + + s, err := t.ToTomlString() + if err != nil { + return nil, err + } + + return []byte(s), nil + } + + return toml.Marshal(v) +} + +func (Codec) Decode(b []byte, v interface{}) error { + tree, err := toml.LoadBytes(b) + if err != nil { + return err + } + + if m, ok := v.(*map[string]interface{}); ok { + vmap := *m + tmap := tree.ToMap() + for k, v := range tmap { + vmap[k] = v + } + + return nil + } + + return tree.Unmarshal(v) +} diff --git a/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go b/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go new file mode 100644 index 000000000..f94b26996 --- /dev/null +++ b/vendor/github.com/spf13/viper/internal/encoding/yaml/codec.go @@ -0,0 +1,14 @@ +package yaml + +import "gopkg.in/yaml.v2" + +// Codec implements the encoding.Encoder and encoding.Decoder interfaces for YAML encoding. +type Codec struct{} + +func (Codec) Encode(v interface{}) ([]byte, error) { + return yaml.Marshal(v) +} + +func (Codec) Decode(b []byte, v interface{}) error { + return yaml.Unmarshal(b, v) +} diff --git a/vendor/github.com/spf13/viper/util.go b/vendor/github.com/spf13/viper/util.go index cee6b2429..09d051a22 100644 --- a/vendor/github.com/spf13/viper/util.go +++ b/vendor/github.com/spf13/viper/util.go @@ -95,19 +95,7 @@ func absPathify(inPath string) string { inPath = userHomeDir() + inPath[5:] } - if strings.HasPrefix(inPath, "$") { - end := strings.Index(inPath, string(os.PathSeparator)) - - var value, suffix string - if end == -1 { - value = os.Getenv(inPath[1:]) - } else { - value = os.Getenv(inPath[1:end]) - suffix = inPath[end:] - } - - inPath = value + suffix - } + inPath = os.ExpandEnv(inPath) if filepath.IsAbs(inPath) { return filepath.Clean(inPath) diff --git a/vendor/github.com/spf13/viper/viper.go b/vendor/github.com/spf13/viper/viper.go index e8c04627b..9e2e3537f 100644 --- a/vendor/github.com/spf13/viper/viper.go +++ b/vendor/github.com/spf13/viper/viper.go @@ -22,7 +22,6 @@ package viper import ( "bytes" "encoding/csv" - "encoding/json" "errors" "fmt" "io" @@ -36,18 +35,20 @@ import ( "time" "github.com/fsnotify/fsnotify" - "github.com/hashicorp/hcl" - "github.com/hashicorp/hcl/hcl/printer" "github.com/magiconair/properties" "github.com/mitchellh/mapstructure" - "github.com/pelletier/go-toml" "github.com/spf13/afero" "github.com/spf13/cast" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/pflag" "github.com/subosito/gotenv" "gopkg.in/ini.v1" - "gopkg.in/yaml.v2" + + "github.com/spf13/viper/internal/encoding" + "github.com/spf13/viper/internal/encoding/hcl" + "github.com/spf13/viper/internal/encoding/json" + "github.com/spf13/viper/internal/encoding/toml" + "github.com/spf13/viper/internal/encoding/yaml" ) // ConfigMarshalError happens when failing to marshal the configuration. @@ -67,8 +68,47 @@ type RemoteResponse struct { Error error } +var ( + encoderRegistry = encoding.NewEncoderRegistry() + decoderRegistry = encoding.NewDecoderRegistry() +) + func init() { v = New() + + { + codec := yaml.Codec{} + + encoderRegistry.RegisterEncoder("yaml", codec) + decoderRegistry.RegisterDecoder("yaml", codec) + + encoderRegistry.RegisterEncoder("yml", codec) + decoderRegistry.RegisterDecoder("yml", codec) + } + + { + codec := json.Codec{} + + encoderRegistry.RegisterEncoder("json", codec) + decoderRegistry.RegisterDecoder("json", codec) + } + + { + codec := toml.Codec{} + + encoderRegistry.RegisterEncoder("toml", codec) + decoderRegistry.RegisterDecoder("toml", codec) + } + + { + codec := hcl.Codec{} + + encoderRegistry.RegisterEncoder("hcl", codec) + decoderRegistry.RegisterDecoder("hcl", codec) + + encoderRegistry.RegisterEncoder("tfvars", codec) + decoderRegistry.RegisterDecoder("tfvars", codec) + } } type remoteConfigFactory interface { @@ -292,7 +332,7 @@ func NewWithOptions(opts ...Option) *Viper { // can use it in their testing as well. func Reset() { v = New() - SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} + SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} } @@ -331,7 +371,7 @@ type RemoteProvider interface { } // SupportedExts are universally supported extensions. -var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "dotenv", "env", "ini"} +var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl", "tfvars", "dotenv", "env", "ini"} // SupportedRemoteProviders are universally supported remote providers. var SupportedRemoteProviders = []string{"etcd", "consul", "firestore"} @@ -1367,11 +1407,13 @@ func (v *Viper) realKey(key string) string { func InConfig(key string) bool { return v.InConfig(key) } func (v *Viper) InConfig(key string) bool { - // if the requested key is an alias, then return the proper key - key = v.realKey(key) + lcaseKey := strings.ToLower(key) - _, exists := v.config[key] - return exists + // if the requested key is an alias, then return the proper key + lcaseKey = v.realKey(lcaseKey) + path := strings.Split(lcaseKey, v.keyDelim) + + return v.searchIndexableWithPathPrefixes(v.config, path) != nil } // SetDefault sets the default value for this key. @@ -1542,7 +1584,7 @@ func (v *Viper) writeConfig(filename string, force bool) error { var configType string ext := filepath.Ext(filename) - if ext != "" { + if ext != "" && ext != filepath.Base(filename) { configType = ext[1:] } else { configType = v.configType @@ -1584,35 +1626,12 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { buf := new(bytes.Buffer) buf.ReadFrom(in) - switch strings.ToLower(v.getConfigType()) { - case "yaml", "yml": - if err := yaml.Unmarshal(buf.Bytes(), &c); err != nil { - return ConfigParseError{err} - } - - case "json": - if err := json.Unmarshal(buf.Bytes(), &c); err != nil { - return ConfigParseError{err} - } - - case "hcl": - obj, err := hcl.Parse(buf.String()) + switch format := strings.ToLower(v.getConfigType()); format { + case "yaml", "yml", "json", "toml", "hcl", "tfvars": + err := decoderRegistry.Decode(format, buf.Bytes(), &c) if err != nil { return ConfigParseError{err} } - if err = hcl.DecodeObject(&c, obj); err != nil { - return ConfigParseError{err} - } - - case "toml": - tree, err := toml.LoadReader(buf) - if err != nil { - return ConfigParseError{err} - } - tmap := tree.ToMap() - for k, v := range tmap { - c[k] = v - } case "dotenv", "env": env, err := gotenv.StrictParse(buf) @@ -1665,26 +1684,13 @@ func (v *Viper) unmarshalReader(in io.Reader, c map[string]interface{}) error { func (v *Viper) marshalWriter(f afero.File, configType string) error { c := v.AllSettings() switch configType { - case "json": - b, err := json.MarshalIndent(c, "", " ") - if err != nil { - return ConfigMarshalError{err} - } - _, err = f.WriteString(string(b)) + case "yaml", "yml", "json", "toml", "hcl", "tfvars": + b, err := encoderRegistry.Encode(configType, c) if err != nil { return ConfigMarshalError{err} } - case "hcl": - b, err := json.Marshal(c) - if err != nil { - return ConfigMarshalError{err} - } - ast, err := hcl.Parse(string(b)) - if err != nil { - return ConfigMarshalError{err} - } - err = printer.Fprint(f, ast.Node) + _, err = f.WriteString(string(b)) if err != nil { return ConfigMarshalError{err} } @@ -1717,25 +1723,6 @@ func (v *Viper) marshalWriter(f afero.File, configType string) error { return ConfigMarshalError{err} } - case "toml": - t, err := toml.TreeFromMap(c) - if err != nil { - return ConfigMarshalError{err} - } - s := t.String() - if _, err := f.WriteString(s); err != nil { - return ConfigMarshalError{err} - } - - case "yaml", "yml": - b, err := yaml.Marshal(c) - if err != nil { - return ConfigMarshalError{err} - } - if _, err = f.WriteString(string(b)); err != nil { - return ConfigMarshalError{err} - } - case "ini": keys := v.AllKeys() cfg := ini.Empty() diff --git a/vendor/github.com/ssgreg/nlreturn/v2/pkg/nlreturn/nlreturn.go b/vendor/github.com/ssgreg/nlreturn/v2/pkg/nlreturn/nlreturn.go index 52318ccfd..42b15e9b3 100644 --- a/vendor/github.com/ssgreg/nlreturn/v2/pkg/nlreturn/nlreturn.go +++ b/vendor/github.com/ssgreg/nlreturn/v2/pkg/nlreturn/nlreturn.go @@ -1,6 +1,7 @@ package nlreturn import ( + "flag" "fmt" "go/ast" "go/token" @@ -13,13 +14,20 @@ const ( linterDoc = `Linter requires a new line before return and branch statements except when the return is alone inside a statement group (such as an if statement) to increase code clarity.` ) +var blockSize int + // NewAnalyzer returns a new nlreturn analyzer. func NewAnalyzer() *analysis.Analyzer { - return &analysis.Analyzer{ + a := &analysis.Analyzer{ Name: linterName, Doc: linterDoc, Run: run, } + + a.Flags.Init("nlreturn", flag.ExitOnError) + a.Flags.IntVar(&blockSize, "block-size", 1, "set block size that is still ok") + + return a } func run(pass *analysis.Pass) (interface{}, error) { @@ -45,7 +53,8 @@ func inspectBlock(pass *analysis.Pass, block []ast.Stmt) { for i, stmt := range block { switch stmt.(type) { case *ast.BranchStmt, *ast.ReturnStmt: - if i == 0 { + + if i == 0 || line(pass, stmt.Pos())-line(pass, block[0].Pos()) < blockSize { return } diff --git a/vendor/github.com/sylvia7788/contextcheck/.gitignore b/vendor/github.com/sylvia7788/contextcheck/.gitignore new file mode 100644 index 000000000..fc1b400c8 --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/.gitignore @@ -0,0 +1,18 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +.idea +.DS_Store diff --git a/vendor/github.com/sylvia7788/contextcheck/LICENSE b/vendor/github.com/sylvia7788/contextcheck/LICENSE new file mode 100644 index 000000000..99e1c482a --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 sylvia.wang + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/sylvia7788/contextcheck/Makefile b/vendor/github.com/sylvia7788/contextcheck/Makefile new file mode 100644 index 000000000..9321e9de3 --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/Makefile @@ -0,0 +1,5 @@ +build: + @GO111MODULE=on go build -ldflags '-s -w' -o contextcheck ./cmd/contextcheck/main.go + +install: + @GO111MODULE=on go install -ldflags '-s -w' ./cmd/contextcheck diff --git a/vendor/github.com/sylvia7788/contextcheck/README.md b/vendor/github.com/sylvia7788/contextcheck/README.md new file mode 100644 index 000000000..dc951aca4 --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/README.md @@ -0,0 +1,61 @@ +[![CircleCI](https://circleci.com/gh/sylvia7788/contextcheck.svg?style=svg)](https://circleci.com/gh/sylvia7788/contextcheck) + + +# contextcheck + +`contextcheck` is a static analysis tool, it is used to check the function whether use a non-inherited context, which will result in a broken call link. + +For example: + +```go +func call1(ctx context.Context) { + ... + + ctx = getNewCtx(ctx) + call2(ctx) // OK + + call2(context.Background()) // Non-inherited new context, use function like `context.WithXXX` instead + + call3() // Function `call3` should pass the context parameter + ... +} + +func call2(ctx context.Context) { + ... +} + +func call3() { + ctx := context.TODO() + call2(ctx) +} + +func getNewCtx(ctx context.Context) (newCtx context.Context) { + ... + return +} +``` + +## Installation + +You can get `contextcheck` by `go get` command. + +```bash +$ go get -u github.com/sylvia7788/contextcheck +``` + +or build yourself. + +```bash +$ make build +$ make install +``` + +## Usage + +Invoke `contextcheck` with your package name + +```bash +$ contextcheck ./... +$ # or +$ go vet -vettool=`which contextcheck` ./... +``` diff --git a/vendor/github.com/sylvia7788/contextcheck/contextcheck.go b/vendor/github.com/sylvia7788/contextcheck/contextcheck.go new file mode 100644 index 000000000..543a80209 --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/contextcheck.go @@ -0,0 +1,507 @@ +package contextcheck + +import ( + "go/ast" + "go/token" + "go/types" + "strconv" + "strings" + "sync" + + "github.com/gostaticanalysis/analysisutil" + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/passes/buildssa" + "golang.org/x/tools/go/ssa" +) + +func NewAnalyzer() *analysis.Analyzer { + return &analysis.Analyzer{ + Name: "contextcheck", + Doc: "check the function whether use a non-inherited context", + Run: NewRun(), + Requires: []*analysis.Analyzer{ + buildssa.Analyzer, + }, + } +} + +const ( + ctxPkg = "context" + ctxName = "Context" +) + +const ( + CtxIn int = 1 << iota // ctx in function's param + CtxOut // ctx in function's results + CtxInField // ctx in function's field param + + CtxInOut = CtxIn | CtxOut +) + +var ( + checkedMap = make(map[string]bool) + checkedMapLock sync.RWMutex +) + +type runner struct { + pass *analysis.Pass + ctxTyp *types.Named + ctxPTyp *types.Pointer + cmpPath string + skipFile map[*ast.File]bool +} + +func NewRun() func(pass *analysis.Pass) (interface{}, error) { + return func(pass *analysis.Pass) (interface{}, error) { + r := new(runner) + r.run(pass) + return nil, nil + } +} + +func (r *runner) run(pass *analysis.Pass) { + r.pass = pass + r.cmpPath = strings.Split(pass.Pkg.Path(), "/")[0] + pssa := pass.ResultOf[buildssa.Analyzer].(*buildssa.SSA) + funcs := pssa.SrcFuncs + name := pass.Pkg.Path() + _ = name + + pkg := pssa.Pkg.Prog.ImportedPackage(ctxPkg) + if pkg == nil { + return + } + + ctxType := pkg.Type(ctxName) + if ctxType == nil { + return + } + + if resNamed, ok := ctxType.Object().Type().(*types.Named); !ok { + return + } else { + r.ctxTyp = resNamed + r.ctxPTyp = types.NewPointer(resNamed) + } + + r.skipFile = make(map[*ast.File]bool) + + for _, f := range funcs { + // skip checked function + key := f.RelString(nil) + _, ok := getValue(key) + if ok { + continue + } + + if !r.checkIsEntry(f, f.Pos()) { + continue + } + + r.checkFuncWithCtx(f) + setValue(key, true) + } +} + +func (r *runner) noImportedContext(f *ssa.Function) (ret bool) { + if !f.Pos().IsValid() { + return false + } + + file := analysisutil.File(r.pass, f.Pos()) + if file == nil { + return false + } + + if skip, has := r.skipFile[file]; has { + return skip + } + defer func() { + r.skipFile[file] = ret + }() + + for _, impt := range file.Imports { + path, err := strconv.Unquote(impt.Path.Value) + if err != nil { + continue + } + path = analysisutil.RemoveVendor(path) + if path == ctxPkg { + return false + } + } + + return true +} + +func (r *runner) checkIsEntry(f *ssa.Function, pos token.Pos) (ret bool) { + if r.noImportedContext(f) { + return false + } + + // check params + tuple := f.Signature.Params() + for i := 0; i < tuple.Len(); i++ { + if r.isCtxType(tuple.At(i).Type()) { + ret = true + break + } + } + + // check freevars + for _, param := range f.FreeVars { + if r.isCtxType(param.Type()) { + ret = true + break + } + } + + // check results + tuple = f.Signature.Results() + for i := 0; i < tuple.Len(); i++ { + // skip the function which generate ctx + if r.isCtxType(tuple.At(i).Type()) { + ret = false + break + } + } + + return +} + +func (r *runner) collectCtxRef(f *ssa.Function) (refMap map[ssa.Instruction]bool, ok bool) { + ok = true + refMap = make(map[ssa.Instruction]bool) + checkedRefMap := make(map[ssa.Value]bool) + storeInstrs := make(map[*ssa.Store]bool) + phiInstrs := make(map[*ssa.Phi]bool) + + var checkRefs func(val ssa.Value, fromAddr bool) + var checkInstr func(instr ssa.Instruction, fromAddr bool) + + checkRefs = func(val ssa.Value, fromAddr bool) { + if val == nil || val.Referrers() == nil { + return + } + + if checkedRefMap[val] { + return + } + checkedRefMap[val] = true + + for _, instr := range *val.Referrers() { + checkInstr(instr, fromAddr) + } + } + + checkInstr = func(instr ssa.Instruction, fromAddr bool) { + switch i := instr.(type) { + case ssa.CallInstruction: + refMap[i] = true + tp := r.getCallInstrCtxType(i) + if tp&CtxOut != 0 { + // collect referrers of the results + checkRefs(i.Value(), false) + return + } + case *ssa.Store: + if fromAddr { + // collect all store to judge whether it's right value is valid + storeInstrs[i] = true + } else { + checkRefs(i.Addr, true) + } + case *ssa.UnOp: + checkRefs(i, false) + case *ssa.MakeClosure: + for _, param := range i.Bindings { + if r.isCtxType(param.Type()) { + refMap[i] = true + break + } + } + case *ssa.Extract: + // only care about ctx + if r.isCtxType(i.Type()) { + checkRefs(i, false) + } + case *ssa.Phi: + phiInstrs[i] = true + checkRefs(i, false) + case *ssa.TypeAssert: + // ctx.(*bm.Context) + } + } + + for _, param := range f.Params { + if r.isCtxType(param.Type()) { + checkRefs(param, false) + } + } + + for _, param := range f.FreeVars { + if r.isCtxType(param.Type()) { + checkRefs(param, false) + } + } + + for instr := range storeInstrs { + if !checkedRefMap[instr.Val] { + r.pass.Reportf(instr.Pos(), "Non-inherited new context, use function like `context.WithXXX` instead") + ok = false + } + } + + for instr := range phiInstrs { + for _, v := range instr.Edges { + if !checkedRefMap[v] { + r.pass.Reportf(instr.Pos(), "Non-inherited new context, use function like `context.WithXXX` instead") + ok = false + } + } + } + + return +} + +func (r *runner) buildPkg(f *ssa.Function) { + if f.Blocks != nil { + return + } + + // only build the pkg which is in the same repo + if r.checkIsSameRepo(f.Pkg.Pkg.Path()) { + f.Pkg.Build() + } +} + +func (r *runner) checkIsSameRepo(s string) bool { + return strings.HasPrefix(s, r.cmpPath+"/") +} + +func (r *runner) checkFuncWithCtx(f *ssa.Function) { + refMap, ok := r.collectCtxRef(f) + if !ok { + return + } + + for _, b := range f.Blocks { + for _, instr := range b.Instrs { + tp, ok := r.getCtxType(instr) + if !ok { + continue + } + + // checked in collectCtxRef, skipped + if tp&CtxOut != 0 { + continue + } + + if tp&CtxIn != 0 { + if !refMap[instr] { + r.pass.Reportf(instr.Pos(), "Non-inherited new context, use function like `context.WithXXX` instead") + } + } + + ff := r.getFunction(instr) + if ff == nil { + continue + } + + key := ff.RelString(nil) + valid, ok := getValue(key) + if ok { + if !valid { + r.pass.Reportf(instr.Pos(), "Function `%s` should pass the context parameter", ff.Name()) + } + continue + } + + // check is thunk or bound + if strings.HasSuffix(key, "$thunk") || strings.HasSuffix(key, "$bound") { + continue + } + + // if ff has no ctx, start deep traversal check + if !r.checkIsEntry(ff, instr.Pos()) { + r.buildPkg(ff) + + checkingMap := make(map[string]bool) + checkingMap[key] = true + valid := r.checkFuncWithoutCtx(ff, checkingMap) + setValue(key, valid) + if !valid { + r.pass.Reportf(instr.Pos(), "Function `%s` should pass the context parameter", ff.Name()) + } + } + } + } +} + +func (r *runner) checkFuncWithoutCtx(f *ssa.Function, checkingMap map[string]bool) (ret bool) { + ret = true + for _, b := range f.Blocks { + for _, instr := range b.Instrs { + tp, ok := r.getCtxType(instr) + if !ok { + continue + } + + if tp&CtxOut != 0 { + continue + } + + // it is considered illegal as long as ctx is in the input and not in *struct X + if tp&CtxIn != 0 { + if tp&CtxInField == 0 { + ret = false + } + continue + } + + ff := r.getFunction(instr) + if ff == nil { + continue + } + + key := ff.RelString(nil) + valid, ok := getValue(key) + if ok { + if !valid { + ret = false + r.pass.Reportf(instr.Pos(), "Function `%s` should pass the context parameter", ff.Name()) + } + continue + } + + // check is thunk or bound + if strings.HasSuffix(key, "$thunk") || strings.HasSuffix(key, "$bound") { + continue + } + + if !r.checkIsEntry(ff, instr.Pos()) { + // handler ring call + if checkingMap[key] { + continue + } + checkingMap[key] = true + + r.buildPkg(ff) + + valid := r.checkFuncWithoutCtx(ff, checkingMap) + setValue(key, valid) + if !valid { + ret = false + r.pass.Reportf(instr.Pos(), "Function `%s` should pass the context parameter", ff.Name()) + } + } + } + } + return ret +} + +func (r *runner) getCtxType(instr ssa.Instruction) (tp int, ok bool) { + switch i := instr.(type) { + case ssa.CallInstruction: + tp = r.getCallInstrCtxType(i) + ok = true + case *ssa.MakeClosure: + tp = r.getMakeClosureCtxType(i) + ok = true + } + return +} + +func (r *runner) getCallInstrCtxType(c ssa.CallInstruction) (tp int) { + // check params + for _, v := range c.Common().Args { + if r.isCtxType(v.Type()) { + if vv, ok := v.(*ssa.UnOp); ok { + if _, ok := vv.X.(*ssa.FieldAddr); ok { + tp |= CtxInField + } + } + + tp |= CtxIn + break + } + } + + // check results + if v := c.Value(); v != nil { + if r.isCtxType(v.Type()) { + tp |= CtxOut + } else { + tuple, ok := v.Type().(*types.Tuple) + if !ok { + return + } + for i := 0; i < tuple.Len(); i++ { + if r.isCtxType(tuple.At(i).Type()) { + tp |= CtxOut + break + } + } + } + } + + return +} + +func (r *runner) getMakeClosureCtxType(c *ssa.MakeClosure) (tp int) { + for _, v := range c.Bindings { + if r.isCtxType(v.Type()) { + if vv, ok := v.(*ssa.UnOp); ok { + if _, ok := vv.X.(*ssa.FieldAddr); ok { + tp |= CtxInField + } + } + + tp |= CtxIn + break + } + } + return +} + +func (r *runner) getFunction(instr ssa.Instruction) (f *ssa.Function) { + switch i := instr.(type) { + case ssa.CallInstruction: + if i.Common().IsInvoke() { + return + } + + switch c := i.Common().Value.(type) { + case *ssa.Function: + f = c + case *ssa.MakeClosure: + // captured in the outer layer + case *ssa.Builtin, *ssa.UnOp, *ssa.Lookup, *ssa.Phi: + // skipped + case *ssa.Extract, *ssa.Call: + // function is a result of a call, skipped + case *ssa.Parameter: + // function is a param, skipped + } + case *ssa.MakeClosure: + f = i.Fn.(*ssa.Function) + } + return +} + +func (r *runner) isCtxType(tp types.Type) bool { + return types.Identical(tp, r.ctxTyp) || types.Identical(tp, r.ctxPTyp) +} + +func getValue(key string) (valid, ok bool) { + checkedMapLock.RLock() + valid, ok = checkedMap[key] + checkedMapLock.RUnlock() + return +} + +func setValue(key string, valid bool) { + checkedMapLock.Lock() + checkedMap[key] = valid + checkedMapLock.Unlock() +} diff --git a/vendor/github.com/sylvia7788/contextcheck/go.mod b/vendor/github.com/sylvia7788/contextcheck/go.mod new file mode 100644 index 000000000..95b9ffaef --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/go.mod @@ -0,0 +1,8 @@ +module github.com/sylvia7788/contextcheck + +go 1.15 + +require ( + github.com/gostaticanalysis/analysisutil v0.7.1 + golang.org/x/tools v0.1.5 +) diff --git a/vendor/github.com/sylvia7788/contextcheck/go.sum b/vendor/github.com/sylvia7788/contextcheck/go.sum new file mode 100644 index 000000000..08eb2c77b --- /dev/null +++ b/vendor/github.com/sylvia7788/contextcheck/go.sum @@ -0,0 +1,62 @@ +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +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.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q= +github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4 h1:d2/eIbH9XjD1fFwD5SHv8x168fjbQ9PB8hvs8DSEC08= +github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI= +github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= +github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0 h1:TJIWdbX0B+kpNagQrjgq8bCMrbhiuX73M2XwgtDMoOI= +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 h1:BCmzIS3n71sGfHB5NMNDB3lHYPz8fWSkCAErHed//qc= +github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= +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/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.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.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA= +golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/vendor/github.com/tetafro/godot/.gitignore b/vendor/github.com/tetafro/godot/.gitignore index db77fd15d..0b17eac4c 100644 --- a/vendor/github.com/tetafro/godot/.gitignore +++ b/vendor/github.com/tetafro/godot/.gitignore @@ -1,4 +1,5 @@ /dist/ +/tmp/ /vendor/ /godot /profile.out diff --git a/vendor/github.com/tetafro/godot/README.md b/vendor/github.com/tetafro/godot/README.md index ff3516e6c..3f97b0e39 100644 --- a/vendor/github.com/tetafro/godot/README.md +++ b/vendor/github.com/tetafro/godot/README.md @@ -39,7 +39,7 @@ defaults are used: # all - for all comments. scope: declarations -# List pf regexps for excluding particular comment lines from check. +# List of regexps for excluding particular comment lines from check. exclude: # Check periods at the end of sentences. diff --git a/vendor/github.com/tetafro/godot/checks.go b/vendor/github.com/tetafro/godot/checks.go index 4a4532767..cba54f310 100644 --- a/vendor/github.com/tetafro/godot/checks.go +++ b/vendor/github.com/tetafro/godot/checks.go @@ -58,18 +58,20 @@ func checkCommentForPeriod(c comment) *Issue { return nil } - // Shift position by the length of comment's special symbols: /* or // - isBlock := strings.HasPrefix(c.lines[0], "/*") - if (isBlock && pos.line == 1) || !isBlock { - pos.column += 2 - } + // Shift position to its real value. `c.text` doesn't contain comment's + // special symbols: /* or //, and line indentations inside. It also + // contains */ in the end in case of block comment. + pos.column += strings.Index( + c.lines[pos.line-1], + strings.Split(c.text, "\n")[pos.line-1], + ) iss := Issue{ Pos: token.Position{ Filename: c.start.Filename, Offset: c.start.Offset, Line: pos.line + c.start.Line - 1, - Column: pos.column + c.start.Column - 1, + Column: pos.column, }, Message: noPeriodMessage, } @@ -77,9 +79,13 @@ func checkCommentForPeriod(c comment) *Issue { // Make a replacement. Use `pos.line` to get an original line from // attached lines. Use `iss.Pos.Column` because it's a position in // the original line. - original := []rune(c.lines[pos.line-1]) - iss.Replacement = string(original[:iss.Pos.Column-1]) + "." + - string(original[iss.Pos.Column-1:]) + original := c.lines[pos.line-1] + if len(original) < iss.Pos.Column-1 { + // This should never happen. Avoid panics, skip this check. + return nil + } + iss.Replacement = original[:iss.Pos.Column-1] + "." + + original[iss.Pos.Column-1:] // Save replacement to raw lines to be able to combine it with // further replacements @@ -115,12 +121,18 @@ func checkCommentForCapital(c comment) []Issue { Message: noCapitalMessage, } - // Make a replacement. Use `pos.line` to get an original line from + // Make a replacement. Use `pos.original` to get an original original from // attached lines. Use `iss.Pos.Column` because it's a position in - // the original line. - rep := []rune(c.lines[pos.line-1]) - rep[iss.Pos.Column-1] = unicode.ToTitle(rep[iss.Pos.Column-1]) - iss.Replacement = string(rep) + // the original original. + original := c.lines[pos.line-1] + col := byteToRuneColumn(original, iss.Pos.Column) - 1 + rep := string(unicode.ToTitle([]rune(original)[col])) // capital letter + if len(original) < iss.Pos.Column-1+len(rep) { + // This should never happen. Avoid panics, skip this check. + continue + } + iss.Replacement = original[:iss.Pos.Column-1] + rep + + original[iss.Pos.Column-1+len(rep):] // Save replacement to raw lines to be able to combine it with // further replacements @@ -158,14 +170,14 @@ func checkPeriod(comment string) (pos position, ok bool) { return position{}, true } - pos.column = len([]rune(line)) + 1 + pos.column = len(line) + 1 return pos, false } // checkCapital checks that each sentense of the text starts with // a capital letter. // NOTE: First letter is not checked in declaration comments, because they -// can describe unexported functions, which start from small letter. +// can describe unexported functions, which start with small letter. func checkCapital(comment string, skipFirst bool) (pp []position) { // Remove common abbreviations from the comment for _, abbr := range abbreviations { @@ -209,7 +221,10 @@ func checkCapital(comment string, skipFirst bool) (pp []position) { continue } if state == endOfSentence && unicode.IsLower(r) { - pp = append(pp, position{line: pos.line, column: pos.column}) + pp = append(pp, position{ + line: pos.line, + column: runeToByteColumn(comment, pos.column), + }) } state = empty } @@ -267,3 +282,22 @@ func hasSuffix(s string, suffixes []string) bool { } return false } + +// The following two functions convert byte and rune indexes. +// +// Example: +// text: a b c Ш e f +// runes: 1 2 3 4 5 6 +// bytes: 0 1 2 3 5 6 +// The reason of the difference is that the size of "Ш" is 2 bytes. +// NOTE: Works only for 1-based indexes (line columns). + +// byteToRuneColumn converts byte index inside the string to rune index. +func byteToRuneColumn(s string, i int) int { + return len([]rune(s[:i-1])) + 1 +} + +// runeToByteColumn converts rune index inside the string to byte index. +func runeToByteColumn(s string, i int) int { + return len(string([]rune(s)[:i-1])) + 1 +} diff --git a/vendor/github.com/tetafro/godot/godot.go b/vendor/github.com/tetafro/godot/godot.go index dcc515b9c..3a360a214 100644 --- a/vendor/github.com/tetafro/godot/godot.go +++ b/vendor/github.com/tetafro/godot/godot.go @@ -27,8 +27,8 @@ type Issue struct { // position is a position inside a comment (might be multiline comment). type position struct { - line int - column int + line int // starts at 1 + column int // starts at 1, byte count } // comment is an internal representation of AST comment entity with additional @@ -38,7 +38,7 @@ type comment struct { lines []string // unmodified lines from file text string // concatenated `lines` with special parts excluded start token.Position // position of the first symbol in comment - decl bool // whether comment is a special one (should not be checked) + decl bool // whether comment is a declaration comment } // Run runs this linter on the provided code. diff --git a/vendor/github.com/tomarrell/wrapcheck/v2/wrapcheck/wrapcheck.go b/vendor/github.com/tomarrell/wrapcheck/v2/wrapcheck/wrapcheck.go index 3b445e295..8168da335 100644 --- a/vendor/github.com/tomarrell/wrapcheck/v2/wrapcheck/wrapcheck.go +++ b/vendor/github.com/tomarrell/wrapcheck/v2/wrapcheck/wrapcheck.go @@ -6,6 +6,7 @@ import ( "go/types" "log" "os" + "regexp" "strings" "github.com/gobwas/glob" @@ -33,7 +34,7 @@ type WrapcheckConfig struct { // allows you to specify functions that wrapcheck will not report as // unwrapped. // - // For example, an ingoredSig of `[]string{"errors.New("}` will ignore errors + // For example, an ignoreSig of `[]string{"errors.New("}` will ignore errors // returned from the stdlib package error's function: // // `func errors.New(message string) error` @@ -45,6 +46,20 @@ type WrapcheckConfig struct { // list to your config. IgnoreSigs []string `mapstructure:"ignoreSigs" yaml:"ignoreSigs"` + // IgnoreSigRegexps defines a list of regular expressions which if matched + // to the signature of the function call returning the error, will be ignored. This + // allows you to specify functions that wrapcheck will not report as + // unwrapped. + // + // For example, an ignoreSigRegexp of `[]string{"\.New.*Err\("}`` will ignore errors + // returned from any signture whose method name starts with "New" and ends with "Err" + // due to the signature matching the regular expression `\.New.*Err\(`. + // + // Note that this is similar to the ignoreSigs configuration, but provides + // slightly more flexibility in defining rules by which signtures will be + // ignored. + IgnoreSigRegexps []string `mapstructure:"ignoreSigRegexps" yaml:"ignoreSigRegexps"` + // IgnorePackageGlobs defines a list of globs which, if matching the package // of the function returning the error, will ignore the error when doing // wrapcheck analysis. @@ -62,6 +77,7 @@ type WrapcheckConfig struct { func NewDefaultConfig() WrapcheckConfig { return WrapcheckConfig{ IgnoreSigs: DefaultIgnoreSigs, + IgnoreSigRegexps: []string{}, IgnorePackageGlobs: []string{}, } } @@ -206,6 +222,8 @@ func reportUnwrapped(pass *analysis.Pass, call *ast.CallExpr, tokenPos token.Pos fnSig := pass.TypesInfo.ObjectOf(sel.Sel).String() if contains(cfg.IgnoreSigs, fnSig) { return + } else if containsMatch(cfg.IgnoreSigRegexps, fnSig) { + return } // Check if the underlying type of the "x" in x.y.z is an interface, as @@ -317,6 +335,22 @@ func contains(slice []string, el string) bool { return false } +func containsMatch(slice []string, el string) bool { + for _, s := range slice { + re, err := regexp.Compile(s) + if err != nil { + log.Printf("unable to parse regexp: %s\n", s) + os.Exit(1) + } + + if re.MatchString(el) { + return true + } + } + + return false +} + // isError returns whether or not the provided type interface is an error func isError(typ types.Type) bool { if typ == nil { diff --git a/vendor/golang.org/x/mod/modfile/read.go b/vendor/golang.org/x/mod/modfile/read.go index 2a961ca81..956f30cbb 100644 --- a/vendor/golang.org/x/mod/modfile/read.go +++ b/vendor/golang.org/x/mod/modfile/read.go @@ -194,12 +194,15 @@ func (x *FileSyntax) updateLine(line *Line, tokens ...string) { line.Token = tokens } -func (x *FileSyntax) removeLine(line *Line) { +// markRemoved modifies line so that it (and its end-of-line comment, if any) +// will be dropped by (*FileSyntax).Cleanup. +func (line *Line) markRemoved() { line.Token = nil + line.Comments.Suffix = nil } // Cleanup cleans up the file syntax x after any edit operations. -// To avoid quadratic behavior, removeLine marks the line as dead +// To avoid quadratic behavior, (*Line).markRemoved marks the line as dead // by setting line.Token = nil but does not remove it from the slice // in which it appears. After edits have all been indicated, // calling Cleanup cleans out the dead lines. diff --git a/vendor/golang.org/x/mod/modfile/rule.go b/vendor/golang.org/x/mod/modfile/rule.go index f8c938498..78f83fa71 100644 --- a/vendor/golang.org/x/mod/modfile/rule.go +++ b/vendor/golang.org/x/mod/modfile/rule.go @@ -47,8 +47,9 @@ type File struct { // A Module is the module statement. type Module struct { - Mod module.Version - Syntax *Line + Mod module.Version + Deprecated string + Syntax *Line } // A Go is the go statement. @@ -57,13 +58,6 @@ type Go struct { Syntax *Line } -// A Require is a single require statement. -type Require struct { - Mod module.Version - Indirect bool // has "// indirect" comment - Syntax *Line -} - // An Exclude is a single exclude statement. type Exclude struct { Mod module.Version @@ -92,6 +86,93 @@ type VersionInterval struct { Low, High string } +// A Require is a single require statement. +type Require struct { + Mod module.Version + Indirect bool // has "// indirect" comment + Syntax *Line +} + +func (r *Require) markRemoved() { + r.Syntax.markRemoved() + *r = Require{} +} + +func (r *Require) setVersion(v string) { + r.Mod.Version = v + + if line := r.Syntax; len(line.Token) > 0 { + if line.InBlock { + // If the line is preceded by an empty line, remove it; see + // https://golang.org/issue/33779. + if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 { + line.Comments.Before = line.Comments.Before[:0] + } + if len(line.Token) >= 2 { // example.com v1.2.3 + line.Token[1] = v + } + } else { + if len(line.Token) >= 3 { // require example.com v1.2.3 + line.Token[2] = v + } + } + } +} + +// setIndirect sets line to have (or not have) a "// indirect" comment. +func (r *Require) setIndirect(indirect bool) { + r.Indirect = indirect + line := r.Syntax + if isIndirect(line) == indirect { + return + } + if indirect { + // Adding comment. + if len(line.Suffix) == 0 { + // New comment. + line.Suffix = []Comment{{Token: "// indirect", Suffix: true}} + return + } + + com := &line.Suffix[0] + text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash))) + if text == "" { + // Empty comment. + com.Token = "// indirect" + return + } + + // Insert at beginning of existing comment. + com.Token = "// indirect; " + text + return + } + + // Removing comment. + f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) + if f == "indirect" { + // Remove whole comment. + line.Suffix = nil + return + } + + // Remove comment prefix. + com := &line.Suffix[0] + i := strings.Index(com.Token, "indirect;") + com.Token = "//" + com.Token[i+len("indirect;"):] +} + +// isIndirect reports whether line has a "// indirect" comment, +// meaning it is in go.mod only for its effect on indirect dependencies, +// so that it can be dropped entirely once the effective version of the +// indirect dependency reaches the given minimum version. +func isIndirect(line *Line) bool { + if len(line.Suffix) == 0 { + return false + } + f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) + return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;") +} + func (f *File) AddModuleStmt(path string) error { if f.Syntax == nil { f.Syntax = new(FileSyntax) @@ -131,8 +212,15 @@ var dontFixRetract VersionFixer = func(_, vers string) (string, error) { return vers, nil } -// Parse parses the data, reported in errors as being from file, -// into a File struct. It applies fix, if non-nil, to canonicalize all module versions found. +// Parse parses and returns a go.mod file. +// +// file is the name of the file, used in positions and errors. +// +// data is the content of the file. +// +// fix is an optional function that canonicalizes module versions. +// If fix is nil, all module versions must be canonical (module.CanonicalVersion +// must return the same string). func Parse(file string, data []byte, fix VersionFixer) (*File, error) { return parseToFile(file, data, fix, true) } @@ -209,6 +297,7 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parse } var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`) +var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`) func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) { // If strict is false, this module is a dependency. @@ -259,8 +348,17 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a errorf("go directive expects exactly one argument") return } else if !GoVersionRE.MatchString(args[0]) { - errorf("invalid go version '%s': must match format 1.23", args[0]) - return + fixed := false + if !strict { + if m := laxGoVersionRE.FindStringSubmatch(args[0]); m != nil { + args[0] = m[1] + fixed = true + } + } + if !fixed { + errorf("invalid go version '%s': must match format 1.23", args[0]) + return + } } f.Go = &Go{Syntax: line} @@ -271,7 +369,11 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a errorf("repeated module statement") return } - f.Module = &Module{Syntax: line} + deprecated := parseDeprecation(block, line) + f.Module = &Module{ + Syntax: line, + Deprecated: deprecated, + } if len(args) != 1 { errorf("usage: module module/path") return @@ -385,7 +487,7 @@ func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, a }) case "retract": - rationale := parseRetractRationale(block, line) + rationale := parseDirectiveComment(block, line) vi, err := parseVersionInterval(verb, "", &args, dontFixRetract) if err != nil { if strict { @@ -454,58 +556,6 @@ func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) { } } -// isIndirect reports whether line has a "// indirect" comment, -// meaning it is in go.mod only for its effect on indirect dependencies, -// so that it can be dropped entirely once the effective version of the -// indirect dependency reaches the given minimum version. -func isIndirect(line *Line) bool { - if len(line.Suffix) == 0 { - return false - } - f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash))) - return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;") -} - -// setIndirect sets line to have (or not have) a "// indirect" comment. -func setIndirect(line *Line, indirect bool) { - if isIndirect(line) == indirect { - return - } - if indirect { - // Adding comment. - if len(line.Suffix) == 0 { - // New comment. - line.Suffix = []Comment{{Token: "// indirect", Suffix: true}} - return - } - - com := &line.Suffix[0] - text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash))) - if text == "" { - // Empty comment. - com.Token = "// indirect" - return - } - - // Insert at beginning of existing comment. - com.Token = "// indirect; " + text - return - } - - // Removing comment. - f := strings.Fields(line.Suffix[0].Token) - if len(f) == 2 { - // Remove whole comment. - line.Suffix = nil - return - } - - // Remove comment prefix. - com := &line.Suffix[0] - i := strings.Index(com.Token, "indirect;") - com.Token = "//" + com.Token[i+len("indirect;"):] -} - // IsDirectoryPath reports whether the given path should be interpreted // as a directory path. Just like on the go command line, relative paths // and rooted paths are directory paths; the rest are module paths. @@ -612,10 +662,29 @@ func parseString(s *string) (string, error) { return t, nil } -// parseRetractRationale extracts the rationale for a retract directive from the -// surrounding comments. If the line does not have comments and is part of a -// block that does have comments, the block's comments are used. -func parseRetractRationale(block *LineBlock, line *Line) string { +var deprecatedRE = lazyregexp.New(`(?s)(?:^|\n\n)Deprecated: *(.*?)(?:$|\n\n)`) + +// parseDeprecation extracts the text of comments on a "module" directive and +// extracts a deprecation message from that. +// +// A deprecation message is contained in a paragraph within a block of comments +// that starts with "Deprecated:" (case sensitive). The message runs until the +// end of the paragraph and does not include the "Deprecated:" prefix. If the +// comment block has multiple paragraphs that start with "Deprecated:", +// parseDeprecation returns the message from the first. +func parseDeprecation(block *LineBlock, line *Line) string { + text := parseDirectiveComment(block, line) + m := deprecatedRE.FindStringSubmatch(text) + if m == nil { + return "" + } + return m[1] +} + +// parseDirectiveComment extracts the text of comments on a directive. +// If the directive's line does not have comments and is part of a block that +// does have comments, the block's comments are used. +func parseDirectiveComment(block *LineBlock, line *Line) string { comments := line.Comment() if block != nil && len(comments.Before) == 0 && len(comments.Suffix) == 0 { comments = block.Comment() @@ -794,6 +863,12 @@ func (f *File) AddGoStmt(version string) error { return nil } +// AddRequire sets the first require line for path to version vers, +// preserving any existing comments for that line and removing all +// other lines for path. +// +// If no line currently exists for path, AddRequire adds a new line +// at the end of the last require block. func (f *File) AddRequire(path, vers string) error { need := true for _, r := range f.Require { @@ -803,7 +878,7 @@ func (f *File) AddRequire(path, vers string) error { f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers) need = false } else { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Require{} } } @@ -815,69 +890,235 @@ func (f *File) AddRequire(path, vers string) error { return nil } +// AddNewRequire adds a new require line for path at version vers at the end of +// the last require block, regardless of any existing require lines for path. func (f *File) AddNewRequire(path, vers string, indirect bool) { line := f.Syntax.addLine(nil, "require", AutoQuote(path), vers) - setIndirect(line, indirect) - f.Require = append(f.Require, &Require{module.Version{Path: path, Version: vers}, indirect, line}) + r := &Require{ + Mod: module.Version{Path: path, Version: vers}, + Syntax: line, + } + r.setIndirect(indirect) + f.Require = append(f.Require, r) } +// SetRequire updates the requirements of f to contain exactly req, preserving +// the existing block structure and line comment contents (except for 'indirect' +// markings) for the first requirement on each named module path. +// +// The Syntax field is ignored for the requirements in req. +// +// Any requirements not already present in the file are added to the block +// containing the last require line. +// +// The requirements in req must specify at most one distinct version for each +// module path. +// +// If any existing requirements may be removed, the caller should call Cleanup +// after all edits are complete. func (f *File) SetRequire(req []*Require) { - need := make(map[string]string) - indirect := make(map[string]bool) + type elem struct { + version string + indirect bool + } + need := make(map[string]elem) for _, r := range req { - need[r.Mod.Path] = r.Mod.Version - indirect[r.Mod.Path] = r.Indirect - } - - for _, r := range f.Require { - if v, ok := need[r.Mod.Path]; ok { - r.Mod.Version = v - r.Indirect = indirect[r.Mod.Path] - } else { - *r = Require{} + if prev, dup := need[r.Mod.Path]; dup && prev.version != r.Mod.Version { + panic(fmt.Errorf("SetRequire called with conflicting versions for path %s (%s and %s)", r.Mod.Path, prev.version, r.Mod.Version)) } + need[r.Mod.Path] = elem{r.Mod.Version, r.Indirect} } - var newStmts []Expr + // Update or delete the existing Require entries to preserve + // only the first for each module path in req. + for _, r := range f.Require { + e, ok := need[r.Mod.Path] + if ok { + r.setVersion(e.version) + r.setIndirect(e.indirect) + } else { + r.markRemoved() + } + delete(need, r.Mod.Path) + } + + // Add new entries in the last block of the file for any paths that weren't + // already present. + // + // This step is nondeterministic, but the final result will be deterministic + // because we will sort the block. + for path, e := range need { + f.AddNewRequire(path, e.version, e.indirect) + } + + f.SortBlocks() +} + +// SetRequireSeparateIndirect updates the requirements of f to contain the given +// requirements. Comment contents (except for 'indirect' markings) are retained +// from the first existing requirement for each module path, and block structure +// is maintained as long as the indirect markings match. +// +// Any requirements on paths not already present in the file are added. Direct +// requirements are added to the last block containing *any* other direct +// requirement. Indirect requirements are added to the last block containing +// *only* other indirect requirements. If no suitable block exists, a new one is +// added, with the last block containing a direct dependency (if any) +// immediately before the first block containing only indirect dependencies. +// +// The Syntax field is ignored for requirements in the given blocks. +func (f *File) SetRequireSeparateIndirect(req []*Require) { + type modKey struct { + path string + indirect bool + } + need := make(map[modKey]string) + for _, r := range req { + need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version + } + + comments := make(map[string]Comments) + for _, r := range f.Require { + v, ok := need[modKey{r.Mod.Path, r.Indirect}] + if !ok { + if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok { + if _, dup := comments[r.Mod.Path]; !dup { + comments[r.Mod.Path] = r.Syntax.Comments + } + } + r.markRemoved() + continue + } + r.setVersion(v) + delete(need, modKey{r.Mod.Path, r.Indirect}) + } + + var ( + lastDirectOrMixedBlock Expr + firstIndirectOnlyBlock Expr + lastIndirectOnlyBlock Expr + ) for _, stmt := range f.Syntax.Stmt { switch stmt := stmt.(type) { - case *LineBlock: - if len(stmt.Token) > 0 && stmt.Token[0] == "require" { - var newLines []*Line - for _, line := range stmt.Line { - if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" { - if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 { - line.Comments.Before = line.Comments.Before[:0] - } - line.Token[1] = need[p] - delete(need, p) - setIndirect(line, indirect[p]) - newLines = append(newLines, line) - } - } - if len(newLines) == 0 { - continue // drop stmt - } - stmt.Line = newLines - } - case *Line: - if len(stmt.Token) > 0 && stmt.Token[0] == "require" { - if p, err := parseString(&stmt.Token[1]); err == nil && need[p] != "" { - stmt.Token[2] = need[p] - delete(need, p) - setIndirect(stmt, indirect[p]) - } else { - continue // drop stmt + if len(stmt.Token) == 0 || stmt.Token[0] != "require" { + continue + } + if isIndirect(stmt) { + lastIndirectOnlyBlock = stmt + } else { + lastDirectOrMixedBlock = stmt + } + case *LineBlock: + if len(stmt.Token) == 0 || stmt.Token[0] != "require" { + continue + } + indirectOnly := true + for _, line := range stmt.Line { + if len(line.Token) == 0 { + continue + } + if !isIndirect(line) { + indirectOnly = false + break + } + } + if indirectOnly { + lastIndirectOnlyBlock = stmt + if firstIndirectOnlyBlock == nil { + firstIndirectOnlyBlock = stmt + } + } else { + lastDirectOrMixedBlock = stmt + } + } + } + + isOrContainsStmt := func(stmt Expr, target Expr) bool { + if stmt == target { + return true + } + if stmt, ok := stmt.(*LineBlock); ok { + if target, ok := target.(*Line); ok { + for _, line := range stmt.Line { + if line == target { + return true + } } } } - newStmts = append(newStmts, stmt) + return false } - f.Syntax.Stmt = newStmts - for path, vers := range need { - f.AddNewRequire(path, vers, indirect[path]) + addRequire := func(path, vers string, indirect bool, comments Comments) { + var line *Line + if indirect { + if lastIndirectOnlyBlock != nil { + line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers) + } else { + // Add a new require block after the last direct-only or mixed "require" + // block (if any). + // + // (f.Syntax.addLine would add the line to an existing "require" block if + // present, but here the existing "require" blocks are all direct-only, so + // we know we need to add a new block instead.) + line = &Line{Token: []string{"require", path, vers}} + lastIndirectOnlyBlock = line + firstIndirectOnlyBlock = line // only block implies first block + if lastDirectOrMixedBlock == nil { + f.Syntax.Stmt = append(f.Syntax.Stmt, line) + } else { + for i, stmt := range f.Syntax.Stmt { + if isOrContainsStmt(stmt, lastDirectOrMixedBlock) { + f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size + copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up + f.Syntax.Stmt[i+1] = line + break + } + } + } + } + } else { + if lastDirectOrMixedBlock != nil { + line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers) + } else { + // Add a new require block before the first indirect block (if any). + // + // That way if the file initially contains only indirect lines, + // the direct lines still appear before it: we preserve existing + // structure, but only to the extent that that structure already + // reflects the direct/indirect split. + line = &Line{Token: []string{"require", path, vers}} + lastDirectOrMixedBlock = line + if firstIndirectOnlyBlock == nil { + f.Syntax.Stmt = append(f.Syntax.Stmt, line) + } else { + for i, stmt := range f.Syntax.Stmt { + if isOrContainsStmt(stmt, firstIndirectOnlyBlock) { + f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size + copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up + f.Syntax.Stmt[i] = line + break + } + } + } + } + } + + line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before) + line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix) + + r := &Require{ + Mod: module.Version{Path: path, Version: vers}, + Indirect: indirect, + Syntax: line, + } + r.setIndirect(indirect) + f.Require = append(f.Require, r) + } + + for k, vers := range need { + addRequire(k.path, vers, k.indirect, comments[k.path]) } f.SortBlocks() } @@ -885,7 +1126,7 @@ func (f *File) SetRequire(req []*Require) { func (f *File) DropRequire(path string) error { for _, r := range f.Require { if r.Mod.Path == path { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Require{} } } @@ -916,7 +1157,7 @@ func (f *File) AddExclude(path, vers string) error { func (f *File) DropExclude(path, vers string) error { for _, x := range f.Exclude { if x.Mod.Path == path && x.Mod.Version == vers { - f.Syntax.removeLine(x.Syntax) + x.Syntax.markRemoved() *x = Exclude{} } } @@ -947,7 +1188,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { continue } // Already added; delete other replacements for same. - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Replace{} } if r.Old.Path == oldPath { @@ -963,7 +1204,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error { func (f *File) DropReplace(oldPath, oldVers string) error { for _, r := range f.Replace { if r.Old.Path == oldPath && r.Old.Version == oldVers { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Replace{} } } @@ -1004,7 +1245,7 @@ func (f *File) AddRetract(vi VersionInterval, rationale string) error { func (f *File) DropRetract(vi VersionInterval) error { for _, r := range f.Retract { if r.VersionInterval == vi { - f.Syntax.removeLine(r.Syntax) + r.Syntax.markRemoved() *r = Retract{} } } diff --git a/vendor/golang.org/x/mod/module/module.go b/vendor/golang.org/x/mod/module/module.go index 0e0301483..ba97ac356 100644 --- a/vendor/golang.org/x/mod/module/module.go +++ b/vendor/golang.org/x/mod/module/module.go @@ -192,6 +192,21 @@ func (e *InvalidVersionError) Error() string { func (e *InvalidVersionError) Unwrap() error { return e.Err } +// An InvalidPathError indicates a module, import, or file path doesn't +// satisfy all naming constraints. See CheckPath, CheckImportPath, +// and CheckFilePath for specific restrictions. +type InvalidPathError struct { + Kind string // "module", "import", or "file" + Path string + Err error +} + +func (e *InvalidPathError) Error() string { + return fmt.Sprintf("malformed %s path %q: %v", e.Kind, e.Path, e.Err) +} + +func (e *InvalidPathError) Unwrap() error { return e.Err } + // Check checks that a given module path, version pair is valid. // In addition to the path being a valid module path // and the version being a valid semantic version, @@ -296,30 +311,36 @@ func fileNameOK(r rune) bool { // this second requirement is replaced by a requirement that the path // follow the gopkg.in server's conventions. // Third, no path element may begin with a dot. -func CheckPath(path string) error { +func CheckPath(path string) (err error) { + defer func() { + if err != nil { + err = &InvalidPathError{Kind: "module", Path: path, Err: err} + } + }() + if err := checkPath(path, modulePath); err != nil { - return fmt.Errorf("malformed module path %q: %v", path, err) + return err } i := strings.Index(path, "/") if i < 0 { i = len(path) } if i == 0 { - return fmt.Errorf("malformed module path %q: leading slash", path) + return fmt.Errorf("leading slash") } if !strings.Contains(path[:i], ".") { - return fmt.Errorf("malformed module path %q: missing dot in first path element", path) + return fmt.Errorf("missing dot in first path element") } if path[0] == '-' { - return fmt.Errorf("malformed module path %q: leading dash in first path element", path) + return fmt.Errorf("leading dash in first path element") } for _, r := range path[:i] { if !firstPathOK(r) { - return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r) + return fmt.Errorf("invalid char %q in first path element", r) } } if _, _, ok := SplitPathVersion(path); !ok { - return fmt.Errorf("malformed module path %q: invalid version", path) + return fmt.Errorf("invalid version") } return nil } @@ -343,7 +364,7 @@ func CheckPath(path string) error { // subtleties of Unicode. func CheckImportPath(path string) error { if err := checkPath(path, importPath); err != nil { - return fmt.Errorf("malformed import path %q: %v", path, err) + return &InvalidPathError{Kind: "import", Path: path, Err: err} } return nil } @@ -358,12 +379,13 @@ const ( filePath ) -// checkPath checks that a general path is valid. -// It returns an error describing why but not mentioning path. -// Because these checks apply to both module paths and import paths, -// the caller is expected to add the "malformed ___ path %q: " prefix. -// fileName indicates whether the final element of the path is a file name -// (as opposed to a directory name). +// checkPath checks that a general path is valid. kind indicates what +// specific constraints should be applied. +// +// checkPath returns an error describing why the path is not valid. +// Because these checks apply to module, import, and file paths, +// and because other checks may be applied, the caller is expected to wrap +// this error with InvalidPathError. func checkPath(path string, kind pathKind) error { if !utf8.ValidString(path) { return fmt.Errorf("invalid UTF-8") @@ -371,7 +393,7 @@ func checkPath(path string, kind pathKind) error { if path == "" { return fmt.Errorf("empty string") } - if path[0] == '-' { + if path[0] == '-' && kind != filePath { return fmt.Errorf("leading dash") } if strings.Contains(path, "//") { @@ -477,7 +499,7 @@ func checkElem(elem string, kind pathKind) error { // subtleties of Unicode. func CheckFilePath(path string) error { if err := checkPath(path, filePath); err != nil { - return fmt.Errorf("malformed file path %q: %v", path, err) + return &InvalidPathError{Kind: "file", Path: path, Err: err} } return nil } diff --git a/vendor/golang.org/x/mod/module/pseudo.go b/vendor/golang.org/x/mod/module/pseudo.go new file mode 100644 index 000000000..f04ad3788 --- /dev/null +++ b/vendor/golang.org/x/mod/module/pseudo.go @@ -0,0 +1,250 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Pseudo-versions +// +// Code authors are expected to tag the revisions they want users to use, +// including prereleases. However, not all authors tag versions at all, +// and not all commits a user might want to try will have tags. +// A pseudo-version is a version with a special form that allows us to +// address an untagged commit and order that version with respect to +// other versions we might encounter. +// +// A pseudo-version takes one of the general forms: +// +// (1) vX.0.0-yyyymmddhhmmss-abcdef123456 +// (2) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456 +// (3) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible +// (4) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456 +// (5) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible +// +// If there is no recently tagged version with the right major version vX, +// then form (1) is used, creating a space of pseudo-versions at the bottom +// of the vX version range, less than any tagged version, including the unlikely v0.0.0. +// +// If the most recent tagged version before the target commit is vX.Y.Z or vX.Y.Z+incompatible, +// then the pseudo-version uses form (2) or (3), making it a prerelease for the next +// possible semantic version after vX.Y.Z. The leading 0 segment in the prerelease string +// ensures that the pseudo-version compares less than possible future explicit prereleases +// like vX.Y.(Z+1)-rc1 or vX.Y.(Z+1)-1. +// +// If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible, +// then the pseudo-version uses form (4) or (5), making it a slightly later prerelease. + +package module + +import ( + "errors" + "fmt" + "strings" + "time" + + "golang.org/x/mod/internal/lazyregexp" + "golang.org/x/mod/semver" +) + +var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`) + +const PseudoVersionTimestampFormat = "20060102150405" + +// PseudoVersion returns a pseudo-version for the given major version ("v1") +// preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time, +// and revision identifier (usually a 12-byte commit hash prefix). +func PseudoVersion(major, older string, t time.Time, rev string) string { + if major == "" { + major = "v0" + } + segment := fmt.Sprintf("%s-%s", t.UTC().Format(PseudoVersionTimestampFormat), rev) + build := semver.Build(older) + older = semver.Canonical(older) + if older == "" { + return major + ".0.0-" + segment // form (1) + } + if semver.Prerelease(older) != "" { + return older + ".0." + segment + build // form (4), (5) + } + + // Form (2), (3). + // Extract patch from vMAJOR.MINOR.PATCH + i := strings.LastIndex(older, ".") + 1 + v, patch := older[:i], older[i:] + + // Reassemble. + return v + incDecimal(patch) + "-0." + segment + build +} + +// ZeroPseudoVersion returns a pseudo-version with a zero timestamp and +// revision, which may be used as a placeholder. +func ZeroPseudoVersion(major string) string { + return PseudoVersion(major, "", time.Time{}, "000000000000") +} + +// incDecimal returns the decimal string incremented by 1. +func incDecimal(decimal string) string { + // Scan right to left turning 9s to 0s until you find a digit to increment. + digits := []byte(decimal) + i := len(digits) - 1 + for ; i >= 0 && digits[i] == '9'; i-- { + digits[i] = '0' + } + if i >= 0 { + digits[i]++ + } else { + // digits is all zeros + digits[0] = '1' + digits = append(digits, '0') + } + return string(digits) +} + +// decDecimal returns the decimal string decremented by 1, or the empty string +// if the decimal is all zeroes. +func decDecimal(decimal string) string { + // Scan right to left turning 0s to 9s until you find a digit to decrement. + digits := []byte(decimal) + i := len(digits) - 1 + for ; i >= 0 && digits[i] == '0'; i-- { + digits[i] = '9' + } + if i < 0 { + // decimal is all zeros + return "" + } + if i == 0 && digits[i] == '1' && len(digits) > 1 { + digits = digits[1:] + } else { + digits[i]-- + } + return string(digits) +} + +// IsPseudoVersion reports whether v is a pseudo-version. +func IsPseudoVersion(v string) bool { + return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v) +} + +// IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base, +// timestamp, and revision, as returned by ZeroPseudoVersion. +func IsZeroPseudoVersion(v string) bool { + return v == ZeroPseudoVersion(semver.Major(v)) +} + +// PseudoVersionTime returns the time stamp of the pseudo-version v. +// It returns an error if v is not a pseudo-version or if the time stamp +// embedded in the pseudo-version is not a valid time. +func PseudoVersionTime(v string) (time.Time, error) { + _, timestamp, _, _, err := parsePseudoVersion(v) + if err != nil { + return time.Time{}, err + } + t, err := time.Parse("20060102150405", timestamp) + if err != nil { + return time.Time{}, &InvalidVersionError{ + Version: v, + Pseudo: true, + Err: fmt.Errorf("malformed time %q", timestamp), + } + } + return t, nil +} + +// PseudoVersionRev returns the revision identifier of the pseudo-version v. +// It returns an error if v is not a pseudo-version. +func PseudoVersionRev(v string) (rev string, err error) { + _, _, rev, _, err = parsePseudoVersion(v) + return +} + +// PseudoVersionBase returns the canonical parent version, if any, upon which +// the pseudo-version v is based. +// +// If v has no parent version (that is, if it is "vX.0.0-[…]"), +// PseudoVersionBase returns the empty string and a nil error. +func PseudoVersionBase(v string) (string, error) { + base, _, _, build, err := parsePseudoVersion(v) + if err != nil { + return "", err + } + + switch pre := semver.Prerelease(base); pre { + case "": + // vX.0.0-yyyymmddhhmmss-abcdef123456 → "" + if build != "" { + // Pseudo-versions of the form vX.0.0-yyyymmddhhmmss-abcdef123456+incompatible + // are nonsensical: the "vX.0.0-" prefix implies that there is no parent tag, + // but the "+incompatible" suffix implies that the major version of + // the parent tag is not compatible with the module's import path. + // + // There are a few such entries in the index generated by proxy.golang.org, + // but we believe those entries were generated by the proxy itself. + return "", &InvalidVersionError{ + Version: v, + Pseudo: true, + Err: fmt.Errorf("lacks base version, but has build metadata %q", build), + } + } + return "", nil + + case "-0": + // vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z + // vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z+incompatible + base = strings.TrimSuffix(base, pre) + i := strings.LastIndexByte(base, '.') + if i < 0 { + panic("base from parsePseudoVersion missing patch number: " + base) + } + patch := decDecimal(base[i+1:]) + if patch == "" { + // vX.0.0-0 is invalid, but has been observed in the wild in the index + // generated by requests to proxy.golang.org. + // + // NOTE(bcmills): I cannot find a historical bug that accounts for + // pseudo-versions of this form, nor have I seen such versions in any + // actual go.mod files. If we find actual examples of this form and a + // reasonable theory of how they came into existence, it seems fine to + // treat them as equivalent to vX.0.0 (especially since the invalid + // pseudo-versions have lower precedence than the real ones). For now, we + // reject them. + return "", &InvalidVersionError{ + Version: v, + Pseudo: true, + Err: fmt.Errorf("version before %s would have negative patch number", base), + } + } + return base[:i+1] + patch + build, nil + + default: + // vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z-pre + // vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z-pre+incompatible + if !strings.HasSuffix(base, ".0") { + panic(`base from parsePseudoVersion missing ".0" before date: ` + base) + } + return strings.TrimSuffix(base, ".0") + build, nil + } +} + +var errPseudoSyntax = errors.New("syntax error") + +func parsePseudoVersion(v string) (base, timestamp, rev, build string, err error) { + if !IsPseudoVersion(v) { + return "", "", "", "", &InvalidVersionError{ + Version: v, + Pseudo: true, + Err: errPseudoSyntax, + } + } + build = semver.Build(v) + v = strings.TrimSuffix(v, build) + j := strings.LastIndex(v, "-") + v, rev = v[:j], v[j+1:] + i := strings.LastIndex(v, "-") + if j := strings.LastIndex(v, "."); j > i { + base = v[:j] // "vX.Y.Z-pre.0" or "vX.Y.(Z+1)-0" + timestamp = v[j+1:] + } else { + base = v[:i] // "vX.0.0" + timestamp = v[i+1:] + } + return base, timestamp, rev, build, nil +} diff --git a/vendor/golang.org/x/mod/semver/semver.go b/vendor/golang.org/x/mod/semver/semver.go index 4338f3517..7be398f80 100644 --- a/vendor/golang.org/x/mod/semver/semver.go +++ b/vendor/golang.org/x/mod/semver/semver.go @@ -22,6 +22,8 @@ // as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0. package semver +import "sort" + // parsed returns the parsed form of a semantic version string. type parsed struct { major string @@ -150,6 +152,24 @@ func Max(v, w string) string { return w } +// ByVersion implements sort.Interface for sorting semantic version strings. +type ByVersion []string + +func (vs ByVersion) Len() int { return len(vs) } +func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] } +func (vs ByVersion) Less(i, j int) bool { + cmp := Compare(vs[i], vs[j]) + if cmp != 0 { + return cmp < 0 + } + return vs[i] < vs[j] +} + +// Sort sorts a list of semantic version strings using ByVersion. +func Sort(list []string) { + sort.Sort(ByVersion(list)) +} + func parse(v string) (p parsed, ok bool) { if v == "" || v[0] != 'v' { p.err = "missing v prefix" diff --git a/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go b/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go index eb0016b18..7b82d0b6d 100644 --- a/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go +++ b/vendor/golang.org/x/tools/go/analysis/passes/asmdecl/asmdecl.go @@ -51,6 +51,11 @@ type asmArch struct { bigEndian bool stack string lr bool + // retRegs is a list of registers for return value in register ABI (ABIInternal). + // For now, as we only check whether we write to any result, here we only need to + // include the first integer register and first floating-point register. Accessing + // any of them counts as writing to result. + retRegs []string // calculated during initialization sizes types.Sizes intSize int @@ -79,8 +84,8 @@ type asmVar struct { var ( asmArch386 = asmArch{name: "386", bigEndian: false, stack: "SP", lr: false} asmArchArm = asmArch{name: "arm", bigEndian: false, stack: "R13", lr: true} - asmArchArm64 = asmArch{name: "arm64", bigEndian: false, stack: "RSP", lr: true} - asmArchAmd64 = asmArch{name: "amd64", bigEndian: false, stack: "SP", lr: false} + asmArchArm64 = asmArch{name: "arm64", bigEndian: false, stack: "RSP", lr: true, retRegs: []string{"R0", "F0"}} + asmArchAmd64 = asmArch{name: "amd64", bigEndian: false, stack: "SP", lr: false, retRegs: []string{"AX", "X0"}} asmArchMips = asmArch{name: "mips", bigEndian: true, stack: "R29", lr: true} asmArchMipsLE = asmArch{name: "mipsle", bigEndian: false, stack: "R29", lr: true} asmArchMips64 = asmArch{name: "mips64", bigEndian: true, stack: "R29", lr: true} @@ -137,7 +142,7 @@ var ( asmSP = re(`[^+\-0-9](([0-9]+)\(([A-Z0-9]+)\))`) asmOpcode = re(`^\s*(?:[A-Z0-9a-z_]+:)?\s*([A-Z]+)\s*([^,]*)(?:,\s*(.*))?`) ppc64Suff = re(`([BHWD])(ZU|Z|U|BR)?$`) - abiSuff = re(`^(.+)$`) + abiSuff = re(`^(.+)<(ABI.+)>$`) ) func run(pass *analysis.Pass) (interface{}, error) { @@ -185,6 +190,7 @@ Files: var ( fn *asmFunc fnName string + abi string localSize, argSize int wroteSP bool noframe bool @@ -195,18 +201,22 @@ Files: flushRet := func() { if fn != nil && fn.vars["ret"] != nil && !haveRetArg && len(retLine) > 0 { v := fn.vars["ret"] + resultStr := fmt.Sprintf("%d-byte ret+%d(FP)", v.size, v.off) + if abi == "ABIInternal" { + resultStr = "result register" + } for _, line := range retLine { - pass.Reportf(analysisutil.LineStart(tf, line), "[%s] %s: RET without writing to %d-byte ret+%d(FP)", arch, fnName, v.size, v.off) + pass.Reportf(analysisutil.LineStart(tf, line), "[%s] %s: RET without writing to %s", arch, fnName, resultStr) } } retLine = nil } - trimABI := func(fnName string) string { + trimABI := func(fnName string) (string, string) { m := abiSuff.FindStringSubmatch(fnName) if m != nil { - return m[1] + return m[1], m[2] } - return fnName + return fnName, "" } for lineno, line := range lines { lineno++ @@ -273,11 +283,12 @@ Files: // log.Printf("%s:%d: [%s] cannot check cross-package assembly function: %s is in package %s", fname, lineno, arch, fnName, pkgPath) fn = nil fnName = "" + abi = "" continue } } // Trim off optional ABI selector. - fnName := trimABI(fnName) + fnName, abi = trimABI(fnName) flag := m[3] fn = knownFunc[fnName][arch] if fn != nil { @@ -305,6 +316,7 @@ Files: flushRet() fn = nil fnName = "" + abi = "" continue } @@ -335,6 +347,15 @@ Files: haveRetArg = true } + if abi == "ABIInternal" && !haveRetArg { + for _, reg := range archDef.retRegs { + if strings.Contains(line, reg) { + haveRetArg = true + break + } + } + } + for _, m := range asmSP.FindAllStringSubmatch(line, -1) { if m[3] != archDef.stack || wroteSP || noframe { continue diff --git a/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go b/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go index f0d2c7edf..2eb782b42 100644 --- a/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go +++ b/vendor/golang.org/x/tools/go/analysis/passes/nilness/nilness.go @@ -135,6 +135,11 @@ func runFunc(pass *analysis.Pass, fn *ssa.Function) { if nilnessOf(stack, instr.X) == isnil { reportf("nilpanic", instr.Pos(), "panic with nil value") } + case *ssa.SliceToArrayPointer: + nn := nilnessOf(stack, instr.X) + if nn == isnil && slice2ArrayPtrLen(instr) > 0 { + reportf("conversionpanic", instr.Pos(), "nil slice being cast to an array of len > 0 will always panic") + } } } @@ -259,6 +264,26 @@ func nilnessOf(stack []fact, v ssa.Value) nilness { if underlying := nilnessOf(stack, v.X); underlying != unknown { return underlying } + case *ssa.SliceToArrayPointer: + nn := nilnessOf(stack, v.X) + if slice2ArrayPtrLen(v) > 0 { + if nn == isnil { + // We know that *(*[1]byte)(nil) is going to panic because of the + // conversion. So return unknown to the caller, prevent useless + // nil deference reporting due to * operator. + return unknown + } + // Otherwise, the conversion will yield a non-nil pointer to array. + // Note that the instruction can still panic if array length greater + // than slice length. If the value is used by another instruction, + // that instruction can assume the panic did not happen when that + // instruction is reached. + return isnonnil + } + // In case array length is zero, the conversion result depends on nilness of the slice. + if nn != unknown { + return nn + } } // Is value intrinsically nil or non-nil? @@ -292,6 +317,10 @@ func nilnessOf(stack []fact, v ssa.Value) nilness { return unknown } +func slice2ArrayPtrLen(v *ssa.SliceToArrayPointer) int64 { + return v.Type().(*types.Pointer).Elem().Underlying().(*types.Array).Len() +} + // If b ends with an equality comparison, eq returns the operation and // its true (equal) and false (not equal) successors. func eq(b *ssa.BasicBlock) (op *ssa.BinOp, tsucc, fsucc *ssa.BasicBlock) { diff --git a/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go b/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go index 6589478af..de0369a42 100644 --- a/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go +++ b/vendor/golang.org/x/tools/go/analysis/passes/printf/printf.go @@ -490,7 +490,7 @@ func printfNameAndKind(pass *analysis.Pass, call *ast.CallExpr) (fn *types.Func, _, ok = isPrint[strings.ToLower(fn.Name())] } if ok { - if fn.Name() == "Errorf" { + if fn.FullName() == "fmt.Errorf" { kind = KindErrorf } else if strings.HasSuffix(fn.Name(), "f") { kind = KindPrintf @@ -590,12 +590,9 @@ func checkPrintf(pass *analysis.Pass, kind Kind, call *ast.CallExpr, fn *types.F } if state.verb == 'w' { switch kind { - case KindNone, KindPrint: + case KindNone, KindPrint, KindPrintf: pass.Reportf(call.Pos(), "%s does not support error-wrapping directive %%w", state.name) return - case KindPrintf: - pass.Reportf(call.Pos(), "%s call has error-wrapping directive %%w, which is only supported for functions backed by fmt.Errorf", state.name) - return } if anyW { pass.Reportf(call.Pos(), "%s call has more than one error-wrapping directive %%w", state.name) diff --git a/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go b/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go index d2b9a5640..ce05a56cc 100644 --- a/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go +++ b/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/testinggoroutine.go @@ -119,11 +119,33 @@ func typeIsTestingDotTOrB(expr ast.Expr) (string, bool) { return varTypeName, ok } +// goStmtFunc returns the ast.Node of a call expression +// that was invoked as a go statement. Currently, only +// function literals declared in the same function, and +// static calls within the same package are supported. +func goStmtFun(goStmt *ast.GoStmt) ast.Node { + switch goStmt.Call.Fun.(type) { + case *ast.Ident: + id := goStmt.Call.Fun.(*ast.Ident) + // TODO(cuonglm): improve this once golang/go#48141 resolved. + if id.Obj == nil { + break + } + if funDecl, ok := id.Obj.Decl.(ast.Node); ok { + return funDecl + } + case *ast.FuncLit: + return goStmt.Call.Fun + } + return goStmt.Call +} + // checkGoStmt traverses the goroutine and checks for the // use of the forbidden *testing.(B, T) methods. func checkGoStmt(pass *analysis.Pass, goStmt *ast.GoStmt) { + fn := goStmtFun(goStmt) // Otherwise examine the goroutine to check for the forbidden methods. - ast.Inspect(goStmt, func(n ast.Node) bool { + ast.Inspect(fn, func(n ast.Node) bool { selExpr, ok := n.(*ast.SelectorExpr) if !ok { return true @@ -147,7 +169,11 @@ func checkGoStmt(pass *analysis.Pass, goStmt *ast.GoStmt) { return true } if typeName, ok := typeIsTestingDotTOrB(field.Type); ok { - pass.ReportRangef(selExpr, "call to (*%s).%s from a non-test goroutine", typeName, selExpr.Sel) + var fnRange analysis.Range = goStmt + if _, ok := fn.(*ast.FuncLit); ok { + fnRange = selExpr + } + pass.ReportRangef(fnRange, "call to (*%s).%s from a non-test goroutine", typeName, selExpr.Sel) } return true }) diff --git a/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go b/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go index 823227618..570ad5c20 100644 --- a/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go +++ b/vendor/golang.org/x/tools/go/analysis/passes/tests/tests.go @@ -8,7 +8,9 @@ package tests import ( "go/ast" + "go/token" "go/types" + "regexp" "strings" "unicode" "unicode/utf8" @@ -42,10 +44,10 @@ func run(pass *analysis.Pass) (interface{}, error) { // Ignore non-functions or functions with receivers. continue } - switch { case strings.HasPrefix(fn.Name.Name, "Example"): - checkExample(pass, fn) + checkExampleName(pass, fn) + checkExampleOutput(pass, fn, f.Comments) case strings.HasPrefix(fn.Name.Name, "Test"): checkTest(pass, fn, "Test") case strings.HasPrefix(fn.Name.Name, "Benchmark"): @@ -108,7 +110,59 @@ func lookup(pkg *types.Package, name string) []types.Object { return ret } -func checkExample(pass *analysis.Pass, fn *ast.FuncDecl) { +// This pattern is taken from /go/src/go/doc/example.go +var outputRe = regexp.MustCompile(`(?i)^[[:space:]]*(unordered )?output:`) + +type commentMetadata struct { + isOutput bool + pos token.Pos +} + +func checkExampleOutput(pass *analysis.Pass, fn *ast.FuncDecl, fileComments []*ast.CommentGroup) { + commentsInExample := []commentMetadata{} + numOutputs := 0 + + // Find the comment blocks that are in the example. These comments are + // guaranteed to be in order of appearance. + for _, cg := range fileComments { + if cg.Pos() < fn.Pos() { + continue + } else if cg.End() > fn.End() { + break + } + + isOutput := outputRe.MatchString(cg.Text()) + if isOutput { + numOutputs++ + } + + commentsInExample = append(commentsInExample, commentMetadata{ + isOutput: isOutput, + pos: cg.Pos(), + }) + } + + // Change message based on whether there are multiple output comment blocks. + msg := "output comment block must be the last comment block" + if numOutputs > 1 { + msg = "there can only be one output comment block per example" + } + + for i, cg := range commentsInExample { + // Check for output comments that are not the last comment in the example. + isLast := (i == len(commentsInExample)-1) + if cg.isOutput && !isLast { + pass.Report( + analysis.Diagnostic{ + Pos: cg.pos, + Message: msg, + }, + ) + } + } +} + +func checkExampleName(pass *analysis.Pass, fn *ast.FuncDecl) { fnName := fn.Name.Name if params := fn.Type.Params; len(params.List) != 0 { pass.Reportf(fn.Pos(), "%s should be niladic", fnName) diff --git a/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go b/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go index b949fc840..5fe75b14c 100644 --- a/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go +++ b/vendor/golang.org/x/tools/go/ast/astutil/rewrite.go @@ -439,8 +439,10 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast. } default: - if typeparams.IsListExpr(n) { - a.applyList(n, "ElemList") + if ix := typeparams.GetIndexExprData(n); ix != nil { + a.apply(n, "X", nil, ix.X) + // *ast.IndexExpr was handled above, so n must be an *ast.MultiIndexExpr. + a.applyList(n, "Indices") } else { panic(fmt.Sprintf("Apply: unexpected node type %T", n)) } diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go index a807d0aaa..072005af8 100644 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go +++ b/vendor/golang.org/x/tools/go/internal/gcimporter/bexport.go @@ -92,16 +92,18 @@ func internalErrorf(format string, args ...interface{}) error { // BExportData returns binary export data for pkg. // If no file set is provided, position info will be missing. func BExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) { - defer func() { - if e := recover(); e != nil { - if ierr, ok := e.(internalError); ok { - err = ierr - return + if !debug { + defer func() { + if e := recover(); e != nil { + if ierr, ok := e.(internalError); ok { + err = ierr + return + } + // Not an internal error; panic again. + panic(e) } - // Not an internal error; panic again. - panic(e) - } - }() + }() + } p := exporter{ fset: fset, diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go index e9f73d14a..b02312000 100644 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go +++ b/vendor/golang.org/x/tools/go/internal/gcimporter/bimport.go @@ -1029,6 +1029,7 @@ func predeclared() []types.Type { // used internally by gc; never used by this package or in .a files anyType{}, } + predecl = append(predecl, additionalPredeclared()...) }) return predecl } diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go index d2fc8b6fa..be8b7459a 100644 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go +++ b/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go @@ -19,11 +19,9 @@ import ( "math/big" "reflect" "sort" -) -// Current indexed export format version. Increase with each format change. -// 0: Go1.11 encoding -const iexportVersion = 0 + "golang.org/x/tools/internal/typeparams" +) // Current bundled export format version. Increase with each format change. // 0: initial implementation @@ -44,16 +42,18 @@ func IExportBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) er } func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, pkgs []*types.Package) (err error) { - defer func() { - if e := recover(); e != nil { - if ierr, ok := e.(internalError); ok { - err = ierr - return + if !debug { + defer func() { + if e := recover(); e != nil { + if ierr, ok := e.(internalError); ok { + err = ierr + return + } + // Not an internal error; panic again. + panic(e) } - // Not an internal error; panic again. - panic(e) - } - }() + }() + } p := iexporter{ fset: fset, @@ -158,7 +158,7 @@ func (w *exportWriter) writeIndex(index map[types.Object]uint64) { pkgs = append(pkgs, pkg) sort.Slice(objs, func(i, j int) bool { - return objs[i].Name() < objs[j].Name() + return indexName(objs[i]) < indexName(objs[j]) }) } @@ -175,12 +175,26 @@ func (w *exportWriter) writeIndex(index map[types.Object]uint64) { objs := pkgObjs[pkg] w.uint64(uint64(len(objs))) for _, obj := range objs { - w.string(obj.Name()) + w.string(indexName(obj)) w.uint64(index[obj]) } } } +// indexName returns the 'indexed' name of an object. It differs from +// obj.Name() only for type parameter names, where we include the subscripted +// type parameter ID. +// +// TODO(rfindley): remove this once we no longer need subscripts. +func indexName(obj types.Object) (res string) { + if _, ok := obj.(*types.TypeName); ok { + if tparam, ok := obj.Type().(*typeparams.TypeParam); ok { + return types.TypeString(tparam, func(*types.Package) string { return "" }) + } + } + return obj.Name() +} + type iexporter struct { fset *token.FileSet out *bytes.Buffer @@ -233,10 +247,11 @@ func (p *iexporter) pushDecl(obj types.Object) { type exportWriter struct { p *iexporter - data intWriter - currPkg *types.Package - prevFile string - prevLine int64 + data intWriter + currPkg *types.Package + prevFile string + prevLine int64 + prevColumn int64 } func (w *exportWriter) exportPath(pkg *types.Package) string { @@ -261,8 +276,23 @@ func (p *iexporter) doDecl(obj types.Object) { if sig.Recv() != nil { panic(internalErrorf("unexpected method: %v", sig)) } - w.tag('F') + + // Function. + if typeparams.ForSignature(sig).Len() == 0 { + w.tag('F') + } else { + w.tag('G') + } w.pos(obj.Pos()) + // The tparam list of the function type is the + // declaration of the type params. So, write out the type + // params right now. Then those type params will be + // referenced via their type offset (via typOff) in all + // other places in the signature and function that they + // are used. + if tparams := typeparams.ForSignature(sig); tparams.Len() > 0 { + w.tparamList(tparams, obj.Pkg()) + } w.signature(sig) case *types.Const: @@ -271,30 +301,46 @@ func (p *iexporter) doDecl(obj types.Object) { w.value(obj.Type(), obj.Val()) case *types.TypeName: + t := obj.Type() + + if tparam, ok := t.(*typeparams.TypeParam); ok { + w.tag('P') + w.pos(obj.Pos()) + w.typ(tparam.Constraint(), obj.Pkg()) + break + } + if obj.IsAlias() { w.tag('A') w.pos(obj.Pos()) - w.typ(obj.Type(), obj.Pkg()) + w.typ(t, obj.Pkg()) break } // Defined type. - w.tag('T') + named, ok := t.(*types.Named) + if !ok { + panic(internalErrorf("%s is not a defined type", t)) + } + + if typeparams.ForNamed(named).Len() == 0 { + w.tag('T') + } else { + w.tag('U') + } w.pos(obj.Pos()) + if typeparams.ForNamed(named).Len() > 0 { + w.tparamList(typeparams.ForNamed(named), obj.Pkg()) + } + underlying := obj.Type().Underlying() w.typ(underlying, obj.Pkg()) - t := obj.Type() if types.IsInterface(t) { break } - named, ok := t.(*types.Named) - if !ok { - panic(internalErrorf("%s is not a defined type", t)) - } - n := named.NumMethods() w.uint64(uint64(n)) for i := 0; i < n; i++ { @@ -318,6 +364,48 @@ func (w *exportWriter) tag(tag byte) { } func (w *exportWriter) pos(pos token.Pos) { + if iexportVersion >= iexportVersionPosCol { + w.posV1(pos) + } else { + w.posV0(pos) + } +} + +func (w *exportWriter) posV1(pos token.Pos) { + if w.p.fset == nil { + w.int64(0) + return + } + + p := w.p.fset.Position(pos) + file := p.Filename + line := int64(p.Line) + column := int64(p.Column) + + deltaColumn := (column - w.prevColumn) << 1 + deltaLine := (line - w.prevLine) << 1 + + if file != w.prevFile { + deltaLine |= 1 + } + if deltaLine != 0 { + deltaColumn |= 1 + } + + w.int64(deltaColumn) + if deltaColumn&1 != 0 { + w.int64(deltaLine) + if deltaLine&1 != 0 { + w.string(file) + } + } + + w.prevFile = file + w.prevLine = line + w.prevColumn = column +} + +func (w *exportWriter) posV0(pos token.Pos) { if w.p.fset == nil { w.int64(0) return @@ -361,8 +449,7 @@ func (w *exportWriter) pkg(pkg *types.Package) { func (w *exportWriter) qualifiedIdent(obj types.Object) { // Ensure any referenced declarations are written out too. w.p.pushDecl(obj) - - w.string(obj.Name()) + w.string(indexName(obj)) w.pkg(obj.Pkg()) } @@ -398,9 +485,22 @@ func (w *exportWriter) startType(k itag) { func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { switch t := t.(type) { case *types.Named: + if targs := typeparams.NamedTypeArgs(t); targs.Len() > 0 { + w.startType(instanceType) + // TODO(rfindley): investigate if this position is correct, and if it + // matters. + w.pos(t.Obj().Pos()) + w.typeList(targs, pkg) + w.typ(typeparams.NamedTypeOrigin(t), pkg) + return + } w.startType(definedType) w.qualifiedIdent(t.Obj()) + case *typeparams.TypeParam: + w.startType(typeParamType) + w.qualifiedIdent(t.Obj()) + case *types.Pointer: w.startType(pointerType) w.typ(t.Elem(), pkg) @@ -461,9 +561,14 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { n := t.NumEmbeddeds() w.uint64(uint64(n)) for i := 0; i < n; i++ { - f := t.Embedded(i) - w.pos(f.Obj().Pos()) - w.typ(f.Obj().Type(), f.Obj().Pkg()) + ft := t.EmbeddedType(i) + tPkg := pkg + if named, _ := ft.(*types.Named); named != nil { + w.pos(named.Obj().Pos()) + } else { + w.pos(token.NoPos) + } + w.typ(ft, tPkg) } n = t.NumExplicitMethods() @@ -476,6 +581,16 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) { w.signature(sig) } + case *typeparams.Union: + w.startType(unionType) + nt := t.Len() + w.uint64(uint64(nt)) + for i := 0; i < nt; i++ { + term := t.Term(i) + w.bool(term.Tilde()) + w.typ(term.Type(), pkg) + } + default: panic(internalErrorf("unexpected type: %v, %v", t, reflect.TypeOf(t))) } @@ -497,6 +612,21 @@ func (w *exportWriter) signature(sig *types.Signature) { } } +func (w *exportWriter) typeList(ts *typeparams.TypeList, pkg *types.Package) { + w.uint64(uint64(ts.Len())) + for i := 0; i < ts.Len(); i++ { + w.typ(ts.At(i), pkg) + } +} + +func (w *exportWriter) tparamList(list *typeparams.TypeParamList, pkg *types.Package) { + ll := uint64(list.Len()) + w.uint64(ll) + for i := 0; i < list.Len(); i++ { + w.typ(list.At(i), pkg) + } +} + func (w *exportWriter) paramList(tup *types.Tuple) { n := tup.Len() w.uint64(uint64(n)) @@ -702,7 +832,7 @@ func (w *exportWriter) localIdent(obj types.Object) { return } - name := obj.Name() + name := indexName(obj) if name == "_" { w.string("_") return diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go index 8ed8bc62d..1fcc87e58 100644 --- a/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go +++ b/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go @@ -18,6 +18,8 @@ import ( "go/types" "io" "sort" + + "golang.org/x/tools/internal/typeparams" ) type intReader struct { @@ -41,6 +43,21 @@ func (r *intReader) uint64() uint64 { return i } +// Keep this in sync with constants in iexport.go. +const ( + iexportVersionGo1_11 = 0 + iexportVersionPosCol = 1 + // TODO: before release, change this back to 2. + iexportVersionGenerics = iexportVersionPosCol + + iexportVersionCurrent = iexportVersionGenerics +) + +type ident struct { + pkg string + name string +} + const predeclReserved = 32 type itag uint64 @@ -56,6 +73,9 @@ const ( signatureType structType interfaceType + typeParamType + instanceType + unionType ) // IImportData imports a package from the serialized package data @@ -78,15 +98,17 @@ func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string) (pkgs []*types.Package, err error) { const currentVersion = 1 version := int64(-1) - defer func() { - if e := recover(); e != nil { - if version > currentVersion { - err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) - } else { - err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) + if !debug { + defer func() { + if e := recover(); e != nil { + if version > currentVersion { + err = fmt.Errorf("cannot import %q (%v), export data is newer version - update tool", path, e) + } else { + err = fmt.Errorf("cannot import %q (%v), possibly version skew - reinstall package", path, e) + } } - } - }() + }() + } r := &intReader{bytes.NewReader(data), path} @@ -101,9 +123,13 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data version = int64(r.uint64()) switch version { - case currentVersion, 0: + case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11: default: - errorf("unknown iexport format version %d", version) + if version > iexportVersionGenerics { + errorf("unstable iexport format version %d, just rebuild compiler and std library", version) + } else { + errorf("unknown iexport format version %d", version) + } } sLen := int64(r.uint64()) @@ -115,8 +141,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data r.Seek(sLen+dLen, io.SeekCurrent) p := iimporter{ - ipath: path, - version: int(version), + exportVersion: version, + ipath: path, + version: int(version), stringData: stringData, stringCache: make(map[uint64]string), @@ -125,6 +152,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data declData: declData, pkgIndex: make(map[*types.Package]map[string]uint64), typCache: make(map[uint64]types.Type), + // Separate map for typeparams, keyed by their package and unique + // name (name with subscript). + tparamIndex: make(map[ident]types.Type), fake: fakeFileSet{ fset: fset, @@ -216,16 +246,18 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data } type iimporter struct { - ipath string - version int + exportVersion int64 + ipath string + version int stringData []byte stringCache map[uint64]string pkgCache map[uint64]*types.Package - declData []byte - pkgIndex map[*types.Package]map[string]uint64 - typCache map[uint64]types.Type + declData []byte + pkgIndex map[*types.Package]map[string]uint64 + typCache map[uint64]types.Type + tparamIndex map[ident]types.Type fake fakeFileSet interfaceList []*types.Interface @@ -315,17 +347,27 @@ func (r *importReader) obj(name string) { r.declare(types.NewConst(pos, r.currPkg, name, typ, val)) - case 'F': + case 'F', 'G': + var tparams []*typeparams.TypeParam + if tag == 'G' { + tparams = r.tparamList() + } sig := r.signature(nil) - + typeparams.SetForSignature(sig, tparams) r.declare(types.NewFunc(pos, r.currPkg, name, sig)) - case 'T': + case 'T', 'U': // Types can be recursive. We need to setup a stub // declaration before recursing. obj := types.NewTypeName(pos, r.currPkg, name, nil) named := types.NewNamed(obj, nil, nil) + // Declare obj before calling r.tparamList, so the new type name is recognized + // if used in the constraint of one of its own typeparams (see #48280). r.declare(obj) + if tag == 'U' { + tparams := r.tparamList() + typeparams.SetForNamed(named, tparams) + } underlying := r.p.typAt(r.uint64(), named).Underlying() named.SetUnderlying(underlying) @@ -337,10 +379,50 @@ func (r *importReader) obj(name string) { recv := r.param() msig := r.signature(recv) + // If the receiver has any targs, set those as the + // rparams of the method (since those are the + // typeparams being used in the method sig/body). + targs := typeparams.NamedTypeArgs(baseType(msig.Recv().Type())) + if targs.Len() > 0 { + rparams := make([]*typeparams.TypeParam, targs.Len()) + for i := range rparams { + // TODO(rfindley): this is less tolerant than the standard library + // go/internal/gcimporter, which calls under(...) and is tolerant + // of nil rparams. Bring them in sync by making the standard + // library importer stricter. + rparams[i] = targs.At(i).(*typeparams.TypeParam) + } + typeparams.SetRecvTypeParams(msig, rparams) + } + named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig)) } } + case 'P': + // We need to "declare" a typeparam in order to have a name that + // can be referenced recursively (if needed) in the type param's + // bound. + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected type param type") + } + name0, sub := parseSubscript(name) + tn := types.NewTypeName(pos, r.currPkg, name0, nil) + t := typeparams.NewTypeParam(tn, nil) + if sub == 0 { + errorf("name %q missing subscript", name) + } + + // TODO(rfindley): can we use a different, stable ID? + // t.SetId(sub) + + // To handle recursive references to the typeparam within its + // bound, save the partial type in tparamIndex before reading the bounds. + id := ident{r.currPkg.Name(), name} + r.p.tparamIndex[id] = t + + typeparams.SetTypeParamConstraint(t, r.typ()) + case 'V': typ := r.typ() @@ -499,7 +581,7 @@ func (r *importReader) qualifiedIdent() (*types.Package, string) { } func (r *importReader) pos() token.Pos { - if r.p.version >= 1 { + if r.p.exportVersion >= iexportVersionPosCol { r.posv1() } else { r.posv0() @@ -618,6 +700,49 @@ func (r *importReader) doType(base *types.Named) types.Type { typ := newInterface(methods, embeddeds) r.p.interfaceList = append(r.p.interfaceList, typ) return typ + + case typeParamType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected type param type") + } + pkg, name := r.qualifiedIdent() + id := ident{pkg.Name(), name} + if t, ok := r.p.tparamIndex[id]; ok { + // We're already in the process of importing this typeparam. + return t + } + // Otherwise, import the definition of the typeparam now. + r.p.doDecl(pkg, name) + return r.p.tparamIndex[id] + + case instanceType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } + // pos does not matter for instances: they are positioned on the original + // type. + _ = r.pos() + len := r.uint64() + targs := make([]types.Type, len) + for i := range targs { + targs[i] = r.typ() + } + baseType := r.typ() + // The imported instantiated type doesn't include any methods, so + // we must always use the methods of the base (orig) type. + // TODO provide a non-nil *Environment + t, _ := typeparams.Instantiate(nil, baseType, targs, false) + return t + + case unionType: + if r.p.exportVersion < iexportVersionGenerics { + errorf("unexpected instantiation type") + } + terms := make([]*typeparams.Term, r.uint64()) + for i := range terms { + terms[i] = typeparams.NewTerm(r.bool(), r.typ()) + } + return typeparams.NewUnion(terms) } } @@ -632,6 +757,20 @@ func (r *importReader) signature(recv *types.Var) *types.Signature { return types.NewSignature(recv, params, results, variadic) } +func (r *importReader) tparamList() []*typeparams.TypeParam { + n := r.uint64() + if n == 0 { + return nil + } + xs := make([]*typeparams.TypeParam, n) + for i := range xs { + // Note: the standard library importer is tolerant of nil types here, + // though would panic in SetTypeParams. + xs[i] = r.typ().(*typeparams.TypeParam) + } + return xs +} + func (r *importReader) paramList() *types.Tuple { xs := make([]*types.Var, r.uint64()) for i := range xs { @@ -674,3 +813,33 @@ func (r *importReader) byte() byte { } return x } + +func baseType(typ types.Type) *types.Named { + // pointer receivers are never types.Named types + if p, _ := typ.(*types.Pointer); p != nil { + typ = p.Elem() + } + // receiver base types are always (possibly generic) types.Named types + n, _ := typ.(*types.Named) + return n +} + +func parseSubscript(name string) (string, uint64) { + // Extract the subscript value from the type param name. We export + // and import the subscript value, so that all type params have + // unique names. + sub := uint64(0) + startsub := -1 + for i, r := range name { + if '₀' <= r && r < '₀'+10 { + if startsub == -1 { + startsub = i + } + sub = sub*10 + uint64(r-'₀') + } + } + if startsub >= 0 { + name = name[:startsub] + } + return name, sub +} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go b/vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go new file mode 100644 index 000000000..817a147ef --- /dev/null +++ b/vendor/golang.org/x/tools/go/internal/gcimporter/support_go117.go @@ -0,0 +1,16 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams || !go1.18 +// +build !typeparams !go1.18 + +package gcimporter + +import "go/types" + +const iexportVersion = iexportVersionGo1_11 + +func additionalPredeclared() []types.Type { + return nil +} diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go b/vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go new file mode 100644 index 000000000..e6b81fc50 --- /dev/null +++ b/vendor/golang.org/x/tools/go/internal/gcimporter/support_go118.go @@ -0,0 +1,20 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams && go1.18 +// +build typeparams,go1.18 + +package gcimporter + +import "go/types" + +const iexportVersion = iexportVersionGenerics + +// additionalPredeclared returns additional predeclared types in go.1.18. +func additionalPredeclared() []types.Type { + return []types.Type{ + // comparable + types.Universe.Lookup("comparable").Type(), + } +} diff --git a/vendor/golang.org/x/tools/go/ssa/builder.go b/vendor/golang.org/x/tools/go/ssa/builder.go index 2d0fdaa4e..e1540dbdc 100644 --- a/vendor/golang.org/x/tools/go/ssa/builder.go +++ b/vendor/golang.org/x/tools/go/ssa/builder.go @@ -579,6 +579,8 @@ func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value { y.pos = e.Lparen case *MakeInterface: y.pos = e.Lparen + case *SliceToArrayPointer: + y.pos = e.Lparen } } return y diff --git a/vendor/golang.org/x/tools/go/ssa/doc.go b/vendor/golang.org/x/tools/go/ssa/doc.go index 1a13640f9..71511bff3 100644 --- a/vendor/golang.org/x/tools/go/ssa/doc.go +++ b/vendor/golang.org/x/tools/go/ssa/doc.go @@ -50,50 +50,51 @@ // Instruction interfaces. The following table shows for each // concrete type which of these interfaces it implements. // -// Value? Instruction? Member? -// *Alloc ✔ ✔ -// *BinOp ✔ ✔ -// *Builtin ✔ -// *Call ✔ ✔ -// *ChangeInterface ✔ ✔ -// *ChangeType ✔ ✔ -// *Const ✔ -// *Convert ✔ ✔ -// *DebugRef ✔ -// *Defer ✔ -// *Extract ✔ ✔ -// *Field ✔ ✔ -// *FieldAddr ✔ ✔ -// *FreeVar ✔ -// *Function ✔ ✔ (func) -// *Global ✔ ✔ (var) -// *Go ✔ -// *If ✔ -// *Index ✔ ✔ -// *IndexAddr ✔ ✔ -// *Jump ✔ -// *Lookup ✔ ✔ -// *MakeChan ✔ ✔ -// *MakeClosure ✔ ✔ -// *MakeInterface ✔ ✔ -// *MakeMap ✔ ✔ -// *MakeSlice ✔ ✔ -// *MapUpdate ✔ -// *NamedConst ✔ (const) -// *Next ✔ ✔ -// *Panic ✔ -// *Parameter ✔ -// *Phi ✔ ✔ -// *Range ✔ ✔ -// *Return ✔ -// *RunDefers ✔ -// *Select ✔ ✔ -// *Send ✔ -// *Slice ✔ ✔ -// *Store ✔ -// *Type ✔ (type) -// *TypeAssert ✔ ✔ -// *UnOp ✔ ✔ +// Value? Instruction? Member? +// *Alloc ✔ ✔ +// *BinOp ✔ ✔ +// *Builtin ✔ +// *Call ✔ ✔ +// *ChangeInterface ✔ ✔ +// *ChangeType ✔ ✔ +// *Const ✔ +// *Convert ✔ ✔ +// *DebugRef ✔ +// *Defer ✔ +// *Extract ✔ ✔ +// *Field ✔ ✔ +// *FieldAddr ✔ ✔ +// *FreeVar ✔ +// *Function ✔ ✔ (func) +// *Global ✔ ✔ (var) +// *Go ✔ +// *If ✔ +// *Index ✔ ✔ +// *IndexAddr ✔ ✔ +// *Jump ✔ +// *Lookup ✔ ✔ +// *MakeChan ✔ ✔ +// *MakeClosure ✔ ✔ +// *MakeInterface ✔ ✔ +// *MakeMap ✔ ✔ +// *MakeSlice ✔ ✔ +// *MapUpdate ✔ +// *NamedConst ✔ (const) +// *Next ✔ ✔ +// *Panic ✔ +// *Parameter ✔ +// *Phi ✔ ✔ +// *Range ✔ ✔ +// *Return ✔ +// *RunDefers ✔ +// *Select ✔ ✔ +// *Send ✔ +// *Slice ✔ ✔ +// *SliceToArrayPointer ✔ ✔ +// *Store ✔ +// *Type ✔ (type) +// *TypeAssert ✔ ✔ +// *UnOp ✔ ✔ // // Other key types in this package include: Program, Package, Function // and BasicBlock. diff --git a/vendor/golang.org/x/tools/go/ssa/emit.go b/vendor/golang.org/x/tools/go/ssa/emit.go index df9ca4ff0..7c8cfdc66 100644 --- a/vendor/golang.org/x/tools/go/ssa/emit.go +++ b/vendor/golang.org/x/tools/go/ssa/emit.go @@ -231,8 +231,8 @@ func emitConv(f *Function, val Value, typ types.Type) Value { // Conversion from slice to array pointer? if slice, ok := ut_src.(*types.Slice); ok { if ptr, ok := ut_dst.(*types.Pointer); ok { - if arr, ok := ptr.Elem().(*types.Array); ok && types.Identical(slice.Elem(), arr.Elem()) { - c := &Convert{X: val} + if arr, ok := ptr.Elem().Underlying().(*types.Array); ok && types.Identical(slice.Elem(), arr.Elem()) { + c := &SliceToArrayPointer{X: val} c.setType(ut_dst) return f.emit(c) } diff --git a/vendor/golang.org/x/tools/go/ssa/print.go b/vendor/golang.org/x/tools/go/ssa/print.go index 3333ba41a..c1b6d22b3 100644 --- a/vendor/golang.org/x/tools/go/ssa/print.go +++ b/vendor/golang.org/x/tools/go/ssa/print.go @@ -159,10 +159,11 @@ func printConv(prefix string, v, x Value) string { relName(x, v.(Instruction))) } -func (v *ChangeType) String() string { return printConv("changetype", v, v.X) } -func (v *Convert) String() string { return printConv("convert", v, v.X) } -func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) } -func (v *MakeInterface) String() string { return printConv("make", v, v.X) } +func (v *ChangeType) String() string { return printConv("changetype", v, v.X) } +func (v *Convert) String() string { return printConv("convert", v, v.X) } +func (v *ChangeInterface) String() string { return printConv("change interface", v, v.X) } +func (v *SliceToArrayPointer) String() string { return printConv("slice to array pointer", v, v.X) } +func (v *MakeInterface) String() string { return printConv("make", v, v.X) } func (v *MakeClosure) String() string { var b bytes.Buffer diff --git a/vendor/golang.org/x/tools/go/ssa/sanity.go b/vendor/golang.org/x/tools/go/ssa/sanity.go index 16df7e4f0..1d4e20f6a 100644 --- a/vendor/golang.org/x/tools/go/ssa/sanity.go +++ b/vendor/golang.org/x/tools/go/ssa/sanity.go @@ -132,14 +132,8 @@ func (s *sanity) checkInstr(idx int, instr Instruction) { case *Call: case *ChangeInterface: case *ChangeType: + case *SliceToArrayPointer: case *Convert: - if _, ok := instr.X.Type().Underlying().(*types.Slice); ok { - if ptr, ok := instr.Type().Underlying().(*types.Pointer); ok { - if _, ok := ptr.Elem().(*types.Array); ok { - break - } - } - } if _, ok := instr.X.Type().Underlying().(*types.Basic); !ok { if _, ok := instr.Type().Underlying().(*types.Basic); !ok { s.errorf("convert %s -> %s: at least one type must be basic", instr.X.Type(), instr.Type()) diff --git a/vendor/golang.org/x/tools/go/ssa/ssa.go b/vendor/golang.org/x/tools/go/ssa/ssa.go index d3faf4438..8358681c7 100644 --- a/vendor/golang.org/x/tools/go/ssa/ssa.go +++ b/vendor/golang.org/x/tools/go/ssa/ssa.go @@ -615,9 +615,10 @@ type ChangeType struct { // - between pointers and unsafe.Pointer. // - between unsafe.Pointer and uintptr. // - from (Unicode) integer to (UTF-8) string. -// - from slice to array pointer. // A conversion may imply a type name change also. // +// This operation cannot fail dynamically. +// // Conversions of untyped string/number/bool constants to a specific // representation are eliminated during SSA construction. // @@ -649,6 +650,20 @@ type ChangeInterface struct { X Value } +// The SliceToArrayPointer instruction yields the conversion of slice X to +// array pointer. +// +// Pos() returns the ast.CallExpr.Lparen, if the instruction arose +// from an explicit conversion in the source. +// +// Example printed form: +// t1 = slice to array pointer *[4]byte <- []byte (t0) +// +type SliceToArrayPointer struct { + register + X Value +} + // MakeInterface constructs an instance of an interface type from a // value of a concrete type. // @@ -1566,6 +1581,10 @@ func (v *Convert) Operands(rands []*Value) []*Value { return append(rands, &v.X) } +func (v *SliceToArrayPointer) Operands(rands []*Value) []*Value { + return append(rands, &v.X) +} + func (s *DebugRef) Operands(rands []*Value) []*Value { return append(rands, &s.X) } diff --git a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go index cffd7acbe..81e8fdcf0 100644 --- a/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go +++ b/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go @@ -58,7 +58,7 @@ type Path string // - The only OT operator is Object.Type, // which we encode as '.' because dot cannot appear in an identifier. // - The TT operators are encoded as [EKPRU]. -// - The OT operators are encoded as [AFMO]; +// - The TO operators are encoded as [AFMO]; // three of these (At,Field,Method) require an integer operand, // which is encoded as a string of decimal digits. // These indices are stable across different representations diff --git a/vendor/golang.org/x/tools/internal/imports/zstdlib.go b/vendor/golang.org/x/tools/internal/imports/zstdlib.go index ccdd4e0ff..7de2be9b4 100644 --- a/vendor/golang.org/x/tools/internal/imports/zstdlib.go +++ b/vendor/golang.org/x/tools/internal/imports/zstdlib.go @@ -180,6 +180,8 @@ var stdlib = map[string][]string{ "NewReader", "NewWriter", "Order", + "Reader", + "Writer", }, "compress/zlib": []string{ "BestCompression", @@ -641,7 +643,9 @@ var stdlib = map[string][]string{ "Named", "NamedArg", "NullBool", + "NullByte", "NullFloat64", + "NullInt16", "NullInt32", "NullInt64", "NullString", @@ -2248,6 +2252,7 @@ var stdlib = map[string][]string{ "SHT_LOOS", "SHT_LOPROC", "SHT_LOUSER", + "SHT_MIPS_ABIFLAGS", "SHT_NOBITS", "SHT_NOTE", "SHT_NULL", @@ -3061,6 +3066,7 @@ var stdlib = map[string][]string{ "ParseExpr", "ParseExprFrom", "ParseFile", + "SkipObjectResolution", "SpuriousErrors", "Trace", }, @@ -3441,6 +3447,7 @@ var stdlib = map[string][]string{ "Pt", "RGBA", "RGBA64", + "RGBA64Image", "Rect", "Rectangle", "RegisterFormat", @@ -3507,6 +3514,7 @@ var stdlib = map[string][]string{ "Op", "Over", "Quantizer", + "RGBA64Image", "Src", }, "image/gif": []string{ @@ -3612,6 +3620,7 @@ var stdlib = map[string][]string{ "FS", "File", "FileInfo", + "FileInfoToDirEntry", "FileMode", "Glob", "GlobFS", @@ -3772,15 +3781,18 @@ var stdlib = map[string][]string{ "Max", "MaxFloat32", "MaxFloat64", + "MaxInt", "MaxInt16", "MaxInt32", "MaxInt64", "MaxInt8", + "MaxUint", "MaxUint16", "MaxUint32", "MaxUint64", "MaxUint8", "Min", + "MinInt", "MinInt16", "MinInt32", "MinInt64", @@ -4078,6 +4090,7 @@ var stdlib = map[string][]string{ "UnknownNetworkError", }, "net/http": []string{ + "AllowQuerySemicolons", "CanonicalHeaderKey", "Client", "CloseNotifier", @@ -4660,6 +4673,7 @@ var stdlib = map[string][]string{ "Value", "ValueError", "ValueOf", + "VisibleFields", "Zero", }, "regexp": []string{ @@ -4799,6 +4813,10 @@ var stdlib = map[string][]string{ "UnlockOSThread", "Version", }, + "runtime/cgo": []string{ + "Handle", + "NewHandle", + }, "runtime/debug": []string{ "BuildInfo", "FreeOSMemory", @@ -4915,6 +4933,7 @@ var stdlib = map[string][]string{ "QuoteRuneToGraphic", "QuoteToASCII", "QuoteToGraphic", + "QuotedPrefix", "Unquote", "UnquoteChar", }, @@ -10334,6 +10353,7 @@ var stdlib = map[string][]string{ "PipeNode", "Pos", "RangeNode", + "SkipFuncCheck", "StringNode", "TemplateNode", "TextNode", @@ -10358,6 +10378,7 @@ var stdlib = map[string][]string{ "July", "June", "Kitchen", + "Layout", "LoadLocation", "LoadLocationFromTZData", "Local", @@ -10406,6 +10427,8 @@ var stdlib = map[string][]string{ "UTC", "Unix", "UnixDate", + "UnixMicro", + "UnixMilli", "Until", "Wednesday", "Weekday", diff --git a/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go b/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go index ac377035e..c1038163f 100644 --- a/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go +++ b/vendor/golang.org/x/tools/internal/lsp/fuzzy/input.go @@ -27,23 +27,23 @@ const ( // RuneRoles detects the roles of each byte rune in an input string and stores it in the output // slice. The rune role depends on the input type. Stops when it parsed all the runes in the string // or when it filled the output. If output is nil, then it gets created. -func RuneRoles(str string, reuse []RuneRole) []RuneRole { +func RuneRoles(candidate []byte, reuse []RuneRole) []RuneRole { var output []RuneRole - if cap(reuse) < len(str) { - output = make([]RuneRole, 0, len(str)) + if cap(reuse) < len(candidate) { + output = make([]RuneRole, 0, len(candidate)) } else { output = reuse[:0] } prev, prev2 := rtNone, rtNone - for i := 0; i < len(str); i++ { - r := rune(str[i]) + for i := 0; i < len(candidate); i++ { + r := rune(candidate[i]) role := RNone curr := rtLower - if str[i] <= unicode.MaxASCII { - curr = runeType(rt[str[i]] - '0') + if candidate[i] <= unicode.MaxASCII { + curr = runeType(rt[candidate[i]] - '0') } if curr == rtLower { @@ -58,7 +58,7 @@ func RuneRoles(str string, reuse []RuneRole) []RuneRole { if prev == rtUpper { // This and previous characters are both upper case. - if i+1 == len(str) { + if i+1 == len(candidate) { // This is last character, previous was also uppercase -> this is UCTail // i.e., (current char is C): aBC / BC / ABC role = RUCTail @@ -118,11 +118,26 @@ func LastSegment(input string, roles []RuneRole) string { return input[start+1 : end+1] } -// ToLower transforms the input string to lower case, which is stored in the output byte slice. +// fromChunks copies string chunks into the given buffer. +func fromChunks(chunks []string, buffer []byte) []byte { + ii := 0 + for _, chunk := range chunks { + for i := 0; i < len(chunk); i++ { + if ii >= cap(buffer) { + break + } + buffer[ii] = chunk[i] + ii++ + } + } + return buffer[:ii] +} + +// toLower transforms the input string to lower case, which is stored in the output byte slice. // The lower casing considers only ASCII values - non ASCII values are left unmodified. // Stops when parsed all input or when it filled the output slice. If output is nil, then it gets // created. -func ToLower(input string, reuse []byte) []byte { +func toLower(input []byte, reuse []byte) []byte { output := reuse if cap(reuse) < len(input) { output = make([]byte, len(input)) @@ -130,7 +145,7 @@ func ToLower(input string, reuse []byte) []byte { for i := 0; i < len(input); i++ { r := rune(input[i]) - if r <= unicode.MaxASCII { + if input[i] <= unicode.MaxASCII { if 'A' <= r && r <= 'Z' { r += 'a' - 'A' } diff --git a/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go b/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go index 16a643097..265cdcf16 100644 --- a/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go +++ b/vendor/golang.org/x/tools/internal/lsp/fuzzy/matcher.go @@ -51,8 +51,12 @@ type Matcher struct { lastCandidateLen int // in bytes lastCandidateMatched bool - // Here we save the last candidate in lower-case. This is basically a byte slice we reuse for - // performance reasons, so the slice is not reallocated for every candidate. + // Reusable buffers to avoid allocating for every candidate. + // - inputBuf stores the concatenated input chunks + // - lowerBuf stores the last candidate in lower-case + // - rolesBuf stores the calculated roles for each rune in the last + // candidate. + inputBuf [MaxInputSize]byte lowerBuf [MaxInputSize]byte rolesBuf [MaxInputSize]RuneRole } @@ -72,7 +76,7 @@ func NewMatcher(pattern string) *Matcher { m := &Matcher{ pattern: pattern, - patternLower: ToLower(pattern, nil), + patternLower: toLower([]byte(pattern), nil), } for i, c := range m.patternLower { @@ -88,7 +92,7 @@ func NewMatcher(pattern string) *Matcher { m.patternShort = m.patternLower } - m.patternRoles = RuneRoles(pattern, nil) + m.patternRoles = RuneRoles([]byte(pattern), nil) if len(pattern) > 0 { maxCharScore := 4 @@ -102,10 +106,15 @@ func NewMatcher(pattern string) *Matcher { // This is not designed for parallel use. Multiple candidates must be scored sequentially. // Returns a score between 0 and 1 (0 - no match, 1 - perfect match). func (m *Matcher) Score(candidate string) float32 { + return m.ScoreChunks([]string{candidate}) +} + +func (m *Matcher) ScoreChunks(chunks []string) float32 { + candidate := fromChunks(chunks, m.inputBuf[:]) if len(candidate) > MaxInputSize { candidate = candidate[:MaxInputSize] } - lower := ToLower(candidate, m.lowerBuf[:]) + lower := toLower(candidate, m.lowerBuf[:]) m.lastCandidateLen = len(candidate) if len(m.pattern) == 0 { @@ -174,7 +183,7 @@ func (m *Matcher) MatchedRanges() []int { return ret } -func (m *Matcher) match(candidate string, candidateLower []byte) bool { +func (m *Matcher) match(candidate []byte, candidateLower []byte) bool { i, j := 0, 0 for ; i < len(candidateLower) && j < len(m.patternLower); i++ { if candidateLower[i] == m.patternLower[j] { @@ -192,7 +201,7 @@ func (m *Matcher) match(candidate string, candidateLower []byte) bool { return true } -func (m *Matcher) computeScore(candidate string, candidateLower []byte) int { +func (m *Matcher) computeScore(candidate []byte, candidateLower []byte) int { pattLen, candLen := len(m.pattern), len(candidate) for j := 0; j <= len(m.pattern); j++ { diff --git a/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go b/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go new file mode 100644 index 000000000..062f491fb --- /dev/null +++ b/vendor/golang.org/x/tools/internal/lsp/fuzzy/symbol.go @@ -0,0 +1,224 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package fuzzy + +import ( + "unicode" +) + +// SymbolMatcher implements a fuzzy matching algorithm optimized for Go symbols +// of the form: +// example.com/path/to/package.object.field +// +// Knowing that we are matching symbols like this allows us to make the +// following optimizations: +// - We can incorporate right-to-left relevance directly into the score +// calculation. +// - We can match from right to left, discarding leading bytes if the input is +// too long. +// - We just take the right-most match without losing too much precision. This +// allows us to use an O(n) algorithm. +// - We can operate directly on chunked strings; in many cases we will +// be storing the package path and/or package name separately from the +// symbol or identifiers, so doing this avoids allocating strings. +// - We can return the index of the right-most match, allowing us to trim +// irrelevant qualification. +// +// This implementation is experimental, serving as a reference fast algorithm +// to compare to the fuzzy algorithm implemented by Matcher. +type SymbolMatcher struct { + // Using buffers of length 256 is both a reasonable size for most qualified + // symbols, and makes it easy to avoid bounds checks by using uint8 indexes. + pattern [256]rune + patternLen uint8 + inputBuffer [256]rune // avoid allocating when considering chunks + roles [256]uint32 // which roles does a rune play (word start, etc.) + segments [256]uint8 // how many segments from the right is each rune +} + +const ( + segmentStart uint32 = 1 << iota + wordStart + separator +) + +// NewSymbolMatcher creates a SymbolMatcher that may be used to match the given +// search pattern. +// +// Currently this matcher only accepts case-insensitive fuzzy patterns. +// +// TODO(rfindley): +// - implement smart-casing +// - implement space-separated groups +// - implement ', ^, and $ modifiers +// +// An empty pattern matches no input. +func NewSymbolMatcher(pattern string) *SymbolMatcher { + m := &SymbolMatcher{} + for _, p := range pattern { + m.pattern[m.patternLen] = unicode.ToLower(p) + m.patternLen++ + if m.patternLen == 255 || int(m.patternLen) == len(pattern) { + // break at 255 so that we can represent patternLen with a uint8. + break + } + } + return m +} + +// Match looks for the right-most match of the search pattern within the symbol +// represented by concatenating the given chunks, returning its offset and +// score. +// +// If a match is found, the first return value will hold the absolute byte +// offset within all chunks for the start of the symbol. In other words, the +// index of the match within strings.Join(chunks, ""). If no match is found, +// the first return value will be -1. +// +// The second return value will be the score of the match, which is always +// between 0 and 1, inclusive. A score of 0 indicates no match. +func (m *SymbolMatcher) Match(chunks []string) (int, float64) { + // Explicit behavior for an empty pattern. + // + // As a minor optimization, this also avoids nilness checks later on, since + // the compiler can prove that m != nil. + if m.patternLen == 0 { + return -1, 0 + } + + // First phase: populate the input buffer with lower-cased runes. + // + // We could also check for a forward match here, but since we'd have to write + // the entire input anyway this has negligible impact on performance. + + var ( + inputLen = uint8(0) + modifiers = wordStart | segmentStart + ) + +input: + for _, chunk := range chunks { + for _, r := range chunk { + if r == '.' || r == '/' { + modifiers |= separator + } + // optimization: avoid calls to unicode.ToLower, which can't be inlined. + l := r + if r <= unicode.MaxASCII { + if 'A' <= r && r <= 'Z' { + l = r + 'a' - 'A' + } + } else { + l = unicode.ToLower(r) + } + if l != r { + modifiers |= wordStart + } + m.inputBuffer[inputLen] = l + m.roles[inputLen] = modifiers + inputLen++ + if m.roles[inputLen-1]&separator != 0 { + modifiers = wordStart | segmentStart + } else { + modifiers = 0 + } + // TODO: we should prefer the right-most input if it overflows, rather + // than the left-most as we're doing here. + if inputLen == 255 { + break input + } + } + } + + // Second phase: find the right-most match, and count segments from the + // right. + + var ( + pi = uint8(m.patternLen - 1) // pattern index + p = m.pattern[pi] // pattern rune + start = -1 // start offset of match + rseg = uint8(0) + ) + const maxSeg = 3 // maximum number of segments from the right to count, for scoring purposes. + + for ii := inputLen - 1; ; ii-- { + r := m.inputBuffer[ii] + if rseg < maxSeg && m.roles[ii]&separator != 0 { + rseg++ + } + m.segments[ii] = rseg + if p == r { + if pi == 0 { + start = int(ii) + break + } + pi-- + p = m.pattern[pi] + } + // Don't check ii >= 0 in the loop condition: ii is a uint8. + if ii == 0 { + break + } + } + + if start < 0 { + // no match: skip scoring + return -1, 0 + } + + // Third phase: find the shortest match, and compute the score. + + // Score is the average score for each character. + // + // A character score is the multiple of: + // 1. 1.0 if the character starts a segment, .8 if the character start a + // mid-segment word, otherwise 0.6. This carries over to immediately + // following characters. + // 2. 1.0 if the character is part of the last segment, otherwise + // 1.0-.2*, with a max segment count of 3. + // + // This is a very naive algorithm, but it is fast. There's lots of prior art + // here, and we should leverage it. For example, we could explicitly consider + // character distance, and exact matches of words or segments. + // + // Also note that this might not actually find the highest scoring match, as + // doing so could require a non-linear algorithm, depending on how the score + // is calculated. + + pi = 0 + p = m.pattern[pi] + + const ( + segStreak = 1.0 + wordStreak = 0.8 + noStreak = 0.6 + perSegment = 0.2 // we count at most 3 segments above + ) + + streakBonus := noStreak + totScore := 0.0 + for ii := uint8(start); ii < inputLen; ii++ { + r := m.inputBuffer[ii] + if r == p { + pi++ + p = m.pattern[pi] + // Note: this could be optimized with some bit operations. + switch { + case m.roles[ii]&segmentStart != 0 && segStreak > streakBonus: + streakBonus = segStreak + case m.roles[ii]&wordStart != 0 && wordStreak > streakBonus: + streakBonus = wordStreak + } + totScore += streakBonus * (1.0 - float64(m.segments[ii])*perSegment) + if pi >= m.patternLen { + break + } + } else { + streakBonus = noStreak + } + } + + return start, totScore / float64(m.patternLen) +} diff --git a/vendor/golang.org/x/tools/internal/typeparams/doc.go b/vendor/golang.org/x/tools/internal/typeparams/common.go similarity index 59% rename from vendor/golang.org/x/tools/internal/typeparams/doc.go rename to vendor/golang.org/x/tools/internal/typeparams/common.go index 5583947e2..9fc6b4beb 100644 --- a/vendor/golang.org/x/tools/internal/typeparams/doc.go +++ b/vendor/golang.org/x/tools/internal/typeparams/common.go @@ -9,3 +9,17 @@ // This package exists to make it easier for tools to work with generic code, // while also compiling against older Go versions. package typeparams + +import ( + "go/ast" + "go/token" +) + +// A IndexExprData holds data from both ast.IndexExpr and the new +// ast.MultiIndexExpr, which was introduced in Go 1.18. +type IndexExprData struct { + X ast.Expr // expression + Lbrack token.Pos // position of "[" + Indices []ast.Expr // index expressions + Rbrack token.Pos // position of "]" +} diff --git a/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go b/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go new file mode 100644 index 000000000..72d010e51 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/enabled_go117.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams || !go1.18 +// +build !typeparams !go1.18 + +package typeparams + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = false diff --git a/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go b/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go new file mode 100644 index 000000000..642fc8ee2 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/enabled_go118.go @@ -0,0 +1,15 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams && go1.18 +// +build typeparams,go1.18 + +package typeparams + +// Note: this constant is in a separate file as this is the only acceptable +// diff between the <1.18 API of this package and the 1.18 API. + +// Enabled reports whether type parameters are enabled in the current build +// environment. +const Enabled = true diff --git a/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go b/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go deleted file mode 100644 index 3a0abc7c1..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/notypeparams.go +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !typeparams || !go1.17 -// +build !typeparams !go1.17 - -package typeparams - -import ( - "go/ast" - "go/types" -) - -// NOTE: doc comments must be kept in sync with typeparams.go. - -// Enabled reports whether type parameters are enabled in the current build -// environment. -const Enabled = false - -// UnpackIndex extracts all index expressions from e. For non-generic code this -// is always one expression: e.Index, but may be more than one expression for -// generic type instantiation. -func UnpackIndex(e *ast.IndexExpr) []ast.Expr { - return []ast.Expr{e.Index} -} - -// IsListExpr reports whether n is an *ast.ListExpr, which is a new node type -// introduced to hold type arguments for generic type instantiation. -func IsListExpr(n ast.Node) bool { - return false -} - -// ForTypeDecl extracts the (possibly nil) type parameter node list from n. -func ForTypeDecl(*ast.TypeSpec) *ast.FieldList { - return nil -} - -// ForFuncDecl extracts the (possibly nil) type parameter node list from n. -func ForFuncDecl(*ast.FuncDecl) *ast.FieldList { - return nil -} - -// ForSignature extracts the (possibly empty) type parameter object list from -// sig. -func ForSignature(*types.Signature) []*types.TypeName { - return nil -} - -// HasTypeSet reports if iface has a type set. -func HasTypeSet(*types.Interface) bool { - return false -} - -// IsComparable reports if iface is the comparable interface. -func IsComparable(*types.Interface) bool { - return false -} - -// IsConstraint reports whether iface may only be used as a type parameter -// constraint (i.e. has a type set or is the comparable interface). -func IsConstraint(*types.Interface) bool { - return false -} - -// ForNamed extracts the (possibly empty) type parameter object list from -// named. -func ForNamed(*types.Named) []*types.TypeName { - return nil -} - -// NamedTArgs extracts the (possibly empty) type argument list from named. -func NamedTArgs(*types.Named) []types.Type { - return nil -} - -// InitInferred initializes info to record inferred type information. -func InitInferred(*types.Info) { -} - -// GetInferred extracts inferred type information from info for e. -// -// The expression e may have an inferred type if it is an *ast.IndexExpr -// representing partial instantiation of a generic function type for which type -// arguments have been inferred using constraint type inference, or if it is an -// *ast.CallExpr for which type type arguments have be inferred using both -// constraint type inference and function argument inference. -func GetInferred(*types.Info, ast.Expr) ([]types.Type, *types.Signature) { - return nil, nil -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeparams.go b/vendor/golang.org/x/tools/internal/typeparams/typeparams.go deleted file mode 100644 index 6b7958af0..000000000 --- a/vendor/golang.org/x/tools/internal/typeparams/typeparams.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2021 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build typeparams && go1.17 -// +build typeparams,go1.17 - -package typeparams - -import ( - "go/ast" - "go/types" -) - -// NOTE: doc comments must be kept in sync with notypeparams.go. - -// Enabled reports whether type parameters are enabled in the current build -// environment. -const Enabled = true - -// UnpackIndex extracts all index expressions from e. For non-generic code this -// is always one expression: e.Index, but may be more than one expression for -// generic type instantiation. -func UnpackIndex(e *ast.IndexExpr) []ast.Expr { - if x, _ := e.Index.(*ast.ListExpr); x != nil { - return x.ElemList - } - if e.Index != nil { - return []ast.Expr{e.Index} - } - return nil -} - -// IsListExpr reports whether n is an *ast.ListExpr, which is a new node type -// introduced to hold type arguments for generic type instantiation. -func IsListExpr(n ast.Node) bool { - _, ok := n.(*ast.ListExpr) - return ok -} - -// ForTypeDecl extracts the (possibly nil) type parameter node list from n. -func ForTypeDecl(n *ast.TypeSpec) *ast.FieldList { - return n.TParams -} - -// ForFuncDecl extracts the (possibly nil) type parameter node list from n. -func ForFuncDecl(n *ast.FuncDecl) *ast.FieldList { - if n.Type != nil { - return n.Type.TParams - } - return nil -} - -// ForSignature extracts the (possibly empty) type parameter object list from -// sig. -func ForSignature(sig *types.Signature) []*types.TypeName { - return sig.TParams() -} - -// HasTypeSet reports if iface has a type set. -func HasTypeSet(iface *types.Interface) bool { - return iface.HasTypeList() -} - -// IsComparable reports if iface is the comparable interface. -func IsComparable(iface *types.Interface) bool { - return iface.IsComparable() -} - -// IsConstraint reports whether iface may only be used as a type parameter -// constraint (i.e. has a type set or is the comparable interface). -func IsConstraint(iface *types.Interface) bool { - return iface.IsConstraint() -} - -// ForNamed extracts the (possibly empty) type parameter object list from -// named. -func ForNamed(named *types.Named) []*types.TypeName { - return named.TParams() -} - -// NamedTArgs extracts the (possibly empty) type argument list from named. -func NamedTArgs(named *types.Named) []types.Type { - return named.TArgs() -} - -// InitInferred initializes info to record inferred type information. -func InitInferred(info *types.Info) { - info.Inferred = make(map[ast.Expr]types.Inferred) -} - -// GetInferred extracts inferred type information from info for e. -// -// The expression e may have an inferred type if it is an *ast.IndexExpr -// representing partial instantiation of a generic function type for which type -// arguments have been inferred using constraint type inference, or if it is an -// *ast.CallExpr for which type type arguments have be inferred using both -// constraint type inference and function argument inference. -func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) { - if info.Inferred == nil { - return nil, nil - } - inf := info.Inferred[e] - return inf.TArgs, inf.Sig -} diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go b/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go new file mode 100644 index 000000000..12817af85 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go @@ -0,0 +1,177 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !typeparams || !go1.18 +// +build !typeparams !go1.18 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +func unsupported() { + panic("type parameters are unsupported at this go version") +} + +// GetIndexExprData extracts data from *ast.IndexExpr nodes. +// For other nodes, GetIndexExprData returns nil. +func GetIndexExprData(n ast.Node) *IndexExprData { + if e, _ := n.(*ast.IndexExpr); e != nil { + return &IndexExprData{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + } + } + return nil +} + +// ForTypeSpec returns an empty field list, as type parameters on not supported +// at this Go version. +func ForTypeSpec(*ast.TypeSpec) *ast.FieldList { + return nil +} + +// ForFuncType returns an empty field list, as type parameters are not +// supported at this Go version. +func ForFuncType(*ast.FuncType) *ast.FieldList { + return nil +} + +// TypeParam is a placeholder type, as type parameters are not supported at +// this Go version. Its methods panic on use. +type TypeParam struct{ types.Type } + +func (*TypeParam) Constraint() types.Type { unsupported(); return nil } +func (*TypeParam) Obj() *types.TypeName { unsupported(); return nil } + +// TypeParamList is a placeholder for an empty type parameter list. +type TypeParamList struct{} + +func (*TypeParamList) Len() int { return 0 } +func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil } + +// TypeList is a placeholder for an empty type list. +type TypeList struct{} + +func (*TypeList) Len() int { return 0 } +func (*TypeList) At(int) types.Type { unsupported(); return nil } + +// NewTypeParam is unsupported at this Go version, and panics. +func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { + unsupported() + return nil +} + +// SetTypeParamConstraint is unsupported at this Go version, and panics. +func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { + unsupported() +} + +// ForSignature returns an empty slice. +func ForSignature(*types.Signature) *TypeParamList { + return nil +} + +// SetForSignature panics if tparams is non-empty. +func SetForSignature(_ *types.Signature, tparams []*TypeParam) { + if len(tparams) > 0 { + unsupported() + } +} + +// RecvTypeParams returns a nil slice. +func RecvTypeParams(sig *types.Signature) *TypeParamList { + return nil +} + +// SetRecvTypeParams panics if rparams is non-empty. +func SetRecvTypeParams(sig *types.Signature, rparams []*TypeParam) { + if len(rparams) > 0 { + unsupported() + } +} + +// IsComparable returns false, as no interfaces are type-restricted at this Go +// version. +func IsComparable(*types.Interface) bool { + return false +} + +// IsConstraint returns false, as no interfaces are type-restricted at this Go +// version. +func IsConstraint(*types.Interface) bool { + return false +} + +// ForNamed returns an empty type parameter list, as type parameters are not +// supported at this Go version. +func ForNamed(*types.Named) *TypeParamList { + return nil +} + +// SetForNamed panics if tparams is non-empty. +func SetForNamed(_ *types.Named, tparams []*TypeParam) { + if len(tparams) > 0 { + unsupported() + } +} + +// NamedTypeArgs returns nil. +func NamedTypeArgs(*types.Named) *TypeList { + return nil +} + +// NamedTypeOrigin is the identity method at this Go version. +func NamedTypeOrigin(named *types.Named) types.Type { + return named +} + +// Term is a placeholder type, as type parameters are not supported at this Go +// version. Its methods panic on use. +type Term struct{} + +func (*Term) Tilde() bool { unsupported(); return false } +func (*Term) Type() types.Type { unsupported(); return nil } +func (*Term) String() string { unsupported(); return "" } +func (*Term) Underlying() types.Type { unsupported(); return nil } + +// NewTerm is unsupported at this Go version, and panics. +func NewTerm(tilde bool, typ types.Type) *Term { + unsupported() + return nil +} + +// Union is a placeholder type, as type parameters are not supported at this Go +// version. Its methods panic on use. +type Union struct{ types.Type } + +func (*Union) Len() int { return 0 } +func (*Union) Term(i int) *Term { unsupported(); return nil } + +// NewUnion is unsupported at this Go version, and panics. +func NewUnion(terms []*Term) *Union { + unsupported() + return nil +} + +// InitInstanceInfo is a noop at this Go version. +func InitInstanceInfo(*types.Info) {} + +// GetInstance returns nothing, as type parameters are not supported at this Go +// version. +func GetInstance(*types.Info, *ast.Ident) (*TypeList, types.Type) { return nil, nil } + +// Environment is a placeholder type, as type parameters are not supported at +// this Go version. +type Environment struct{} + +// Instantiate is unsupported on this Go version, and panics. +func Instantiate(env *Environment, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { + unsupported() + return nil, nil +} diff --git a/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go b/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go new file mode 100644 index 000000000..8ab17b777 --- /dev/null +++ b/vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go @@ -0,0 +1,165 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build typeparams && go1.18 +// +build typeparams,go1.18 + +package typeparams + +import ( + "go/ast" + "go/types" +) + +// GetIndexExprData extracts data from AST nodes that represent index +// expressions. +// +// For an ast.IndexExpr, the resulting IndexExprData will have exactly one +// index expression. For an ast.IndexListExpr (go1.18+), it may have a +// variable number of index expressions. +// +// For nodes that don't represent index expressions, GetIndexExprData returns +// nil. +func GetIndexExprData(n ast.Node) *IndexExprData { + switch e := n.(type) { + case *ast.IndexExpr: + return &IndexExprData{ + X: e.X, + Lbrack: e.Lbrack, + Indices: []ast.Expr{e.Index}, + Rbrack: e.Rbrack, + } + case *ast.IndexListExpr: + return (*IndexExprData)(e) + } + return nil +} + +// ForTypeSpec returns n.TypeParams. +func ForTypeSpec(n *ast.TypeSpec) *ast.FieldList { + if n == nil { + return nil + } + return n.TypeParams +} + +// ForFuncType returns n.TypeParams. +func ForFuncType(n *ast.FuncType) *ast.FieldList { + if n == nil { + return nil + } + return n.TypeParams +} + +// TypeParam is an alias for types.TypeParam +type TypeParam = types.TypeParam + +// TypeParamList is an alias for types.TypeParamList +type TypeParamList = types.TypeParamList + +// TypeList is an alias for types.TypeList +type TypeList = types.TypeList + +// NewTypeParam calls types.NewTypeParam. +func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam { + return types.NewTypeParam(name, constraint) +} + +// SetTypeParamConstraint calls tparam.SetConstraint(constraint). +func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) { + tparam.SetConstraint(constraint) +} + +// ForSignature returns sig.TypeParams() +func ForSignature(sig *types.Signature) *TypeParamList { + return sig.TypeParams() +} + +// SetForSignature calls sig.SetTypeParams(tparams) +func SetForSignature(sig *types.Signature, tparams []*TypeParam) { + sig.SetTypeParams(tparams) +} + +// RecvTypeParams returns sig.RecvTypeParams(). +func RecvTypeParams(sig *types.Signature) *TypeParamList { + return sig.RecvTypeParams() +} + +// SetRecvTypeParams calls sig.SetRecvTypeParams(rparams). +func SetRecvTypeParams(sig *types.Signature, rparams []*TypeParam) { + sig.SetRecvTypeParams(rparams) +} + +// IsComparable calls iface.IsComparable(). +func IsComparable(iface *types.Interface) bool { + return iface.IsComparable() +} + +// IsConstraint calls iface.IsConstraint(). +func IsConstraint(iface *types.Interface) bool { + return iface.IsConstraint() +} + +// ForNamed extracts the (possibly empty) type parameter object list from +// named. +func ForNamed(named *types.Named) *TypeParamList { + return named.TypeParams() +} + +// SetForNamed sets the type params tparams on n. Each tparam must be of +// dynamic type *types.TypeParam. +func SetForNamed(n *types.Named, tparams []*TypeParam) { + n.SetTypeParams(tparams) +} + +// NamedTypeArgs returns named.TypeArgs(). +func NamedTypeArgs(named *types.Named) *TypeList { + return named.TypeArgs() +} + +// NamedTypeOrigin returns named.Orig(). +func NamedTypeOrigin(named *types.Named) types.Type { + return named.Origin() +} + +// Term is an alias for types.Term. +type Term = types.Term + +// NewTerm calls types.NewTerm. +func NewTerm(tilde bool, typ types.Type) *Term { + return types.NewTerm(tilde, typ) +} + +// Union is an alias for types.Union +type Union = types.Union + +// NewUnion calls types.NewUnion. +func NewUnion(terms []*Term) *Union { + return types.NewUnion(terms) +} + +// InitInstanceInfo initializes info to record information about type and +// function instances. +func InitInstanceInfo(info *types.Info) { + info.Instances = make(map[*ast.Ident]types.Instance) +} + +// GetInstance extracts information about the instantiation occurring at the +// identifier id. id should be the identifier denoting a parameterized type or +// function in an instantiation expression or function call. +func GetInstance(info *types.Info, id *ast.Ident) (*TypeList, types.Type) { + if info.Instances != nil { + inf := info.Instances[id] + return inf.TypeArgs, inf.Type + } + return nil, nil +} + +// Environment is an alias for types.Environment. +type Environment = types.Environment + +// Instantiate calls types.Instantiate. +func Instantiate(env *Environment, typ types.Type, targs []types.Type, validate bool) (types.Type, error) { + return types.Instantiate(env, typ, targs, validate) +} diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go index c3e1a397d..7c77c2fbc 100644 --- a/vendor/golang.org/x/tools/internal/typesinternal/types.go +++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go @@ -30,10 +30,15 @@ func SetUsesCgo(conf *types.Config) bool { return true } -func ReadGo116ErrorData(terr types.Error) (ErrorCode, token.Pos, token.Pos, bool) { +// ReadGo116ErrorData extracts additional information from types.Error values +// generated by Go version 1.16 and later: the error code, start position, and +// end position. If all positions are valid, start <= err.Pos <= end. +// +// If the data could not be read, the final result parameter will be false. +func ReadGo116ErrorData(err types.Error) (code ErrorCode, start, end token.Pos, ok bool) { var data [3]int // By coincidence all of these fields are ints, which simplifies things. - v := reflect.ValueOf(terr) + v := reflect.ValueOf(err) for i, name := range []string{"go116code", "go116start", "go116end"} { f := v.FieldByName(name) if !f.IsValid() { diff --git a/vendor/gopkg.in/ini.v1/.golangci.yml b/vendor/gopkg.in/ini.v1/.golangci.yml new file mode 100644 index 000000000..b7256bae1 --- /dev/null +++ b/vendor/gopkg.in/ini.v1/.golangci.yml @@ -0,0 +1,21 @@ +linters-settings: + nakedret: + max-func-lines: 0 # Disallow any unnamed return statement + +linters: + enable: + - deadcode + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - structcheck + - typecheck + - unused + - varcheck + - nakedret + - gofmt + - rowserrcheck + - unconvert + - goimports diff --git a/vendor/gopkg.in/ini.v1/codecov.yml b/vendor/gopkg.in/ini.v1/codecov.yml index fc947f230..31f646ee0 100644 --- a/vendor/gopkg.in/ini.v1/codecov.yml +++ b/vendor/gopkg.in/ini.v1/codecov.yml @@ -6,4 +6,4 @@ coverage: threshold: 1% comment: - layout: 'diff, files' + layout: 'diff' diff --git a/vendor/gopkg.in/ini.v1/ini.go b/vendor/gopkg.in/ini.v1/ini.go index 23f07422e..ac2a93a5b 100644 --- a/vendor/gopkg.in/ini.v1/ini.go +++ b/vendor/gopkg.in/ini.v1/ini.go @@ -1,5 +1,3 @@ -// +build go1.6 - // Copyright 2014 Unknwon // // Licensed under the Apache License, Version 2.0 (the "License"): you may @@ -125,6 +123,8 @@ type LoadOptions struct { ReaderBufferSize int // AllowNonUniqueSections indicates whether to allow sections with the same name multiple times. AllowNonUniqueSections bool + // AllowDuplicateShadowValues indicates whether values for shadowed keys should be deduplicated. + AllowDuplicateShadowValues bool } // DebugFunc is the type of function called to log parse events. diff --git a/vendor/gopkg.in/ini.v1/key.go b/vendor/gopkg.in/ini.v1/key.go index 8baafd9ea..0302c291b 100644 --- a/vendor/gopkg.in/ini.v1/key.go +++ b/vendor/gopkg.in/ini.v1/key.go @@ -54,14 +54,16 @@ func (k *Key) addShadow(val string) error { return errors.New("cannot add shadow to auto-increment or boolean key") } - // Deduplicate shadows based on their values. - if k.value == val { - return nil - } - for i := range k.shadows { - if k.shadows[i].value == val { + if !k.s.f.options.AllowDuplicateShadowValues { + // Deduplicate shadows based on their values. + if k.value == val { return nil } + for i := range k.shadows { + if k.shadows[i].value == val { + return nil + } + } } shadow := newKey(k.s, k.name, val) @@ -781,10 +783,8 @@ func (k *Key) parseUint64s(strs []string, addInvalid, returnOnInvalid bool) ([]u return vals, err } - type Parser func(str string) (interface{}, error) - // parseTimesFormat transforms strings to times in given format. func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnOnInvalid bool) ([]time.Time, error) { vals := make([]time.Time, 0, len(strs)) @@ -801,7 +801,6 @@ func (k *Key) parseTimesFormat(format string, strs []string, addInvalid, returnO return vals, err } - // doParse transforms strings to different types func (k *Key) doParse(strs []string, addInvalid, returnOnInvalid bool, parser Parser) ([]interface{}, error) { vals := make([]interface{}, 0, len(strs)) diff --git a/vendor/gopkg.in/ini.v1/parser.go b/vendor/gopkg.in/ini.v1/parser.go index 65147166f..b8b5aa86a 100644 --- a/vendor/gopkg.in/ini.v1/parser.go +++ b/vendor/gopkg.in/ini.v1/parser.go @@ -131,7 +131,7 @@ func readKeyName(delimiters string, in []byte) (string, int, error) { // Check if key name surrounded by quotes. var keyQuote string if line[0] == '"' { - if len(line) > 6 && string(line[0:3]) == `"""` { + if len(line) > 6 && line[0:3] == `"""` { keyQuote = `"""` } else { keyQuote = `"` @@ -232,7 +232,7 @@ func (p *parser) readValue(in []byte, bufferSize int) (string, error) { } var valQuote string - if len(line) > 3 && string(line[0:3]) == `"""` { + if len(line) > 3 && line[0:3] == `"""` { valQuote = `"""` } else if line[0] == '`' { valQuote = "`" @@ -289,12 +289,8 @@ func (p *parser) readValue(in []byte, bufferSize int) (string, error) { hasSurroundedQuote(line, '"')) && !p.options.PreserveSurroundedQuote { line = line[1 : len(line)-1] } else if len(valQuote) == 0 && p.options.UnescapeValueCommentSymbols { - if strings.Contains(line, `\;`) { - line = strings.Replace(line, `\;`, ";", -1) - } - if strings.Contains(line, `\#`) { - line = strings.Replace(line, `\#`, "#", -1) - } + line = strings.ReplaceAll(line, `\;`, ";") + line = strings.ReplaceAll(line, `\#`, "#") } else if p.options.AllowPythonMultilineValues && lastChar == '\n' { return p.readPythonMultilines(line, bufferSize) } diff --git a/vendor/gopkg.in/ini.v1/section.go b/vendor/gopkg.in/ini.v1/section.go index afaa97c97..a3615d820 100644 --- a/vendor/gopkg.in/ini.v1/section.go +++ b/vendor/gopkg.in/ini.v1/section.go @@ -217,7 +217,7 @@ func (s *Section) KeysHash() map[string]string { defer s.f.lock.RUnlock() } - hash := map[string]string{} + hash := make(map[string]string, len(s.keysHash)) for key, value := range s.keysHash { hash[key] = value } diff --git a/vendor/modules.txt b/vendor/modules.txt index c7345cb1a..f41ae35a3 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,10 +1,12 @@ -# 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a +# 4d63.com/gochecknoglobals v0.1.0 4d63.com/gochecknoglobals/checknoglobals # code.gitea.io/sdk/gitea v0.15.0 ## explicit code.gitea.io/sdk/gitea -# github.com/Antonboom/errname v0.1.4 +# github.com/Antonboom/errname v0.1.5 github.com/Antonboom/errname/pkg/analyzer +# github.com/Antonboom/nilnil v0.1.0 +github.com/Antonboom/nilnil/pkg/analyzer # github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 github.com/Azure/go-ansiterm github.com/Azure/go-ansiterm/winterm @@ -31,14 +33,22 @@ github.com/ashanbrown/makezero/makezero github.com/beorn7/perks/quantile # github.com/bkielbasa/cyclop v1.2.0 github.com/bkielbasa/cyclop/pkg/analyzer +# github.com/blizzy78/varnamelen v0.3.0 +github.com/blizzy78/varnamelen # github.com/bmatcuk/doublestar/v4 v4.0.2 ## explicit github.com/bmatcuk/doublestar/v4 # github.com/bombsimon/wsl/v3 v3.3.0 github.com/bombsimon/wsl/v3 +# github.com/breml/bidichk v0.1.1 +github.com/breml/bidichk/pkg/bidichk +# github.com/butuzov/ireturn v0.1.1 +github.com/butuzov/ireturn/analyzer +github.com/butuzov/ireturn/config +github.com/butuzov/ireturn/types # github.com/cespare/xxhash/v2 v2.1.1 github.com/cespare/xxhash/v2 -# github.com/charithe/durationcheck v0.0.8 +# github.com/charithe/durationcheck v0.0.9 github.com/charithe/durationcheck # github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af github.com/chavacava/garif @@ -102,11 +112,11 @@ github.com/docker/go-units github.com/drone/envsubst github.com/drone/envsubst/parse github.com/drone/envsubst/path -# github.com/esimonov/ifshort v1.0.2 +# github.com/esimonov/ifshort v1.0.3 github.com/esimonov/ifshort/pkg/analyzer # github.com/ettle/strcase v0.1.1 github.com/ettle/strcase -# github.com/fatih/color v1.12.0 +# github.com/fatih/color v1.13.0 github.com/fatih/color # github.com/fatih/structtag v1.2.0 github.com/fatih/structtag @@ -116,7 +126,7 @@ github.com/flynn/go-shlex # github.com/franela/goblin v0.0.0-20211003143422-0a4f594942bf ## explicit github.com/franela/goblin -# github.com/fsnotify/fsnotify v1.4.9 +# github.com/fsnotify/fsnotify v1.5.1 github.com/fsnotify/fsnotify # github.com/fzipp/gocyclo v0.3.1 github.com/fzipp/gocyclo @@ -132,10 +142,11 @@ github.com/gin-gonic/gin/binding github.com/gin-gonic/gin/internal/bytesconv github.com/gin-gonic/gin/internal/json github.com/gin-gonic/gin/render -# github.com/go-critic/go-critic v0.5.6 +# github.com/go-critic/go-critic v0.6.1 github.com/go-critic/go-critic/checkers github.com/go-critic/go-critic/checkers/internal/astwalk github.com/go-critic/go-critic/checkers/internal/lintutil +github.com/go-critic/go-critic/checkers/rulesdata github.com/go-critic/go-critic/framework/linter # github.com/go-playground/locales v0.14.0 github.com/go-playground/locales @@ -152,7 +163,7 @@ github.com/go-sql-driver/mysql github.com/go-toolsmith/astcast # github.com/go-toolsmith/astcopy v1.0.0 github.com/go-toolsmith/astcopy -# github.com/go-toolsmith/astequal v1.0.0 +# github.com/go-toolsmith/astequal v1.0.1 github.com/go-toolsmith/astequal # github.com/go-toolsmith/astfmt v1.0.0 github.com/go-toolsmith/astfmt @@ -199,7 +210,7 @@ github.com/golang/protobuf/ptypes github.com/golang/protobuf/ptypes/any github.com/golang/protobuf/ptypes/duration github.com/golang/protobuf/ptypes/timestamp -# github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db +# github.com/golang/snappy v0.0.3 github.com/golang/snappy # github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 github.com/golangci/check/cmd/structcheck @@ -216,7 +227,7 @@ github.com/golangci/go-misc/deadcode # github.com/golangci/gofmt v0.0.0-20190930125516-244bba706f1a github.com/golangci/gofmt/gofmt github.com/golangci/gofmt/goimports -# github.com/golangci/golangci-lint v1.42.1 +# github.com/golangci/golangci-lint v1.43.0 ## explicit github.com/golangci/golangci-lint/cmd/golangci-lint github.com/golangci/golangci-lint/internal/cache @@ -250,7 +261,7 @@ github.com/golangci/lint-1 github.com/golangci/maligned # github.com/golangci/misspell v0.3.5 github.com/golangci/misspell -# github.com/golangci/revgrep v0.0.0-20210208091834-cd28932614b5 +# github.com/golangci/revgrep v0.0.0-20210930125155-c22e5001d4f2 github.com/golangci/revgrep # github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4 github.com/golangci/unconvert @@ -270,9 +281,9 @@ github.com/gordonklaus/ineffassign/pkg/ineffassign # github.com/gorilla/securecookie v1.1.1 ## explicit github.com/gorilla/securecookie -# github.com/gostaticanalysis/analysisutil v0.4.1 +# github.com/gostaticanalysis/analysisutil v0.7.1 github.com/gostaticanalysis/analysisutil -# github.com/gostaticanalysis/comment v1.4.1 +# github.com/gostaticanalysis/comment v1.4.2 github.com/gostaticanalysis/comment github.com/gostaticanalysis/comment/passes/commentmap # github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5 @@ -305,7 +316,7 @@ github.com/hashicorp/hcl/json/token github.com/inconshreveable/mousetrap # github.com/jgautheron/goconst v1.5.1 github.com/jgautheron/goconst -# github.com/jingyugao/rowserrcheck v1.1.0 +# github.com/jingyugao/rowserrcheck v1.1.1 github.com/jingyugao/rowserrcheck/passes/rowserr # github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af github.com/jirfag/go-printf-func-name/pkg/analyzer @@ -329,7 +340,7 @@ github.com/kr/pretty github.com/kr/text # github.com/kulti/thelper v0.4.0 github.com/kulti/thelper/pkg/analyzer -# github.com/kunwardeep/paralleltest v1.0.2 +# github.com/kunwardeep/paralleltest v1.0.3 github.com/kunwardeep/paralleltest/pkg/paralleltest # github.com/kyoh86/exportloopref v0.1.8 github.com/kyoh86/exportloopref @@ -350,9 +361,9 @@ github.com/magiconair/properties github.com/maratori/testpackage/pkg/testpackage # github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 github.com/matoous/godox -# github.com/mattn/go-colorable v0.1.8 +# github.com/mattn/go-colorable v0.1.11 github.com/mattn/go-colorable -# github.com/mattn/go-isatty v0.0.12 +# github.com/mattn/go-isatty v0.0.14 github.com/mattn/go-isatty # github.com/mattn/go-runewidth v0.0.9 github.com/mattn/go-runewidth @@ -363,16 +374,16 @@ github.com/mattn/go-sqlite3 github.com/matttproud/golang_protobuf_extensions/pbutil # github.com/mbilski/exhaustivestruct v1.2.0 github.com/mbilski/exhaustivestruct/pkg/analyzer -# github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 +# github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 github.com/mgechev/dots -# github.com/mgechev/revive v1.1.1 +# github.com/mgechev/revive v1.1.2 github.com/mgechev/revive/config github.com/mgechev/revive/formatter github.com/mgechev/revive/lint github.com/mgechev/revive/rule # github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/go-homedir -# github.com/mitchellh/mapstructure v1.4.1 +# github.com/mitchellh/mapstructure v1.4.2 github.com/mitchellh/mapstructure # github.com/moby/moby v20.10.10+incompatible ## explicit @@ -397,7 +408,7 @@ github.com/morikuni/aec # github.com/mrjones/oauth v0.0.0-20190623134757-126b35219450 ## explicit github.com/mrjones/oauth -# github.com/nakabonne/nestif v0.3.0 +# github.com/nakabonne/nestif v0.3.1 github.com/nakabonne/nestif # github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 github.com/nbutton23/zxcvbn-go @@ -420,7 +431,7 @@ github.com/opencontainers/go-digest # github.com/opencontainers/image-spec v1.0.1 github.com/opencontainers/image-spec/specs-go github.com/opencontainers/image-spec/specs-go/v1 -# github.com/pelletier/go-toml v1.9.3 +# github.com/pelletier/go-toml v1.9.4 github.com/pelletier/go-toml # github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d github.com/phayes/checkstyle @@ -447,14 +458,20 @@ github.com/prometheus/common/model github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util -# github.com/quasilyte/go-ruleguard v0.3.4 +# github.com/quasilyte/go-ruleguard v0.3.13 +github.com/quasilyte/go-ruleguard/internal/goenv github.com/quasilyte/go-ruleguard/internal/gogrep github.com/quasilyte/go-ruleguard/internal/golist +github.com/quasilyte/go-ruleguard/internal/stdinfo +github.com/quasilyte/go-ruleguard/internal/xsrcimporter github.com/quasilyte/go-ruleguard/internal/xtypes github.com/quasilyte/go-ruleguard/nodetag github.com/quasilyte/go-ruleguard/ruleguard github.com/quasilyte/go-ruleguard/ruleguard/goutil +github.com/quasilyte/go-ruleguard/ruleguard/ir +github.com/quasilyte/go-ruleguard/ruleguard/irconv github.com/quasilyte/go-ruleguard/ruleguard/quasigo +github.com/quasilyte/go-ruleguard/ruleguard/textmatch github.com/quasilyte/go-ruleguard/ruleguard/typematch # github.com/quasilyte/regex/syntax v0.0.0-20200407221936-30656e2c4a95 github.com/quasilyte/regex/syntax @@ -475,7 +492,7 @@ github.com/ryancurrah/gomodguard github.com/ryanrolds/sqlclosecheck/pkg/analyzer # github.com/sanposhiho/wastedassign/v2 v2.0.6 github.com/sanposhiho/wastedassign/v2 -# github.com/securego/gosec/v2 v2.8.1 +# github.com/securego/gosec/v2 v2.9.1 github.com/securego/gosec/v2 github.com/securego/gosec/v2/cwe github.com/securego/gosec/v2/rules @@ -483,6 +500,8 @@ github.com/securego/gosec/v2/rules github.com/shazow/go-diff/difflib # github.com/sirupsen/logrus v1.8.1 github.com/sirupsen/logrus +# github.com/sivchari/tenv v1.4.7 +github.com/sivchari/tenv # github.com/sonatard/noctx v0.0.1 github.com/sonatard/noctx github.com/sonatard/noctx/ngfunc @@ -492,7 +511,7 @@ github.com/sourcegraph/go-diff/diff # github.com/spf13/afero v1.6.0 github.com/spf13/afero github.com/spf13/afero/mem -# github.com/spf13/cast v1.3.1 +# github.com/spf13/cast v1.4.1 github.com/spf13/cast # github.com/spf13/cobra v1.2.1 github.com/spf13/cobra @@ -500,9 +519,14 @@ github.com/spf13/cobra github.com/spf13/jwalterweatherman # github.com/spf13/pflag v1.0.5 github.com/spf13/pflag -# github.com/spf13/viper v1.8.1 +# github.com/spf13/viper v1.9.0 github.com/spf13/viper -# github.com/ssgreg/nlreturn/v2 v2.1.0 +github.com/spf13/viper/internal/encoding +github.com/spf13/viper/internal/encoding/hcl +github.com/spf13/viper/internal/encoding/json +github.com/spf13/viper/internal/encoding/toml +github.com/spf13/viper/internal/encoding/yaml +# github.com/ssgreg/nlreturn/v2 v2.2.1 github.com/ssgreg/nlreturn/v2/pkg/nlreturn # github.com/stretchr/objx v0.3.0 ## explicit @@ -513,6 +537,8 @@ github.com/stretchr/testify/assert github.com/stretchr/testify/mock # github.com/subosito/gotenv v1.2.0 github.com/subosito/gotenv +# github.com/sylvia7788/contextcheck v1.0.4 +github.com/sylvia7788/contextcheck # github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb/leveldb github.com/syndtr/goleveldb/leveldb/cache @@ -528,14 +554,14 @@ github.com/syndtr/goleveldb/leveldb/table github.com/syndtr/goleveldb/leveldb/util # github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b github.com/tdakkota/asciicheck -# github.com/tetafro/godot v1.4.9 +# github.com/tetafro/godot v1.4.11 github.com/tetafro/godot # github.com/tevino/abool v1.2.0 ## explicit github.com/tevino/abool # github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94 github.com/timakin/bodyclose/passes/bodyclose -# github.com/tomarrell/wrapcheck/v2 v2.3.0 +# github.com/tomarrell/wrapcheck/v2 v2.4.0 github.com/tomarrell/wrapcheck/v2/wrapcheck # github.com/tommy-muehle/go-mnd/v2 v2.4.0 github.com/tommy-muehle/go-mnd/v2 @@ -583,7 +609,7 @@ golang.org/x/crypto/openpgp/errors golang.org/x/crypto/openpgp/packet golang.org/x/crypto/openpgp/s2k golang.org/x/crypto/sha3 -# golang.org/x/mod v0.4.2 +# golang.org/x/mod v0.5.0 golang.org/x/mod/internal/lazyregexp golang.org/x/mod/modfile golang.org/x/mod/module @@ -618,7 +644,6 @@ golang.org/x/sys/internal/unsafeheader golang.org/x/sys/unix golang.org/x/sys/windows # golang.org/x/text v0.3.7 -## explicit golang.org/x/text/internal/language golang.org/x/text/internal/language/compact golang.org/x/text/internal/tag @@ -631,7 +656,7 @@ golang.org/x/text/width # golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac ## explicit golang.org/x/time/rate -# golang.org/x/tools v0.1.5 +# golang.org/x/tools v0.1.7 golang.org/x/tools/go/analysis golang.org/x/tools/go/analysis/passes/asmdecl golang.org/x/tools/go/analysis/passes/assign @@ -795,7 +820,7 @@ google.golang.org/protobuf/types/descriptorpb google.golang.org/protobuf/types/known/anypb google.golang.org/protobuf/types/known/durationpb google.golang.org/protobuf/types/known/timestamppb -# gopkg.in/ini.v1 v1.62.0 +# gopkg.in/ini.v1 v1.63.2 gopkg.in/ini.v1 # gopkg.in/yaml.v2 v2.4.0 ## explicit