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