generate command line options section of README
This commit is contained in:
		
							parent
							
								
									4df5df2ab7
								
							
						
					
					
						commit
						9133ef4271
					
				| @ -10,7 +10,6 @@ output: | |||||||
|   format: colored-line-number |   format: colored-line-number | ||||||
|   print-issued-lines: true |   print-issued-lines: true | ||||||
|   print-linter-name: true |   print-linter-name: true | ||||||
|   print-welcome: true |  | ||||||
| 
 | 
 | ||||||
| linters-settings: | linters-settings: | ||||||
|   errcheck: |   errcheck: | ||||||
|  | |||||||
| @ -20,7 +20,3 @@ linters: | |||||||
|   enable-all: true |   enable-all: true | ||||||
|   disable: |   disable: | ||||||
|     - maligned |     - maligned | ||||||
| 
 |  | ||||||
| issues: |  | ||||||
|   exclude: |  | ||||||
|     - should have a package comment |  | ||||||
|  | |||||||
							
								
								
									
										1
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Makefile
									
									
									
									
									
								
							| @ -2,7 +2,6 @@ test: | |||||||
| 	go install ./cmd/... | 	go install ./cmd/... | ||||||
| 	golangci-lint run -v | 	golangci-lint run -v | ||||||
| 	golangci-lint run --fast --no-config -v | 	golangci-lint run --fast --no-config -v | ||||||
| 	golangci-lint run --fast --no-config -v |  | ||||||
| 	golangci-lint run --no-config -v | 	golangci-lint run --no-config -v | ||||||
| 	golangci-lint run --fast --no-config -v ./test/testdata/typecheck.go | 	golangci-lint run --fast --no-config -v ./test/testdata/typecheck.go | ||||||
| 	go test -v -race ./... | 	go test -v -race ./... | ||||||
|  | |||||||
							
								
								
									
										170
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										170
									
								
								README.md
									
									
									
									
									
								
							| @ -134,7 +134,10 @@ This issue is important because often you'd like to set concurrency to CPUs coun | |||||||
| 3. It will take more time because of different usages and need of tracking of versions of `n` linters. | 3. It will take more time because of different usages and need of tracking of versions of `n` linters. | ||||||
| 
 | 
 | ||||||
