github.com/songshiyun/revive@v1.1.5-0.20220323112655-f8433a19b3c5/README.md (about) 1 [![Build Status](https://travis-ci.org/songshiyun/revive.svg?branch=master)](https://travis-ci.org/songshiyun/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 - [`cadence`](https://github.com/uber/cadence) - Cadence is a distributed, scalable, durable, and highly available orchestration engine by Uber to execute asynchronous long-running business logic in a scalable and resilient way 32 - [`ferret`](https://github.com/MontFerret/ferret) - Declarative web scraping 33 - [`gopass`](https://github.com/gopasspw/gopass) - The slightly more awesome standard unix password manager for teams 34 - [`gitea`](https://github.com/go-gitea/gitea) - Git with a cup of tea, painless self-hosted git service 35 - [`excelize`](https://github.com/360EntSecGroup-Skylar/excelize) - Go library for reading and writing Microsoft Excelâ„¢ (XLSX) files 36 - [`aurora`](https://github.com/xuri/aurora) - aurora is a web-based Beanstalk queue server console written in Go 37 - [`soar`](https://github.com/XiaoMi/soar) - SQL Optimizer And Rewriter 38 - [`pyroscope`](https://github.com/pyroscope-io/pyroscope) - Continuous profiling platform 39 - [`gorush`](https://github.com/appleboy/gorush) - A push notification server written in Go (Golang). 40 - [`dry`](https://github.com/moncho/dry) - dry - A Docker manager for the terminal. 41 - [`go-echarts`](https://github.com/chenjiandongx/go-echarts) - The adorable charts library for Golang 42 - [`reviewdog`](https://github.com/reviewdog/reviewdog) - Automated code review tool integrated with any code analysis tools regardless of programming language 43 - [`rudder-server`](https://github.com/rudderlabs/rudder-server) - Privacy and Security focused Segment-alternative, in Golang and React. 44 - [`sklearn`](https://github.com/pa-m/sklearn) - A partial port of scikit-learn written in Go. 45 - [`protoc-gen-doc`](https://github.com/pseudomuto/protoc-gen-doc) - Documentation generator plugin for Google Protocol Buffers. 46 - [`llvm`](https://github.com/llir/llvm) - Library for interacting with LLVM IR in pure Go. 47 - [`jenkins-library`](https://github.com/SAP/jenkins-library) - Jenkins shared library for Continuous Delivery pipelines by SAP. 48 - [`pd`](https://github.com/tikv/pd) - Placement driver for TiKV. 49 - [`shellhub`](https://github.com/shellhub-io/shellhub) - ShellHub enables teams to easily access any Linux device behind firewall and NAT. 50 - [`lorawan-stack`](https://github.com/TheThingsNetwork/lorawan-stack) - The Things Network Stack for LoRaWAN V3 51 - [`gin-jwt`](https://github.com/appleboy/gin-jwt) - This is a JWT middleware for Gin framework. 52 - [`gofight`](https://github.com/appleboy/gofight) - Testing API Handler written in Golang. 53 - [`Beaver`](https://github.com/Clivern/Beaver) - A Real Time Messaging Server. 54 - [`ggz`](https://github.com/go-ggz/ggz) - An URL shortener service written in Golang 55 - [`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. 56 57 *Open a PR to add your project*. 58 59 <p align="center"> 60 <img src="./assets/demo.svg" alt="" width="700"> 61 </p> 62 63 <!-- TOC --> 64 65 - [revive](#revive) 66 - [Installation](#installation) 67 - [Usage](#usage) 68 - [Bazel](#bazel) 69 - [Text Editors](#text-editors) 70 - [Continuous Integration](#continuous-integration) 71 - [Linter Aggregators](#linter-aggregators) 72 - [golangci-lint](#golangci-lint) 73 - [Command Line Flags](#command-line-flags) 74 - [Sample Invocations](#sample-invocations) 75 - [Comment Annotations](#comment-annotations) 76 - [Configuration](#configuration) 77 - [Default Configuration](#default-configuration) 78 - [Custom Configuration](#custom-configuration) 79 - [Recommended Configuration](#recommended-configuration) 80 - [Available Rules](#available-rules) 81 - [Configurable rules](#configurable-rules) 82 - [`var-naming`](#var-naming) 83 - [Available Formatters](#available-formatters) 84 - [Friendly](#friendly) 85 - [Stylish](#stylish) 86 - [Default](#default) 87 - [Plain](#plain) 88 - [Unix](#unix) 89 - [SARIF](#sarif) 90 - [Extensibility](#extensibility) 91 - [Custom Rule](#custom-rule) 92 - [Example](#example) 93 - [Custom Formatter](#custom-formatter) 94 - [Speed Comparison](#speed-comparison) 95 - [golint](#golint) 96 - [revive](#revive) 97 - [Overriding colorization detection](#overriding-colorization-detection) 98 - [Contributors](#contributors) 99 - [License](#license) 100 101 <!-- /TOC --> 102 103 ## Installation 104 105 ```bash 106 go install github.com/songshiyun/revive@latest 107 ``` 108 109 or get a released executable from the [Releases](https://github.com/songshiyun/revive/releases) page. 110 111 You can install the main branch (including the last commit) with: 112 ```bash 113 go install github.com/songshiyun/revive@master 114 ``` 115 116 ## Usage 117 118 Since the default behavior of `revive` is compatible with `golint`, without providing any additional flags, the only difference you'd notice is faster execution. 119 120 `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. 121 122 ### Docker 123 A volume needs to be mounted to share the current repository with the container. 124 Please refer to the [bind mounts Docker documentation](https://docs.docker.com/storage/bind-mounts/) 125 126 ```bash 127 docker run -v "$(pwd)":/var/<repository> ghcr.io/songshiyun/revive:v1.1.2-next -config /var/<repository>/revive.toml -formatter stylish ./var/kidle/... 128 ``` 129 130 - `-v` is for the volume 131 - `ghcr.io/songshiyun/revive:v1.1.2-next ` is the image name and its version corresponding to `revive` command 132 - The provided flags are the same as the binary usage. 133 134 ### Bazel 135 136 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. 137 138 ### Text Editors 139 140 - Support for VSCode in [vscode-go](https://github.com/Microsoft/vscode-go/pull/1699). 141 - Support for GoLand via [File Watchers](https://dev.to/s0xzwasd/configure-revive-go-linter-in-goland-2ggl). 142 - Support for Atom via [linter-revive](https://github.com/morphy2k/linter-revive). 143 - Support for vim via [dense-analysis/ale](https://github.com/dense-analysis/ale). 144 145 ```vim 146 let g:ale_linters = { 147 \ 'go': ['revive'], 148 \} 149 ``` 150 151 ### GitHub Actions 152 153 - [Revive Action](https://github.com/marketplace/actions/revive-action) with annotation support 154 155 ### Continuous Integration 156 157 [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) 158 159 ### Linter aggregators 160 161 #### golangci-lint 162 To enable `revive` in `golangci-lint` you need to add `revive` to the list of enabled linters: 163 164 ```yaml 165 # golangci-lint configuration file 166 linters: 167 enable: 168 - revive 169 ``` 170 Then `revive` can be configured by adding an entry to the `linters-settings` section of the configuration, for example: 171 172 ```yaml 173 # golangci-lint configuration file 174 linters-settings: 175 revive: 176 ignore-generated-header: true 177 severity: warning 178 rules: 179 - name: atomic 180 - name: line-length-limit 181 severity: error 182 arguments: [80] 183 - name: unhandled-error 184 arguments : ["fmt.Printf", "myFunction"] 185 ``` 186 187 The above configuration enables three rules of `revive`: _atomic_, _line-length-limit_ and _unhandled-error_ and pass some arguments to the last two. 188 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. 189 190 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. 191 192 ### Command Line Flags 193 194 `revive` accepts the following command line parameters: 195 196 - `-config [PATH]` - path to config file in TOML format, defaults to `$HOME/revive.toml` if present. 197 - `-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/songshiyun/revive`), list them as individual files (i.e. `file.go`), directories (i.e. `./foo/...`), or any combination of the three. 198 - `-formatter [NAME]` - formatter to be used for the output. The currently available formatters are: 199 200 - `default` - will output the failures the same way that `golint` does. 201 - `json` - outputs the failures in JSON format. 202 - `ndjson` - outputs the failures as stream in newline delimited JSON (NDJSON) format. 203 - `friendly` - outputs the failures when found. Shows summary of all the failures. 204 - `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. 205 - `checkstyle` - outputs the failures in XML format compatible with that of Java's [Checkstyle](https://checkstyle.org/). 206 - `-max_open_files` - maximum number of open files at the same time. Defaults to unlimited. 207 - `-set_exit_status` - set exit status to 1 if any issues are found, overwrites `errorCode` and `warningCode` in config. 208 - `-version` - get revive version. 209 210 211 ### Sample Invocations 212 213 ```shell 214 revive -config revive.toml -exclude file1.go -exclude file2.go -formatter friendly github.com/songshiyun/revive package/... 215 ``` 216 217 - The command above will use the configuration from `revive.toml` 218 - `revive` will ignore `file1.go` and `file2.go` 219 - The output will be formatted with the `friendly` formatter 220 - The linter will analyze `github.com/songshiyun/revive` and the files in `package` 221 222 ### Comment Directives 223 224 Using comments, you can disable the linter for the entire file or only range of lines: 225 226 ```go 227 //revive:disable 228 229 func Public() {} 230 //revive:enable 231 ``` 232 233 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. 234 235 With `revive:disable-next-line` and `revive:disable-line` you can disable `revive` on a particular code line. 236 237 You can do the same on a rule level. In case you want to disable only a particular rule, you can use: 238 239 ```go 240 //revive:disable:unexported-return 241 func Public() private { 242 return private 243 } 244 //revive:enable:unexported-return 245 ``` 246 247 This way, `revive` will not warn you for that you're returning an object of an unexported type, from an exported function. 248 249 You can document why you disable the linter by adding a trailing text in the directive, for example 250 251 ```go 252 //revive:disable Until the code is stable 253 ``` 254 ```go 255 //revive:disable:cyclomatic High complexity score but easy to understand 256 ``` 257 258 You can also configure `revive` to enforce documenting linter disabling directives by adding 259 260 ```toml 261 [directive.specify-disable-reason] 262 ``` 263 264 in the configuration. You can set the severity (defaults to _warning_) of the violation of this directive 265 266 ```toml 267 [directive.specify-disable-reason] 268 severity = "error" 269 ``` 270 271 ### Configuration 272 273 `revive` can be configured with a TOML file. Here's a sample configuration with explanation for the individual properties: 274 275 ```toml 276 # When set to false, ignores files with "GENERATED" header, similar to golint 277 ignoreGeneratedHeader = true 278 279 # Sets the default severity to "warning" 280 severity = "warning" 281 282 # Sets the default failure confidence. This means that linting errors 283 # with less than 0.8 confidence will be ignored. 284 confidence = 0.8 285 286 # Sets the error code for failures with severity "error" 287 errorCode = 0 288 289 # Sets the error code for failures with severity "warning" 290 warningCode = 0 291 292 # Configuration of the `cyclomatic` rule. Here we specify that 293 # the rule should fail if it detects code with higher complexity than 10. 294 [rule.cyclomatic] 295 arguments = [10] 296 297 # Sets the severity of the `package-comments` rule to "error". 298 [rule.package-comments] 299 severity = "error" 300 ``` 301 302 By default `revive` will enable only the linting rules that are named in the configuration file. 303 For example, the previous configuration file makes `revive` to enable only _cyclomatic_ and _package-comments_ linting rules. 304 305 To enable all available rules you need to add: 306 307 ```toml 308 enableAllRules = true 309 ``` 310 311 This will enable all available rules no matter of what rules are named in the configuration file. 312 313 To disable a rule, you simply mark it as disabled in the configuration. 314 For example: 315 316 ```toml 317 [rule.line-length-limit] 318 Disabled = true 319 ``` 320 When enabling all rules you still need/can provide specific configurations for rules. 321 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: 322 323 ```toml 324 severity = "warning" 325 confidence = 0.8 326 errorCode = 0 327 warningCode = 0 328 329 # Enable all available rules 330 enableAllRules = true 331 332 # Disabled rules 333 [rule.blank-imports] 334 Disabled = true 335 [rule.file-header] 336 Disabled = true 337 [rule.max-public-structs] 338 Disabled = true 339 [rule.line-length-limit] 340 Disabled = true 341 [rule.function-length] 342 Disabled = true 343 344 # Rule tuning 345 [rule.argument-limit] 346 Arguments = [5] 347 [rule.cyclomatic] 348 Arguments = [10] 349 [rule.cognitive-complexity] 350 Arguments = [7] 351 [rule.function-result-limit] 352 Arguments = [3] 353 ``` 354 355 ### Default Configuration 356 357 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`). 358 359 ```shell 360 revive -config defaults.toml github.com/songshiyun/revive 361 ``` 362 363 This will use the configuration file `defaults.toml`, the `default` formatter, and will run linting over the `github.com/songshiyun/revive` package. 364 365 ### Custom Configuration 366 367 ```shell 368 revive -config config.toml -formatter friendly github.com/songshiyun/revive 369 ``` 370 371 This will use `config.toml`, the `friendly` formatter, and will run linting over the `github.com/songshiyun/revive` package. 372 373 ### Recommended Configuration 374 375 The following snippet contains the recommended `revive` configuration that you can use in your project: 376 377 ```toml 378 ignoreGeneratedHeader = false 379 severity = "warning" 380 confidence = 0.8 381 errorCode = 0 382 warningCode = 0 383 384 [rule.blank-imports] 385 [rule.context-as-argument] 386 [rule.context-keys-type] 387 [rule.dot-imports] 388 [rule.error-return] 389 [rule.error-strings] 390 [rule.error-naming] 391 [rule.exported] 392 [rule.if-return] 393 [rule.increment-decrement] 394 [rule.var-naming] 395 [rule.var-declaration] 396 [rule.package-comments] 397 [rule.range] 398 [rule.receiver-naming] 399 [rule.time-naming] 400 [rule.unexported-return] 401 [rule.indent-error-flow] 402 [rule.errorf] 403 [rule.empty-block] 404 [rule.superfluous-else] 405 [rule.unused-parameter] 406 [rule.unreachable-code] 407 [rule.redefines-builtin-id] 408 ``` 409 410 ## Available Rules 411 412 List of all available rules. The rules ported from `golint` are left unchanged and indicated in the `golint` column. 413 414 | Name | Config | Description | `golint` | Typed | 415 | --------------------- | :----: | :--------------------------------------------------------------- | :------: | :---: | 416 | [`context-keys-type`](./RULES_DESCRIPTIONS.md#context-key-types) | n/a | Disallows the usage of basic types in `context.WithValue`. | yes | yes | 417 | [`time-equal`](./RULES_DESCRIPTIONS.md#time-equal) | n/a | Suggests to use `time.Time.Equal` instead of `==` and `!=` for equality check time. | no | yes | 418 | [`time-naming`](./RULES_DESCRIPTIONS.md#time-naming) | n/a | Conventions around the naming of time variables. | yes | yes | 419 | [`var-declaration`](./RULES_DESCRIPTIONS.md#var-declaration) | n/a | Reduces redundancies around variable declaration. | yes | yes | 420 | [`unexported-return`](./RULES_DESCRIPTIONS.md#unexported-return) | n/a | Warns when a public return is from unexported type. | yes | yes | 421 | [`errorf`](./RULES_DESCRIPTIONS.md#errorf) | n/a | Should replace `errors.New(fmt.Sprintf())` with `fmt.Errorf()` | yes | yes | 422 | [`blank-imports`](./RULES_DESCRIPTIONS.md#blank-imports) | n/a | Disallows blank imports | yes | no | 423 | [`context-as-argument`](./RULES_DESCRIPTIONS.md#context-as-argument) | n/a | `context.Context` should be the first argument of a function. | yes | no | 424 | [`dot-imports`](./RULES_DESCRIPTIONS.md#dot-imports) | n/a | Forbids `.` imports. | yes | no | 425 | [`error-return`](./RULES_DESCRIPTIONS.md#error-return) | n/a | The error return parameter should be last. | yes | no | 426 | [`error-strings`](./RULES_DESCRIPTIONS.md#error-strings) | n/a | Conventions around error strings. | yes | no | 427 | [`error-naming`](./RULES_DESCRIPTIONS.md#error-naming) | n/a | Naming of error variables. | yes | no | 428 | [`exported`](./RULES_DESCRIPTIONS.md#exported) | []string | Naming and commenting conventions on exported symbols. | yes | no | 429 | [`if-return`](./RULES_DESCRIPTIONS.md#if-return) | n/a | Redundant if when returning an error. | no | no | 430 | [`increment-decrement`](./RULES_DESCRIPTIONS.md#increment-decrement) | n/a | Use `i++` and `i--` instead of `i += 1` and `i -= 1`. | yes | no | 431 | [`var-naming`](./RULES_DESCRIPTIONS.md#var-naming) | whitelist & blacklist of initialisms | Naming rules. | yes | no | 432 | [`package-comments`](./RULES_DESCRIPTIONS.md#package-comments) | n/a | Package commenting conventions. | yes | no | 433 | [`range`](./RULES_DESCRIPTIONS.md#range) | n/a | Prevents redundant variables when iterating over a collection. | yes | no | 434 | [`receiver-naming`](./RULES_DESCRIPTIONS.md#receiver-naming) | n/a | Conventions around the naming of receivers. | yes | no | 435 | [`indent-error-flow`](./RULES_DESCRIPTIONS.md#indent-error-flow) | n/a | Prevents redundant else statements. | yes | no | 436 | [`argument-limit`](./RULES_DESCRIPTIONS.md#argument-limit) | int | Specifies the maximum number of arguments a function can receive | no | no | 437 | [`cyclomatic`](./RULES_DESCRIPTIONS.md#cyclomatic) | int | Sets restriction for maximum Cyclomatic complexity. | no | no | 438 | [`max-public-structs`](./RULES_DESCRIPTIONS.md#max-public-structs) | int | The maximum number of public structs in a file. | no | no | 439 | [`file-header`](./RULES_DESCRIPTIONS.md#file-header) | string | Header which each file should have. | no | no | 440 | [`empty-block`](./RULES_DESCRIPTIONS.md#empty-block) | n/a | Warns on empty code blocks | no | yes | 441 | [`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 | 442 | [`confusing-naming`](./RULES_DESCRIPTIONS.md#confusing-naming) | n/a | Warns on methods with names that differ only by capitalization | no | no | 443 | [`get-return`](./RULES_DESCRIPTIONS.md#get-return) | n/a | Warns on getters that do not yield any result | no | no | 444 | [`modifies-parameter`](./RULES_DESCRIPTIONS.md#modifies-parameter) | n/a | Warns on assignments to function parameters | no | no | 445 | [`confusing-results`](./RULES_DESCRIPTIONS.md#confusing-results) | n/a | Suggests to name potentially confusing function results | no | no | 446 | [`deep-exit`](./RULES_DESCRIPTIONS.md#deep-exit) | n/a | Looks for program exits in funcs other than `main()` or `init()` | no | no | 447 | [`unused-parameter`](./RULES_DESCRIPTIONS.md#unused-parameter) | n/a | Suggests to rename or remove unused function parameters | no | no | 448 | [`unreachable-code`](./RULES_DESCRIPTIONS.md#unreachable-code) | n/a | Warns on unreachable code | no | no | 449 | [`add-constant`](./RULES_DESCRIPTIONS.md#add-constant) | map | Suggests using constant for magic numbers and string literals | no | no | 450 | [`flag-parameter`](./RULES_DESCRIPTIONS.md#flag-parameter) | n/a | Warns on boolean parameters that create a control coupling | no | no | 451 | [`unnecessary-stmt`](./RULES_DESCRIPTIONS.md#unnecessary-stmt) | n/a | Suggests removing or simplifying unnecessary statements | no | no | 452 | [`struct-tag`](./RULES_DESCRIPTIONS.md#struct-tag) | n/a | Checks common struct tags like `json`,`xml`,`yaml` | no | no | 453 | [`modifies-value-receiver`](./RULES_DESCRIPTIONS.md#modifies-value-receiver) | n/a | Warns on assignments to value-passed method receivers | no | yes | 454 | [`constant-logical-expr`](./RULES_DESCRIPTIONS.md#constant-logical-expr) | n/a | Warns on constant logical expressions | no | no | 455 | [`bool-literal-in-expr`](./RULES_DESCRIPTIONS.md#bool-literal-in-expr)| n/a | Suggests removing Boolean literals from logic expressions | no | no | 456 | [`redefines-builtin-id`](./RULES_DESCRIPTIONS.md#redefines-builtin-id)| n/a | Warns on redefinitions of builtin identifiers | no | no | 457 | [`function-result-limit`](./RULES_DESCRIPTIONS.md#function-result-limit) | int | Specifies the maximum number of results a function can return | no | no | 458 | [`imports-blacklist`](./RULES_DESCRIPTIONS.md#imports-blacklist) | []string | Disallows importing the specified packages | no | no | 459 | [`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 | 460 | [`range-val-address`](./RULES_DESCRIPTIONS.md#range-val-address)| n/a | Warns if address of range value is used dangerously | no | yes | 461 | [`waitgroup-by-value`](./RULES_DESCRIPTIONS.md#waitgroup-by-value) | n/a | Warns on functions taking sync.WaitGroup as a by-value parameter | no | no | 462 | [`atomic`](./RULES_DESCRIPTIONS.md#atomic) | n/a | Check for common mistaken usages of the `sync/atomic` package | no | no | 463 | [`empty-lines`](./RULES_DESCRIPTIONS.md#empty-lines) | n/a | Warns when there are heading or trailing newlines in a block | no | no | 464 | [`line-length-limit`](./RULES_DESCRIPTIONS.md#line-length-limit) | int | Specifies the maximum number of characters in a line | no | no | 465 | [`call-to-gc`](./RULES_DESCRIPTIONS.md#call-to-gc) | n/a | Warns on explicit call to the garbage collector | no | no | 466 | [`duplicated-imports`](./RULES_DESCRIPTIONS.md#duplicated-imports) | n/a | Looks for packages that are imported two or more times | no | no | 467 | [`import-shadowing`](./RULES_DESCRIPTIONS.md#import-shadowing) | n/a | Spots identifiers that shadow an import | no | no | 468 | [`bare-return`](./RULES_DESCRIPTIONS.md#bare-return) | n/a | Warns on bare returns | no | no | 469 | [`unused-receiver`](./RULES_DESCRIPTIONS.md#unused-receiver) | n/a | Suggests to rename or remove unused method receivers | no | no | 470 | [`unhandled-error`](./RULES_DESCRIPTIONS.md#unhandled-error) | []string | Warns on unhandled errors returned by funcion calls | no | yes | 471 | [`cognitive-complexity`](./RULES_DESCRIPTIONS.md#cognitive-complexity) | int | Sets restriction for maximum Cognitive complexity. | no | no | 472 | [`string-of-int`](./RULES_DESCRIPTIONS.md#string-of-int) | n/a | Warns on suspicious casts from int to string | no | yes | 473 | [`string-format`](./RULES_DESCRIPTIONS.md#string-format) | map | Warns on specific string literals that fail one or more user-configured regular expressions | no | no | 474 | [`early-return`](./RULES_DESCRIPTIONS.md#early-return) | n/a | Spots if-then-else statements that can be refactored to simplify code reading | no | no | 475 | [`unconditional-recursion`](./RULES_DESCRIPTIONS.md#unconditional-recursion) | n/a | Warns on function calls that will lead to (direct) infinite recursion | no | no | 476 | [`identical-branches`](./RULES_DESCRIPTIONS.md#identical-branches) | n/a | Spots if-then-else statements with identical `then` and `else` branches | no | no | 477 | [`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 | 478 | [`unexported-naming`](./RULES_DESCRIPTIONS.md#unexported-naming) | n/a | Warns on wrongly named un-exported symbols | no | no | 479 | [`function-length`](./RULES_DESCRIPTIONS.md#function-length) | n/a | Warns on functions exceeding the statements or lines max | no | no | 480 | [`nested-structs`](./RULES_DESCRIPTIONS.md#nested-structs) | n/a | Warns on structs within structs | no | no | 481 | [`useless-break`](./RULES_DESCRIPTIONS.md#useless-break) | n/a | Warns on useless `break` statements in case clauses | no | no | 482 | [`banned-characters`](./RULES_DESCRIPTIONS.md#banned-characters) | n/a | Checks banned characters in identifiers | no | no | 483 | [`optimize-operands-order`](./RULES_DESCRIPTIONS.md#optimize-operands-order) | n/a | Checks inefficient conditional expressions | no | no | 484 485 ## Configurable rules 486 487 Here you can find how you can configure some existing rules: 488 489 ### `var-naming` 490 491 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)) 492 493 ```toml 494 [rule.var-naming] 495 arguments = [["ID"], ["VM"]] 496 ``` 497 498 This way, revive will not warn for identifier called `customId` but will warn that `customVm` should be called `customVM`. 499 500 ## Available Formatters 501 502 This section lists all the available formatters and provides a screenshot for each one. 503 504 ### Friendly 505 506 ![Friendly formatter](/assets/formatter-friendly.png) 507 508 ### Stylish 509 510 ![Stylish formatter](/assets/formatter-stylish.png) 511 512 ### Default 513 514 The default formatter produces the same output as `golint`. 515 516 ![Default formatter](/assets/formatter-default.png) 517 518 ### Plain 519 520 The plain formatter produces the same output as the default formatter and appends URL to the rule description. 521 522 ![Plain formatter](/assets/formatter-plain.png) 523 524 ### Unix 525 526 The unix formatter produces the same output as the default formatter but surrounds the rules in `[]`. 527 528 ![Unix formatter](/assets/formatter-unix.png) 529 530 ### SARIF 531 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/). 532 533 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 534 ). 535 536 ## Extensibility 537 538 The tool can be extended with custom rules or formatters. This section contains additional information on how to implement such. 539 540 To extend the linter with a custom rule you can push it to this repository or use `revive` as a library (see below) 541 542 To add a custom 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/). 543 544 ### Writing a Custom Rule 545 546 Each rule needs to implement the `lint.Rule` interface: 547 548 ```go 549 type Rule interface { 550 Name() string 551 Apply(*File, Arguments) []Failure 552 } 553 ``` 554 555 The `Arguments` type is an alias of the type `[]interface{}`. The arguments of the rule are passed from the configuration file. 556 557 #### Example 558 559 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: 560 561 ```toml 562 [rule.ban-struct-name] 563 arguments = ["Foo"] 564 ``` 565 566 With the snippet above we: 567 568 - Enable the rule with name `ban-struct-name`. The `Name()` method of our rule should return a string which matches `ban-struct-name`. 569 - 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. 570 571 A sample rule implementation can be found [here](/rule/argument-limit.go). 572 573 #### Using `revive` as a library 574 If a rule is specific to your use case 575 (i.e. it is not a good candidate to be added to `revive`'s rule set) you can add it to your own linter using `revive` as linting engine. 576 577 The following code shows how to use `revive` in your own application. 578 In the example only one rule is added (`myRule`), of course, you can add as many as you need to. 579 Your rules can be configured programmatically or with the standard `revive` configuration file. 580 The full rule set of `revive` is also actionable by your application. 581 582 ```go 583 package main 584 585 import ( 586 "github.com/songshiyun/revive/cli" 587 "github.com/songshiyun/revive/lint" 588 ) 589 590 func main() { 591 cli.RunRevive(cli.NewExtraRule(&myRule{}, lint.RuleConfig{})) 592 } 593 594 type myRule struct{} 595 596 func (f myRule) Name() string { 597 return "myRule" 598 } 599 600 func (f myRule) Apply(*lint.File, lint.Arguments) []lint.Failure { ... } 601 ``` 602 603 ### Custom Formatter 604 605 Each formatter needs to implement the following interface: 606 607 ```go 608 type Formatter interface { 609 Format(<-chan Failure, Config) (string, error) 610 Name() string 611 } 612 ``` 613 614 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. 615 616 For a sample formatter, take a look at [this file](/formatter/json.go). 617 618 ## Speed Comparison 619 620 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: 621 622 ### golint 623 624 ```shell 625 time golint kubernetes/... > /dev/null 626 627 real 0m54.837s 628 user 0m57.844s 629 sys 0m9.146s 630 ``` 631 632 ### revive 633 634 ```shell 635 # no type checking 636 time revive -config untyped.toml kubernetes/... > /dev/null 637 638 real 0m8.471s 639 user 0m40.721s 640 sys 0m3.262s 641 ``` 642 643 Keep in mind that if you use rules which require type checking, the performance may drop to 2x faster than `golint`: 644 645 ```shell 646 # type checking enabled 647 time revive kubernetes/... > /dev/null 648 649 real 0m26.211s 650 user 2m6.708s 651 sys 0m17.192s 652 ``` 653 654 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. 655 656 ## Overriding colorization detection 657 658 By default, `revive` determines whether or not to colorize its output based on whether it's connected to a TTY or not. 659 This works for most use cases, but may not behave as expected if you use `revive` in a pipeline of commands, 660 where STDOUT is being piped to another command. 661 662 To force colorization, add `REVIVE_FORCE_COLOR=1` to the environment you're running in. For example: 663 664 ```shell 665 REVIVE_FORCE_COLOR=1 revive -formatter friendly ./... | tee revive.log 666 ``` 667 668 ## Contributors 669 670 [<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) | 671 :---: |:---: |:---: |:---: |:---: |:---: | 672 [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) | 673 674 [<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) | 675 :---: |:---: |:---: |:---: |:---: |:---: | 676 [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) | 677 678 [<img alt="mapreal19" src="https://avatars.githubusercontent.com/u/3055997?v=4&s=117" width="117">](https://github.com/mapreal19) |[<img alt="abeltay" src="https://avatars.githubusercontent.com/u/15604207?v=4&s=117" width="117">](https://github.com/abeltay) |[<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="derekperkins" src="https://avatars.githubusercontent.com/u/3588778?v=4&s=117" width="117">](https://github.com/derekperkins) |[<img alt="yangdiangzb" src="https://avatars.githubusercontent.com/u/16643665?v=4&s=117" width="117">](https://github.com/yangdiangzb) | 679 :---: |:---: |:---: |:---: |:---: |:---: | 680 [mapreal19](https://github.com/mapreal19) |[abeltay](https://github.com/abeltay) |[Aragur](https://github.com/Aragur) |[s0xzwasd](https://github.com/s0xzwasd) |[derekperkins](https://github.com/derekperkins) |[yangdiangzb](https://github.com/yangdiangzb) | 681 682 [<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) |[<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) | 683 :---: |:---: |:---: |:---: |:---: |:---: | 684 [petethepig](https://github.com/petethepig) |[quasilyte](https://github.com/quasilyte) |[grongor](https://github.com/grongor) |[jamesmaidment](https://github.com/jamesmaidment) |[johnrichardrinehart](https://github.com/johnrichardrinehart) |[very-amused](https://github.com/very-amused) | 685 686 [<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) |[<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="rdeusser" src="https://avatars.githubusercontent.com/u/5935071?v=4&s=117" width="117">](https://github.com/rdeusser) | 687 :---: |:---: |:---: |:---: |:---: |:---: | 688 [mathieu-aubin](https://github.com/mathieu-aubin) |[michalhisim](https://github.com/michalhisim) |[pa-m](https://github.com/pa-m) |[paul-at-start](https://github.com/paul-at-start) |[paco0x](https://github.com/paco0x) |[rdeusser](https://github.com/rdeusser) | 689 690 [<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) |[<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) | 691 :---: |:---: |:---: |:---: |:---: |:---: | 692 [ridvansumset](https://github.com/ridvansumset) |[Jarema](https://github.com/Jarema) |[vkrol](https://github.com/vkrol) |[haya14busa](https://github.com/haya14busa) |[sina-devel](https://github.com/sina-devel) |[techknowlogick](https://github.com/techknowlogick) | 693 694 ## License 695 696 MIT