11package lintersdb
22
33import (
4+ "errors"
45 "fmt"
56 "path/filepath"
67 "plugin"
@@ -45,14 +46,14 @@ func (m *Manager) WithCustomLinters() *Manager {
4546// loadCustomLinterConfig loads the configuration of private linters.
4647// Private linters are dynamically loaded from .so plugin files.
4748func (m * Manager ) loadCustomLinterConfig (name string , settings config.CustomLinterSettings ) (* linter.Config , error ) {
48- analyzer , err := m .getAnalyzerPlugin (settings .Path )
49+ analyzers , err := m .getAnalyzerPlugin (settings .Path , settings . Settings )
4950 if err != nil {
5051 return nil , err
5152 }
5253
5354 m .log .Infof ("Loaded %s: %s" , settings .Path , name )
5455
55- customLinter := goanalysis .NewLinter (name , settings .Description , analyzer . GetAnalyzers () , nil ).
56+ customLinter := goanalysis .NewLinter (name , settings .Description , analyzers , nil ).
5657 WithLoadMode (goanalysis .LoadModeTypesInfo )
5758
5859 linterConfig := linter .NewConfig (customLinter )
@@ -68,7 +69,7 @@ func (m *Manager) loadCustomLinterConfig(name string, settings config.CustomLint
6869// and returns the 'AnalyzerPlugin' interface implemented by the private plugin.
6970// An error is returned if the private linter cannot be loaded
7071// or the linter does not implement the AnalyzerPlugin interface.
71- func (m * Manager ) getAnalyzerPlugin (path string ) (AnalyzerPlugin , error ) {
72+ func (m * Manager ) getAnalyzerPlugin (path string , settings any ) ([] * analysis. Analyzer , error ) {
7273 if ! filepath .IsAbs (path ) {
7374 // resolve non-absolute paths relative to config file's directory
7475 configFilePath := viper .ConfigFileUsed ()
@@ -84,15 +85,43 @@ func (m *Manager) getAnalyzerPlugin(path string) (AnalyzerPlugin, error) {
8485 return nil , err
8586 }
8687
88+ analyzers , errP := lookupPluginNew (plug , settings )
89+ if errP != nil {
90+ // fallback to the old plugin interface.
91+ analyzers , err = lookupAnalyzerPlugin (plug )
92+ if err != nil {
93+ return nil , fmt .Errorf ("lookup plugin %s: %w" , path , errors .Join (errP , err ))
94+ }
95+ }
96+
97+ return analyzers , nil
98+ }
99+
100+ func lookupPluginNew (plug * plugin.Plugin , settings any ) ([]* analysis.Analyzer , error ) {
101+ symbol , err := plug .Lookup ("New" )
102+ if err != nil {
103+ return nil , err
104+ }
105+
106+ // The type func cannot be used here, must be the explicit signature.
107+ constructor , ok := symbol .(func (any ) ([]* analysis.Analyzer , error ))
108+ if ! ok {
109+ return nil , fmt .Errorf ("plugin does not abide by 'New' function: %T" , symbol )
110+ }
111+
112+ return constructor (settings )
113+ }
114+
115+ func lookupAnalyzerPlugin (plug * plugin.Plugin ) ([]* analysis.Analyzer , error ) {
87116 symbol , err := plug .Lookup ("AnalyzerPlugin" )
88117 if err != nil {
89118 return nil , err
90119 }
91120
92121 analyzerPlugin , ok := symbol .(AnalyzerPlugin )
93122 if ! ok {
94- return nil , fmt .Errorf ("plugin %s does not abide by 'AnalyzerPlugin' interface" , path )
123+ return nil , fmt .Errorf ("plugin does not abide by 'AnalyzerPlugin' interface: %T " , symbol )
95124 }
96125
97- return analyzerPlugin , nil
126+ return analyzerPlugin . GetAnalyzers () , nil
98127}
0 commit comments