1
0
mirror of https://github.com/mgechev/revive.git synced 2025-10-30 23:37:49 +02:00

Initial commit

This commit is contained in:
mgechev
2017-07-04 19:37:19 +03:00
commit 891f525abc
3 changed files with 669 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
golinter

53
main.go Normal file
View File

@@ -0,0 +1,53 @@
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"github.com/mgechev/golinter/syntaxvisitor"
)
type CustomLinter struct {
syntaxvisitor.SyntaxVisitor
}
func (w *CustomLinter) VisitIdent(node *ast.Ident) {
fmt.Println("Child", node.Name)
}
// This example demonstrates how to inspect the AST of a Go program.
func ExampleInspect() {
// src is the input for which we want to inspect the AST.
src := `
package p
const c = 1.0
var X = f(3.14)*2 + c
`
// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "src.go", src, 0)
if err != nil {
panic(err)
}
var visitor CustomLinter
visitor.SyntaxVisitor.Impl = &visitor
visitor.Visit(f)
// output:
// src.go:2:9: p
// src.go:3:7: c
// src.go:3:11: 1.0
// src.go:4:5: X
// src.go:4:9: f
// src.go:4:11: 3.14
// src.go:4:17: 2
// src.go:4:21: c
}
func main() {
ExampleInspect()
}

View File

