mirror of
https://github.com/mgechev/revive.git
synced 2025-07-15 01:04:40 +02:00
refactor: moves code related to AST from rule.utils into astutils package (#1380)
Modifications summary: * Moves AST-related functions from rule/utils.go to astutils/ast_utils.go (+ modifies function calls) * Renames some of these AST-related functions * Avoids instantiating a printer config at each call to astutils.GoFmt * Uses astutils.IsIdent and astutils.IsPkgDotName when possible
This commit is contained in:
@ -2,8 +2,12 @@
|
||||
package astutils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"regexp"
|
||||
"slices"
|
||||
)
|
||||
|
||||
@ -78,9 +82,80 @@ func getFieldTypeName(typ ast.Expr) string {
|
||||
}
|
||||
}
|
||||
|
||||
// IsStringLiteral returns true if the given expression is a string literal, false otherwise
|
||||
// IsStringLiteral returns true if the given expression is a string literal, false otherwise.
|
||||
func IsStringLiteral(e ast.Expr) bool {
|
||||
sl, ok := e.(*ast.BasicLit)
|
||||
|
||||
return ok && sl.Kind == token.STRING
|
||||
}
|
||||
|
||||
// IsCgoExported returns true if the given function declaration is exported as Cgo function, false otherwise.
|
||||
func IsCgoExported(f *ast.FuncDecl) bool {
|
||||
if f.Recv != nil || f.Doc == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
cgoExport := regexp.MustCompile(fmt.Sprintf("(?m)^//export %s$", regexp.QuoteMeta(f.Name.Name)))
|
||||
for _, c := range f.Doc.List {
|
||||
if cgoExport.MatchString(c.Text) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsIdent returns true if the given expression is the identifier with name ident, false otherwise.
|
||||
func IsIdent(expr ast.Expr, ident string) bool {
|
||||
id, ok := expr.(*ast.Ident)
|
||||
return ok && id.Name == ident
|
||||
}
|
||||
|
||||
// IsPkgDotName returns true if the given expression is a selector expression of the form <pkg>.<name>, false otherwise.
|
||||
func IsPkgDotName(expr ast.Expr, pkg, name string) bool {
|
||||
sel, ok := expr.(*ast.SelectorExpr)
|
||||
return ok && IsIdent(sel.X, pkg) && IsIdent(sel.Sel, name)
|
||||
}
|
||||
|
||||
// PickNodes yields a list of nodes by picking them from a sub-ast with root node n.
|
||||
// Nodes are selected by applying the selector function
|
||||
func PickNodes(n ast.Node, selector func(n ast.Node) bool) []ast.Node {
|
||||
var result []ast.Node
|
||||
|
||||
if n == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
onSelect := func(n ast.Node) {
|
||||
result = append(result, n)
|
||||
}
|
||||
p := picker{selector: selector, onSelect: onSelect}
|
||||
ast.Walk(p, n)
|
||||
return result
|
||||
}
|
||||
|
||||
type picker struct {
|
||||
selector func(n ast.Node) bool
|
||||
onSelect func(n ast.Node)
|
||||
}
|
||||
|
||||
func (p picker) Visit(node ast.Node) ast.Visitor {
|
||||
if p.selector == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.selector(node) {
|
||||
p.onSelect(node)
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
var gofmtConfig = &printer.Config{Tabwidth: 8}
|
||||
|
||||
// GoFmt returns a string representation of an AST subtree.
|
||||
func GoFmt(x any) string {
|
||||
buf := bytes.Buffer{}
|
||||
fs := token.NewFileSet()
|
||||
gofmtConfig.Fprint(&buf, fs, x)
|
||||
return buf.String()
|
||||
}
|
||||
|
Reference in New Issue
Block a user