Skip to content

Commit

Permalink
feat: allow to use settings for plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
ldez committed Jun 4, 2023
1 parent ab78b2f commit d828ce1
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 7 deletions.
2 changes: 1 addition & 1 deletion go.mod
@@ -1,6 +1,6 @@
module github.com/golangci/golangci-lint

go 1.19
go 1.20

require (
4d63.com/gocheckcompilerdirectives v1.2.1
Expand Down
5 changes: 4 additions & 1 deletion pkg/config/linters_settings.go
Expand Up @@ -828,6 +828,9 @@ type CustomLinterSettings struct {
Path string
// Description describes the purpose of the private linter.
Description string
// The URL containing the source code for the private linter.
// OriginalURL The URL containing the source code for the private linter.
OriginalURL string `mapstructure:"original-url"`

// Settings plugin settings only work with linterdb.PluginConstructor symbol.
Settings any
}
40 changes: 35 additions & 5 deletions pkg/lint/lintersdb/custom_linters.go
@@ -1,6 +1,7 @@
package lintersdb

import (
"errors"
"fmt"
"path/filepath"
"plugin"
Expand Down Expand Up @@ -45,14 +46,14 @@ func (m *Manager) WithCustomLinters() *Manager {
// loadCustomLinterConfig loads the configuration of private linters.
// Private linters are dynamically loaded from .so plugin files.
func (m *Manager) loadCustomLinterConfig(name string, settings config.CustomLinterSettings) (*linter.Config, error) {
analyzer, err := m.getAnalyzerPlugin(settings.Path)
analyzers, err := m.getAnalyzerPlugin(settings.Path, settings.Settings)
if err != nil {
return nil, err
}

m.log.Infof("Loaded %s: %s", settings.Path, name)

customLinter := goanalysis.NewLinter(name, settings.Description, analyzer.GetAnalyzers(), nil).
customLinter := goanalysis.NewLinter(name, settings.Description, analyzers, nil).
WithLoadMode(goanalysis.LoadModeTypesInfo)

linterConfig := linter.NewConfig(customLinter)
Expand All @@ -68,7 +69,7 @@ func (m *Manager) loadCustomLinterConfig(name string, settings config.CustomLint
// and returns the 'AnalyzerPlugin' interface implemented by the private plugin.
// An error is returned if the private linter cannot be loaded
// or the linter does not implement the AnalyzerPlugin interface.
func (m *Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) {
func (m *Manager) getAnalyzerPlugin(path string, settings any) ([]*analysis.Analyzer, error) {
if !filepath.IsAbs(path) {
// resolve non-absolute paths relative to config file's directory
configFilePath := viper.ConfigFileUsed()
Expand All @@ -84,15 +85,44 @@ func (m *Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) {
return nil, err
}

analyzers, errP := lookupPluginNew(plug, settings)
if errP != nil {
println(errP.Error())
// fallback to the old plugin interface.
analyzers, err = lookupAnalyzerPlugin(plug)
if err != nil {
return nil, fmt.Errorf("lookup plugin %s: %w", path, errors.Join(errP, err))

Check failure on line 94 in pkg/lint/lintersdb/custom_linters.go

View workflow job for this annotation

GitHub Actions / tests-on-unix (1.19)

undefined: errors.Join
}
}

return analyzers, nil
}

func lookupPluginNew(plug *plugin.Plugin, settings any) ([]*analysis.Analyzer, error) {
symbol, err := plug.Lookup("New")
if err != nil {
return nil, err
}

// The type func cannot be used here, must be the explicit signature.
constructor, ok := symbol.(func(any) ([]*analysis.Analyzer, error))
if !ok {
return nil, fmt.Errorf("plugin does not abide by 'New' function: %T", symbol)
}

return constructor(settings)
}

func lookupAnalyzerPlugin(plug *plugin.Plugin) ([]*analysis.Analyzer, error) {
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 nil, fmt.Errorf("plugin does not abide by 'AnalyzerPlugin' interface: %T", symbol)
}

return analyzerPlugin, nil
return analyzerPlugin.GetAnalyzers(), nil
}

0 comments on commit d828ce1

Please sign in to comment.