logic: index and store Java annotations
* add annotation symbol kind * add annotation_usage edge kind * increment storage version * record java annotation decls * record java annotation member decls (as fields) * update expected output of java sample project indexing tests * add tests for recording annotations * add annotation icon, annotation colors * add new annotation node and edge types to legend
This commit is contained in:
@@ -8,6 +8,9 @@ import java.util.Stack;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.AnnotationTypeDeclaration;
|
||||
import org.eclipse.jdt.core.dom.AnnotationTypeMemberDeclaration;
|
||||
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
|
||||
import org.eclipse.jdt.core.dom.ArrayInitializer;
|
||||
import org.eclipse.jdt.core.dom.Block;
|
||||
@@ -21,6 +24,7 @@ import org.eclipse.jdt.core.dom.EnumDeclaration;
|
||||
import org.eclipse.jdt.core.dom.ExpressionMethodReference;
|
||||
import org.eclipse.jdt.core.dom.FieldAccess;
|
||||
import org.eclipse.jdt.core.dom.FieldDeclaration;
|
||||
import org.eclipse.jdt.core.dom.IAnnotationBinding;
|
||||
import org.eclipse.jdt.core.dom.IBinding;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.IPackageBinding;
|
||||
@@ -29,16 +33,20 @@ import org.eclipse.jdt.core.dom.IVariableBinding;
|
||||
import org.eclipse.jdt.core.dom.ImportDeclaration;
|
||||
import org.eclipse.jdt.core.dom.Javadoc;
|
||||
import org.eclipse.jdt.core.dom.LineComment;
|
||||
import org.eclipse.jdt.core.dom.MarkerAnnotation;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.MethodInvocation;
|
||||
import org.eclipse.jdt.core.dom.Name;
|
||||
import org.eclipse.jdt.core.dom.NameQualifiedType;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.PackageDeclaration;
|
||||
import org.eclipse.jdt.core.dom.PrimitiveType;
|
||||
import org.eclipse.jdt.core.dom.QualifiedName;
|
||||
import org.eclipse.jdt.core.dom.QualifiedType;
|
||||
import org.eclipse.jdt.core.dom.SimpleName;
|
||||
import org.eclipse.jdt.core.dom.SimpleType;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
|
||||
import org.eclipse.jdt.core.dom.SuperFieldAccess;
|
||||
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
|
||||
@@ -116,7 +124,60 @@ public abstract class AstVisitor extends ASTVisitor
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(AnnotationTypeDeclaration node)
|
||||
{
|
||||
DeclName symbolName = DeclNameResolver.getQualifiedDeclName(node, m_filePath, m_compilationUnit);
|
||||
Range scopeRange = getRange(node);
|
||||
|
||||
m_client.recordSymbolWithLocationAndScope(
|
||||
symbolName.toNameHierarchy(),
|
||||
SymbolKind.ANNOTATION,
|
||||
getRange(node.getName()),
|
||||
scopeRange,
|
||||
AccessKind.fromModifiers(node.getModifiers()),
|
||||
DefinitionKind.EXPLICIT);
|
||||
|
||||
scopeRange.begin = m_fileContent.findStartPosition("{", scopeRange.begin);
|
||||
recordScope(scopeRange);
|
||||
|
||||
m_contextStack.push(Arrays.asList(symbolName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(AnnotationTypeDeclaration node)
|
||||
{
|
||||
m_contextStack.pop();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(AnnotationTypeMemberDeclaration node)
|
||||
{
|
||||
DeclName symbolName = BindingNameResolver.getQualifiedName(node.resolveBinding(), m_filePath, m_compilationUnit).orElse(DeclName.unsolved());
|
||||
|
||||
m_client.recordSymbolWithLocation(
|
||||
symbolName.toNameHierarchy(),
|
||||
SymbolKind.FIELD,
|
||||
getRange(node.getName()),
|
||||
AccessKind.fromModifiers(node.getModifiers()),
|
||||
DefinitionKind.EXPLICIT);
|
||||
|
||||
m_contextStack.push(Arrays.asList(symbolName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(AnnotationTypeMemberDeclaration node)
|
||||
{
|
||||
m_contextStack.pop();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(TypeDeclaration node)
|
||||
@@ -153,7 +214,8 @@ public abstract class AstVisitor extends ASTVisitor
|
||||
DeclName symbolName = BindingNameResolver.getQualifiedName(node.resolveBinding(), m_filePath, m_compilationUnit).map(tn -> tn.toDeclName()).orElse(DeclName.unsolved());
|
||||
|
||||
m_client.recordSymbolWithLocation(
|
||||
symbolName.toNameHierarchy(), SymbolKind.TYPE_PARAMETER,
|
||||
symbolName.toNameHierarchy(),
|
||||
SymbolKind.TYPE_PARAMETER,
|
||||
getRange(node.getName()),
|
||||
AccessKind.TYPE_PARAMETER,
|
||||
DefinitionKind.EXPLICIT);
|
||||
@@ -316,7 +378,8 @@ public abstract class AstVisitor extends ASTVisitor
|
||||
DeclName symbolName = DeclNameResolver.getQualifiedDeclName(fragment, m_filePath, m_compilationUnit);
|
||||
|
||||
m_client.recordSymbolWithLocation(
|
||||
symbolName.toNameHierarchy(), SymbolKind.FIELD,
|
||||
symbolName.toNameHierarchy(),
|
||||
SymbolKind.FIELD,
|
||||
getRange(fragment.getName()),
|
||||
AccessKind.fromModifiers(node.getModifiers()),
|
||||
DefinitionKind.EXPLICIT);
|
||||
@@ -389,6 +452,70 @@ public abstract class AstVisitor extends ASTVisitor
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node)
|
||||
{
|
||||
return recordAnnotation(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(NormalAnnotation node)
|
||||
{
|
||||
for (Object value: node.values())
|
||||
{
|
||||
if (value instanceof MemberValuePair)
|
||||
{
|
||||
SimpleName name = ((MemberValuePair)value).getName();
|
||||
IBinding binding = name.resolveBinding();
|
||||
if (binding instanceof IMethodBinding)
|
||||
{
|
||||
DeclName symbolName = BindingNameResolver.getQualifiedName((IMethodBinding) binding, m_filePath, m_compilationUnit).orElse(DeclName.unsolved());
|
||||
|
||||
for (SymbolName context: m_contextStack.peek())
|
||||
{
|
||||
m_client.recordReference(ReferenceKind.USAGE, symbolName.toNameHierarchy(), context.toNameHierarchy(), getRange(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return recordAnnotation(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MarkerAnnotation node)
|
||||
{
|
||||
return recordAnnotation(node);
|
||||
}
|
||||
|
||||
private boolean recordAnnotation(Annotation node)
|
||||
{
|
||||
for (SymbolName context: m_contextStack.peek())
|
||||
{
|
||||
IAnnotationBinding annotationBinding = node.resolveAnnotationBinding();
|
||||
ITypeBinding typeBinding = null;
|
||||
if (annotationBinding != null)
|
||||
{
|
||||
typeBinding = annotationBinding.getAnnotationType();
|
||||
}
|
||||
|
||||
Range range = getRange(node.getTypeName());
|
||||
if (node.getTypeName() instanceof QualifiedName)
|
||||
{
|
||||
range = getRange(((QualifiedName) node.getTypeName()).getName());
|
||||
}
|
||||
|
||||
m_client.recordReference(
|
||||
ReferenceKind.ANNOTATION_USAGE,
|
||||
BindingNameResolver.getQualifiedName(typeBinding, m_filePath, m_compilationUnit).orElse(TypeName.unsolved()).toDeclName().toNameHierarchy(),
|
||||
context.toNameHierarchy(),
|
||||
range);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean visit(SimpleType node)
|
||||
|
||||
@@ -15,7 +15,8 @@ public enum ReferenceKind
|
||||
TEMPLATE_MEMBER_SPECIALIZATION_OF(10),
|
||||
INCLUDE(11),
|
||||
IMPORT(12),
|
||||
MACRO_USAGE(13);
|
||||
MACRO_USAGE(13),
|
||||
ANNOTATION_USAGE(14);
|
||||
|
||||
private final int m_value;
|
||||
|
||||
|
||||
@@ -2,26 +2,27 @@ package com.sourcetrail;
|
||||
|
||||
public enum SymbolKind
|
||||
{ // these values need to be the same as SymbolKind in C++ code
|
||||
BUILTIN_TYPE(1),
|
||||
CLASS(2),
|
||||
ENUM(3),
|
||||
ENUM_CONSTANT(4),
|
||||
FIELD(5),
|
||||
FUNCTION(6),
|
||||
GLOBAL_VARIABLE(7),
|
||||
INTERFACE(8),
|
||||
LOCAL_VARIABLE(9),
|
||||
MACRO(10),
|
||||
METHOD(11),
|
||||
NAMESPACE(12),
|
||||
PACKAGE(13),
|
||||
PARAMETER(14),
|
||||
STRUCT(15),
|
||||
TEMPLATE_PARAMETER(16),
|
||||
TYPEDEF(17),
|
||||
TYPE_PARAMETER(18),
|
||||
UNION(19),
|
||||
TYPE_MAX(20);
|
||||
ANNOTATION(1),
|
||||
BUILTIN_TYPE(2),
|
||||
CLASS(3),
|
||||
ENUM(4),
|
||||
ENUM_CONSTANT(5),
|
||||
FIELD(6),
|
||||
FUNCTION(7),
|
||||
GLOBAL_VARIABLE(8),
|
||||
INTERFACE(9),
|
||||
LOCAL_VARIABLE(10),
|
||||
MACRO(11),
|
||||
METHOD(12),
|
||||
NAMESPACE(13),
|
||||
PACKAGE(14),
|
||||
PARAMETER(15),
|
||||
STRUCT(16),
|
||||
TEMPLATE_PARAMETER(17),
|
||||
TYPEDEF(18),
|
||||
TYPE_PARAMETER(19),
|
||||
UNION(20),
|
||||
TYPE_MAX(21);
|
||||
|
||||
private final int m_value;
|
||||
|
||||
|
||||
@@ -200,21 +200,31 @@ public class BindingNameResolver extends NameResolver
|
||||
}
|
||||
}
|
||||
|
||||
ContextList ignoredContexts = m_ignoredContexts.copy();
|
||||
ignoredContexts.add(binding);
|
||||
|
||||
TypeName returnTypeName = binding.isConstructor() ? null : getQualifiedName(binding.getReturnType(), m_currentFile, m_compilationUnit, ignoredContexts).orElse(TypeName.unsolved());
|
||||
|
||||
List<TypeName> parameterTypeNames = new ArrayList<>();
|
||||
for (ITypeBinding parameterType: binding.getParameterTypes())
|
||||
DeclName declName = null;
|
||||
{
|
||||
parameterTypeNames.add(getQualifiedName(parameterType, m_currentFile, m_compilationUnit, ignoredContexts).orElse(TypeName.unsolved()));
|
||||
boolean isStatic = Modifier.isStatic(binding.getModifiers());
|
||||
|
||||
ContextList ignoredContexts = m_ignoredContexts.copy();
|
||||
ignoredContexts.add(binding);
|
||||
|
||||
TypeName returnTypeName = binding.isConstructor() ? null : getQualifiedName(binding.getReturnType(), m_currentFile, m_compilationUnit, ignoredContexts).orElse(TypeName.unsolved());
|
||||
|
||||
if (binding.isAnnotationMember())
|
||||
{
|
||||
declName = new VariableDeclName(name, returnTypeName, isStatic);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<TypeName> parameterTypeNames = new ArrayList<>();
|
||||
for (ITypeBinding parameterType: binding.getParameterTypes())
|
||||
{
|
||||
parameterTypeNames.add(getQualifiedName(parameterType, m_currentFile, m_compilationUnit, ignoredContexts).orElse(TypeName.unsolved()));
|
||||
}
|
||||
|
||||
declName = new FunctionDeclName(name, typeParameterNames, returnTypeName, parameterTypeNames, isStatic);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isStatic = Modifier.isStatic(binding.getModifiers());
|
||||
|
||||
FunctionDeclName declName = new FunctionDeclName(name, typeParameterNames, returnTypeName, parameterTypeNames, isStatic);
|
||||
|
||||
DeclName parentDeclName = getQualifiedContextName(binding);
|
||||
if (parentDeclName != null)
|
||||
{
|
||||
|
||||
@@ -151,7 +151,7 @@ public class DeclNameResolver extends NameResolver
|
||||
{
|
||||
if (decl instanceof AnnotationTypeDeclaration)
|
||||
{
|
||||
declName = new DeclName("AnnotationTypeDeclaration");
|
||||
declName = new DeclName(((AnnotationTypeDeclaration) decl).getName().getIdentifier());
|
||||
}
|
||||
else if (decl instanceof EnumDeclaration)
|
||||
{
|
||||
@@ -174,7 +174,7 @@ public class DeclNameResolver extends NameResolver
|
||||
}
|
||||
else if (decl instanceof AnnotationTypeMemberDeclaration)
|
||||
{
|
||||
declName = new DeclName("AnnotationTypeMemberDeclaration");
|
||||
declName = new DeclName(((AnnotationTypeMemberDeclaration) decl).getName().getIdentifier());
|
||||
}
|
||||
else if (decl instanceof EnumConstantDeclaration)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user