mirror of
https://github.com/anchore/syft.git
synced 2025-11-17 16:33:21 +01:00
wire up settings
Signed-off-by: Will Murphy <will.murphy@anchore.com>
This commit is contained in:
parent
34f9e6fec9
commit
b00c492b0b
@ -1,7 +1,9 @@
|
|||||||
package ensuredefer
|
package ensuredefer
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/golangci/plugin-module-register/register"
|
"github.com/golangci/plugin-module-register/register"
|
||||||
"golang.org/x/tools/go/analysis"
|
"golang.org/x/tools/go/analysis"
|
||||||
@ -10,29 +12,63 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
register.Plugin("ensuredefer", func(_ any) (register.LinterPlugin, error) {
|
register.Plugin("ensuredefer", func(conf any) (register.LinterPlugin, error) {
|
||||||
return &analyzerPlugin{}, nil
|
m, ok := conf.(map[string]any)
|
||||||
})
|
if !ok {
|
||||||
}
|
return nil, fmt.Errorf("expected map[string]any but got %+v (%T)", conf, conf)
|
||||||
|
}
|
||||||
|
|
||||||
func run(pass *analysis.Pass) (any, error) {
|
var toCheck []mustDeferSymbol
|
||||||
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
symbols := m["symbols"]
|
||||||
nodeFilter := []ast.Node{
|
if symbols != nil {
|
||||||
(*ast.ExprStmt)(nil),
|
s, ok := symbols.([]any)
|
||||||
}
|
if !ok {
|
||||||
insp.Preorder(nodeFilter, func(node ast.Node) {
|
return nil, fmt.Errorf("expected slice but got %v (%T)", symbols, symbols)
|
||||||
// if we have a *ast.ExprStmt that calls internal.CloseAndLogError, report a problem.
|
}
|
||||||
// (if the function is correctly called in a defer statement, the block will have
|
for _, maybeSym := range s {
|
||||||
if t, ok := node.(*ast.ExprStmt); ok {
|
sym, ok := maybeSym.(string)
|
||||||
if !isExprStmtAllowed(t, pass) {
|
if !ok {
|
||||||
pass.Reportf(t.Pos(), "internal.CloseAndLogError must be called in defer")
|
return nil, fmt.Errorf("expect slice of string but found %v (%T)", maybeSym, maybeSym)
|
||||||
|
}
|
||||||
|
|
||||||
|
splitAt := strings.LastIndex(sym, ".")
|
||||||
|
if splitAt == -1 {
|
||||||
|
return nil, fmt.Errorf("symbols must have form example.com/some/package.SomeMethod, but got %s", sym)
|
||||||
|
}
|
||||||
|
toCheck = append(toCheck, mustDeferSymbol{
|
||||||
|
pkg: sym[:splitAt],
|
||||||
|
funName: sym[splitAt+1:],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &analyzerPlugin{
|
||||||
|
symbols: toCheck,
|
||||||
|
}, nil
|
||||||
})
|
})
|
||||||
return nil, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func isExprStmtAllowed(e *ast.ExprStmt, pass *analysis.Pass) bool {
|
func makeRun(toCheck map[string]mustDeferSymbol) func(pass *analysis.Pass) (any, error) {
|
||||||
|
return func(pass *analysis.Pass) (any, error) {
|
||||||
|
insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
|
||||||
|
nodeFilter := []ast.Node{
|
||||||
|
(*ast.ExprStmt)(nil),
|
||||||
|
}
|
||||||
|
insp.Preorder(nodeFilter, func(node ast.Node) {
|
||||||
|
// if we have a *ast.ExprStmt that calls internal.CloseAndLogError, report a problem.
|
||||||
|
// (if the function is correctly called in a defer statement, the statement will have type
|
||||||
|
// *ast.DeferStmt.)
|
||||||
|
if t, ok := node.(*ast.ExprStmt); ok {
|
||||||
|
if !isExprStmtAllowed(t, pass, toCheck) {
|
||||||
|
pass.Reportf(t.Pos(), "internal.CloseAndLogError must be called in defer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isExprStmtAllowed(e *ast.ExprStmt, pass *analysis.Pass, toCheck map[string]mustDeferSymbol) bool {
|
||||||
call, ok := e.X.(*ast.CallExpr)
|
call, ok := e.X.(*ast.CallExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return true
|
||||||
@ -41,6 +77,10 @@ func isExprStmtAllowed(e *ast.ExprStmt, pass *analysis.Pass) bool {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
candidate, ok := toCheck[sel.Sel.Name]
|
||||||
|
if !ok {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
obj := pass.TypesInfo.Uses[sel.Sel]
|
obj := pass.TypesInfo.Uses[sel.Sel]
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
@ -51,34 +91,40 @@ func isExprStmtAllowed(e *ast.ExprStmt, pass *analysis.Pass) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if pkg.Path() == "github.com/anchore/syft/internal" && sel.Sel.Name == "CloseAndLogError" {
|
if pkg.Path() == candidate.pkg && sel.Sel.Name == candidate.funName {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAnalyzer() *analysis.Analyzer {
|
type mustDeferSymbol struct {
|
||||||
analyzer := analysis.Analyzer{
|
pkg string
|
||||||
Name: "ensuredefer",
|
funName string
|
||||||
Doc: "enforce that specified functions are called in defer statements",
|
|
||||||
Run: run,
|
|
||||||
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
|
||||||
}
|
|
||||||
return &analyzer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var analyzerInstance = NewAnalyzer()
|
type analyzerPlugin struct {
|
||||||
|
symbols []mustDeferSymbol
|
||||||
type analyzerPlugin struct{}
|
}
|
||||||
|
|
||||||
func (p *analyzerPlugin) BuildAnalyzers() ([]*analysis.Analyzer, error) {
|
func (p *analyzerPlugin) BuildAnalyzers() ([]*analysis.Analyzer, error) {
|
||||||
|
analyzer := &analysis.Analyzer{
|
||||||
|
Name: "ensuredefer",
|
||||||
|
Doc: "enforce that specified functions are called in defer statements",
|
||||||
|
Requires: []*analysis.Analyzer{inspect.Analyzer},
|
||||||
|
}
|
||||||
|
|
||||||
|
callsToCheck := make(map[string]mustDeferSymbol)
|
||||||
|
for _, s := range p.symbols {
|
||||||
|
callsToCheck[s.funName] = s
|
||||||
|
}
|
||||||
|
analyzer.Run = makeRun(callsToCheck)
|
||||||
|
|
||||||
return []*analysis.Analyzer{
|
return []*analysis.Analyzer{
|
||||||
analyzerInstance,
|
analyzer,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *analyzerPlugin) GetLoadMode() string {
|
func (p *analyzerPlugin) GetLoadMode() string {
|
||||||
//TODO: what does this do
|
|
||||||
return register.LoadModeSyntax
|
return register.LoadModeSyntax
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user