@@ -0,0 +1,615 @@
package syntaxvisitor
import (
"fmt"
"go/ast"
)
type Visitor interface {
Visit(node ast.Node)
VisitUnaryExpr(node *ast.UnaryExpr)
VisitStructType(node *ast.StructType)
VisitSendStmt(node *ast.SendStmt)
VisitReturnStmt(node *ast.ReturnStmt)
VisitArrayType(node *ast.ArrayType)
VisitAssignStmt(node *ast.AssignStmt)
VisitBasicLit(node *ast.BasicLit)
VisitBinaryExpr(node *ast.BinaryExpr)
VisitBlockStmt(node *ast.BlockStmt)
VisitFile(node *ast.File)
VisitDeclStmt(node *ast.DeclStmt)
VisitDecl(node *ast.Decl)
VisitBranchStmt(node *ast.BranchStmt)
VisitCallExpr(node *ast.CallExpr)
VisitCaseClause(node *ast.CaseClause)
VisitChanType(node *ast.ChanType)
VisitCommClause(node *ast.CommClause)
VisitComment(node *ast.Comment)
VisitCommentGroup(node *ast.CommentGroup)
VisitCompositeLit(node *ast.CompositeLit)
VisitDeferStmt(node *ast.DeferStmt)
VisitEllipsis(node *ast.Ellipsis)
VisitEmptyStmt(node *ast.EmptyStmt)
VisitExprStmt(node *ast.ExprStmt)
VisitField(node *ast.Field)
VisitFieldList(node *ast.FieldList)
VisitForStmt(node *ast.ForStmt)
VisitFuncDecl(node *ast.FuncDecl)
VisitFuncLit(node *ast.FuncLit)
VisitFuncType(node *ast.FuncType)
VisitGenDecl(node *ast.GenDecl)
VisitGoStmt(node *ast.GoStmt)
VisitIdent(node *ast.Ident)
VisitIfStmt(node *ast.IfStmt)
VisitImportSpec(node *ast.ImportSpec)
VisitIncDecStmt(node *ast.IncDecStmt)
VisitIndexExpr(node *ast.IndexExpr)
VisitInterfaceType(node *ast.InterfaceType)
VisitKeyValueExpr(node *ast.KeyValueExpr)
VisitLabeledStmt(node *ast.LabeledStmt)
VisitMapType(node *ast.MapType)
VisitParenExpr(node *ast.ParenExpr)
VisitSelectorExpr(node *ast.SelectorExpr)
VisitSliceExpr(node *ast.SliceExpr)
VisitTypeAssertExpr(node *ast.TypeAssertExpr)
VisitStarExpr(node *ast.StarExpr)
VisitSwitchStmt(node *ast.SwitchStmt)
VisitTypeSwitchStmt(node *ast.TypeSwitchStmt)
VisitSelectStmt(node *ast.SelectStmt)
VisitRangeStmt(node *ast.RangeStmt)
VisitValueSpec(node *ast.ValueSpec)
VisitTypeSpec(node *ast.TypeSpec)
VisitPackage(node *ast.Package)
VisitBadStmt(node *ast.BadStmt)
VisitBadDecl(node *ast.BadDecl)
}
type SyntaxVisitor struct {
Impl Visitor
}
func (w *SyntaxVisitor) Visit(node ast.Node) {
if node == nil {
return
}
switch x := node.(type) {
case *ast.UnaryExpr:
w.Impl.VisitUnaryExpr(x)
break
case *ast.StructType:
w.Impl.VisitStructType(x)
break
case *ast.File:
w.Impl.VisitFile(x)
break
case *ast.SendStmt:
w.Impl.VisitSendStmt(x)
break
case *ast.ReturnStmt:
w.Impl.VisitReturnStmt(x)
break
case *ast.ArrayType:
w.Impl.VisitArrayType(x)
break
case *ast.AssignStmt:
w.Impl.VisitAssignStmt(x)
break
case *ast.BasicLit:
w.Impl.VisitBasicLit(x)
break
case *ast.BinaryExpr:
w.Impl.VisitBinaryExpr(x)
break
case *ast.BlockStmt:
w.Impl.VisitBlockStmt(x)
break
case *ast.BranchStmt:
w.Impl.VisitBranchStmt(x)
break
case *ast.CallExpr:
w.Impl.VisitCallExpr(x)
break
case *ast.CaseClause:
w.Impl.VisitCaseClause(x)
break
case *ast.ChanType:
w.Impl.VisitChanType(x)
break
case *ast.CommClause:
w.Impl.VisitCommClause(x)
break
case *ast.Comment:
w.Impl.VisitComment(x)
break
case *ast.CommentGroup:
w.Impl.VisitCommentGroup(x)
break
case *ast.CompositeLit:
w.Impl.VisitCompositeLit(x)
break
case *ast.DeclStmt:
w.Impl.VisitDeclStmt(x)
break
case *ast.DeferStmt:
w.Impl.VisitDeferStmt(x)
break
case *ast.Ellipsis:
w.Impl.VisitEllipsis(x)
break
case *ast.EmptyStmt:
w.Impl.VisitEmptyStmt(x)
break
case *ast.ExprStmt:
w.Impl.VisitExprStmt(x)
break
case *ast.Field:
w.Impl.VisitField(x)
break
case *ast.FieldList:
w.Impl.VisitFieldList(x)
break
case *ast.ForStmt:
w.Impl.VisitForStmt(x)
break
case *ast.FuncDecl:
w.Impl.VisitFuncDecl(x)
break
case *ast.FuncLit:
w.Impl.VisitFuncLit(x)
break
case *ast.FuncType:
w.Impl.VisitFuncType(x)
break
case *ast.GenDecl:
w.Impl.VisitGenDecl(x)
break
case *ast.GoStmt:
w.Impl.VisitGoStmt(x)
break
case *ast.Ident:
w.Impl.VisitIdent(x)
break
case *ast.IfStmt:
w.Impl.VisitIfStmt(x)
break
case *ast.ImportSpec:
w.Impl.VisitImportSpec(x)
break
case *ast.IncDecStmt:
w.Impl.VisitIncDecStmt(x)
break
case *ast.IndexExpr:
w.Impl.VisitIndexExpr(x)
break
case *ast.InterfaceType:
w.Impl.VisitInterfaceType(x)
break
case *ast.KeyValueExpr:
w.Impl.VisitKeyValueExpr(x)
break
case *ast.LabeledStmt:
w.Impl.VisitLabeledStmt(x)
break
case *ast.MapType:
w.Impl.VisitMapType(x)
break
case *ast.ParenExpr:
w.Impl.VisitParenExpr(x)
break
case *ast.SelectorExpr:
w.Impl.VisitSelectorExpr(x)
break
case *ast.SliceExpr:
w.Impl.VisitSliceExpr(x)
break
case *ast.SwitchStmt:
w.Impl.VisitSwitchStmt(x)
break
case *ast.TypeAssertExpr:
w.Impl.VisitTypeAssertExpr(x)
break
case *ast.TypeSwitchStmt:
w.Impl.VisitTypeSwitchStmt(x)
break
case *ast.StarExpr:
w.Impl.VisitStarExpr(x)
break
case *ast.SelectStmt:
w.Impl.VisitSelectStmt(x)
break
case *ast.RangeStmt:
w.Impl.VisitRangeStmt(x)
break
case *ast.ValueSpec:
w.Impl.VisitValueSpec(x)
break
case *ast.TypeSpec:
w.Impl.VisitTypeSpec(x)
break
case *ast.Package:
w.Impl.VisitPackage(x)
break
case *ast.BadStmt:
w.Impl.VisitBadStmt(x)
break
case *ast.BadDecl:
w.Impl.VisitBadDecl(x)
break
default:
panic(fmt.Sprintf("ast.Walk: unexpected node type %T", node))
}
}
func (w *SyntaxVisitor) VisitUnaryExpr(node *ast.UnaryExpr) {
w.Impl.Visit(node.X)
}
func (w *SyntaxVisitor) VisitStructType(node *ast.StructType) {
w.Impl.Visit(node.Fields)
}
func (w *SyntaxVisitor) VisitSendStmt(node *ast.SendStmt) {
w.Impl.Visit(node.Chan)
w.Impl.Visit(node.Value)
}
func (w *SyntaxVisitor) VisitReturnStmt(node *ast.ReturnStmt) {
for _, x := range node.Results {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitArrayType(node *ast.ArrayType) {
if node.Len != nil {
w.Impl.Visit(node.Len)
}
w.Impl.Visit(node.Elt)
}
func (w *SyntaxVisitor) VisitAssignStmt(node *ast.AssignStmt) {
for _, x := range node.Lhs {
w.Impl.Visit(x)
}
for _, x := range node.Rhs {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitBasicLit(node *ast.BasicLit) {
}
func (w *SyntaxVisitor) VisitBinaryExpr(node *ast.BinaryExpr) {
w.Impl.Visit(node.X)
w.Impl.Visit(node.Y)
}
func (w *SyntaxVisitor) VisitBlockStmt(node *ast.BlockStmt) {
for _, x := range node.List {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitFile(node *ast.File) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
w.Impl.Visit(node.Name)
for _, x := range node.Decls {
w.Impl.Visit(x)
}
// don't walk n.Comments - they have been
// visited already through the individual
// nodes
}
func (w *SyntaxVisitor) VisitDeclStmt(node *ast.DeclStmt) {
w.Impl.Visit(node.Decl)
}
func (w *SyntaxVisitor) VisitDecl(node *ast.Decl) {
}
func (w *SyntaxVisitor) VisitBranchStmt(node *ast.BranchStmt) {
if node.Label != nil {
w.Impl.Visit(node.Label)
}
}
func (w *SyntaxVisitor) VisitCallExpr(node *ast.CallExpr) {
w.Impl.Visit(node.Fun)
for _, x := range node.Args {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitCaseClause(node *ast.CaseClause) {
for _, x := range node.List {
w.Impl.Visit(x)
}
for _, x := range node.Body {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitChanType(node *ast.ChanType) {
w.Impl.Visit(node.Value)
}
func (w *SyntaxVisitor) VisitCommClause(node *ast.CommClause) {
if node.Comm != nil {
w.Impl.Visit(node.Comm)
}
for _, x := range node.Body {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitComment(node *ast.Comment) {
}
func (w *SyntaxVisitor) VisitCommentGroup(node *ast.CommentGroup) {
for _, x := range node.List {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitCompositeLit(node *ast.CompositeLit) {
if node.Type != nil {
w.Impl.Visit(node.Type)
}
for _, x := range node.Elts {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitDeferStmt(node *ast.DeferStmt) {
w.Impl.Visit(node.Call)
}
func (w *SyntaxVisitor) VisitEllipsis(node *ast.Ellipsis) {
w.Impl.Visit(node.Elt)
}
func (w *SyntaxVisitor) VisitEmptyStmt(node *ast.EmptyStmt) {
}
func (w *SyntaxVisitor) VisitExprStmt(node *ast.ExprStmt) {
w.Impl.Visit(node.X)
}
func (w *SyntaxVisitor) VisitField(node *ast.Field) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
for _, x := range node.Names {
w.Impl.Visit(x)
}
w.Impl.Visit(node.Type)
if node.Tag != nil {
w.Impl.Visit(node.Tag)
}
if node.Comment != nil {
w.Impl.Visit(node.Comment)
}
}
func (w *SyntaxVisitor) VisitFieldList(node *ast.FieldList) {
for _, x := range node.List {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitForStmt(node *ast.ForStmt) {
if node.Init != nil {
w.Impl.Visit(node.Init)
}
if node.Cond != nil {
w.Impl.Visit(node.Cond)
}
if node.Post != nil {
w.Impl.Visit(node.Post)
}
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitFuncDecl(node *ast.FuncDecl) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
if node.Recv != nil {
w.Impl.Visit(node.Recv)
}
w.Impl.Visit(node.Name)
w.Impl.Visit(node.Type)
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitFuncLit(node *ast.FuncLit) {
w.Impl.Visit(node.Type)
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitFuncType(node *ast.FuncType) {
if node.Params != nil {
w.Impl.Visit(node.Params)
}
if node.Results != nil {
w.Impl.Visit(node.Results)
}
}
func (w *SyntaxVisitor) VisitGenDecl(node *ast.GenDecl) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
for _, x := range node.Specs {
w.Impl.Visit(x)
}
}
func (w *SyntaxVisitor) VisitGoStmt(node *ast.GoStmt) {
w.Impl.Visit(node.Call)
}
func (w *SyntaxVisitor) VisitIdent(node *ast.Ident) {}
func (w *SyntaxVisitor) VisitIfStmt(node *ast.IfStmt) {
if node.Init != nil {
w.Impl.Visit(node.Init)
}
w.Impl.Visit(node.Cond)
w.Impl.Visit(node.Body)
if node.Else != nil {
w.Impl.Visit(node.Else)
}
}
func (w *SyntaxVisitor) VisitImportSpec(node *ast.ImportSpec) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
if node.Name != nil {
w.Impl.Visit(node.Name)
}
w.Impl.Visit(node.Path)
if node.Comment != nil {
w.Impl.Visit(node.Comment)
}
}
func (w *SyntaxVisitor) VisitIncDecStmt(node *ast.IncDecStmt) {
w.Impl.Visit(node.X)
}
func (w *SyntaxVisitor) VisitIndexExpr(node *ast.IndexExpr) {
w.Impl.Visit(node.X)
w.Impl.Visit(node.Index)
}
func (w *SyntaxVisitor) VisitInterfaceType(node *ast.InterfaceType) {
w.Impl.Visit(node.Methods)
}
func (w *SyntaxVisitor) VisitKeyValueExpr(node *ast.KeyValueExpr) {
w.Impl.Visit(node.Key)
w.Impl.Visit(node.Value)
}
func (w *SyntaxVisitor) VisitLabeledStmt(node *ast.LabeledStmt) {
w.Impl.Visit(node.Label)
w.Impl.Visit(node.Stmt)
}
func (w *SyntaxVisitor) VisitMapType(node *ast.MapType) {
w.Impl.Visit(node.Key)
w.Impl.Visit(node.Value)
}
func (w *SyntaxVisitor) VisitParenExpr(node *ast.ParenExpr) {
w.Impl.Visit(node.X)
}
func (w *SyntaxVisitor) VisitSelectorExpr(node *ast.SelectorExpr) {
w.Impl.Visit(node.X)
w.Impl.Visit(node.Sel)
}
func (w *SyntaxVisitor) VisitSliceExpr(node *ast.SliceExpr) {
w.Impl.Visit(node.X)
if node.Low != nil {
w.Impl.Visit(node.Low)
}
if node.High != nil {
w.Impl.Visit(node.High)
}
if node.Max != nil {
w.Impl.Visit(node.Max)
}
}
func (w *SyntaxVisitor) VisitTypeAssertExpr(node *ast.TypeAssertExpr) {
w.Impl.Visit(node.X)
if node.Type != nil {
w.Impl.Visit(node.Type)
}
}
func (w *SyntaxVisitor) VisitStarExpr(node *ast.StarExpr) {
w.Impl.Visit(node.X)
}
func (w *SyntaxVisitor) VisitSwitchStmt(node *ast.SwitchStmt) {
if node.Init != nil {
w.Impl.Visit(node.Init)
}
if node.Tag != nil {
w.Impl.Visit(node.Tag)
}
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitTypeSwitchStmt(node *ast.TypeSwitchStmt) {
if node.Init != nil {
w.Impl.Visit(node.Init)
}
w.Impl.Visit(node.Assign)
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitSelectStmt(node *ast.SelectStmt) {
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitRangeStmt(node *ast.RangeStmt) {
if node.Key != nil {
w.Impl.Visit(node.Key)
}
if node.Value != nil {
w.Impl.Visit(node.Value)
}
w.Impl.Visit(node.X)
w.Impl.Visit(node.Body)
}
func (w *SyntaxVisitor) VisitValueSpec(node *ast.ValueSpec) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
for _, x := range node.Names {
w.Impl.Visit(x)
}
if node.Type != nil {
w.Impl.Visit(node.Type)
}
for _, x := range node.Values {
w.Impl.Visit(x)
}
if node.Comment != nil {
w.Impl.Visit(node.Comment)
}
}
func (w *SyntaxVisitor) VisitTypeSpec(node *ast.TypeSpec) {
if node.Doc != nil {
w.Impl.Visit(node.Doc)
}
w.Impl.Visit(node.Name)
w.Impl.Visit(node.Type)
if node.Comment != nil {
w.Impl.Visit(node.Comment)
}
}
func (w *SyntaxVisitor) VisitPackage(node *ast.Package) {
for _, f := range node.Files {
w.Impl.Visit(f)
}
}
func (w *SyntaxVisitor) VisitBadStmt(node *ast.BadStmt) {}
func (w *SyntaxVisitor) VisitBadDecl(node *ast.BadDecl) {}