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,44 @@ 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+ println (errP .Error ())
91+ // fallback to the old plugin interface.
92+ analyzers , err = lookupAnalyzerPlugin (plug )
93+ if err != nil {
94+ return nil , fmt .Errorf ("lookup plugin %s: %w" , path , errors .Join (errP , err ))
95+ }
96+ }
97+
98+ return analyzers , nil
99+ }
100+
101+ func lookupPluginNew (plug * plugin.Plugin , settings any ) ([]* analysis.Analyzer , error ) {
102+ symbol , err := plug .Lookup ("New" )
103+ if err != nil {
104+ return nil , err
105+ }
106+
107+ // The type func cannot be used here, must be the explicit signature.
108+ constructor , ok := symbol .(func (any ) ([]* analysis.Analyzer , error ))
109+ if ! ok {
110+ return nil , fmt .Errorf ("plugin does not abide by 'New' function: %T" , symbol )
111+ }
112+
113+ return constructor (settings )
114+ }
115+
116+ func lookupAnalyzerPlugin (plug * plugin.Plugin ) ([]* analysis.Analyzer , error ) {
87117 symbol , err := plug .Lookup ("AnalyzerPlugin" )
88118 if err != nil {
89119 return nil , err
90120 }
91121
92122 analyzerPlugin , ok := symbol .(AnalyzerPlugin )
93123 if ! ok {
94- return nil , fmt .Errorf ("plugin %s does not abide by 'AnalyzerPlugin' interface" , path )
124+ return nil , fmt .Errorf ("plugin does not abide by 'AnalyzerPlugin' interface: %T " , symbol )
95125 }
96126
97- return analyzerPlugin , nil
127+ return analyzerPlugin . GetAnalyzers () , nil
98128}
0 commit comments