├── test ├── testdata │ ├── nogofiles │ │ └── test.txt │ ├── symlink_loop │ │ ├── pkg │ │ │ └── subpkg │ │ └── realpkg │ │ │ └── p.go │ ├── withxtest │ │ ├── p.go │ │ └── p_test.go │ ├── withconfig │ │ ├── .golangci.yml │ │ └── pkg │ │ │ └── pkg.go │ ├── configs │ │ ├── errcheck_exclude.txt │ │ ├── errchkjson.yml │ │ ├── lll.yml │ │ ├── dupl.yml │ │ ├── tenv_all.yml │ │ ├── cyclop.yml │ │ ├── gocognit.yml │ │ ├── gocyclo.yml │ │ ├── govet.yml │ │ ├── nestif.yml │ │ ├── nlreturn.yml │ │ ├── gofmt_no_simplify.yml │ │ ├── gofumpt-fix.yml │ │ ├── maintidx_under_100.yml │ │ ├── makezero_always.yml │ │ ├── wsl.yml │ │ ├── goconst_ignore.yml │ │ ├── gofumpt_with_extra.yml │ │ ├── govet_ifaceassert.yml │ │ ├── errcheck_ignore_default.yml │ │ ├── funlen.yml │ │ ├── goconst_calls_enabled.yml │ │ ├── goconst_dont_ignore.yml │ │ ├── govet_fieldalignment.yml │ │ ├── ireturn.yml │ │ ├── nolintlint_unused.yml │ │ ├── paralleltest.yml │ │ ├── importas_noalias.yml │ │ ├── ireturn_stdlib_reject.yml │ │ ├── lll_import.yml │ │ ├── misspell.yml │ │ ├── errchkjson_no_exported.yml │ │ ├── godox.yml │ │ ├── nonamedreturns.yml │ │ ├── errcheck_type_assertions.yml │ │ ├── exhaustive_default.yml │ │ ├── predeclared.yml │ │ ├── thelper.yml │ │ ├── whitespace-fix.yml │ │ ├── default_exclude.yml │ │ ├── exhaustive_ignore_enum_members.yml │ │ ├── goimports_local.yml │ │ ├── forbidigo_include_godoc_examples.yml │ │ ├── gosec_severity_confidence.yml │ │ ├── nolintlint.yml │ │ ├── errcheck_exclude.yml │ │ ├── errorlint_asserts.yml │ │ ├── errorlint_errorf.yml │ │ ├── errorlint_comparison.yml │ │ ├── forbidigo.yml │ │ ├── reassign_patterns.yml │ │ ├── go-header.yml │ │ ├── gci.yml │ │ ├── errchkjson_check_error_free_encoding.yml │ │ ├── exhaustruct.yml │ │ ├── exhaustivestruct.yml │ │ ├── ignore_config.yml │ │ ├── exclude_functions.yml │ │ ├── depguard.yml │ │ ├── gofmt_rewrite_rules.yml │ │ ├── gocritic-fix.yml │ │ ├── importas.yml │ │ ├── musttag.yml │ │ ├── importas_strict.yml │ │ ├── decorder.yml │ │ ├── depguard_ignore_file_rules.yml │ │ ├── gosec.yml │ │ ├── depguard_additional_guards.yml │ │ ├── revive.yml │ │ ├── gomodguard.yml │ │ └── gocritic.yml │ ├── linedirective │ │ ├── dupl.yml │ │ ├── lll.yml │ │ ├── hello.tmpl │ │ ├── gomodguard.yml │ │ └── hello.go │ ├── minimalpkg │ │ └── minimalpkg.go │ ├── used_only_in_tests │ │ ├── a.go │ │ └── a_test.go │ ├── ginkgolinter │ │ ├── configs │ │ │ ├── ginkgolinter_default.yml │ │ │ ├── ginkgolinter_suppress_err.yml │ │ │ ├── ginkgolinter_suppress_len.yml │ │ │ └── ginkgolinter_suppress_nil.yml │ │ └── go.mod │ ├── autogenerated │ │ ├── autogenerated.go │ │ ├── do_not_edit.go │ │ ├── protoc_gen_foo.go │ │ ├── go_bindata.go │ │ └── mockgen.go │ ├── withtests │ │ ├── p.go │ │ └── p_test.go │ ├── loggercheck │ │ ├── configs │ │ │ ├── loggercheck_noprintflike.yml │ │ │ ├── loggercheck_requirestringkey.yml │ │ │ ├── loggercheck_logronly.yml │ │ │ ├── loggercheck_zaponly.yml │ │ │ ├── loggercheck_kitlogonly.yml │ │ │ └── loggercheck_custom.yml │ │ ├── go.mod │ │ ├── loggercheck_zaponly.go │ │ ├── loggercheck_noprintflike.go │ │ ├── loggercheck_logronly.go │ │ └── loggercheck_requirestringkey.go │ ├── varcheck.go │ ├── testpackage_test.go │ ├── structcheck.go │ ├── notcompiles │ │ ├── typecheck.go │ │ └── typecheck_many_issues.go │ ├── skipdirs │ │ ├── examples │ │ │ └── with_issue.go │ │ ├── examples_no_skip │ │ │ └── with_issue.go │ │ └── skip_me │ │ │ └── nested │ │ │ └── with_issue.go │ ├── unparam.go │ ├── gofumpt.go │ ├── go-header_good.go │ ├── godot.go │ ├── go-header_bad.go │ ├── fix │ │ ├── out │ │ │ ├── gofmt.go │ │ │ ├── goimports.go │ │ │ ├── gofumpt.go │ │ │ ├── godot.go │ │ │ ├── gci.go │ │ │ ├── misspell.go │ │ │ ├── gocritic.go │ │ │ ├── nolintlint.go │ │ │ └── gofmt_rewrite_rules.go │ │ └── in │ │ │ ├── gofmt.go │ │ │ ├── gofumpt.go │ │ │ ├── goimports.go │ │ │ ├── godot.go │ │ │ ├── gci.go │ │ │ ├── misspell.go │ │ │ ├── gocritic.go │ │ │ ├── gofmt_rewrite_rules.go │ │ │ └── nolintlint.go │ ├── interfacer.go │ ├── unconvert.go │ ├── gochecknoinits.go │ ├── gofmt.go │ ├── stylecheck_not_in_megacheck.go │ ├── maligned.go │ ├── ineffassign.go │ ├── unsafe │ │ └── pkg.go │ ├── sort_results │ │ └── main.go │ ├── goimports.go │ ├── goprintffuncname.go │ ├── prealloc.go │ ├── quicktemplate │ │ └── hello.qtpl │ ├── usestdlibvars.go │ ├── reassign.go │ ├── bodyclose.go │ ├── gofumpt_with_extra.go │ ├── bidichk.go │ ├── tparallel_missing_subtest_test.go │ ├── varnamelen.go │ ├── containedctx.go │ ├── wrapcheck.go │ ├── misspell.go │ ├── tparallel_missing_toplevel_test.go │ ├── forbidigo_example_test.go │ ├── forbidigo_include_godoc_examples_test.go │ ├── gofmt_no_simplify.go │ ├── deadcode.go │ ├── ifshort.go │ ├── cgo │ │ └── main.go │ ├── decorder_default.go │ ├── errcheck_type_assertions.go │ ├── depguard.go │ ├── lll_single_import.go │ ├── exhaustive.go │ ├── tparallel_happy_path_test.go │ ├── forbidigo_example.go │ ├── depguard_ignore_file_rules.go │ ├── ireturn_default.go │ ├── importas_noalias.go │ ├── gofmt_rewrite_rules.go │ ├── govet_ifaceassert.go │ ├── nlreturn-block-size.go │ ├── scopelint.go │ ├── errcheck_exclude.go │ ├── goconst_calls_enabled.go │ ├── reassign_patterns.go │ ├── goimports_local.go │ ├── makezero_always.go │ ├── forcetypeassert.go │ ├── ireturn_allow.go │ ├── gosec_rules_config.go │ ├── testableexamples_test.go │ ├── gochecknoglobals.go │ ├── errcheck_exclude_functions.go │ ├── dogsled.go │ ├── gocheckcompilerdirectives.go │ ├── lll_multi_import.go │ ├── dupword.go │ ├── decorder.go │ ├── thelper_with_options.go │ ├── ireturn_reject_stdlib.go │ ├── tenv_go118.go │ ├── nolintlint_unused.go │ ├── staticcheck.go │ ├── paralleltest_custom.go │ ├── cgo_with_issues │ │ └── main.go │ ├── cyclop.go │ ├── gci.go │ ├── paralleltest.go │ ├── unused.go │ ├── errcheck_ignore_default.go │ ├── exhaustive_ignore_enum_members.go │ ├── staticcheck_in_megacheck.go │ ├── gocyclo.go │ ├── gosimple.go │ ├── exhaustive_generated.go │ ├── musttag.go │ ├── predeclared.go │ ├── predeclared_custom.go │ ├── depguard_additional_guards.go │ ├── errcheck_ignore.go │ ├── exhaustive_default.go │ ├── godox.go │ ├── golint.go │ ├── asasalint.go │ ├── goerr113.go │ ├── thelper_go118.go │ ├── makezero.go │ ├── nilerr.go │ ├── asciicheck.go │ ├── importas.go │ ├── stylecheck.go │ ├── revive_default.go │ ├── rowserrcheck.go │ ├── funlen.go │ ├── goconst.go │ ├── nolintlint.go │ ├── lll.go │ ├── revive.go │ ├── goconst_ignore_test.go │ ├── gomnd.go │ ├── gomodguard.go │ ├── gosec_severity_confidence.go │ ├── default_exclude.go │ ├── importas_strict.go │ ├── errcheck.go │ ├── errorlint.go │ ├── musttag_custom.go │ ├── gosec.go │ ├── exhaustruct.go │ ├── execinquery.go │ ├── goconst_dont_ignore_test.go │ └── exhaustivestruct.go ├── .gitignore ├── testdata_etc │ ├── unused_exported │ │ ├── lib │ │ │ ├── bar_test.go │ │ │ └── foo.go │ │ ├── golangci.yml │ │ └── main.go │ └── abspath │ │ └── with_issue.go ├── ruleguard │ ├── README.md │ ├── rangeExprCopy.go │ ├── strings_simplify.go │ └── dup.go └── testshared │ ├── testdata │ └── all.go │ └── runner_unix.go ├── .github ├── peril │ ├── .gitignore │ ├── tsconfig.json │ ├── README.md │ ├── settings.json │ └── package.json ├── contributors │ ├── .gitignore │ ├── def.d.ts │ ├── .prettierrc.json │ ├── tsconfig.json │ ├── info.ts │ └── package.json ├── CONTRIBUTING.md ├── boring-cyborg.yml ├── ISSUE_TEMPLATE │ └── config.yml ├── workflows │ └── pr-extra.yml ├── dependabot.yml └── stale.yml ├── .markdownlint.yaml ├── assets └── go.png ├── pkg ├── result │ └── processors │ │ ├── testdata │ │ ├── severity_rules.go │ │ ├── nolint_apply_to_unknown.go │ │ ├── autogen_exclude.go │ │ ├── nolint_unused.go │ │ ├── autogen_exclude_doc.go │ │ ├── exclude_rules_case_sensitive.go │ │ ├── nolint_whole_file.go │ │ ├── autogen_exclude_block_comment.go │ │ ├── exclude_rules.go │ │ ├── nolint2.go │ │ └── nolint_bad_names.go │ │ ├── processor.go │ │ ├── max_from_linter_test.go │ │ └── max_same_issues_test.go ├── fsutils │ ├── path_unix.go │ └── path_windows.go ├── printers │ ├── printer.go │ └── json.go ├── golinters │ ├── commons.go │ ├── execinquery.go │ ├── nosnakecase.go │ ├── containedctx.go │ ├── durationcheck.go │ ├── exportloopref.go │ ├── noctx.go │ ├── goerr113.go │ ├── nosprintfhostport.go │ ├── testableexamples.go │ ├── wastedassign.go │ ├── bodyclose.go │ ├── forcetypeassert.go │ ├── asciicheck.go │ ├── tparallel.go │ ├── ineffassign.go │ ├── nilerr.go │ ├── gocheckcompilerdirectives.go │ ├── sqlclosecheck.go │ ├── errname.go │ ├── goprintffuncname.go │ ├── typecheck.go │ ├── gosimple.go │ ├── goanalysis │ │ ├── load │ │ │ └── guard.go │ │ └── issue.go │ ├── contextcheck.go │ ├── tenv.go │ ├── rowserrcheck.go │ ├── musttag.go │ ├── maintidx.go │ ├── dupword.go │ ├── interfacebloat.go │ ├── nilnil.go │ ├── nonamedreturns.go │ ├── ireturn.go │ ├── nlreturn.go │ ├── predeclared.go │ ├── staticcheck.go │ ├── exhaustruct.go │ ├── exhaustivestruct.go │ ├── paralleltest.go │ ├── asasalint.go │ ├── reassign.go │ ├── ginkgolinter.go │ ├── ifshort.go │ ├── tagliatelle.go │ ├── testpackage.go │ ├── errorlint.go │ └── gochecknoglobals.go ├── config │ ├── linters.go │ └── severity.go ├── logutils │ └── out.go ├── sliceutil │ ├── sliceutil.go │ └── sliceutil_test.go ├── exitcodes │ └── exitcodes.go ├── packages │ ├── skip.go │ ├── errors.go │ └── skip_test.go ├── report │ └── data.go └── lint │ └── linter │ └── linter.go ├── tools ├── package.json └── tools.go ├── .gitattributes ├── docs ├── static │ ├── logo.png │ ├── banner.png │ └── logo-400.png ├── src │ ├── @rocketseat │ │ ├── gatsby-theme-docs-core │ │ │ ├── index.js │ │ │ └── util │ │ │ │ ├── url.js │ │ │ │ └── with-default.js │ │ └── gatsby-theme-docs │ │ │ ├── src │ │ │ ├── templates │ │ │ │ ├── homepage-query.js │ │ │ │ └── docs-query.js │ │ │ ├── util │ │ │ │ ├── url.js │ │ │ │ └── slug.js │ │ │ ├── components │ │ │ │ ├── Docs-wrapper.js │ │ │ │ ├── Homepage.js │ │ │ │ └── Sidebar │ │ │ │ │ ├── InternalLink │ │ │ │ │ └── index.js │ │ │ │ │ └── ExternalLink │ │ │ │ │ └── index.js │ │ │ ├── styles │ │ │ │ └── theme.js │ │ │ └── text │ │ │ │ └── index.mdx │ │ │ └── gatsby │ │ │ ├── wrapPageElement.js │ │ │ └── wrapRootElement.js │ ├── docs │ │ ├── usage │ │ │ ├── install │ │ │ │ └── annotations.png │ │ │ └── linters.mdx │ │ ├── product │ │ │ └── thanks.mdx │ │ └── contributing │ │ │ ├── debug.mdx │ │ │ └── quick-start.mdx │ ├── config │ │ └── site.js │ ├── components │ │ ├── SearchBar │ │ │ ├── README.md │ │ │ └── styles.css │ │ └── ResponsiveContainer.js │ ├── lib │ │ └── icons.js │ └── pages │ │ └── 404.js ├── template_data.state ├── gatsby-browser.js └── gatsby-ssr.js ├── .pre-commit-hooks.yaml ├── internal ├── robustio │ ├── readme.md │ ├── robustio_darwin.go │ ├── robustio_other.go │ └── robustio_windows.go ├── renameio │ └── readme.md ├── errorutil │ └── errors.go └── cache │ └── readme.md ├── .gitignore ├── cmd └── golangci-lint │ ├── mod_version.go │ └── main.go ├── scripts ├── expand_website_templates │ └── main_test.go ├── print_ast │ └── main.go └── gen_github_action_config │ └── go.mod ├── .nancy-ignore └── netlify.toml /test/testdata/nogofiles/test.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | /testdata/fix.tmp/ 2 | -------------------------------------------------------------------------------- /.github/peril/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /test/testdata/symlink_loop/pkg/subpkg: -------------------------------------------------------------------------------- 1 | ../ -------------------------------------------------------------------------------- /test/testdata/withxtest/p.go: -------------------------------------------------------------------------------- 1 | package p 2 | -------------------------------------------------------------------------------- /.markdownlint.yaml: -------------------------------------------------------------------------------- 1 | MD013: false 2 | MD033: false -------------------------------------------------------------------------------- /test/testdata/symlink_loop/realpkg/p.go: -------------------------------------------------------------------------------- 1 | package p 2 | -------------------------------------------------------------------------------- /test/testdata/withconfig/.golangci.yml: -------------------------------------------------------------------------------- 1 | InternalTest: true -------------------------------------------------------------------------------- /test/testdata/configs/errcheck_exclude.txt: -------------------------------------------------------------------------------- 1 | io/ioutil.ReadFile 2 | -------------------------------------------------------------------------------- /test/testdata_etc/unused_exported/lib/bar_test.go: -------------------------------------------------------------------------------- 1 | package lib 2 | -------------------------------------------------------------------------------- /test/testdata/configs/errchkjson.yml: -------------------------------------------------------------------------------- 1 | issues: 2 | max-issues-per-linter: 100 3 | -------------------------------------------------------------------------------- /test/testdata/configs/lll.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | lll: 3 | tab-width: 4 4 | -------------------------------------------------------------------------------- /test/testdata/withconfig/pkg/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | func SomeTestFunc() {} 4 | -------------------------------------------------------------------------------- /assets/go.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/multiply/golangci-lint/master/assets/go.png -------------------------------------------------------------------------------- /test/testdata/configs/dupl.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | dupl: 3 | threshold: 20 4 | -------------------------------------------------------------------------------- /test/testdata/configs/tenv_all.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | tenv: 3 | all: true 4 | -------------------------------------------------------------------------------- /test/testdata/linedirective/dupl.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | dupl: 3 | threshold: 10 4 | -------------------------------------------------------------------------------- /test/testdata/linedirective/lll.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | lll: 3 | line-length: 50 4 | -------------------------------------------------------------------------------- /test/testdata/minimalpkg/minimalpkg.go: -------------------------------------------------------------------------------- 1 | package minimalpkg 2 | 3 | func SomeTestFunc() {} 4 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/severity_rules.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | //go:dosomething 4 | -------------------------------------------------------------------------------- /test/testdata/configs/cyclop.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | cyclop: 3 | max-complexity: 15 4 | -------------------------------------------------------------------------------- /test/testdata/configs/gocognit.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gocognit: 3 | min-complexity: 2 4 | -------------------------------------------------------------------------------- /test/testdata/configs/gocyclo.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gocyclo: 3 | min-complexity: 20 4 | -------------------------------------------------------------------------------- /test/testdata/configs/govet.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | govet: 3 | check-shadowing: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/nestif.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | nestif: 3 | min-complexity: 1 4 | -------------------------------------------------------------------------------- /test/testdata/configs/nlreturn.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | nlreturn: 3 | block-size: 2 4 | -------------------------------------------------------------------------------- /tools/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "svg-term-cli": "2.1.1" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | go.sum linguist-generated 2 | * text=auto eol=lf 3 | *.ps1 text eol=crlf 4 | -------------------------------------------------------------------------------- /docs/static/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/multiply/golangci-lint/master/docs/static/logo.png -------------------------------------------------------------------------------- /test/ruleguard/README.md: -------------------------------------------------------------------------------- 1 | This directory contains ruleguard files that are used in functional tests. 2 | -------------------------------------------------------------------------------- /test/testdata/configs/gofmt_no_simplify.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gofmt: 3 | simplify: false 4 | -------------------------------------------------------------------------------- /test/testdata/configs/gofumpt-fix.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gofumpt: 3 | extra-rules: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/maintidx_under_100.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | maintidx: 3 | under: 100 4 | -------------------------------------------------------------------------------- /test/testdata/configs/makezero_always.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | makezero: 3 | always: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/wsl.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | wsl: 3 | allow-cuddle-declarations: false 4 | -------------------------------------------------------------------------------- /test/testdata/used_only_in_tests/a.go: -------------------------------------------------------------------------------- 1 | package p 2 | 3 | func f() bool { 4 | return true 5 | } 6 | -------------------------------------------------------------------------------- /docs/static/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/multiply/golangci-lint/master/docs/static/banner.png -------------------------------------------------------------------------------- /docs/static/logo-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/multiply/golangci-lint/master/docs/static/logo-400.png -------------------------------------------------------------------------------- /test/testdata/configs/goconst_ignore.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | goconst: 3 | ignore-tests: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/gofumpt_with_extra.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gofumpt: 3 | extra-rules: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/govet_ifaceassert.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | govet: 3 | enable: ifaceassert 4 | -------------------------------------------------------------------------------- /test/testdata/ginkgolinter/configs/ginkgolinter_default.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | ginkgolinter: {} 3 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs-core/index.js: -------------------------------------------------------------------------------- 1 | export { useSidebar } from './src/hooks/useSidebar'; 2 | -------------------------------------------------------------------------------- /test/testdata/configs/errcheck_ignore_default.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | check-blank: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/funlen.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | funlen: 3 | lines: 20 4 | statements: 10 5 | -------------------------------------------------------------------------------- /test/testdata/configs/goconst_calls_enabled.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | goconst: 3 | ignore-calls: false 4 | -------------------------------------------------------------------------------- /test/testdata/configs/goconst_dont_ignore.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | goconst: 3 | ignore-tests: false 4 | -------------------------------------------------------------------------------- /test/testdata/configs/govet_fieldalignment.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | govet: 3 | enable: fieldalignment 4 | -------------------------------------------------------------------------------- /test/testdata/configs/ireturn.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | ireturn: 3 | allow: 4 | - IreturnAllowDoer 5 | -------------------------------------------------------------------------------- /test/testdata/configs/nolintlint_unused.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | nolintlint: 3 | allow-unused: false 4 | -------------------------------------------------------------------------------- /test/testdata/configs/paralleltest.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | paralleltest: 3 | ignore-missing: true 4 | -------------------------------------------------------------------------------- /.github/contributors/.gitignore: -------------------------------------------------------------------------------- 1 | /cache/ 2 | /node_modules/ 3 | *.log 4 | *.tsbuildinfo 5 | /*.js 6 | /contributors.json -------------------------------------------------------------------------------- /.github/contributors/def.d.ts: -------------------------------------------------------------------------------- 1 | declare module "name-your-contributors" 2 | 3 | declare module "@octokit/graphql" 4 | -------------------------------------------------------------------------------- /test/testdata/configs/importas_noalias.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | importas: 3 | fff: fmt 4 | std_os: os 5 | -------------------------------------------------------------------------------- /test/testdata/configs/ireturn_stdlib_reject.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | ireturn: 3 | reject: 4 | - stdlib 5 | -------------------------------------------------------------------------------- /test/testdata/configs/lll_import.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | lll: 3 | tab-width: 4 4 | line-length: 60 5 | -------------------------------------------------------------------------------- /test/testdata/configs/misspell.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | misspell: 3 | ignore-words: 4 | - langauge 5 | -------------------------------------------------------------------------------- /test/testdata/autogenerated/autogenerated.go: -------------------------------------------------------------------------------- 1 | // Code generated by ... DO NOT EDIT. 2 | package p 3 | 4 | var vvv int 5 | -------------------------------------------------------------------------------- /test/testdata/configs/errchkjson_no_exported.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errchkjson: 3 | report-no-exported: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/godox.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | godox: 3 | keywords: 4 | - FIXME 5 | - TODO 6 | -------------------------------------------------------------------------------- /test/testdata/configs/nonamedreturns.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | nonamedreturns: 3 | report-error-in-defer: true 4 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See [contibuting quick start](https://golangci-lint.run/contributing/quick-start/) on our website. 2 | -------------------------------------------------------------------------------- /test/testdata/configs/errcheck_type_assertions.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | check-type-assertions: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/exhaustive_default.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | exhaustive: 3 | default-signifies-exhaustive: true 4 | -------------------------------------------------------------------------------- /test/testdata/configs/predeclared.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | predeclared: 3 | ignore: "real,recover" 4 | q: true 5 | -------------------------------------------------------------------------------- /test/testdata/configs/thelper.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | thelper: 3 | test: 4 | name: false 5 | begin: true 6 | -------------------------------------------------------------------------------- /test/testdata/configs/whitespace-fix.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | whitespace: 3 | multi-if: true 4 | multi-func: true 5 | -------------------------------------------------------------------------------- /test/testdata/linedirective/hello.tmpl: -------------------------------------------------------------------------------- 1 | # This is a template file for some code generator, and is not a valid go source file. 2 | -------------------------------------------------------------------------------- /test/testdata/withtests/p.go: -------------------------------------------------------------------------------- 1 | package withtests 2 | 3 | import "fmt" 4 | 5 | func init() { 6 | fmt.Printf("init") 7 | } 8 | -------------------------------------------------------------------------------- /test/testdata/autogenerated/do_not_edit.go: -------------------------------------------------------------------------------- 1 | // DO NOT EDIT Code generated by something 2 | package p 3 | 4 | func unusedFunc() {} 5 | -------------------------------------------------------------------------------- /test/testdata/configs/default_exclude.yml: -------------------------------------------------------------------------------- 1 | issues: 2 | include: 3 | - EXC0011 # include issues about comments from `stylecheck` -------------------------------------------------------------------------------- /test/testdata/configs/exhaustive_ignore_enum_members.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | exhaustive: 3 | ignore-enum-members: "West$" 4 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/configs/loggercheck_noprintflike.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | loggercheck: 3 | no-printf-like: true 4 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/nolint_apply_to_unknown.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | func bar() { 4 | _ = 0 //nolint: foobar 5 | } 6 | -------------------------------------------------------------------------------- /test/testdata/configs/goimports_local.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | goimports: 3 | local-prefixes: github.com/golangci/golangci-lint 4 | -------------------------------------------------------------------------------- /test/testdata/configs/forbidigo_include_godoc_examples.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | forbidigo: 3 | exclude-godoc-examples: false 4 | 5 | -------------------------------------------------------------------------------- /test/testdata/configs/gosec_severity_confidence.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gosec: 3 | severity: "medium" 4 | confidence: "medium" 5 | -------------------------------------------------------------------------------- /test/testdata/configs/nolintlint.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | nolintlint: 3 | require-explanation: true 4 | require-specific: true 5 | -------------------------------------------------------------------------------- /test/testdata/ginkgolinter/configs/ginkgolinter_suppress_err.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | ginkgolinter: 3 | suppress-err-assertion: true 4 | -------------------------------------------------------------------------------- /test/testdata/ginkgolinter/configs/ginkgolinter_suppress_len.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | ginkgolinter: 3 | suppress-len-assertion: true 4 | -------------------------------------------------------------------------------- /test/testdata/ginkgolinter/configs/ginkgolinter_suppress_nil.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | ginkgolinter: 3 | suppress-nil-assertion: true 4 | -------------------------------------------------------------------------------- /test/testdata/linedirective/gomodguard.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gomodguard: 3 | allowed: 4 | domains: 5 | - golang.org 6 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/configs/loggercheck_requirestringkey.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | loggercheck: 3 | require-string-key: true 4 | -------------------------------------------------------------------------------- /docs/src/docs/usage/install/annotations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/multiply/golangci-lint/master/docs/src/docs/usage/install/annotations.png -------------------------------------------------------------------------------- /test/testdata/configs/errcheck_exclude.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | check-blank: true 4 | exclude: errcheck_exclude.txt 5 | -------------------------------------------------------------------------------- /test/testdata/varcheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Evarcheck --internal-cmd-test 2 | package testdata 3 | 4 | var v string // want "`v` is unused" 5 | -------------------------------------------------------------------------------- /test/testdata/configs/errorlint_asserts.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errorlint: 3 | errorf: false 4 | asserts: true 5 | comparison: false 6 | -------------------------------------------------------------------------------- /test/testdata/configs/errorlint_errorf.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errorlint: 3 | errorf: true 4 | asserts: false 5 | comparison: false 6 | -------------------------------------------------------------------------------- /test/testdata/configs/errorlint_comparison.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errorlint: 3 | errorf: false 4 | asserts: false 5 | comparison: true 6 | -------------------------------------------------------------------------------- /test/testdata/configs/forbidigo.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | forbidigo: 3 | forbid: 4 | - fmt\.Print.* 5 | - time.Sleep(# no sleeping!)? 6 | -------------------------------------------------------------------------------- /test/testdata/configs/reassign_patterns.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | reassign: 3 | patterns: 4 | - DefaultClient 5 | - DefaultTransport 6 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/configs/loggercheck_logronly.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | loggercheck: 3 | logr: true 4 | klog: false 5 | zap: false 6 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/configs/loggercheck_zaponly.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | loggercheck: 3 | logr: false 4 | klog: false 5 | zap: true 6 | -------------------------------------------------------------------------------- /test/testdata/testpackage_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Etestpackage 2 | package testdata // want "package should be `testdata_test` instead of `testdata`" 3 | -------------------------------------------------------------------------------- /test/testdata/configs/go-header.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | goheader: 3 | template: MY {{title}} 4 | values: 5 | const: 6 | title: TITLE. 7 | -------------------------------------------------------------------------------- /test/testdata/autogenerated/protoc_gen_foo.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-foo 2 | // source: bar.proto 3 | // DO NOT EDIT!!! 4 | package p 5 | 6 | var v int 7 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/templates/homepage-query.js: -------------------------------------------------------------------------------- 1 | import HomepageComponent from '../components/Homepage'; 2 | 3 | export default HomepageComponent; 4 | -------------------------------------------------------------------------------- /test/testdata/structcheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Estructcheck 2 | package testdata 3 | 4 | type t struct { 5 | unusedField int // want "`unusedField` is unused" 6 | } 7 | -------------------------------------------------------------------------------- /test/testdata/used_only_in_tests/a_test.go: -------------------------------------------------------------------------------- 1 | package p 2 | 3 | import "testing" 4 | 5 | func TestF(t *testing.T) { 6 | if !f() { 7 | t.Fail() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/autogen_exclude.go: -------------------------------------------------------------------------------- 1 | // first line 2 | //second line 3 | 4 | // third line 5 | 6 | package testdata // this text also 7 | // and this text also 8 | -------------------------------------------------------------------------------- /test/testdata/autogenerated/go_bindata.go: -------------------------------------------------------------------------------- 1 | // Code generated by go-bindata. 2 | // sources: 3 | // bar.baz 4 | // x/y.z 5 | // DO NOT EDIT! 6 | package p 7 | 8 | var vv int 9 | -------------------------------------------------------------------------------- /test/testdata/configs/gci.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gci: 3 | sections: 4 | - standard 5 | - prefix(github.com/golangci/golangci-lint) 6 | - default 7 | -------------------------------------------------------------------------------- /test/testdata/notcompiles/typecheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Etypecheck 2 | package testdata 3 | 4 | fun NotCompiles() { // want "expected declaration, found.* fun" 5 | } 6 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/configs/loggercheck_kitlogonly.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | loggercheck: 3 | kitlog: true 4 | klog: false 5 | logr: false 6 | zap: false 7 | -------------------------------------------------------------------------------- /test/testdata_etc/unused_exported/golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | disable-all: true 3 | enable: 4 | - unused 5 | linters-settings: 6 | unused: 7 | check-exported: true 8 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/nolint_unused.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | var nolintVarcheck int //nolint:varcheck 4 | 5 | var nolintVarcheckUnusedOK int //nolint:varcheck,nolintlint 6 | -------------------------------------------------------------------------------- /test/testdata/autogenerated/mockgen.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: ./app/analyze/executors/executor.go 3 | 4 | package p 5 | 6 | func UnusedFunc2() {} 7 | -------------------------------------------------------------------------------- /test/testdata/configs/errchkjson_check_error_free_encoding.yml: -------------------------------------------------------------------------------- 1 | issues: 2 | max-issues-per-linter: 100 3 | linters-settings: 4 | errchkjson: 5 | check-error-free-encoding: true 6 | -------------------------------------------------------------------------------- /test/testdata/configs/exhaustruct.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | exhaustruct: 3 | include: 4 | - .*\.ExhaustructCustom 5 | exclude: 6 | - .*\.ExhaustructCustom[\d]{1,2} 7 | -------------------------------------------------------------------------------- /test/testdata_etc/abspath/with_issue.go: -------------------------------------------------------------------------------- 1 | package abspath 2 | 3 | import "fmt" 4 | 5 | func f() { 6 | if true { 7 | return 8 | } else { 9 | fmt.Print("") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/configs/exhaustivestruct.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | exhaustivestruct: 3 | struct-patterns: 4 | - '*.ExhaustiveStructCustom' 5 | - '*.ExhaustiveStructCustom2' 6 | -------------------------------------------------------------------------------- /test/testdata/configs/ignore_config.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | check-blank: true 4 | ignore: os:.*,io/ioutil:^ReadF.* 5 | issues: 6 | include: 7 | - EXC0001 8 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/util/url.js: -------------------------------------------------------------------------------- 1 | function isExternalUrl(url) { 2 | return new RegExp('^((https?:)?//)', 'i').test(url); 3 | } 4 | 5 | module.exports = { isExternalUrl }; 6 | -------------------------------------------------------------------------------- /docs/src/config/site.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | configPath: `src/config`, 3 | docsPath: `src/docs`, 4 | githubUrl: `https://github.com/golangci/golangci-lint`, 5 | baseDir: `docs`, 6 | }; 7 | -------------------------------------------------------------------------------- /test/testdata/configs/exclude_functions.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | errcheck: 3 | check-blank: true 4 | exclude-functions: 5 | - io/ioutil.ReadFile 6 | - io/ioutil.ReadDir 7 | -------------------------------------------------------------------------------- /test/testdata/skipdirs/examples/with_issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | if true { 7 | return 8 | } else { 9 | fmt.Printf("") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/unparam.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eunparam 2 | package testdata 3 | 4 | func unparamUnused(a, b uint) uint { // want "`unparamUnused` - `b` is unused" 5 | a++ 6 | return a 7 | } 8 | -------------------------------------------------------------------------------- /test/testdata/gofumpt.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofumpt 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func GofumptNewLine() { 7 | fmt.Println( "foo" ) // want "File is not `gofumpt`-ed" 8 | } 9 | -------------------------------------------------------------------------------- /test/testdata/skipdirs/examples_no_skip/with_issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | if true { 7 | return 8 | } else { 9 | fmt.Printf("") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/skipdirs/skip_me/nested/with_issue.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | if true { 7 | return 8 | } else { 9 | fmt.Printf("") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /docs/template_data.state: -------------------------------------------------------------------------------- 1 | This file stores hash of website templates to trigger Netlify rebuild when something changes, e.g. new linter is added. 2 | c80d06da70dd682f6b984675eb5b193e4a47552fa15e1a732a189901c5505e74 -------------------------------------------------------------------------------- /pkg/fsutils/path_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package fsutils 4 | 5 | // NormalizePathInRegex it's a noop function on Unix. 6 | func NormalizePathInRegex(path string) string { 7 | return path 8 | } 9 | -------------------------------------------------------------------------------- /test/testdata/configs/depguard.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | depguard: 3 | include-go-root: true 4 | packages: 5 | - compress/* 6 | packages-with-error-message: 7 | log: "don't use log" 8 | -------------------------------------------------------------------------------- /test/testdata/go-header_good.go: -------------------------------------------------------------------------------- 1 | /*MY TITLE.*/ 2 | 3 | //golangcitest:args -Egoheader 4 | //golangcitest:config_path testdata/configs/go-header.yml 5 | //golangcitest:expected_exitcode 0 6 | package testdata 7 | -------------------------------------------------------------------------------- /test/testdata/godot.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egodot 2 | package testdata 3 | 4 | // Godot checks top-level comments // want "Comment should end in a period" 5 | func Godot() { 6 | // nothing to do here 7 | } 8 | -------------------------------------------------------------------------------- /docs/gatsby-browser.js: -------------------------------------------------------------------------------- 1 | export { wrapRootElement } from "./src/@rocketseat/gatsby-theme-docs/gatsby/wrapRootElement"; 2 | export { wrapPageElement } from "./src/@rocketseat/gatsby-theme-docs/gatsby/wrapPageElement"; 3 | -------------------------------------------------------------------------------- /docs/gatsby-ssr.js: -------------------------------------------------------------------------------- 1 | export { wrapRootElement } from "./src/@rocketseat/gatsby-theme-docs/gatsby/wrapRootElement"; 2 | export { wrapPageElement } from "./src/@rocketseat/gatsby-theme-docs/gatsby/wrapPageElement"; 3 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/autogen_exclude_doc.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | // DO NOT EDIT 4 | 5 | import "fmt" 6 | 7 | //nolint:all 8 | func PrintString(s string) { 9 | fmt.Printf("%s", s) 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/go-header_bad.go: -------------------------------------------------------------------------------- 1 | /*MY TITLE!*/ // want `Expected:TITLE\., Actual: TITLE!` 2 | 3 | //golangcitest:args -Egoheader 4 | //golangcitest:config_path testdata/configs/go-header.yml 5 | package testdata 6 | -------------------------------------------------------------------------------- /.github/peril/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": false, 4 | "target": "es5", 5 | "module": "commonjs", 6 | "lib": ["es2017"], 7 | "strict": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/testdata/fix/out/gofmt.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | func gofmt(a, b int) int { 6 | if a != b { 7 | return 1 8 | } 9 | return 2 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/withxtest/p_test.go: -------------------------------------------------------------------------------- 1 | package p_test 2 | 3 | import "fmt" 4 | 5 | func WithGolintIssues(b bool) { //nolint:megacheck 6 | if b { 7 | return 8 | } else { 9 | fmt.Print("1") 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata_etc/unused_exported/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/golangci/golangci-lint/test/testdata_etc/unused_exported/lib" 5 | ) 6 | 7 | func main() { 8 | lib.PublicFunc() 9 | } 10 | -------------------------------------------------------------------------------- /.github/peril/README.md: -------------------------------------------------------------------------------- 1 | Based on https://github.com/gatsbyjs/gatsby/tree/master/peril. 2 | 3 | ## Update a code 4 | 5 | ```bash 6 | heroku ps:restart web --app golangci-peril 7 | heroku logs --app golangci-peril -t 8 | ``` 9 | -------------------------------------------------------------------------------- /.pre-commit-hooks.yaml: -------------------------------------------------------------------------------- 1 | - id: golangci-lint 2 | name: golangci-lint 3 | description: Fast linters runner for Go. 4 | entry: golangci-lint run --fix 5 | types: [go] 6 | language: golang 7 | pass_filenames: false 8 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/exclude_rules_case_sensitive.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | //GO:generate long line that will be excluded by default processor but will not be affected by case-sensitive one because of capital GO 4 | -------------------------------------------------------------------------------- /test/testdata/fix/in/gofmt.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | func gofmt(a, b int) int { 6 | if a != b { 7 | return 1 8 | } 9 | return 2 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/interfacer.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Einterfacer --internal-cmd-test 2 | package testdata 3 | 4 | import "io" 5 | 6 | func InterfacerCheck(f io.ReadCloser) { // want "`f` can be `io.Closer`" 7 | f.Close() 8 | } 9 | -------------------------------------------------------------------------------- /test/testdata/unconvert.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eunconvert 2 | package testdata 3 | 4 | import "log" 5 | 6 | func Unconvert() { 7 | a := 1 8 | b := int(a) // want "unnecessary conversion" 9 | log.Print(b) 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata_etc/unused_exported/lib/foo.go: -------------------------------------------------------------------------------- 1 | package lib 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func PublicFunc() { 8 | privateFunc() 9 | } 10 | 11 | func privateFunc() { 12 | fmt.Println("side effect") 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/configs/gofmt_rewrite_rules.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gofmt: 3 | rewrite-rules: 4 | - pattern: 'interface{}' 5 | replacement: 'any' 6 | - pattern: 'a[b:len(a)]' 7 | replacement: 'a[b:]' 8 | -------------------------------------------------------------------------------- /test/testdata/gochecknoinits.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egochecknoinits 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func init() { // want "don't use `init` function" 7 | fmt.Println() 8 | } 9 | 10 | func Init() {} 11 | -------------------------------------------------------------------------------- /.github/contributors/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "endOfLine": "lf", 3 | "semi": false, 4 | "singleQuote": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5", 7 | "printWidth": 140, 8 | "parser": "typescript" 9 | } -------------------------------------------------------------------------------- /test/testdata/fix/out/goimports.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt,goimports 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | func goimports(a, b int) int { 6 | if a != b { 7 | return 1 8 | } 9 | return 2 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/gofmt.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func GofmtNotSimplified() { 7 | var x []string 8 | fmt.Print(x[1:len(x)]) // want "File is not `gofmt`-ed with `-s`" 9 | } 10 | -------------------------------------------------------------------------------- /test/testdata/stylecheck_not_in_megacheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emegacheck 2 | //golangcitest:expected_exitcode 0 3 | package testdata 4 | 5 | func StylecheckNotInMegacheck(x int) { 6 | if 0 == x { 7 | panic(x) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/testdata/configs/gocritic-fix.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gocritic: 3 | enabled-checks: 4 | - ruleguard 5 | settings: 6 | ruleguard: 7 | rules: 'ruleguard/rangeExprCopy.go,ruleguard/strings_simplify.go' 8 | 9 | -------------------------------------------------------------------------------- /test/testdata/maligned.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emaligned --internal-cmd-test 2 | package testdata 3 | 4 | type BadAlignedStruct struct { // want "struct of size 24 bytes could be of size 16 bytes" 5 | B bool 6 | I int 7 | B2 bool 8 | } 9 | -------------------------------------------------------------------------------- /test/testdata/withtests/p_test.go: -------------------------------------------------------------------------------- 1 | package withtests 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | ) 7 | 8 | func TestSomething(t *testing.T) { 9 | if true { 10 | return 11 | } else { 12 | fmt.Printf("test") 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pkg/printers/printer.go: -------------------------------------------------------------------------------- 1 | package printers 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/golangci/golangci-lint/pkg/result" 7 | ) 8 | 9 | type Printer interface { 10 | Print(ctx context.Context, issues []result.Issue) error 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/configs/importas.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | importas: 3 | alias: 4 | - pkg: fmt 5 | alias: fff 6 | - pkg: os 7 | alias: std_os 8 | - pkg: github.com/pkg/errors 9 | alias: pkgerr 10 | -------------------------------------------------------------------------------- /.github/contributors/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "esModuleInterop": false, 4 | "target": "es2015", 5 | "module": "es2015", 6 | "lib": ["es2015"], 7 | "strict": true, 8 | "incremental": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /pkg/golinters/commons.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import "github.com/golangci/golangci-lint/pkg/logutils" 4 | 5 | // linterLogger must be use only when the context logger is not available. 6 | var linterLogger = logutils.NewStderrLog(logutils.DebugKeyLinter) 7 | -------------------------------------------------------------------------------- /test/testdata/ineffassign.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eineffassign 2 | package testdata 3 | 4 | import "math" 5 | 6 | func _() { 7 | x := math.MinInt8 8 | for { 9 | _ = x 10 | x = 0 // want "ineffectual assignment to x" 11 | x = 0 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/configs/musttag.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | musttag: 3 | functions: 4 | - name: encoding/asn1.Marshal 5 | tag: asn1 6 | arg-pos: 0 7 | - name: encoding/asn1.Unmarshal 8 | tag: asn1 9 | arg-pos: 1 10 | -------------------------------------------------------------------------------- /test/testdata/unsafe/pkg.go: -------------------------------------------------------------------------------- 1 | package pkg 2 | 3 | import ( 4 | "log" 5 | "unsafe" 6 | ) 7 | 8 | func F() { 9 | x := 123 // of type int 10 | p := unsafe.Pointer(&x) 11 | pp := &p // of type *unsafe.Pointer 12 | p = unsafe.Pointer(pp) 13 | log.Print(p) 14 | } 15 | -------------------------------------------------------------------------------- /.github/contributors/info.ts: -------------------------------------------------------------------------------- 1 | export type ContributorInfo = { 2 | login: string 3 | name: string 4 | avatarUrl: string 5 | websiteUrl: string 6 | } 7 | 8 | export type DataJSON = { 9 | contributors: ContributorInfo[] 10 | coreTeam: ContributorInfo[] 11 | } 12 | -------------------------------------------------------------------------------- /pkg/result/processors/processor.go: -------------------------------------------------------------------------------- 1 | package processors 2 | 3 | import ( 4 | "github.com/golangci/golangci-lint/pkg/result" 5 | ) 6 | 7 | type Processor interface { 8 | Process(issues []result.Issue) ([]result.Issue, error) 9 | Name() string 10 | Finish() 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/sort_results/main.go: -------------------------------------------------------------------------------- 1 | package sortresults 2 | 3 | import ( 4 | "database/sql" 5 | "errors" 6 | ) 7 | 8 | func returnError() error { 9 | return errors.New("sss") 10 | } 11 | 12 | var db *sql.DB 13 | 14 | func Example() { 15 | returnError() 16 | } 17 | -------------------------------------------------------------------------------- /pkg/config/linters.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | type Linters struct { 4 | Enable []string 5 | Disable []string 6 | EnableAll bool `mapstructure:"enable-all"` 7 | DisableAll bool `mapstructure:"disable-all"` 8 | Fast bool 9 | 10 | Presets []string 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/configs/importas_strict.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | importas: 3 | no-unaliased: true 4 | alias: 5 | - pkg: fmt 6 | alias: fff 7 | - pkg: os 8 | alias: std_os 9 | - pkg: github.com/pkg/errors 10 | alias: pkgerr 11 | -------------------------------------------------------------------------------- /pkg/logutils/out.go: -------------------------------------------------------------------------------- 1 | package logutils 2 | 3 | import ( 4 | "github.com/fatih/color" 5 | colorable "github.com/mattn/go-colorable" 6 | ) 7 | 8 | var StdOut = color.Output // https://github.com/golangci/golangci-lint/issues/14 9 | var StdErr = colorable.NewColorableStderr() 10 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/nolint_whole_file.go: -------------------------------------------------------------------------------- 1 | //nolint:errcheck 2 | package testdata 3 | 4 | func RetError() error { 5 | return nil 6 | } 7 | 8 | func MissedErrorCheck1() { 9 | RetErr() 10 | } 11 | 12 | func jo(v, w bool) bool { 13 | return v == w || v == w 14 | } 15 | -------------------------------------------------------------------------------- /test/testdata/configs/decorder.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | decorder: 3 | dec-order: 4 | - type 5 | - const 6 | - var 7 | - func 8 | disable-dec-order-check: false 9 | disable-init-func-first-check: false 10 | disable-dec-num-check: false 11 | -------------------------------------------------------------------------------- /test/testdata/goimports.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoimports 2 | package testdata 3 | 4 | import ( 5 | "fmt" // want "File is not `goimports`-ed" 6 | "github.com/golangci/golangci-lint/pkg/config" 7 | ) 8 | 9 | func Bar() { 10 | fmt.Print("x") 11 | _ = config.Config{} 12 | } 13 | -------------------------------------------------------------------------------- /docs/src/components/SearchBar/README.md: -------------------------------------------------------------------------------- 1 | The source code copy-pasted from [here](https://github.com/facebook/docusaurus/blob/master/packages/docusaurus-theme-search-algolia/src/theme/SearchBar/). 2 | 3 | Waiting for [the official component](https://github.com/algolia/docsearch/issues/689). 4 | -------------------------------------------------------------------------------- /test/testdata/fix/out/gofumpt.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofumpt 2 | //golangcitest:config_path testdata/configs/gofumpt-fix.yml 3 | //golangcitest:expected_exitcode 0 4 | package p 5 | 6 | import "fmt" 7 | 8 | func GofmtNotExtra(bar, baz string) { 9 | fmt.Print(bar, baz) 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/goprintffuncname.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoprintffuncname 2 | package testdata 3 | 4 | func PrintfLikeFuncWithBadName(format string, args ...interface{}) { // want "printf-like formatting function 'PrintfLikeFuncWithBadName' should be named 'PrintfLikeFuncWithBadNamef'" 5 | } 6 | -------------------------------------------------------------------------------- /test/testdata/prealloc.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eprealloc 2 | package testdata 3 | 4 | func Prealloc(source []int) []int { 5 | var dest []int // want "Consider pre-allocating `dest`" 6 | for _, v := range source { 7 | dest = append(dest, v) 8 | } 9 | 10 | return dest 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/fix/in/gofumpt.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofumpt 2 | //golangcitest:config_path testdata/configs/gofumpt-fix.yml 3 | //golangcitest:expected_exitcode 0 4 | package p 5 | 6 | import "fmt" 7 | 8 | func GofmtNotExtra(bar string, baz string) { 9 | fmt.Print(bar, baz) 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/fix/in/goimports.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt,goimports 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | import ( 6 | "os" 7 | "fmt" 8 | ) 9 | 10 | func goimports(a, b int) int { 11 | if a != b { 12 | return 1 13 | } 14 | return 2 15 | } 16 | -------------------------------------------------------------------------------- /internal/robustio/readme.md: -------------------------------------------------------------------------------- 1 | # robustio 2 | 3 | Extracted from go1.19.1/src/cmd/go/internal/robustio 4 | 5 | There is only one modification: 6 | - ERROR_SHARING_VIOLATION extracted from go1.19.1/src/internal/syscall/windows/syscall_windows.go to remove the dependencies to `internal/syscall/windows` 7 | -------------------------------------------------------------------------------- /test/testdata/quicktemplate/hello.qtpl: -------------------------------------------------------------------------------- 1 | All text outside function templates is treated as comments, 2 | i.e. it is just ignored by quicktemplate compiler (`qtc`). It is for humans. 3 | 4 | Hello is a simple template function. 5 | {% func Hello(name string) %} 6 | Hello, {%s name %}! 7 | {% endfunc %} 8 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/autogen_exclude_block_comment.go: -------------------------------------------------------------------------------- 1 | /* 2 | * first line 3 | * 4 | * second line 5 | * third line 6 | */ 7 | 8 | // and this text also 9 | 10 | /* 11 | this type of block comment also 12 | */ 13 | 14 | /* this one line comment also */ 15 | 16 | package testdata 17 | -------------------------------------------------------------------------------- /test/testdata/usestdlibvars.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eusestdlibvars 2 | package testdata 3 | 4 | import "net/http" 5 | 6 | func _200() { 7 | _ = 200 8 | } 9 | 10 | func _200_1() { 11 | var w http.ResponseWriter 12 | w.WriteHeader(200) // want `"200" can be replaced by http.StatusOK` 13 | } 14 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/components/Docs-wrapper.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable react/prop-types */ 2 | import React from "react"; 3 | import Docs from "./Docs"; 4 | 5 | export default function Docspage({ data: { mdx }, pageContext }) { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /test/testdata/fix/in/godot.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egodot 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | /* 6 | This comment won't be checked in default mode 7 | */ 8 | 9 | // This comment will be fixed 10 | func godot(a, b int) int { 11 | // Nothing to do here 12 | return a + b 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/reassign.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ereassign 2 | package testdata 3 | 4 | import ( 5 | "io" 6 | "net/http" 7 | ) 8 | 9 | func reassignTest() { 10 | http.DefaultClient = nil 11 | http.DefaultTransport = nil 12 | io.EOF = nil // want `reassigning variable EOF in other package io` 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/bodyclose.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ebodyclose 2 | package testdata 3 | 4 | import ( 5 | "io/ioutil" 6 | "net/http" 7 | ) 8 | 9 | func BodycloseNotClosed() { 10 | resp, _ := http.Get("https://google.com") // want "response body must be closed" 11 | _, _ = ioutil.ReadAll(resp.Body) 12 | } 13 | -------------------------------------------------------------------------------- /test/testdata/fix/out/godot.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egodot 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | /* 6 | This comment won't be checked in default mode 7 | */ 8 | 9 | // This comment will be fixed. 10 | func godot(a, b int) int { 11 | // Nothing to do here 12 | return a + b 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/gofumpt_with_extra.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofumpt 2 | //golangcitest:config_path testdata/configs/gofumpt_with_extra.yml 3 | package testdata 4 | 5 | import "fmt" 6 | 7 | func GofmtNotExtra(bar string, baz string) { // want "File is not `gofumpt`-ed with `-extra`" 8 | fmt.Print("foo") 9 | } 10 | -------------------------------------------------------------------------------- /test/testshared/testdata/all.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Efoo --simple --hello=world 2 | //golangcitest:config_path testdata/example.yml 3 | //golangcitest:expected_linter bar 4 | //golangcitest:expected_exitcode 0 5 | package testdata 6 | 7 | import "fmt" 8 | 9 | func main() { 10 | fmt.Println("Hello") 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/bidichk.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ebidichk 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func main() { 7 | fmt.Println("LEFT-TO-RIGHT-OVERRIDE: '‭', it is between the single quotes, but it is not visible with a regular editor") // want "found dangerous unicode character sequence LEFT-TO-RIGHT-OVERRIDE" 8 | } 9 | -------------------------------------------------------------------------------- /test/testdata/ginkgolinter/go.mod: -------------------------------------------------------------------------------- 1 | module ginkgolinter 2 | 3 | go 1.19 4 | 5 | require github.com/onsi/gomega v1.24.1 6 | 7 | require ( 8 | github.com/google/go-cmp v0.5.9 // indirect 9 | golang.org/x/net v0.2.0 // indirect 10 | golang.org/x/text v0.4.0 // indirect 11 | gopkg.in/yaml.v3 v3.0.1 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /test/testdata/tparallel_missing_subtest_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Etparallel 2 | package testdata 3 | 4 | import ( 5 | "testing" 6 | ) 7 | 8 | func TestSubtests(t *testing.T) { // want "TestSubtests's subtests should call t.Parallel" 9 | t.Parallel() 10 | 11 | t.Run("", func(t *testing.T) { 12 | }) 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/varnamelen.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Evarnamelen 2 | package testdata 3 | 4 | import "math" 5 | 6 | func varnamelen() { 7 | x := math.MinInt8 // want "variable name 'x' is too short for the scope of its usage" 8 | x++ 9 | x++ 10 | x++ 11 | x++ 12 | x++ 13 | x++ 14 | x++ 15 | x++ 16 | x++ 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/configs/depguard_ignore_file_rules.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | depguard: 3 | list-type: denylist 4 | include-go-root: true 5 | packages: 6 | - compress/* 7 | packages-with-error-message: 8 | log: "don't use log" 9 | ignore-file-rules: 10 | - "**/*_ignore_file_rules.go" 11 | -------------------------------------------------------------------------------- /test/testdata/containedctx.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Econtainedctx 2 | package testdata 3 | 4 | import "context" 5 | 6 | type ok struct { 7 | i int 8 | s string 9 | } 10 | 11 | type ng struct { 12 | ctx context.Context // want "found a struct that contains a context.Context field" 13 | } 14 | 15 | type empty struct{} 16 | -------------------------------------------------------------------------------- /test/testdata/wrapcheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ewrapcheck 2 | package testdata 3 | 4 | import ( 5 | "encoding/json" 6 | ) 7 | 8 | func do() error { 9 | _, err := json.Marshal(struct{}{}) 10 | if err != nil { 11 | return err // want "error returned from external package is unwrapped" 12 | } 13 | 14 | return nil 15 | } 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.test 2 | .DS_Store 3 | /*.pdf 4 | /*.pprof 5 | /*.txt 6 | /.idea/ 7 | /.vscode/ 8 | /dist/ 9 | /golangci-lint 10 | /test/path 11 | /tools/Dracula.itermcolors 12 | /tools/dist/ 13 | /tools/godownloader 14 | /tools/goreleaser 15 | /tools/node_modules 16 | /tools/svg-term 17 | /vendor/ 18 | coverage.out 19 | coverage.xml 20 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/exclude_rules.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | //go:generate --long line --with a --lot of --arguments --that we --would like --to exclude --from lll --issues --by exclude-rules 4 | 5 | // long line that we don't want to exclude from lll issues. Use the similar pattern: go:generate. This line should be reported by lll 6 | -------------------------------------------------------------------------------- /test/testdata/configs/gosec.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gosec: 3 | includes: 4 | - G306 5 | - G101 6 | config: 7 | G306: "0666" 8 | G101: 9 | pattern: "(?i)simple" 10 | ignore_entropy: false 11 | entropy_threshold: "80.0" 12 | per_char_threshold: "3.0" 13 | truncate: "32" 14 | -------------------------------------------------------------------------------- /test/testdata/misspell.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emisspell 2 | //golangcitest:config_path testdata/configs/misspell.yml 3 | package testdata 4 | 5 | func Misspell() { 6 | // comment with incorrect spelling: occured // want "`occured` is a misspelling of `occurred`" 7 | } 8 | 9 | // the word langauge should be ignored here: it's set in config 10 | -------------------------------------------------------------------------------- /test/testdata/tparallel_missing_toplevel_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Etparallel 2 | package testdata 3 | 4 | import ( 5 | "testing" 6 | ) 7 | 8 | func TestTopLevel(t *testing.T) { // want "TestTopLevel should call t.Parallel on the top level as well as its subtests" 9 | t.Run("", func(t *testing.T) { 10 | t.Parallel() 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /test/testdata/forbidigo_example_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eforbidigo 2 | //golangcitest:config_path testdata/configs/forbidigo.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | import "fmt" 7 | 8 | func ExampleForbidigo() { 9 | fmt.Printf("too noisy!!!") // godoc examples are ignored (in *_test.go files only) 10 | } 11 | -------------------------------------------------------------------------------- /test/testdata/forbidigo_include_godoc_examples_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eforbidigo 2 | //golangcitest:config_path testdata/configs/forbidigo_include_godoc_examples.yml 3 | package testdata 4 | 5 | import "fmt" 6 | 7 | func ExampleForbidigoNoGodoc() { 8 | fmt.Printf("too noisy!!!") // want "use of `fmt.Printf` forbidden by pattern.*" 9 | } 10 | -------------------------------------------------------------------------------- /test/testdata/gofmt_no_simplify.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | //golangcitest:config_path testdata/configs/gofmt_no_simplify.yml 3 | package testdata 4 | 5 | import "fmt" 6 | 7 | func GofmtNotSimplifiedOk() { 8 | var x []string 9 | fmt.Print(x[1:len(x)]) 10 | } 11 | 12 | func GofmtBadFormat(){ // want "^File is not `gofmt`-ed" 13 | } 14 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/components/Homepage.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Index from '../text/index.mdx'; 3 | 4 | import Layout from './Layout'; 5 | import SEO from './SEO'; 6 | 7 | export default function Home() { 8 | return ( 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /test/testdata/deadcode.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edeadcode --internal-cmd-test 2 | package testdata 3 | 4 | var y int 5 | 6 | var unused int // want "`unused` is unused" 7 | 8 | func f(x int) { 9 | } 10 | 11 | func g(x int) { // want "`g` is unused" 12 | } 13 | 14 | func H(x int) { 15 | } 16 | 17 | func init() { 18 | f(y) 19 | } 20 | 21 | var _ int 22 | -------------------------------------------------------------------------------- /test/testdata/ifshort.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | //golangcitest:args -Eifshort --internal-cmd-test 4 | package testdata 5 | 6 | func DontUseShortSyntaxWhenPossible() { 7 | getValue := func() interface{} { return nil } 8 | 9 | v := getValue() // want "variable 'v' is only used in the if-statement .*" 10 | if v != nil { 11 | return 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.github/boring-cyborg.yml: -------------------------------------------------------------------------------- 1 | firstPRWelcomeComment: Hey, thank you for opening your first Pull Request ! 2 | 3 | # Comment to be posted to on first time issues 4 | firstIssueWelcomeComment: > 5 | Hey, thank you for opening your first Issue ! 🙂 6 | If you would like to contribute we have a [guide for contributors](https://golangci-lint.run/contributing/quick-start/). 7 | -------------------------------------------------------------------------------- /test/testdata/cgo/main.go: -------------------------------------------------------------------------------- 1 | package cgoexample 2 | 3 | /* 4 | #include 5 | #include 6 | 7 | void myprint(char* s) { 8 | printf("%d\n", s); 9 | } 10 | */ 11 | import "C" 12 | 13 | import ( 14 | "unsafe" 15 | ) 16 | 17 | func Example() { 18 | cs := C.CString("Hello from stdio\n") 19 | C.myprint(cs) 20 | C.free(unsafe.Pointer(cs)) 21 | } 22 | -------------------------------------------------------------------------------- /test/testdata/decorder_default.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edecorder 2 | //golangcitest:expected_exitcode 0 3 | package testdata 4 | 5 | import "math" 6 | 7 | const ( 8 | decoh = math.MaxInt64 9 | decoi = 1 10 | ) 11 | 12 | var decoj = 1 13 | var decok = 1 14 | 15 | type decol int 16 | 17 | func decom() { 18 | const decon = 1 19 | } 20 | 21 | func init() {} 22 | -------------------------------------------------------------------------------- /test/testdata/errcheck_type_assertions.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrcheck 2 | //golangcitest:config_path testdata/configs/errcheck_type_assertions.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | func ErrorTypeAssertion(filter map[string]interface{}) bool { 7 | return filter["messages_sent.messageid"].(map[string]interface{})["$ne"] != nil 8 | } 9 | -------------------------------------------------------------------------------- /tools/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package tools 5 | 6 | // Manage tool dependencies via go.mod. 7 | // 8 | // https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module 9 | // https://github.com/golang/go/issues/25922 10 | // 11 | //nolint:all 12 | import ( 13 | _ "github.com/goreleaser/goreleaser" 14 | ) 15 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/styles/theme.js: -------------------------------------------------------------------------------- 1 | export default { 2 | colors: { 3 | primary: '#7159c1', 4 | background: '#fff', 5 | sidebar: { 6 | background: '#ffffff', 7 | link: '#999', 8 | heading: '#aaa', 9 | linkActive: '#13131A', 10 | itemActive: '#F5F5FA', 11 | footer: '#A8A8B3', 12 | }, 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /test/testdata/depguard.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edepguard 2 | //golangcitest:config_path testdata/configs/depguard.yml 3 | package testdata 4 | 5 | import ( 6 | "compress/gzip" // want "`compress/gzip` is in the denylist" 7 | "log" // want "`log` is in the denylist: don't use log" 8 | ) 9 | 10 | func SpewDebugInfo() { 11 | log.Println(gzip.BestCompression) 12 | } 13 | -------------------------------------------------------------------------------- /test/testdata/lll_single_import.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Elll 2 | //golangcitest:config_path testdata/configs/lll_import.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | import veryLongImportAliasNameForTest "github.com/golangci/golangci-lint/internal/golinters" 7 | 8 | func LllSingleImport() { 9 | _ = veryLongImportAliasNameForTest.NewLLL(nil) 10 | } 11 | -------------------------------------------------------------------------------- /docs/src/components/ResponsiveContainer.js: -------------------------------------------------------------------------------- 1 | /** @jsxRuntime classic */ 2 | /** @jsx jsx */ 3 | import { css, jsx } from "@emotion/react"; 4 | 5 | const ResponsiveContainer = ({ children }) => ( 6 |
12 | {children} 13 |
14 | ); 15 | 16 | export default ResponsiveContainer; 17 | -------------------------------------------------------------------------------- /test/testdata/exhaustive.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexhaustive 2 | package testdata 3 | 4 | type Direction int 5 | 6 | const ( 7 | North Direction = iota 8 | East 9 | South 10 | West 11 | ) 12 | 13 | func processDirection(d Direction) { 14 | switch d { // want "missing cases in switch of type testdata.Direction: testdata.East, testdata.West" 15 | case North, South: 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/go.mod: -------------------------------------------------------------------------------- 1 | module loggercheck 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/go-kit/log v0.2.1 7 | github.com/go-logr/logr v1.2.3 8 | go.uber.org/zap v1.23.0 9 | k8s.io/klog/v2 v2.70.1 10 | ) 11 | 12 | require ( 13 | github.com/go-logfmt/logfmt v0.5.1 // indirect 14 | go.uber.org/atomic v1.10.0 // indirect 15 | go.uber.org/multierr v1.8.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /test/testdata/tparallel_happy_path_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Etparallel 2 | //golangcitest:expected_exitcode 0 3 | package testdata 4 | 5 | import ( 6 | "testing" 7 | ) 8 | 9 | func TestValidHappyPath(t *testing.T) { 10 | t.Parallel() 11 | t.Run("", func(t *testing.T) { 12 | t.Parallel() 13 | }) 14 | } 15 | 16 | func TestValidNoSubTest(t *testing.T) { 17 | t.Parallel() 18 | } 19 | -------------------------------------------------------------------------------- /cmd/golangci-lint/mod_version.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "runtime/debug" 6 | ) 7 | 8 | //nolint:gochecknoinits 9 | func init() { 10 | if info, available := debug.ReadBuildInfo(); available { 11 | if date == "" { 12 | version = info.Main.Version 13 | commit = fmt.Sprintf("(unknown, mod sum: %q)", info.Main.Sum) 14 | date = "(unknown)" 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/fix/in/gci.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egci 2 | //golangcitest:config_path testdata/configs/gci.yml 3 | //golangcitest:expected_exitcode 0 4 | package gci 5 | 6 | import ( 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/pkg/errors" 9 | "fmt" 10 | ) 11 | 12 | func GoimportsLocalTest() { 13 | fmt.Print("x") 14 | _ = config.Config{} 15 | _ = errors.New("") 16 | } 17 | -------------------------------------------------------------------------------- /test/testdata/forbidigo_example.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eforbidigo 2 | //golangcitest:config_path testdata/configs/forbidigo.yml 3 | package testdata 4 | 5 | import ( 6 | "fmt" 7 | "time" 8 | ) 9 | 10 | func Forbidigo() { 11 | fmt.Printf("too noisy!!!") // want "use of `fmt\\.Printf` forbidden by pattern `fmt\\\\.Print\\.\\*`" 12 | time.Sleep(time.Nanosecond) // want "no sleeping!" 13 | } 14 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Questions 4 | url: https://github.com/golangci/golangci-lint/discussions 5 | about: If you have a question, or are looking for advice, please post on our Discussions forum! 6 | - name: golangci-lint documentation 7 | url: https://golangci-lint.run 8 | about: Please take a look to our documentation. 9 | -------------------------------------------------------------------------------- /docs/src/lib/icons.js: -------------------------------------------------------------------------------- 1 | /** @jsxRuntime classic */ 2 | /** @jsx jsx */ 3 | import { css, jsx } from "@emotion/react"; 4 | 5 | export const IconContainer = ({ color, children }) => ( 6 | 15 | {children} 16 | 17 | ); 18 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/nolint2.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | ) 7 | 8 | func noTransitiveExpanding() { 9 | //nolint:errcheck 10 | var buf io.Writer = &bytes.Buffer{} 11 | buf.Write([]byte("123")) 12 | } 13 | 14 | func nolintFuncByInlineCommentDoesNotWork() { //nolint:errcheck 15 | var buf io.Writer = &bytes.Buffer{} 16 | buf.Write([]byte("123")) 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/depguard_ignore_file_rules.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edepguard 2 | //golangcitest:config_path testdata/configs/depguard_ignore_file_rules.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | // NOTE - No lint errors because this file is ignored 7 | import ( 8 | "compress/gzip" 9 | "log" 10 | ) 11 | 12 | func SpewDebugInfo() { 13 | log.Println(gzip.BestCompression) 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/docs/usage/linters.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Linters 3 | --- 4 | 5 | To see a list of supported linters and which linters are enabled/disabled: 6 | 7 | ```sh 8 | golangci-lint help linters 9 | ``` 10 | 11 | ## Enabled by Default 12 | 13 | {.EnabledByDefaultLinters} 14 | 15 | ## Disabled by Default 16 | 17 | {.DisabledByDefaultLinters} 18 | 19 | ## Linters Configuration 20 | 21 | { .LintersExample } 22 | -------------------------------------------------------------------------------- /test/testdata/fix/out/gci.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egci 2 | //golangcitest:config_path testdata/configs/gci.yml 3 | //golangcitest:expected_exitcode 0 4 | package gci 5 | 6 | import ( 7 | "fmt" 8 | 9 | "github.com/pkg/errors" 10 | 11 | "github.com/golangci/golangci-lint/pkg/config" 12 | ) 13 | 14 | func GoimportsLocalTest() { 15 | fmt.Print("x") 16 | _ = config.Config{} 17 | _ = errors.New("") 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/ireturn_default.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eireturn 2 | package testdata 3 | 4 | type ( 5 | IreturnDoer interface{ Do() } 6 | ireturnDoer struct{} 7 | ) 8 | 9 | func New() IreturnDoer { return new(ireturnDoer) } // want `New returns interface \(command-line-arguments.IreturnDoer\)` 10 | func (d *ireturnDoer) Do() { /*...*/ } 11 | 12 | func Newer() *ireturnDoer { return new(ireturnDoer) } 13 | -------------------------------------------------------------------------------- /internal/renameio/readme.md: -------------------------------------------------------------------------------- 1 | # renameio 2 | 3 | Extracted from go/src/cmd/go/internal/renameio/ 4 | I don't know what version of Go this package was pulled from. 5 | 6 | Adapted for golangci-lint: 7 | - https://github.com/golangci/golangci-lint/pull/699 8 | - https://github.com/golangci/golangci-lint/pull/808 9 | - https://github.com/golangci/golangci-lint/pull/1063 10 | - https://github.com/golangci/golangci-lint/pull/3204 11 | -------------------------------------------------------------------------------- /test/ruleguard/rangeExprCopy.go: -------------------------------------------------------------------------------- 1 | // go:build ruleguard 2 | package ruleguard 3 | 4 | import ( 5 | "github.com/quasilyte/go-ruleguard/dsl" 6 | ) 7 | 8 | func RangeExprVal(m dsl.Matcher) { 9 | m.Match(`for _, $_ := range $x { $*_ }`, `for _, $_ = range $x { $*_ }`). 10 | Where(m["x"].Addressable && m["x"].Type.Size >= 512). 11 | Report(`$x copy can be avoided with &$x`). 12 | At(m["x"]). 13 | Suggest(`&$x`) 14 | } 15 | -------------------------------------------------------------------------------- /test/testdata/fix/in/misspell.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emisspell 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | import "log" 6 | 7 | // langauge lala 8 | // lala langauge 9 | // langauge 10 | // langauge langauge 11 | 12 | // check Langauge 13 | // and check langAuge 14 | 15 | func langaugeMisspell() { 16 | var langauge, langaugeAnd string 17 | log.Printf("it's becouse of them: %s, %s", langauge, langaugeAnd) 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/fix/out/misspell.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emisspell 2 | //golangcitest:expected_exitcode 0 3 | package p 4 | 5 | import "log" 6 | 7 | // language lala 8 | // lala language 9 | // language 10 | // language language 11 | 12 | // check Language 13 | // and check langAuge 14 | 15 | func langaugeMisspell() { 16 | var language, langaugeAnd string 17 | log.Printf("it's because of them: %s, %s", language, langaugeAnd) 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/importas_noalias.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eimportas 2 | //golangcitest:config_path testdata/configs/importas_noalias.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | import ( 7 | wrong_alias "fmt" 8 | "os" 9 | wrong_alias_again "os" 10 | ) 11 | 12 | func ImportAsNoAlias() { 13 | wrong_alias.Println("foo") 14 | wrong_alias_again.Stdout.WriteString("bar") 15 | os.Stdout.WriteString("test") 16 | } 17 | -------------------------------------------------------------------------------- /pkg/result/processors/testdata/nolint_bad_names.go: -------------------------------------------------------------------------------- 1 | package testdata 2 | 3 | import "math" 4 | 5 | func RetErr() error { 6 | return nil 7 | } 8 | 9 | func MissedErrorCheck() { 10 | RetErr() //nolint:bad1,errcheck 11 | } 12 | 13 | //nolint:bad2,errcheck 14 | func MissedErrorCheck2() { 15 | RetErr() 16 | } 17 | 18 | func _() { 19 | x := math.MinInt8 20 | for { 21 | _ = x 22 | x = 0 //nolint:bad1,ineffassign 23 | x = 0 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/testdata/gofmt_rewrite_rules.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | //golangcitest:config_path testdata/configs/gofmt_rewrite_rules.yml 3 | package testdata 4 | 5 | import "fmt" 6 | 7 | func GofmtRewriteRule() { 8 | vals := make([]int, 0) 9 | 10 | vals = append(vals, 1) 11 | vals = append(vals, 2) 12 | vals = append(vals, 3) 13 | 14 | slice := vals[1:len(vals)] // want "^File is not `gofmt`-ed" 15 | 16 | fmt.Println(slice) 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/govet_ifaceassert.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egovet 2 | //golangcitest:config_path testdata/configs/govet_ifaceassert.yml 3 | package testdata 4 | 5 | import ( 6 | "io" 7 | ) 8 | 9 | func GovetIfaceAssert() { 10 | var v interface { 11 | Read() 12 | } 13 | _ = v.(io.Reader) // want "impossible type assertion: no type can implement both interface\\{Read\\(\\)\\} and io\\.Reader \\(conflicting types for Read method\\)" 14 | } 15 | -------------------------------------------------------------------------------- /test/testdata/nlreturn-block-size.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Enlreturn 2 | //golangcitest:config_path testdata/configs/nlreturn.yml 3 | package testdata 4 | 5 | func foo0(n int) int { 6 | if n == 1 { 7 | n2 := n * n 8 | return n2 9 | } 10 | 11 | return 1 12 | } 13 | 14 | func foo1(n int) int { 15 | if n == 1 { 16 | n2 := n * n 17 | n3 := n2 * n 18 | return n3 // want "return with no blank line before" 19 | } 20 | 21 | return 1 22 | } 23 | -------------------------------------------------------------------------------- /test/testdata/notcompiles/typecheck_many_issues.go: -------------------------------------------------------------------------------- 1 | //go:build go1.20 2 | 3 | //golangcitest:args -Etypecheck 4 | package testdata 5 | 6 | func TypeCheckBadCalls() { 7 | typecheckNotExists1.F1() // want "undefined: typecheckNotExists1" 8 | typecheckNotExists2.F2() // want "undefined: typecheckNotExists2" 9 | typecheckNotExists3.F3() // want "undefined: typecheckNotExists3" 10 | typecheckNotExists4.F4() // want "undefined: typecheckNotExists4" 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/scopelint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Escopelint --internal-cmd-test 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func ScopelintTest() { 7 | values := []string{"a", "b", "c"} 8 | var funcs []func() 9 | for _, val := range values { 10 | funcs = append(funcs, func() { 11 | fmt.Println(val) // want "Using the variable on range scope `val` in function literal" 12 | }) 13 | } 14 | for _, f := range funcs { 15 | f() 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.github/peril/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/danger/peril/master/peril-settings-json.schema", 3 | "settings": { 4 | "ignored_repos": [], 5 | "env_vars": ["SLACK_WEBHOOK_URL", "GITHUB_ACCESS_TOKEN"] 6 | }, 7 | "repos": { 8 | "golangci/golangci-lint": { 9 | "pull_request.closed (pull_request.merged == true)": [ 10 | ".github/peril/rules/invite-collaborator.ts" 11 | ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /pkg/golinters/execinquery.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/lufeee/execinquery" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewExecInQuery() *goanalysis.Linter { 11 | a := execinquery.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/golinters/nosnakecase.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/sivchari/nosnakecase" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewNoSnakeCase() *goanalysis.Linter { 11 | a := nosnakecase.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeSyntax) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/golinters/containedctx.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/sivchari/containedctx" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewContainedCtx() *goanalysis.Linter { 11 | a := containedctx.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeSyntax) 19 | } 20 | -------------------------------------------------------------------------------- /test/testdata/errcheck_exclude.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrcheck 2 | //golangcitest:config_path testdata/configs/errcheck_exclude.yml 3 | package testdata 4 | 5 | import ( 6 | "io/ioutil" 7 | ) 8 | 9 | func TestErrcheckExclude() []byte { 10 | ret, _ := ioutil.ReadFile("f.txt") 11 | return ret 12 | } 13 | 14 | func TestErrcheckNoExclude() []byte { 15 | ret, _ := ioutil.ReadAll(nil) // want "Error return value of `ioutil.ReadAll` is not checked" 16 | return ret 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/goconst_calls_enabled.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoconst 2 | //golangcitest:config_path testdata/configs/goconst_calls_enabled.yml 3 | package testdata 4 | 5 | import "fmt" 6 | 7 | const FooBar = "foobar" 8 | 9 | func Baz() { 10 | a := "foobar" // want "string `foobar` has 4 occurrences, but such constant `FooBar` already exists" 11 | fmt.Print(a) 12 | b := "foobar" 13 | fmt.Print(b) 14 | c := "foobar" 15 | fmt.Print(c) 16 | fmt.Print("foobar") 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/reassign_patterns.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ereassign 2 | //golangcitest:config_path testdata/configs/reassign_patterns.yml 3 | package testdata 4 | 5 | import ( 6 | "io" 7 | "net/http" 8 | ) 9 | 10 | func reassignTestPatterns() { 11 | http.DefaultClient = nil // want `reassigning variable DefaultClient in other package http` 12 | http.DefaultTransport = nil // want `reassigning variable DefaultTransport in other package http` 13 | io.EOF = nil 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs-core/util/url.js: -------------------------------------------------------------------------------- 1 | function normalizeBasePath(basePath, link) { 2 | return `/${basePath}/${link}`.replace(/\/\/+/g, `/`); 3 | } 4 | 5 | function isExternalUrl(url) { 6 | return new RegExp('^((https?:)?//)', 'i').test(url); 7 | } 8 | 9 | function resolveLink(link, basePath) { 10 | return isExternalUrl(link) ? link : normalizeBasePath(basePath, link); 11 | } 12 | 13 | module.exports = { resolveLink, normalizeBasePath, isExternalUrl }; 14 | -------------------------------------------------------------------------------- /pkg/golinters/durationcheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/charithe/durationcheck" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewDurationCheck() *goanalysis.Linter { 11 | a := durationcheck.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/golinters/exportloopref.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/kyoh86/exportloopref" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewExportLoopRef() *goanalysis.Linter { 11 | a := exportloopref.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/sliceutil/sliceutil.go: -------------------------------------------------------------------------------- 1 | package sliceutil 2 | 3 | // IndexOf get the index of the given value in the given string slice, 4 | // or -1 if not found. 5 | func IndexOf(slice []string, value string) int { 6 | for i, v := range slice { 7 | if v == value { 8 | return i 9 | } 10 | } 11 | return -1 12 | } 13 | 14 | // Contains check if a string slice contains a value. 15 | func Contains(slice []string, value string) bool { 16 | return IndexOf(slice, value) != -1 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/goimports_local.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoimports 2 | //golangcitest:config_path testdata/configs/goimports_local.yml 3 | package testdata 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/golangci/golangci-lint/pkg/config" // want "File is not `goimports`-ed with -local github.com/golangci/golangci-lint" 9 | "github.com/pkg/errors" 10 | ) 11 | 12 | func GoimportsLocalPrefixTest() { 13 | fmt.Print("x") 14 | _ = config.Config{} 15 | _ = errors.New("") 16 | } 17 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/gatsby/wrapPageElement.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React from 'react'; 3 | import { MDXProvider } from '@mdx-js/react'; 4 | 5 | import Code from '../src/components/Code'; 6 | 7 | const components = { 8 | code: Code, 9 | inlineCode: props => , 10 | }; 11 | 12 | export function wrapPageElement({ element }) { 13 | return {element}; 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/text/index.mdx: -------------------------------------------------------------------------------- 1 | Welcome, this is the default page of `@rocketseat/gatsby-theme-docs` from Rocketseat! To 2 | change this page just create a file named `index.mdx` inside `@rocketseat/gatsby-theme-docs/text` 3 | and place there your text. Also, if you need help, feel free to open an issue with a 4 | description of the problem you're facing or, if you prefer, you can chat with us 5 | on our [Discord Community](https://rocketseat.com.br/comunidade) 👋🏻 6 | -------------------------------------------------------------------------------- /docs/src/docs/product/thanks.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Thanks 3 | --- 4 | 5 | ## ❤️ 6 | 7 | Thanks to all [contributors](https://github.com/golangci/golangci-lint/graphs/contributors)! 8 | 9 | Thanks to [alecthomas/gometalinter](https://github.com/alecthomas/gometalinter) for inspiration and amazing work. 10 | Thanks to [bradleyfalzon/revgrep](https://github.com/bradleyfalzon/revgrep) for cool diff tool. 11 | 12 | Thanks to developers and authors of used linters: 13 | 14 | {.ThanksList} 15 | -------------------------------------------------------------------------------- /pkg/golinters/noctx.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/sonatard/noctx" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewNoctx() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "noctx", 13 | "noctx finds sending http request without context.Context", 14 | []*analysis.Analyzer{noctx.Analyzer}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 17 | } 18 | -------------------------------------------------------------------------------- /scripts/expand_website_templates/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/require" 8 | ) 9 | 10 | func Test_extractExampleSnippets(t *testing.T) { 11 | t.Skip("only for debugging purpose") 12 | 13 | example, err := os.ReadFile("../../../golangci-lint/.golangci.reference.yml") 14 | require.NoError(t, err) 15 | 16 | m, err := extractExampleSnippets(example) 17 | require.NoError(t, err) 18 | 19 | t.Log(m) 20 | } 21 | -------------------------------------------------------------------------------- /test/testdata/makezero_always.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emakezero 2 | //golangcitest:config_path testdata/configs/makezero_always.yml 3 | package testdata 4 | 5 | import "math" 6 | 7 | func MakezeroAlways() []int { 8 | x := make([]int, math.MaxInt8) // want "slice `x` does not have non-zero initial length" 9 | return x 10 | } 11 | 12 | func MakezeroAlwaysNolint() []int { 13 | x := make([]int, math.MaxInt8) //nolint:makezero // ok that this is not initialized 14 | return x 15 | } 16 | -------------------------------------------------------------------------------- /test/testdata/forcetypeassert.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eforcetypeassert 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func forcetypeassertInvalid() { 7 | var a interface{} 8 | _ = a.(int) // want "type assertion must be checked" 9 | 10 | var b interface{} 11 | bi := b.(int) // want "type assertion must be checked" 12 | fmt.Println(bi) 13 | } 14 | 15 | func forcetypeassertValid() { 16 | var a interface{} 17 | if ai, ok := a.(int); ok { 18 | fmt.Println(ai) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/testdata/ireturn_allow.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eireturn 2 | //golangcitest:config_path testdata/configs/ireturn.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | type ( 7 | IreturnAllowDoer interface{ Do() } 8 | ireturnAllowDoer struct{} 9 | ) 10 | 11 | func NewAllowDoer() IreturnAllowDoer { return new(ireturnAllowDoer) } 12 | func (d *ireturnAllowDoer) Do() { /*...*/ } 13 | 14 | func NewerAllowDoer() *ireturnAllowDoer { return new(ireturnAllowDoer) } 15 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs-core/util/with-default.js: -------------------------------------------------------------------------------- 1 | module.exports = themeOptions => { 2 | const basePath = themeOptions.basePath || `/`; 3 | const configPath = themeOptions.configPath || `config`; 4 | const docsPath = themeOptions.docsPath || `docs`; 5 | const baseDir = themeOptions.baseDir || ``; 6 | const { githubUrl } = themeOptions; 7 | 8 | return { 9 | basePath, 10 | configPath, 11 | docsPath, 12 | baseDir, 13 | githubUrl, 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /scripts/print_ast/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "go/ast" 6 | "go/parser" 7 | "go/token" 8 | "log" 9 | ) 10 | 11 | func main() { 12 | var filename string 13 | flag.StringVar(&filename, "f", "", "input file") 14 | flag.Parse() 15 | 16 | fset := token.NewFileSet() 17 | f, err := parser.ParseFile(fset, filename, nil, parser.ParseComments) 18 | if err != nil { 19 | log.Fatalf("Failed to parse file %s: %s", filename, err) 20 | } 21 | ast.Print(fset, f) 22 | } 23 | -------------------------------------------------------------------------------- /test/testdata/configs/depguard_additional_guards.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | depguard: 3 | list-type: denylist 4 | include-go-root: true 5 | packages: 6 | - compress/* 7 | packages-with-error-message: 8 | log: "don't use log" 9 | additional-guards: 10 | - list-type: denylist 11 | include-go-root: true 12 | packages: 13 | - fmt 14 | packages-with-error-message: 15 | strings: "disallowed in additional guard" 16 | 17 | -------------------------------------------------------------------------------- /.github/peril/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "jest": "^29.0.3" 4 | }, 5 | "scripts": { 6 | "test": "jest" 7 | }, 8 | "jest": { 9 | "rootDir": "../", 10 | "roots": [ 11 | "/peril" 12 | ], 13 | "transform": { 14 | "^.+\\.tsx?$": "/node_modules/ts-jest/preprocessor.js" 15 | }, 16 | "moduleFileExtensions": [ 17 | "js", 18 | "jsx", 19 | "ts", 20 | "tsx", 21 | "json" 22 | ] 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/components/Sidebar/InternalLink/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { Link } from 'gatsby'; 4 | 5 | export default function InternalLink({ link, label }) { 6 | return ( 7 | 8 | {label} 9 | 10 | ); 11 | } 12 | 13 | InternalLink.propTypes = { 14 | link: PropTypes.string.isRequired, 15 | label: PropTypes.string.isRequired, 16 | }; 17 | -------------------------------------------------------------------------------- /pkg/golinters/goerr113.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/Djarvur/go-err113" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewGoerr113() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "goerr113", 13 | "Golang linter to check the errors handling expressions", 14 | []*analysis.Analyzer{err113.NewAnalyzer()}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/golinters/nosprintfhostport.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/stbenjam/no-sprintf-host-port/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewNoSprintfHostPort() *goanalysis.Linter { 11 | a := analyzer.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeSyntax) 19 | } 20 | -------------------------------------------------------------------------------- /test/testdata/fix/in/gocritic.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egocritic 2 | //golangcitest:config_path testdata/configs/gocritic-fix.yml 3 | //golangcitest:expected_exitcode 0 4 | package p 5 | 6 | import ( 7 | "strings" 8 | ) 9 | 10 | func gocritic() { 11 | var xs [2048]byte 12 | 13 | // xs -> &xs 14 | for _, x := range xs { 15 | print(x) 16 | } 17 | 18 | // strings.Count("foo", "bar") == 0 -> !strings.Contains("foo", "bar") 19 | if strings.Count("foo", "bar") == 0 { 20 | print("qu") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/testdata/fix/out/gocritic.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egocritic 2 | //golangcitest:config_path testdata/configs/gocritic-fix.yml 3 | //golangcitest:expected_exitcode 0 4 | package p 5 | 6 | import ( 7 | "strings" 8 | ) 9 | 10 | func gocritic() { 11 | var xs [2048]byte 12 | 13 | // xs -> &xs 14 | for _, x := range &xs { 15 | print(x) 16 | } 17 | 18 | // strings.Count("foo", "bar") == 0 -> !strings.Contains("foo", "bar") 19 | if !strings.Contains("foo", "bar") { 20 | print("qu") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/gatsby/wrapRootElement.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | import React from 'react'; 3 | import { ThemeProvider } from '@emotion/react'; 4 | 5 | import defaultTheme from '../src/styles/theme'; 6 | import GlobalStyle from '../src/styles/global'; 7 | 8 | export function wrapRootElement({ element }) { 9 | return ( 10 | 11 | <> 12 | 13 | {element} 14 | 15 | 16 | ); 17 | } 18 | -------------------------------------------------------------------------------- /pkg/golinters/testableexamples.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/maratori/testableexamples/pkg/testableexamples" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewTestableexamples() *goanalysis.Linter { 11 | a := testableexamples.NewAnalyzer() 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeSyntax) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/golinters/wastedassign.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/sanposhiho/wastedassign/v2" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewWastedAssign() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "wastedassign", 13 | "wastedassign finds wasted assignment statements.", 14 | []*analysis.Analyzer{wastedassign.Analyzer}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/gosec_rules_config.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egosec 2 | //golangcitest:config_path testdata/configs/gosec.yml 3 | package testdata 4 | 5 | import "io/ioutil" 6 | 7 | const gosecToken = "62ebc7a03d6ca24dca1258fd4b48462f6fed1545" 8 | const gosecSimple = "62ebc7a03d6ca24dca1258fd4b48462f6fed1545" // want "G101: Potential hardcoded credentials" 9 | 10 | func gosecCustom() { 11 | ioutil.WriteFile("filename", []byte("test"), 0755) // want "G306: Expect WriteFile permissions to be 0666 or less" 12 | } 13 | -------------------------------------------------------------------------------- /pkg/golinters/bodyclose.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/timakin/bodyclose/passes/bodyclose" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewBodyclose() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "bodyclose", 13 | "checks whether HTTP response body is closed successfully", 14 | []*analysis.Analyzer{bodyclose.Analyzer}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/golinters/forcetypeassert.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/gostaticanalysis/forcetypeassert" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewForceTypeAssert() *goanalysis.Linter { 11 | a := forcetypeassert.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | "finds forced type assertions", 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeSyntax) 19 | } 20 | -------------------------------------------------------------------------------- /test/testdata/testableexamples_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Etestableexamples 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func Example_good() { 7 | fmt.Println("hello") 8 | // Output: hello 9 | } 10 | 11 | func Example_goodEmptyOutput() { 12 | fmt.Println("") 13 | // Output: 14 | } 15 | 16 | func Example_bad() { // want `^missing output for example, go test can't validate it$` 17 | fmt.Println("hello") 18 | } 19 | 20 | //nolint:testableexamples 21 | func Example_nolint() { 22 | fmt.Println("hello") 23 | } 24 | -------------------------------------------------------------------------------- /pkg/golinters/asciicheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/tdakkota/asciicheck" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewAsciicheck() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "asciicheck", 13 | "Simple linter to check that your code does not contain non-ASCII identifiers", 14 | []*analysis.Analyzer{asciicheck.NewAnalyzer()}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeSyntax) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/golinters/tparallel.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/moricho/tparallel" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewTparallel() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "tparallel", 13 | "tparallel detects inappropriate usage of t.Parallel() method in your Go test codes", 14 | []*analysis.Analyzer{tparallel.Analyzer}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/gochecknoglobals.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egochecknoglobals 2 | package testdata 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | "regexp" 8 | ) 9 | 10 | var noGlobalsVar int // want "noGlobalsVar is a global variable" 11 | var ErrSomeType = errors.New("test that global erorrs aren't warned") 12 | 13 | var ( 14 | OnlyDigites = regexp.MustCompile(`^\d+$`) 15 | BadNamedErr = errors.New("this is bad") // want "BadNamedErr is a global variable" 16 | ) 17 | 18 | func NoGlobals() { 19 | fmt.Print(noGlobalsVar) 20 | } 21 | -------------------------------------------------------------------------------- /pkg/golinters/ineffassign.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/gordonklaus/ineffassign/pkg/ineffassign" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewIneffassign() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "ineffassign", 13 | "Detects when assignments to existing variables are not used", 14 | []*analysis.Analyzer{ineffassign.Analyzer}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeSyntax) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/golinters/nilerr.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/gostaticanalysis/nilerr" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewNilErr() *goanalysis.Linter { 11 | a := nilerr.Analyzer 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | "Finds the code that returns nil even if it checks that the error is not nil.", 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 19 | } 20 | -------------------------------------------------------------------------------- /pkg/sliceutil/sliceutil_test.go: -------------------------------------------------------------------------------- 1 | package sliceutil 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestContains(t *testing.T) { 10 | assert.True(t, Contains([]string{"val1", "val2", "val3"}, "val2")) 11 | assert.False(t, Contains([]string{"val1", "val2", "val3"}, "val4")) 12 | } 13 | 14 | func TestIndexOf(t *testing.T) { 15 | assert.Equal(t, 1, IndexOf([]string{"val1", "val2", "val3"}, "val2")) 16 | assert.Equal(t, -1, IndexOf([]string{"val1", "val2", "val3"}, "val4")) 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/errcheck_exclude_functions.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrcheck 2 | //golangcitest:config_path testdata/configs/exclude_functions.yml 3 | package testdata 4 | 5 | import ( 6 | "io/ioutil" 7 | ) 8 | 9 | func TestErrcheckExcludeFunctions() []byte { 10 | ret, _ := ioutil.ReadFile("f.txt") 11 | ioutil.ReadDir("dir") 12 | return ret 13 | } 14 | 15 | func TestErrcheckNoExcludeFunctions() []byte { 16 | ret, _ := ioutil.ReadAll(nil) // want "Error return value of `ioutil.ReadAll` is not checked" 17 | return ret 18 | } 19 | -------------------------------------------------------------------------------- /pkg/golinters/gocheckcompilerdirectives.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "4d63.com/gocheckcompilerdirectives/checkcompilerdirectives" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewGoCheckCompilerDirectives() *goanalysis.Linter { 11 | a := checkcompilerdirectives.Analyzer() 12 | 13 | return goanalysis.NewLinter( 14 | a.Name, 15 | a.Doc, 16 | []*analysis.Analyzer{a}, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeSyntax) 19 | } 20 | -------------------------------------------------------------------------------- /test/testdata/dogsled.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edogsled 2 | package testdata 3 | 4 | func Dogsled() { 5 | _ = ret1() 6 | _, _ = ret2() 7 | _, _, _ = ret3() // want "declaration has 3 blank identifiers" 8 | _, _, _, _ = ret4() // want "declaration has 4 blank identifiers" 9 | } 10 | 11 | func ret1() (a int) { 12 | return 1 13 | } 14 | 15 | func ret2() (a, b int) { 16 | return 1, 2 17 | } 18 | 19 | func ret3() (a, b, c int) { 20 | return 1, 2, 3 21 | } 22 | 23 | func ret4() (a, b, c, d int) { 24 | return 1, 2, 3, 4 25 | } 26 | -------------------------------------------------------------------------------- /test/testdata/fix/out/nolintlint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Enolintlint -Elll 2 | //golangcitest:expected_linter nolintlint 3 | package p 4 | 5 | import "fmt" 6 | 7 | func nolintlint() { 8 | fmt.Println() //nolint:bob // leading space should be dropped 9 | fmt.Println() //nolint:bob // leading spaces should be dropped 10 | 11 | // note that the next lines will retain trailing whitespace when fixed 12 | fmt.Println() 13 | fmt.Println() 14 | 15 | fmt.Println() //nolint:alice,lll // we don't drop individual linters from lists 16 | } 17 | -------------------------------------------------------------------------------- /test/testdata/gocheckcompilerdirectives.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egocheckcompilerdirectives 2 | package testdata 3 | 4 | import _ "embed" 5 | 6 | // Okay cases: 7 | 8 | //go:generate echo hello world 9 | 10 | //go:embed 11 | var Value string 12 | 13 | //go: 14 | 15 | // Problematic cases: 16 | 17 | // go:embed // want "compiler directive contains space: // go:embed" 18 | 19 | // go:embed // want "compiler directive contains space: // go:embed" 20 | 21 | //go:genrate // want "compiler directive unrecognized: //go:genrate" 22 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/loggercheck_zaponly.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eloggercheck 2 | //golangcitest:config_path configs/loggercheck_zaponly.yml 3 | package loggercheck 4 | 5 | import "go.uber.org/zap" 6 | 7 | func ExampleZapOnly() { 8 | sugar := zap.NewExample().Sugar() 9 | 10 | sugar.Infow("message", "key1", "value1", "key2") // want `odd number of arguments passed as key-value pairs for logging` 11 | sugar.Errorw("error message", "key1") // want `odd number of arguments passed as key-value pairs for logging` 12 | } 13 | -------------------------------------------------------------------------------- /internal/errorutil/errors.go: -------------------------------------------------------------------------------- 1 | package errorutil 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | // PanicError can be used to not print stacktrace twice 8 | type PanicError struct { 9 | recovered interface{} 10 | stack []byte 11 | } 12 | 13 | func NewPanicError(recovered interface{}, stack []byte) *PanicError { 14 | return &PanicError{recovered: recovered, stack: stack} 15 | } 16 | 17 | func (e PanicError) Error() string { 18 | return fmt.Sprint(e.recovered) 19 | } 20 | 21 | func (e PanicError) Stack() []byte { 22 | return e.stack 23 | } 24 | -------------------------------------------------------------------------------- /pkg/config/severity.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | const severityRuleMinConditionsCount = 1 4 | 5 | type Severity struct { 6 | Default string `mapstructure:"default-severity"` 7 | CaseSensitive bool `mapstructure:"case-sensitive"` 8 | Rules []SeverityRule `mapstructure:"rules"` 9 | } 10 | 11 | type SeverityRule struct { 12 | BaseRule `mapstructure:",squash"` 13 | Severity string 14 | } 15 | 16 | func (s *SeverityRule) Validate() error { 17 | return s.BaseRule.Validate(severityRuleMinConditionsCount) 18 | } 19 | -------------------------------------------------------------------------------- /pkg/golinters/sqlclosecheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/ryanrolds/sqlclosecheck/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewSQLCloseCheck() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "sqlclosecheck", 13 | "Checks that sql.Rows and sql.Stmt are closed.", 14 | []*analysis.Analyzer{ 15 | analyzer.NewAnalyzer(), 16 | }, 17 | nil, 18 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 19 | } 20 | -------------------------------------------------------------------------------- /test/testdata/fix/out/gofmt_rewrite_rules.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | //golangcitest:config_path testdata/configs/gofmt_rewrite_rules.yml 3 | //golangcitest:expected_exitcode 0 4 | package p 5 | 6 | import "fmt" 7 | 8 | func GofmtRewriteRule() { 9 | values := make([]int, 0) 10 | 11 | values = append(values, 1) 12 | values = append(values, 2) 13 | values = append(values, 3) 14 | 15 | slice := values[1:] 16 | 17 | fmt.Println(slice) 18 | } 19 | 20 | func GofmtRewriteRule2() { 21 | var to any 22 | 23 | fmt.Println(to) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/golinters/errname.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/Antonboom/errname/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewErrName() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "errname", 13 | "Checks that sentinel errors are prefixed with the `Err` and error types are suffixed with the `Error`.", 14 | []*analysis.Analyzer{analyzer.New()}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 17 | } 18 | -------------------------------------------------------------------------------- /pkg/golinters/goprintffuncname.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/jirfag/go-printf-func-name/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewGoPrintfFuncName() *goanalysis.Linter { 11 | return goanalysis.NewLinter( 12 | "goprintffuncname", 13 | "Checks that printf-like functions are named with `f` at the end", 14 | []*analysis.Analyzer{analyzer.Analyzer}, 15 | nil, 16 | ).WithLoadMode(goanalysis.LoadModeSyntax) 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/lll_multi_import.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Elll 2 | //golangcitest:config_path testdata/configs/lll_import.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | import ( 7 | anotherVeryLongImportAliasNameForTest "github.com/golangci/golangci-lint/internal/golinters" 8 | veryLongImportAliasNameForTest "github.com/golangci/golangci-lint/internal/golinters" 9 | ) 10 | 11 | func LllMultiImport() { 12 | _ = veryLongImportAliasNameForTest.NewLLL(nil) 13 | _ = anotherVeryLongImportAliasNameForTest.NewLLL(nil) 14 | } 15 | -------------------------------------------------------------------------------- /test/testdata/dupword.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edupword 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func duplicateWordInComments() { 7 | // this line include duplicated word the the // want `Duplicate words \(the\) found` 8 | fmt.Println("hello") 9 | } 10 | 11 | func duplicateWordInStr() { 12 | a := "this line include duplicate word and and" // want `Duplicate words \(and\) found` 13 | b := "print the\n the line, print the the \n\t the line. and and" // want `Duplicate words \(and,the\) found` 14 | fmt.Println(a, b) 15 | } 16 | -------------------------------------------------------------------------------- /test/testdata/decorder.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edecorder 2 | //golangcitest:config_path testdata/configs/decorder.yml 3 | package testdata 4 | 5 | import "math" 6 | 7 | const ( 8 | decoc = math.MaxInt64 9 | decod = 1 10 | ) 11 | 12 | var decoa = 1 13 | var decob = 1 // want "multiple \"var\" declarations are not allowed; use parentheses instead" 14 | 15 | type decoe int // want "type must not be placed after const" 16 | 17 | func decof() { 18 | const decog = 1 19 | } 20 | 21 | func init() {} // want "init func must be the first function in file" 22 | -------------------------------------------------------------------------------- /test/testdata/thelper_with_options.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ethelper 2 | //golangcitest:config_path testdata/configs/thelper.yml 3 | package testdata 4 | 5 | import "testing" 6 | 7 | func thelperWithHelperAfterAssignmentWO(t *testing.T) { // want "test helper function should start from t.Helper()" 8 | _ = 0 9 | t.Helper() 10 | } 11 | 12 | func thelperWithNotFirstWO(s string, t *testing.T, i int) { // want `parameter \*testing.T should be the first` 13 | t.Helper() 14 | } 15 | 16 | func thelperWithIncorrectNameWO(o *testing.T) { 17 | o.Helper() 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/fix/in/gofmt_rewrite_rules.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egofmt 2 | //golangcitest:config_path testdata/configs/gofmt_rewrite_rules.yml 3 | //golangcitest:expected_exitcode 0 4 | package p 5 | 6 | import "fmt" 7 | 8 | func GofmtRewriteRule() { 9 | values := make([]int, 0) 10 | 11 | values = append(values, 1) 12 | values = append(values, 2) 13 | values = append(values, 3) 14 | 15 | slice := values[1:len(values)] 16 | 17 | fmt.Println(slice) 18 | } 19 | 20 | func GofmtRewriteRule2() { 21 | var to interface{} 22 | 23 | fmt.Println(to) 24 | } 25 | -------------------------------------------------------------------------------- /test/testdata/linedirective/hello.go: -------------------------------------------------------------------------------- 1 | // Refers a existent, but non-go file with line directive 2 | //line hello.tmpl:1 3 | package main 4 | 5 | import ( 6 | "github.com/ryancurrah/gomodguard" 7 | ) 8 | 9 | func _() { 10 | var x int 11 | _ = x 12 | x = 0 //x 13 | } 14 | 15 | func main() { 16 | a() 17 | b() 18 | wsl() 19 | } 20 | 21 | func a() { 22 | fmt.Println("foo") 23 | } 24 | 25 | func b() { 26 | fmt.Println("foo") 27 | } 28 | 29 | func wsl() bool { 30 | 31 | return true 32 | } 33 | 34 | func notFormatted() { 35 | } 36 | 37 | // langauge 38 | -------------------------------------------------------------------------------- /test/testdata/ireturn_reject_stdlib.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eireturn 2 | //golangcitest:config_path testdata/configs/ireturn_stdlib_reject.yml 3 | package testdata 4 | 5 | import ( 6 | "bytes" 7 | "io" 8 | ) 9 | 10 | func NewWriter() io.Writer { // want `NewWriter returns interface \(io.Writer\)` 11 | var buf bytes.Buffer 12 | return &buf 13 | } 14 | 15 | func TestError() error { 16 | return nil 17 | } 18 | 19 | type Foo interface { 20 | Foo() 21 | } 22 | type foo int 23 | 24 | func (f foo) Foo() {} 25 | 26 | func NewFoo() Foo { 27 | return foo(1) 28 | } 29 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/configs/loggercheck_custom.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | loggercheck: 3 | rules: 4 | - (*command-line-arguments.Logger).Debugw 5 | - (*command-line-arguments.Logger).Infow 6 | - (*command-line-arguments.Logger).Warnw 7 | - (*command-line-arguments.Logger).Errorw 8 | - (*command-line-arguments.Logger).With 9 | - command-line-arguments.Debugw 10 | - command-line-arguments.Infow 11 | - command-line-arguments.Warnw 12 | - command-line-arguments.Errorw 13 | - command-line-arguments.With 14 | -------------------------------------------------------------------------------- /test/testdata/tenv_go118.go: -------------------------------------------------------------------------------- 1 | //go:build go1.18 2 | 3 | //golangcitest:args -Etenv 4 | package testdata 5 | 6 | import ( 7 | "os" 8 | "testing" 9 | ) 10 | 11 | func FuzzF(f *testing.F) { 12 | os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `f\\.Setenv\\(\\)` in FuzzF" 13 | err := os.Setenv("a", "b") // want "os\\.Setenv\\(\\) can be replaced by `f\\.Setenv\\(\\)` in FuzzF" 14 | _ = err 15 | if err := os.Setenv("a", "b"); err != nil { // want "os\\.Setenv\\(\\) can be replaced by `f\\.Setenv\\(\\)` in FuzzF" 16 | _ = err 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/nolintlint_unused.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Enolintlint -Evarcheck 2 | //golangcitest:expected_linter nolintlint 3 | //golangcitest:config_path testdata/configs/nolintlint_unused.yml 4 | package testdata 5 | 6 | import "fmt" 7 | 8 | func Foo() { 9 | fmt.Println("unused") //nolint:all // want "directive `//nolint .*` is unused" 10 | fmt.Println("unused,specific") //nolint:varcheck // want "directive `//nolint:varcheck .*` is unused for linter varcheck" 11 | fmt.Println("not run") //nolint:unparam // unparam is not run so this is ok 12 | } 13 | -------------------------------------------------------------------------------- /cmd/golangci-lint/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | 7 | "github.com/golangci/golangci-lint/pkg/commands" 8 | "github.com/golangci/golangci-lint/pkg/exitcodes" 9 | ) 10 | 11 | var ( 12 | // Populated by goreleaser during build 13 | version = "master" 14 | commit = "?" 15 | date = "" 16 | ) 17 | 18 | func main() { 19 | e := commands.NewExecutor(version, commit, date) 20 | 21 | if err := e.Execute(); err != nil { 22 | fmt.Fprintf(os.Stderr, "failed executing command with error %v\n", err) 23 | os.Exit(exitcodes.Failure) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /internal/robustio/robustio_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package robustio 6 | 7 | import ( 8 | "errors" 9 | "syscall" 10 | ) 11 | 12 | const errFileNotFound = syscall.ENOENT 13 | 14 | // isEphemeralError returns true if err may be resolved by waiting. 15 | func isEphemeralError(err error) bool { 16 | var errno syscall.Errno 17 | if errors.As(err, &errno) { 18 | return errno == errFileNotFound 19 | } 20 | return false 21 | } 22 | -------------------------------------------------------------------------------- /test/testdata/staticcheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Estaticcheck 2 | package testdata 3 | 4 | import ( 5 | "fmt" 6 | ) 7 | 8 | func Staticcheck() { 9 | var x int 10 | x = x // want "self-assignment of x to x" 11 | fmt.Printf("%d", x) 12 | } 13 | 14 | func StaticcheckNolintStaticcheck() { 15 | var x int 16 | x = x //nolint:staticcheck 17 | } 18 | 19 | func StaticcheckNolintMegacheck() { 20 | var x int 21 | x = x //nolint:megacheck 22 | } 23 | 24 | func StaticcheckPrintf() { 25 | x := "dummy" 26 | fmt.Printf("%d", x) // want "SA5009: Printf format %d has arg #1 of wrong type" 27 | } 28 | -------------------------------------------------------------------------------- /pkg/exitcodes/exitcodes.go: -------------------------------------------------------------------------------- 1 | package exitcodes 2 | 3 | const ( 4 | Success = iota 5 | IssuesFound 6 | WarningInTest 7 | Failure 8 | Timeout 9 | NoGoFiles 10 | NoConfigFileDetected 11 | ErrorWasLogged 12 | ) 13 | 14 | type ExitError struct { 15 | Message string 16 | Code int 17 | } 18 | 19 | func (e ExitError) Error() string { 20 | return e.Message 21 | } 22 | 23 | var ( 24 | ErrNoGoFiles = &ExitError{ 25 | Message: "no go files to analyze", 26 | Code: NoGoFiles, 27 | } 28 | ErrFailure = &ExitError{ 29 | Message: "failed to analyze", 30 | Code: Failure, 31 | } 32 | ) 33 | -------------------------------------------------------------------------------- /test/testdata/configs/revive.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | revive: 3 | ignore-generated-header: true 4 | severity: warning 5 | rules: 6 | - name: exported 7 | - name: package-comments 8 | - name: cognitive-complexity 9 | arguments: [ 7 ] 10 | - name: line-length-limit 11 | arguments: [ 130 ] 12 | - name: function-result-limit 13 | arguments: [ 3 ] 14 | - name: argument-limit 15 | arguments: [ 4 ] 16 | - name: cyclomatic 17 | arguments: [ 10 ] 18 | - name: max-public-structs 19 | arguments: [ 3 ] 20 | -------------------------------------------------------------------------------- /test/testdata/paralleltest_custom.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eparalleltest 2 | //golangcitest:config_path testdata/configs/paralleltest.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | ) 10 | 11 | func TestParallelTestIgnore(t *testing.T) { 12 | testCases := []struct { 13 | name string 14 | }{{name: "foo"}} 15 | for _, tc := range testCases { 16 | tc := tc 17 | t.Run(tc.name, func(t *testing.T) { 18 | t.Parallel() 19 | fmt.Println(tc.name) 20 | }) 21 | } 22 | } 23 | 24 | func TestParallelTestEmptyIgnore(t *testing.T) {} 25 | -------------------------------------------------------------------------------- /pkg/result/processors/max_from_linter_test.go: -------------------------------------------------------------------------------- 1 | package processors 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/golangci/golangci-lint/pkg/config" 7 | "github.com/golangci/golangci-lint/pkg/logutils" 8 | ) 9 | 10 | func TestMaxFromLinter(t *testing.T) { 11 | p := NewMaxFromLinter(1, logutils.NewStderrLog(logutils.DebugKeyEmpty), &config.Config{}) 12 | gosimple := newFromLinterIssue("gosimple") 13 | gofmt := newFromLinterIssue("gofmt") 14 | processAssertSame(t, p, gosimple) // ok 15 | processAssertSame(t, p, gofmt) // ok: another 16 | processAssertEmpty(t, p, gosimple) // skip 17 | } 18 | -------------------------------------------------------------------------------- /test/testdata/cgo_with_issues/main.go: -------------------------------------------------------------------------------- 1 | package cgoexample 2 | 3 | /* 4 | #include 5 | #include 6 | 7 | void myprint(char* s) { 8 | printf("%s\n", s); 9 | } 10 | */ 11 | import "C" 12 | 13 | import ( 14 | "fmt" 15 | "unsafe" 16 | ) 17 | 18 | func Example() { 19 | cs := C.CString("Hello from stdio\n") 20 | C.myprint(cs) 21 | fmt.Printf("bad format %t", cs) 22 | C.free(unsafe.Pointer(cs)) 23 | } 24 | 25 | func notFormattedForGofmt() { 26 | } 27 | 28 | func errorForRevive(p *int) error { 29 | if p == nil { 30 | return nil 31 | } else { 32 | return nil 33 | } 34 | } 35 | 36 | -------------------------------------------------------------------------------- /test/testdata/cyclop.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Ecyclop 2 | //golangcitest:config_path testdata/configs/cyclop.yml 3 | package testdata 4 | 5 | func cyclopComplexFunc(s string) { // want "calculated cyclomatic complexity for function cyclopComplexFunc is 22, max is 15" 6 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 7 | return 8 | } 9 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 10 | return 11 | } 12 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 13 | return 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/testdata/gci.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egci 2 | //golangcitest:config_path testdata/configs/gci.yml 3 | package testdata 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/golangci/golangci-lint/pkg/config" // want "File is not \\`gci\\`-ed with --skip-generated -s standard,prefix\\(github.com/golangci/golangci-lint\\),default" 9 | 10 | "github.com/pkg/errors" // want "File is not \\`gci\\`-ed with --skip-generated -s standard,prefix\\(github.com/golangci/golangci-lint\\),default" 11 | ) 12 | 13 | func GoimportsLocalTest() { 14 | fmt.Print("x") 15 | _ = config.Config{} 16 | _ = errors.New("") 17 | } 18 | -------------------------------------------------------------------------------- /scripts/gen_github_action_config/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/golangci/golangci-lint/scripts/gen_github_action_config 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/shurcooL/githubv4 v0.0.0-20220922232305-70b4d362a8cb 7 | golang.org/x/oauth2 v0.0.0-20221014153046-6fdb5e3db783 8 | ) 9 | 10 | require ( 11 | github.com/golang/protobuf v1.5.2 // indirect 12 | github.com/shurcooL/graphql v0.0.0-20220606043923-3cf50f8a0a29 // indirect 13 | golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect 14 | google.golang.org/appengine v1.6.7 // indirect 15 | google.golang.org/protobuf v1.28.0 // indirect 16 | ) 17 | -------------------------------------------------------------------------------- /test/testdata/paralleltest.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eparalleltest 2 | package testdata 3 | 4 | import ( 5 | "fmt" 6 | "testing" 7 | ) 8 | 9 | func TestFunctionSuccessfulRangeTest(t *testing.T) { 10 | t.Parallel() 11 | 12 | testCases := []struct { 13 | name string 14 | }{{name: "foo"}} 15 | for _, tc := range testCases { 16 | tc := tc 17 | t.Run(tc.name, func(t *testing.T) { 18 | t.Parallel() 19 | fmt.Println(tc.name) 20 | }) 21 | } 22 | } 23 | 24 | func TestFunctionMissingCallToParallel(t *testing.T) {} // want "Function TestFunctionMissingCallToParallel missing the call to method parallel" 25 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/components/Sidebar/ExternalLink/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { FiExternalLink } from 'react-icons/fi'; 4 | 5 | export default function ExternalLink({ link, label }) { 6 | return ( 7 | 8 | {label} 9 | 12 | 13 | ); 14 | } 15 | 16 | ExternalLink.propTypes = { 17 | link: PropTypes.string.isRequired, 18 | label: PropTypes.string.isRequired, 19 | }; 20 | -------------------------------------------------------------------------------- /docs/src/pages/404.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "gatsby"; 3 | 4 | import Layout from "@rocketseat/gatsby-theme-docs/src/components/Layout"; 5 | import SEO from "@rocketseat/gatsby-theme-docs/src/components/SEO"; 6 | 7 | export default function NotFound() { 8 | return ( 9 | 10 | 11 |

You just hit a route that doesn't exist... the sadness.

12 |

13 | If you'd like to go back to homepage, click here 14 | . 15 |

16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/fix/in/nolintlint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Enolintlint -Elll 2 | //golangcitest:expected_linter nolintlint 3 | package p 4 | 5 | import "fmt" 6 | 7 | func nolintlint() { 8 | fmt.Println() // nolint:bob // leading space should be dropped 9 | fmt.Println() // nolint:bob // leading spaces should be dropped 10 | 11 | // note that the next lines will retain trailing whitespace when fixed 12 | fmt.Println() //nolint:all // nolint should be dropped 13 | fmt.Println() //nolint:lll // nolint should be dropped 14 | 15 | fmt.Println() //nolint:alice,lll // we don't drop individual linters from lists 16 | } 17 | -------------------------------------------------------------------------------- /test/testdata/unused.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eunused 2 | package testdata 3 | 4 | func fn1() {} // want "func `fn1` is unused" 5 | 6 | //nolint:unused 7 | func fn2() { fn3() } 8 | 9 | func fn3() {} // want "func `fn3` is unused" 10 | 11 | func fn4() { fn5() } // want "func `fn4` is unused" 12 | 13 | func fn5() {} // want "func `fn5` is unused" 14 | 15 | func fn6() { fn4() } // want "func `fn6` is unused" 16 | 17 | type unusedStruct struct{} // want "type `unusedStruct` is unused" 18 | 19 | type unusedStructNolintUnused struct{} //nolint:unused 20 | 21 | type unusedStructNolintMegacheck struct{} //nolint:megacheck 22 | -------------------------------------------------------------------------------- /test/testdata/errcheck_ignore_default.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrcheck 2 | //golangcitest:config_path testdata/configs/errcheck_ignore_default.yml 3 | package testdata 4 | 5 | import ( 6 | "crypto/sha256" 7 | "fmt" 8 | "os" 9 | ) 10 | 11 | func TestErrcheckIgnoreHashWriteByDefault() []byte { 12 | h := sha256.New() 13 | h.Write([]byte("food")) 14 | return h.Sum(nil) 15 | } 16 | 17 | func TestErrcheckIgnoreFmtByDefault(s string) int { 18 | n, _ := fmt.Println(s) 19 | return n 20 | } 21 | 22 | func TestErrcheckNoIgnoreOs() { 23 | _, _ = os.Open("f.txt") // want "Error return value of `os.Open` is not checked" 24 | } 25 | -------------------------------------------------------------------------------- /test/testdata/exhaustive_ignore_enum_members.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexhaustive 2 | //golangcitest:config_path testdata/configs/exhaustive_ignore_enum_members.yml 3 | package testdata 4 | 5 | type Direction int 6 | 7 | const ( 8 | North Direction = iota 9 | East 10 | South 11 | West 12 | ) 13 | 14 | // Should only report East as missing because the enum member West is ignored 15 | // using the ignore-enum-members setting. 16 | 17 | func processDirectionIgnoreEnumMembers(d Direction) { 18 | switch d { // want "missing cases in switch of type testdata.Direction: testdata.East" 19 | case North, South: 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/testdata/staticcheck_in_megacheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emegacheck 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func StaticcheckInMegacheck() { 7 | var x int 8 | x = x // want staticcheck:"self-assignment of x to x" 9 | fmt.Printf("%d", x) 10 | } 11 | 12 | func StaticcheckNolintStaticcheckInMegacheck() { 13 | var x int 14 | x = x //nolint:staticcheck 15 | } 16 | 17 | func StaticcheckNolintMegacheckInMegacheck() { 18 | var x int 19 | x = x //nolint:megacheck 20 | } 21 | 22 | func Staticcheck2() { 23 | var x int 24 | x = x // want staticcheck:"self-assignment of x to x" 25 | fmt.Printf("%d", x) 26 | } 27 | -------------------------------------------------------------------------------- /test/testdata/gocyclo.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egocyclo 2 | //golangcitest:config_path testdata/configs/gocyclo.yml 3 | package testdata 4 | 5 | import "net/http" 6 | 7 | func GocycloBigComplexity(s string) { // want "cyclomatic complexity .* of func .* is high .*" 8 | if s == http.MethodGet || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 9 | return 10 | } 11 | 12 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 13 | return 14 | } 15 | 16 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 17 | return 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/testdata/gosimple.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egosimple 2 | package testdata 3 | 4 | import ( 5 | "log" 6 | ) 7 | 8 | func Gosimple(ss []string) { 9 | if ss != nil { // want "S1031: unnecessary nil check around range" 10 | for _, s := range ss { 11 | log.Printf(s) 12 | } 13 | } 14 | } 15 | 16 | func GosimpleNolintGosimple(ss []string) { 17 | if ss != nil { //nolint:gosimple 18 | for _, s := range ss { 19 | log.Printf(s) 20 | } 21 | } 22 | } 23 | 24 | func GosimpleNolintMegacheck(ss []string) { 25 | if ss != nil { //nolint:megacheck 26 | for _, s := range ss { 27 | log.Printf(s) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/loggercheck_noprintflike.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eloggercheck 2 | //golangcitest:config_path configs/loggercheck_noprintflike.yml 3 | package loggercheck 4 | 5 | import ( 6 | "github.com/go-logr/logr" 7 | ) 8 | 9 | func ExampleNoPrintfLike() { 10 | log := logr.Discard() 11 | 12 | log.Info("This message is ok") 13 | log.Info("Should not contains printf like format specifiers: %s %d %w") // want `logging message should not use format specifier "%s"` 14 | log.Info("It also checks for the key value pairs", "key", "value %.2f") // want `logging message should not use format specifier "%\.2f"` 15 | } 16 | -------------------------------------------------------------------------------- /test/testdata/exhaustive_generated.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexhaustive 2 | //golangcitest:expected_exitcode 0 3 | package testdata 4 | 5 | // Code generated by some program. DO NOT EDIT. 6 | 7 | // Should not report missing cases in the switch statement below, because this 8 | // is a generated file as indicated by the above comment 9 | // (golang.org/s/generatedcode), and check-generated setting is false. 10 | 11 | type Direction int 12 | 13 | const ( 14 | North Direction = iota 15 | East 16 | South 17 | West 18 | ) 19 | 20 | func processDirectionGenerated(d Direction) { 21 | switch d { 22 | case North, South: 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/util/slug.js: -------------------------------------------------------------------------------- 1 | export default function(string) { 2 | return string 3 | .toString() // Cast to string 4 | .toLowerCase() // Convert the string to lowercase letters 5 | .trim() // Remove whitespace from both sides of a string 6 | .replace(/\s/g, '-') // Replace each space with - 7 | .replace( 8 | /[^\w\-\u00b4\u00C0-\u00C3\u00c7\u00C9-\u00CA\u00CD\u00D3-\u00D5\u00DA\u00E0-\u00E3\u00E7\u00E9-\u00EA\u00ED\u00F3-\u00F5\u00FA]+/g, 9 | '', 10 | ); // Removes all chars that aren't words, -, ´ or some latin characters (À Á Â Ã Ç É Ê Í Ó Ô Õ Ú à á â ã ç é ê í ó ô õ ú) 11 | } 12 | -------------------------------------------------------------------------------- /test/testdata/musttag.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emusttag 2 | package testdata 3 | 4 | import ( 5 | "encoding/asn1" 6 | "encoding/json" 7 | ) 8 | 9 | // builtin functions: 10 | func musttagJSON() { 11 | var user struct { // want "`anonymous struct` should be annotated with the `json` tag as it is passed to `json.Marshal` at test(/|\\\\)testdata(/|\\\\)musttag.go:15:2" 12 | Name string 13 | Email string `json:"email"` 14 | } 15 | json.Marshal(user) 16 | } 17 | 18 | // custom functions from config: 19 | func musttagASN1() { 20 | var user struct { 21 | Name string 22 | Email string `asn1:"email"` 23 | } 24 | asn1.Marshal(user) 25 | } 26 | -------------------------------------------------------------------------------- /test/testdata/predeclared.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Epredeclared 2 | package testdata 3 | 4 | func hello() { 5 | var real int // want "variable real has same name as predeclared identifier" 6 | a := A{} 7 | copy := Clone(a) // want "variable copy has same name as predeclared identifier" 8 | 9 | // suppress any "declared but not used" errors 10 | _ = real 11 | _ = a 12 | _ = copy 13 | } 14 | 15 | type A struct { 16 | true bool 17 | foo int 18 | } 19 | 20 | func Clone(a A) A { 21 | return A{ 22 | true: a.true, 23 | foo: a.foo, 24 | } 25 | } 26 | 27 | func recover() {} // want "function recover has same name as predeclared identifier" 28 | -------------------------------------------------------------------------------- /docs/src/docs/contributing/debug.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Debugging 3 | --- 4 | 5 | You can see a verbose output of linter by using `-v` option. 6 | 7 | ```bash 8 | golangci-lint run -v 9 | ``` 10 | 11 | If you would like to see more detailed logs you can use the environment variable `GL_DEBUG`. 12 | Its value is a list of debug tags. 13 | 14 | The existing debug tags are documented in the following file: https://github.com/golangci/golangci-lint/blob/master/pkg/logutils/logutils.go 15 | 16 | For example: 17 | 18 | ```bash 19 | GL_DEBUG="loader,gocritic" golangci-lint run 20 | ``` 21 | 22 | ```bash 23 | GL_DEBUG="loader,env" golangci-lint run 24 | ``` 25 | -------------------------------------------------------------------------------- /pkg/packages/skip.go: -------------------------------------------------------------------------------- 1 | package packages 2 | 3 | import ( 4 | "fmt" 5 | "path/filepath" 6 | "regexp" 7 | ) 8 | 9 | func pathElemReImpl(e string, sep rune) string { 10 | escapedSep := regexp.QuoteMeta(string(sep)) // needed for windows sep '\\' 11 | return fmt.Sprintf(`(^|%s)%s($|%s)`, escapedSep, e, escapedSep) 12 | } 13 | 14 | func pathElemRe(e string) string { 15 | return pathElemReImpl(e, filepath.Separator) 16 | } 17 | 18 | var StdExcludeDirRegexps = []string{ 19 | pathElemRe("vendor"), 20 | pathElemRe("third_party"), 21 | pathElemRe("testdata"), 22 | pathElemRe("examples"), 23 | pathElemRe("Godeps"), 24 | pathElemRe("builtin"), 25 | } 26 | -------------------------------------------------------------------------------- /pkg/result/processors/max_same_issues_test.go: -------------------------------------------------------------------------------- 1 | package processors 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/golangci/golangci-lint/pkg/config" 7 | "github.com/golangci/golangci-lint/pkg/logutils" 8 | "github.com/golangci/golangci-lint/pkg/result" 9 | ) 10 | 11 | func TestMaxSameIssues(t *testing.T) { 12 | p := NewMaxSameIssues(1, logutils.NewStderrLog(logutils.DebugKeyEmpty), &config.Config{}) 13 | i1 := result.Issue{ 14 | Text: "1", 15 | } 16 | i2 := result.Issue{ 17 | Text: "2", 18 | } 19 | 20 | processAssertSame(t, p, i1) // ok 21 | processAssertSame(t, p, i2) // ok: another 22 | processAssertEmpty(t, p, i1) // skip 23 | } 24 | -------------------------------------------------------------------------------- /test/testdata/predeclared_custom.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Epredeclared 2 | //golangcitest:config_path testdata/configs/predeclared.yml 3 | package testdata 4 | 5 | func hello() { 6 | var real int 7 | a := A{} 8 | copy := Clone(a) // want "variable copy has same name as predeclared identifier" 9 | 10 | // suppress any "declared but not used" errors 11 | _ = real 12 | _ = a 13 | _ = copy 14 | } 15 | 16 | type A struct { 17 | true bool // want "field true has same name as predeclared identifier" 18 | foo int 19 | } 20 | 21 | func Clone(a A) A { 22 | return A{ 23 | true: a.true, 24 | foo: a.foo, 25 | } 26 | } 27 | 28 | func recover() {} 29 | -------------------------------------------------------------------------------- /docs/src/docs/contributing/quick-start.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Contributing Quick Start 3 | --- 4 | 5 | 1. [Contributing workflow](/contributing/workflow/): about our workflow and environment setup. 6 | 2. [Architecture of golangci-lint](/contributing/architecture/) 7 | 3. [How to add new linters](/contributing/new-linters/) 8 | 4. [Debugging golangci-lint](/contributing/debug/) 9 | 5. [Contributing FAQ](/contributing/faq/) 10 | 6. [Contributing to the website](/contributing/website/) 11 | 12 | We have [good issues for first-time contributing](https://github.com/golangci/golangci-lint/issues?q=is%3Aopen+label%3A%22good+first+issue%22+sort%3Areactions-%2B1-desc). 13 | -------------------------------------------------------------------------------- /pkg/golinters/typecheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "golang.org/x/tools/go/analysis" 5 | 6 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 7 | ) 8 | 9 | func NewTypecheck() *goanalysis.Linter { 10 | const linterName = "typecheck" 11 | 12 | analyzer := &analysis.Analyzer{ 13 | Name: linterName, 14 | Doc: goanalysis.TheOnlyanalyzerDoc, 15 | Run: goanalysis.DummyRun, 16 | } 17 | 18 | return goanalysis.NewLinter( 19 | linterName, 20 | "Like the front-end of a Go compiler, parses and type-checks Go code", 21 | []*analysis.Analyzer{analyzer}, 22 | nil, 23 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 24 | } 25 | -------------------------------------------------------------------------------- /test/testdata/depguard_additional_guards.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Edepguard 2 | //golangcitest:config_path testdata/configs/depguard_additional_guards.yml 3 | package testdata 4 | 5 | import ( 6 | "compress/gzip" // want "`compress/gzip` is in the denylist" 7 | "fmt" // want "`fmt` is in the denylist" 8 | "log" // want "`log` is in the denylist: don't use log" 9 | "strings" // want "`strings` is in the denylist: disallowed in additional guard" 10 | ) 11 | 12 | func SpewDebugInfo() { 13 | log.Println(gzip.BestCompression) 14 | log.Println(fmt.Sprintf("SpewDebugInfo")) 15 | log.Println(strings.ToLower("SpewDebugInfo")) 16 | } 17 | -------------------------------------------------------------------------------- /docs/src/@rocketseat/gatsby-theme-docs/src/templates/docs-query.js: -------------------------------------------------------------------------------- 1 | import { graphql } from "gatsby"; 2 | import DocsComponent from "../components/Docs-wrapper"; 3 | 4 | export default DocsComponent; 5 | 6 | export const query = graphql` 7 | query($slug: String!) { 8 | mdx(fields: { slug: { eq: $slug } }) { 9 | id 10 | excerpt(pruneLength: 160) 11 | fields { 12 | slug 13 | } 14 | frontmatter { 15 | title 16 | description 17 | image 18 | disableTableOfContents 19 | } 20 | body 21 | headings { 22 | depth 23 | value 24 | } 25 | } 26 | } 27 | `; 28 | -------------------------------------------------------------------------------- /internal/robustio/robustio_other.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build !windows && !darwin 6 | 7 | package robustio 8 | 9 | import ( 10 | "os" 11 | ) 12 | 13 | func rename(oldpath, newpath string) error { 14 | return os.Rename(oldpath, newpath) 15 | } 16 | 17 | func readFile(filename string) ([]byte, error) { 18 | return os.ReadFile(filename) 19 | } 20 | 21 | func removeAll(path string) error { 22 | return os.RemoveAll(path) 23 | } 24 | 25 | func isEphemeralError(err error) bool { 26 | return false 27 | } 28 | -------------------------------------------------------------------------------- /pkg/golinters/gosimple.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "honnef.co/go/tools/simple" 5 | 6 | "github.com/golangci/golangci-lint/pkg/config" 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewGosimple(settings *config.StaticCheckSettings) *goanalysis.Linter { 11 | cfg := staticCheckConfig(settings) 12 | 13 | analyzers := setupStaticCheckAnalyzers(simple.Analyzers, getGoVersion(settings), cfg.Checks) 14 | 15 | return goanalysis.NewLinter( 16 | "gosimple", 17 | "Linter for Go source code that specializes in simplifying code", 18 | analyzers, 19 | nil, 20 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 21 | } 22 | -------------------------------------------------------------------------------- /pkg/golinters/goanalysis/load/guard.go: -------------------------------------------------------------------------------- 1 | package load 2 | 3 | import ( 4 | "sync" 5 | 6 | "golang.org/x/tools/go/packages" 7 | ) 8 | 9 | type Guard struct { 10 | loadMutexes map[*packages.Package]*sync.Mutex 11 | mutex sync.Mutex 12 | } 13 | 14 | func NewGuard() *Guard { 15 | return &Guard{ 16 | loadMutexes: map[*packages.Package]*sync.Mutex{}, 17 | } 18 | } 19 | 20 | func (g *Guard) AddMutexForPkg(pkg *packages.Package) { 21 | g.loadMutexes[pkg] = &sync.Mutex{} 22 | } 23 | 24 | func (g *Guard) MutexForPkg(pkg *packages.Package) *sync.Mutex { 25 | return g.loadMutexes[pkg] 26 | } 27 | 28 | func (g *Guard) Mutex() *sync.Mutex { 29 | return &g.mutex 30 | } 31 | -------------------------------------------------------------------------------- /.github/contributors/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "contributors", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "gen": "tsc && node --trace-warnings ./generate.js", 9 | "rewrite_readme": "tsc && node --trace-warnings ./rewrite_readme.js", 10 | "all": "npm run gen && npm run rewrite_readme" 11 | }, 12 | "author": "", 13 | "license": "MIT", 14 | "type": "module", 15 | "dependencies": { 16 | "@octokit/graphql": "^4.4.0", 17 | "@types/node": "^14.0.1", 18 | "name-your-contributors": "^3.8.3", 19 | "typescript": "^3.9.2" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/testdata/errcheck_ignore.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrcheck 2 | //golangcitest:config_path testdata/configs/ignore_config.yml 3 | package testdata 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | ) 10 | 11 | func TestErrcheckIgnoreOs() { 12 | _, _ = os.Open("f.txt") 13 | } 14 | 15 | func TestErrcheckIgnoreFmt(s string) int { 16 | n, _ := fmt.Println(s) 17 | return n 18 | } 19 | 20 | func TestErrcheckIgnoreIoutil() []byte { 21 | ret, _ := ioutil.ReadFile("f.txt") 22 | return ret 23 | } 24 | 25 | func TestErrcheckNoIgnoreIoutil() []byte { 26 | ret, _ := ioutil.ReadAll(nil) // want "Error return value of `ioutil.ReadAll` is not checked" 27 | return ret 28 | } 29 | -------------------------------------------------------------------------------- /test/testdata/exhaustive_default.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexhaustive 2 | //golangcitest:config_path testdata/configs/exhaustive_default.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | type Direction int 7 | 8 | const ( 9 | North Direction = iota 10 | East 11 | South 12 | West 13 | ) 14 | 15 | // Should not report missing cases in the switch statement below even though 16 | // some enum members (East, West) are not listed, because the switch statement 17 | // has a 'default' case and the default-signifies-exhaustive setting is true. 18 | 19 | func processDirectionDefault(d Direction) { 20 | switch d { 21 | case North, South: 22 | default: 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/testdata/godox.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egodox 2 | //golangcitest:config_path testdata/configs/godox.yml 3 | package testdata 4 | 5 | func todoLeftInCode() { 6 | // TODO implement me // want `Line contains FIXME/TODO: "TODO implement me` 7 | //TODO no space // want `Line contains FIXME/TODO: "TODO no space` 8 | // TODO(author): 123 // want `Line contains FIXME/TODO: "TODO\(author\): 123` 9 | //TODO(author): 123 // want `Line contains FIXME/TODO: "TODO\(author\): 123` 10 | //TODO(author) 456 // want `Line contains FIXME/TODO: "TODO\(author\) 456` 11 | // TODO: qwerty // want `Line contains FIXME/TODO: "TODO: qwerty` 12 | // todo 789 // want `Line contains FIXME/TODO: "todo 789` 13 | } 14 | -------------------------------------------------------------------------------- /test/testdata/golint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egolint --internal-cmd-test 2 | package testdata 3 | 4 | var Go_lint string // want "don't use underscores in Go names; var `Go_lint` should be `GoLint`" 5 | 6 | func ExportedFuncWithNoComment() { 7 | } 8 | 9 | var ExportedVarWithNoComment string 10 | 11 | type ExportedStructWithNoComment struct{} 12 | 13 | type ExportedInterfaceWithNoComment interface{} 14 | 15 | // Bad comment 16 | func ExportedFuncWithBadComment() {} 17 | 18 | type GolintTest struct{} 19 | 20 | func (receiver1 GolintTest) A() {} 21 | 22 | func (receiver2 GolintTest) B() {} // want "receiver name receiver2 should be consistent with previous receiver name receiver1 for GolintTest" 23 | -------------------------------------------------------------------------------- /test/testdata/asasalint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Easasalint 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func getArgsLength(args ...interface{}) int { 7 | // this line will not report as error 8 | fmt.Println(args) 9 | return len(args) 10 | } 11 | 12 | func checkArgsLength(args ...interface{}) int { 13 | return getArgsLength(args) // want `pass \[\]any as any to func getArgsLength func\(args \.\.\.interface\{\}\)` 14 | } 15 | 16 | func someCall() { 17 | var a = []interface{}{1, 2, 3} 18 | fmt.Println(checkArgsLength(a...) == getArgsLength(a)) // want `pass \[\]any as any to func getArgsLength func\(args \.\.\.interface\{\}\)` 19 | fmt.Println(checkArgsLength(a...) == getArgsLength(a...)) 20 | } 21 | -------------------------------------------------------------------------------- /test/testdata/goerr113.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoerr113 2 | package testdata 3 | 4 | import "os" 5 | 6 | func SimpleEqual(e1, e2 error) bool { 7 | return e1 == e2 // want `err113: do not compare errors directly "e1 == e2", use "errors.Is\(e1, e2\)" instead` 8 | } 9 | 10 | func SimpleNotEqual(e1, e2 error) bool { 11 | return e1 != e2 // want `err113: do not compare errors directly "e1 != e2", use "!errors.Is\(e1, e2\)" instead` 12 | } 13 | 14 | func CheckGoerr13Import(e error) bool { 15 | f, err := os.Create("f.txt") 16 | if err != nil { 17 | return err == e // want `err113: do not compare errors directly "err == e", use "errors.Is\(err, e\)" instead` 18 | } 19 | f.Close() 20 | return false 21 | } 22 | -------------------------------------------------------------------------------- /test/testdata/thelper_go118.go: -------------------------------------------------------------------------------- 1 | //go:build go1.18 2 | 3 | //golangcitest:args -Ethelper 4 | package testdata 5 | 6 | import "testing" 7 | 8 | func fhelperWithHelperAfterAssignment(f *testing.F) { // want "test helper function should start from f.Helper()" 9 | _ = 0 10 | f.Helper() 11 | } 12 | 13 | func fhelperWithNotFirst(s string, f *testing.F, i int) { // want `parameter \*testing.F should be the first` 14 | f.Helper() 15 | } 16 | 17 | func fhelperWithIncorrectName(o *testing.F) { // want `parameter \*testing.F should have name f` 18 | o.Helper() 19 | } 20 | 21 | func FuzzSubtestShouldNotBeChecked(f *testing.F) { 22 | f.Add(5, "hello") 23 | f.Fuzz(func(t *testing.T, a int, b string) {}) 24 | } 25 | -------------------------------------------------------------------------------- /pkg/golinters/contextcheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/kkHAIKE/contextcheck" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | "github.com/golangci/golangci-lint/pkg/lint/linter" 9 | ) 10 | 11 | func NewContextCheck() *goanalysis.Linter { 12 | analyzer := contextcheck.NewAnalyzer(contextcheck.Configuration{}) 13 | 14 | return goanalysis.NewLinter( 15 | analyzer.Name, 16 | analyzer.Doc, 17 | []*analysis.Analyzer{analyzer}, 18 | nil, 19 | ).WithContextSetter(func(lintCtx *linter.Context) { 20 | analyzer.Run = contextcheck.NewRun(lintCtx.Packages, false) 21 | }).WithLoadMode(goanalysis.LoadModeTypesInfo) 22 | } 23 | -------------------------------------------------------------------------------- /.github/workflows/pr-extra.yml: -------------------------------------------------------------------------------- 1 | name: Extra 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | 8 | jobs: 9 | vulns: 10 | name: Vulnerability scanner 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-go@v3 15 | with: 16 | # https://github.com/actions/setup-go#supported-version-syntax 17 | # ex: 18 | # - 1.18beta1 -> 1.18.0-beta.1 19 | # - 1.18rc1 -> 1.18.0-rc.1 20 | go-version: '1.20' 21 | - name: Run go list 22 | run: go list -json -m all > go.list 23 | - name: Nancy 24 | uses: sonatype-nexus-community/nancy-github-action@v1.0.2 25 | -------------------------------------------------------------------------------- /.nancy-ignore: -------------------------------------------------------------------------------- 1 | # Skip for indirect dependency github.com/coreos/etcd@3.3.13 2 | CVE-2020-15114 3 | CVE-2020-15115 4 | CVE-2020-15136 5 | 6 | # Skip for indirect dependency github.com/gogo/protobuf@1.3.1 7 | CVE-2021-3121 8 | 9 | # Skip for indirect dependency github.com/dgrijalva/jwt-go@3.2.0 10 | CVE-2020-26160 11 | 12 | # Skip for indirect dependencies: 13 | # golang/github.com/hashicorp/consul/api@v1.12.0 14 | # golang/github.com/hashicorp/consul/sdk@v0.8.0 15 | CVE-2022-29153 16 | CVE-2022-24687 17 | CVE-2021-41803 18 | 19 | # Skip for indirect dependencies golang/github.com/valyala/fasthttp@v1.30.0 20 | CVE-2022-21221 21 | 22 | # Skip for indirect dependencies golang/golang.org/x/net@v0.6.0 23 | CVE-2022-41723 24 | -------------------------------------------------------------------------------- /pkg/golinters/goanalysis/issue.go: -------------------------------------------------------------------------------- 1 | package goanalysis 2 | 3 | import ( 4 | "go/token" 5 | 6 | "golang.org/x/tools/go/analysis" 7 | 8 | "github.com/golangci/golangci-lint/pkg/result" 9 | ) 10 | 11 | type Issue struct { 12 | result.Issue 13 | Pass *analysis.Pass 14 | } 15 | 16 | func NewIssue(i *result.Issue, pass *analysis.Pass) Issue { 17 | return Issue{ 18 | Issue: *i, 19 | Pass: pass, 20 | } 21 | } 22 | 23 | type EncodingIssue struct { 24 | FromLinter string 25 | Text string 26 | Pos token.Position 27 | LineRange *result.Range 28 | Replacement *result.Replacement 29 | ExpectNoLint bool 30 | ExpectedNoLintLinter string 31 | } 32 | -------------------------------------------------------------------------------- /pkg/report/data.go: -------------------------------------------------------------------------------- 1 | package report 2 | 3 | type Warning struct { 4 | Tag string `json:",omitempty"` 5 | Text string 6 | } 7 | 8 | type LinterData struct { 9 | Name string 10 | Enabled bool `json:",omitempty"` 11 | EnabledByDefault bool `json:",omitempty"` 12 | } 13 | 14 | type Data struct { 15 | Warnings []Warning `json:",omitempty"` 16 | Linters []LinterData `json:",omitempty"` 17 | Error string `json:",omitempty"` 18 | } 19 | 20 | func (d *Data) AddLinter(name string, enabled, enabledByDefault bool) { 21 | d.Linters = append(d.Linters, LinterData{ 22 | Name: name, 23 | Enabled: enabled, 24 | EnabledByDefault: enabledByDefault, 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/golinters/tenv.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/sivchari/tenv" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewTenv(settings *config.TenvSettings) *goanalysis.Linter { 12 | a := tenv.Analyzer 13 | 14 | var cfg map[string]map[string]interface{} 15 | if settings != nil { 16 | cfg = map[string]map[string]interface{}{ 17 | a.Name: { 18 | tenv.A: settings.All, 19 | }, 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | a.Doc, 26 | []*analysis.Analyzer{a}, 27 | cfg, 28 | ).WithLoadMode(goanalysis.LoadModeSyntax) 29 | } 30 | -------------------------------------------------------------------------------- /test/ruleguard/strings_simplify.go: -------------------------------------------------------------------------------- 1 | // go:build ruleguard 2 | package ruleguard 3 | 4 | import "github.com/quasilyte/go-ruleguard/dsl" 5 | 6 | func StringsSimplify(m dsl.Matcher) { 7 | // Some issues have simple fixes that can be expressed as 8 | // a replacement pattern. Rules can use Suggest() function 9 | // to add a quickfix action for such issues. 10 | m.Match(`strings.Replace($s, $old, $new, -1)`). 11 | Report(`this Replace call can be simplified`). 12 | Suggest(`strings.ReplaceAll($s, $old, $new)`) 13 | 14 | // Suggest() can be used without Report(). 15 | // It'll print the suggested template to the user. 16 | m.Match(`strings.Count($s1, $s2) == 0`). 17 | Suggest(`!strings.Contains($s1, $s2)`) 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/makezero.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emakezero 2 | package testdata 3 | 4 | import "math" 5 | 6 | func Makezero() []int { 7 | x := make([]int, math.MaxInt8) 8 | return append(x, 1) // want "append to slice `x` with non-zero initialized length" 9 | } 10 | 11 | func MakezeroMultiple() []int { 12 | x, y := make([]int, math.MaxInt8), make([]int, math.MaxInt8) 13 | return append(x, // want "append to slice `x` with non-zero initialized length" 14 | append(y, 1)...) // want "append to slice `y` with non-zero initialized length" 15 | } 16 | 17 | func MakezeroNolint() []int { 18 | x := make([]int, math.MaxInt8) 19 | return append(x, 1) //nolint:makezero // ok that we're appending to an uninitialized slice 20 | } 21 | -------------------------------------------------------------------------------- /test/testdata/nilerr.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Enilerr 2 | package testdata 3 | 4 | import "os" 5 | 6 | func nilErr1() error { 7 | err := nilErrDo() 8 | if err == nil { 9 | return err // want `error is nil \(line 7\) but it returns error` 10 | } 11 | 12 | return nil 13 | } 14 | 15 | func nilErr2() error { 16 | err := nilErrDo() 17 | if err == nil { 18 | return err // want `error is nil \(line 16\) but it returns error` 19 | } 20 | 21 | return nil 22 | } 23 | 24 | func nilErr3() error { 25 | err := nilErrDo() 26 | if err != nil { 27 | return nil // want `error is not nil \(line 25\) but it returns nil` 28 | } 29 | 30 | return nil 31 | } 32 | 33 | func nilErrDo() error { 34 | return os.ErrNotExist 35 | } 36 | -------------------------------------------------------------------------------- /test/testdata/asciicheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Easciicheck 2 | package testdata 3 | 4 | import ( 5 | "fmt" 6 | "time" 7 | ) 8 | 9 | type AsciicheckTеstStruct struct { // want `identifier "AsciicheckTеstStruct" contain non-ASCII character: U\+0435 'е'` 10 | Date time.Time 11 | } 12 | 13 | type AsciicheckField struct{} 14 | 15 | type AsciicheckJustStruct struct { 16 | Tеst AsciicheckField // want `identifier "Tеst" contain non-ASCII character: U\+0435 'е'` 17 | } 18 | 19 | func AsciicheckTеstFunc() { // want `identifier "AsciicheckTеstFunc" contain non-ASCII character: U\+0435 'е'` 20 | var tеstVar int // want `identifier "tеstVar" contain non-ASCII character: U\+0435 'е'` 21 | tеstVar = 0 22 | fmt.Println(tеstVar) 23 | } 24 | -------------------------------------------------------------------------------- /test/testdata/importas.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eimportas 2 | //golangcitest:config_path testdata/configs/importas.yml 3 | package testdata 4 | 5 | import ( 6 | wrong_alias "fmt" // want `import "fmt" imported as "wrong_alias" but must be "fff" according to config` 7 | "os" 8 | wrong_alias_again "os" // want `import "os" imported as "wrong_alias_again" but must be "std_os" according to config` 9 | 10 | wrong "github.com/pkg/errors" // want `import "github.com/pkg/errors" imported as "wrong" but must be "pkgerr" according to config` 11 | ) 12 | 13 | func ImportAsWrongAlias() { 14 | wrong_alias.Println("foo") 15 | wrong_alias_again.Stdout.WriteString("bar") 16 | os.Stdout.WriteString("test") 17 | _ = wrong.New("baz") 18 | } 19 | -------------------------------------------------------------------------------- /test/testdata/stylecheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Estylecheck 2 | package testdata 3 | 4 | func Stylecheck(x int) { 5 | switch x { 6 | case 1: 7 | return 8 | default: // want "ST1015: default case should be first or last in switch statement" 9 | return 10 | case 2: 11 | return 12 | } 13 | } 14 | 15 | func StylecheckNolintStylecheck(x int) { 16 | switch x { 17 | case 1: 18 | return 19 | default: //nolint:stylecheck 20 | return 21 | case 2: 22 | return 23 | } 24 | } 25 | 26 | func StylecheckNolintMegacheck(x int) { 27 | switch x { 28 | case 1: 29 | return 30 | default: //nolint:megacheck // want "ST1015: default case should be first or last in switch statement" 31 | return 32 | case 2: 33 | return 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /pkg/golinters/rowserrcheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/jingyugao/rowserrcheck/passes/rowserr" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewRowsErrCheck(settings *config.RowsErrCheckSettings) *goanalysis.Linter { 12 | var pkgs []string 13 | if settings != nil { 14 | pkgs = settings.Packages 15 | } 16 | 17 | analyzer := rowserr.NewAnalyzer(pkgs...) 18 | 19 | return goanalysis.NewLinter( 20 | "rowserrcheck", 21 | "checks whether Err of rows is checked successfully", 22 | []*analysis.Analyzer{analyzer}, 23 | nil, 24 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 25 | } 26 | -------------------------------------------------------------------------------- /test/testdata/configs/gomodguard.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gomodguard: 3 | allowed: 4 | modules: # List of allowed modules 5 | - golang.org/x/mod/modfile 6 | blocked: 7 | modules: # List of blocked modules 8 | - gopkg.in/yaml.v3: # Blocked module 9 | recommendations: # Recommended modules that should be used instead (Optional) 10 | - github.com/kylelemons/go-gypsy 11 | reason: "This is an example of recommendations." # Reason why the recommended module should be used (Optional) 12 | -------------------------------------------------------------------------------- /test/testdata/revive_default.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Erevive 2 | package testdata 3 | 4 | import ( 5 | "net/http" 6 | "time" 7 | ) 8 | 9 | func testReviveDefault(t *time.Duration) error { 10 | if t == nil { 11 | return nil 12 | } else { // want "indent-error-flow: if block ends with a return statement, .*" 13 | return nil 14 | } 15 | } 16 | 17 | func testReviveComplexityDefault(s string) { 18 | if s == http.MethodGet || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 19 | return 20 | } 21 | 22 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 23 | return 24 | } 25 | 26 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 27 | return 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/testdata/rowserrcheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Erowserrcheck 2 | package testdata 3 | 4 | import ( 5 | "database/sql" 6 | "fmt" 7 | "math/rand" 8 | ) 9 | 10 | func RowsErrNotChecked(db *sql.DB) { 11 | rows, _ := db.Query("select id from tb") // want "rows.Err must be checked" 12 | for rows.Next() { 13 | 14 | } 15 | } 16 | 17 | func issue943(db *sql.DB) { 18 | var rows *sql.Rows 19 | var err error 20 | 21 | if rand.Float64() < 0.5 { 22 | rows, err = db.Query("select 1") 23 | } else { 24 | rows, err = db.Query("select 2") 25 | } 26 | if err != nil { 27 | panic(err) 28 | } 29 | 30 | defer rows.Close() 31 | 32 | for rows.Next() { 33 | fmt.Println("new rows") 34 | } 35 | 36 | if err := rows.Err(); err != nil { 37 | panic(err) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/testdata/funlen.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Efunlen 2 | //golangcitest:config_path testdata/configs/funlen.yml 3 | package testdata 4 | 5 | func TooManyLines() { // want `Function 'TooManyLines' is too long \(22 > 20\)` 6 | t := struct { 7 | A string 8 | B string 9 | C string 10 | D string 11 | E string 12 | F string 13 | G string 14 | H string 15 | I string 16 | }{ 17 | `a`, 18 | `b`, 19 | `c`, 20 | `d`, 21 | `e`, 22 | `f`, 23 | `g`, 24 | `h`, 25 | `i`, 26 | } 27 | _ = t 28 | } 29 | 30 | func TooManyStatements() { // want `Function 'TooManyStatements' has too many statements \(11 > 10\)` 31 | a := 1 32 | b := a 33 | c := b 34 | d := c 35 | e := d 36 | f := e 37 | g := f 38 | h := g 39 | i := h 40 | j := i 41 | _ = j 42 | } 43 | -------------------------------------------------------------------------------- /pkg/golinters/musttag.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/junk1tm/musttag" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewMustTag(setting *config.MustTagSettings) *goanalysis.Linter { 12 | var funcs []musttag.Func 13 | 14 | if setting != nil { 15 | for _, fn := range setting.Functions { 16 | funcs = append(funcs, musttag.Func{ 17 | Name: fn.Name, 18 | Tag: fn.Tag, 19 | ArgPos: fn.ArgPos, 20 | }) 21 | } 22 | } 23 | 24 | a := musttag.New(funcs...) 25 | 26 | return goanalysis. 27 | NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, nil). 28 | WithLoadMode(goanalysis.LoadModeTypesInfo) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/golinters/maintidx.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/yagipy/maintidx" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewMaintIdx(cfg *config.MaintIdxSettings) *goanalysis.Linter { 12 | analyzer := maintidx.Analyzer 13 | 14 | cfgMap := map[string]map[string]interface{}{ 15 | analyzer.Name: {"under": 20}, 16 | } 17 | 18 | if cfg != nil { 19 | cfgMap[analyzer.Name] = map[string]interface{}{ 20 | "under": cfg.Under, 21 | } 22 | } 23 | 24 | return goanalysis.NewLinter( 25 | analyzer.Name, 26 | analyzer.Doc, 27 | []*analysis.Analyzer{analyzer}, 28 | cfgMap, 29 | ).WithLoadMode(goanalysis.LoadModeSyntax) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/printers/json.go: -------------------------------------------------------------------------------- 1 | package printers 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "io" 7 | 8 | "github.com/golangci/golangci-lint/pkg/report" 9 | "github.com/golangci/golangci-lint/pkg/result" 10 | ) 11 | 12 | type JSON struct { 13 | rd *report.Data 14 | w io.Writer 15 | } 16 | 17 | func NewJSON(rd *report.Data, w io.Writer) *JSON { 18 | return &JSON{ 19 | rd: rd, 20 | w: w, 21 | } 22 | } 23 | 24 | type JSONResult struct { 25 | Issues []result.Issue 26 | Report *report.Data 27 | } 28 | 29 | func (p JSON) Print(ctx context.Context, issues []result.Issue) error { 30 | res := JSONResult{ 31 | Issues: issues, 32 | Report: p.rd, 33 | } 34 | if res.Issues == nil { 35 | res.Issues = []result.Issue{} 36 | } 37 | 38 | return json.NewEncoder(p.w).Encode(res) 39 | } 40 | -------------------------------------------------------------------------------- /test/testdata/goconst.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoconst 2 | package testdata 3 | 4 | import "fmt" 5 | 6 | func GoconstA() { 7 | a := "needconst" // want "string `needconst` has 5 occurrences, make it a constant" 8 | fmt.Print(a) 9 | b := "needconst" 10 | fmt.Print(b) 11 | c := "needconst" 12 | fmt.Print(c) 13 | } 14 | 15 | func GoconstB() { 16 | a := "needconst" 17 | fmt.Print(a) 18 | b := "needconst" 19 | fmt.Print(b) 20 | } 21 | 22 | const AlreadyHasConst = "alreadyhasconst" 23 | 24 | func GoconstC() { 25 | a := "alreadyhasconst" // want "string `alreadyhasconst` has 3 occurrences, but such constant `AlreadyHasConst` already exists" 26 | fmt.Print(a) 27 | b := "alreadyhasconst" 28 | fmt.Print(b) 29 | c := "alreadyhasconst" 30 | fmt.Print(c) 31 | fmt.Print("alreadyhasconst") 32 | } 33 | -------------------------------------------------------------------------------- /pkg/golinters/dupword.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/Abirdcfly/dupword" 7 | "golang.org/x/tools/go/analysis" 8 | 9 | "github.com/golangci/golangci-lint/pkg/config" 10 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 11 | ) 12 | 13 | func NewDupWord(setting *config.DupWordSettings) *goanalysis.Linter { 14 | a := dupword.NewAnalyzer() 15 | 16 | cfgMap := map[string]map[string]interface{}{} 17 | if setting != nil { 18 | cfgMap[a.Name] = map[string]interface{}{ 19 | "keyword": strings.Join(setting.Keywords, ","), 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | "checks for duplicate words in the source code", 26 | []*analysis.Analyzer{a}, 27 | cfgMap, 28 | ).WithLoadMode(goanalysis.LoadModeSyntax) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/golinters/interfacebloat.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/sashamelentyev/interfacebloat/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewInterfaceBloat(settings *config.InterfaceBloatSettings) *goanalysis.Linter { 12 | a := analyzer.New() 13 | 14 | var cfg map[string]map[string]interface{} 15 | if settings != nil { 16 | cfg = map[string]map[string]interface{}{ 17 | a.Name: { 18 | analyzer.InterfaceMaxMethodsFlag: settings.Max, 19 | }, 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | a.Doc, 26 | []*analysis.Analyzer{a}, 27 | cfg, 28 | ).WithLoadMode(goanalysis.LoadModeSyntax) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/golinters/nilnil.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/Antonboom/nilnil/pkg/analyzer" 7 | "golang.org/x/tools/go/analysis" 8 | 9 | "github.com/golangci/golangci-lint/pkg/config" 10 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 11 | ) 12 | 13 | func NewNilNil(cfg *config.NilNilSettings) *goanalysis.Linter { 14 | a := analyzer.New() 15 | 16 | cfgMap := make(map[string]map[string]interface{}) 17 | if cfg != nil && len(cfg.CheckedTypes) != 0 { 18 | cfgMap[a.Name] = map[string]interface{}{ 19 | "checked-types": strings.Join(cfg.CheckedTypes, ","), 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | a.Doc, 26 | []*analysis.Analyzer{a}, 27 | cfgMap, 28 | ). 29 | WithLoadMode(goanalysis.LoadModeTypesInfo) 30 | } 31 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/loggercheck_logronly.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eloggercheck 2 | //golangcitest:config_path configs/loggercheck_logronly.yml 3 | package loggercheck 4 | 5 | import ( 6 | "fmt" 7 | 8 | "github.com/go-logr/logr" 9 | "go.uber.org/zap" 10 | "k8s.io/klog/v2" 11 | ) 12 | 13 | func ExampleLogrOnly() { 14 | log := logr.Discard() 15 | log.Info("message", "key1", "value1", "key2", "value2", "key3") // want `odd number of arguments passed as key-value pairs for logging` 16 | 17 | klog.InfoS("message", "key1") 18 | 19 | sugar := zap.NewExample().Sugar() 20 | sugar.Infow("message", "key1", "value1", "key2") 21 | sugar.Errorw("error message", "key1") 22 | 23 | // Will not check by default (-requirestringkey) 24 | log.Error(fmt.Errorf("error"), "message", []byte("key1"), "value1") 25 | } 26 | -------------------------------------------------------------------------------- /test/testdata/nolintlint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Enolintlint -Emisspell 2 | //golangcitest:expected_linter nolintlint 3 | //golangcitest:config_path testdata/configs/nolintlint.yml 4 | package testdata 5 | 6 | import "fmt" 7 | 8 | func Foo() { 9 | fmt.Println("not specific") //nolint // want "directive `.*` should mention specific linter such as `//nolint:my-linter`" 10 | fmt.Println("not machine readable") // nolint // want "directive `.*` should be written as `//nolint`" 11 | fmt.Println("extra spaces") // nolint:unused // because // want "directive `.*` should not have more than one leading space" 12 | 13 | // test expanded range 14 | //nolint:misspell // deliberate misspelling to trigger nolintlint 15 | func() { 16 | mispell := true 17 | fmt.Println(mispell) 18 | }() 19 | } 20 | -------------------------------------------------------------------------------- /test/testshared/runner_unix.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | package testshared 4 | 5 | import ( 6 | "path/filepath" 7 | "testing" 8 | ) 9 | 10 | // SkipOnWindows it's a noop function on Unix. 11 | func SkipOnWindows(_ testing.TB) {} 12 | 13 | // NormalizeFilePathInJSON it's a noop function on Unix. 14 | func NormalizeFilePathInJSON(in string) string { 15 | return in 16 | } 17 | 18 | // NormalizeFileInString it's a noop function on Unix. 19 | func NormalizeFileInString(in string) string { 20 | return in 21 | } 22 | 23 | // defaultBinaryName returns the path to the default binary. 24 | func defaultBinaryName() string { 25 | return filepath.Join("..", "golangci-lint") 26 | } 27 | 28 | // normalizeFilePath it's a noop function on Unix. 29 | func normalizeFilePath(in string) string { 30 | return in 31 | } 32 | -------------------------------------------------------------------------------- /pkg/golinters/nonamedreturns.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/firefart/nonamedreturns/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewNoNamedReturns(settings *config.NoNamedReturnsSettings) *goanalysis.Linter { 12 | a := analyzer.Analyzer 13 | 14 | var cfg map[string]map[string]interface{} 15 | if settings != nil { 16 | cfg = map[string]map[string]interface{}{ 17 | a.Name: { 18 | analyzer.FlagReportErrorInDefer: settings.ReportErrorInDefer, 19 | }, 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | a.Doc, 26 | []*analysis.Analyzer{a}, 27 | cfg, 28 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 29 | } 30 | -------------------------------------------------------------------------------- /test/testdata/lll.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Elll 2 | //golangcitest:config_path testdata/configs/lll.yml 3 | package testdata 4 | 5 | import ( 6 | _ "unsafe" 7 | ) 8 | 9 | func Lll() { 10 | // In my experience, long lines are the lines with comments, not the code. So this is a long comment // want "line is 137 characters" 11 | } 12 | 13 | //go:generate mockgen -source lll.go -destination a_verylong_generate_mock_my_lll_interface.go --package testdata -self_package github.com/golangci/golangci-lint/test/testdata 14 | type MyLllInterface interface { 15 | } 16 | 17 | //go:linkname VeryLongNameForTestAndLinkNameFunction github.com/golangci/golangci-lint/test/testdata.VeryLongNameForTestAndLinkedNameFunction 18 | func VeryLongNameForTestAndLinkNameFunction() 19 | 20 | func VeryLongNameForTestAndLinkedNameFunction() {} 21 | -------------------------------------------------------------------------------- /test/testdata/revive.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Erevive 2 | //golangcitest:config_path testdata/configs/revive.yml 3 | package testdata 4 | 5 | import ( 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | func SampleRevive(t *time.Duration) error { 11 | if t == nil { 12 | return nil 13 | } else { 14 | return nil 15 | } 16 | } 17 | 18 | func testReviveComplexity(s string) { // want "cyclomatic: function testReviveComplexity has cyclomatic complexity 22" 19 | if s == http.MethodGet || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 20 | return 21 | } 22 | 23 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 24 | return 25 | } 26 | 27 | if s == "1" || s == "2" || s == "3" || s == "4" || s == "5" || s == "6" || s == "7" { 28 | return 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gomod 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | day: "sunday" 8 | time: "11:00" # 11am UTC 9 | ignore: 10 | # ignore forked linters because of their versioning issues. TODO: fix it. 11 | - dependency-name: "github.com/golangci/*" 12 | - package-ecosystem: github-actions 13 | directory: "/" 14 | schedule: 15 | interval: weekly 16 | - package-ecosystem: docker 17 | directory: "/build" 18 | schedule: 19 | interval: weekly 20 | - package-ecosystem: gomod 21 | directory: "/scripts/gen_github_action_config" 22 | schedule: 23 | interval: weekly 24 | - package-ecosystem: npm 25 | directory: "/docs" 26 | schedule: 27 | interval: monthly 28 | -------------------------------------------------------------------------------- /pkg/golinters/ireturn.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/butuzov/ireturn/analyzer" 7 | "golang.org/x/tools/go/analysis" 8 | 9 | "github.com/golangci/golangci-lint/pkg/config" 10 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 11 | ) 12 | 13 | func NewIreturn(settings *config.IreturnSettings) *goanalysis.Linter { 14 | a := analyzer.NewAnalyzer() 15 | 16 | cfg := map[string]map[string]interface{}{} 17 | if settings != nil { 18 | cfg[a.Name] = map[string]interface{}{ 19 | "allow": strings.Join(settings.Allow, ","), 20 | "reject": strings.Join(settings.Reject, ","), 21 | } 22 | } 23 | 24 | return goanalysis.NewLinter( 25 | a.Name, 26 | a.Doc, 27 | []*analysis.Analyzer{a}, 28 | cfg, 29 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/golinters/nlreturn.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/ssgreg/nlreturn/v2/pkg/nlreturn" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewNLReturn(settings *config.NlreturnSettings) *goanalysis.Linter { 12 | a := nlreturn.NewAnalyzer() 13 | 14 | cfg := map[string]map[string]interface{}{} 15 | if settings != nil { 16 | cfg[a.Name] = map[string]interface{}{ 17 | "block-size": settings.BlockSize, 18 | } 19 | } 20 | 21 | return goanalysis.NewLinter( 22 | a.Name, 23 | "nlreturn checks for a new line before return and branch statements to increase code clarity", 24 | []*analysis.Analyzer{a}, 25 | cfg, 26 | ).WithLoadMode(goanalysis.LoadModeSyntax) 27 | } 28 | -------------------------------------------------------------------------------- /pkg/golinters/predeclared.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/nishanths/predeclared/passes/predeclared" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewPredeclared(settings *config.PredeclaredSettings) *goanalysis.Linter { 12 | a := predeclared.Analyzer 13 | 14 | var cfg map[string]map[string]interface{} 15 | if settings != nil { 16 | cfg = map[string]map[string]interface{}{ 17 | a.Name: { 18 | predeclared.IgnoreFlag: settings.Ignore, 19 | predeclared.QualifiedFlag: settings.Qualified, 20 | }, 21 | } 22 | } 23 | 24 | return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, cfg). 25 | WithLoadMode(goanalysis.LoadModeSyntax) 26 | } 27 | -------------------------------------------------------------------------------- /pkg/golinters/staticcheck.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "honnef.co/go/tools/staticcheck" 5 | 6 | "github.com/golangci/golangci-lint/pkg/config" 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewStaticcheck(settings *config.StaticCheckSettings) *goanalysis.Linter { 11 | cfg := staticCheckConfig(settings) 12 | analyzers := setupStaticCheckAnalyzers(staticcheck.Analyzers, getGoVersion(settings), cfg.Checks) 13 | 14 | return goanalysis.NewLinter( 15 | "staticcheck", 16 | "It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary."+ 17 | " The author of staticcheck doesn't support or approve the use of staticcheck as a library inside golangci-lint.", 18 | analyzers, 19 | nil, 20 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 21 | } 22 | -------------------------------------------------------------------------------- /test/testdata/goconst_ignore_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoconst 2 | //golangcitest:config_path testdata/configs/goconst_ignore.yml 3 | //golangcitest:expected_exitcode 0 4 | package testdata 5 | 6 | import ( 7 | "fmt" 8 | "testing" 9 | ) 10 | 11 | func TestGoConstA(t *testing.T) { 12 | a := "needconst" 13 | fmt.Print(a) 14 | b := "needconst" 15 | fmt.Print(b) 16 | c := "needconst" 17 | fmt.Print(c) 18 | } 19 | 20 | func TestGoConstB(t *testing.T) { 21 | a := "needconst" 22 | fmt.Print(a) 23 | b := "needconst" 24 | fmt.Print(b) 25 | } 26 | 27 | const AlreadyHasConst = "alreadyhasconst" 28 | 29 | func TestGoConstC(t *testing.T) { 30 | a := "alreadyhasconst" 31 | fmt.Print(a) 32 | b := "alreadyhasconst" 33 | fmt.Print(b) 34 | c := "alreadyhasconst" 35 | fmt.Print(c) 36 | fmt.Print("alreadyhasconst") 37 | } 38 | -------------------------------------------------------------------------------- /test/testdata/gomnd.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egomnd 2 | package testdata 3 | 4 | import ( 5 | "log" 6 | "net/http" 7 | "time" 8 | ) 9 | 10 | func UseMagicNumber() { 11 | c := &http.Client{ 12 | Timeout: 2 * time.Second, // want "Magic number: 2, in detected" 13 | } 14 | 15 | res, err := c.Get("http://www.google.com") 16 | if err != nil { 17 | log.Fatal(err) 18 | } 19 | if res.StatusCode != 200 { // want "Magic number: 200, in detected" 20 | log.Println("Something went wrong") 21 | } 22 | } 23 | 24 | func UseNoMagicNumber() { 25 | c := &http.Client{ 26 | Timeout: time.Second, 27 | } 28 | 29 | res, err := c.Get("http://www.google.com") 30 | if err != nil { 31 | log.Fatal(err) 32 | } 33 | if res.StatusCode != http.StatusOK { 34 | log.Println("Something went wrong") 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/ruleguard/dup.go: -------------------------------------------------------------------------------- 1 | // go:build ruleguard 2 | package ruleguard 3 | 4 | import "github.com/quasilyte/go-ruleguard/dsl" 5 | 6 | // Suppose that we want to report the duplicated left and right operands of binary operations. 7 | // 8 | // But if the operand has some side effects, this rule can cause false positives: 9 | // `f() && f()` can make sense (although it's not the best piece of code). 10 | // 11 | // This is where *filters* come to the rescue. 12 | func DupSubExpr(m dsl.Matcher) { 13 | // All filters are written as a Where() argument. 14 | // In our case, we need to assert that $x is "pure". 15 | // It can be achieved by checking the m["x"] member Pure field. 16 | m.Match(`$x || $x`, 17 | `$x && $x`, 18 | `$x | $x`, 19 | `$x & $x`). 20 | Where(m["x"].Pure). 21 | Report(`suspicious identical LHS and RHS`) 22 | } 23 | -------------------------------------------------------------------------------- /test/testdata/gomodguard.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egomodguard 2 | //golangcitest:config_path testdata/configs/gomodguard.yml 3 | package testdata 4 | 5 | import ( 6 | "log" 7 | 8 | "golang.org/x/mod/modfile" 9 | "gopkg.in/yaml.v3" // want "import of package `gopkg.in/yaml.v3` is blocked because the module is in the blocked modules list. `github.com/kylelemons/go-gypsy` is a recommended module. This is an example of recommendations." 10 | ) 11 | 12 | // Something just some struct 13 | type Something struct{} 14 | 15 | func aAllowedImport() { //nolint:unused 16 | mfile, _ := modfile.Parse("go.mod", []byte{}, nil) 17 | 18 | log.Println(mfile) 19 | } 20 | 21 | func aBlockedImport() { //nolint:unused 22 | data := []byte{} 23 | something := Something{} 24 | _ = yaml.Unmarshal(data, &something) 25 | 26 | log.Println(data) 27 | } 28 | -------------------------------------------------------------------------------- /test/testdata/gosec_severity_confidence.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egosec 2 | //golangcitest:config_path testdata/configs/gosec_severity_confidence.yml 3 | package testdata 4 | 5 | import ( 6 | "fmt" 7 | "io/ioutil" 8 | "net/http" 9 | ) 10 | 11 | var url string = "https://www.abcdefghijk.com" 12 | 13 | func gosecVariableURL() { 14 | resp, err := http.Get(url) // want "G107: Potential HTTP request made with variable url" 15 | if err != nil { 16 | panic(err) 17 | } 18 | defer resp.Body.Close() 19 | body, err := ioutil.ReadAll(resp.Body) 20 | if err != nil { 21 | panic(err) 22 | } 23 | fmt.Printf("%s", body) 24 | } 25 | 26 | func gosecHardcodedCredentials() { 27 | username := "admin" 28 | var password = "f62e5bcda4fae4f82370da0c6f20697b8f8447ef" 29 | 30 | fmt.Println("Doing something with: ", username, password) 31 | } 32 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 366 3 | 4 | # Number of days of inactivity before a stale issue is closed 5 | daysUntilClose: 30 6 | 7 | # Issues with these labels will never be considered stale 8 | exemptLabels: 9 | - pinned 10 | - security 11 | - blocked 12 | - protected 13 | - triaged 14 | 15 | # Label to use when marking an issue as stale 16 | staleLabel: stale 17 | 18 | # Comment to post when marking an issue as stale. Set to `false` to disable 19 | markComment: > 20 | This issue has been automatically marked as stale because it has not had 21 | recent activity. It will be closed if no further activity occurs. Thank you 22 | for your contributions. 23 | 24 | # Comment to post when closing a stale issue. Set to `false` to disable 25 | closeComment: false 26 | -------------------------------------------------------------------------------- /pkg/golinters/exhaustruct.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewExhaustruct(settings *config.ExhaustructSettings) *goanalysis.Linter { 12 | var include, exclude []string 13 | if settings != nil { 14 | include = settings.Include 15 | exclude = settings.Exclude 16 | } 17 | 18 | a, err := analyzer.NewAnalyzer(include, exclude) 19 | if err != nil { 20 | linterLogger.Fatalf("exhaustruct configuration: %v", err) 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | a.Doc, 26 | []*analysis.Analyzer{a}, 27 | nil, 28 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/golinters/exhaustivestruct.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/mbilski/exhaustivestruct/pkg/analyzer" 7 | "golang.org/x/tools/go/analysis" 8 | 9 | "github.com/golangci/golangci-lint/pkg/config" 10 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 11 | ) 12 | 13 | func NewExhaustiveStruct(settings *config.ExhaustiveStructSettings) *goanalysis.Linter { 14 | a := analyzer.Analyzer 15 | 16 | var cfg map[string]map[string]interface{} 17 | if settings != nil { 18 | cfg = map[string]map[string]interface{}{ 19 | a.Name: { 20 | "struct_patterns": strings.Join(settings.StructPatterns, ","), 21 | }, 22 | } 23 | } 24 | 25 | return goanalysis.NewLinter( 26 | a.Name, 27 | a.Doc, 28 | []*analysis.Analyzer{a}, 29 | cfg, 30 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 31 | } 32 | -------------------------------------------------------------------------------- /test/testdata/default_exclude.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Estylecheck,golint --internal-cmd-test 2 | //golangcitest:config_path testdata/configs/default_exclude.yml 3 | 4 | /*Package testdata ...*/ 5 | package testdata 6 | 7 | // InvalidFuncComment, both golint and stylecheck will complain about this, // want stylecheck:`ST1020: comment on exported function ExportedFunc1 should be of the form "ExportedFunc1 ..."` 8 | // if include EXC0011, only the warning from golint will be ignored. 9 | // And only the warning from stylecheck will start with "ST1020". 10 | func ExportedFunc1() { 11 | } 12 | 13 | // InvalidFuncComment // want stylecheck:`ST1020: comment on exported function ExportedFunc2 should be of the form "ExportedFunc2 ..."` 14 | // 15 | //nolint:golint 16 | func ExportedFunc2() { 17 | } 18 | 19 | //nolint:stylecheck 20 | func IgnoreAll() { 21 | } 22 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [context.production.environment] 2 | GO_VERSION = "1.19" 3 | NODE_VERSION = "17" 4 | # TODO https://github.com/golangci/golangci-lint/pull/2904#issuecomment-1146870535 5 | # NPM_FLAGS = "--legacy-peer-deps" 6 | # NPM_FLAGS = "--force" 7 | NPM_VERSION = "8.5.5" 8 | 9 | [context.deploy-preview.environment] 10 | GO_VERSION = "1.19" 11 | NODE_VERSION = "17" 12 | # TODO https://github.com/golangci/golangci-lint/pull/2904#issuecomment-1146870535 13 | # NPM_FLAGS = "--legacy-peer-deps" 14 | # NPM_FLAGS = "--force" 15 | NPM_VERSION = "8.5.5" 16 | 17 | [context.branch-deploy.environment] 18 | GO_VERSION = "1.19" 19 | NODE_VERSION = "17" 20 | # TODO https://github.com/golangci/golangci-lint/pull/2904#issuecomment-1146870535 21 | # NPM_FLAGS = "--legacy-peer-deps" 22 | # NPM_FLAGS = "--force" 23 | NPM_VERSION = "8.5.5" 24 | -------------------------------------------------------------------------------- /pkg/golinters/paralleltest.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/kunwardeep/paralleltest/pkg/paralleltest" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewParallelTest(settings *config.ParallelTestSettings) *goanalysis.Linter { 12 | a := paralleltest.Analyzer 13 | 14 | var cfg map[string]map[string]interface{} 15 | if settings != nil { 16 | cfg = map[string]map[string]interface{}{ 17 | a.Name: { 18 | "i": settings.IgnoreMissing, 19 | }, 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | "paralleltest", 25 | "paralleltest detects missing usage of t.Parallel() method in your Go test", 26 | []*analysis.Analyzer{a}, 27 | cfg, 28 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/golinters/asasalint.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/alingse/asasalint" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewAsasalint(setting *config.AsasalintSettings) *goanalysis.Linter { 12 | cfg := asasalint.LinterSetting{} 13 | if setting != nil { 14 | cfg.Exclude = setting.Exclude 15 | cfg.NoBuiltinExclusions = !setting.UseBuiltinExclusions 16 | cfg.IgnoreTest = setting.IgnoreTest 17 | } 18 | 19 | a, err := asasalint.NewAnalyzer(cfg) 20 | if err != nil { 21 | linterLogger.Fatalf("asasalint: create analyzer: %v", err) 22 | } 23 | 24 | return goanalysis.NewLinter( 25 | a.Name, 26 | a.Doc, 27 | []*analysis.Analyzer{a}, 28 | nil, 29 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 30 | } 31 | -------------------------------------------------------------------------------- /test/testdata/importas_strict.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eimportas 2 | //golangcitest:config_path testdata/configs/importas_strict.yml 3 | package testdata 4 | 5 | import ( 6 | wrong_alias "fmt" // want `import "fmt" imported as "wrong_alias" but must be "fff" according to config` 7 | "os" // want `import "os" imported without alias but must be with alias "std_os" according to config` 8 | wrong_alias_again "os" // want `import "os" imported as "wrong_alias_again" but must be "std_os" according to config` 9 | 10 | wrong "github.com/pkg/errors" // want `import "github.com/pkg/errors" imported as "wrong" but must be "pkgerr" according to config` 11 | ) 12 | 13 | func ImportAsStrictWrongAlias() { 14 | wrong_alias.Println("foo") 15 | wrong_alias_again.Stdout.WriteString("bar") 16 | os.Stdout.WriteString("test") 17 | _ = wrong.New("baz") 18 | } 19 | -------------------------------------------------------------------------------- /internal/cache/readme.md: -------------------------------------------------------------------------------- 1 | # cache 2 | 3 | Extracted from go/src/cmd/go/internal/cache/ 4 | I don't know what version of Go this package was pulled from. 5 | 6 | Adapted for golangci-lint: 7 | - https://github.com/golangci/golangci-lint/pull/699 8 | - https://github.com/golangci/golangci-lint/pull/779 9 | - https://github.com/golangci/golangci-lint/pull/788 10 | - https://github.com/golangci/golangci-lint/pull/808 11 | - https://github.com/golangci/golangci-lint/pull/1063 12 | - https://github.com/golangci/golangci-lint/pull/1070 13 | - https://github.com/golangci/golangci-lint/pull/1162 14 | - https://github.com/golangci/golangci-lint/pull/2318 15 | - https://github.com/golangci/golangci-lint/pull/2352 16 | - https://github.com/golangci/golangci-lint/pull/3012 17 | - https://github.com/golangci/golangci-lint/pull/3096 18 | - https://github.com/golangci/golangci-lint/pull/3204 19 | -------------------------------------------------------------------------------- /pkg/golinters/reassign.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | 7 | "github.com/curioswitch/go-reassign" 8 | "golang.org/x/tools/go/analysis" 9 | 10 | "github.com/golangci/golangci-lint/pkg/config" 11 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 12 | ) 13 | 14 | func NewReassign(settings *config.ReassignSettings) *goanalysis.Linter { 15 | a := reassign.NewAnalyzer() 16 | 17 | var cfg map[string]map[string]interface{} 18 | if settings != nil && len(settings.Patterns) > 0 { 19 | cfg = map[string]map[string]interface{}{ 20 | a.Name: { 21 | reassign.FlagPattern: fmt.Sprintf("^(%s)$", strings.Join(settings.Patterns, "|")), 22 | }, 23 | } 24 | } 25 | 26 | return goanalysis.NewLinter( 27 | a.Name, 28 | a.Doc, 29 | []*analysis.Analyzer{a}, 30 | cfg, 31 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 32 | } 33 | -------------------------------------------------------------------------------- /test/testdata/errcheck.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrcheck 2 | package testdata 3 | 4 | import ( 5 | "bytes" 6 | "net/http" 7 | "os" 8 | ) 9 | 10 | func RetErr() error { 11 | return nil 12 | } 13 | 14 | func MissedErrorCheck() { 15 | RetErr() // want "Error return value is not checked" 16 | } 17 | 18 | func IgnoreCloseMissingErrHandling() error { 19 | f, err := os.Open("t.go") 20 | if err != nil { 21 | return err 22 | } 23 | 24 | f.Close() 25 | return nil 26 | } 27 | 28 | func IgnoreCloseInDeferMissingErrHandling() { 29 | resp, err := http.Get("http://example.com/") 30 | if err != nil { 31 | panic(err) 32 | } 33 | defer resp.Body.Close() 34 | 35 | panic(resp) 36 | } 37 | 38 | func IgnoreStdxWrite() { 39 | os.Stdout.Write([]byte{}) 40 | os.Stderr.Write([]byte{}) 41 | } 42 | 43 | func IgnoreBufferWrites(buf *bytes.Buffer) { 44 | buf.WriteString("x") 45 | } 46 | -------------------------------------------------------------------------------- /test/testdata/errorlint.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eerrorlint 2 | package testdata 3 | 4 | import ( 5 | "errors" 6 | "fmt" 7 | "log" 8 | ) 9 | 10 | var errLintFoo = errors.New("foo") 11 | 12 | type errLintBar struct{} 13 | 14 | func (*errLintBar) Error() string { 15 | return "bar" 16 | } 17 | 18 | func errorLintAll() { 19 | err := func() error { return nil }() 20 | if err == errLintFoo { // want "comparing with == will fail on wrapped errors. Use errors.Is to check for a specific error" 21 | log.Println("errCompare") 22 | } 23 | 24 | err = errors.New("oops") 25 | fmt.Errorf("error: %v", err) // want "non-wrapping format verb for fmt.Errorf. Use `%w` to format errors" 26 | 27 | switch err.(type) { // want "type switch on error will fail on wrapped errors. Use errors.As to check for specific errors" 28 | case *errLintBar: 29 | log.Println("errLintBar") 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /pkg/fsutils/path_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | package fsutils 4 | 5 | import ( 6 | "path/filepath" 7 | "regexp" 8 | "strings" 9 | ) 10 | 11 | var separatorToReplace = regexp.QuoteMeta(string(filepath.Separator)) 12 | 13 | // NormalizePathInRegex normalizes path in regular expressions. 14 | // noop on Unix. 15 | // This replacing should be safe because "/" are disallowed in Windows 16 | // https://docs.microsoft.com/windows/win32/fileio/naming-a-file 17 | func NormalizePathInRegex(path string) string { 18 | // remove redundant character escape "\/" https://github.com/golangci/golangci-lint/issues/3277 19 | clean := regexp.MustCompile(`\\+/`). 20 | ReplaceAllStringFunc(path, func(s string) string { 21 | if strings.Count(s, "\\")%2 == 0 { 22 | return s 23 | } 24 | return s[1:] 25 | }) 26 | 27 | return strings.ReplaceAll(clean, "/", separatorToReplace) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/golinters/ginkgolinter.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/nunnatsa/ginkgolinter" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewGinkgoLinter(cfg *config.GinkgoLinterSettings) *goanalysis.Linter { 12 | a := ginkgolinter.NewAnalyzer() 13 | 14 | cfgMap := make(map[string]map[string]interface{}) 15 | if cfg != nil { 16 | cfgMap[a.Name] = map[string]interface{}{ 17 | "suppress-len-assertion": cfg.SuppressLenAssertion, 18 | "suppress-nil-assertion": cfg.SuppressNilAssertion, 19 | "suppress-err-assertion": cfg.SuppressErrAssertion, 20 | } 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | a.Name, 25 | a.Doc, 26 | []*analysis.Analyzer{a}, 27 | cfgMap, 28 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/golinters/ifshort.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/esimonov/ifshort/pkg/analyzer" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewIfshort(settings *config.IfshortSettings) *goanalysis.Linter { 12 | var cfg map[string]map[string]interface{} 13 | if settings != nil { 14 | cfg = map[string]map[string]interface{}{ 15 | analyzer.Analyzer.Name: { 16 | "max-decl-lines": settings.MaxDeclLines, 17 | "max-decl-chars": settings.MaxDeclChars, 18 | }, 19 | } 20 | } 21 | 22 | return goanalysis.NewLinter( 23 | "ifshort", 24 | "Checks that your code uses short syntax for if-statements whenever possible", 25 | []*analysis.Analyzer{analyzer.Analyzer}, 26 | cfg, 27 | ).WithLoadMode(goanalysis.LoadModeSyntax) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/golinters/tagliatelle.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/ldez/tagliatelle" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewTagliatelle(settings *config.TagliatelleSettings) *goanalysis.Linter { 12 | cfg := tagliatelle.Config{ 13 | Rules: map[string]string{ 14 | "json": "camel", 15 | "yaml": "camel", 16 | "header": "header", 17 | }, 18 | } 19 | 20 | if settings != nil { 21 | for k, v := range settings.Case.Rules { 22 | cfg.Rules[k] = v 23 | } 24 | cfg.UseFieldName = settings.Case.UseFieldName 25 | } 26 | 27 | a := tagliatelle.New(cfg) 28 | 29 | return goanalysis.NewLinter( 30 | a.Name, 31 | a.Doc, 32 | []*analysis.Analyzer{a}, 33 | nil, 34 | ).WithLoadMode(goanalysis.LoadModeSyntax) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/golinters/testpackage.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "strings" 5 | 6 | "github.com/maratori/testpackage/pkg/testpackage" 7 | "golang.org/x/tools/go/analysis" 8 | 9 | "github.com/golangci/golangci-lint/pkg/config" 10 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 11 | ) 12 | 13 | func NewTestpackage(cfg *config.TestpackageSettings) *goanalysis.Linter { 14 | var a = testpackage.NewAnalyzer() 15 | 16 | var settings map[string]map[string]interface{} 17 | if cfg != nil { 18 | settings = map[string]map[string]interface{}{ 19 | a.Name: { 20 | testpackage.SkipRegexpFlagName: cfg.SkipRegexp, 21 | testpackage.AllowPackagesFlagName: strings.Join(cfg.AllowPackages, ","), 22 | }, 23 | } 24 | } 25 | 26 | return goanalysis.NewLinter(a.Name, a.Doc, []*analysis.Analyzer{a}, settings). 27 | WithLoadMode(goanalysis.LoadModeSyntax) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/packages/errors.go: -------------------------------------------------------------------------------- 1 | package packages 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "go/token" 7 | "strconv" 8 | "strings" 9 | ) 10 | 11 | func ParseErrorPosition(pos string) (*token.Position, error) { 12 | // file:line(:colon) 13 | parts := strings.Split(pos, ":") 14 | if len(parts) == 1 { 15 | return nil, errors.New("no colons") 16 | } 17 | 18 | file := parts[0] 19 | line, err := strconv.Atoi(parts[1]) 20 | if err != nil { 21 | return nil, fmt.Errorf("can't parse line number %q: %s", parts[1], err) 22 | } 23 | 24 | var column int 25 | if len(parts) == 3 { // no column 26 | column, err = strconv.Atoi(parts[2]) 27 | if err != nil { 28 | return nil, fmt.Errorf("failed to parse column from %q: %w", parts[2], err) 29 | } 30 | } 31 | 32 | return &token.Position{ 33 | Filename: file, 34 | Line: line, 35 | Column: column, 36 | }, nil 37 | } 38 | -------------------------------------------------------------------------------- /test/testdata/musttag_custom.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Emusttag 2 | //golangcitest:config_path testdata/configs/musttag.yml 3 | package testdata 4 | 5 | import ( 6 | "encoding/asn1" 7 | "encoding/json" 8 | ) 9 | 10 | // builtin functions: 11 | func musttagJSONCustom() { 12 | var user struct { // want "`anonymous struct` should be annotated with the `json` tag as it is passed to `json.Marshal` at test(/|\\\\)testdata(/|\\\\)musttag_custom.go:16:2" 13 | Name string 14 | Email string `json:"email"` 15 | } 16 | json.Marshal(user) 17 | } 18 | 19 | // custom functions from config: 20 | func musttagASN1Custom() { 21 | var user struct { // want "`anonymous struct` should be annotated with the `asn1` tag as it is passed to `asn1.Marshal` at test(/|\\\\)testdata(/|\\\\)musttag_custom.go:25:2" 22 | Name string 23 | Email string `asn1:"email"` 24 | } 25 | asn1.Marshal(user) 26 | } 27 | -------------------------------------------------------------------------------- /test/testdata/gosec.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egosec 2 | package testdata 3 | 4 | import ( 5 | "crypto/md5" // want "G501: Blocklisted import crypto/md5: weak cryptographic primitive" 6 | "fmt" 7 | "log" 8 | "os" 9 | "os/exec" 10 | ) 11 | 12 | func Gosec() { 13 | h := md5.New() // want "G401: Use of weak cryptographic primitive" 14 | log.Print(h) 15 | } 16 | 17 | func GosecNolintGas() { 18 | h := md5.New() //nolint:gas 19 | log.Print(h) 20 | } 21 | 22 | func GosecNolintGosec() { 23 | h := md5.New() //nolint:gosec 24 | log.Print(h) 25 | } 26 | 27 | func GosecNoErrorCheckingByDefault() { 28 | f, _ := os.Create("foo") 29 | fmt.Println(f) 30 | } 31 | 32 | func GosecG204SubprocWithFunc() { 33 | arg := func() string { 34 | return "/tmp/dummy" 35 | } 36 | 37 | exec.Command("ls", arg()).Run() // want "G204: Subprocess launched with a potential tainted input or cmd arguments" 38 | } 39 | -------------------------------------------------------------------------------- /test/testdata/exhaustruct.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexhaustruct 2 | package testdata 3 | 4 | import "time" 5 | 6 | type Exhaustruct struct { 7 | A string 8 | B int 9 | c bool // private field inside the same package are not ignored 10 | D float64 11 | E time.Time 12 | } 13 | 14 | func exhaustruct() { 15 | // pass 16 | _ = Exhaustruct{ 17 | A: "a", 18 | B: 0, 19 | c: false, 20 | D: 1.0, 21 | E: time.Now(), 22 | } 23 | 24 | // failPrivate 25 | _ = Exhaustruct{ // want "c is missing in Exhaustruct" 26 | A: "a", 27 | B: 0, 28 | D: 1.0, 29 | E: time.Now(), 30 | } 31 | 32 | // fail 33 | _ = Exhaustruct{ // want "B is missing in Exhaustruct" 34 | A: "a", 35 | c: false, 36 | D: 1.0, 37 | E: time.Now(), 38 | } 39 | 40 | // failMultiple 41 | _ = Exhaustruct{ // want "B, D are missing in Exhaustruct" 42 | A: "a", 43 | c: false, 44 | E: time.Now(), 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /pkg/lint/linter/linter.go: -------------------------------------------------------------------------------- 1 | package linter 2 | 3 | import ( 4 | "context" 5 | 6 | "golang.org/x/tools/go/analysis" 7 | 8 | "github.com/golangci/golangci-lint/pkg/result" 9 | ) 10 | 11 | type Linter interface { 12 | Run(ctx context.Context, lintCtx *Context) ([]result.Issue, error) 13 | Name() string 14 | Desc() string 15 | } 16 | 17 | type Noop struct { 18 | name string 19 | desc string 20 | run func(pass *analysis.Pass) (interface{}, error) 21 | } 22 | 23 | func (n Noop) Run(_ context.Context, lintCtx *Context) ([]result.Issue, error) { 24 | lintCtx.Log.Warnf("%s is disabled because of generics."+ 25 | " You can track the evolution of the generics support by following the https://github.com/golangci/golangci-lint/issues/2649.", n.name) 26 | return nil, nil 27 | } 28 | 29 | func (n Noop) Name() string { 30 | return n.name 31 | } 32 | 33 | func (n Noop) Desc() string { 34 | return n.desc 35 | } 36 | -------------------------------------------------------------------------------- /pkg/packages/skip_test.go: -------------------------------------------------------------------------------- 1 | package packages 2 | 3 | import ( 4 | "regexp" 5 | "strings" 6 | "testing" 7 | 8 | "github.com/stretchr/testify/assert" 9 | ) 10 | 11 | func TestPathElemRe(t *testing.T) { 12 | matches := [][]string{ 13 | {"dir"}, 14 | {"root", "dir"}, 15 | {"root", "dir", "subdir"}, 16 | {"dir", "subdir"}, 17 | } 18 | noMatches := [][]string{ 19 | {"nodir"}, 20 | {"dirno"}, 21 | {"root", "dirno"}, 22 | {"root", "nodir"}, 23 | {"root", "dirno", "subdir"}, 24 | {"root", "nodir", "subdir"}, 25 | {"dirno", "subdir"}, 26 | {"nodir", "subdir"}, 27 | } 28 | for _, sep := range []rune{'/', '\\'} { 29 | reStr := pathElemReImpl("dir", sep) 30 | re := regexp.MustCompile(reStr) 31 | for _, m := range matches { 32 | assert.Regexp(t, re, strings.Join(m, string(sep))) 33 | } 34 | for _, m := range noMatches { 35 | assert.NotRegexp(t, re, strings.Join(m, string(sep))) 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /internal/robustio/robustio_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2019 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package robustio 6 | 7 | import ( 8 | "errors" 9 | "syscall" 10 | ) 11 | 12 | const errFileNotFound = syscall.ERROR_FILE_NOT_FOUND 13 | 14 | // ERROR_SHARING_VIOLATION (ldez) extract from go1.19.1/src/internal/syscall/windows/syscall_windows.go. 15 | // This is the only modification of this file. 16 | const ERROR_SHARING_VIOLATION syscall.Errno = 32 17 | 18 | // isEphemeralError returns true if err may be resolved by waiting. 19 | func isEphemeralError(err error) bool { 20 | var errno syscall.Errno 21 | if errors.As(err, &errno) { 22 | switch errno { 23 | case syscall.ERROR_ACCESS_DENIED, 24 | syscall.ERROR_FILE_NOT_FOUND, 25 | ERROR_SHARING_VIOLATION: 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | -------------------------------------------------------------------------------- /test/testdata/execinquery.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexecinquery 2 | package testdata 3 | 4 | import ( 5 | "context" 6 | "database/sql" 7 | ) 8 | 9 | func execInQuery(db *sql.DB) { 10 | test := "a" 11 | 12 | _, err := db.Query("Update * FROM hoge where id = ?", test) // want "Use Exec instead of Query to execute `UPDATE` query" 13 | if err != nil { 14 | return 15 | } 16 | 17 | db.QueryRow("Update * FROM hoge where id = ?", test) // want "Use Exec instead of QueryRow to execute `UPDATE` query" 18 | if err != nil { 19 | return 20 | } 21 | 22 | ctx := context.Background() 23 | 24 | _, err = db.QueryContext(ctx, "Update * FROM hoge where id = ?", test) // want "Use ExecContext instead of QueryContext to execute `UPDATE` query" 25 | if err != nil { 26 | return 27 | } 28 | 29 | db.QueryRowContext(ctx, "Update * FROM hoge where id = ?", test) // want "Use ExecContext instead of QueryRowContext to execute `UPDATE` query" 30 | } 31 | -------------------------------------------------------------------------------- /test/testdata/loggercheck/loggercheck_requirestringkey.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eloggercheck 2 | //golangcitest:config_path configs/loggercheck_requirestringkey.yml 3 | package loggercheck 4 | 5 | import ( 6 | "github.com/go-logr/logr" 7 | ) 8 | 9 | func ExampleRequireStringKey() { 10 | log := logr.Discard() 11 | log.Info("message", "key1", "value1") 12 | const key1 = "key1" 13 | log.Info("message", key1, "value1") 14 | 15 | key2 := []byte(key1) 16 | log.Info("message", key2, "value2") // want `logging keys are expected to be inlined constant strings, please replace "key2" provided with string` 17 | 18 | key3 := key1 19 | log.Info("message", key3, "value3") // want `logging keys are expected to be inlined constant strings, please replace "key3" provided with string` 20 | 21 | log.Info("message", "键1", "value1") // want `logging keys are expected to be alphanumeric strings, please remove any non-latin characters from "键1"` 22 | } 23 | -------------------------------------------------------------------------------- /pkg/golinters/errorlint.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "github.com/polyfloyd/go-errorlint/errorlint" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/config" 8 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 9 | ) 10 | 11 | func NewErrorLint(cfg *config.ErrorLintSettings) *goanalysis.Linter { 12 | a := errorlint.NewAnalyzer() 13 | 14 | cfgMap := map[string]map[string]interface{}{} 15 | 16 | if cfg != nil { 17 | cfgMap[a.Name] = map[string]interface{}{ 18 | "errorf": cfg.Errorf, 19 | "asserts": cfg.Asserts, 20 | "comparison": cfg.Comparison, 21 | } 22 | } 23 | 24 | return goanalysis.NewLinter( 25 | a.Name, 26 | "errorlint is a linter for that can be used to find code "+ 27 | "that will cause problems with the error wrapping scheme introduced in Go 1.13.", 28 | []*analysis.Analyzer{a}, 29 | cfgMap, 30 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 31 | } 32 | -------------------------------------------------------------------------------- /pkg/golinters/gochecknoglobals.go: -------------------------------------------------------------------------------- 1 | package golinters 2 | 3 | import ( 4 | "4d63.com/gochecknoglobals/checknoglobals" 5 | "golang.org/x/tools/go/analysis" 6 | 7 | "github.com/golangci/golangci-lint/pkg/golinters/goanalysis" 8 | ) 9 | 10 | func NewGochecknoglobals() *goanalysis.Linter { 11 | gochecknoglobals := checknoglobals.Analyzer() 12 | 13 | // gochecknoglobals only lints test files if the `-t` flag is passed, so we 14 | // pass the `t` flag as true to the analyzer before running it. This can be 15 | // turned off by using the regular golangci-lint flags such as `--tests` or 16 | // `--skip-files`. 17 | linterConfig := map[string]map[string]interface{}{ 18 | gochecknoglobals.Name: { 19 | "t": true, 20 | }, 21 | } 22 | 23 | return goanalysis.NewLinter( 24 | gochecknoglobals.Name, 25 | gochecknoglobals.Doc, 26 | []*analysis.Analyzer{gochecknoglobals}, 27 | linterConfig, 28 | ).WithLoadMode(goanalysis.LoadModeTypesInfo) 29 | } 30 | -------------------------------------------------------------------------------- /test/testdata/configs/gocritic.yml: -------------------------------------------------------------------------------- 1 | linters-settings: 2 | gocritic: 3 | enabled-checks: 4 | - rangeValCopy 5 | - flagDeref 6 | - wrapperFunc 7 | - ruleguard 8 | settings: 9 | rangeValCopy: 10 | sizeThreshold: 2 11 | ruleguard: 12 | debug: dupSubExpr 13 | failOn: dsl,import 14 | # comma-separated paths to ruleguard files. 15 | # The ${configDir} is substituted by the directory containing the golangci-lint config file. 16 | # Note about the directory structure for functional tests: 17 | # The ruleguard files used in functional tests cannot be under the 'testdata' directory. 18 | # This is because they import the 'github.com/quasilyte/go-ruleguard/dsl' package, 19 | # which needs to be added to go.mod. The testdata directory is ignored by go mod. 20 | rules: '${configDir}/../../ruleguard/strings_simplify.go,${configDir}/../../ruleguard/dup.go' 21 | -------------------------------------------------------------------------------- /test/testdata/goconst_dont_ignore_test.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Egoconst 2 | //golangcitest:config_path testdata/configs/goconst_dont_ignore.yml 3 | package testdata 4 | 5 | import ( 6 | "fmt" 7 | "testing" 8 | ) 9 | 10 | func TestGoConstA(t *testing.T) { 11 | a := "needconst" // want "string `needconst` has 5 occurrences, make it a constant" 12 | fmt.Print(a) 13 | b := "needconst" 14 | fmt.Print(b) 15 | c := "needconst" 16 | fmt.Print(c) 17 | } 18 | 19 | func TestGoConstB(t *testing.T) { 20 | a := "needconst" 21 | fmt.Print(a) 22 | b := "needconst" 23 | fmt.Print(b) 24 | } 25 | 26 | const AlreadyHasConst = "alreadyhasconst" 27 | 28 | func TestGoConstC(t *testing.T) { 29 | a := "alreadyhasconst" // want "string `alreadyhasconst` has 3 occurrences, but such constant `AlreadyHasConst` already exists" 30 | fmt.Print(a) 31 | b := "alreadyhasconst" 32 | fmt.Print(b) 33 | c := "alreadyhasconst" 34 | fmt.Print(c) 35 | fmt.Print("alreadyhasconst") 36 | } 37 | -------------------------------------------------------------------------------- /test/testdata/exhaustivestruct.go: -------------------------------------------------------------------------------- 1 | //golangcitest:args -Eexhaustivestruct --internal-cmd-test 2 | package testdata 3 | 4 | import "time" 5 | 6 | type ExhaustiveStruct struct { 7 | A string 8 | B int 9 | c bool // private field inside the same package are not ignored 10 | D float64 11 | E time.Time 12 | } 13 | 14 | func exhaustiveStruct() { 15 | // pass 16 | _ = ExhaustiveStruct{ 17 | A: "a", 18 | B: 0, 19 | c: false, 20 | D: 1.0, 21 | E: time.Now(), 22 | } 23 | 24 | // failPrivate 25 | _ = ExhaustiveStruct{ // want "c is missing in ExhaustiveStruct" 26 | A: "a", 27 | B: 0, 28 | D: 1.0, 29 | E: time.Now(), 30 | } 31 | 32 | // fail 33 | _ = ExhaustiveStruct{ // want "B is missing in ExhaustiveStruct" 34 | A: "a", 35 | c: false, 36 | D: 1.0, 37 | E: time.Now(), 38 | } 39 | 40 | // failMultiple 41 | _ = ExhaustiveStruct{ // want "B, D are missing in ExhaustiveStruct" 42 | A: "a", 43 | c: false, 44 | E: time.Now(), 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /docs/src/components/SearchBar/styles.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | .search-icon { 9 | background-image: var(--ifm-navbar-search-input-icon); 10 | height: auto; 11 | width: 24px; 12 | cursor: pointer; 13 | padding: 8px; 14 | line-height: 32px; 15 | background-repeat: no-repeat; 16 | background-position: center; 17 | display: none; 18 | } 19 | 20 | .search-icon-hidden { 21 | visibility: hidden; 22 | } 23 | 24 | @media (max-width: 360px) { 25 | .search-bar { 26 | width: 0 !important; 27 | background: none !important; 28 | padding: 0 !important; 29 | transition: none !important; 30 | } 31 | 32 | .search-bar-expanded { 33 | width: 9rem !important; 34 | } 35 | 36 | .search-icon { 37 | display: inline; 38 | vertical-align: sub; 39 | } 40 | } 41 | --------------------------------------------------------------------------------