I473 (#841)
Support custom linters integration by plugins Co-authored-by: Isaev Denis <idenx@yandex.com>
This commit is contained in:
parent
d3e36a97cd
commit
be3c688da4
@ -230,6 +230,18 @@ linters-settings:
|
|||||||
# Force newlines in end of case at this limit (0 = never).
|
# Force newlines in end of case at this limit (0 = never).
|
||||||
force-case-trailing-whitespace: 0
|
force-case-trailing-whitespace: 0
|
||||||
|
|
||||||
|
# The custom section can be used to define linter plugins to be loaded at runtime. See README doc
|
||||||
|
# for more info.
|
||||||
|
custom:
|
||||||
|
# Each custom linter should have a unique name.
|
||||||
|
example:
|
||||||
|
# The path to the plugin *.so. Can be absolute or local. Required for each custom linter
|
||||||
|
path: /path/to/example.so
|
||||||
|
# The description of the linter. Optional, just for documentation purposes.
|
||||||
|
description: This is an example usage of a plugin linter.
|
||||||
|
# Intended to point to the repo location of the linter. Optional, just for documentation purposes.
|
||||||
|
original-url: github.com/golangci/example-linter
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- megacheck
|
- megacheck
|
||||||
|
6
Makefile
6
Makefile
@ -108,4 +108,8 @@ go.sum: go.mod
|
|||||||
|
|
||||||
vendor: go.mod go.sum
|
vendor: go.mod go.sum
|
||||||
go mod vendor
|
go mod vendor
|
||||||
.PHONY: vendor
|
|
||||||
|
unexport GOFLAGS
|
||||||
|
vendor_free_build: FORCE
|
||||||
|
go build -o golangci-lint ./cmd/golangci-lint
|
||||||
|
.PHONY: vendor_free_build vendor
|
||||||
|
64
README.md
64
README.md
@ -834,6 +834,18 @@ linters-settings:
|
|||||||
# Force newlines in end of case at this limit (0 = never).
|
# Force newlines in end of case at this limit (0 = never).
|
||||||
force-case-trailing-whitespace: 0
|
force-case-trailing-whitespace: 0
|
||||||
|
|
||||||
|
# The custom section can be used to define linter plugins to be loaded at runtime. See README doc
|
||||||
|
# for more info.
|
||||||
|
custom:
|
||||||
|
# Each custom linter should have a unique name.
|
||||||
|
example:
|
||||||
|
# The path to the plugin *.so. Can be absolute or local. Required for each custom linter
|
||||||
|
path: /path/to/example.so
|
||||||
|
# The description of the linter. Optional, just for documentation purposes.
|
||||||
|
description: This is an example usage of a plugin linter.
|
||||||
|
# Intended to point to the repo location of the linter. Optional, just for documentation purposes.
|
||||||
|
original-url: github.com/golangci/example-linter
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
enable:
|
enable:
|
||||||
- megacheck
|
- megacheck
|
||||||
@ -1026,6 +1038,58 @@ service:
|
|||||||
- echo "here I can run custom commands, but no preparation needed for this repo"
|
- echo "here I can run custom commands, but no preparation needed for this repo"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Linters
|
||||||
|
Some people and organizations may choose to have custom made linters run as a part of golangci-lint. That functionality
|
||||||
|
is supported through go's plugin library.
|
||||||
|
|
||||||
|
### Create a Copy of `golangci-lint` that Can Run with Plugins
|
||||||
|
In order to use plugins, you'll need a golangci-lint executable that can run them. The normal version of this project
|
||||||
|
is built with the vendors option, which breaks plugins that have overlapping dependencies.
|
||||||
|
|
||||||
|
1. Download [golangci-lint](https://github.com/golangci/golangci-lint) source code
|
||||||
|
2. From the projects root directory, run `make vendor_free_build`
|
||||||
|
3. Copy the `golangci-lint` executable that was created to your path, project, or other location
|
||||||
|
|
||||||
|
### Configure Your Project for Linting
|
||||||
|
If you already have a linter plugin available, you can follow these steps to define it's 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:
|
||||||
|
```
|
||||||
|
linters-settings:
|
||||||
|
custom:
|
||||||
|
example:
|
||||||
|
path: /example.so
|
||||||
|
description: The description of the linter
|
||||||
|
original-url: github.com/golangci/example-linter
|
||||||
|
```
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
### To Create Your Own Custom Linter
|
||||||
|
|
||||||
|
Your linter must implement 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 MUST be in the package `main`, and define a
|
||||||
|
variable of name `AnalyzerPlugin`. The `AnalyzerPlugin` instance MUST implement the following interface:
|
||||||
|
```
|
||||||
|
type AnalyzerPlugin interface {
|
||||||
|
GetAnalyzers() []*analysis.Analyzer
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The type of `AnalyzerPlugin` is not important, but is by convention `type analyzerPlugin struct {}`. See
|
||||||
|
[plugin/example.go](https://github.com/golangci/example-plugin-linter/plugin/example.go) for more info.
|
||||||
|
|
||||||
|
To build the plugin, from the root project directory, run `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.
|
||||||
|
|
||||||
## False Positives
|
## False Positives
|
||||||
|
|
||||||
False positives are inevitable, but we did our best to reduce their count. For example, we have a default enabled set of [exclude patterns](#command-line-options). If a false positive occurred you have the following choices:
|
False positives are inevitable, but we did our best to reduce their count. For example, we have a default enabled set of [exclude patterns](#command-line-options). If a false positive occurred you have the following choices:
|
||||||
|
@ -455,6 +455,58 @@ than the default and have more strict settings:
|
|||||||
{{.GolangciYaml}}
|
{{.GolangciYaml}}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Custom Linters
|
||||||
|
Some people and organizations may choose to have custom made linters run as a part of golangci-lint. That functionality
|
||||||
|
is supported through go's plugin library.
|
||||||
|
|
||||||
|
### Create a Copy of `golangci-lint` that Can Run with Plugins
|
||||||
|
In order to use plugins, you'll need a golangci-lint executable that can run them. The normal version of this project
|
||||||
|
is built with the vendors option, which breaks plugins that have overlapping dependencies.
|
||||||
|
|
||||||
|
1. Download [golangci-lint](https://github.com/golangci/golangci-lint) source code
|
||||||
|
2. From the projects root directory, run `make vendor_free_build`
|
||||||
|
3. Copy the `golangci-lint` executable that was created to your path, project, or other location
|
||||||
|
|
||||||
|
### Configure Your Project for Linting
|
||||||
|
If you already have a linter plugin available, you can follow these steps to define it's 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:
|
||||||
|
```
|
||||||
|
linters-settings:
|
||||||
|
custom:
|
||||||
|
example:
|
||||||
|
path: /example.so
|
||||||
|
description: The description of the linter
|
||||||
|
original-url: github.com/golangci/example-linter
|
||||||
|
```
|
||||||
|
|
||||||
|
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`.
|
||||||
|
|
||||||
|
### To Create Your Own Custom Linter
|
||||||
|
|
||||||
|
Your linter must implement 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 MUST be in the package `main`, and define a
|
||||||
|
variable of name `AnalyzerPlugin`. The `AnalyzerPlugin` instance MUST implement the following interface:
|
||||||
|
```
|
||||||
|
type AnalyzerPlugin interface {
|
||||||
|
GetAnalyzers() []*analysis.Analyzer
|
||||||
|
}
|
||||||
|
```
|
||||||
|
The type of `AnalyzerPlugin` is not important, but is by convention `type analyzerPlugin struct {}`. See
|
||||||
|
[plugin/example.go](https://github.com/golangci/example-plugin-linter/plugin/example.go) for more info.
|
||||||
|
|
||||||
|
To build the plugin, from the root project directory, run `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.
|
||||||
|
|
||||||
## False Positives
|
## False Positives
|
||||||
|
|
||||||
False positives are inevitable, but we did our best to reduce their count. For example, we have a default enabled set of [exclude patterns](#command-line-options). If a false positive occurred you have the following choices:
|
False positives are inevitable, but we did our best to reduce their count. For example, we have a default enabled set of [exclude patterns](#command-line-options). If a false positive occurred you have the following choices:
|
||||||
|
@ -60,7 +60,7 @@ func NewExecutor(version, commit, date string) *Executor {
|
|||||||
version: version,
|
version: version,
|
||||||
commit: commit,
|
commit: commit,
|
||||||
date: date,
|
date: date,
|
||||||
DBManager: lintersdb.NewManager(nil),
|
DBManager: lintersdb.NewManager(nil, nil),
|
||||||
debugf: logutils.Debug("exec"),
|
debugf: logutils.Debug("exec"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +112,7 @@ func NewExecutor(version, commit, date string) *Executor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// recreate after getting config
|
// recreate after getting config
|
||||||
e.DBManager = lintersdb.NewManager(e.cfg)
|
e.DBManager = lintersdb.NewManager(e.cfg, e.log).WithCustomLinters()
|
||||||
|
|
||||||
e.cfg.LintersSettings.Gocritic.InferEnabledChecks(e.log)
|
e.cfg.LintersSettings.Gocritic.InferEnabledChecks(e.log)
|
||||||
if err = e.cfg.LintersSettings.Gocritic.Validate(e.log); err != nil {
|
if err = e.cfg.LintersSettings.Gocritic.Validate(e.log); err != nil {
|
||||||
|
@ -190,6 +190,8 @@ type LintersSettings struct {
|
|||||||
Godox GodoxSettings
|
Godox GodoxSettings
|
||||||
Dogsled DogsledSettings
|
Dogsled DogsledSettings
|
||||||
Gocognit GocognitSettings
|
Gocognit GocognitSettings
|
||||||
|
|
||||||
|
Custom map[string]CustomLinterSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
type GovetSettings struct {
|
type GovetSettings struct {
|
||||||
@ -301,6 +303,12 @@ var defaultLintersSettings = LintersSettings{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CustomLinterSettings struct {
|
||||||
|
Path string
|
||||||
|
Description string
|
||||||
|
OriginalURL string `mapstructure:"original-url"`
|
||||||
|
}
|
||||||
|
|
||||||
type Linters struct {
|
type Linters struct {
|
||||||
Enable []string
|
Enable []string
|
||||||
Disable []string
|
Disable []string
|
||||||
|
@ -91,7 +91,7 @@ func TestGetEnabledLintersSet(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
m := NewManager(nil)
|
m := NewManager(nil, nil)
|
||||||
es := NewEnabledSet(m, NewValidator(m), nil, nil)
|
es := NewEnabledSet(m, NewValidator(m), nil, nil)
|
||||||
for _, c := range cases {
|
for _, c := range cases {
|
||||||
c := c
|
c := c
|
||||||
|
@ -1,20 +1,28 @@
|
|||||||
package lintersdb
|
package lintersdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"plugin"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/analysis"
|
||||||
|
|
||||||
"github.com/golangci/golangci-lint/pkg/config"
|
"github.com/golangci/golangci-lint/pkg/config"
|
||||||
"github.com/golangci/golangci-lint/pkg/golinters"
|
"github.com/golangci/golangci-lint/pkg/golinters"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/golinters/goanalysis"
|
||||||
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
"github.com/golangci/golangci-lint/pkg/lint/linter"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/logutils"
|
||||||
|
"github.com/golangci/golangci-lint/pkg/report"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
nameToLCs map[string][]*linter.Config
|
nameToLCs map[string][]*linter.Config
|
||||||
cfg *config.Config
|
cfg *config.Config
|
||||||
|
log logutils.Log
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(cfg *config.Config) *Manager {
|
func NewManager(cfg *config.Config, log logutils.Log) *Manager {
|
||||||
m := &Manager{cfg: cfg}
|
m := &Manager{cfg: cfg, log: log}
|
||||||
nameToLCs := make(map[string][]*linter.Config)
|
nameToLCs := make(map[string][]*linter.Config)
|
||||||
for _, lc := range m.GetAllSupportedLinterConfigs() {
|
for _, lc := range m.GetAllSupportedLinterConfigs() {
|
||||||
for _, name := range lc.AllNames() {
|
for _, name := range lc.AllNames() {
|
||||||
@ -26,6 +34,27 @@ func NewManager(cfg *config.Config) *Manager {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Manager) WithCustomLinters() *Manager {
|
||||||
|
if m.log == nil {
|
||||||
|
m.log = report.NewLogWrapper(logutils.NewStderrLog(""), &report.Data{})
|
||||||
|
}
|
||||||
|
if m.cfg != nil {
|
||||||
|
for name, settings := range m.cfg.LintersSettings.Custom {
|
||||||
|
lc, err := m.loadCustomLinterConfig(name, settings)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
m.log.Errorf("Unable to load custom analyzer %s:%s, %v",
|
||||||
|
name,
|
||||||
|
settings.Path,
|
||||||
|
err)
|
||||||
|
} else {
|
||||||
|
m.nameToLCs[name] = append(m.nameToLCs[name], lc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
func (Manager) AllPresets() []string {
|
func (Manager) AllPresets() []string {
|
||||||
return []string{linter.PresetBugs, linter.PresetComplexity, linter.PresetFormatting,
|
return []string{linter.PresetBugs, linter.PresetComplexity, linter.PresetFormatting,
|
||||||
linter.PresetPerformance, linter.PresetStyle, linter.PresetUnused}
|
linter.PresetPerformance, linter.PresetStyle, linter.PresetUnused}
|
||||||
@ -267,3 +296,44 @@ func (m Manager) GetAllLinterConfigsForPreset(p string) []*linter.Config {
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m Manager) loadCustomLinterConfig(name string, settings config.CustomLinterSettings) (*linter.Config, error) {
|
||||||
|
analyzer, err := m.getAnalyzerPlugin(settings.Path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
m.log.Infof("Loaded %s: %s", settings.Path, name)
|
||||||
|
customLinter := goanalysis.NewLinter(
|
||||||
|
name,
|
||||||
|
settings.Description,
|
||||||
|
analyzer.GetAnalyzers(),
|
||||||
|
nil).WithLoadMode(goanalysis.LoadModeTypesInfo)
|
||||||
|
linterConfig := linter.NewConfig(customLinter)
|
||||||
|
linterConfig.EnabledByDefault = true
|
||||||
|
linterConfig.IsSlow = false
|
||||||
|
linterConfig.WithURL(settings.OriginalURL)
|
||||||
|
return linterConfig, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AnalyzerPlugin interface {
|
||||||
|
GetAnalyzers() []*analysis.Analyzer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) {
|
||||||
|
plug, err := plugin.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
symbol, err := plug.Lookup("AnalyzerPlugin")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
analyzerPlugin, ok := symbol.(AnalyzerPlugin)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("plugin %s does not abide by 'AnalyzerPlugin' interface", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return analyzerPlugin, nil
|
||||||
|
}
|
||||||
|
@ -31,7 +31,7 @@ func newNolint2FileIssue(line int) result.Issue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newTestNolintProcessor(log logutils.Log) *Nolint {
|
func newTestNolintProcessor(log logutils.Log) *Nolint {
|
||||||
return NewNolint(log, lintersdb.NewManager(nil))
|
return NewNolint(log, lintersdb.NewManager(nil, nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getMockLog() *logutils.MockLog {
|
func getMockLog() *logutils.MockLog {
|
||||||
|
@ -114,7 +114,7 @@ func buildTemplateContext() (map[string]interface{}, error) {
|
|||||||
|
|
||||||
func getLintersListMarkdown(enabled bool) string {
|
func getLintersListMarkdown(enabled bool) string {
|
||||||
var neededLcs []*linter.Config
|
var neededLcs []*linter.Config
|
||||||
lcs := lintersdb.NewManager(nil).GetAllSupportedLinterConfigs()
|
lcs := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs()
|
||||||
for _, lc := range lcs {
|
for _, lc := range lcs {
|
||||||
if lc.EnabledByDefault == enabled {
|
if lc.EnabledByDefault == enabled {
|
||||||
neededLcs = append(neededLcs, lc)
|
neededLcs = append(neededLcs, lc)
|
||||||
@ -139,7 +139,7 @@ func getLintersListMarkdown(enabled bool) string {
|
|||||||
func getThanksList() string {
|
func getThanksList() string {
|
||||||
var lines []string
|
var lines []string
|
||||||
addedAuthors := map[string]bool{}
|
addedAuthors := map[string]bool{}
|
||||||
for _, lc := range lintersdb.NewManager(nil).GetAllSupportedLinterConfigs() {
|
for _, lc := range lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs() {
|
||||||
if lc.OriginalURL == "" {
|
if lc.OriginalURL == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ func inSlice(s []string, v string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getEnabledByDefaultFastLintersExcept(except ...string) []string {
|
func getEnabledByDefaultFastLintersExcept(except ...string) []string {
|
||||||
m := lintersdb.NewManager(nil)
|
m := lintersdb.NewManager(nil, nil)
|
||||||
ebdl := m.GetAllEnabledByDefaultLinters()
|
ebdl := m.GetAllEnabledByDefaultLinters()
|
||||||
ret := []string{}
|
ret := []string{}
|
||||||
for _, lc := range ebdl {
|
for _, lc := range ebdl {
|
||||||
@ -38,7 +38,7 @@ func getEnabledByDefaultFastLintersExcept(except ...string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getAllFastLintersWith(with ...string) []string {
|
func getAllFastLintersWith(with ...string) []string {
|
||||||
linters := lintersdb.NewManager(nil).GetAllSupportedLinterConfigs()
|
linters := lintersdb.NewManager(nil, nil).GetAllSupportedLinterConfigs()
|
||||||
ret := append([]string{}, with...)
|
ret := append([]string{}, with...)
|
||||||
for _, lc := range linters {
|
for _, lc := range linters {
|
||||||
if lc.IsSlowLinter() {
|
if lc.IsSlowLinter() {
|
||||||
@ -51,7 +51,7 @@ func getAllFastLintersWith(with ...string) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getEnabledByDefaultLinters() []string {
|
func getEnabledByDefaultLinters() []string {
|
||||||
ebdl := lintersdb.NewManager(nil).GetAllEnabledByDefaultLinters()
|
ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters()
|
||||||
ret := []string{}
|
ret := []string{}
|
||||||
for _, lc := range ebdl {
|
for _, lc := range ebdl {
|
||||||
ret = append(ret, lc.Name())
|
ret = append(ret, lc.Name())
|
||||||
@ -61,7 +61,7 @@ func getEnabledByDefaultLinters() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getEnabledByDefaultFastLintersWith(with ...string) []string {
|
func getEnabledByDefaultFastLintersWith(with ...string) []string {
|
||||||
ebdl := lintersdb.NewManager(nil).GetAllEnabledByDefaultLinters()
|
ebdl := lintersdb.NewManager(nil, nil).GetAllEnabledByDefaultLinters()
|
||||||
ret := append([]string{}, with...)
|
ret := append([]string{}, with...)
|
||||||
for _, lc := range ebdl {
|
for _, lc := range ebdl {
|
||||||
if lc.IsSlowLinter() {
|
if lc.IsSlowLinter() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user