/*
* Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.tvl.goworks.editor.go.semantics;
import java.math.BigInteger;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.antlr.netbeans.editor.text.VersionedDocument;
import org.antlr.netbeans.semantics.ObjectDecorator;
import org.antlr.netbeans.semantics.ObjectProperty;
import org.antlr.v4.runtime.Dependents;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RuleDependencies;
import org.antlr.v4.runtime.RuleDependency;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.antlr.v4.runtime.tree.TerminalNode;
import org.antlr.v4.runtime.tree.Tree;
import org.antlr.works.editor.antlr4.parsing.ParseTrees;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.project.FileOwnerQuery;
import org.netbeans.api.project.Project;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Parameters;
import org.tvl.goworks.editor.go.codemodel.ChannelKind;
import org.tvl.goworks.editor.go.codemodel.CodeElementModel;
import org.tvl.goworks.editor.go.codemodel.ConstModel;
import org.tvl.goworks.editor.go.codemodel.FunctionModel;
import org.tvl.goworks.editor.go.codemodel.IntrinsicTypeModels;
import org.tvl.goworks.editor.go.codemodel.PackageModel;
import org.tvl.goworks.editor.go.codemodel.TypeKind;
import org.tvl.goworks.editor.go.codemodel.TypeModel;
import org.tvl.goworks.editor.go.codemodel.VarKind;
import org.tvl.goworks.editor.go.codemodel.VarModel;
import org.tvl.goworks.editor.go.codemodel.impl.CodeModelCacheImpl;
import org.tvl.goworks.editor.go.codemodel.impl.TypeArrayModelImpl;
import org.tvl.goworks.editor.go.codemodel.impl.TypeChannelModelImpl;
import org.tvl.goworks.editor.go.codemodel.impl.TypeMapModelImpl;
import org.tvl.goworks.editor.go.codemodel.impl.TypeModelImpl;
import org.tvl.goworks.editor.go.codemodel.impl.TypePointerModelImpl;
import org.tvl.goworks.editor.go.codemodel.impl.TypeSliceModelImpl;
import org.tvl.goworks.editor.go.highlighter.SemanticHighlighter;
import org.tvl.goworks.editor.go.parser.GoParser;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.AddAssignOpContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.AddExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.AndExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.AnonymousFieldContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ArgumentListContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ArrayLengthContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ArrayTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.AssignOpContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.AssignmentContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BaseTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BaseTypeNameContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BasicLiteralContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BlockContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BodyContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BreakStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BuiltinArgsContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BuiltinCallContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.BuiltinCallExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.CallExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ChannelContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ChannelTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.CommCaseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.CommClauseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.CompareExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.CompositeLiteralContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ConditionContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ConstDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ConstSpecContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ContinueStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ConversionContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ConversionOrCallExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.DeclarationContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.DeferStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ElementContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ElementListContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ElementNameOrIndexContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ElementTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.EmptyStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ExprCaseClauseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ExprSwitchCaseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ExprSwitchStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ExpressionContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ExpressionListContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ExpressionStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.FallthroughStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.FieldDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ForClauseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ForStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.FunctionDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.FunctionLiteralContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.FunctionTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.GoStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.GotoStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.IdentifierListContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.IfStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ImportDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ImportPathContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ImportSpecContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.IncDecStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.IndexExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.InitStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.InterfaceTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.InterfaceTypeNameContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.KeyContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.KeyTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.LabelContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.LabeledStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.LiteralContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.LiteralTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.LiteralValueContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MapTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MethodDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MethodExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MethodNameContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MethodSpecContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MulAssignOpContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.MultExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.OperandContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.OperandExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.OrExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.PackageClauseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.PackageNameContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ParameterDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ParameterListContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ParametersContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.PointerTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.PostStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.QualifiedIdentifierContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.RangeClauseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ReceiverContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ReceiverTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.RecvExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.RecvStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ResultContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ReturnStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SelectStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SelectorExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SendStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ShortVarDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SignatureContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SimpleStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SliceExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SliceTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SourceFileBodyContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SourceFileContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.StatementContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.StructTypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.SwitchStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TagContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TopLevelDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeAssertionExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeCaseClauseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeListContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeLiteralContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeNameContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeSpecContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeSwitchCaseContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeSwitchGuardContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.TypeSwitchStmtContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.UnaryExprContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.ValueContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.VarDeclContext;
import org.tvl.goworks.editor.go.parser.generated.AbstractGoParser.VarSpecContext;
import org.tvl.goworks.editor.go.parser.generated.GoParserBaseListener;
import org.tvl.goworks.editor.go.parser.generated.GoParserListener;
import org.tvl.goworks.project.GoProject;
/* TODO for QUALIFIED_EXPR and UNQUALIFIED_LINK
* +qualifiedIdentifier
* +typeName
* operand
* type
* literalType
* interfaceTypeName?
* receiverType?
* -anonymousField?
*/
/*
* CODE_TYPE should be valid for the following types
*/
/**
* Summary of required attributes.
*
* Need to specify {@link GoAnnotations#VAR_TYPE} for the following:
* - varSpec.idList
* - shortVarDecl.idList
* - parameterDecl.idList
*
* Need to specify {@link GoAnnotations#GLOBAL} for the following:
* - constSpec.idList
*
* Need to specify {@link GoAnnotations#BUILTIN} for the following:
* - function, var, and const references
*
* @author Sam Harwell
*/
public class SemanticAnalyzerListener implements GoParserListener {
private static final Logger LOGGER = Logger.getLogger(SemanticAnalyzerListener.class.getName());
@NonNull
private final VersionedDocument document;
@NonNull
private final GoAnnotatedParseTree annotatedParseTree;
@NonNull
private final ObjectDecorator<Tree> treeDecorator;
private final Deque<Map<String, TerminalNode>> visibleLocals = new ArrayDeque<>();
private final Deque<Map<String, TerminalNode>> visibleConstants = new ArrayDeque<>();
private final Deque<Map<String, TerminalNode>> visibleFunctions = new ArrayDeque<>();
private final Deque<Map<String, TerminalNode>> visibleTypes = new ArrayDeque<>();
private final Deque<Map<String, TerminalNode>> pendingVisibleLocals = new ArrayDeque<>();
private final Deque<Map<String, TerminalNode>> pendingVisibleConstants = new ArrayDeque<>();
private final List<TerminalNode> unresolvedIdentifiers = new ArrayList<>();
private final List<TerminalNode> unresolvedQualifiedIdentifiers = new ArrayList<>();
// label references are resolved at the end of a function
private final Deque<Map<String, TerminalNode>> visibleLabels = new ArrayDeque<>();
private final Deque<Collection<TerminalNode>> unresolvedLabels = new ArrayDeque<>();
private final Map<String, List<TerminalNode>> importedPackages = new HashMap<>();
private BigInteger _iota = BigInteger.ZERO;
public SemanticAnalyzerListener(@NonNull VersionedDocument document, @NonNull GoAnnotatedParseTree annotatedParseTree) {
Parameters.notNull("document", document);
Parameters.notNull("annotatedParseTree", annotatedParseTree);
this.document = document;
this.annotatedParseTree = annotatedParseTree;
this.treeDecorator = annotatedParseTree.getTreeDecorator();
pushVarScope();
}
public void resolveReferences() {
CodeModelCacheImpl codeModelCache = CodeModelCacheImpl.getInstance();
Project project = FileOwnerQuery.getOwner(document.getFileObject());
if (!(project instanceof GoProject)) {
throw new UnsupportedOperationException("Unsupported project type.");
}
String currentPackagePath = getCurrentPackagePath((GoProject)project, document);
PackageModel currentPackage = codeModelCache.getUniquePackage((GoProject)project, currentPackagePath);
Map<String, Collection<PackageModel>> resolvedPackages = new HashMap<>();
for (Map.Entry<String, List<TerminalNode>> entry : importedPackages.entrySet()) {
Collection<PackageModel> packages = resolvedPackages.get(entry.getKey());
if (packages == null) {
packages = new ArrayList<>();
resolvedPackages.put(entry.getKey(), packages);
}
for (TerminalNode importToken : entry.getValue()) {
Collection<? extends CodeElementModel> resolved = treeDecorator.getProperty(importToken, GoAnnotations.MODELS);
for (CodeElementModel model : resolved) {
if (!(model instanceof PackageModel)) {
continue;
}
packages.add((PackageModel)model);
}
}
}
for (TerminalNode node : unresolvedIdentifiers) {
resolveIdentifier(node, currentPackage, resolvedPackages);
}
boolean updatedResolution;
do {
updatedResolution = false;
for (TerminalNode node : unresolvedQualifiedIdentifiers) {
try {
updatedResolution |= resolveQualifiedIdentifier(node, currentPackage, resolvedPackages);
} catch (RuntimeException | Error ex) {
LOGGER.log(Level.FINE, String.format("An exception occurred while resolving a qualified identifier '%s'", node.getSymbol()), ex);
}
}
} while (updatedResolution);
}
private static String getCurrentPackagePath(GoProject project, VersionedDocument document) {
FileObject documentFileObject = document.getFileObject();
FileObject packageFolder = documentFileObject != null ? documentFileObject.getParent() : null;
FileObject sourceRoot = project != null ? project.getSourceRoot() : null;
String packagePath;
if (sourceRoot != null) {
packagePath = FileUtil.getRelativePath(sourceRoot, packageFolder);
} else {
packagePath = packageFolder.getNameExt();
}
return packagePath;
}
private void resolveIdentifier(TerminalNode node,
PackageModel currentPackage,
Map<String, ? extends Collection<? extends PackageModel>> importedPackages) {
// check again for a top-level definition in the current file
Token token = node.getSymbol();
TerminalNode target = getVisibleDeclaration(node);
if (target != null) {
boolean resolved = true;
switch (treeDecorator.getProperty(target, GoAnnotations.NODE_TYPE)) {
case CONST_DECL:
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
break;
case VAR_DECL:
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, NodeType.VAR_REF);
break;
case FUNC_DECL:
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, NodeType.FUNC_REF);
break;
case TYPE_DECL:
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, NodeType.TYPE_REF);
break;
default:
resolved = false;
break;
}
treeDecorator.putProperty(node, GoAnnotations.LOCAL_TARGET, target);
if (resolved) {
treeDecorator.putProperty(node, GoAnnotations.RESOLVED, true);
}
VarKind varType = treeDecorator.getProperty(target, GoAnnotations.VAR_TYPE);
if (varType != VarKind.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.VAR_TYPE, varType);
}
TypeKind typeKind = treeDecorator.getProperty(target, GoAnnotations.TYPE_KIND);
if (typeKind != TypeKind.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.TYPE_KIND, typeKind);
}
if (treeDecorator.getProperty(target, GoAnnotations.GLOBAL)) {
treeDecorator.putProperty(node, GoAnnotations.GLOBAL, true);
}
return;
}
// try to resolve the element in the current package
if (currentPackage != null) {
if (resolveIdentifier(node, currentPackage)) {
return;
}
}
// check packages with alias '.'
Collection<? extends PackageModel> mergedPackages = importedPackages.get("");
if (mergedPackages != null) {
for (PackageModel model : mergedPackages) {
if (resolveIdentifier(node, model)) {
return;
}
}
}
}
private boolean resolveIdentifier(TerminalNode node, PackageModel packageModel) {
Token token = node.getSymbol();
Collection<? extends CodeElementModel> members = packageModel.getMembers(token.getText());
for (CodeElementModel model : members) {
NodeType nodeType = NodeType.UNDEFINED;
VarKind varType = VarKind.UNDEFINED;
TypeKind typeKind = TypeKind.UNDEFINED;
boolean global = true;
boolean resolved = true;
if (model instanceof ConstModel) {
nodeType = NodeType.CONST_REF;
} else if (model instanceof VarModel) {
nodeType = NodeType.VAR_REF;
varType = VarKind.GLOBAL;
} else if (model instanceof TypeModel) {
nodeType = NodeType.TYPE_REF;
typeKind = ((TypeModel)model).getKind();
} else if (model instanceof FunctionModel) {
nodeType = NodeType.FUNC_REF;
} else {
resolved = false;
}
if (nodeType != NodeType.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, nodeType);
}
if (resolved) {
treeDecorator.putProperty(node, GoAnnotations.RESOLVED, true);
}
if (varType != VarKind.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.VAR_TYPE, varType);
}
if (typeKind != TypeKind.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.TYPE_KIND, typeKind);
}
treeDecorator.putProperty(node, GoAnnotations.GLOBAL, true);
treeDecorator.putProperty(node, GoAnnotations.MODELS, members);
return true;
}
return false;
}
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageName, version=0)
private boolean resolveQualifiedIdentifier(TerminalNode node, PackageModel currentPackage, Map<String, Collection<PackageModel>> resolvedPackages) {
Token token = node.getSymbol();
if (treeDecorator.getProperty(node, GoAnnotations.NODE_TYPE) != NodeType.UNDEFINED) {
// already resolved
return false;
}
ParserRuleContext qualifier = treeDecorator.getProperty(node, GoAnnotations.QUALIFIER);
if (qualifier == null) {
// don't have the information necessary to resolve
return false;
}
Collection<? extends CodeElementModel> resolvedQualifier = treeDecorator.getProperty(qualifier, GoAnnotations.MODELS);
if (resolvedQualifier == null) {
CodeElementReference qualifierCodeClass = treeDecorator.getProperty(qualifier, GoAnnotations.CODE_CLASS);
assert qualifierCodeClass != null;
if (qualifierCodeClass != CodeElementReference.MISSING) {
resolvedQualifier = qualifierCodeClass.resolve(annotatedParseTree, currentPackage, resolvedPackages);
}
}
if (resolvedQualifier == null) {
CodeElementReference qualifierExprType = treeDecorator.getProperty(qualifier, GoAnnotations.EXPR_TYPE);
assert qualifierExprType != null;
if (qualifierExprType != CodeElementReference.MISSING) {
resolvedQualifier = qualifierExprType.resolve(annotatedParseTree, currentPackage, resolvedPackages);
}
}
if (resolvedQualifier == null) {
NodeType qualifierNodeType = treeDecorator.getProperty(qualifier, GoAnnotations.NODE_TYPE);
if (qualifierNodeType == NodeType.UNDEFINED) {
if (treeDecorator.getProperty(qualifier, GoAnnotations.QUALIFIED_EXPR)) {
// haven't resolved the qualifier, which is itself a qualified expression
return false;
}
TerminalNode unqualifiedLink = treeDecorator.getProperty(qualifier, GoAnnotations.UNQUALIFIED_LINK);
if (unqualifiedLink != null) {
Map<? extends ObjectProperty<?>, ?> properties = treeDecorator.getProperties(unqualifiedLink);
treeDecorator.putProperties(qualifier, properties);
qualifierNodeType = treeDecorator.getProperty(qualifier, GoAnnotations.NODE_TYPE);
if (qualifierNodeType == NodeType.UNDEFINED) {
treeDecorator.putProperty(qualifier, GoAnnotations.NODE_TYPE, NodeType.UNKNOWN);
qualifierNodeType = NodeType.UNKNOWN;
}
} else {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, "Unable to resolve unqualified link from qualifier: {0}", qualifier.toString(Arrays.asList(GoParser.ruleNames)));
}
qualifierNodeType = NodeType.UNKNOWN;
}
}
assert qualifierNodeType != NodeType.UNDEFINED;
if (qualifierNodeType == NodeType.UNKNOWN) {
// can't resolve a dereference if the qualifier couldn't be resolved
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, NodeType.UNKNOWN);
return true;
}
if (qualifierNodeType == NodeType.TYPE_LITERAL) {
return resolveQualifierType(qualifier, currentPackage, resolvedPackages);
} else if (qualifierNodeType == NodeType.PACKAGE_REF) {
assert qualifier instanceof PackageNameContext;
String packageName = ((PackageNameContext)qualifier).IDENTIFIER().getSymbol().getText();
resolvedQualifier = resolvedPackages.get(packageName);
if (resolvedQualifier == null) {
resolvedQualifier = Collections.emptyList();
}
} else if (qualifierNodeType == NodeType.VAR_REF) {
// must be referring to something within the current file since it's resolved internally
TerminalNode target = treeDecorator.getProperty(qualifier, GoAnnotations.LOCAL_TARGET);
assert target != null && treeDecorator.getProperty(target, GoAnnotations.NODE_TYPE) == NodeType.VAR_DECL;
ParserRuleContext explicitType = treeDecorator.getProperty(qualifier, GoAnnotations.EXPLICIT_TYPE);
if (explicitType == null && target != null) {
explicitType = treeDecorator.getProperty(target, GoAnnotations.EXPLICIT_TYPE);
}
if (explicitType != null) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, "Unable to resolve explicit type for qualifier: {0}", qualifier.toString(Arrays.asList(GoParser.ruleNames)));
}
resolvedQualifier = Collections.emptyList();
} else {
ParserRuleContext implicitType = target != null ? treeDecorator.getProperty(target, GoAnnotations.IMPLICIT_TYPE) : null;
int implicitIndex = target != null ? treeDecorator.getProperty(target, GoAnnotations.IMPLICIT_INDEX) : -1;
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, "Unable to resolve implicit type for qualifier: {0}", qualifier.toString(Arrays.asList(GoParser.ruleNames)));
}
resolvedQualifier = Collections.emptyList();
}
} else {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING, "Unable to resolve qualifier: {0}", qualifier.toString(Arrays.asList(GoParser.ruleNames)));
}
resolvedQualifier = Collections.emptyList();
}
}
assert resolvedQualifier != null;
if (resolvedQualifier == null) {
LOGGER.log(Level.WARNING, "Should not have a null resolved qualifier at this point.");
resolvedQualifier = Collections.emptyList();
}
String nameText = token.getText();
List<CodeElementModel> qualifiedModels = new ArrayList<>();
for (CodeElementModel model : resolvedQualifier) {
qualifiedModels.addAll(SemanticAnalyzer.getSelectableMembers(model, nameText));
}
if (qualifiedModels.isEmpty()) {
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, NodeType.UNKNOWN);
return true;
}
setNodeType(node, qualifiedModels.get(0));
treeDecorator.putProperty(node, GoAnnotations.RESOLVED, true);
treeDecorator.putProperty(node, GoAnnotations.MODELS, qualifiedModels);
return true;
}
private void setNodeType(TerminalNode node, CodeElementModel model) {
NodeType nodeType;
VarKind varType = VarKind.UNDEFINED;
TypeKind typeKind = TypeKind.UNDEFINED;
if (model instanceof PackageModel) {
nodeType = NodeType.PACKAGE_REF;
} else if (model instanceof TypeModel) {
nodeType = NodeType.TYPE_REF;
typeKind = ((TypeModel)model).getKind();
} else if (model instanceof VarModel) {
nodeType = NodeType.VAR_REF;
varType = ((VarModel)model).getVarKind();
} else if (model instanceof ConstModel) {
nodeType = NodeType.CONST_REF;
} else if (model instanceof FunctionModel) {
nodeType = ((FunctionModel)model).isMethod() ? NodeType.METHOD_REF : NodeType.FUNC_REF;
} else {
LOGGER.log(Level.WARNING, "Could not get a NodeType from model type: {0}", model.getClass());
nodeType = NodeType.UNKNOWN;
}
treeDecorator.putProperty(node, GoAnnotations.NODE_TYPE, nodeType);
if (typeKind != TypeKind.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.TYPE_KIND, typeKind);
}
if (varType != VarKind.UNDEFINED) {
treeDecorator.putProperty(node, GoAnnotations.VAR_TYPE, varType);
}
}
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayType, version=0)
private boolean resolveQualifierType(ParserRuleContext qualifier,
PackageModel currentPackage,
Map<String, Collection<PackageModel>> resolvedPackages) {
if (qualifier instanceof ArrayTypeContext) {
ArrayTypeContext ctx = (ArrayTypeContext)qualifier;
}
throw new UnsupportedOperationException("Not yet implemented");
}
private class QualifierTypeResolver extends GoParserBaseListener {
public boolean resolveType(ParserRuleContext qualifier) {
ParseTreeWalker.DEFAULT.walk(this, qualifier);
return treeDecorator.getProperty(qualifier, GoAnnotations.MODELS) != null;
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitArrayType(ArrayTypeContext ctx) {
Collection<? extends CodeElementModel> elementTypes = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.MODELS);
if (elementTypes != null) {
if (elementTypes.isEmpty()) {
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, Collections.<CodeElementModel>emptyList());
return;
}
List<TypeModelImpl> arrayTypes = new ArrayList<>();
for (CodeElementModel model : elementTypes) {
if (!(model instanceof TypeModelImpl)) {
continue;
}
TypeModelImpl elementType = (TypeModelImpl)model;
TypeModelImpl arrayType = new TypeArrayModelImpl(elementType);
arrayTypes.add(arrayType);
}
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, arrayTypes);
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_pointerType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseType, version=0),
})
public void exitPointerType(PointerTypeContext ctx) {
Collection<? extends CodeElementModel> elementTypes = treeDecorator.getProperty(ctx.baseType(), GoAnnotations.MODELS);
if (elementTypes != null) {
if (elementTypes.isEmpty()) {
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, Collections.<CodeElementModel>emptyList());
return;
}
List<TypeModelImpl> pointerTypes = new ArrayList<>();
for (CodeElementModel model : elementTypes) {
if (!(model instanceof TypeModelImpl)) {
continue;
}
TypeModelImpl elementType = (TypeModelImpl)model;
TypeModelImpl pointerType = new TypePointerModelImpl(elementType);
pointerTypes.add(pointerType);
}
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, pointerTypes);
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sliceType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitSliceType(SliceTypeContext ctx) {
Collection<? extends CodeElementModel> elementTypes = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.MODELS);
if (elementTypes != null) {
if (elementTypes.isEmpty()) {
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, Collections.<CodeElementModel>emptyList());
return;
}
List<TypeModelImpl> sliceTypes = new ArrayList<>();
for (CodeElementModel model : elementTypes) {
if (!(model instanceof TypeModelImpl)) {
continue;
}
TypeModelImpl elementType = (TypeModelImpl)model;
TypeModelImpl sliceType = new TypeSliceModelImpl(elementType);
sliceTypes.add(sliceType);
}
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, sliceTypes);
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mapType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_keyType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitMapType(MapTypeContext ctx) {
Collection<? extends CodeElementModel> keyTypes = treeDecorator.getProperty(ctx.keyType(), GoAnnotations.MODELS);
Collection<? extends CodeElementModel> elementTypes = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.MODELS);
if (keyTypes != null && elementTypes != null) {
if (keyTypes == null || elementTypes.isEmpty()) {
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, Collections.<CodeElementModel>emptyList());
return;
}
List<TypeModelImpl> mapTypes = new ArrayList<>();
for (CodeElementModel keyModel : keyTypes) {
if (!(keyModel instanceof TypeModelImpl)) {
continue;
}
for (CodeElementModel model : elementTypes) {
if (!(model instanceof TypeModelImpl)) {
continue;
}
TypeModelImpl keyType = (TypeModelImpl)keyModel;
TypeModelImpl elementType = (TypeModelImpl)model;
TypeModelImpl mapType = new TypeMapModelImpl(keyType, elementType);
mapTypes.add(mapType);
}
}
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, mapTypes);
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channelType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitChannelType(ChannelTypeContext ctx) {
Collection<? extends CodeElementModel> elementTypes = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.MODELS);
if (elementTypes != null) {
if (elementTypes.isEmpty()) {
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, Collections.<CodeElementModel>emptyList());
return;
}
ChannelKind channelKind = ChannelKind.SendReceive;
if (ctx.send != null) {
channelKind = ChannelKind.Send;
} else if (ctx.recv != null) {
channelKind = ChannelKind.Receive;
}
List<TypeModelImpl> channelTypes = new ArrayList<>();
for (CodeElementModel model : elementTypes) {
if (!(model instanceof TypeModelImpl)) {
continue;
}
TypeModelImpl elementType = (TypeModelImpl)model;
TypeModelImpl channelType = new TypeChannelModelImpl(elementType, channelKind);
channelTypes.add(channelType);
}
treeDecorator.putProperty(ctx, GoAnnotations.MODELS, channelTypes);
}
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterMultExpr(MultExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitMultExpr(MultExprContext ctx) {
CodeElementReference exprType = CodeElementReference.MISSING;
if (ctx.expression(0) != null && ctx.op != null && ctx.expression(1) != null) {
CodeElementReference left = treeDecorator.getProperty(ctx.expression(0), GoAnnotations.EXPR_TYPE);
CodeElementReference right = treeDecorator.getProperty(ctx.expression(1), GoAnnotations.EXPR_TYPE);
exprType = new BinaryExpressionTypeReference(left, ctx.op, right);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channelType, version=0)
public void enterChannelType(ChannelTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channelType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitChannelType(ChannelTypeContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.elementType() != null) {
ChannelKind kind = ChannelKind.SendReceive;
if (ctx.send != null) {
kind = ChannelKind.Send;
} else if (ctx.recv != null) {
kind = ChannelKind.Receive;
}
codeClass = new ChannelTypeReference(treeDecorator.getProperty(ctx.elementType(), GoAnnotations.CODE_CLASS), kind);
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.CHANNEL);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mulAssignOp, version=0)
public void enterMulAssignOp(MulAssignOpContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mulAssignOp, version=0)
public void exitMulAssignOp(MulAssignOpContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageName, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageClause, version=0),
})
public void enterPackageName(PackageNameContext ctx) {
int invokingRule = ParseTrees.getInvokingRule(GoParser._ATN, ctx);
NodeType nodeType = invokingRule == GoParser.RULE_packageClause ? NodeType.PACKAGE_DECL : NodeType.PACKAGE_REF;
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, nodeType);
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, nodeType);
if (treeDecorator.getProperty(ctx, GoAnnotations.RESOLVED)) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
}
TerminalNode localTarget = treeDecorator.getProperty(ctx, GoAnnotations.LOCAL_TARGET);
if (localTarget != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.LOCAL_TARGET, localTarget);
}
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageName, version=0)
public void exitPackageName(PackageNameContext ctx) {
// not qualified!
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_receiver, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseTypeName, version=0),
})
public void enterReceiver(ReceiverContext ctx) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.VAR_TYPE, VarKind.RECEIVER);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EXPLICIT_TYPE, ctx.baseTypeName());
visibleLocals.peek().put(ctx.IDENTIFIER().getSymbol().getText(), ctx.IDENTIFIER());
}
if (ctx.ptr != null && ctx.baseTypeName() != null) {
treeDecorator.putProperty(ctx.baseTypeName(), GoAnnotations.POINTER_RECEIVER, true);
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_receiver, version=0)
public void exitReceiver(ReceiverContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayType, version=0)
public void enterArrayType(ArrayTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitArrayType(ArrayTypeContext ctx) {
CodeElementReference elemClass = CodeElementReference.UNKNOWN;
if (ctx.elementType() != null) {
elemClass = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.CODE_CLASS);
}
CodeElementReference arrayClass = new ArrayTypeReference(elemClass);
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, arrayClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.ARRAY);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionList, version=0)
public void enterExpressionList(ExpressionListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionList, version=0)
public void exitExpressionList(ExpressionListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_tag, version=0)
public void enterTag(TagContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_tag, version=0)
public void exitTag(TagContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_fallthroughStmt, version=0)
public void enterFallthroughStmt(FallthroughStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_fallthroughStmt, version=0)
public void exitFallthroughStmt(FallthroughStmtContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterSelectorExpr(SelectorExprContext ctx) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.QUALIFIED_EXPR, true);
if (ctx.expression() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.QUALIFIER, ctx.expression());
}
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitSelectorExpr(SelectorExprContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
TerminalNode node = ctx.IDENTIFIER();
if (node != null) {
assert ctx.expression() != null;
exprType = new SelectedElementReference(treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE), node.getSymbol());
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
if (node != null) {
unresolvedQualifiedIdentifiers.add(node);
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_parameterList, version=0)
public void enterParameterList(ParameterListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_parameterList, version=0)
public void exitParameterList(ParameterListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_receiverType, version=0)
public void enterReceiverType(ReceiverTypeContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_receiverType, version=0)
public void exitReceiverType(ReceiverTypeContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_ifStmt, version=0)
public void enterIfStmt(IfStmtContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_ifStmt, version=0)
public void exitIfStmt(IfStmtContext ctx) {
popVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodName, version=0)
public void enterMethodName(MethodNameContext ctx) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.METHOD_DECL);
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodName, version=0)
public void exitMethodName(MethodNameContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_signature, version=0)
public void enterSignature(SignatureContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_signature, version=0)
public void exitSignature(SignatureContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mapType, version=0)
public void enterMapType(MapTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mapType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_keyType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitMapType(MapTypeContext ctx) {
CodeElementReference keyType = CodeElementReference.UNKNOWN;
if (ctx.keyType() != null) {
keyType = treeDecorator.getProperty(ctx.keyType(), GoAnnotations.CODE_CLASS);
}
CodeElementReference valueType = CodeElementReference.UNKNOWN;
if (ctx.elementType() != null) {
valueType = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.CODE_CLASS);
}
CodeElementReference codeClass = new MapTypeReference(keyType, valueType);
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.MAP);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_element, version=0)
public void enterElement(ElementContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_element, version=0)
public void exitElement(ElementContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterCallExpr(CallExprContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_argumentList, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionList, version=1),
})
public void exitCallExpr(CallExprContext ctx) {
CodeElementReference returnType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
boolean builtin = false;
if (ctx.expression().start != null && ctx.expression().start == ctx.expression().stop) {
String methodName = ctx.expression().start.getText();
builtin = SemanticHighlighter.PREDEFINED_FUNCTIONS.contains(methodName);
}
if (builtin) {
CodeElementReference typeArgument = CodeElementReference.UNKNOWN;
ArgumentListContext args = ctx.argumentList();
if (args != null) {
ExpressionListContext exprs = args.expressionList();
if (exprs != null && !exprs.expression().isEmpty()) {
typeArgument = treeDecorator.getProperty(exprs.expression(0), GoAnnotations.CODE_CLASS);
if (typeArgument == CodeElementReference.MISSING) {
typeArgument = treeDecorator.getProperty(exprs.expression(0), GoAnnotations.EXPR_TYPE);
}
}
}
returnType = new BuiltinCallResultReference(ctx.expression().start, typeArgument);
} else {
returnType = new CallResultReference(treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE));
}
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, returnType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeCaseClause, version=0)
public void enterTypeCaseClause(TypeCaseClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeCaseClause, version=0)
public void exitTypeCaseClause(TypeCaseClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_exprCaseClause, version=0)
public void enterExprCaseClause(ExprCaseClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_exprCaseClause, version=0)
public void exitExprCaseClause(ExprCaseClauseContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchGuard, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void enterTypeSwitchGuard(TypeSwitchGuardContext ctx) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.VAR_TYPE, VarKind.LOCAL);
if (ctx.expression() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EXPLICIT_TYPE, ctx.expression());
}
pendingVisibleLocals.peek().put(ctx.IDENTIFIER().getText(), ctx.IDENTIFIER());
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchGuard, version=0)
public void exitTypeSwitchGuard(TypeSwitchGuardContext ctx) {
applyPendingVars();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionLiteral, version=0)
public void enterFunctionLiteral(FunctionLiteralContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionLiteral, version=0)
public void exitFunctionLiteral(FunctionLiteralContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
LOGGER.log(Level.FINE, "Element references not implemented for context {0}.", ctx.getClass().getSimpleName());
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
popVarScope();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterExpression(ExpressionContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitExpression(ExpressionContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterOrExpr(OrExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitOrExpr(OrExprContext ctx) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, BuiltinTypeReference.BOOL);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_recvExpr, version=0)
public void enterRecvExpr(RecvExprContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_recvExpr, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitRecvExpr(RecvExprContext ctx) {
assert ctx.getChildCount() <= 1;
assert ctx.getChildCount() == 0 || ctx.expression() != null;
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_topLevelDecl, version=0)
public void enterTopLevelDecl(TopLevelDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_topLevelDecl, version=0)
public void exitTopLevelDecl(TopLevelDeclContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodSpec, version=0)
public void enterMethodSpec(MethodSpecContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodSpec, version=0)
public void exitMethodSpec(MethodSpecContext ctx) {
popVarScope();
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_constSpec, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_constDecl, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_declaration, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_topLevelDecl, version=0),
})
public void enterConstSpec(ConstSpecContext ctx) {
if (ctx.identifierList() != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.NODE_TYPE, NodeType.CONST_DECL);
boolean global = ParseTrees.isInContexts(ctx, false, GoParser.RULE_constSpec, GoParser.RULE_constDecl, GoParser.RULE_declaration, GoParser.RULE_topLevelDecl);
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.GLOBAL, global);
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_constSpec, version=0)
public void exitConstSpec(ConstSpecContext ctx) {
_iota = _iota.add(BigInteger.ONE);
applyPendingVars();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_compositeLiteral, version=0)
public void enterCompositeLiteral(CompositeLiteralContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_compositeLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalValue, version=0),
})
public void exitCompositeLiteral(CompositeLiteralContext ctx) {
CodeElementReference exprType;
if (ctx.literalType() != null) {
exprType = treeDecorator.getProperty(ctx.literalType(), GoAnnotations.CODE_CLASS);
} else {
exprType = CodeElementReference.UNKNOWN;
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
if (ctx.literalValue() != null) {
treeDecorator.putProperty(ctx.literalValue(), GoAnnotations.EXPR_TYPE, exprType);
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_forClause, version=0)
public void enterForClause(ForClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_forClause, version=0)
public void exitForClause(ForClauseContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_shortVarDecl, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionList, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void enterShortVarDecl(ShortVarDeclContext ctx) {
if (ctx.identifierList() != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VAR_TYPE, VarKind.LOCAL);
if (ctx.expressionList() != null) {
int varCount = ctx.identifierList().IDENTIFIER().size();
int exprCount = ctx.expressionList().expression().size();
if (varCount > 1 && exprCount == 1) {
for (int i = 0; i < varCount; i++) {
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_TYPE, ctx.expressionList().expression(0));
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_INDEX, i);
}
} else if (varCount == exprCount) {
for (int i = 0; i < varCount; i++) {
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_TYPE, ctx.expressionList().expression(i));
if (varCount > 1) {
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_INDEX, i);
}
}
}
}
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_shortVarDecl, version=1)
public void exitShortVarDecl(ShortVarDeclContext ctx) {
applyPendingVars();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_gotoStmt, version=0)
public void enterGotoStmt(GotoStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_gotoStmt, version=0)
public void exitGotoStmt(GotoStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayLength, version=0)
public void enterArrayLength(ArrayLengthContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayLength, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitArrayLength(ArrayLengthContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_interfaceType, version=0)
public void enterInterfaceType(InterfaceTypeContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_interfaceType, version=0)
public void exitInterfaceType(InterfaceTypeContext ctx) {
CodeElementReference codeClass = new InterfaceTypeReference(((TypeModelImpl)IntrinsicTypeModels.INT).getFile());
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.INTERFACE);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_conversion, version=0)
public void enterConversion(ConversionContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_conversion, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void exitConversion(ConversionContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.type() != null) {
exprType = treeDecorator.getProperty(ctx.type(), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_block, version=0)
public void enterBlock(BlockContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_block, version=0)
public void exitBlock(BlockContext ctx) {
popVarScope();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_breakStmt, version=0)
public void enterBreakStmt(BreakStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_breakStmt, version=0)
public void exitBreakStmt(BreakStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_emptyStmt, version=0)
public void enterEmptyStmt(EmptyStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_emptyStmt, version=0)
public void exitEmptyStmt(EmptyStmtContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionLiteral, version=0),
})
public void enterFunctionType(FunctionTypeContext ctx) {
if (!ParseTrees.isInContexts(ctx, false, GoParser.RULE_functionType, GoParser.RULE_functionLiteral)) {
pushVarScope();
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionLiteral, version=0),
})
public void exitFunctionType(FunctionTypeContext ctx) {
CodeElementReference codeClass = new FunctionTypeReference();
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
if (!ParseTrees.isInContexts(ctx, false, GoParser.RULE_functionType, GoParser.RULE_functionLiteral)) {
popVarScope();
}
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.FUNCTION);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseType, version=0)
public void enterBaseType(BaseTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void exitBaseType(BaseTypeContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.type() != null) {
codeClass = treeDecorator.getProperty(ctx.type(), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_fieldDecl, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void enterFieldDecl(FieldDeclContext ctx) {
if (ctx.identifierList() != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VAR_TYPE, VarKind.FIELD);
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.EXPLICIT_TYPE, ctx.type());
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_fieldDecl, version=0)
public void exitFieldDecl(FieldDeclContext ctx) {
applyPendingVars();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_exprSwitchStmt, version=0)
public void enterExprSwitchStmt(ExprSwitchStmtContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_exprSwitchStmt, version=0)
public void exitExprSwitchStmt(ExprSwitchStmtContext ctx) {
popVarScope();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_goStmt, version=0)
public void enterGoStmt(GoStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_goStmt, version=0)
public void exitGoStmt(GoStmtContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_parameterDecl, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void enterParameterDecl(ParameterDeclContext ctx) {
if (ctx.identifierList() != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
if (ctx.ellip != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VARIADIC, true);
}
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.EXPLICIT_TYPE, ctx.type());
if (ParseTrees.isInContexts(ctx, false, GoParser.RULE_parameterDecl, GoParser.RULE_parameterList, GoParser.RULE_parameters, GoParser.RULE_result)) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VAR_TYPE, VarKind.RETURN);
} else {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VAR_TYPE, VarKind.PARAMETER);
}
for (TerminalNode id : ctx.identifierList().IDENTIFIER()) {
visibleLocals.peek().put(id.getSymbol().getText(), id);
}
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_parameterDecl, version=0)
public void exitParameterDecl(ParameterDeclContext ctx) {
applyPendingVars();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_basicLiteral, version=0)
public void enterBasicLiteral(BasicLiteralContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_basicLiteral, version=0)
public void exitBasicLiteral(BasicLiteralContext ctx) {
assert ctx.stop == null || ctx.start == ctx.stop;
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, new LiteralTypeReference(ctx.start));
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_exprSwitchCase, version=0)
public void enterExprSwitchCase(ExprSwitchCaseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_exprSwitchCase, version=0)
public void exitExprSwitchCase(ExprSwitchCaseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeLiteral, version=0)
public void enterTypeLiteral(TypeLiteralContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeLiteral, version=0)
public void exitTypeLiteral(TypeLiteralContext ctx) {
assert ctx.getChildCount() <= 1;
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.getChildCount() == 1) {
codeClass = treeDecorator.getProperty(ctx.getChild(0), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_selectStmt, version=0)
public void enterSelectStmt(SelectStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_selectStmt, version=0)
public void exitSelectStmt(SelectStmtContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importSpec, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importPath, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageName, version=0),
})
public void enterImportSpec(ImportSpecContext ctx) {
if (ctx.importPath() == null || ctx.importPath().StringLiteral() == null) {
return;
}
String name = null;
String path = null;
TerminalNode target = null;
if (ctx.importPath() != null && ctx.importPath().StringLiteral() != null) {
target = ctx.importPath().StringLiteral();
path = target.getText();
if (path.startsWith("\"")) {
path = path.substring(1);
}
if (path.endsWith("\"")) {
path = path.substring(0, path.length() - 1);
}
}
if (ctx.dot != null) {
name = "";
target = null;
} else if (ctx.packageName != null) {
if (ctx.packageName.IDENTIFIER() != null) {
target = ctx.packageName.IDENTIFIER();
name = target.getText();
}
} else {
name = path.substring(path.lastIndexOf('/') + 1);
}
if (target != null) {
Project currentProject = FileOwnerQuery.getOwner(document.getFileObject());
if (!(currentProject instanceof GoProject)) {
return;
}
Collection<? extends PackageModel> packages = CodeModelCacheImpl.getInstance().getPackages((GoProject)currentProject, path);
Set<PackageModel> libraryPackages = new HashSet<>();
for (GoProject importedProject : ((GoProject)currentProject).getLibraryProjects()) {
libraryPackages.addAll(CodeModelCacheImpl.getInstance().getPackages(importedProject, path));
}
List<PackageModel> visiblePackages = new ArrayList<>(packages);
visiblePackages.addAll(libraryPackages);
treeDecorator.putProperty(target, GoAnnotations.MODELS, visiblePackages);
if (!visiblePackages.isEmpty()) {
treeDecorator.putProperty(target, GoAnnotations.RESOLVED, true);
}
List<TerminalNode> packageList = importedPackages.get(name);
if (packageList == null) {
packageList = new ArrayList<>();
importedPackages.put(name, packageList);
}
packageList.add(target);
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importSpec, version=0)
public void exitImportSpec(ImportSpecContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeName, version=0)
public void enterTypeName(TypeNameContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeName, version=3, dependents=Dependents.PARENTS),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_qualifiedIdentifier, version=0),
})
public void exitTypeName(TypeNameContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.qualifiedIdentifier() != null) {
codeClass = new QualifiedIdentifierElementReference(ctx.qualifiedIdentifier());
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
if (ctx.qualifiedIdentifier() == null) {
return;
}
if (treeDecorator.getProperty(ctx.qualifiedIdentifier(), GoAnnotations.QUALIFIED_EXPR)) {
treeDecorator.putProperty(ctx, GoAnnotations.QUALIFIED_EXPR, true);
} else {
treeDecorator.putProperty(ctx, GoAnnotations.UNQUALIFIED_LINK, treeDecorator.getProperty(ctx.qualifiedIdentifier(), GoAnnotations.UNQUALIFIED_LINK));
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalType, version=0)
public void enterLiteralType(LiteralTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_structType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sliceType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mapType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeName, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitLiteralType(LiteralTypeContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.getChildCount() == 1) {
ParseTree child = ctx.getChild(0);
assert child instanceof StructTypeContext
|| child instanceof ArrayTypeContext
|| child instanceof SliceTypeContext
|| child instanceof MapTypeContext
|| child instanceof TypeNameContext;
codeClass = treeDecorator.getProperty(child, GoAnnotations.CODE_CLASS);
} else if (ctx.getChildCount() > 1) {
ParseTree firstChild = ctx.getChild(0);
assert firstChild instanceof TerminalNode
&& ((TerminalNode)firstChild).getSymbol() instanceof Token
&& ((TerminalNode)firstChild).getSymbol().getType() == GoParser.LeftBrack;
ParseTree lastChild = ctx.getChild(ctx.getChildCount() - 1);
assert lastChild instanceof ElementTypeContext;
codeClass = new ArrayTypeReference(treeDecorator.getProperty(lastChild, GoAnnotations.CODE_CLASS));
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_assignment, version=0)
public void enterAssignment(AssignmentContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_assignment, version=0)
public void exitAssignment(AssignmentContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_assignOp, version=0)
public void enterAssignOp(AssignOpContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_assignOp, version=0)
public void exitAssignOp(AssignOpContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_recvStmt, version=0)
public void enterRecvStmt(RecvStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_recvStmt, version=0)
public void exitRecvStmt(RecvStmtContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSpec, version=0)
public void enterTypeSpec(TypeSpecContext ctx) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.TYPE_DECL);
visibleTypes.peek().put(ctx.IDENTIFIER().getSymbol().getText(), ctx.IDENTIFIER());
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSpec, version=0)
public void exitTypeSpec(TypeSpecContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageClause, version=0)
public void enterPackageClause(PackageClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageClause, version=0)
public void exitPackageClause(PackageClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalValue, version=0)
public void enterLiteralValue(LiteralValueContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalValue, version=0)
public void exitLiteralValue(LiteralValueContext ctx) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, new LiteralValueElementReference());
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterIndexExpr(IndexExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitIndexExpr(IndexExprContext ctx) {
CodeElementReference exprType = CodeElementReference.MISSING;
if (ctx.expression(0) != null) {
CodeElementReference arrayType = treeDecorator.getProperty(ctx.expression(0), GoAnnotations.EXPR_TYPE);
exprType = new ArrayElementTypeReference(arrayType);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_varSpec, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionList, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_varDecl, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_declaration, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_topLevelDecl, version=0),
})
public void enterVarSpec(VarSpecContext ctx) {
if (ctx.identifierList() != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
if (ParseTrees.isInContexts(ctx, false, GoParser.RULE_varSpec, GoParser.RULE_varDecl, GoParser.RULE_declaration, GoParser.RULE_topLevelDecl)) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VAR_TYPE, VarKind.GLOBAL);
} else {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.VAR_TYPE, VarKind.LOCAL);
}
if (ctx.type() != null) {
treeDecorator.putProperty(ctx.identifierList(), GoAnnotations.EXPLICIT_TYPE, ctx.type());
} else if (ctx.expressionList() != null) {
int varCount = ctx.identifierList().IDENTIFIER().size();
int exprCount = ctx.expressionList().expression().size();
if (varCount > 1 && exprCount == 1) {
for (int i = 0; i < varCount; i++) {
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_TYPE, ctx.expressionList().expression(0));
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_INDEX, i);
}
} else if (varCount == exprCount) {
for (int i = 0; i < varCount; i++) {
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_TYPE, ctx.expressionList().expression(i));
treeDecorator.putProperty(ctx.identifierList().IDENTIFIER(i), GoAnnotations.IMPLICIT_INDEX, i);
}
}
}
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_varSpec, version=0)
public void exitVarSpec(VarSpecContext ctx) {
applyPendingVars();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterOperandExpr(OperandExprContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_operand, version=0),
})
public void exitOperandExpr(OperandExprContext ctx) {
// this isn't true in some parse error scenarios
//assert ctx.getChildCount() == 0 || (ctx.getChildCount() == 1 && ctx.operand() != null);
if (ctx.operand() != null) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, treeDecorator.getProperty(ctx.operand(), GoAnnotations.EXPR_TYPE));
} else {
LOGGER.log(Level.WARNING, "Unrecognized tree structure.");
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, CodeElementReference.UNKNOWN);
}
if (ctx.operand() != null) {
treeDecorator.putProperties(ctx, treeDecorator.getProperties(ctx.operand()));
} else {
LOGGER.log(Level.FINER, "Expression resolution links are not supported for context: {0}", ctx.toString(Arrays.asList(GoParser.ruleNames)));
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterBuiltinCallExpr(BuiltinCallExprContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinCall, version=0),
})
public void exitBuiltinCallExpr(BuiltinCallExprContext ctx) {
assert ctx.getChildCount() == 0 || (ctx.getChildCount() == 1 && ctx.builtinCall() != null);
if (ctx.builtinCall() != null) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, treeDecorator.getProperty(ctx.builtinCall(), GoAnnotations.EXPR_TYPE));
} else {
LOGGER.log(Level.WARNING, "Unrecognized tree structure.");
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, CodeElementReference.UNKNOWN);
}
LOGGER.log(Level.FINER, "Expression resolution links are not supported for context: {0}", ctx.toString(Arrays.asList(GoParser.ruleNames)));
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_body, version=0)
public void enterBody(BodyContext ctx) {
pushVarScope();
visibleLabels.push(new HashMap<String, TerminalNode>());
unresolvedLabels.push(new ArrayList<TerminalNode>());
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_body, version=0)
public void exitBody(BodyContext ctx) {
for (TerminalNode labelReference : unresolvedLabels.peek()) {
TerminalNode target = visibleLabels.peek().get(labelReference.getText());
if (target == null) {
continue;
}
treeDecorator.putProperty(labelReference, GoAnnotations.LOCAL_TARGET, target);
treeDecorator.putProperty(labelReference, GoAnnotations.RESOLVED, true);
}
popVarScope();
visibleLabels.pop();
unresolvedLabels.pop();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_commClause, version=0)
public void enterCommClause(CommClauseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_commClause, version=0)
public void exitCommClause(CommClauseContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_qualifiedIdentifier, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageName, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchGuard, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchStmt, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeCaseClause, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchCase, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeList, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void enterQualifiedIdentifier(QualifiedIdentifierContext ctx) {
if (ctx.packageName() != null) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.QUALIFIED_EXPR, true);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.QUALIFIER, ctx.packageName());
unresolvedQualifiedIdentifiers.add(ctx.IDENTIFIER());
}
// check known imports
if (ctx.packageName().IDENTIFIER() != null) {
List<? extends TerminalNode> imports = ParseTrees.emptyIfNull(importedPackages.get(ctx.packageName().IDENTIFIER().getSymbol().getText()));
TerminalNode bestImport = null;
boolean resolvedImport = false;
for (TerminalNode importToken : imports) {
if (bestImport == null || (!resolvedImport && treeDecorator.getProperty(importToken, GoAnnotations.RESOLVED))) {
bestImport = importToken;
resolvedImport = treeDecorator.getProperty(importToken, GoAnnotations.RESOLVED);
break;
}
}
if (bestImport != null) {
treeDecorator.putProperty(ctx.packageName(), GoAnnotations.LOCAL_TARGET, bestImport);
if (resolvedImport) {
treeDecorator.putProperty(ctx.packageName(), GoAnnotations.RESOLVED, true);
}
}
}
} else if (ctx.IDENTIFIER() != null) {
assert ctx.packageName() == null;
String text = ctx.IDENTIFIER().getText();
switch (text) {
case "true":
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.UNEVALUATED_CONSTANT, "true");
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EVALUATED_CONSTANT, BigInteger.ONE);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
break;
case "false":
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.UNEVALUATED_CONSTANT, "false");
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EVALUATED_CONSTANT, BigInteger.ZERO);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
break;
case "iota":
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.UNEVALUATED_CONSTANT, "iota");
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EVALUATED_CONSTANT, _iota);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
break;
}
TerminalNode local = getVisibleLocal(ctx.IDENTIFIER());
if (local != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.VAR_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.LOCAL_TARGET, local);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
VarKind varType = treeDecorator.getProperty(local, GoAnnotations.VAR_TYPE);
if (varType != VarKind.UNDEFINED) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.VAR_TYPE, varType);
}
if (local.getParent().getRuleContext() instanceof TypeSwitchGuardContext) {
TypeSwitchGuardContext typeSwitchGuardContext = (TypeSwitchGuardContext)local.getParent().getRuleContext();
TypeSwitchStmtContext typeSwitchStmtContext = (TypeSwitchStmtContext)typeSwitchGuardContext.getParent();
for (TypeCaseClauseContext typeCaseClauseContext : typeSwitchStmtContext.typeCaseClause()) {
if (ParseTrees.isAncestorOf(typeCaseClauseContext, ctx)) {
TypeListContext typeListContext = typeCaseClauseContext.typeSwitchCase() != null ? typeCaseClauseContext.typeSwitchCase().typeList() : null;
if (typeListContext != null && typeListContext.type().size() == 1) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EXPLICIT_TYPE, typeListContext.type(0));
}
break;
}
}
}
return;
}
TerminalNode constant = getVisibleConstant(ctx.IDENTIFIER());
if (constant != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.LOCAL_TARGET, constant);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
return;
}
// check built-ins
if (SemanticHighlighter.PREDEFINED_FUNCTIONS.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.FUNC_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else if (SemanticHighlighter.PREDEFINED_TYPES.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.TYPE_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.TYPE_KIND, TypeKind.INTRINSIC);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else if (SemanticHighlighter.PREDEFINED_CONSTANTS.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else {
unresolvedIdentifiers.add(ctx.IDENTIFIER());
}
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_qualifiedIdentifier, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_packageName, version=0),
})
public void exitQualifiedIdentifier(QualifiedIdentifierContext ctx) {
if (ctx.packageName() != null) {
treeDecorator.putProperty(ctx, GoAnnotations.QUALIFIED_EXPR, true);
} else if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx, GoAnnotations.UNQUALIFIED_LINK, ctx.IDENTIFIER());
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_returnStmt, version=0)
public void enterReturnStmt(ReturnStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_returnStmt, version=0)
public void exitReturnStmt(ReturnStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_simpleStmt, version=0)
public void enterSimpleStmt(SimpleStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_simpleStmt, version=0)
public void exitSimpleStmt(SimpleStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterTypeAssertionExpr(TypeAssertionExprContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void exitTypeAssertionExpr(TypeAssertionExprContext ctx) {
CodeElementReference exprType = CodeElementReference.MISSING;
if (ctx.type() != null) {
exprType = treeDecorator.getProperty(ctx.type(), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, new TypeAssertionResultReference(exprType));
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0)
public void enterType(TypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=2, dependents=Dependents.PARENTS),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeName, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeLiteral, version=0),
})
public void exitType(TypeContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.typeName() != null) {
codeClass = treeDecorator.getProperty(ctx.typeName(), GoAnnotations.CODE_CLASS);
} else if (ctx.typeLiteral() != null) {
codeClass = treeDecorator.getProperty(ctx.typeLiteral(), GoAnnotations.CODE_CLASS);
} else if (ctx.type() != null) {
codeClass = treeDecorator.getProperty(ctx.type(), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_interfaceTypeName, version=0)
public void enterInterfaceTypeName(InterfaceTypeNameContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_interfaceTypeName, version=0)
public void exitInterfaceTypeName(InterfaceTypeNameContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_continueStmt, version=0)
public void enterContinueStmt(ContinueStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_continueStmt, version=0)
public void exitContinueStmt(ContinueStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_value, version=0)
public void enterValue(ValueContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_value, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalValue, version=0),
})
public void exitValue(ValueContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
} else if (ctx.literalValue() != null) {
exprType = treeDecorator.getProperty(ctx.literalValue(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodDecl, version=0)
public void enterMethodDecl(MethodDeclContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodDecl, version=0)
public void exitMethodDecl(MethodDeclContext ctx) {
popVarScope();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_labeledStmt, version=0)
public void enterLabeledStmt(LabeledStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_labeledStmt, version=0)
public void exitLabeledStmt(LabeledStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_parameters, version=0)
public void enterParameters(ParametersContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_parameters, version=0)
public void exitParameters(ParametersContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_deferStmt, version=0)
public void enterDeferStmt(DeferStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_deferStmt, version=0)
public void exitDeferStmt(DeferStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_key, version=0)
public void enterKey(KeyContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_key, version=0)
public void exitKey(KeyContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_declaration, version=0)
public void enterDeclaration(DeclarationContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_declaration, version=0)
public void exitDeclaration(DeclarationContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_commCase, version=0)
public void enterCommCase(CommCaseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_commCase, version=0)
public void exitCommCase(CommCaseContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinArgs, version=0)
public void enterBuiltinArgs(BuiltinArgsContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinArgs, version=0)
public void exitBuiltinArgs(BuiltinArgsContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_condition, version=0)
public void enterCondition(ConditionContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_condition, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitCondition(ConditionContext ctx) {
assert ctx.getChildCount() == 0 || (ctx.getChildCount() == 1 && ctx.expression() != null);
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterConversionOrCallExpr(ConversionOrCallExprContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_conversion, version=0),
})
public void exitConversionOrCallExpr(ConversionOrCallExprContext ctx) {
CodeElementReference exprType = CodeElementReference.MISSING;
if (ctx.conversion() != null) {
exprType = new ConversionOrCallResultReference(treeDecorator.getProperty(ctx.conversion(), GoAnnotations.EXPR_TYPE));
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_label, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_labeledStmt, version=0),
})
public void enterLabel(LabelContext ctx) {
if (ctx.IDENTIFIER() == null) {
return;
}
boolean definition = ParseTrees.isInContexts(ctx, false, GoParser.RULE_label, GoParser.RULE_labeledStmt);
if (definition) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.LABEL_DECL);
visibleLabels.peek().put(ctx.IDENTIFIER().getSymbol().getText(), ctx.IDENTIFIER());
} else {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.LABEL_REF);
unresolvedLabels.peek().add(ctx.IDENTIFIER());
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_label, version=0)
public void exitLabel(LabelContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0)
public void enterElementType(ElementTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void exitElementType(ElementTypeContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.type() != null) {
codeClass = treeDecorator.getProperty(ctx.type(), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionDecl, version=0)
public void enterFunctionDecl(FunctionDeclContext ctx) {
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.FUNC_DECL);
visibleFunctions.peek().put(ctx.IDENTIFIER().getSymbol().getText(), ctx.IDENTIFIER());
}
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionDecl, version=0)
public void exitFunctionDecl(FunctionDeclContext ctx) {
popVarScope();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_statement, version=0)
public void enterStatement(StatementContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_statement, version=0)
public void exitStatement(StatementContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_pointerType, version=0)
public void enterPointerType(PointerTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_pointerType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseType, version=0),
})
public void exitPointerType(PointerTypeContext ctx) {
CodeElementReference elemClass = CodeElementReference.UNKNOWN;
if (ctx.baseType() != null) {
elemClass = treeDecorator.getProperty(ctx.baseType(), GoAnnotations.CODE_CLASS);
}
CodeElementReference codeClass = new PointerTypeReference(elemClass);
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.POINTER);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_addAssignOp, version=0)
public void enterAddAssignOp(AddAssignOpContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_addAssignOp, version=0)
public void exitAddAssignOp(AddAssignOpContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sourceFileBody, version=0)
public void enterSourceFileBody(SourceFileBodyContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sourceFileBody, version=0)
public void exitSourceFileBody(SourceFileBodyContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sourceFile, version=1)
public void enterSourceFile(SourceFileContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sourceFile, version=1)
public void exitSourceFile(SourceFileContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterSliceExpr(SliceExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitSliceExpr(SliceExprContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression(0) != null) {
exprType = new SliceExpressionTypeReference(treeDecorator.getProperty(ctx.expression(0), GoAnnotations.EXPR_TYPE));
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseTypeName, version=0)
public void enterBaseTypeName(BaseTypeNameContext ctx) {
if (ctx.IDENTIFIER() != null) {
unresolvedIdentifiers.add(ctx.IDENTIFIER());
}
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseTypeName, version=0)
public void exitBaseTypeName(BaseTypeNameContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.IDENTIFIER() != null) {
codeClass = new ReceiverTypeReference(ctx.IDENTIFIER(), treeDecorator.getProperty(ctx, GoAnnotations.POINTER_RECEIVER));
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodExpr, version=0)
public void enterMethodExpr(MethodExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodExpr, version=0)
public void exitMethodExpr(MethodExprContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
LOGGER.log(Level.FINE, "Element references not implemented for context {0}.", ctx.getClass().getSimpleName());
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementNameOrIndex, version=0)
public void enterElementNameOrIndex(ElementNameOrIndexContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementNameOrIndex, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitElementNameOrIndex(ElementNameOrIndexContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeList, version=0)
public void enterTypeList(TypeListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeList, version=0)
public void exitTypeList(TypeListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_incDecStmt, version=0)
public void enterIncDecStmt(IncDecStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_incDecStmt, version=0)
public void exitIncDecStmt(IncDecStmtContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinCall, version=0)
public void enterBuiltinCall(BuiltinCallContext ctx) {
if (ctx.IDENTIFIER() != null) {
if (SemanticHighlighter.PREDEFINED_FUNCTIONS.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.FUNC_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else {
unresolvedIdentifiers.add(ctx.IDENTIFIER());
}
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinCall, version=0, dependents=Dependents.PARENTS),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinArgs, version=2, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_argumentList, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionList, version=1, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchGuard, version=0, dependents=Dependents.PARENTS),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchStmt, version=0, dependents=Dependents.PARENTS),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeCaseClause, version=3, dependents={Dependents.SELF, Dependents.DESCENDANTS}),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchCase, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeList, version=0, dependents=Dependents.SELF),
})
public void exitBuiltinCall(BuiltinCallContext ctx) {
BuiltinArgsContext args = ctx.builtinArgs();
if (ctx.IDENTIFIER() != null
&& !SemanticHighlighter.PREDEFINED_FUNCTIONS.contains(ctx.IDENTIFIER().getText())
&& (args == null || args.type() == null))
{
// not a built in function, and no type was passed to it
// HACK: copied from enterQualifiedIdentifier
TerminalNode local = getVisibleLocal(ctx.IDENTIFIER());
if (local != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.VAR_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.LOCAL_TARGET, local);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
VarKind varType = treeDecorator.getProperty(local, GoAnnotations.VAR_TYPE);
if (varType != VarKind.UNDEFINED) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.VAR_TYPE, varType);
}
if (local.getParent().getRuleContext() instanceof TypeSwitchGuardContext) {
TypeSwitchGuardContext typeSwitchGuardContext = (TypeSwitchGuardContext)local.getParent().getRuleContext();
TypeSwitchStmtContext typeSwitchStmtContext = (TypeSwitchStmtContext)typeSwitchGuardContext.getParent();
for (TypeCaseClauseContext typeCaseClauseContext : typeSwitchStmtContext.typeCaseClause()) {
if (ParseTrees.isAncestorOf(typeCaseClauseContext, ctx)) {
TypeListContext typeListContext = typeCaseClauseContext.typeSwitchCase() != null ? typeCaseClauseContext.typeSwitchCase().typeList() : null;
if (typeListContext != null && typeListContext.type().size() == 1) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.EXPLICIT_TYPE, typeListContext.type(0));
}
break;
}
}
}
} else {
TerminalNode constant = getVisibleConstant(ctx.IDENTIFIER());
if (constant != null) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.LOCAL_TARGET, constant);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.RESOLVED, true);
} else {
// check built-ins
if (SemanticHighlighter.PREDEFINED_FUNCTIONS.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.FUNC_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else if (SemanticHighlighter.PREDEFINED_TYPES.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.TYPE_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.TYPE_KIND, TypeKind.INTRINSIC);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else if (SemanticHighlighter.PREDEFINED_CONSTANTS.contains(ctx.IDENTIFIER().getSymbol().getText())) {
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.NODE_TYPE, NodeType.CONST_REF);
treeDecorator.putProperty(ctx.IDENTIFIER(), GoAnnotations.BUILTIN, true);
} else {
unresolvedIdentifiers.add(ctx.IDENTIFIER());
}
}
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, new CallResultReference(new UnqualifiedIdentifierElementReference(ctx.IDENTIFIER())));
return;
}
CodeElementReference typeArgument = CodeElementReference.UNKNOWN;
if (args != null) {
if (args.type() != null) {
typeArgument = treeDecorator.getProperty(args.type(), GoAnnotations.CODE_CLASS);
} else {
ArgumentListContext argumentList = args.argumentList();
ExpressionListContext exprList = argumentList != null ? argumentList.expressionList() : null;
if (exprList != null) {
List<? extends ExpressionContext> exprs = exprList.expression();
if (exprs != null && !exprs.isEmpty()) {
typeArgument = treeDecorator.getProperty(exprs.get(0), GoAnnotations.EXPR_TYPE);
if (typeArgument == CodeElementReference.MISSING) {
typeArgument = treeDecorator.getProperty(exprs.get(0), GoAnnotations.CODE_CLASS);
}
}
}
}
}
if (ctx.IDENTIFIER() != null) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, new BuiltinCallResultReference(ctx.IDENTIFIER().getSymbol(), typeArgument));
} else {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, CodeElementReference.UNKNOWN);
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_constDecl, version=0)
public void enterConstDecl(ConstDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_constDecl, version=0)
public void exitConstDecl(ConstDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_result, version=0)
public void enterResult(ResultContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_result, version=0)
public void exitResult(ResultContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterAndExpr(AndExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitAndExpr(AndExprContext ctx) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, BuiltinTypeReference.BOOL);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_structType, version=0)
public void enterStructType(StructTypeContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_structType, version=0)
public void exitStructType(StructTypeContext ctx) {
CodeElementReference codeClass = new StructTypeReference();
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.STRUCT);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_varDecl, version=0)
public void enterVarDecl(VarDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_varDecl, version=0)
public void exitVarDecl(VarDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_initStmt, version=0)
public void enterInitStmt(InitStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_initStmt, version=0)
public void exitInitStmt(InitStmtContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0)
public void enterIdentifierList(IdentifierListContext ctx) {
NodeType nodeType = treeDecorator.getProperty(ctx, GoAnnotations.NODE_TYPE);
VarKind varType = treeDecorator.getProperty(ctx, GoAnnotations.VAR_TYPE);
boolean variadic = treeDecorator.getProperty(ctx, GoAnnotations.VARIADIC);
ParserRuleContext explicitType = treeDecorator.getProperty(ctx, GoAnnotations.EXPLICIT_TYPE);
boolean global =
(varType != VarKind.LOCAL && varType != VarKind.RECEIVER && varType != VarKind.PARAMETER && varType != VarKind.RETURN)
|| treeDecorator.getProperty(ctx, GoAnnotations.GLOBAL);
if (nodeType == NodeType.VAR_DECL) {
if (varType == VarKind.UNDEFINED) {
return;
}
} else if (nodeType == NodeType.CONST_DECL) {
// nothing special to do here
} else {
return;
}
for (TerminalNode terminalNode : ctx.IDENTIFIER()) {
Token token = terminalNode.getSymbol();
if (nodeType == NodeType.VAR_DECL) {
if (varType != VarKind.FIELD) {
pendingVisibleLocals.peek().put(token.getText(), terminalNode);
}
} else {
assert nodeType == NodeType.CONST_DECL;
pendingVisibleConstants.peek().put(token.getText(), terminalNode);
}
treeDecorator.putProperty(terminalNode, GoAnnotations.NODE_TYPE, nodeType);
if (varType != null) {
treeDecorator.putProperty(terminalNode, GoAnnotations.VAR_TYPE, varType);
}
if (variadic) {
treeDecorator.putProperty(terminalNode, GoAnnotations.VARIADIC, variadic);
}
if (explicitType != null) {
treeDecorator.putProperty(terminalNode, GoAnnotations.EXPLICIT_TYPE, explicitType);
}
if (global) {
treeDecorator.putProperty(terminalNode, GoAnnotations.GLOBAL, global);
}
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_identifierList, version=0)
public void exitIdentifierList(IdentifierListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sliceType, version=0)
public void enterSliceType(SliceTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sliceType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
})
public void exitSliceType(SliceTypeContext ctx) {
CodeElementReference elemClass = CodeElementReference.UNKNOWN;
if (ctx.elementType() != null) {
elemClass = treeDecorator.getProperty(ctx.elementType(), GoAnnotations.CODE_CLASS);
}
CodeElementReference codeClass = new SliceTypeReference(elemClass);
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
treeDecorator.putProperty(ctx, GoAnnotations.NODE_TYPE, NodeType.TYPE_LITERAL);
treeDecorator.putProperty(ctx, GoAnnotations.TYPE_KIND, TypeKind.SLICE);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterCompareExpr(CompareExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitCompareExpr(CompareExprContext ctx) {
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, BuiltinTypeReference.BOOL);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importDecl, version=0)
public void enterImportDecl(ImportDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importDecl, version=0)
public void exitImportDecl(ImportDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementList, version=0)
public void enterElementList(ElementListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementList, version=0)
public void exitElementList(ElementListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_keyType, version=0)
public void enterKeyType(KeyTypeContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_keyType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
})
public void exitKeyType(KeyTypeContext ctx) {
CodeElementReference codeClass = CodeElementReference.UNKNOWN;
if (ctx.type() != null) {
codeClass = treeDecorator.getProperty(ctx.type(), GoAnnotations.CODE_CLASS);
}
treeDecorator.putProperty(ctx, GoAnnotations.CODE_CLASS, codeClass);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importPath, version=0)
public void enterImportPath(ImportPathContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_importPath, version=0)
public void exitImportPath(ImportPathContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_anonymousField, version=0)
public void enterAnonymousField(AnonymousFieldContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_anonymousField, version=0)
public void exitAnonymousField(AnonymousFieldContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterAddExpr(AddExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitAddExpr(AddExprContext ctx) {
CodeElementReference exprType = CodeElementReference.MISSING;
if (ctx.expression(0) != null && ctx.op != null && ctx.expression(1) != null) {
CodeElementReference left = treeDecorator.getProperty(ctx.expression(0), GoAnnotations.EXPR_TYPE);
CodeElementReference right = treeDecorator.getProperty(ctx.expression(1), GoAnnotations.EXPR_TYPE);
exprType = new BinaryExpressionTypeReference(left, ctx.op, right);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionStmt, version=0)
public void enterExpressionStmt(ExpressionStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expressionStmt, version=0)
public void exitExpressionStmt(ExpressionStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sendStmt, version=0)
public void enterSendStmt(SendStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sendStmt, version=0)
public void exitSendStmt(SendStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_switchStmt, version=0)
public void enterSwitchStmt(SwitchStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_switchStmt, version=0)
public void exitSwitchStmt(SwitchStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_postStmt, version=0)
public void enterPostStmt(PostStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_postStmt, version=0)
public void exitPostStmt(PostStmtContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_forStmt, version=0)
public void enterForStmt(ForStmtContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_forStmt, version=0)
public void exitForStmt(ForStmtContext ctx) {
popVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchCase, version=0)
public void enterTypeSwitchCase(TypeSwitchCaseContext ctx) {
pushVarScope();
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchCase, version=0)
public void exitTypeSwitchCase(TypeSwitchCaseContext ctx) {
popVarScope();
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_rangeClause, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void enterRangeClause(RangeClauseContext ctx) {
if (ctx.defeq != null) {
if (ctx.e1 != null && ctx.e1.start == ParseTrees.getStopSymbol(ctx.e1)) {
Token token = ctx.e1.start;
TerminalNode startNode = ParseTrees.getStartNode(ctx.e1);
pendingVisibleLocals.peek().put(token.getText(), startNode);
treeDecorator.putProperty(startNode, GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
treeDecorator.putProperty(startNode, GoAnnotations.VAR_TYPE, VarKind.LOCAL);
treeDecorator.putProperty(startNode, GoAnnotations.IMPLICIT_TYPE, ctx);
treeDecorator.putProperty(startNode, GoAnnotations.IMPLICIT_INDEX, 0);
}
if (ctx.e2 != null && ctx.e2.start == ParseTrees.getStopSymbol(ctx.e2)) {
Token token = ctx.e2.start;
TerminalNode startNode = ParseTrees.getStartNode(ctx.e2);
pendingVisibleLocals.peek().put(token.getText(), startNode);
treeDecorator.putProperty(startNode, GoAnnotations.NODE_TYPE, NodeType.VAR_DECL);
treeDecorator.putProperty(startNode, GoAnnotations.VAR_TYPE, VarKind.LOCAL);
treeDecorator.putProperty(startNode, GoAnnotations.IMPLICIT_TYPE, ctx);
treeDecorator.putProperty(startNode, GoAnnotations.IMPLICIT_INDEX, 1);
}
}
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_rangeClause, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitRangeClause(RangeClauseContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.e != null) {
exprType = new RangeClauseResultReference(treeDecorator.getProperty(ctx.e, GoAnnotations.EXPR_TYPE));
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
applyPendingVars();
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_operand, version=0)
public void enterOperand(OperandContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_operand, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literal, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_qualifiedIdentifier, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodExpr, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitOperand(OperandContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.literal() != null) {
exprType = treeDecorator.getProperty(ctx.literal(), GoAnnotations.EXPR_TYPE);
} else if (ctx.qualifiedIdentifier() != null) {
exprType = new QualifiedIdentifierElementReference(ctx.qualifiedIdentifier());
} else if (ctx.methodExpr() != null) {
exprType = treeDecorator.getProperty(ctx.methodExpr(), GoAnnotations.EXPR_TYPE);
} else if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
if (ctx.qualifiedIdentifier() != null) {
treeDecorator.putProperties(ctx, treeDecorator.getProperties(ctx.qualifiedIdentifier()));
} else {
LOGGER.log(Level.FINER, "Expression resolution links are not supported for context: {0}", ctx.toString(Arrays.asList(GoParser.ruleNames)));
}
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_argumentList, version=0)
public void enterArgumentList(ArgumentListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_argumentList, version=0)
public void exitArgumentList(ArgumentListContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchStmt, version=0)
public void enterTypeSwitchStmt(TypeSwitchStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeSwitchStmt, version=0)
public void exitTypeSwitchStmt(TypeSwitchStmtContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeDecl, version=0)
public void enterTypeDecl(TypeDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeDecl, version=0)
public void exitTypeDecl(TypeDeclContext ctx) {
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void enterUnaryExpr(UnaryExprContext ctx) {
}
@Override
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1)
public void exitUnaryExpr(UnaryExprContext ctx) {
CodeElementReference exprType = CodeElementReference.MISSING;
if (ctx.expression() != null && ctx.op != null) {
CodeElementReference e = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
exprType = new UnaryExpressionTypeReference(e, ctx.op);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channel, version=0)
public void enterChannel(ChannelContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channel, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
})
public void exitChannel(ChannelContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.expression() != null) {
exprType = treeDecorator.getProperty(ctx.expression(), GoAnnotations.EXPR_TYPE);
assert exprType != CodeElementReference.MISSING;
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
//@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literal, version=0)
public void enterLiteral(LiteralContext ctx) {
}
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literal, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_basicLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_compositeLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionLiteral, version=0),
})
public void exitLiteral(LiteralContext ctx) {
CodeElementReference exprType = CodeElementReference.UNKNOWN;
if (ctx.basicLiteral() != null) {
exprType = treeDecorator.getProperty(ctx.basicLiteral(), GoAnnotations.EXPR_TYPE);
} else if (ctx.compositeLiteral() != null) {
exprType = treeDecorator.getProperty(ctx.compositeLiteral(), GoAnnotations.EXPR_TYPE);
} else if (ctx.functionLiteral() != null) {
exprType = treeDecorator.getProperty(ctx.functionLiteral(), GoAnnotations.EXPR_TYPE);
}
treeDecorator.putProperty(ctx, GoAnnotations.EXPR_TYPE, exprType);
}
@Override
public void visitTerminal(TerminalNode node) {
Token symbol = node.getSymbol();
switch (symbol.getType()) {
case GoParser.Const:
_iota = BigInteger.ZERO;
break;
default:
break;
}
}
@Override
public void visitErrorNode(ErrorNode node) {
}
@Override
public void enterEveryRule(ParserRuleContext ctx) {
}
private static final Set<Class<? extends ParserRuleContext>> EXPR_TYPE_CONTEXTS =
new HashSet<Class<? extends ParserRuleContext>>() {{
add(ExpressionContext.class);
add(ConversionOrCallExprContext.class);
add(BuiltinCallContext.class);
add(SelectorExprContext.class);
add(IndexExprContext.class);
add(SliceExprContext.class);
add(TypeAssertionExprContext.class);
add(CallExprContext.class);
add(UnaryExprContext.class);
add(MultExprContext.class);
add(AddExprContext.class);
add(CompareExprContext.class);
add(AndExprContext.class);
add(OrExprContext.class);
add(OperandContext.class);
add(LiteralContext.class);
add(MethodExprContext.class);
add(BasicLiteralContext.class);
add(CompositeLiteralContext.class);
add(FunctionLiteralContext.class);
add(LiteralValueContext.class);
add(ValueContext.class);
add(ElementNameOrIndexContext.class);
add(ConversionContext.class);
add(ArrayLengthContext.class);
add(ChannelContext.class);
add(ConditionContext.class);
add(RecvExprContext.class);
add(RangeClauseContext.class);
}};
private static final Set<Class<? extends ParserRuleContext>> CODE_CLASS_CONTEXTS =
new HashSet<Class<? extends ParserRuleContext>>() {{
add(TypeContext.class);
add(TypeNameContext.class);
add(TypeLiteralContext.class);
add(ArrayTypeContext.class);
add(StructTypeContext.class);
add(PointerTypeContext.class);
add(FunctionTypeContext.class);
add(InterfaceTypeContext.class);
add(SliceTypeContext.class);
add(MapTypeContext.class);
add(ChannelTypeContext.class);
add(ElementTypeContext.class);
add(BaseTypeContext.class);
add(KeyTypeContext.class);
add(LiteralTypeContext.class);
}};
@Override
@RuleDependencies({
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_expression, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_builtinCall, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_operand, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literal, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_methodExpr, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_basicLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_compositeLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalValue, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_value, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementNameOrIndex, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_conversion, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayLength, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channel, version=1),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_condition, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_recvExpr, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_rangeClause, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_type, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeName, version=0, dependents=Dependents.SELF),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_typeLiteral, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_arrayType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_structType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_pointerType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_functionType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_interfaceType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_sliceType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_mapType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_channelType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_elementType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_baseType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_keyType, version=0),
@RuleDependency(recognizer=GoParser.class, rule=GoParser.RULE_literalType, version=0),
})
@SuppressWarnings("element-type-mismatch")
public void exitEveryRule(ParserRuleContext ctx) {
if (EXPR_TYPE_CONTEXTS.contains(ctx.getClass())) {
if (treeDecorator.getProperty(ctx, GoAnnotations.EXPR_TYPE) == CodeElementReference.MISSING) {
LOGGER.log(Level.WARNING, "Expected EXPR_TYPE data for context {0}.", ctx.getClass().getSimpleName());
}
}
if (CODE_CLASS_CONTEXTS.contains(ctx.getClass())) {
if (treeDecorator.getProperty(ctx, GoAnnotations.CODE_CLASS) == CodeElementReference.MISSING) {
LOGGER.log(Level.WARNING, "Expected CODE_TYPE data for context {0}.", ctx.getClass().getSimpleName());
}
}
}
private void pushVarScope() {
visibleLocals.push(new HashMap<String, TerminalNode>());
visibleConstants.push(new HashMap<String, TerminalNode>());
visibleFunctions.push(new HashMap<String, TerminalNode>());
visibleTypes.push(new HashMap<String, TerminalNode>());
pendingVisibleLocals.push(new HashMap<String, TerminalNode>());
pendingVisibleConstants.push(new HashMap<String, TerminalNode>());
}
private void popVarScope() {
visibleLocals.pop();
visibleConstants.pop();
visibleFunctions.pop();
visibleTypes.pop();
assert pendingVisibleLocals.peek().isEmpty();
assert pendingVisibleConstants.peek().isEmpty();
pendingVisibleLocals.pop();
pendingVisibleConstants.pop();
}
private void applyPendingVars() {
visibleLocals.peek().putAll(pendingVisibleLocals.peek());
pendingVisibleLocals.peek().clear();
visibleConstants.peek().putAll(pendingVisibleConstants.peek());
pendingVisibleConstants.peek().clear();
}
private TerminalNode getVisibleDeclaration(TerminalNode reference) {
TerminalNode result = getVisibleLocal(reference);
result = result != null ? result : getVisibleConstant(reference);
result = result != null ? result : getVisibleFunction(reference);
result = result != null ? result : getVisibleType(reference);
return result;
}
private TerminalNode getVisibleLocal(TerminalNode reference) {
return getVisibleElement(visibleLocals, reference);
}
private TerminalNode getVisibleConstant(TerminalNode reference) {
return getVisibleElement(visibleConstants, reference);
}
private TerminalNode getVisibleFunction(TerminalNode reference) {
return getVisibleElement(visibleFunctions, reference);
}
private TerminalNode getVisibleType(TerminalNode reference) {
return getVisibleElement(visibleTypes, reference);
}
private TerminalNode getVisibleElement(Collection<Map<String, TerminalNode>> elements, TerminalNode reference) {
for (Map<String, TerminalNode> localCollection : elements) {
TerminalNode local = localCollection.get(reference.getText());
if (local != null) {
return local;
}
}
return null;
}
}