github.com/yoheimuta/protolint@v0.49.8-0.20240515023657-4ecaebb7575d/README.md (about)

     1  # protolint
     2  ![Action](https://github.com/yoheimuta/protolint/workflows/Go/badge.svg)
     3  [![Release](https://img.shields.io/github/v/release/yoheimuta/protolint?include_prereleases)](https://github.com/yoheimuta/protolint/releases)[
     4  ![Go Report Card](https://goreportcard.com/badge/github.com/yoheimuta/protolint)](https://goreportcard.com/report/github.com/yoheimuta/protolint)
     5  [![License](http://img.shields.io/:license-mit-blue.svg)](https://github.com/yoheimuta/protolint/blob/master/LICENSE)
     6  [![Docker](https://img.shields.io/docker/pulls/yoheimuta/protolint)](https://hub.docker.com/r/yoheimuta/protolint)
     7  
     8  protolint is the pluggable linting/fixing utility for Protocol Buffer files (proto2+proto3):
     9  
    10  - Runs fast because this works without compiler.
    11  - Easy to follow the official style guide. The rules and the style guide correspond to each other exactly.
    12    - Fixer automatically fixes all the possible official style guide violations.
    13  - Allows to disable rules with a comment in a Protocol Buffer file.
    14    - It is useful for projects which must keep API compatibility while enforce the style guide as much as possible.
    15    - Some rules can be automatically disabled by inserting comments to the spotted violations.
    16  - Loads plugins to contain your custom lint rules.
    17  - Undergone testing for all rules.
    18  - Many integration supports.
    19    - protoc plugin
    20    - Editor integration
    21    - GitHub Action
    22    - CI Integration
    23  
    24  ## Demo
    25  
    26  For example, vim-protolint works like the following.
    27  
    28  <img src="_doc/demo-v2.gif" alt="demo" width="600"/>
    29  
    30  ## Installation
    31  
    32  ### Via Homebrew
    33  
    34  protolint can be installed for Mac or Linux using Homebrew via the [yoheimuta/protolint](https://github.com/yoheimuta/homebrew-protolint) tap.
    35  
    36  ```sh
    37  brew tap yoheimuta/protolint
    38  brew install protolint
    39  ```
    40  
    41  Since [homebrew-core](https://github.com/Homebrew/homebrew-core/pkgs/container/core%2Fprotolint) includes `protolint,` you can also install it by just `brew install protolint.` This is the default tap that is installed by default. It's easier, but not maintained by the same author. To keep it updated, I recommend you run `brew tap yoheimuta/protolint` first.
    42  
    43  
    44  ### Via GitHub Releases
    45  
    46  You can also download a pre-built binary from this release page:
    47  
    48  - https://github.com/yoheimuta/protolint/releases
    49  
    50  In the downloads section of each release, you can find pre-built binaries in .tar.gz packages.
    51  
    52  ### Use the maintained Docker image
    53  
    54  protolint ships a Docker image [yoheimuta/protolint](https://hub.docker.com/r/yoheimuta/protolint) that allows you to use protolint as part of your Docker workflow.
    55  
    56  ```
    57  ❯❯❯ docker run --volume "$(pwd):/workspace" --workdir /workspace yoheimuta/protolint lint _example/proto
    58  [_example/proto/invalidFileName.proto:1:1] File name should be lower_snake_case.proto.
    59  [_example/proto/issue_88/oneof_options.proto:11:5] Found an incorrect indentation style "    ". "  " is correct.
    60  [_example/proto/issue_88/oneof_options.proto:12:5] Found an incorrect indentation style "    ". "  " is correct.
    61  ```
    62  
    63  ### From Source
    64  
    65  The binary can be installed from source if Go is available.
    66  However, I recommend using one of the pre-built binaries instead because it doesn't include the version info.
    67  
    68  ```sh
    69  go install github.com/yoheimuta/protolint/cmd/protolint@latest
    70  ```
    71  
    72  ### Within JavaScript / TypeScript
    73  
    74  You can use `protolint` using your nodejs package manager like `npm` or `yarn`.
    75  
    76  ```sh
    77  $ npm install protolint --save-dev
    78  ```
    79  
    80  This will add a reference to a development dependency to your local `package.json`.
    81  
    82  During install, the [install.mjs](bdist/js/install.mjs) script will be called. It will download the matching `protolint` from github. Just like [@electron/get](https://github.com/electron/get/), you can bypass the download using the following environment variables:
    83  
    84  | Environment Variable          | Default value                         | Description                                   |
    85  |-------------------------------|---------------------------------------|-----------------------------------------------|
    86  | PROTOLINT_MIRROR_HOST         | https://github.com                    | HTTP/Web server base url hosting the binaries |
    87  | PROTOLINT_MIRROR_REMOTE_PATH  | yoheimuta/protolint/download/releases | Path to the archives on the remote host       |
    88  | PROTOLINT_MIRROR_USERNAME     |                                       | HTTP Basic auth user name                     |
    89  | PROTOLINT_MIRROR_PASSWORD     |                                       | HTTP Basic auth password                      |
    90  | PROTOLINT_PROXY               |                                       | HTTP(S) Proxy with optional auth data         |
    91  
    92  Within the remote path, the archives from the [releases](https://github.com/yoheimuta/protolint/releases/latest/) page must be
    93  mirrored.
    94  
    95  After that, you can use `npx protolint` (with all supplied protolint arguments) within your dev-scripts.
    96  
    97  ```json
    98  {
    99    ...
   100    "scripts": {
   101      "protoc": "....",
   102      "preprotoc": "npx protolint"
   103    },
   104    ...
   105  }
   106  ```
   107  
   108  You can add a `protolint` node to your `package.json` which may contain the content of `protolint.yml` below the `lint` node, i.e. the root element of the configuration will be `protolint`.
   109  
   110  If you want to get an output that matches the TSC compiler, use reporter `tsc`.
   111  
   112  ### Within Python projects
   113  
   114  You can use `protolint` as a linter within your python projects, the wheel `protolint-bin` on [pypi](https://pypi.org) contains the pre-compiled binaries for various platforms. Just add the desired version to
   115  your `pyproject.toml` or `requirements.txt`.
   116  
   117  The wheels downloaded will contain the compiled go binaries for `protolint` and `protoc-gen-protolint`. Your platform must
   118  be compatible with the supported binary platforms.
   119  
   120  You can add the linter configuration to the `tools.protolint` package in `pyproject.toml`.
   121  
   122  ## Usage
   123  
   124  ```sh
   125  protolint lint example.proto example2.proto # file mode, specify multiple specific files
   126  protolint lint .                            # directory mode, search for all .proto files recursively
   127  protolint .                                 # same as "protolint lint ."
   128  protolint lint -config_path=path/to/your_protolint.yaml . # use path/to/your_protolint.yaml
   129  protolint lint -config_dir_path=path/to .   # search path/to for .protolint.yaml
   130  protolint lint -fix .                       # automatically fix some of the problems reported by some rules
   131  protolint lint -fix -auto_disable=next .    # this is preferable when you want to fix problems while maintaining the compatibility. Automatically fix some problems and insert disable comments to the other problems. The available values are next and this.
   132  protolint lint -auto_disable=next .         # automatically insert disable comments to the other problems. 
   133  protolint lint -v .                         # with verbose output to investigate the parsing error
   134  protolint lint -no-error-on-unmatched-pattern . # exits with success code even if no file is found (file & directory mode)
   135  protolint lint -reporter junit .            # output results in JUnit XML format
   136  protolint lint -output_file=path/to/out.txt # output results to path/to/out.txt
   137  protolint lint -plugin ./my_custom_rule1 -plugin ./my_custom_rule2 .   # run custom lint rules.
   138  protolint list                              # list all current lint rules being used
   139  protolint version                           # print protolint version
   140  ```
   141  
   142  protolint does not require configuration by default, for the majority of projects it should work out of the box.
   143  
   144  ## Version Control Integration
   145  
   146  protolint is available as a [pre-commit](https://pre-commit.com) hook.  Add this to your `.pre-commit-config.yaml` in your repository to run protolint with Go:
   147  ```yaml
   148  repos:
   149    - repo: https://github.com/yoheimuta/protolint
   150      rev: <version> # Select a release here like v0.44.0
   151      hooks:
   152        - id: protolint
   153  ```
   154  or alternatively use this to run protolint with Docker:
   155  ```yaml
   156  repos:
   157    - repo: https://github.com/yoheimuta/protolint
   158      rev: <version> # Select a release here like v0.44.0
   159      hooks:
   160        - id: protolint-docker
   161  ```
   162  
   163  ## Editor Integration
   164  
   165  Visual Studio Code
   166  
   167  - [vscode-protolint](https://github.com/plexsystems/vscode-protolint)
   168  
   169  JetBrains IntelliJ IDEA, GoLand, WebStorm, PHPStorm, PyCharm...
   170  
   171  - [intellij-protolint](https://github.com/yoheimuta/intellij-protolint)
   172  
   173  Vim([ALE engine](https://github.com/dense-analysis/ale))
   174  
   175  - [ale](https://github.com/dense-analysis/ale)'s [built-in support](https://github.com/dense-analysis/ale/blob/master/supported-tools.md)
   176  
   177  Vim([Syntastic](https://github.com/vim-syntastic/syntastic))
   178  
   179  - [vim-protolint](https://github.com/yoheimuta/vim-protolint)
   180  
   181  ## GitHub Action
   182  
   183  A [GitHub Action](https://github.com/features/actions) to run protolint in your workflows
   184  
   185  - [github/super-linter](https://github.com/github/super-linter)
   186  - [plexsystems/protolint-action](https://github.com/plexsystems/protolint-action)
   187  - [yoheimuta/action-protolint](https://github.com/yoheimuta/action-protolint) - Integrated with [reviewdog](https://github.com/reviewdog/reviewdog)
   188  
   189  ## CI Integration
   190  
   191  Jenkins Plugins
   192  
   193  - [warnings-ng](https://github.com/jenkinsci/warnings-ng-plugin) and any that use [violatons-lib](https://github.com/tomasbjerre/violations-lib)
   194  
   195  ### Environment specific output
   196  
   197  It is possible to format your linting according to the formatting of the CI/CD environment. The environment must be set using the output format. Currently, the following output is realized:
   198  
   199  | Environment | Command Line Value | Description | Example |
   200  |-------------|--------------------|-------------|---------|
   201  | Github Actions | ci-gh | [Github Help](https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#setting-a-notice-message) | `::warning file=example.proto,line=10,col=20,title=ENUM_NAMES_UPPER_CAMEL_CASE::EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES` |
   202  | Azure DevOps | ci-az | [Azure DevOps Help](https://learn.microsoft.com/en-us/azure/devops/pipelines/scripts/logging-commands?view=azure-devops&tabs=bash#task-commands) | `##vso[task.logissue type=warning;sourcepath=example.proto;linenumber=10;columnnumber=20;code=ENUM_NAMES_UPPER_CAMEL_CASE;]EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES` |
   203  | Gitlab CI/CD | ci-glab | Reverse Engineered from Examples | `WARNING: ENUM_NAMES_UPPER_CAMEL_CASE  example.proto(10,20) : EnumField name \"SECOND.VALUE\" must be CAPITALS_WITH_UNDERSCORES` |
   204  
   205  You can also use the generic `ci` formatter, which will create a generic problem matcher.
   206  
   207  With the `ci-env` value, you can specify the template from the following environment variables:
   208  
   209  | Environment Variable | Priority | Meaning |
   210  |----------------------|----------|---------|
   211  | PROTOLINT_CIREPORTER_TEMPLATE_STRING | 1 | String containing a Go-template |
   212  | PROTOLINT_CIREPORTER_TEMPLATE_FILE | 2 | Path to a file containing a Go-template |
   213  
   214  The resulting line-feed must not be added, as it will be added automatically.
   215  
   216  The following fields are available:
   217  
   218  `Severity`
   219  : The severity as string (either note, warning or error)
   220  
   221  `File`
   222  : Path to the file containing the error
   223  
   224  `Line`
   225  : Line within the `file` containing the error (starting position)
   226  
   227  `Column`
   228  : Column within the `file` containing the error (starting position)
   229  
   230  `Rule`
   231  : The name of the rule that is faulting
   232  
   233  `Message`
   234  : The error message that descibes the error
   235  
   236  ### Producing an output file and an CI/CD Error stream
   237  
   238  You can create a specific output matching your CI/CD environment and also create an output file, e.g. for your static code analysis tools like github CodeQL or SonarQube.
   239  
   240  This can be done by adding the `--add-reporter` flag.
   241  Please note, that the value must be formatted `<reporter-name>:<output-file-path>` (omitting `<` and `>`).
   242  
   243  ```shell
   244  $ protolint --reporter ci-gh --add-reporter sarif:/path/to/my/output.sarif.json proto/*.proto
   245  ```
   246  
   247  ## Use as a protoc plugin
   248  
   249  protolint also maintains a binary [protoc-gen-protolint](cmd/protoc-gen-protolint) that performs the lint functionality as a protoc plugin.
   250  See [cmd/protoc-gen-protolint/README.md](https://github.com/yoheimuta/protolint/blob/master/cmd/protoc-gen-protolint/README.md) in detail.
   251  
   252  This is useful in situations where you already have a protoc plugin workflow.
   253  
   254  ## Call from Go code
   255  
   256  You can also use protolint from Go code.
   257  See [Go Documentation](https://pkg.go.dev/github.com/yoheimuta/protolint/lib) and [lib/lint_test.go](https://github.com/yoheimuta/protolint/blob/master/lib/lint_test.go) in detail.
   258  
   259  ```go
   260  args := []string{"-config_path", "path/to/your_protolint.yaml", "."}
   261  var stdout bytes.Buffer
   262  var stderr bytes.Buffer
   263  
   264  err := lib.Lint(test.inputArgs, &stdout, &stderr)
   265  ```
   266  
   267  ## Rules
   268  
   269  See `internal/addon/rules` in detail.
   270  
   271  The rule set follows:
   272  
   273  - [Official Style Guide](https://protobuf.dev/programming-guides/style/). This is enabled by default. Basically, these rules can fix the violations by appending `-fix` option.
   274  - Unofficial Style Guide. This is disabled by default. You can enable each rule with `.protolint.yaml`.
   275  
   276  The `-fix` option on the command line can automatically fix all the problems reported by fixable rules.
   277  See Fixable columns below.
   278  
   279  The `-auto_disable` option on the command line can automatically disable all the problems reported by auto-disable rules.
   280  This feature is helpful when fixing the existing violations breaks the compatibility.
   281  See AutoDisable columns below.
   282  
   283  - *1: These rules are not supposed to support AutoDisable because the fixes don't break their compatibilities. You should run the protolint with `-fix`.
   284  
   285  | Official | Fixable | AutoDisable | ID                                | Purpose                                                                  |
   286  |----------|---------|---------|-----------------------------------|--------------------------------------------------------------------------|
   287  | Yes | ✅ | ✅ | ENUM_FIELD_NAMES_PREFIX | Verifies that enum field names are prefixed with its ENUM_NAME_UPPER_SNAKE_CASE.        |
   288  | Yes | ✅ | ✅ | ENUM_FIELD_NAMES_UPPER_SNAKE_CASE | Verifies that all enum field names are CAPITALS_WITH_UNDERSCORES.        |
   289  | Yes | ✅ | ✅ | ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH | Verifies that the zero value enum should have the suffix (e.g. "UNSPECIFIED", "INVALID"). The default is "UNSPECIFIED". You can configure the specific suffix with `.protolint.yaml`. |
   290  | Yes | ✅ | ✅ | ENUM_NAMES_UPPER_CAMEL_CASE       | Verifies that all enum names are CamelCase (with an initial capital).    |
   291  | Yes | ✅ | *1 | FILE_NAMES_LOWER_SNAKE_CASE       | Verifies that all file names are lower_snake_case.proto. You can configure the excluded files with `.protolint.yaml`. |
   292  | Yes | ✅ | ✅ | FIELD_NAMES_LOWER_SNAKE_CASE      | Verifies that all field names are underscore_separated_names.            |
   293  | Yes | ✅ | *1 | IMPORTS_SORTED                    | Verifies that all imports are sorted. |
   294  | Yes | ✅ | ✅ | MESSAGE_NAMES_UPPER_CAMEL_CASE    | Verifies that all message names are CamelCase (with an initial capital). |
   295  | Yes | ✅ | *1 | ORDER                             | Verifies that all files should be ordered in the specific manner. |
   296  | Yes | ✅ | *1 | PACKAGE_NAME_LOWER_CASE           | Verifies that the package name should only contain lowercase letters. |
   297  | Yes | ✅ | ✅ | RPC_NAMES_UPPER_CAMEL_CASE        | Verifies that all rpc names are CamelCase (with an initial capital).     |
   298  | Yes | ✅ | ✅ | SERVICE_NAMES_UPPER_CAMEL_CASE    | Verifies that all service names are CamelCase (with an initial capital). |
   299  | Yes | ✅ | ✅ | REPEATED_FIELD_NAMES_PLURALIZED   | Verifies that repeated field names are pluralized names.            |
   300  | Yes | ✅ | *1 | QUOTE_CONSISTENT   | Verifies that the use of quote for strings is consistent. The default is double quoted. You can configure the specific quote with `.protolint.yaml`.          |
   301  | Yes | ✅ | *1 | INDENT    | Enforces a consistent indentation style. The default style is 2 spaces. Inserting appropriate new lines is also forced by default. You can configure the detail with `.protolint.yaml`. |
   302  | Yes | ✅ | *1 | PROTO3_FIELDS_AVOID_REQUIRED      | Verifies that all fields should avoid required for proto3.            |
   303  | Yes | _  | ✅ | PROTO3_GROUPS_AVOID      | Verifies that all groups should be avoided for proto3.            |
   304  | Yes | _  | *1 | MAX_LINE_LENGTH    | Enforces a maximum line length. The length of a line is defined as the number of Unicode characters in the line. The default is 80 characters. You can configure the detail with `.protolint.yaml`. |
   305  | No | _  | - | SERVICE_NAMES_END_WITH    | Enforces a consistent suffix for service names. You can configure the specific suffix with `.protolint.yaml`. |
   306  | No | _  | - | FIELD_NAMES_EXCLUDE_PREPOSITIONS | Verifies that all field names don't include prepositions (e.g. "for", "during", "at"). You can configure the specific prepositions and excluded keywords with `.protolint.yaml`. |
   307  | No | _  | - | MESSAGE_NAMES_EXCLUDE_PREPOSITIONS | Verifies that all message names don't include prepositions (e.g. "With", "For"). You can configure the specific prepositions and excluded keywords with `.protolint.yaml`. |
   308  | No | _  | - | RPC_NAMES_CASE        | Verifies that all rpc names conform to the specified convention. You need to configure the specific convention with `.protolint.yaml`.     |
   309  | No | _  | - | MESSAGES_HAVE_COMMENT | Verifies that all messages have a comment. You can configure to enforce Golang Style comments with `.protolint.yaml`. |
   310  | No | _  | - | SERVICES_HAVE_COMMENT | Verifies that all services have a comment. You can configure to enforce Golang Style comments with `.protolint.yaml`. |
   311  | No | _  | - | RPCS_HAVE_COMMENT | Verifies that all rps have a comment. You can configure to enforce Golang Style comments with `.protolint.yaml`. |
   312  | No | _  | - | FIELDS_HAVE_COMMENT | Verifies that all fields have a comment. You can configure to enforce Golang Style comments with `.protolint.yaml`. |
   313  | No | _  | - | ENUMS_HAVE_COMMENT | Verifies that all enums have a comment. You can configure to enforce Golang Style comments with `.protolint.yaml`. |
   314  | No | _  | - | ENUM_FIELDS_HAVE_COMMENT | Verifies that all enum fields have a comment. You can configure to enforce Golang Style comments with `.protolint.yaml`. |
   315  | No | _  | - | FILE_HAS_COMMENT | Verifies that a file starts with a doc comment. |
   316  | No | _  | - | SYNTAX_CONSISTENT | Verifies that syntax is a specified version. The default is proto3. You can configure the version with `.protolint.yaml`. |
   317  
   318  I recommend that you add `all_default: true` in `.protolint.yaml`, because all linters above are automatically enabled so that you can always enjoy maximum benefits whenever protolint is updated.
   319  
   320  Here are some examples that show good style enabled by default.
   321  `-` is a bad style, `+` is a good style:
   322  
   323  __ENUM_FIELD_NAMES_PREFIX__
   324  
   325  ```diff
   326  enum FooBar {
   327  -  UNSPECIFIED = 0;
   328  +  FOO_BAR_UNSPECIFIED = 0;
   329  }
   330  ```
   331  
   332  __ENUM_FIELD_NAMES_UPPER_SNAKE_CASE__
   333  
   334  ```diff
   335  enum Foo {
   336  -  firstValue = 0;
   337  +  FIRST_VALUE = 0;
   338  -  second_value = 1;
   339  +  SECOND_VALUE = 1;
   340  }
   341  ```
   342  
   343  __ENUM_FIELD_NAMES_ZERO_VALUE_END_WITH__
   344  
   345  ```diff
   346  enum Foo {
   347  -  FOO_FIRST = 0;
   348  +  FOO_UNSPECIFIED = 0;
   349  }
   350  ```
   351  
   352  __ENUM_NAMES_UPPER_CAMEL_CASE__
   353  
   354  ```diff
   355  - enum foobar {
   356  + enum FooBar {
   357    FIRST_VALUE = 0;
   358    SECOND_VALUE = 1;
   359  }
   360  ```
   361  
   362  __FIELD_NAMES_LOWER_SNAKE_CASE__
   363  
   364  ```diff
   365  message SongServerRequest {
   366  -  required string SongName = 1;
   367  +  required string song_name = 1;
   368  }
   369  ```
   370  
   371  __IMPORTS_SORTED__
   372  
   373  ```diff
   374  - import public "new.proto";
   375  + import "myproject/other_protos.proto";
   376  - import "myproject/other_protos.proto";
   377  + import public "new.proto";
   378  
   379  import "google/protobuf/empty.proto";
   380  import "google/protobuf/timestamp.proto";
   381  ```
   382  
   383  __MESSAGE_NAMES_UPPER_CAMEL_CASE__
   384  
   385  ```diff
   386  - message song_server_request {
   387  + message SongServerRequest {
   388    required string SongName = 1;
   389    required string song_name = 1;
   390  }
   391  ```
   392  
   393  __ORDER__
   394  
   395  ```diff
   396  - option java_package = "com.example.foo";
   397  - syntax = "proto3";
   398  - package examplePb;
   399  - message song_server_request { }
   400  - import "other.proto";
   401  + syntax = "proto3";
   402  + package examplePb;
   403  + import "other.proto";
   404  + option java_package = "com.example.foo";
   405  + message song_server_request { }
   406  ```
   407  
   408  __PACKAGE_NAME_LOWER_CASE__
   409  
   410  ```diff
   411  - package myPackage
   412  + package my.package
   413  ```
   414  
   415  __RPC_NAMES_UPPER_CAMEL_CASE__
   416  
   417  ```diff
   418  service FooService {
   419  -  rpc get_something(FooRequest) returns (FooResponse);
   420  +  rpc GetSomething(FooRequest) returns (FooResponse);
   421  }
   422  ```
   423  
   424  __RPC_NAMES_UPPER_CAMEL_CASE__
   425  
   426  ```diff
   427  - service foo_service {
   428  + service FooService {
   429    rpc get_something(FooRequest) returns (FooResponse);
   430    rpc GetSomething(FooRequest) returns (FooResponse);
   431  }
   432  ```
   433  
   434  __REPEATED_FIELD_NAMES_PLURALIZED__
   435  
   436  ```diff
   437  -  repeated string song_name = 1;
   438  +  repeated string song_names = 1;
   439  ```
   440  
   441  __INDENT__
   442  
   443  ```diff
   444   enum enumAllowingAlias {
   445     UNKNOWN = 0;
   446  -        option allow_alias = true;
   447  +  option allow_alias = true;
   448     STARTED = 1;
   449  -     RUNNING = 2 [(custom_option) = "hello world"];
   450  +  RUNNING = 2 [(custom_option) = "hello world"];
   451  - }
   452  +}
   453  ```
   454  
   455  ```diff
   456  -   message TestMessage { string test_field = 1; }
   457  + message TestMessage {
   458  +  string test_field = 1;
   459  +}
   460  ```
   461  
   462  __QUOTE_CONSISTENT__
   463  
   464  ```diff
   465   option java_package = "com.example.foo";
   466  - option go_package = 'example';
   467  + option go_package = "example";
   468  ```
   469  
   470  ## Creating your custom rules
   471  
   472  protolint is the pluggable linter so that you can freely create custom lint rules.
   473  
   474  A complete sample project (aka plugin) is included in this repo under the [_example/plugin](_example/plugin) directory.
   475  
   476  ## Reporters
   477  
   478  protolint comes with several built-in reporters(aka. formatters) to control the appearance of the linting results.
   479  
   480  You can specify a reporter using the -reporter flag on the command line. For example, `-reporter junit` uses the junit reporter.
   481  
   482  The built-in reporter options are:
   483  
   484  - plain (default)
   485  - junit
   486  - json
   487  - sarif
   488  - sonar (SonarQube generic issue format)
   489  - unix
   490  - tsc (compatible to TypeScript compiler)
   491  
   492  ## Configuring
   493  
   494  __Disable rules in a Protocol Buffer file__
   495  
   496  Rules can be disabled with a comment inside a Protocol Buffer file with the following format.
   497  The rules will be disabled until the end of the file or until the linter sees a matching enable comment:
   498  
   499  ```
   500  // protolint:disable <ruleID1> [<ruleID2> <ruleID3>...]
   501  ...
   502  // protolint:enable <ruleID1> [<ruleID2> <ruleID3>...]
   503  ```
   504  
   505  It's also possible to modify a disable command by appending :next or :this for only applying the command to this(current) or the next line respectively.
   506  
   507  For example:
   508  
   509  ```proto
   510  enum Foo {
   511    // protolint:disable:next ENUM_FIELD_NAMES_UPPER_SNAKE_CASE
   512    firstValue = 0;    // no error
   513    second_value = 1;  // protolint:disable:this ENUM_FIELD_NAMES_UPPER_SNAKE_CASE
   514    THIRD_VALUE = 2;   // spits out an error
   515  }
   516  ```
   517  
   518  Setting the command-line option `-auto_disable` to `next` or `this` inserts disable commands whenever spotting problems. 
   519  
   520  You can specify `-fix` option together. The rules supporting auto_disable suppress the violations instead of fixing them that cause a schema incompatibility.
   521  
   522  __Config file__
   523  
   524  protolint can operate using a config file named `.protolint.yaml`.
   525  
   526  Refer to [_example/config/.protolint.yaml](_example/config/.protolint.yaml) for the config file specification.
   527  
   528  protolint will automatically search a current working directory for the config file by default
   529  and successive parent directories all the way up to the root directory of the filesystem.
   530  And it can search the specified directory with `-config_dir_path` flag.
   531  It can also search the specified file with `--config_path` flag.
   532  
   533  ## Exit codes
   534  
   535  When linting files, protolint will exit with one of the following exit codes:
   536  
   537  - `0`: Linting was successful and there are no linting errors.
   538  - `1`: Linting was successful and there is at least one linting error.
   539  - `2`: Linting was unsuccessful due to all other errors, such as parsing, internal, and runtime errors.
   540  
   541  ## Motivation
   542  
   543  There exists the similar protobuf linters as of 2018/12/20.
   544  
   545  One is a plug-in for Google's Protocol Buffers compiler.
   546  
   547  - When you just want to lint the files, it may be tedious to create the compilation environment.
   548  - And it generally takes a lot of time to compile the files than to parse the files.
   549  
   550  Other is a command line tool which also lints Protocol Buffer files.
   551  
   552  - While it has a lot of features other than lint, it seems cumbersome for users who just want the linter.
   553  - The lint rule slants towards to be opinionated.
   554  - Further more, the rule set and the official style guide don't correspond to each other exactly. It requires to understand both rules and the guide in detail, and then to combine the rules accurately.
   555  
   556  ### Other tools
   557  
   558  I wrote an article comparing various Protocol Buffer Linters, including protolint, on 2019/12/17.
   559  
   560  - https://qiita.com/yoheimuta/items/da7678fcd046b93a2637
   561    - NOTE: This one is written in Japanese.
   562  
   563  ## Dependencies
   564  
   565  - [go-protoparser](https://github.com/yoheimuta/go-protoparser)
   566  
   567  ## License
   568  
   569  The MIT License (MIT)
   570  
   571  ## Acknowledgement
   572  
   573  Thank you to the prototool package: https://github.com/uber/prototool
   574  
   575  I referred to the package for the good proven design, interface and some source code.