| # Performance | # Performance | ||||||
| Benchmarks were executed on MacBook Pro (Retina, 13-inch, Late 2013), 2,4 GHz Intel Core i5, 8 GB 1600 MHz DDR3. It has 4 cores and concurrency for linters was default: number of cores. Benchmark runs and measures timings automatically, it's code is [here](https://github.com/golangci/golangci-lint/blob/master/test/bench.go) (`BenchmarkWithGometalinter`). | Benchmarks were executed on MacBook Pro (Retina, 13-inch, Late 2013), 2,4 GHz Intel Core i5, 8 GB 1600 MHz DDR3. | ||||||
|  | It has 4 cores and concurrency for linters was default: number of cores. | ||||||
|  | Benchmark runs and measures timings automatically, it's code is | ||||||
|  | [here](https://github.com/golangci/golangci-lint/blob/master/test/bench_test.go) (`BenchmarkWithGometalinter`). | ||||||
| 
 | 
 | ||||||
| We measure peak memory usage (RSS) by tracking of processes RSS every 5 ms. | We measure peak memory usage (RSS) by tracking of processes RSS every 5 ms. | ||||||
| 
 | 
 | ||||||
| @ -172,7 +175,7 @@ On average golangci-lint consumes 1.35 times less memory. | |||||||
| 
 | 
 | ||||||
| # Supported Linters | # Supported Linters | ||||||
| To see a list of supported linters and which linters are enabled/disabled by default execute a command | To see a list of supported linters and which linters are enabled/disabled by default execute a command | ||||||
| ```bash | ``` | ||||||
| golangci-lint linters | golangci-lint linters | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| @ -204,99 +207,77 @@ golangci-lint linters | |||||||
| 
 | 
 | ||||||
| # Configuration | # Configuration | ||||||
| ## Command-Line Options | ## Command-Line Options | ||||||
| Run next command to see their description and defaults. | ``` | ||||||
| ```bash |  | ||||||
| golangci-lint run -h | golangci-lint run -h | ||||||
|  | Usage: | ||||||
|  |   golangci-lint run [flags] | ||||||
|  | 
 | ||||||
|  | Flags: | ||||||
|  |       --out-format string           Format of output: colored-line-number|line-number|json (default "colored-line-number") | ||||||
|  |       --print-issued-lines          Print lines of code with issue (default true) | ||||||
|  |       --print-linter-name           Print linter name in issue line (default true) | ||||||
|  |       --issues-exit-code int        Exit code when issues were found (default 1) | ||||||
|  |       --build-tags strings          Build tags (not all linters support them) | ||||||
|  |       --deadline duration           Deadline for total work (default 1m0s) | ||||||
|  |       --tests                       Analyze tests (*_test.go) | ||||||
|  |       --print-resources-usage       Print avg and max memory usage of golangci-lint and total time | ||||||
|  |   -c, --config PATH                 Read config from file path PATH | ||||||
|  |       --no-config                   Don't read config | ||||||
|  |   -E, --enable strings              Enable specific linter | ||||||
|  |   -D, --disable strings             Disable specific linter | ||||||
|  |       --enable-all                  Enable all linters | ||||||
|  |       --disable-all                 Disable all linters | ||||||
|  |   -p, --presets strings             Enable presets (bugs|unused|format|style|complexity|performance) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all | ||||||
|  |       --fast                        Run only fast linters from enabled linters set | ||||||
|  |   -e, --exclude strings             Exclude issue by regexp | ||||||
|  |       --exclude-use-default         Use or not use default excludes: | ||||||
|  |                                       # errcheck: Almost all programs ignore errors on these functions and in most cases it's ok | ||||||
|  |                                       - Error return value of .((os\.)?std(out|err)\..*|.*Close|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked | ||||||
|  |                                      | ||||||
|  |                                       # golint: Annoying issue about not having a comment. The rare codebase has such comments | ||||||
|  |                                       - (should have comment|comment on exported method|should have a package comment) | ||||||
|  |                                      | ||||||
|  |                                       # golint: False positive when tests are defined in package 'test' | ||||||
|  |                                       - func name will be used as test\.Test.* by other packages, and that stutters; consider calling this | ||||||
|  |                                      | ||||||
|  |                                       # gas: Too many false-positives on 'unsafe' usage | ||||||
|  |                                       - Use of unsafe calls should be audited | ||||||
|  |                                      | ||||||
|  |                                       # gas: Too many false-positives for parametrized shell calls | ||||||
|  |                                       - Subprocess launch(ed with variable|ing should be audited) | ||||||
|  |                                      | ||||||
|  |                                       # gas: Duplicated errcheck checks | ||||||
|  |                                       - G104 | ||||||
|  |                                      | ||||||
|  |                                       # gas: Too many issues in popular repos | ||||||
|  |                                       - (Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less) | ||||||
|  |                                      | ||||||
|  |                                       # gas: False positive is triggered by 'src, err := ioutil.ReadFile(filename)' | ||||||
|  |                                       - Potential file inclusion via variable | ||||||
|  |                                      | ||||||
|  |                                       # govet: Common false positives | ||||||
|  |                                       - (possible misuse of unsafe.Pointer|should have signature) | ||||||
|  |                                      | ||||||
|  |                                       # megacheck: Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore | ||||||
|  |                                       - ineffective break statement. Did you mean to break out of the outer loop | ||||||
|  |                                      (default true) | ||||||
|  |       --max-issues-per-linter int   Maximum issues count per one linter. Set to 0 to disable (default 50) | ||||||
|  |       --max-same-issues int         Maximum count of issues with the same text. Set to 0 to disable (default 3) | ||||||
|  |   -n, --new                         Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed. | ||||||
|  |                                     It's a super-useful option for integration of golangci-lint into existing large codebase. | ||||||
|  |                                     It's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code | ||||||
|  |       --new-from-rev REV            Show only new issues created after git revision REV | ||||||
|  |       --new-from-patch PATH         Show only new issues created in git patch with file path PATH | ||||||
|  |   -h, --help                        help for run | ||||||
|  | 
 | ||||||
|  | Global Flags: | ||||||
|  |   -j, --concurrency int           Concurrency (default NumCPU) (default 8) | ||||||
|  |       --cpu-profile-path string   Path to CPU profile output file | ||||||
|  |       --mem-profile-path string   Path to memory profile output file | ||||||
|  |   -v, --verbose                   verbose output | ||||||
|  | 
 | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### Run Options |  | ||||||
| - `-c, --config` - path to [config file](#configuration-file) if you don't like using default config path `.golangci.(yml|toml|json)`. |  | ||||||
| - `-j, --concurrency` - the number of threads used. By default, it's a number of CPUs. Unlike `gometalinter`, it's an honest value, since we do not fork linter processes. |  | ||||||
| - `--build-tags` - build tags to take into account. |  | ||||||
| - `--issues-exit-code` - exit code if issues were found. The default is `1`. |  | ||||||
| - `--deadline` - timeout for running golangci-lint, `1m` by default. |  | ||||||
| - `--tests` - analyze `*_test.go` files. It's `false` by default. |  | ||||||
| - `-v, --verbose` - enable verbose output. Use this options to see which linters were enabled, to see timings of steps and another helpful information. |  | ||||||
| - `--print-resources-usage` - print memory usage and total time elapsed. |  | ||||||
| 
 |  | ||||||
| ### Linters |  | ||||||
| - `-E, --enable` - enable specific linter. You can pass option multiple times or use a comma: |  | ||||||
| ```bash |  | ||||||
| golangci-lint run --disable-all -E golint -E govet -E errcheck |  | ||||||
| golangci-lint run --disable-all --enable golint,govet,errcheck |  | ||||||
| ``` |  | ||||||
| - `-D, --disable` - disable specific linter. Similar to enabling option. |  | ||||||
| - `--enable-all` - enable all supported linters. |  | ||||||
| - `--disable-all` - disable all supported linters. |  | ||||||
| - `-p, --presets` - enable specific presets. To list all presets run |  | ||||||
| ```bash |  | ||||||
| $ golangci-lint linters |  | ||||||
| ... |  | ||||||
| Linters presets: |  | ||||||
| bugs: govet, errcheck, staticcheck, gas, megacheck |  | ||||||
| unused: unused, structcheck, varcheck, ineffassign, deadcode, megacheck |  | ||||||
| format: gofmt, goimports |  | ||||||
| style: golint, gosimple, interfacer, unconvert, dupl, goconst, megacheck, depguard |  | ||||||
| complexity: gocyclo |  | ||||||
| performance: maligned |  | ||||||
| ``` |  | ||||||
| Usage example: |  | ||||||
| ```bash |  | ||||||
| $ golangci-lint run -v --disable-all -p bugs,style,complexity,format |  | ||||||
| INFO[0000] Active linters: [govet goconst gocyclo gofmt gas dupl goimports megacheck interfacer unconvert errcheck golint] |  | ||||||
| ``` |  | ||||||
| - `--fast` - run only fast linters from the enabled set of linters. To find out which linters are fast run `golangci-lint linters`. |  | ||||||
| 
 |  | ||||||
| ### Linters Options |  | ||||||
| - `--errcheck.check-type-assertions` - errcheck: check for ignored type assertion results. Disabled by default. |  | ||||||
| - `--errcheck.check-blank` - errcheck: check for errors assigned to blank identifier: `_ = errFunc()`. Disabled by default |  | ||||||
| - `--govet.check-shadowing` - govet: check for shadowed variables. Disabled by default. |  | ||||||
| - `--golint.min-confidence` - golint: minimum confidence of a problem to print it. The default is `0.8`. |  | ||||||
| - `--gofmt.simplify` - gofmt: simplify code (`gofmt -s`), enabled by default. |  | ||||||
| - `--gocyclo.min-complexity` - gocyclo: a minimal complexity of function to report it. The default is `30` (it's very high limit). |  | ||||||
| - `--maligned.suggest-new` - Maligned: print suggested more optimal struct fields ordering. Disabled by default. Example: |  | ||||||
| ``` |  | ||||||
| crypto/tls/ticket.go:20: struct of size 64 bytes could be of size 56 bytes: |  | ||||||
| struct{ |  | ||||||
| 	masterSecret	[]byte, |  | ||||||
| 	certificates	[][]byte, |  | ||||||
| 	vers        	uint16, |  | ||||||
| 	cipherSuite 	uint16, |  | ||||||
| 	usedOldKey  	bool, |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| - `--dupl.threshold` - dupl: Minimal threshold to detect copy-paste, `150` by default. |  | ||||||
| - `--goconst.min-len` - goconst: minimum constant string length, `3` by default. |  | ||||||
| - `--goconst.min-occurrences` - goconst: minimum occurences of constant string count to trigger issue. Default is `3`. |  | ||||||
| 
 |  | ||||||
| ### Issues Options |  | ||||||
| - `-n, --new` - show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed. It's a super-useful option for integration `golangci-lint` into existing large codebase. It's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code. Disabled by default. |  | ||||||
| - `--new-from-rev` - show only new issues created after specified git revision. |  | ||||||
| - `--new-from-patch` - show only new issues created in git patch with the specified file path. |  | ||||||
| - `-e, --exclude` - exclude issue by regexp on issue text. |  | ||||||
| - `--exclude-use-default` - use or not use default excludes. We tested our linter on large codebases and marked common false positives. By default we ignore common false positives by next regexps: |  | ||||||
|   - `Error return value of .((os\.)?std(out|err)\..*|.*Close|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked` - ercheck: almost all programs ignore errors on these functions and in most cases it's ok. |  | ||||||
|   - `(should have comment|comment on exported method)` - golint: annoying issues about not having a comment. The rare codebase has such comments. |  | ||||||
|   - `G103:` - gas: `Use of unsafe calls should be audited` |  | ||||||
|   - `G104:` - gas: `disable what errcheck does: it reports on Close etc` |  | ||||||
|   - `G204:` - gas: `Subprocess launching should be audited: too lot false - positives` |  | ||||||
|   - `G301:` - gas: `Expect directory permissions to be 0750 or less` |  | ||||||
|   - `G302:` - gas: `Expect file permissions to be 0600 or less` |  | ||||||
|   - `G304:` - gas: ``Potential file inclusion via variable: `src, err := ioutil.ReadFile(filename)`.`` |  | ||||||
| 
 |  | ||||||
|   - `(possible misuse of unsafe.Pointer|should have signature)` - common false positives by govet. |  | ||||||
|   - `ineffective break statement. Did you mean to break out of the outer loop` - megacheck: developers tend to write in C-style with an explicit `break` in a switch, so it's ok to ignore. |  | ||||||
| 
 |  | ||||||
|   Use option `--exclude-use-default=false` to disable these default exclude regexps. |  | ||||||
| - `--max-issues-per-linter` - maximum issues count per one linter. Set to `0` to disable. The default value is `50` to not being annoying. |  | ||||||
| - `--max-same-issues` - maximum count of issues with the same text. Set to 0 to disable. The default value is `3` to not being annoying. |  | ||||||
| 
 |  | ||||||
| ### Output Options |  | ||||||
| - `--out-format` - format of output: `colored-line-number|line-number|json`, default is `colored-line-number`. |  | ||||||
| - `--print-issued-lines` - print line of source code where the issue occurred. Enabled by default. |  | ||||||
| - `--print-linter-name` - print linter name in issue line. Enabled by default. |  | ||||||
| - `--print-welcome` - print welcome message. Enabled by default. |  | ||||||
| 
 |  | ||||||
| ## Configuration File | ## Configuration File | ||||||
| GolangCI-Lint looks for next config paths in the current directory: | GolangCI-Lint looks for next config paths in the current directory: | ||||||
| - `.golangci.yml` | - `.golangci.yml` | ||||||
| @ -330,11 +311,6 @@ linters: | |||||||
|   enable-all: true |   enable-all: true | ||||||
|   disable: |   disable: | ||||||
|     - maligned |     - maligned | ||||||
| 
 |  | ||||||
| issues: |  | ||||||
|   exclude: |  | ||||||
|     - should have a package comment |  | ||||||
| 
 |  | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| # False Positives | # False Positives | ||||||
|  | |||||||
| @ -112,7 +112,10 @@ This issue is important because often you'd like to set concurrency to CPUs coun | |||||||
| 3. It will take more time because of different usages and need of tracking of versions of `n` linters. | 3. It will take more time because of different usages and need of tracking of versions of `n` linters. | ||||||
| 
 | 
 | ||||||
| # Performance | # Performance | ||||||
| Benchmarks were executed on MacBook Pro (Retina, 13-inch, Late 2013), 2,4 GHz Intel Core i5, 8 GB 1600 MHz DDR3. It has 4 cores and concurrency for linters was default: number of cores. Benchmark runs and measures timings automatically, it's code is [here](https://github.com/golangci/golangci-lint/blob/master/test/bench.go) (`BenchmarkWithGometalinter`). | Benchmarks were executed on MacBook Pro (Retina, 13-inch, Late 2013), 2,4 GHz Intel Core i5, 8 GB 1600 MHz DDR3. | ||||||
|  | It has 4 cores and concurrency for linters was default: number of cores. | ||||||
|  | Benchmark runs and measures timings automatically, it's code is | ||||||
|  | [here](https://github.com/golangci/golangci-lint/blob/master/test/bench_test.go) (`BenchmarkWithGometalinter`). | ||||||
| 
 | 
 | ||||||
| We measure peak memory usage (RSS) by tracking of processes RSS every 5 ms. | We measure peak memory usage (RSS) by tracking of processes RSS every 5 ms. | ||||||
| 
 | 
 | ||||||
| @ -150,7 +153,7 @@ On average golangci-lint consumes 1.35 times less memory. | |||||||
| 
 | 
 | ||||||
| # Supported Linters | # Supported Linters | ||||||
| To see a list of supported linters and which linters are enabled/disabled by default execute a command | To see a list of supported linters and which linters are enabled/disabled by default execute a command | ||||||
| ```bash | ``` | ||||||
| golangci-lint linters | golangci-lint linters | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| @ -162,99 +165,11 @@ golangci-lint linters | |||||||
| 
 | 
 | ||||||
| # Configuration | # Configuration | ||||||
| ## Command-Line Options | ## Command-Line Options | ||||||
| Run next command to see their description and defaults. | ``` | ||||||
| ```bash |  | ||||||
| golangci-lint run -h | golangci-lint run -h | ||||||
|  | {{.RunHelpText}} | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
| ### Run Options |  | ||||||
| - `-c, --config` - path to [config file](#configuration-file) if you don't like using default config path `.golangci.(yml|toml|json)`. |  | ||||||
| - `-j, --concurrency` - the number of threads used. By default, it's a number of CPUs. Unlike `gometalinter`, it's an honest value, since we do not fork linter processes. |  | ||||||
| - `--build-tags` - build tags to take into account. |  | ||||||
| - `--issues-exit-code` - exit code if issues were found. The default is `1`. |  | ||||||
| - `--deadline` - timeout for running golangci-lint, `1m` by default. |  | ||||||
| - `--tests` - analyze `*_test.go` files. It's `false` by default. |  | ||||||
| - `-v, --verbose` - enable verbose output. Use this options to see which linters were enabled, to see timings of steps and another helpful information. |  | ||||||
| - `--print-resources-usage` - print memory usage and total time elapsed. |  | ||||||
| 
 |  | ||||||
| ### Linters |  | ||||||
| - `-E, --enable` - enable specific linter. You can pass option multiple times or use a comma: |  | ||||||
| ```bash |  | ||||||
| golangci-lint run --disable-all -E golint -E govet -E errcheck |  | ||||||
| golangci-lint run --disable-all --enable golint,govet,errcheck |  | ||||||
| ``` |  | ||||||
| - `-D, --disable` - disable specific linter. Similar to enabling option. |  | ||||||
| - `--enable-all` - enable all supported linters. |  | ||||||
| - `--disable-all` - disable all supported linters. |  | ||||||
| - `-p, --presets` - enable specific presets. To list all presets run |  | ||||||
| ```bash |  | ||||||
| $ golangci-lint linters |  | ||||||
| ... |  | ||||||
| Linters presets: |  | ||||||
| bugs: govet, errcheck, staticcheck, gas, megacheck |  | ||||||
| unused: unused, structcheck, varcheck, ineffassign, deadcode, megacheck |  | ||||||
| format: gofmt, goimports |  | ||||||
| style: golint, gosimple, interfacer, unconvert, dupl, goconst, megacheck, depguard |  | ||||||
| complexity: gocyclo |  | ||||||
| performance: maligned |  | ||||||
| ``` |  | ||||||
| Usage example: |  | ||||||
| ```bash |  | ||||||
| $ golangci-lint run -v --disable-all -p bugs,style,complexity,format |  | ||||||
| INFO[0000] Active linters: [govet goconst gocyclo gofmt gas dupl goimports megacheck interfacer unconvert errcheck golint] |  | ||||||
| ``` |  | ||||||
| - `--fast` - run only fast linters from the enabled set of linters. To find out which linters are fast run `golangci-lint linters`. |  | ||||||
| 
 |  | ||||||
| ### Linters Options |  | ||||||
| - `--errcheck.check-type-assertions` - errcheck: check for ignored type assertion results. Disabled by default. |  | ||||||
| - `--errcheck.check-blank` - errcheck: check for errors assigned to blank identifier: `_ = errFunc()`. Disabled by default |  | ||||||
| - `--govet.check-shadowing` - govet: check for shadowed variables. Disabled by default. |  | ||||||
| - `--golint.min-confidence` - golint: minimum confidence of a problem to print it. The default is `0.8`. |  | ||||||
| - `--gofmt.simplify` - gofmt: simplify code (`gofmt -s`), enabled by default. |  | ||||||
| - `--gocyclo.min-complexity` - gocyclo: a minimal complexity of function to report it. The default is `30` (it's very high limit). |  | ||||||
| - `--maligned.suggest-new` - Maligned: print suggested more optimal struct fields ordering. Disabled by default. Example: |  | ||||||
| ``` |  | ||||||
| crypto/tls/ticket.go:20: struct of size 64 bytes could be of size 56 bytes: |  | ||||||
| struct{ |  | ||||||
| 	masterSecret	[]byte, |  | ||||||
| 	certificates	[][]byte, |  | ||||||
| 	vers        	uint16, |  | ||||||
| 	cipherSuite 	uint16, |  | ||||||
| 	usedOldKey  	bool, |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
| - `--dupl.threshold` - dupl: Minimal threshold to detect copy-paste, `150` by default. |  | ||||||
| - `--goconst.min-len` - goconst: minimum constant string length, `3` by default. |  | ||||||
| - `--goconst.min-occurrences` - goconst: minimum occurences of constant string count to trigger issue. Default is `3`. |  | ||||||
| 
 |  | ||||||
| ### Issues Options |  | ||||||
| - `-n, --new` - show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed. It's a super-useful option for integration `golangci-lint` into existing large codebase. It's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code. Disabled by default. |  | ||||||
| - `--new-from-rev` - show only new issues created after specified git revision. |  | ||||||
| - `--new-from-patch` - show only new issues created in git patch with the specified file path. |  | ||||||
| - `-e, --exclude` - exclude issue by regexp on issue text. |  | ||||||
| - `--exclude-use-default` - use or not use default excludes. We tested our linter on large codebases and marked common false positives. By default we ignore common false positives by next regexps: |  | ||||||
|   - `Error return value of .((os\.)?std(out|err)\..*|.*Close|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked` - ercheck: almost all programs ignore errors on these functions and in most cases it's ok. |  | ||||||
|   - `(should have comment|comment on exported method)` - golint: annoying issues about not having a comment. The rare codebase has such comments. |  | ||||||
|   - `G103:` - gas: `Use of unsafe calls should be audited` |  | ||||||
|   - `G104:` - gas: `disable what errcheck does: it reports on Close etc` |  | ||||||
|   - `G204:` - gas: `Subprocess launching should be audited: too lot false - positives` |  | ||||||
|   - `G301:` - gas: `Expect directory permissions to be 0750 or less` |  | ||||||
|   - `G302:` - gas: `Expect file permissions to be 0600 or less` |  | ||||||
|   - `G304:` - gas: ``Potential file inclusion via variable: `src, err := ioutil.ReadFile(filename)`.`` |  | ||||||
| 
 |  | ||||||
|   - `(possible misuse of unsafe.Pointer|should have signature)` - common false positives by govet. |  | ||||||
|   - `ineffective break statement. Did you mean to break out of the outer loop` - megacheck: developers tend to write in C-style with an explicit `break` in a switch, so it's ok to ignore. |  | ||||||
| 
 |  | ||||||
|   Use option `--exclude-use-default=false` to disable these default exclude regexps. |  | ||||||
| - `--max-issues-per-linter` - maximum issues count per one linter. Set to `0` to disable. The default value is `50` to not being annoying. |  | ||||||
| - `--max-same-issues` - maximum count of issues with the same text. Set to 0 to disable. The default value is `3` to not being annoying. |  | ||||||
| 
 |  | ||||||
| ### Output Options |  | ||||||
| - `--out-format` - format of output: `colored-line-number|line-number|json`, default is `colored-line-number`. |  | ||||||
| - `--print-issued-lines` - print line of source code where the issue occurred. Enabled by default. |  | ||||||
| - `--print-linter-name` - print linter name in issue line. Enabled by default. |  | ||||||
| - `--print-welcome` - print welcome message. Enabled by default. |  | ||||||
| 
 |  | ||||||
| ## Configuration File | ## Configuration File | ||||||
| GolangCI-Lint looks for next config paths in the current directory: | GolangCI-Lint looks for next config paths in the current directory: | ||||||
| - `.golangci.yml` | - `.golangci.yml` | ||||||
|  | |||||||
| @ -56,6 +56,14 @@ func (e *Executor) persistentPreRun(cmd *cobra.Command, args []string) { | |||||||
| 	os.Exit(e.exitCode) | 	os.Exit(e.exitCode) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func getDefaultConcurrency() int { | ||||||
|  | 	if os.Getenv("HELP_RUN") == "1" { | ||||||
|  | 		return 8 // to make stable concurrency for README help generating builds | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return runtime.NumCPU() | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (e *Executor) initRoot() { | func (e *Executor) initRoot() { | ||||||
| 	rootCmd := &cobra.Command{ | 	rootCmd := &cobra.Command{ | ||||||
| 		Use:   "golangci-lint", | 		Use:   "golangci-lint", | ||||||
| @ -69,11 +77,13 @@ func (e *Executor) initRoot() { | |||||||
| 		PersistentPreRun:  e.persistentPostRun, | 		PersistentPreRun:  e.persistentPostRun, | ||||||
| 		PersistentPostRun: e.persistentPreRun, | 		PersistentPostRun: e.persistentPreRun, | ||||||
| 	} | 	} | ||||||
| 	rootCmd.PersistentFlags().BoolVarP(&e.cfg.Run.IsVerbose, "verbose", "v", false, "verbose output") | 	rootCmd.PersistentFlags().BoolVarP(&e.cfg.Run.IsVerbose, "verbose", "v", false, wh("verbose output")) | ||||||
| 	rootCmd.PersistentFlags().StringVar(&e.cfg.Run.CPUProfilePath, "cpu-profile-path", "", "Path to CPU profile output file") | 	rootCmd.PersistentFlags().StringVar(&e.cfg.Run.CPUProfilePath, "cpu-profile-path", "", wh("Path to CPU profile output file")) | ||||||
| 	rootCmd.PersistentFlags().StringVar(&e.cfg.Run.MemProfilePath, "mem-profile-path", "", "Path to memory profile output file") | 	rootCmd.PersistentFlags().StringVar(&e.cfg.Run.MemProfilePath, "mem-profile-path", "", wh("Path to memory profile output file")) | ||||||
| 	rootCmd.PersistentFlags().IntVarP(&e.cfg.Run.Concurrency, "concurrency", "j", runtime.NumCPU(), "Concurrency (default NumCPU)") | 	rootCmd.PersistentFlags().IntVarP(&e.cfg.Run.Concurrency, "concurrency", "j", getDefaultConcurrency(), wh("Concurrency (default NumCPU)")) | ||||||
| 	rootCmd.PersistentFlags().BoolVar(&e.cfg.Run.PrintVersion, "version", false, "Print version") | 	if e.commit != "" { | ||||||
|  | 		rootCmd.PersistentFlags().BoolVar(&e.cfg.Run.PrintVersion, "version", false, wh("Print version")) | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| 	e.rootCmd = rootCmd | 	e.rootCmd = rootCmd | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | 	"github.com/fatih/color" | ||||||
| 	"github.com/golangci/golangci-lint/pkg/config" | 	"github.com/golangci/golangci-lint/pkg/config" | ||||||
| 	"github.com/golangci/golangci-lint/pkg/lint" | 	"github.com/golangci/golangci-lint/pkg/lint" | ||||||
| 	"github.com/golangci/golangci-lint/pkg/lint/lintersdb" | 	"github.com/golangci/golangci-lint/pkg/lint/lintersdb" | ||||||
| @ -29,92 +30,131 @@ const ( | |||||||
| 	exitCodeIfTimeout = 4 | 	exitCodeIfTimeout = 4 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | func getDefaultExcludeHelp() string { | ||||||
|  | 	parts := []string{"Use or not use default excludes:"} | ||||||
|  | 	for _, ep := range config.DefaultExcludePatterns { | ||||||
|  | 		parts = append(parts, fmt.Sprintf("  # %s: %s", ep.Linter, ep.Why)) | ||||||
|  | 		parts = append(parts, fmt.Sprintf("  - %s", color.YellowString(ep.Pattern))) | ||||||
|  | 		parts = append(parts, "") | ||||||
|  | 	} | ||||||
|  | 	return strings.Join(parts, "\n") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | const welcomeMessage = "Run this tool in cloud on every github pull request in https://golangci.com for free (public repos)" | ||||||
|  | 
 | ||||||
|  | func wh(text string) string { | ||||||
|  | 	return color.GreenString(text) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (e *Executor) initRun() { | func (e *Executor) initRun() { | ||||||
| 	var runCmd = &cobra.Command{ | 	var runCmd = &cobra.Command{ | ||||||
| 		Use:   "run", | 		Use:   "run", | ||||||
| 		Short: "Run linters", | 		Short: welcomeMessage, | ||||||
| 		Run:   e.executeRun, | 		Run:   e.executeRun, | ||||||
| 	} | 	} | ||||||
| 	e.rootCmd.AddCommand(runCmd) | 	e.rootCmd.AddCommand(runCmd) | ||||||
| 
 | 
 | ||||||
|  | 	runCmd.SetOutput(printers.StdOut) // use custom output to properly color it in Windows terminals | ||||||
|  | 	runCmd.Flags().SortFlags = false  // sort them as they are defined here | ||||||
|  | 
 | ||||||
|  | 	hideFlag := func(name string) { | ||||||
|  | 		if err := runCmd.Flags().MarkHidden(name); err != nil { | ||||||
|  | 			panic(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	// Output config | 	// Output config | ||||||
| 	oc := &e.cfg.Output | 	oc := &e.cfg.Output | ||||||
| 	runCmd.Flags().StringVar(&oc.Format, "out-format", | 	runCmd.Flags().StringVar(&oc.Format, "out-format", | ||||||
| 		config.OutFormatColoredLineNumber, | 		config.OutFormatColoredLineNumber, | ||||||
| 		fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|"))) | 		wh(fmt.Sprintf("Format of output: %s", strings.Join(config.OutFormats, "|")))) | ||||||
| 	runCmd.Flags().BoolVar(&oc.PrintIssuedLine, "print-issued-lines", true, "Print lines of code with issue") | 	runCmd.Flags().BoolVar(&oc.PrintIssuedLine, "print-issued-lines", true, wh("Print lines of code with issue")) | ||||||
| 	runCmd.Flags().BoolVar(&oc.PrintLinterName, "print-linter-name", true, "Print linter name in issue line") | 	runCmd.Flags().BoolVar(&oc.PrintLinterName, "print-linter-name", true, wh("Print linter name in issue line")) | ||||||
| 	runCmd.Flags().BoolVar(&oc.PrintWelcomeMessage, "print-welcome", false, "Print welcome message") | 	runCmd.Flags().BoolVar(&oc.PrintWelcomeMessage, "print-welcome", false, wh("Print welcome message")) | ||||||
|  | 	hideFlag("print-welcome") // no longer used | ||||||
| 
 | 
 | ||||||
| 	// Run config | 	// Run config | ||||||
| 	rc := &e.cfg.Run | 	rc := &e.cfg.Run | ||||||
| 	runCmd.Flags().IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code", | 	runCmd.Flags().IntVar(&rc.ExitCodeIfIssuesFound, "issues-exit-code", | ||||||
| 		1, "Exit code when issues were found") | 		1, wh("Exit code when issues were found")) | ||||||
| 	runCmd.Flags().StringSliceVar(&rc.BuildTags, "build-tags", []string{}, "Build tags (not all linters support them)") | 	runCmd.Flags().StringSliceVar(&rc.BuildTags, "build-tags", []string{}, wh("Build tags (not all linters support them)")) | ||||||
| 	runCmd.Flags().DurationVar(&rc.Deadline, "deadline", time.Minute, "Deadline for total work") | 	runCmd.Flags().DurationVar(&rc.Deadline, "deadline", time.Minute, wh("Deadline for total work")) | ||||||
| 	runCmd.Flags().BoolVar(&rc.AnalyzeTests, "tests", false, "Analyze tests (*_test.go)") | 	runCmd.Flags().BoolVar(&rc.AnalyzeTests, "tests", false, wh("Analyze tests (*_test.go)")) | ||||||
| 	runCmd.Flags().BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, "Print avg and max memory usage of golangci-lint and total time") | 	runCmd.Flags().BoolVar(&rc.PrintResourcesUsage, "print-resources-usage", false, wh("Print avg and max memory usage of golangci-lint and total time")) | ||||||
| 	runCmd.Flags().StringVarP(&rc.Config, "config", "c", "", "Read config from file path `PATH`") | 	runCmd.Flags().StringVarP(&rc.Config, "config", "c", "", wh("Read config from file path `PATH`")) | ||||||
| 	runCmd.Flags().BoolVar(&rc.NoConfig, "no-config", false, "Don't read config") | 	runCmd.Flags().BoolVar(&rc.NoConfig, "no-config", false, wh("Don't read config")) | ||||||
| 
 | 
 | ||||||
| 	// Linters settings config | 	// Linters settings config | ||||||
| 	lsc := &e.cfg.LintersSettings | 	lsc := &e.cfg.LintersSettings | ||||||
|  | 
 | ||||||
|  | 	// Hide all linters settings flags: they were initially visible, | ||||||
|  | 	// but when number of linters started to grow it became ovious that | ||||||
|  | 	// we can't fill 90% of flags by linters settings: common flags became hard to find. | ||||||
|  | 	// New linters settings should be done only through config file. | ||||||
| 	runCmd.Flags().BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results") | 	runCmd.Flags().BoolVar(&lsc.Errcheck.CheckTypeAssertions, "errcheck.check-type-assertions", false, "Errcheck: check for ignored type assertion results") | ||||||
|  | 	hideFlag("errcheck.check-type-assertions") | ||||||
|  | 
 | ||||||
| 	runCmd.Flags().BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()") | 	runCmd.Flags().BoolVar(&lsc.Errcheck.CheckAssignToBlank, "errcheck.check-blank", false, "Errcheck: check for errors assigned to blank identifier: _ = errFunc()") | ||||||
|  | 	hideFlag("errcheck.check-blank") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, "Govet: check for shadowed variables") | 	runCmd.Flags().BoolVar(&lsc.Govet.CheckShadowing, "govet.check-shadowing", false, "Govet: check for shadowed variables") | ||||||
|  | 	hideFlag("govet.check-shadowing") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it") | 	runCmd.Flags().Float64Var(&lsc.Golint.MinConfidence, "golint.min-confidence", 0.8, "Golint: minimum confidence of a problem to print it") | ||||||
|  | 	hideFlag("golint.min-confidence") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code") | 	runCmd.Flags().BoolVar(&lsc.Gofmt.Simplify, "gofmt.simplify", true, "Gofmt: simplify code") | ||||||
|  | 	hideFlag("gofmt.simplify") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().IntVar(&lsc.Gocyclo.MinComplexity, "gocyclo.min-complexity", | 	runCmd.Flags().IntVar(&lsc.Gocyclo.MinComplexity, "gocyclo.min-complexity", | ||||||
| 		30, "Minimal complexity of function to report it") | 		30, "Minimal complexity of function to report it") | ||||||
|  | 	hideFlag("gocyclo.min-complexity") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, "Maligned: print suggested more optimal struct fields ordering") | 	runCmd.Flags().BoolVar(&lsc.Maligned.SuggestNewOrder, "maligned.suggest-new", false, "Maligned: print suggested more optimal struct fields ordering") | ||||||
|  | 	hideFlag("maligned.suggest-new") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().IntVar(&lsc.Dupl.Threshold, "dupl.threshold", | 	runCmd.Flags().IntVar(&lsc.Dupl.Threshold, "dupl.threshold", | ||||||
| 		150, "Dupl: Minimal threshold to detect copy-paste") | 		150, "Dupl: Minimal threshold to detect copy-paste") | ||||||
|  | 	hideFlag("dupl.threshold") | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().IntVar(&lsc.Goconst.MinStringLen, "goconst.min-len", | 	runCmd.Flags().IntVar(&lsc.Goconst.MinStringLen, "goconst.min-len", | ||||||
| 		3, "Goconst: minimum constant string length") | 		3, "Goconst: minimum constant string length") | ||||||
|  | 	hideFlag("goconst.min-len") | ||||||
| 	runCmd.Flags().IntVar(&lsc.Goconst.MinOccurrencesCount, "goconst.min-occurrences", | 	runCmd.Flags().IntVar(&lsc.Goconst.MinOccurrencesCount, "goconst.min-occurrences", | ||||||
| 		3, "Goconst: minimum occurrences of constant string count to trigger issue") | 		3, "Goconst: minimum occurrences of constant string count to trigger issue") | ||||||
|  | 	hideFlag("goconst.min-occurrences") | ||||||
| 
 | 
 | ||||||
| 	// (@dixonwille) These flag is only used for testing purposes. | 	// (@dixonwille) These flag is only used for testing purposes. | ||||||
| 	runCmd.Flags().StringSliceVar(&lsc.Depguard.Packages, "depguard.packages", nil, | 	runCmd.Flags().StringSliceVar(&lsc.Depguard.Packages, "depguard.packages", nil, | ||||||
| 		"Depguard: packages to add to the list") | 		"Depguard: packages to add to the list") | ||||||
| 	if err := runCmd.Flags().MarkHidden("depguard.packages"); err != nil { | 	hideFlag("depguard.packages") | ||||||
| 		panic(err) //Considering The only time this is called is if name does not exist | 
 | ||||||
| 	} |  | ||||||
| 	runCmd.Flags().BoolVar(&lsc.Depguard.IncludeGoRoot, "depguard.include-go-root", false, | 	runCmd.Flags().BoolVar(&lsc.Depguard.IncludeGoRoot, "depguard.include-go-root", false, | ||||||
| 		"Depguard: check list against standard lib") | 		"Depguard: check list against standard lib") | ||||||
| 	if err := runCmd.Flags().MarkHidden("depguard.include-go-root"); err != nil { | 	hideFlag("depguard.include-go-root") | ||||||
| 		panic(err) //Considering The only time this is called is if name does not exist |  | ||||||
| 	} |  | ||||||
| 
 | 
 | ||||||
| 	// Linters config | 	// Linters config | ||||||
| 	lc := &e.cfg.Linters | 	lc := &e.cfg.Linters | ||||||
| 	runCmd.Flags().StringSliceVarP(&lc.Enable, "enable", "E", []string{}, "Enable specific linter") | 	runCmd.Flags().StringSliceVarP(&lc.Enable, "enable", "E", []string{}, wh("Enable specific linter")) | ||||||
| 	runCmd.Flags().StringSliceVarP(&lc.Disable, "disable", "D", []string{}, "Disable specific linter") | 	runCmd.Flags().StringSliceVarP(&lc.Disable, "disable", "D", []string{}, wh("Disable specific linter")) | ||||||
| 	runCmd.Flags().BoolVar(&lc.EnableAll, "enable-all", false, "Enable all linters") | 	runCmd.Flags().BoolVar(&lc.EnableAll, "enable-all", false, wh("Enable all linters")) | ||||||
| 	runCmd.Flags().BoolVar(&lc.DisableAll, "disable-all", false, "Disable all linters") | 	runCmd.Flags().BoolVar(&lc.DisableAll, "disable-all", false, wh("Disable all linters")) | ||||||
| 	runCmd.Flags().StringSliceVarP(&lc.Presets, "presets", "p", []string{}, | 	runCmd.Flags().StringSliceVarP(&lc.Presets, "presets", "p", []string{}, | ||||||
| 		fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|"))) | 		wh(fmt.Sprintf("Enable presets (%s) of linters. Run 'golangci-lint linters' to see them. This option implies option --disable-all", strings.Join(lintersdb.AllPresets(), "|")))) | ||||||
| 	runCmd.Flags().BoolVar(&lc.Fast, "fast", false, "Run only fast linters from enabled linters set") | 	runCmd.Flags().BoolVar(&lc.Fast, "fast", false, wh("Run only fast linters from enabled linters set")) | ||||||
| 
 | 
 | ||||||
| 	// Issues config | 	// Issues config | ||||||
| 	ic := &e.cfg.Issues | 	ic := &e.cfg.Issues | ||||||
| 	runCmd.Flags().StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", []string{}, "Exclude issue by regexp") | 	runCmd.Flags().StringSliceVarP(&ic.ExcludePatterns, "exclude", "e", []string{}, wh("Exclude issue by regexp")) | ||||||
| 	runCmd.Flags().BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, | 	runCmd.Flags().BoolVar(&ic.UseDefaultExcludes, "exclude-use-default", true, getDefaultExcludeHelp()) | ||||||
| 		fmt.Sprintf("Use or not use default excludes: (%s)", strings.Join(config.DefaultExcludePatterns, "|"))) |  | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, "Maximum issues count per one linter. Set to 0 to disable") | 	runCmd.Flags().IntVar(&ic.MaxIssuesPerLinter, "max-issues-per-linter", 50, wh("Maximum issues count per one linter. Set to 0 to disable")) | ||||||
| 	runCmd.Flags().IntVar(&ic.MaxSameIssues, "max-same-issues", 3, "Maximum count of issues with the same text. Set to 0 to disable") | 	runCmd.Flags().IntVar(&ic.MaxSameIssues, "max-same-issues", 3, wh("Maximum count of issues with the same text. Set to 0 to disable")) | ||||||
| 
 | 
 | ||||||
| 	runCmd.Flags().BoolVarP(&ic.Diff, "new", "n", false, "Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed") | 	runCmd.Flags().BoolVarP(&ic.Diff, "new", "n", false, | ||||||
| 	runCmd.Flags().StringVar(&ic.DiffFromRevision, "new-from-rev", "", "Show only new issues created after git revision `REV`") | 		wh("Show only new issues: if there are unstaged changes or untracked files, only those changes are analyzed, else only changes in HEAD~ are analyzed.\nIt's a super-useful option for integration of golangci-lint into existing large codebase.\nIt's not practical to fix all existing issues at the moment of integration: much better don't allow issues in new code")) | ||||||
| 	runCmd.Flags().StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", "Show only new issues created in git patch with file path `PATH`") | 	runCmd.Flags().StringVar(&ic.DiffFromRevision, "new-from-rev", "", wh("Show only new issues created after git revision `REV`")) | ||||||
|  | 	runCmd.Flags().StringVar(&ic.DiffPatchFilePath, "new-from-patch", "", wh("Show only new issues created in git patch with file path `PATH`")) | ||||||
| 
 | 
 | ||||||
| 	e.parseConfig(runCmd) | 	e.parseConfig(runCmd) | ||||||
| } | } | ||||||
| @ -134,7 +174,7 @@ func (e *Executor) runAnalysis(ctx context.Context, args []string) (<-chan resul | |||||||
| 
 | 
 | ||||||
| 	excludePatterns := e.cfg.Issues.ExcludePatterns | 	excludePatterns := e.cfg.Issues.ExcludePatterns | ||||||
| 	if e.cfg.Issues.UseDefaultExcludes { | 	if e.cfg.Issues.UseDefaultExcludes { | ||||||
| 		excludePatterns = append(excludePatterns, config.DefaultExcludePatterns...) | 		excludePatterns = append(excludePatterns, config.GetDefaultExcludePatternsStrings()...) | ||||||
| 	} | 	} | ||||||
| 	var excludeTotalPattern string | 	var excludeTotalPattern string | ||||||
| 	if len(excludePatterns) != 0 { | 	if len(excludePatterns) != 0 { | ||||||
| @ -207,9 +247,6 @@ func (e *Executor) runAndPrint(ctx context.Context, args []string) error { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (e *Executor) executeRun(cmd *cobra.Command, args []string) { | func (e *Executor) executeRun(cmd *cobra.Command, args []string) { | ||||||
| 	logrus.Infof("Concurrency: %d, machine cpus count: %d", |  | ||||||
| 		e.cfg.Run.Concurrency, runtime.NumCPU()) |  | ||||||
| 
 |  | ||||||
| 	needTrackResources := e.cfg.Run.IsVerbose || e.cfg.Run.PrintResourcesUsage | 	needTrackResources := e.cfg.Run.IsVerbose || e.cfg.Run.PrintResourcesUsage | ||||||
| 	trackResourcesEndCh := make(chan struct{}) | 	trackResourcesEndCh := make(chan struct{}) | ||||||
| 	defer func() { // XXX: this defer must be before ctx.cancel defer | 	defer func() { // XXX: this defer must be before ctx.cancel defer | ||||||
| @ -225,10 +262,6 @@ func (e *Executor) executeRun(cmd *cobra.Command, args []string) { | |||||||
| 		go watchResources(ctx, trackResourcesEndCh) | 		go watchResources(ctx, trackResourcesEndCh) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if e.cfg.Output.PrintWelcomeMessage { |  | ||||||
| 		fmt.Fprintln(printers.StdOut, "Run this tool in cloud on every github pull request in https://golangci.com for free (public repos)") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err := e.runAndPrint(ctx, args); err != nil { | 	if err := e.runAndPrint(ctx, args); err != nil { | ||||||
| 		logrus.Warnf("running error: %s", err) | 		logrus.Warnf("running error: %s", err) | ||||||
| 		if e.exitCode == 0 { | 		if e.exitCode == 0 { | ||||||
|  | |||||||
| @ -14,29 +14,72 @@ const ( | |||||||
| 
 | 
 | ||||||
| var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON} | var OutFormats = []string{OutFormatColoredLineNumber, OutFormatLineNumber, OutFormatJSON} | ||||||
| 
 | 
 | ||||||
| var DefaultExcludePatterns = []string{ | type ExcludePattern struct { | ||||||
| 	// errcheck | 	Pattern string | ||||||
| 	"Error return value of .((os\\.)?std(out|err)\\..*|.*Close|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked", | 	Linter  string | ||||||
|  | 	Why     string | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 	// golint | var DefaultExcludePatterns = []ExcludePattern{ | ||||||
| 	"should have comment", | 	{ | ||||||
| 	"comment on exported method", | 		Pattern: "Error return value of .((os\\.)?std(out|err)\\..*|.*Close|os\\.Remove(All)?|.*printf?|os\\.(Un)?Setenv). is not checked", | ||||||
| 	"func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this", | 		Linter:  "errcheck", | ||||||
|  | 		Why:     "Almost all programs ignore errors on these functions and in most cases it's ok", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "(should have comment|comment on exported method|should have a package comment)", | ||||||
|  | 		Linter:  "golint", | ||||||
|  | 		Why:     "Annoying issue about not having a comment. The rare codebase has such comments", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "func name will be used as test\\.Test.* by other packages, and that stutters; consider calling this", | ||||||
|  | 		Linter:  "golint", | ||||||
|  | 		Why:     "False positive when tests are defined in package 'test'", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "Use of unsafe calls should be audited", | ||||||
|  | 		Linter:  "gas", | ||||||
|  | 		Why:     "Too many false-positives on 'unsafe' usage", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "Subprocess launch(ed with variable|ing should be audited)", | ||||||
|  | 		Linter:  "gas", | ||||||
|  | 		Why:     "Too many false-positives for parametrized shell calls", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "G104", | ||||||
|  | 		Linter:  "gas", | ||||||
|  | 		Why:     "Duplicated errcheck checks", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "(Expect directory permissions to be 0750 or less|Expect file permissions to be 0600 or less)", | ||||||
|  | 		Linter:  "gas", | ||||||
|  | 		Why:     "Too many issues in popular repos", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "Potential file inclusion via variable", | ||||||
|  | 		Linter:  "gas", | ||||||
|  | 		Why:     "False positive is triggered by 'src, err := ioutil.ReadFile(filename)'", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "(possible misuse of unsafe.Pointer|should have signature)", | ||||||
|  | 		Linter:  "govet", | ||||||
|  | 		Why:     "Common false positives", | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		Pattern: "ineffective break statement. Did you mean to break out of the outer loop", | ||||||
|  | 		Linter:  "megacheck", | ||||||
|  | 		Why:     "Developers tend to write in C-style with an explicit 'break' in a 'switch', so it's ok to ignore", | ||||||
|  | 	}, | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| 	// gas | func GetDefaultExcludePatternsStrings() []string { | ||||||
| 	"G103:", // Use of unsafe calls should be audited | 	var ret []string | ||||||
| 	"G104:", // disable what errcheck does: it reports on Close etc | 	for _, p := range DefaultExcludePatterns { | ||||||
| 	"G204:", // Subprocess launching should be audited: too lot false positives | 		ret = append(ret, p.Pattern) | ||||||
| 	"G301:", // Expect directory permissions to be 0750 or less | 	} | ||||||
| 	"G302:", // Expect file permissions to be 0600 or less |  | ||||||
| 	"G304:", // Potential file inclusion via variable: `src, err := ioutil.ReadFile(filename)` |  | ||||||
| 
 | 
 | ||||||
| 	// govet | 	return ret | ||||||
| 	"possible misuse of unsafe.Pointer", |  | ||||||
| 	"should have signature", |  | ||||||
| 
 |  | ||||||
| 	// megacheck |  | ||||||
| 	"ineffective break statement. Did you mean to break out of the outer loop", // developers tend to write in C-style with break in switch |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Run struct { | type Run struct { | ||||||
|  | |||||||
| @ -59,6 +59,17 @@ func buildTemplateContext() (map[string]interface{}, error) { | |||||||
| 
 | 
 | ||||||
| 	lintersOutParts := bytes.Split(lintersOut, []byte("\n\n")) | 	lintersOutParts := bytes.Split(lintersOut, []byte("\n\n")) | ||||||
| 
 | 
 | ||||||
|  | 	helpCmd := exec.Command("golangci-lint", "run", "-h") | ||||||
|  | 	helpCmd.Env = append(helpCmd.Env, os.Environ()...) | ||||||
|  | 	helpCmd.Env = append(helpCmd.Env, "HELP_RUN=1") // make default concurrency stable: don't depend on machine CPU number | ||||||
|  | 	help, err := helpCmd.Output() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, fmt.Errorf("can't run help cmd: %s", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	helpLines := bytes.Split(help, []byte("\n")) | ||||||
|  | 	shortHelp := bytes.Join(helpLines[2:], []byte("\n")) | ||||||
|  | 
 | ||||||
| 	return map[string]interface{}{ | 	return map[string]interface{}{ | ||||||
| 		"GolangciYaml":                     string(golangciYaml), | 		"GolangciYaml":                     string(golangciYaml), | ||||||
| 		"LintersCommandOutputEnabledOnly":  string(lintersOutParts[0]), | 		"LintersCommandOutputEnabledOnly":  string(lintersOutParts[0]), | ||||||
| @ -66,6 +77,7 @@ func buildTemplateContext() (map[string]interface{}, error) { | |||||||
| 		"EnabledByDefaultLinters":          getLintersListMarkdown(true), | 		"EnabledByDefaultLinters":          getLintersListMarkdown(true), | ||||||
| 		"DisabledByDefaultLinters":         getLintersListMarkdown(false), | 		"DisabledByDefaultLinters":         getLintersListMarkdown(false), | ||||||
| 		"ThanksList":                       getThanksList(), | 		"ThanksList":                       getThanksList(), | ||||||
|  | 		"RunHelpText":                      string(shortHelp), | ||||||
| 	}, nil | 	}, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -74,7 +74,7 @@ func getGometalinterCommonArgs() []string { | |||||||
| 		"--vendor", | 		"--vendor", | ||||||
| 		"--cyclo-over=30", | 		"--cyclo-over=30", | ||||||
| 		"--dupl-threshold=150", | 		"--dupl-threshold=150", | ||||||
| 		"--exclude", fmt.Sprintf("(%s)", strings.Join(config.DefaultExcludePatterns, "|")), | 		"--exclude", fmt.Sprintf("(%s)", strings.Join(config.GetDefaultExcludePatternsStrings(), "|")), | ||||||
| 		"--disable-all", | 		"--disable-all", | ||||||
| 		"--enable=vet", | 		"--enable=vet", | ||||||
| 		"--enable=vetshadow", | 		"--enable=vetshadow", | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 golangci
						golangci