in internal/lsp/semantic.go [284:438]
func (e *encoded) inspector(n ast.Node) bool {
pop := func() {
e.stack = e.stack[:len(e.stack)-1]
}
if n == nil {
pop()
return true
}
e.stack = append(e.stack, n)
switch x := n.(type) {
case *ast.ArrayType:
case *ast.AssignStmt:
e.token(x.TokPos, len(x.Tok.String()), tokOperator, nil)
case *ast.BasicLit:
if strings.Contains(x.Value, "\n") {
// has to be a string
e.multiline(x.Pos(), x.End(), x.Value, tokString)
break
}
ln := len(x.Value)
what := tokNumber
if x.Kind == token.STRING {
what = tokString
if _, ok := e.stack[len(e.stack)-2].(*ast.Field); ok {
// struct tags (this is probably pointless, as the
// TextMate grammar will treat all the other comments the same)
what = tokComment
}
}
e.token(x.Pos(), ln, what, nil)
case *ast.BinaryExpr:
e.token(x.OpPos, len(x.Op.String()), tokOperator, nil)
case *ast.BlockStmt:
case *ast.BranchStmt:
e.token(x.TokPos, len(x.Tok.String()), tokKeyword, nil)
// There's no semantic encoding for labels
case *ast.CallExpr:
if x.Ellipsis != token.NoPos {
e.token(x.Ellipsis, len("..."), tokOperator, nil)
}
case *ast.CaseClause:
iam := "case"
if x.List == nil {
iam = "default"
}
e.token(x.Case, len(iam), tokKeyword, nil)
case *ast.ChanType:
// chan | chan <- | <- chan
if x.Arrow == token.NoPos || x.Arrow != x.Begin {
e.token(x.Begin, len("chan"), tokKeyword, nil)
break
}
pos := e.findKeyword("chan", x.Begin+2, x.Value.Pos())
e.token(pos, len("chan"), tokKeyword, nil)
case *ast.CommClause:
iam := len("case")
if x.Comm == nil {
iam = len("default")
}
e.token(x.Case, iam, tokKeyword, nil)
case *ast.CompositeLit:
case *ast.DeclStmt:
case *ast.DeferStmt:
e.token(x.Defer, len("defer"), tokKeyword, nil)
case *ast.Ellipsis:
e.token(x.Ellipsis, len("..."), tokOperator, nil)
case *ast.EmptyStmt:
case *ast.ExprStmt:
case *ast.Field:
case *ast.FieldList:
case *ast.ForStmt:
e.token(x.For, len("for"), tokKeyword, nil)
case *ast.FuncDecl:
case *ast.FuncLit:
case *ast.FuncType:
if x.Func != token.NoPos {
e.token(x.Func, len("func"), tokKeyword, nil)
}
case *ast.GenDecl:
e.token(x.TokPos, len(x.Tok.String()), tokKeyword, nil)
case *ast.GoStmt:
e.token(x.Go, len("go"), tokKeyword, nil)
case *ast.Ident:
e.ident(x)
case *ast.IfStmt:
e.token(x.If, len("if"), tokKeyword, nil)
if x.Else != nil {
// x.Body.End() or x.Body.End()+1, not that it matters
pos := e.findKeyword("else", x.Body.End(), x.Else.Pos())
e.token(pos, len("else"), tokKeyword, nil)
}
case *ast.ImportSpec:
e.importSpec(x)
pop()
return false
case *ast.IncDecStmt:
e.token(x.TokPos, len(x.Tok.String()), tokOperator, nil)
case *ast.IndexExpr:
case *typeparams.IndexListExpr: // accomodate generics
case *ast.InterfaceType:
e.token(x.Interface, len("interface"), tokKeyword, nil)
case *ast.KeyValueExpr:
case *ast.LabeledStmt:
case *ast.MapType:
e.token(x.Map, len("map"), tokKeyword, nil)
case *ast.ParenExpr:
case *ast.RangeStmt:
e.token(x.For, len("for"), tokKeyword, nil)
// x.TokPos == token.NoPos is legal (for range foo {})
offset := x.TokPos
if offset == token.NoPos {
offset = x.For
}
pos := e.findKeyword("range", offset, x.X.Pos())
e.token(pos, len("range"), tokKeyword, nil)
case *ast.ReturnStmt:
e.token(x.Return, len("return"), tokKeyword, nil)
case *ast.SelectStmt:
e.token(x.Select, len("select"), tokKeyword, nil)
case *ast.SelectorExpr:
case *ast.SendStmt:
e.token(x.Arrow, len("<-"), tokOperator, nil)
case *ast.SliceExpr:
case *ast.StarExpr:
e.token(x.Star, len("*"), tokOperator, nil)
case *ast.StructType:
e.token(x.Struct, len("struct"), tokKeyword, nil)
case *ast.SwitchStmt:
e.token(x.Switch, len("switch"), tokKeyword, nil)
case *ast.TypeAssertExpr:
if x.Type == nil {
pos := e.findKeyword("type", x.Lparen, x.Rparen)
e.token(pos, len("type"), tokKeyword, nil)
}
case *ast.TypeSpec:
case *ast.TypeSwitchStmt:
e.token(x.Switch, len("switch"), tokKeyword, nil)
case *ast.UnaryExpr:
e.token(x.OpPos, len(x.Op.String()), tokOperator, nil)
case *ast.ValueSpec:
// things only seen with parsing or type errors, so ignore them
case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt:
return true
// not going to see these
case *ast.File, *ast.Package:
e.unexpected(fmt.Sprintf("implement %T %s", x, e.pgf.Tok.PositionFor(x.Pos(), false)))
// other things we knowingly ignore
case *ast.Comment, *ast.CommentGroup:
pop()
return false
default:
e.unexpected(fmt.Sprintf("failed to implement %T", x))
}
return true
}