59 lines
1.5 KiB
Go
59 lines
1.5 KiB
Go
// Package lintdsl provides helpers for implementing static analysis
|
||
// checks. Dot-importing this package is encouraged.
|
||
package lintdsl
|
||
|
||
import (
|
||
"bytes"
|
||
"fmt"
|
||
"go/ast"
|
||
"go/format"
|
||
|
||
"golang.org/x/tools/go/analysis"
|
||
"honnef.co/go/tools/pattern"
|
||
)
|
||
|
||
func Inspect(node ast.Node, fn func(node ast.Node) bool) {
|
||
if node == nil {
|
||
return
|
||
}
|
||
ast.Inspect(node, fn)
|
||
}
|
||
|
||
func Match(pass *analysis.Pass, q pattern.Pattern, node ast.Node) (*pattern.Matcher, bool) {
|
||
// Note that we ignore q.Relevant – callers of Match usually use
|
||
// AST inspectors that already filter on nodes we're interested
|
||
// in.
|
||
m := &pattern.Matcher{TypesInfo: pass.TypesInfo}
|
||
ok := m.Match(q.Root, node)
|
||
return m, ok
|
||
}
|
||
|
||
func MatchAndEdit(pass *analysis.Pass, before, after pattern.Pattern, node ast.Node) (*pattern.Matcher, []analysis.TextEdit, bool) {
|
||
m, ok := Match(pass, before, node)
|
||
if !ok {
|
||
return m, nil, false
|
||
}
|
||
r := pattern.NodeToAST(after.Root, m.State)
|
||
buf := &bytes.Buffer{}
|
||
format.Node(buf, pass.Fset, r)
|
||
edit := []analysis.TextEdit{{
|
||
Pos: node.Pos(),
|
||
End: node.End(),
|
||
NewText: buf.Bytes(),
|
||
}}
|
||
return m, edit, true
|
||
}
|
||
|
||
func Selector(x, sel string) *ast.SelectorExpr {
|
||
return &ast.SelectorExpr{
|
||
X: &ast.Ident{Name: x},
|
||
Sel: &ast.Ident{Name: sel},
|
||
}
|
||
}
|
||
|
||
// ExhaustiveTypeSwitch panics when called. It can be used to ensure
|
||
// that type switches are exhaustive.
|
||
func ExhaustiveTypeSwitch(v interface{}) {
|
||
panic(fmt.Sprintf("internal error: unhandled case %T", v))
|
||
}
|