in Extractors/Go/walker.go [45:730]
func Walk(parent *etree.Element, node ast.Node, fileset *token.FileSet, info *types.Info) {
switch n := node.(type) {
// Comments and fields
// https://golang.org/pkg/go/ast/#Comment
case *ast.Comment:
commentNode := parent.CreateElement("Comment")
commentNode.CreateText(n.Text)
// A CommentGroup represents a sequence of comments with no other tokens and no empty lines between.
// https://golang.org/pkg/go/ast/#CommentGroup
case *ast.CommentGroup:
commentGroupNode := parent.CreateElement("CommentGroup")
for _, c := range n.List {
Walk(commentGroupNode, c, fileset, info)
}
addPositionStartEnd(commentGroupNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#Field
// A Field represents a Field declaration list in a struct type, a method list in an interface type,
// or a parameter/result declaration in a signature. Field.Names is nil for unnamed parameters
// (parameter lists which only contain types) and embedded struct fields. In the latter case,
// the field name is the type name.
case *ast.Field:
fieldNode := parent.CreateElement("Field")
if n.Doc != nil {
Walk(fieldNode, n.Doc, fileset, info)
}
namesNode := fieldNode.CreateElement("Names")
walkIdentList(namesNode, n.Names, fileset, info)
Walk(fieldNode, n.Type, fileset, info)
if n.Tag != nil {
Walk(fieldNode, n.Tag, fileset, info)
}
if n.Comment != nil {
Walk(fieldNode, n.Comment, fileset, info)
}
addPositionStartEnd(fieldNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#FieldList
// A FieldList represents a list of Fields, enclosed by parentheses or braces.
case *ast.FieldList:
fieldListNode := parent.CreateElement("Fields")
for _, f := range n.List {
Walk(fieldListNode, f, fileset, info)
}
addPositionStartEnd(fieldListNode, n.Pos(), n.End(), fileset)
// Expressions
// https://golang.org/pkg/go/ast/#Ident
// An Ident node represents an identifier.
case *ast.Ident:
// Nothing to do
identNode := parent.CreateElement("Ident")
identNode.CreateAttr("Name", n.Name)
identNode.CreateAttr("IsExported", strconv.FormatBool(n.IsExported()))
addTypeInformation(identNode, n, info)
addPositionStartEnd(identNode, n.Pos(), n.End(), fileset)
case *ast.BadExpr:
badExprNode := parent.CreateElement("BadExpression")
addPositionStartEnd(badExprNode, n.Pos(), n.End(), fileset)
case *ast.BasicLit:
var literalNode *etree.Element
if n.Kind == token.INT {
literalNode = parent.CreateElement("Int")
} else if n.Kind == token.FLOAT {
literalNode = parent.CreateElement("Float")
} else if n.Kind == token.IMAG {
literalNode = parent.CreateElement("Imaginary")
} else if n.Kind == token.STRING {
literalNode = parent.CreateElement("String")
} else if n.Kind == token.CHAR {
literalNode = parent.CreateElement("Char")
}
literalNode.CreateAttr("Value", stripQuotes(n.Value))
addTypeInformation(literalNode, n, info)
addPositionStartEnd(literalNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#Ellipsis
// An Ellipsis node stands for the "..." type in a parameter list or the "..." length in an array type.
case *ast.Ellipsis:
ellipsisNode := parent.CreateElement("Ellipsis")
if n.Elt != nil {
Walk(ellipsisNode, n.Elt, fileset, info)
}
addTypeInformation(ellipsisNode, n, info)
addPositionStartEnd(ellipsisNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#FuncLit
// A FuncLit node represents a function literal.
case *ast.FuncLit:
funcLitNode := parent.CreateElement("FuncLit")
Walk(funcLitNode, n.Type, fileset, info)
Walk(funcLitNode, n.Body, fileset, info)
addTypeInformation(funcLitNode, n, info)
addPositionStartEnd(funcLitNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#CompositeLit
// A CompositeLit node represents a composite literal, i.e. array of struct literals.
case *ast.CompositeLit:
compositeLiteral := parent.CreateElement("CompositeLiteral")
compositeLiteral.CreateAttr("Incomplete", strconv.FormatBool(n.Incomplete))
if n.Type != nil {
Walk(compositeLiteral, n.Type, fileset, info)
}
walkExprList(compositeLiteral, n.Elts, fileset, info)
addTypeInformation(compositeLiteral, n, info)
addPositionStartEnd(compositeLiteral, n.Pos(), n.End(), fileset)
case *ast.ParenExpr:
Walk(parent, n.X, fileset, info)
case *ast.SelectorExpr:
// https://golang.org/pkg/go/ast/#SelectorExpr
// A SelectorExpr node represents an expression followed by a selector.
selectorExprNode := parent.CreateElement("Selector")
Walk(selectorExprNode, n.X, fileset, info)
Walk(selectorExprNode, n.Sel, fileset, info)
addTypeInformation(selectorExprNode, n, info)
addPositionStartEnd(selectorExprNode, n.Pos(), n.End(), fileset)
case *ast.IndexExpr:
// https://golang.org/pkg/go/ast/#IndexExpr
// An IndexExpr node represents an expression followed by an index.
indexExprNode := parent.CreateElement("Index")
Walk(indexExprNode, n.X, fileset, info)
Walk(indexExprNode, n.Index, fileset, info)
addTypeInformation(indexExprNode, n, info)
addPositionStartEnd(indexExprNode, n.Pos(), n.End(), fileset)
case *ast.SliceExpr:
// https://golang.org/pkg/go/ast/#SliceExpr
// A SliceExpr node represents an expression followed by slice indices.
sliceExprNode := parent.CreateElement("Slice")
Walk(sliceExprNode, n.X, fileset, info)
if n.Low != nil {
Walk(sliceExprNode, n.Low, fileset, info)
}
if n.High != nil {
Walk(sliceExprNode, n.High, fileset, info)
}
if n.Max != nil {
Walk(sliceExprNode, n.Max, fileset, info)
}
addTypeInformation(sliceExprNode, n, info)
addPositionStartEnd(sliceExprNode, n.Pos(), n.End(), fileset)
case *ast.TypeAssertExpr:
// https://golang.org/pkg/go/ast/#TypeAssertExpr
// A TypeAssertExpr node represents an expression followed by a type assertion.
typeAssertExprNode := parent.CreateElement("TypeAssert")
Walk(typeAssertExprNode, n.X, fileset, info)
if n.Type != nil {
Walk(typeAssertExprNode, n.Type, fileset, info)
}
addTypeInformation(typeAssertExprNode, n, info)
addPositionStartEnd(typeAssertExprNode, n.Pos(), n.End(), fileset)
case *ast.CallExpr:
// https://golang.org/pkg/go/ast/#CallExpr
// A CallExpr node represents an expression followed by an argument list.
callExprNode := parent.CreateElement("Call")
Walk(callExprNode, n.Fun, fileset, info)
walkExprList(callExprNode, n.Args, fileset, info)
addTypeInformation(callExprNode, n, info)
addPositionStartEnd(callExprNode, n.Pos(), n.End(), fileset)
case *ast.StarExpr:
// https://golang.org/pkg/go/ast/#StarExpr
// A StarExpr node represents an expression of the form "*" Expression. Semantically it
// could be a unary "*" expression, or a pointer type.
starExprNode := parent.CreateElement("Star")
Walk(starExprNode, n.X, fileset, info)
addTypeInformation(starExprNode, n, info)
addPositionStartEnd(starExprNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#UnaryExpr
// Unary expressions
case *ast.UnaryExpr: // NOT, Xor, Address of, Receive, monadic plus and minus
var unaryExpressionKind string
if n.Op == token.AND {
unaryExpressionKind = "AddressOf"
} else if n.Op == token.SUB {
unaryExpressionKind = "UnaryMinus"
} else if n.Op == token.ADD {
unaryExpressionKind = "UnaryPlus"
} else if n.Op == token.NOT {
unaryExpressionKind = "Negation"
} else if n.Op == token.ARROW {
unaryExpressionKind = "Receive"
} else if n.Op == token.XOR {
unaryExpressionKind = "Xor"
} else {
panic("Unknown unary operator ")
}
unaryExprNode := parent.CreateElement(unaryExpressionKind)
Walk(unaryExprNode, n.X, fileset, info)
addTypeInformation(unaryExprNode, n, info)
addPositionStartEnd(unaryExprNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#BinaryExpr
// A BinaryExpr node represents a binary expression.
case *ast.BinaryExpr:
var operatorName string
switch n.Op {
case token.ADD:
operatorName = "Plus"
case token.SUB:
operatorName = "Minus"
case token.MUL:
operatorName = "Multiply"
case token.QUO:
operatorName = "Divide"
case token.REM:
operatorName = "Remainder"
case token.AND:
operatorName = "BitwiseAnd"
case token.OR:
operatorName = "BitwiseOr"
case token.XOR:
operatorName = "Xor"
case token.AND_NOT:
operatorName = "BitClear"
case token.SHL:
operatorName = "ShiftLeft"
case token.SHR:
operatorName = "ShiftRight"
case token.EQL:
operatorName = "Equal"
case token.NEQ:
operatorName = "NotEqual"
case token.LSS:
operatorName = "LessThan"
case token.LEQ:
operatorName = "LessThanOrEqual"
case token.GTR:
operatorName = "GreaterThan"
case token.GEQ:
operatorName = "GreaterThanOrEqual"
case token.LAND:
operatorName = "And"
case token.LOR:
operatorName = "Or"
default:
panic("Unknown binary operator")
}
binaryExpressionNode := parent.CreateElement(operatorName)
Walk(binaryExpressionNode, n.X, fileset, info)
Walk(binaryExpressionNode, n.Y, fileset, info)
addTypeInformation(binaryExpressionNode, n, info)
addPositionStartEnd(binaryExpressionNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#KeyValueExpr
// A KeyValueExpr node represents (key : value) pairs in composite literals.
case *ast.KeyValueExpr:
keyValuePairNode := parent.CreateElement("KeyValuePair")
Walk(keyValuePairNode, n.Key, fileset, info)
Walk(keyValuePairNode, n.Value, fileset, info)
addTypeInformation(keyValuePairNode, n, info)
addPositionStartEnd(keyValuePairNode, n.Pos(), n.End(), fileset)
// Types
// https://golang.org/pkg/go/ast/#ArrayType
// An ArrayType node represents an array or slice type.
case *ast.ArrayType:
arrayTypeNode := parent.CreateElement("ArrayType")
if n.Len != nil {
Walk(arrayTypeNode, n.Len, fileset, info)
}
Walk(arrayTypeNode, n.Elt, fileset, info)
addTypeInformation(arrayTypeNode, n, info)
addPositionStartEnd(arrayTypeNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#StructType
// A StructType node represents a struct type.
case *ast.StructType:
structTypeNode := parent.CreateElement("Struct")
structTypeNode.CreateAttr("Incomplete", strconv.FormatBool(n.Incomplete))
Walk(structTypeNode, n.Fields, fileset, info)
addTypeInformation(structTypeNode, n, info)
addPositionStartEnd(structTypeNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#FuncType
// A FuncType node represents a function type.
case *ast.FuncType:
funcTypeNode := parent.CreateElement("FuncType")
if n.Params != nil {
Walk(funcTypeNode, n.Params, fileset, info)
}
if n.Results != nil {
Walk(funcTypeNode, n.Results, fileset, info)
}
addTypeInformation(funcTypeNode, n, info)
addPositionStartEnd(funcTypeNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#InterfaceType
// An InterfaceType node represents an interface type.
case *ast.InterfaceType:
interfaceTypeNode := parent.CreateElement("InterfaceType")
Walk(interfaceTypeNode, n.Methods, fileset, info)
addTypeInformation(interfaceTypeNode, n, info)
addPositionStartEnd(interfaceTypeNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#MapType
// A MapType node represents a map type.
case *ast.MapType:
mapTypeNode := parent.CreateElement("MapType")
Walk(mapTypeNode, n.Key, fileset, info)
Walk(mapTypeNode, n.Value, fileset, info)
addTypeInformation(mapTypeNode, n, info)
addPositionStartEnd(mapTypeNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#ChanType
// A ChanType node represents a channel type.
case *ast.ChanType:
chanTypeNode := parent.CreateElement("ChanType")
Walk(parent, n.Value, fileset, info)
addTypeInformation(chanTypeNode, n, info)
addPositionStartEnd(chanTypeNode, n.Pos(), n.End(), fileset)
// Statements
case *ast.BadStmt:
badStatementNode := parent.CreateElement("BadStatement")
addPositionStartEnd(badStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#DeclStmt
// A DeclStmt node represents a declaration in a statement list.
case *ast.DeclStmt:
declStatementNode := parent.CreateElement("DeclStatement")
Walk(declStatementNode, n.Decl, fileset, info)
addPositionStartEnd(declStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#EmptyStmt
// An EmptyStmt node represents an empty statement. The "position" of the empty
// statement is the position of the immediately following (explicit or implicit) semicolon.
case *ast.EmptyStmt:
emptyStatementNode := parent.CreateElement("EmptyStatement")
addPositionStartEnd(emptyStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#LabeledStmt
// A LabeledStmt node represents a labeled statement.
case *ast.LabeledStmt:
labeledStatementNode := parent.CreateElement("LabeledStatement")
// Get the label as a string and include as attribute
labeledStatementNode.CreateAttr("Label", n.Label.Name)
Walk(labeledStatementNode, n.Stmt, fileset, info)
addPositionStartEnd(labeledStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#ExprStmt
// An ExprStmt node represents a (stand-alone) expression in a statement list.
case *ast.ExprStmt:
exprStatementNode := parent.CreateElement("ExpressionStatement")
Walk(exprStatementNode, n.X, fileset, info)
addPositionStartEnd(exprStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#SendStmt
// A SendStmt node represents a send statement.
case *ast.SendStmt:
sendStatementNode := parent.CreateElement("SendStatement")
Walk(sendStatementNode, n.Chan, fileset, info)
Walk(sendStatementNode, n.Value, fileset, info)
addPositionStartEnd(sendStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#IncDecStmt
// An IncDecStmt node represents an increment or decrement statement.
// The Tok token is either token.INC or token.DEC
case *ast.IncDecStmt:
var incDecStatementNode *etree.Element
if n.Tok == token.INC {
incDecStatementNode = parent.CreateElement("IncrementStatement")
} else {
incDecStatementNode = parent.CreateElement("DecrementStatement")
}
Walk(incDecStatementNode, n.X, fileset, info)
addPositionStartEnd(incDecStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#AssignStmt
// An AssignStmt node represents an assignment or a short variable declaration.
case *ast.AssignStmt:
assignmentStatementNode := parent.CreateElement("AssignmentStatement")
walkExprList(assignmentStatementNode, n.Lhs, fileset, info)
walkExprList(assignmentStatementNode, n.Rhs, fileset, info)
addPositionStartEnd(assignmentStatementNode, n.Pos(), n.End(), fileset)
// https://golang.org/pkg/go/ast/#GoStmt
// A GoStmt node represents a go statement.
case *ast.GoStmt:
goStatementNode := parent.CreateElement("GoStatement")
Walk(goStatementNode, n.Call, fileset, info)
addPositionStartEnd(goStatementNode, n.Pos(), n.End(), fileset)
case *ast.DeferStmt:
// https://golang.org/pkg/go/ast/#DeferStmt
// A DeferStmt node represents a defer statement.
deferStatementNode := parent.CreateElement("DeferStatement")
Walk(deferStatementNode, n.Call, fileset, info)
addPositionStartEnd(deferStatementNode, n.Pos(), n.End(), fileset)
case *ast.ReturnStmt:
// https://golang.org/pkg/go/ast/#ReturnStmt
// A ReturnStmt node represents a return statement.
returnStatementNode := parent.CreateElement("ReturnStatement")
walkExprList(returnStatementNode, n.Results, fileset, info)
addPositionStartEnd(returnStatementNode, n.Pos(), n.End(), fileset)
case *ast.BranchStmt:
// https://golang.org/pkg/go/ast/#BranchStmt
// A BranchStmt node represents a break, continue, goto, or fallthrough statement.
var branchStatementNode *etree.Element
if n.Tok == token.BREAK {
branchStatementNode = parent.CreateElement("BreakStatement")
} else if n.Tok == token.CONTINUE {
branchStatementNode = parent.CreateElement("ContinueStatement")
} else if n.Tok == token.GOTO {
branchStatementNode = parent.CreateElement("GotoStatement")
branchStatementNode.CreateAttr("Label", n.Label.Name)
} else {
branchStatementNode = parent.CreateElement("FallthroughStatement")
}
addPositionStartEnd(branchStatementNode, n.Pos(), n.End(), fileset)
case *ast.BlockStmt:
// https://golang.org/pkg/go/ast/#BlockStmt
// A BlockStmt node represents a braced statement list.
blockStatementNode := parent.CreateElement("BlockStatement")
walkStmtList(blockStatementNode, n.List, fileset, info)
addPositionStartEnd(blockStatementNode, n.Pos(), n.End(), fileset)
case *ast.IfStmt:
// https://golang.org/pkg/go/ast/#IfStmt
// An IfStmt node represents an if statement or an if else statement
ifStatementNode := parent.CreateElement("IfStatement")
if n.Init != nil {
Walk(ifStatementNode, n.Init, fileset, info)
}
Walk(ifStatementNode, n.Cond, fileset, info)
Walk(ifStatementNode, n.Body, fileset, info)
if n.Else != nil {
Walk(ifStatementNode, n.Else, fileset, info)
}
addPositionStartEnd(ifStatementNode, n.Pos(), n.End(), fileset)
case *ast.CaseClause:
// https://golang.org/pkg/go/ast/#CaseClause
// A CaseClause represents a case of an expression or type switch statement.
caseClauseNode := parent.CreateElement("CaseClause")
walkExprList(caseClauseNode, n.List, fileset, info)
walkStmtList(caseClauseNode, n.Body, fileset, info)
addPositionStartEnd(caseClauseNode, n.Pos(), n.End(), fileset)
case *ast.SwitchStmt:
// https://golang.org/pkg/go/ast/#SwitchStmt
// A SwitchStmt node represents an expression switch statement.
switchStatementNode := parent.CreateElement("SwitchStatement")
if n.Init != nil {
Walk(switchStatementNode, n.Init, fileset, info)
}
if n.Tag != nil {
Walk(switchStatementNode, n.Tag, fileset, info)
}
Walk(parent, n.Body, fileset, info)
addPositionStartEnd(switchStatementNode, n.Pos(), n.End(), fileset)
case *ast.TypeSwitchStmt:
// https://golang.org/pkg/go/ast/#TypeSwitchStmt
// A TypeSwitchStmt node represents a type switch statement.
typeSwitchStatementNode := parent.CreateElement("TypeSwitchStatement")
if n.Init != nil {
Walk(typeSwitchStatementNode, n.Init, fileset, info)
}
Walk(typeSwitchStatementNode, n.Assign, fileset, info)
Walk(typeSwitchStatementNode, n.Body, fileset, info)
addPositionStartEnd(typeSwitchStatementNode, n.Pos(), n.End(), fileset)
case *ast.CommClause:
// https://golang.org/pkg/go/ast/#CommClause
// A CommClause node represents a case of a select statement.
commClauseNode := parent.CreateElement("CommClause")
if n.Comm != nil {
Walk(commClauseNode, n.Comm, fileset, info)
}
walkStmtList(commClauseNode, n.Body, fileset, info)
addPositionStartEnd(commClauseNode, n.Pos(), n.End(), fileset)
case *ast.SelectStmt:
// https://golang.org/pkg/go/ast/#SelectStmt
// A SelectStmt node represents a select statement.
selectStatementNode := parent.CreateElement("SelectStatement")
Walk(selectStatementNode, n.Body, fileset, info)
addPositionStartEnd(selectStatementNode, n.Pos(), n.End(), fileset)
case *ast.ForStmt:
// https://golang.org/pkg/go/ast/#ForStmt
// A ForStmt represents a for statement.
forStatementNode := parent.CreateElement("ForStatement")
if n.Init != nil {
Walk(forStatementNode, n.Init, fileset, info)
}
if n.Cond != nil {
Walk(forStatementNode, n.Cond, fileset, info)
}
if n.Post != nil {
Walk(forStatementNode, n.Post, fileset, info)
}
Walk(forStatementNode, n.Body, fileset, info)
addPositionStartEnd(forStatementNode, n.Pos(), n.End(), fileset)
case *ast.RangeStmt:
// https://golang.org/pkg/go/ast/#RangeStmt
// A RangeStmt represents a for statement with a range clause.
rangeStatementNode := parent.CreateElement("RangeStatement")
if n.Key != nil {
Walk(rangeStatementNode, n.Key, fileset, info)
}
if n.Value != nil {
Walk(rangeStatementNode, n.Value, fileset, info)
}
Walk(rangeStatementNode, n.X, fileset, info)
Walk(rangeStatementNode, n.Body, fileset, info)
addPositionStartEnd(rangeStatementNode, n.Pos(), n.End(), fileset)
// Declarations
case *ast.ImportSpec:
importSpecNode := parent.CreateElement("Item")
if n.Name != nil {
importSpecNode.CreateAttr("Name", n.Name.Name)
}
importSpecNode.CreateAttr("Path", stripQuotes(n.Path.Value))
if n.Doc != nil {
Walk(importSpecNode, n.Doc, fileset, info)
}
// if n.Name != nil {
// Walk(importSpecNode, n.Name, fileset)
// }
// Walk(parent, n.Path, fileset)
if n.Comment != nil {
Walk(importSpecNode, n.Comment, fileset, info)
}
addPositionStartEnd(importSpecNode, n.Pos(), n.End(), fileset)
case *ast.ValueSpec:
// https://golang.org/pkg/go/ast/#ValueSpec
// A ValueSpec node represents a constant or variable declaration (ConstSpec or VarSpec production).
valueSpecNode := parent.CreateElement("ValueSpec")
if n.Doc != nil {
Walk(valueSpecNode, n.Doc, fileset, info)
}
walkIdentList(valueSpecNode, n.Names, fileset, info)
if n.Type != nil {
Walk(valueSpecNode, n.Type, fileset, info)
}
walkExprList(valueSpecNode, n.Values, fileset, info)
if n.Comment != nil {
Walk(valueSpecNode, n.Comment, fileset, info)
}
addPositionStartEnd(valueSpecNode, n.Pos(), n.End(), fileset)
case *ast.TypeSpec:
// https://golang.org/pkg/go/ast/#TypeSpec
// A TypeSpec node represents a type declaration (TypeSpec production).
itemNode := parent.CreateElement("Item")
itemNode.CreateAttr("Name", n.Name.Name)
if n.Doc != nil {
Walk(itemNode, n.Doc, fileset, info)
}
// Walk(itemNode, n.Name, fileset)
Walk(itemNode, n.Type, fileset, info)
if n.Comment != nil {
Walk(itemNode, n.Comment, fileset, info)
}
addPositionStartEnd(itemNode, n.Pos(), n.End(), fileset)
case *ast.BadDecl:
badDeclNode := parent.CreateElement("BadDeclaration")
addPositionStartEnd(badDeclNode, n.Pos(), n.End(), fileset)
case *ast.GenDecl:
var declkind string = ""
if n.Tok == token.IMPORT {
declkind = "Import"
} else if n.Tok == token.CONST {
declkind = "Constant"
} else if n.Tok == token.TYPE {
declkind = "Type"
} else if n.Tok == token.VAR {
declkind = "Var"
}
declNode := parent.CreateElement(declkind)
if n.Doc != nil {
Walk(declNode, n.Doc, fileset, info)
}
for _, s := range n.Specs {
Walk(declNode, s, fileset, info)
}
addPositionStartEnd(declNode, n.Pos(), n.End(), fileset)
case *ast.FuncDecl:
funcNode := parent.CreateElement("Func")
funcNode.CreateAttr("Name", n.Name.Name)
if n.Doc != nil {
Walk(funcNode, n.Doc, fileset, info)
}
if n.Recv != nil {
Walk(funcNode, n.Recv, fileset, info)
}
// Walk(funcNode, n.Name, fileset)
Walk(funcNode, n.Type, fileset, info)
if n.Body != nil {
Walk(funcNode, n.Body, fileset, info)
}
addPositionStartEnd(funcNode, n.Pos(), n.End(), fileset)
// Files and packages
case *ast.File:
fileNode := parent.CreateElement("File")
fileNode.CreateAttr("Package", n.Name.Name)
fileNode.CreateAttr("Filename", fileset.File(n.Package).Name())
file, err := os.Open(fileset.File(n.Package).Name())
if err != nil {
log.Fatal(err)
}
source, err := ioutil.ReadAll(file)
// Encode the file in Base64, since this XML implementation does not
// quote illegal characters (like <, > etc.).
encoded := base64.StdEncoding.EncodeToString([]byte(source))
fileNode.CreateAttr("Source", encoded)
defer func() {
if err = file.Close(); err != nil {
log.Fatal(err)
}
}()
if n.Doc != nil {
Walk(fileNode, n.Doc, fileset, info)
}
// Walk(parent, n.Name, fileset)
walkDeclList(fileNode, n.Decls, fileset, info)
// don't walk n.Comments - they have been
// visited already through the individual
// nodes
addPositionStartEnd(fileNode, n.Pos(), n.End(), fileset)
case *ast.Package:
packageNode := parent.CreateElement("Package")
packageNode.CreateAttr("Language", "go")
packageNode.CreateAttr("Name", n.Name)
// Do what is needed to implement type resolution.
fileRefs := []*ast.File{}
for _, v := range n.Files {
fileRefs = append(fileRefs, v)
}
conf := types.Config{Importer: importer.Default()}
conf.Check(n.Name, fileset, fileRefs, info)
for _, f := range n.Files {
Walk(packageNode, f, fileset, info)
}
addPositionStartEnd(packageNode, n.Pos(), n.End(), fileset)
default:
panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
}
}