github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/README.md (about) 1 [![Build Status](https://travis-ci.org/mgechev/revive.svg?branch=master)](https://travis-ci.org/mgechev/revive) 2 3 # revive 4 5 Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. **`Revive` provides a framework for development of custom rules, and lets you define a strict preset for enhancing your development & code review processes**. 6 7 <p align="center"> 8 <img src="./assets/logo.png" alt="" width="300"> 9 <br> 10 Logo by <a href="https://github.com/hawkgs">Georgi Serev</a> 11 </p> 12 13 Here's how `revive` is different from `golint`: 14 15 - Allows to enable or disable rules using a configuration file. 16 - Allows to configure the linting rules with a TOML file. 17 - 2x faster running the same rules as golint. 18 - Provides functionality for disabling a specific rule or the entire linter for a file or a range of lines. 19 - `golint` allows this only for generated files. 20 - Optional type checking. Most rules in golint do not require type checking. If you disable them in the config file, revive will run over 6x faster than golint. 21 - Provides multiple formatters which let us customize the output. 22 - Allows to customize the return code for the entire linter or based on the failure of only some rules. 23 - _Everyone can extend it easily with custom rules or formatters._ 24 - `Revive` provides more rules compared to `golint`. 25 26 ## Who uses Revive 27 28 - [`tidb`](https://github.com/pingcap/tidb) - TiDB is a distributed HTAP database compatible with the MySQL protocol 29 - [`grafana`](https://github.com/grafana/grafana) - The tool for beautiful monitoring and metric analytics & dashboards for Graphite, InfluxDB & Prometheus & More 30 - [`etcd`](https://github.com/etcd-io/etcd) - Distributed reliable key-value store for the most critical data of a distributed system 31 - [`ferret`](https://github.com/MontFerret/ferret) - Declarative web scraping 32 - [`gopass`](https://github.com/gopasspw/gopass) - The slightly more awesome standard unix password manager for teams 33 - [`gitea`](https://github.com/go-gitea/gitea) - Git with a cup of tea, painless self-hosted git service 34 - [`excelize`](https://github.com/360EntSecGroup-Skylar/excelize) - Go library for reading and writing Microsoft Excelâ„¢ (XLSX) files 35 - [`aurora`](https://github.com/xuri/aurora) - aurora is a web-based Beanstalk queue server console written in Go 36 - [`soar`](https://github.com/XiaoMi/soar) - SQL Optimizer And Rewriter 37 - [`pyroscope`](https://github.com/pyroscope-io/pyroscope) - Continuous profiling platform 38 - [`gorush`](https://github.com/appleboy/gorush) - A push notification server written in Go (Golang)a 39 - [`dry`](https://github.com/moncho/dry) - dry - A Docker manager for the terminal. 40 - [`go-echarts`](https://github.com/chenjiandongx/go-echarts) - The adorable charts library for Golang 41 - [`reviewdog`](https://github.com/reviewdog/reviewdog) - Automated code review tool integrated with any code analysis tools regardless of programming language 42 - [`rudder-server`](https://github.com/rudderlabs/rudder-server) - Privacy and Security focused Segment-alternative, in Golang and React. 43 - [`sklearn`](https://github.com/pa-m/sklearn) - A partial port of scikit-learn written in Go. 44 - [`protoc-gen-doc`](https://github.com/pseudomuto/protoc-gen-doc) - Documentation generator plugin for Google Protocol Buffers. 45 - [`llvm`](https://github.com/llir/llvm) - Library for interacting with LLVM IR in pure Go. 46 - [`jenkins-library`](https://github.com/SAP/jenkins-library) - Jenkins shared library for Continuous Delivery pipelines by SAP. 47 - [`pd`](https://github.com/tikv/pd) - Placement driver for TiKV. 48 - [`shellhub`](https://github.com/shellhub-io/shellhub) - ShellHub enables teams to easily access any Linux device behind firewall and NAT. 49 - [`lorawan-stack`](https://github.com/TheThingsNetwork/lorawan-stack) - The Things Network Stack for LoRaWAN V3 50 - [`gin-jwt`](https://github.com/appleboy/gin-jwt) - This is a JWT middleware for Gin framework. 51 - [`gofight`](https://github.com/appleboy/gofight) - Testing API Handler written in Golang. 52 - [`Beaver`](https://github.com/Clivern/Beaver) - A Real Time Messaging Server. 53 - [`ggz`](https://github.com/go-ggz/ggz) - An URL shortener service written in Golang 54 - [`Codeac.io`](https://www.codeac.io?ref=revive) - Automated code review service integrates with GitHub, Bitbucket and GitLab (even self-hosted) and helps you fight technical debt. 55 56 *Open a PR to add your project*. 57 58 <p align="center"> 59 <img src="./assets/demo.svg" alt="" width="700"> 60 </p> 61 62 <!-- TOC --> 63 64 - [revive](#revive) 65 - [Usage](#usage) 66 - [Bazel](#bazel) 67 - [Text Editors](#text-editors) 68 - [Continuous Integration](#continuous-integration) 69 - [Linter Aggregators](#linter-aggregators) 70 - [golangci-lint](#golangci-lint) 71 - [Installation](#installation) 72 - [Command Line Flags](#command-line-flags) 73 - [Sample Invocations](#sample-invocations) 74 - [Comment Annotations](#comment-annotations) 75 - [Configuration](#configuration) 76 - [Default Configuration](#default-configuration) 77 - [Custom Configuration](#custom-configuration) 78 - [Recommended Configuration](#recommended-configuration) 79 - [Available Rules](#available-rules) 80 - [Configurable rules](#configurable-rules) 81 - [`var-naming`](#var-naming) 82 - [Available Formatters](#available-formatters) 83 - [Friendly](#friendly) 84 - [Stylish](#stylish) 85 - [Default](#default) 86 - [Plain](#plain) 87 - [Unix](#unix) 88 - [SARIF](#sarif) 89 - [Extensibility](#extensibility) 90 - [Custom Rule](#custom-rule) 91 - [Example](#example) 92 - [Custom Formatter](#custom-formatter) 93 - [Speed Comparison](#speed-comparison) 94 - [golint](#golint) 95 - [revive](#revive) 96 - [Overriding colorization detection](#overriding-colorization-detection) 97 - [Contributors](#contributors) 98 - [License](#license) 99 100 <!-- /TOC --> 101 102 ## Usage 103 104 Since the default behavior of `revive` is compatible with `golint`, without providing any additional flags, the only difference you'd notice is faster execution. 105 106 `revive` supports a `-config` flag whose value should correspond to a TOML file describing which rules to use for `revive`'s linting. If not provided, `revive` will try to use a global config file (assumed to be located at `$HOME/revive.toml`). Otherwise, if no configuration TOML file is found then `revive` uses a built-in set of default linting rules. 107 108 ### Bazel 109 110 If you want to use revive with Bazel, take a look at the [rules](https://github.com/atlassian/bazel-tools/tree/master/gorevive) that Atlassian maintains. 111 112 ### Text Editors 113 114 - Support for VSCode in [vscode-go](https://github.com/Microsoft/vscode-go/pull/1699). 115 - Support for GoLand via [File Watchers](https://dev.to/s0xzwasd/configure-revive-go-linter-in-goland-2ggl). 116 - Support for Atom via [linter-revive](https://github.com/morphy2k/linter-revive). 117 - Support for vim via [dense-analysis/ale](https://github.com/dense-analysis/ale). 118 119 ```vim 120 let g:ale_linters = { 121 \ 'go': ['revive'], 122 \} 123 ``` 124 125 ### GitHub Actions 126 127 - [Revive Action](https://github.com/marketplace/actions/revive-action) with annotation support 128 129 ### Continuous Integration 130 131 [Codeac.io](https://www.codeac.io?ref=revive) - Automated code review service integrates with GitHub, Bitbucket and GitLab (even self-hosted) and helps you fight technical debt. Check your [pull-requests](https://www.codeac.io/documentation/pull-requests.html?ref=revive) with [revive](https://www.codeac.io/documentation/revive-configuration.html?ref=revive) automatically. (free for open-source projects) 132 133 ### Linter aggregators 134 135 #### golangci-lint 136 To enable `revive` in `golangci-lint` you need to add `revive` to the list of enabled linters: 137 138 ```yaml 139 # golangci-lint configuration file 140 linters: 141 enable: 142 - revive 143 ``` 144 Then `revive` can be configured by adding an entry to the `linters-settings` section of the configuration, for example: 145 146 ```yaml 147 # golangci-lint configuration file 148 linters-settings: 149 revive: 150 ignore-generated-header: true 151 severity: warning 152 rules: 153 - name: atomic 154 - name: line-length-limit 155 severity: error 156 arguments: [80] 157 - name: unhandled-error 158 arguments : ["fmt.Printf", "myFunction"] 159 ``` 160 161 The above configuration enables three rules of `revive`: _atomic_, _line-length-limit_ and _unhandled-error_ and pass some arguments to the last two. 162 The [Configuration](#configuration) section of this document provides details on how to configure `revive`. Note that while `revive` configuration is in TOML, that of `golangci-lint` is in YAML. 163 164 Please notice that if no particular configuration is provided, `revive` will behave as `go-lint` does, i.e. all `go-lint` rules are enabled (the [Available Rules table](#available-rules) details what are the `go-lint` rules). When a configuration is provided, only rules in the configuration are enabled. 165 166 ### Installation 167 168 ```bash 169 go get -u github.com/mgechev/revive 170 ``` 171 172 ### Command Line Flags 173 174 `revive` accepts three command line parameters: 175 176 - `-config [PATH]` - path to config file in TOML format, defaults to `$HOME/revive.toml` if present. 177 - `-exclude [PATTERN]` - pattern for files/directories/packages to be excluded for linting. You can specify the files you want to exclude for linting either as package name (i.e. `github.com/mgechev/revive`), list them as individual files (i.e. `file.go`), directories (i.e. `./foo/...`), or any combination of the three. 178 - `-formatter [NAME]` - formatter to be used for the output. The currently available formatters are: 179 180 - `default` - will output the failures the same way that `golint` does. 181 - `json` - outputs the failures in JSON format. 182 - `ndjson` - outputs the failures as stream in newline delimited JSON (NDJSON) format. 183 - `friendly` - outputs the failures when found. Shows summary of all the failures. 184 - `stylish` - formats the failures in a table. Keep in mind that it doesn't stream the output so it might be perceived as slower compared to others. 185 - `checkstyle` - outputs the failures in XML format compatible with that of Java's [Checkstyle](https://checkstyle.org/). 186 187 ### Sample Invocations 188 189 ```shell 190 revive -config revive.toml -exclude file1.go -exclude file2.go -formatter friendly github.com/mgechev/revive package/... 191 ``` 192 193 - The command above will use the configuration from `revive.toml` 194 - `revive` will ignore `file1.go` and `file2.go` 195 - The output will be formatted with the `friendly` formatter 196 - The linter will analyze `github.com/mgechev/revive` and the files in `package` 197 198 ### Comment Directives 199 200 Using comments, you can disable the linter for the entire file or only range of lines: 201 202 ```go 203 //revive:disable 204 205 func Public() {} 206 //revive:enable 207 ``` 208 209 The snippet above, will disable `revive` between the `revive:disable` and `revive:enable` comments. If you skip `revive:enable`, the linter will be disabled for the rest of the file. 210 211 With `revive:disable-next-line` and `revive:disable-line` you can disable `revive` on a particular code line. 212 213 You can do the same on a rule level. In case you want to disable only a particular rule, you can use: 214 215 ```go 216 //revive:disable:unexported-return 217 func Public() private { 218 return private 219 } 220 //revive:enable:unexported-return 221 ``` 222 223 This way, `revive` will not warn you for that you're returning an object of an unexported type, from an exported function. 224 225 You can document why you disable the linter by adding a trailing text in the directive, for example 226 227 ```go 228 //revive:disable Until the code is stable 229 ``` 230 ```go 231 //revive:disable:cyclomatic High complexity score but easy to understand 232 ``` 233 234 You can also configure `revive` to enforce documenting linter disabling directives by adding 235 236 ```toml 237 [directive.specify-disable-reason] 238 ``` 239 240 in the configuration. You can set the severity (defaults to _warning_) of the violation of this directive 241 242 ```toml 243 [directive.specify-disable-reason] 244 severity = "error" 245 ``` 246 247 ### Configuration 248 249 `revive` can be configured with a TOML file. Here's a sample configuration with explanation for the individual properties: 250 251 ```toml 252 # When set to false, ignores files with "GENERATED" header, similar to golint 253 ignoreGeneratedHeader = true 254 255 # Sets the default severity to "warning" 256 severity = "warning" 257 258 # Sets the default failure confidence. This means that linting errors 259 # with less than 0.8 confidence will be ignored. 260 confidence = 0.8 261 262 # Sets the error code for failures with severity "error" 263 errorCode = 0 264 265 # Sets the error code for failures with severity "warning" 266 warningCode = 0 267 268 # Configuration of the `cyclomatic` rule. Here we specify that 269 # the rule should fail if it detects code with higher complexity than 10. 270 [rule.cyclomatic] 271 arguments = [10] 272 273 # Sets the severity of the `package-comments` rule to "error". 274 [rule.package-comments] 275 severity = "error" 276 ``` 277 278 By default `revive` will enable only the linting rules that are named in the configuration file. 279 For example, the previous configuration file makes `revive` to enable only _cyclomatic_ and _package-comments_ linting rules. 280 281 To enable all available rules you need to add: 282 283 ```toml 284 enableAllRules = true 285 ``` 286 287 This will enable all available rules no matter of what rules are named in the configuration file. 288 289 To disable a rule, you simply mark it as disabled in the configuration. 290 For example: 291 292 ```toml 293 [rule.line-length-limit] 294 Disabled = true 295 ``` 296 When enabling all rules you still need/can provide specific configurations for rules. 297 The following files is an example configuration were all rules are enabled, with exception to those that are explicitly disabled, and some rules are configured with particular arguments: 298 299 ```toml 300 severity = "warning" 301 confidence = 0.8 302 errorCode = 0 303 warningCode = 0 304 305 # Enable all available rules 306 enableAllRules = true 307 308 # Disabled rules 309 [rule.blank-imports] 310 Disabled = true 311 [rule.file-header] 312 Disabled = true 313 [rule.max-public-structs] 314 Disabled = true 315 [rule.line-length-limit] 316 Disabled = true 317 [rule.function-length] 318 Disabled = true 319 320 # Rule tunning 321 [rule.argument-limit] 322 Arguments = [5] 323 [rule.cyclomatic] 324 Arguments = [10] 325 [rule.cognitive-complexity] 326 Arguments = [7] 327 [rule.function-result-limit] 328 Arguments = [3] 329 ``` 330 331 ### Default Configuration 332 333 The default configuration of `revive` can be found at `defaults.toml`. This will enable all rules available in `golint` and use their default configuration (i.e. the way they are hardcoded in `golint`). 334 335 ```shell 336 revive -config defaults.toml github.com/mgechev/revive 337 ``` 338 339 This will use the configuration file `defaults.toml`, the `default` formatter, and will run linting over the `github.com/mgechev/revive` package. 340 341 ### Custom Configuration 342 343 ```shell 344 revive -config config.toml -formatter friendly github.com/mgechev/revive 345 ``` 346 347 This will use `config.toml`, the `friendly` formatter, and will run linting over the `github.com/mgechev/revive` package. 348 349 ### Recommended Configuration 350 351 The following snippet contains the recommended `revive` configuration that you can use in your project: 352 353 ```toml 354 ignoreGeneratedHeader = false 355 severity = "warning" 356 confidence = 0.8 357 errorCode = 0 358 warningCode = 0 359 360 [rule.blank-imports] 361 [rule.context-as-argument] 362 [rule.context-keys-type] 363 [rule.dot-imports] 364 [rule.error-return] 365 [rule.error-strings] 366 [rule.error-naming] 367 [rule.exported] 368 [rule.if-return] 369 [rule.increment-decrement] 370 [rule.var-naming] 371 [rule.var-declaration] 372 [rule.package-comments] 373 [rule.range] 374 [rule.receiver-naming] 375 [rule.time-naming] 376 [rule.unexported-return] 377 [rule.indent-error-flow] 378 [rule.errorf] 379 [rule.empty-block] 380 [rule.superfluous-else] 381 [rule.unused-parameter] 382 [rule.unreachable-code] 383 [rule.redefines-builtin-id] 384 ``` 385 386 ## Available Rules 387 388 List of all available rules. The rules ported from `golint` are left unchanged and indicated in the `golint` column. 389 390 | Name | Config | Description | `golint` | Typed | 391 | --------------------- | :----: | :--------------------------------------------------------------- | :------: | :---: | 392 | [`context-keys-type`](./RULES_DESCRIPTIONS.md#context-key-types) | n/a | Disallows the usage of basic types in `context.WithValue`. | yes | yes | 393 | [`time-naming`](./RULES_DESCRIPTIONS.md#time-naming) | n/a | Conventions around the naming of time variables. | yes | yes | 394 | [`var-declaration`](./RULES_DESCRIPTIONS.md#var-declaration) | n/a | Reduces redundancies around variable declaration. | yes | yes | 395 | [`unexported-return`](./RULES_DESCRIPTIONS.md#unexported-return) | n/a | Warns when a public return is from unexported type. | yes | yes | 396 | [`errorf`](./RULES_DESCRIPTIONS.md#errorf) | n/a | Should replace `errors.New(fmt.Sprintf())` with `fmt.Errorf()` | yes | yes | 397 | [`blank-imports`](./RULES_DESCRIPTIONS.md#blank-imports) | n/a | Disallows blank imports | yes | no | 398 | [`context-as-argument`](./RULES_DESCRIPTIONS.md#context-as-argument) | n/a | `context.Context` should be the first argument of a function. | yes | no | 399 | [`dot-imports`](./RULES_DESCRIPTIONS.md#dot-imports) | n/a | Forbids `.` imports. | yes | no | 400 | [`error-return`](./RULES_DESCRIPTIONS.md#error-return) | n/a | The error return parameter should be last. | yes | no | 401 | [`error-strings`](./RULES_DESCRIPTIONS.md#error-strings) | n/a | Conventions around error strings. | yes | no | 402 | [`error-naming`](./RULES_DESCRIPTIONS.md#error-naming) | n/a | Naming of error variables. | yes | no | 403 | [`exported`](./RULES_DESCRIPTIONS.md#exported) | n/a | Naming and commenting conventions on exported symbols. | yes | no | 404 | [`if-return`](./RULES_DESCRIPTIONS.md#if-return) | n/a | Redundant if when returning an error. | yes | no | 405 | [`increment-decrement`](./RULES_DESCRIPTIONS.md#increment-decrement) | n/a | Use `i++` and `i--` instead of `i += 1` and `i -= 1`. | yes | no | 406 | [`var-naming`](./RULES_DESCRIPTIONS.md#var-naming) | whitelist & blacklist of initialisms | Naming rules. | yes | no | 407 | [`package-comments`](./RULES_DESCRIPTIONS.md#package-comments) | n/a | Package commenting conventions. | yes | no | 408 | [`range`](./RULES_DESCRIPTIONS.md#range) | n/a | Prevents redundant variables when iterating over a collection. | yes | no | 409 | [`receiver-naming`](./RULES_DESCRIPTIONS.md#receiver-naming) | n/a | Conventions around the naming of receivers. | yes | no | 410 | [`indent-error-flow`](./RULES_DESCRIPTIONS.md#indent-error-flow) | n/a | Prevents redundant else statements. | yes | no | 411 | [`argument-limit`](./RULES_DESCRIPTIONS.md#argument-limit) | int | Specifies the maximum number of arguments a function can receive | no | no | 412 | [`cyclomatic`](./RULES_DESCRIPTIONS.md#cyclomatic) | int | Sets restriction for maximum Cyclomatic complexity. | no | no | 413 | [`max-public-structs`](./RULES_DESCRIPTIONS.md#max-public-structs) | int | The maximum number of public structs in a file. | no | no | 414 | [`file-header`](./RULES_DESCRIPTIONS.md#file-header) | string | Header which each file should have. | no | no | 415 | [`empty-block`](./RULES_DESCRIPTIONS.md#empty-block) | n/a | Warns on empty code blocks | no | yes | 416 | [`superfluous-else`](./RULES_DESCRIPTIONS.md#superfluous-else) | n/a | Prevents redundant else statements (extends [`indent-error-flow`](./RULES_DESCRIPTIONS.md#indent-error-flow)) | no | no | 417 | [`confusing-naming`](./RULES_DESCRIPTIONS.md#confusing-naming) | n/a | Warns on methods with names that differ only by capitalization | no | no | 418 | [`get-return`](./RULES_DESCRIPTIONS.md#get-return) | n/a | Warns on getters that do not yield any result | no | no | 419 | [`modifies-parameter`](./RULES_DESCRIPTIONS.md#modifies-parameter) | n/a | Warns on assignments to function parameters | no | no | 420 | [`confusing-results`](./RULES_DESCRIPTIONS.md#confusing-results) | n/a | Suggests to name potentially confusing function results | no | no | 421 | [`deep-exit`](./RULES_DESCRIPTIONS.md#deep-exit) | n/a | Looks for program exits in funcs other than `main()` or `init()` | no | no | 422 | [`unused-parameter`](./RULES_DESCRIPTIONS.md#unused-parameter) | n/a | Suggests to rename or remove unused function parameters | no | no | 423 | [`unreachable-code`](./RULES_DESCRIPTIONS.md#unreachable-code) | n/a | Warns on unreachable code | no | no | 424 | [`add-constant`](./RULES_DESCRIPTIONS.md#add-constant) | map | Suggests using constant for magic numbers and string literals | no | no | 425 | [`flag-parameter`](./RULES_DESCRIPTIONS.md#flag-parameter) | n/a | Warns on boolean parameters that create a control coupling | no | no | 426 | [`unnecessary-stmt`](./RULES_DESCRIPTIONS.md#unnecessary-stmt) | n/a | Suggests removing or simplifying unnecessary statements | no | no | 427 | [`struct-tag`](./RULES_DESCRIPTIONS.md#struct-tag) | n/a | Checks common struct tags like `json`,`xml`,`yaml` | no | no | 428 | [`modifies-value-receiver`](./RULES_DESCRIPTIONS.md#modifies-value-receiver) | n/a | Warns on assignments to value-passed method receivers | no | yes | 429 | [`constant-logical-expr`](./RULES_DESCRIPTIONS.md#constant-logical-expr) | n/a | Warns on constant logical expressions | no | no | 430 | [`bool-literal-in-expr`](./RULES_DESCRIPTIONS.md#bool-literal-in-expr)| n/a | Suggests removing Boolean literals from logic expressions | no | no | 431 | [`redefines-builtin-id`](./RULES_DESCRIPTIONS.md#redefines-builtin-id)| n/a | Warns on redefinitions of builtin identifiers | no | no | 432 | [`function-result-limit`](./RULES_DESCRIPTIONS.md#function-result-limit) | int | Specifies the maximum number of results a function can return | no | no | 433 | [`imports-blacklist`](./RULES_DESCRIPTIONS.md#imports-blacklist) | []string | Disallows importing the specified packages | no | no | 434 | [`range-val-in-closure`](./RULES_DESCRIPTIONS.md#range-val-in-closure)| n/a | Warns if range value is used in a closure dispatched as goroutine| no | no | 435 | [`range-val-address`](./RULES_DESCRIPTIONS.md#range-val-address)| n/a | Warns if address of range value is used dangerously | no | no | 436 | [`waitgroup-by-value`](./RULES_DESCRIPTIONS.md#waitgroup-by-value) | n/a | Warns on functions taking sync.WaitGroup as a by-value parameter | no | no | 437 | [`atomic`](./RULES_DESCRIPTIONS.md#atomic) | n/a | Check for common mistaken usages of the `sync/atomic` package | no | no | 438 | [`empty-lines`](./RULES_DESCRIPTIONS.md#empty-lines) | n/a | Warns when there are heading or trailing newlines in a block | no | no | 439 | [`line-length-limit`](./RULES_DESCRIPTIONS.md#line-length-limit) | int | Specifies the maximum number of characters in a line | no | no | 440 | [`call-to-gc`](./RULES_DESCRIPTIONS.md#call-to-gc) | n/a | Warns on explicit call to the garbage collector | no | no | 441 | [`duplicated-imports`](./RULES_DESCRIPTIONS.md#duplicated-imports) | n/a | Looks for packages that are imported two or more times | no | no | 442 | [`import-shadowing`](./RULES_DESCRIPTIONS.md#import-shadowing) | n/a | Spots identifiers that shadow an import | no | no | 443 | [`bare-return`](./RULES_DESCRIPTIONS.md#bare-return) | n/a | Warns on bare returns | no | no | 444 | [`unused-receiver`](./RULES_DESCRIPTIONS.md#unused-receiver) | n/a | Suggests to rename or remove unused method receivers | no | no | 445 | [`unhandled-error`](./RULES_DESCRIPTIONS.md#unhandled-error) | []string | Warns on unhandled errors returned by funcion calls | no | yes | 446 | [`cognitive-complexity`](./RULES_DESCRIPTIONS.md#cognitive-complexity) | int | Sets restriction for maximum Cognitive complexity. | no | no | 447 | [`string-of-int`](./RULES_DESCRIPTIONS.md#string-of-int) | n/a | Warns on suspicious casts from int to string | no | yes | 448 | [`string-format`](./RULES_DESCRIPTIONS.md#string-format) | map | Warns on specific string literals that fail one or more user-configured regular expressions | no | no | 449 | [`early-return`](./RULES_DESCRIPTIONS.md#early-return) | n/a | Spots if-then-else statements that can be refactored to simplify code reading | no | no | 450 | [`unconditional-recursion`](./RULES_DESCRIPTIONS.md#unconditional-recursion) | n/a | Warns on function calls that will lead to (direct) infinite recursion | no | no | 451 | [`identical-branches`](./RULES_DESCRIPTIONS.md#identical-branches) | n/a | Spots if-then-else statements with identical `then` and `else` branches | no | no | 452 | [`defer`](./RULES_DESCRIPTIONS.md#defer) | map | Warns on some [defer gotchas](https://blog.learngoprogramming.com/5-gotchas-of-defer-in-go-golang-part-iii-36a1ab3d6ef1) | no | no | 453 | [`unexported-naming`](./RULES_DESCRIPTIONS.md#unexported-naming) | n/a | Warns on wrongly named un-exported symbols | no | no | 454 | [`function-length`](./RULES_DESCRIPTIONS.md#function-length) | n/a | Warns on functions exceeding the statements or lines max | no | no | 455 | [`nested-structs`](./RULES_DESCRIPTIONS.md#nested-structs) | n/a | Warns on structs within structs | no | no | 456 457 ## Configurable rules 458 459 Here you can find how you can configure some of the existing rules: 460 461 ### `var-naming` 462 463 This rule accepts two slices of strings, a whitelist and a blacklist of initialisms. By default the rule behaves exactly as the alternative in `golint` but optionally, you can relax it (see [golint/lint/issues/89](https://github.com/golang/lint/issues/89)) 464 465 ```toml 466 [rule.var-naming] 467 arguments = [["ID"], ["VM"]] 468 ``` 469 470 This way, revive will not warn for identifier called `customId` but will warn that `customVm` should be called `customVM`. 471 472 ## Available Formatters 473 474 This section lists all the available formatters and provides a screenshot for each one. 475 476 ### Friendly 477 478 ![Friendly formatter](/assets/formatter-friendly.png) 479 480 ### Stylish 481 482 ![Stylish formatter](/assets/formatter-stylish.png) 483 484 ### Default 485 486 The default formatter produces the same output as `golint`. 487 488 ![Default formatter](/assets/formatter-default.png) 489 490 ### Plain 491 492 The plain formatter produces the same output as the default formatter and appends URL to the rule description. 493 494 ![Plain formatter](/assets/formatter-plain.png) 495 496 ### Unix 497 498 The unix formatter produces the same output as the default formatter but surrounds the rules in `[]`. 499 500 ![Unix formatter](/assets/formatter-unix.png) 501 502 ### SARIF 503 The `sarif` formatter produces outputs in SARIF, for _Static Analysis Results Interchange Format_, a standard JSON-based format for the output of static analysis tools defined and promoted by [OASIS](https://www.oasis-open.org/). 504 505 Current supported version of the standard is [SARIF-v2.1.0](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html 506 ). 507 508 ## Extensibility 509 510 The tool can be extended with custom rules or formatters. This section contains additional information on how to implement such. 511 512 **To extend the linter with a custom rule or a formatter you'll have to push it to this repository or fork it**. This is due to the limited `-buildmode=plugin` support which [works only on Linux (with known issues)](https://golang.org/pkg/plugin/). 513 514 ### Custom Rule 515 516 Each rule needs to implement the `lint.Rule` interface: 517 518 ```go 519 type Rule interface { 520 Name() string 521 Apply(*File, Arguments) []Failure 522 } 523 ``` 524 525 The `Arguments` type is an alias of the type `[]interface{}`. The arguments of the rule are passed from the configuration file. 526 527 #### Example 528 529 Let's suppose we have developed a rule called `BanStructNameRule` which disallow us to name a structure with given identifier. We can set the banned identifier by using the TOML configuration file: 530 531 ```toml 532 [rule.ban-struct-name] 533 arguments = ["Foo"] 534 ``` 535 536 With the snippet above we: 537 538 - Enable the rule with name `ban-struct-name`. The `Name()` method of our rule should return a string which matches `ban-struct-name`. 539 - Configure the rule with the argument `Foo`. The list of arguments will be passed to `Apply(*File, Arguments)` together with the target file we're linting currently. 540 541 A sample rule implementation can be found [here](/rule/argument-limit.go). 542 543 ### Custom Formatter 544 545 Each formatter needs to implement the following interface: 546 547 ```go 548 type Formatter interface { 549 Format(<-chan Failure, Config) (string, error) 550 Name() string 551 } 552 ``` 553 554 The `Format` method accepts a channel of `Failure` instances and the configuration of the enabled rules. The `Name()` method should return a string different from the names of the already existing rules. This string is used when specifying the formatter when invoking the `revive` CLI tool. 555 556 For a sample formatter, take a look at [this file](/formatter/json.go). 557 558 ## Speed Comparison 559 560 Compared to `golint`, `revive` performs better because it lints the files for each individual rule into a separate goroutine. Here's a basic performance benchmark on MacBook Pro Early 2013 run on kubernetes: 561 562 ### golint 563 564 ```shell 565 time golint kubernetes/... > /dev/null 566 567 real 0m54.837s 568 user 0m57.844s 569 sys 0m9.146s 570 ``` 571 572 ### revive 573 574 ```shell 575 # no type checking 576 time revive -config untyped.toml kubernetes/... > /dev/null 577 578 real 0m8.471s 579 user 0m40.721s 580 sys 0m3.262s 581 ``` 582 583 Keep in mind that if you use rules which require type checking, the performance may drop to 2x faster than `golint`: 584 585 ```shell 586 # type checking enabled 587 time revive kubernetes/... > /dev/null 588 589 real 0m26.211s 590 user 2m6.708s 591 sys 0m17.192s 592 ``` 593 594 Currently, type checking is enabled by default. If you want to run the linter without type checking, remove all typed rules from the configuration file. 595 596 ## Overriding colorization detection 597 598 By default, `revive` determines whether or not to colorize its output based on whether it's connected to a TTY or not. 599 This works for most use cases, but may not behave as expected if you use `revive` in a pipeline of commands, 600 where STDOUT is being piped to another command. 601 602 To force colorization, add `REVIVE_FORCE_COLOR=1` to the environment you're running in. For example: 603 604 ```shell 605 REVIVE_FORCE_COLOR=1 revive -formatter friendly ./... | tee revive.log 606 ``` 607 608 ## Contributors 609 610 [<img alt="mgechev" src="https://avatars.githubusercontent.com/u/455023?v=4&s=117" width="117">](https://github.com/mgechev) |[<img alt="chavacava" src="https://avatars.githubusercontent.com/u/25788468?v=4&s=117" width="117">](https://github.com/chavacava) |[<img alt="renovate-bot" src="https://avatars.githubusercontent.com/u/25180681?v=4&s=117" width="117">](https://github.com/renovate-bot) |[<img alt="xuri" src="https://avatars.githubusercontent.com/u/2809468?v=4&s=117" width="117">](https://github.com/xuri) |[<img alt="morphy2k" src="https://avatars.githubusercontent.com/u/4280578?v=4&s=117" width="117">](https://github.com/morphy2k) |[<img alt="dshemin" src="https://avatars.githubusercontent.com/u/11780307?v=4&s=117" width="117">](https://github.com/dshemin) | 611 :---: |:---: |:---: |:---: |:---: |:---: | 612 [mgechev](https://github.com/mgechev) |[chavacava](https://github.com/chavacava) |[renovate-bot](https://github.com/renovate-bot) |[xuri](https://github.com/xuri) |[morphy2k](https://github.com/morphy2k) |[dshemin](https://github.com/dshemin) | 613 614 [<img alt="Clivern" src="https://avatars.githubusercontent.com/u/1634427?v=4&s=117" width="117">](https://github.com/Clivern) |[<img alt="gsamokovarov" src="https://avatars.githubusercontent.com/u/604618?v=4&s=117" width="117">](https://github.com/gsamokovarov) |[<img alt="tymonx" src="https://avatars.githubusercontent.com/u/8367378?v=4&s=117" width="117">](https://github.com/tymonx) |[<img alt="bernhardreisenberger" src="https://avatars.githubusercontent.com/u/5809300?v=4&s=117" width="117">](https://github.com/bernhardreisenberger) |[<img alt="markelog" src="https://avatars.githubusercontent.com/u/945528?v=4&s=117" width="117">](https://github.com/markelog) |[<img alt="tamird" src="https://avatars.githubusercontent.com/u/1535036?v=4&s=117" width="117">](https://github.com/tamird) | 615 :---: |:---: |:---: |:---: |:---: |:---: | 616 [Clivern](https://github.com/Clivern) |[gsamokovarov](https://github.com/gsamokovarov) |[tymonx](https://github.com/tymonx) |[bernhardreisenberger](https://github.com/bernhardreisenberger) |[markelog](https://github.com/markelog) |[tamird](https://github.com/tamird) | 617 618 [<img alt="mapreal19" src="https://avatars.githubusercontent.com/u/3055997?v=4&s=117" width="117">](https://github.com/mapreal19) |[<img alt="Aragur" src="https://avatars.githubusercontent.com/u/11004008?v=4&s=117" width="117">](https://github.com/Aragur) |[<img alt="s0xzwasd" src="https://avatars.githubusercontent.com/u/29286703?v=4&s=117" width="117">](https://github.com/s0xzwasd) |[<img alt="yangdiangzb" src="https://avatars.githubusercontent.com/u/16643665?v=4&s=117" width="117">](https://github.com/yangdiangzb) |[<img alt="petethepig" src="https://avatars.githubusercontent.com/u/662636?v=4&s=117" width="117">](https://github.com/petethepig) |[<img alt="quasilyte" src="https://avatars.githubusercontent.com/u/6286655?v=4&s=117" width="117">](https://github.com/quasilyte) | 619 :---: |:---: |:---: |:---: |:---: |:---: | 620 [mapreal19](https://github.com/mapreal19) |[Aragur](https://github.com/Aragur) |[s0xzwasd](https://github.com/s0xzwasd) |[yangdiangzb](https://github.com/yangdiangzb) |[petethepig](https://github.com/petethepig) |[quasilyte](https://github.com/quasilyte) | 621 622 [<img alt="grongor" src="https://avatars.githubusercontent.com/u/972493?v=4&s=117" width="117">](https://github.com/grongor) |[<img alt="jamesmaidment" src="https://avatars.githubusercontent.com/u/2050324?v=4&s=117" width="117">](https://github.com/jamesmaidment) |[<img alt="johnrichardrinehart" src="https://avatars.githubusercontent.com/u/6321578?v=4&s=117" width="117">](https://github.com/johnrichardrinehart) |[<img alt="very-amused" src="https://avatars.githubusercontent.com/u/44382255?v=4&s=117" width="117">](https://github.com/very-amused) |[<img alt="mathieu-aubin" src="https://avatars.githubusercontent.com/u/15820228?v=4&s=117" width="117">](https://github.com/mathieu-aubin) |[<img alt="michalhisim" src="https://avatars.githubusercontent.com/u/764249?v=4&s=117" width="117">](https://github.com/michalhisim) | 623 :---: |:---: |:---: |:---: |:---: |:---: | 624 [grongor](https://github.com/grongor) |[jamesmaidment](https://github.com/jamesmaidment) |[johnrichardrinehart](https://github.com/johnrichardrinehart) |[very-amused](https://github.com/very-amused) |[mathieu-aubin](https://github.com/mathieu-aubin) |[michalhisim](https://github.com/michalhisim) | 625 626 [<img alt="pa-m" src="https://avatars.githubusercontent.com/u/5503106?v=4&s=117" width="117">](https://github.com/pa-m) |[<img alt="paul-at-start" src="https://avatars.githubusercontent.com/u/5486775?v=4&s=117" width="117">](https://github.com/paul-at-start) |[<img alt="paco0x" src="https://avatars.githubusercontent.com/u/6123425?v=4&s=117" width="117">](https://github.com/paco0x) |[<img alt="ridvansumset" src="https://avatars.githubusercontent.com/u/26631560?v=4&s=117" width="117">](https://github.com/ridvansumset) |[<img alt="Jarema" src="https://avatars.githubusercontent.com/u/7369771?v=4&s=117" width="117">](https://github.com/Jarema) |[<img alt="vkrol" src="https://avatars.githubusercontent.com/u/153412?v=4&s=117" width="117">](https://github.com/vkrol) | 627 :---: |:---: |:---: |:---: |:---: |:---: | 628 [pa-m](https://github.com/pa-m) |[paul-at-start](https://github.com/paul-at-start) |[paco0x](https://github.com/paco0x) |[ridvansumset](https://github.com/ridvansumset) |[Jarema](https://github.com/Jarema) |[vkrol](https://github.com/vkrol) | 629 630 [<img alt="haya14busa" src="https://avatars.githubusercontent.com/u/3797062?v=4&s=117" width="117">](https://github.com/haya14busa) |[<img alt="sina-devel" src="https://avatars.githubusercontent.com/u/61763643?v=4&s=117" width="117">](https://github.com/sina-devel) |[<img alt="techknowlogick" src="https://avatars.githubusercontent.com/u/164197?v=4&s=117" width="117">](https://github.com/techknowlogick) | 631 :---: |:---: |:---: | 632 [haya14busa](https://github.com/haya14busa) |[sina-devel](https://github.com/sina-devel) |[techknowlogick](https://github.com/techknowlogick) | 633 634 ## License 635 636 MIT