feat: new custom linters system ()

This commit is contained in:
Ludovic Fernandez 2024-03-11 17:40:26 +01:00 committed by GitHub
parent f0fdea006f
commit 167204c1fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
31 changed files with 1339 additions and 110 deletions

View file

@ -46,3 +46,10 @@
link: /contributing/faq/
- label: This Website
link: /contributing/website/
- label: Plugins
items:
- label: Module Plugin System
link: /contributing/new-linters/
- label: Go Plugin System
link: /contributing/private-linters/

View file

@ -2,10 +2,6 @@
title: Contributing FAQ
---
## How to write a custom linter
See [there](/contributing/new-linters#how-to-write-a-custom-linter).
## How to add a new open-source linter to `golangci-lint`
See [there](/contributing/new-linters#how-to-add-a-public-linter-to-golangci-lint).
@ -16,7 +12,7 @@ See [there](/contributing/new-linters#how-to-add-a-private-linter-to-golangci-li
## How to update existing linter
Just update it's version in `go.mod`.
Just update its version in `go.mod`.
## How to add configuration option to existing linter

View file

@ -46,75 +46,7 @@ After that:
Some people and organizations may choose to have custom-made linters run as a part of `golangci-lint`.
Typically, these linters can't be open-sourced or too specific.
Such linters can be added through Go's plugin library.
Such linters can be added through 2 plugin systems:
For a private linter (which acts as a plugin) to work properly,
the plugin as well as the golangci-lint binary **needs to be built for the same environment**.
`CGO_ENABLED` is another requirement.
This means that `golangci-lint` needs to be built for whatever machine you intend to run it on
(cloning the golangci-lint repository and running a `CGO_ENABLED=1 make build` should do the trick for your machine).
### Configure a Plugin
If you already have a linter plugin available, you can follow these steps to define its usage in a projects `.golangci.yml` file.
An example linter can be found at [here](https://github.com/golangci/example-plugin-linter).
If you're looking for instructions on how to configure your own custom linter, they can be found further down.
1. If the project you want to lint does not have one already, copy the [.golangci.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.yml) to the root directory.
2. Adjust the yaml to appropriate `linters-settings:custom` entries as so:
```yaml
linters-settings:
custom:
example:
path: /example.so
description: The description of the linter
original-url: github.com/golangci/example-linter
settings: # Settings are optional.
one: Foo
two:
- name: Bar
three:
name: Bar
```
That is all the configuration that is required to run a custom linter in your project.
Custom linters are enabled by default, but abide by the same rules as other linters.
If the disable all option is specified either on command line or in `.golang.yml` files `linters.disable-all: true`, custom linters will be disabled;
they can be re-enabled by adding them to the `linters:enable` list,
or providing the enabled option on the command line, `golangci-lint run -Eexample`.
The configuration inside the `settings` field of linter have some limitations (there are NOT related to the plugin system itself):
we use Viper to handle the configuration but Viper put all the keys in lowercase, and `.` cannot be used inside a key.
### Create a Plugin
Your linter must provide one or more `golang.org/x/tools/go/analysis.Analyzer` structs.
Your project should also use `go.mod`.
All versions of libraries that overlap `golangci-lint` (including replaced libraries) MUST be set to the same version as `golangci-lint`.
You can see the versions by running `go version -m golangci-lint`.
You'll also need to create a Go file like `plugin/example.go`.
This file MUST be in the package `main`, and MUST define an exposed function called `New` with the following signature:
```go
func New(conf any) ([]*analysis.Analyzer, error) {
// ...
}
```
See [plugin/example.go](https://github.com/golangci/example-plugin-linter/blob/master/plugin/example.go) for more info.
To build the plugin, from the root project directory, run:
```bash
go build -buildmode=plugin plugin/example.go
```
This will create a plugin `*.so` file that can be copied into your project or another well known location for usage in `golangci-lint`.
- [Go Plugin System](/plugins/module-plugins)
- [Module Plugin System](/plugins/go-plugins)

View file

@ -0,0 +1,76 @@
---
title: Go Plugin System
---
Private linters can be added through [Go's plugin system](https://pkg.go.dev/plugin).
For a private linter (which acts as a plugin) to work properly,
the plugin as well as the golangci-lint binary **needs to be built for the same environment**.
`CGO_ENABLED` is another requirement.
This means that `golangci-lint` needs to be built for whatever machine you intend to run it on
(cloning the golangci-lint repository and running a `CGO_ENABLED=1 make build` should do the trick for your machine).
## Create a Plugin
Your linter must provide one or more `golang.org/x/tools/go/analysis.Analyzer` structs.
Your project should also use `go.mod`.
All versions of libraries that overlap `golangci-lint` (including replaced libraries) MUST be set to the same version as `golangci-lint`.
You can see the versions by running `go version -m golangci-lint`.
You'll also need to create a Go file like `plugin/example.go`.
This file MUST be in the package `main`, and MUST define an exposed function called `New` with the following signature:
```go
func New(conf any) ([]*analysis.Analyzer, error) {
// ...
}
```
See [plugin/example.go](https://github.com/golangci/example-plugin-linter/blob/master/plugin/example.go) for more info.
To build the plugin, from the root project directory, run:
```bash
go build -buildmode=plugin plugin/example.go
```
This will create a plugin `*.so` file that can be copied into your project or another well known location for usage in `golangci-lint`.
## Configure a Plugin
If you already have a linter plugin available, you can follow these steps to define its usage in a projects `.golangci.yml` file.
An example linter can be found at [here](https://github.com/golangci/example-plugin-linter).
If you're looking for instructions on how to configure your own custom linter, they can be found further down.
1. If the project you want to lint does not have one already, copy the [.golangci.yml](https://github.com/golangci/golangci-lint/blob/master/.golangci.yml) to the root directory.
2. Adjust the yaml to appropriate `linters-settings.custom` entries as so:
```yaml title=.golangci.yml
linters-settings:
custom:
example:
path: /example.so
description: The description of the linter
original-url: github.com/golangci/example-linter
settings: # Settings are optional.
one: Foo
two:
- name: Bar
three:
name: Bar
```
That is all the configuration that is required to run a custom linter in your project.
Custom linters are enabled by default, but abide by the same rules as other linters.
If the disable all option is specified either on command line or in `.golang.yml` files `linters.disable-all: true`, custom linters will be disabled;
they can be re-enabled by adding them to the `linters.enable` list,
or providing the enabled option on the command line, `golangci-lint run -Eexample`.
The configuration inside the `settings` field of linter have some limitations (there are NOT related to the plugin system itself):
we use Viper to handle the configuration but Viper put all the keys in lowercase, and `.` cannot be used inside a key.

View file

@ -0,0 +1,71 @@
---
title: Module Plugin System
---
An example linter can be found at [here](https://github.com/golangci/example-plugin-module-linter/settings).
## The Automatic Way
- define your building configuration into `.custom-gcl.yml`
- run the command `golangci-lint custom` ( or `golangci-lint custom -v` to have logs)
- define the plugin inside the `linters-settings.custom` section with the type `module`.
- run your custom version of golangci-lint
Requirements:
- Go
- git
### Configuration Example
```yaml title=.custom-gcl.yml
version: v1.57.0
plugins:
# a plugin from a Go proxy
- module: 'github.com/golangci/plugin1'
import: 'github.com/golangci/plugin1/foo'
version: v1.0.0
# a plugin from local source
- module: 'github.com/golangci/plugin2'
path: /my/local/path/plugin2
```
```yaml title=.golangci.yml
linters-settings:
custom:
foo:
type: "module"
description: This is an example usage of a plugin linter.
settings:
message: hello
linters:
disable-all: true
enable:
- foo
```
## The Manual Way
- add a blank-import of your module inside `cmd/golangci-lint/plugins.go`
- run `go mod tidy`. (the module containing the plugin will be imported)
- run `make build`
- define the plugin inside the configuration `linters-settings.custom` section with the type `module`.
- run your custom version of golangci-lint
### Configuration Example
```yaml title=.golangci.yml
linters-settings:
custom:
foo:
type: "module"
description: This is an example usage of a plugin linter.
settings:
message: hello
linters:
disable-all: true
enable:
- foo
```