build: switch to Maven configuration for JavaIndexer
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import com.github.javaparser.ast.AccessSpecifier;
|
||||
|
||||
public enum AccessKind
|
||||
{ // these values need to be the same as AccesKind in C++ code
|
||||
NONE(0),
|
||||
PUBLIC(1),
|
||||
PROTECTED(2),
|
||||
PRIVATE(3),
|
||||
DEFAULT(4),
|
||||
TEMPLATE_PARAMETER(5),
|
||||
TYPE_PARAMETER(6);
|
||||
|
||||
private final int m_value;
|
||||
|
||||
private AccessKind(int value)
|
||||
{
|
||||
this.m_value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
public static AccessKind fromAccessSpecifier(AccessSpecifier specifier)
|
||||
{
|
||||
switch (specifier)
|
||||
{
|
||||
case PUBLIC:
|
||||
return AccessKind.PUBLIC;
|
||||
case PROTECTED:
|
||||
return AccessKind.PROTECTED;
|
||||
case PRIVATE:
|
||||
return AccessKind.PRIVATE;
|
||||
case DEFAULT:
|
||||
return AccessKind.DEFAULT;
|
||||
default:
|
||||
return AccessKind.NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,958 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.lang.String;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
|
||||
import com.github.javaparser.ast.body.ConstructorDeclaration;
|
||||
import com.github.javaparser.ast.body.EnumConstantDeclaration;
|
||||
import com.github.javaparser.ast.body.EnumDeclaration;
|
||||
import com.github.javaparser.ast.body.FieldDeclaration;
|
||||
import com.github.javaparser.ast.body.MethodDeclaration;
|
||||
import com.github.javaparser.ast.body.Parameter;
|
||||
import com.github.javaparser.ast.body.VariableDeclarator;
|
||||
import com.github.javaparser.ast.comments.BlockComment;
|
||||
import com.github.javaparser.ast.comments.LineComment;
|
||||
import com.github.javaparser.ast.expr.ArrayInitializerExpr;
|
||||
import com.github.javaparser.ast.expr.FieldAccessExpr;
|
||||
import com.github.javaparser.ast.expr.MethodCallExpr;
|
||||
import com.github.javaparser.ast.expr.Name;
|
||||
import com.github.javaparser.ast.expr.NameExpr;
|
||||
import com.github.javaparser.ast.expr.ObjectCreationExpr;
|
||||
import com.github.javaparser.ast.expr.SimpleName;
|
||||
import com.github.javaparser.ast.expr.VariableDeclarationExpr;
|
||||
import com.github.javaparser.ast.stmt.BlockStmt;
|
||||
import com.github.javaparser.ast.stmt.SwitchStmt;
|
||||
import com.github.javaparser.ast.type.ClassOrInterfaceType;
|
||||
import com.github.javaparser.ast.type.PrimitiveType;
|
||||
import com.github.javaparser.ast.type.Type;
|
||||
import com.github.javaparser.ast.type.TypeParameter;
|
||||
import com.github.javaparser.ast.type.VoidType;
|
||||
import com.github.javaparser.Position;
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.ast.ImportDeclaration;
|
||||
import com.github.javaparser.ast.Modifier;
|
||||
import com.github.javaparser.ast.Node;
|
||||
import com.github.javaparser.ast.PackageDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserConstructorDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserFieldDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserParameterDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserSymbolDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.MethodAmbiguityException;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.ReferenceTypeDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.ValueDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.SymbolReference;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.UnsolvedSymbolException;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.*;
|
||||
import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic;
|
||||
|
||||
public class AstVisitor extends AstVisitorAdapter
|
||||
{
|
||||
protected AstVisitorClient m_client = null;
|
||||
private String m_filePath;
|
||||
private FileContent m_fileContent;
|
||||
private TypeSolver m_typeSolver;
|
||||
private List<DeclContext> m_context = new ArrayList<DeclContext>();
|
||||
|
||||
public AstVisitor(AstVisitorClient client, String filePath, FileContent fileContent, TypeSolver typeSolver)
|
||||
{
|
||||
m_client = client;
|
||||
m_filePath = filePath;
|
||||
m_fileContent = fileContent;
|
||||
m_typeSolver = typeSolver;
|
||||
|
||||
m_context.add(new DeclContext("/\tm" + filePath + "\ts\tp"));
|
||||
}
|
||||
|
||||
// --- record declarations ---
|
||||
|
||||
@Override public void visit(final PackageDeclaration n, final Void v)
|
||||
{
|
||||
Name name = n.getName();
|
||||
|
||||
m_client.recordSymbolWithLocationAndScope(
|
||||
JavaparserDeclNameResolver.getQualifiedName(name).toSerializedNameHierarchy(),
|
||||
SymbolKind.PACKAGE,
|
||||
name.getRange(),
|
||||
n.getRange(),
|
||||
AccessKind.NONE,
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
while (name.getQualifier().isPresent())
|
||||
{
|
||||
name = name.getQualifier().get();
|
||||
m_client.recordSymbol(
|
||||
JavaparserDeclNameResolver.getQualifiedName(name).toSerializedNameHierarchy(),
|
||||
SymbolKind.PACKAGE,
|
||||
AccessKind.NONE,
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final ClassOrInterfaceDeclaration n, final Void v)
|
||||
{
|
||||
SimpleName name = n.getName();
|
||||
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbolWithLocationAndScope(
|
||||
qualifiedName, (n.isInterface() ? SymbolKind.INTERFACE : SymbolKind.CLASS),
|
||||
name.getRange(),
|
||||
n.getRange(),
|
||||
AccessKind.fromAccessSpecifier(Modifier.getAccessSpecifier(n.getModifiers())),
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
if (n.getRange().isPresent())
|
||||
{
|
||||
FileContent.Location scopeStartLocation = m_fileContent.find("{", n.getBegin());
|
||||
recordScope(Range.range(scopeStartLocation.line, scopeStartLocation.column, n.getRange().get().end.line, n.getRange().get().end.column));
|
||||
}
|
||||
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
@Override public void visit(final TypeParameter n, final Void v)
|
||||
{
|
||||
// todo: test recording of typeargument of type parameter bound type??
|
||||
|
||||
|
||||
|
||||
if (m_context.size() != 1)
|
||||
{
|
||||
// throw something!
|
||||
}
|
||||
|
||||
String qualifiedName = m_context.get(0).getName();
|
||||
qualifiedName += "\tn";
|
||||
qualifiedName += n.getName() + "\ts\tp";
|
||||
|
||||
|
||||
Optional<Range> range = Optional.empty();
|
||||
if (n.getBegin().isPresent())
|
||||
{
|
||||
range = Optional.of(Range.range(
|
||||
n.getBegin().get().line,
|
||||
n.getBegin().get().column,
|
||||
n.getBegin().get().line,
|
||||
n.getBegin().get().column + n.getNameAsString().length() - 1
|
||||
));
|
||||
}
|
||||
|
||||
m_client.recordSymbolWithLocation(
|
||||
qualifiedName, SymbolKind.TYPE_PARAMETER,
|
||||
range,
|
||||
AccessKind.TYPE_PARAMETER,
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
@Override public void visit(final EnumDeclaration n, final Void v)
|
||||
{
|
||||
SimpleName name = n.getName();
|
||||
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbolWithLocationAndScope(
|
||||
qualifiedName, SymbolKind.ENUM,
|
||||
name.getRange(),
|
||||
n.getRange(),
|
||||
AccessKind.fromAccessSpecifier(Modifier.getAccessSpecifier(n.getModifiers())),
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
if (n.getRange().isPresent())
|
||||
{
|
||||
FileContent.Location scopeStartLocation = m_fileContent.find("{", n.getBegin());
|
||||
recordScope(Range.range(scopeStartLocation.line, scopeStartLocation.column, n.getRange().get().end.line, n.getRange().get().end.column));
|
||||
}
|
||||
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
@Override public void visit(final EnumConstantDeclaration n, final Void v)
|
||||
{
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbolWithLocation(
|
||||
qualifiedName, SymbolKind.ENUM_CONSTANT,
|
||||
n.getRange(),
|
||||
AccessKind.NONE,
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
@Override public void visit(final ConstructorDeclaration n, final Void v)
|
||||
{
|
||||
SimpleName name = n.getName();
|
||||
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbolWithLocationAndScope(
|
||||
qualifiedName, SymbolKind.METHOD,
|
||||
name.getRange(),
|
||||
n.getRange(),
|
||||
AccessKind.fromAccessSpecifier(Modifier.getAccessSpecifier(n.getModifiers())),
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
@Override public void visit(final MethodDeclaration n, final Void v)
|
||||
{
|
||||
SimpleName name = n.getName();
|
||||
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbolWithLocationAndScope(
|
||||
qualifiedName, SymbolKind.METHOD,
|
||||
name.getRange(),
|
||||
n.getRange(),
|
||||
AccessKind.fromAccessSpecifier(Modifier.getAccessSpecifier(n.getModifiers())),
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
|
||||
// test this!
|
||||
com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration overridden = getOverridden(n);
|
||||
if (overridden != null && (overridden instanceof JavaParserMethodDeclaration))
|
||||
{
|
||||
String overriddenName = JavaparserDeclNameResolver.getQualifiedDeclName(((JavaParserMethodDeclaration)overridden).getWrappedNode(), m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordReference(
|
||||
ReferenceKind.OVERRIDE, overriddenName, qualifiedName,
|
||||
name.getRange()
|
||||
);
|
||||
}
|
||||
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
private com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration getOverridden(MethodDeclaration overrider)
|
||||
{
|
||||
com.github.javaparser.ast.body.TypeDeclaration<?> scopeNode = overrider.getAncestorOfType(com.github.javaparser.ast.body.TypeDeclaration.class).get();
|
||||
if (scopeNode instanceof ClassOrInterfaceDeclaration)
|
||||
{
|
||||
List<com.github.javaparser.symbolsolver.model.typesystem.Type> parameterTypes = new ArrayList<>();
|
||||
try
|
||||
{
|
||||
for (Parameter parameter: overrider.getParameters())
|
||||
{
|
||||
Type parameterType = parameter.getType();
|
||||
parameterTypes.add(JavaParserFacade.get(m_typeSolver).convert(parameterType, parameterType));
|
||||
}
|
||||
|
||||
ReferenceTypeDeclaration scopeDecl = JavaParserFacade.get(m_typeSolver).getTypeDeclaration((ClassOrInterfaceDeclaration)scopeNode);
|
||||
for (ReferenceType ancestor: scopeDecl.getAllAncestors())
|
||||
{
|
||||
try
|
||||
{
|
||||
SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration> solvedMethod = MethodResolutionLogic.solveMethodInType(
|
||||
ancestor.getTypeDeclaration(),
|
||||
overrider.getNameAsString(),
|
||||
parameterTypes,
|
||||
m_typeSolver
|
||||
);
|
||||
|
||||
if (solvedMethod.isSolved())
|
||||
{
|
||||
return solvedMethod.getCorrespondingDeclaration();
|
||||
}
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
// nothing to do here, just try to solve in the next ancestor
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// hmm, maybe we should handle these cases. soon..
|
||||
// don't do anything for parse exceptions. they are displayed as errors anyways.
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (UnsolvedSymbolException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
catch (ClassCastException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override public void visit(final FieldDeclaration n, final Void v)
|
||||
{
|
||||
List<DeclContext> parentContext = m_context;
|
||||
m_context = new ArrayList<DeclContext>();
|
||||
|
||||
for (VariableDeclarator declarator: n.getVariables())
|
||||
{
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(declarator, m_typeSolver).toSerializedNameHierarchy();
|
||||
SimpleName name = declarator.getName();
|
||||
|
||||
m_client.recordSymbolWithLocation(
|
||||
qualifiedName, SymbolKind.FIELD,
|
||||
name.getRange(),
|
||||
AccessKind.fromAccessSpecifier(Modifier.getAccessSpecifier(n.getModifiers())),
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
m_context.add(new DeclContext(qualifiedName));
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
m_context = parentContext;
|
||||
}
|
||||
|
||||
@Override public void visit(final VariableDeclarationExpr n, final Void v)
|
||||
{
|
||||
for (VariableDeclarator declarator: n.getVariables())
|
||||
{
|
||||
SimpleName name = declarator.getName();
|
||||
|
||||
if (name.getBegin().isPresent())
|
||||
{
|
||||
String qualifiedName = m_filePath + "<" + name.getBegin().get().line + ":" + name.getBegin().get().column + ">";
|
||||
|
||||
m_client.recordLocalSymbol(qualifiedName, name.getRange());
|
||||
}
|
||||
}
|
||||
|
||||
// don't change the context here.
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final Parameter n, final Void v)
|
||||
{
|
||||
SimpleName name = n.getName();
|
||||
|
||||
if (name.getBegin().isPresent())
|
||||
{
|
||||
String qualifiedName = m_filePath + "<" + name.getBegin().get().line + ":" + name.getBegin().get().column + ">";
|
||||
|
||||
m_client.recordLocalSymbol(qualifiedName, name.getRange());
|
||||
}
|
||||
|
||||
// don't change the context here.
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
|
||||
// --- record references ---
|
||||
|
||||
@Override
|
||||
public void visit(final ImportDeclaration n, final Void v)
|
||||
{
|
||||
Name name = n.getName();
|
||||
|
||||
if (n.isAsterisk())
|
||||
{
|
||||
String importedName = JavaparserDeclNameResolver.getQualifiedName(name).toSerializedNameHierarchy();
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.IMPORT,
|
||||
importedName, context.getName(),
|
||||
name.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
List<JavaDeclName> importedDeclNames = new ArrayList<>();
|
||||
|
||||
SymbolReference<ReferenceTypeDeclaration> solvedTypeDeclatarion = m_typeSolver.tryToSolveType(name.asString());
|
||||
if (solvedTypeDeclatarion.isSolved())
|
||||
{
|
||||
importedDeclNames.add(JavaSymbolSolverDeclNameResolver.getQualifiedDeclName(solvedTypeDeclatarion.getCorrespondingDeclaration(), m_typeSolver));
|
||||
}
|
||||
else if (n.isStatic())
|
||||
{
|
||||
String typeName = name.getQualifier().get().asString();
|
||||
String memberName = name.getIdentifier();
|
||||
|
||||
ReferenceTypeDeclaration solvedDecl = m_typeSolver.solveType(typeName);
|
||||
|
||||
for (com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration methodDecl: solvedDecl.getDeclaredMethods()) // look for method
|
||||
{
|
||||
if (methodDecl.getName().equals(memberName))
|
||||
{
|
||||
importedDeclNames.add(
|
||||
JavaSymbolSolverDeclNameResolver.getQualifiedDeclName(methodDecl, m_typeSolver
|
||||
));
|
||||
}
|
||||
}
|
||||
if (importedDeclNames.isEmpty() && solvedDecl.hasField(memberName)) // look for field
|
||||
{
|
||||
JavaDeclName importedTypeDeclName = JavaSymbolSolverDeclNameResolver.getQualifiedDeclName(solvedDecl, m_typeSolver);
|
||||
if (importedTypeDeclName != null)
|
||||
{
|
||||
JavaDeclName importedDeclName = new JavaDeclName(memberName);
|
||||
importedDeclName.setParent(importedTypeDeclName);
|
||||
importedDeclNames.add(importedDeclName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!importedDeclNames.isEmpty())
|
||||
{
|
||||
for (JavaDeclName importedDeclName: importedDeclNames)
|
||||
{
|
||||
String nameHierarchy = importedDeclName.toSerializedNameHierarchy();
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.IMPORT,
|
||||
nameHierarchy, context.getName(),
|
||||
n.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_client.recordError("Import not found: " + name, true, true, n.getRange());
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
}
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final ClassOrInterfaceType n, final Void v)
|
||||
{
|
||||
try
|
||||
{
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
Range range = Range.range(0, 0, 0, 0);
|
||||
|
||||
if (n.getRange().isPresent())
|
||||
{
|
||||
range = Range.range(
|
||||
n.getRange().get().begin.line,
|
||||
n.getRange().get().begin.column,
|
||||
n.getRange().get().begin.line,
|
||||
n.getRange().get().begin.column + n.getNameAsString().length() - 1
|
||||
);
|
||||
}
|
||||
|
||||
Optional<ClassOrInterfaceType> scope = n.getScope();
|
||||
if (scope.isPresent())
|
||||
{
|
||||
Optional<Position> position = scope.get().getEnd();
|
||||
|
||||
if (position.isPresent())
|
||||
{
|
||||
range = range.withEnd(
|
||||
Position.pos(position.get().line,
|
||||
position.get().column + n.getNameAsString().length() + 1 // +1 for separator
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
m_client.recordReference(
|
||||
getTypeReferenceKind(), referencedName, context.getName(), range
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final PrimitiveType n, final Void v)
|
||||
{
|
||||
try
|
||||
{
|
||||
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbol(
|
||||
referencedName, SymbolKind.BUILTIN_TYPE,
|
||||
AccessKind.NONE,
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
getTypeReferenceKind(), referencedName, context.getName(),
|
||||
n.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final VoidType n, final Void v)
|
||||
{
|
||||
try
|
||||
{
|
||||
String referencedName = JavaparserTypeNameResolver.getQualifiedTypeName(n, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
m_client.recordSymbol(
|
||||
referencedName, SymbolKind.BUILTIN_TYPE, AccessKind.NONE, DefinitionKind.EXPLICIT
|
||||
);
|
||||
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
getTypeReferenceKind(), referencedName, context.getName(), n.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final FieldAccessExpr n, final Void v)
|
||||
{
|
||||
SimpleName fieldName = n.getField();
|
||||
|
||||
try
|
||||
{
|
||||
SymbolReference<? extends ValueDeclaration> ref = JavaParserFacade.get(m_typeSolver).solve(fieldName);
|
||||
if (ref.isSolved())
|
||||
{
|
||||
ValueDeclaration valueDecl = ref.getCorrespondingDeclaration();
|
||||
|
||||
Node wrappedNode = null;
|
||||
if (valueDecl instanceof JavaParserFieldDeclaration)
|
||||
{
|
||||
wrappedNode = ((JavaParserFieldDeclaration)valueDecl).getWrappedNode();
|
||||
}
|
||||
if (wrappedNode != null && wrappedNode instanceof FieldDeclaration)
|
||||
{
|
||||
|
||||
for (VariableDeclarator var: ((FieldDeclaration)wrappedNode).getVariables())
|
||||
{
|
||||
if (var.getName().getIdentifier().equals(fieldName.getIdentifier()))
|
||||
{
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(var, m_typeSolver).toSerializedNameHierarchy();
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.USAGE, qualifiedName, context.getName(),
|
||||
fieldName.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final NameExpr n, final Void v)
|
||||
{
|
||||
try
|
||||
{
|
||||
recordRef(n);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
private void recordRef(NameExpr e)
|
||||
{
|
||||
SymbolReference<? extends ValueDeclaration> ref = JavaParserFacade.get(m_typeSolver).solve(e);
|
||||
if (ref.isSolved())
|
||||
{
|
||||
ValueDeclaration valueDecl = ref.getCorrespondingDeclaration();
|
||||
|
||||
Node wrappedNode = null;
|
||||
if (valueDecl instanceof JavaParserSymbolDeclaration)
|
||||
{
|
||||
wrappedNode = ((JavaParserSymbolDeclaration)valueDecl).getWrappedNode();
|
||||
}
|
||||
else if (valueDecl instanceof JavaParserParameterDeclaration)
|
||||
{
|
||||
wrappedNode = ((JavaParserParameterDeclaration)valueDecl).getWrappedNode();
|
||||
}
|
||||
else if (valueDecl instanceof JavaParserFieldDeclaration)
|
||||
{
|
||||
wrappedNode = ((JavaParserFieldDeclaration)valueDecl).getWrappedNode();
|
||||
}
|
||||
|
||||
if (wrappedNode != null)
|
||||
{
|
||||
if (wrappedNode instanceof FieldDeclaration)
|
||||
{
|
||||
|
||||
for (VariableDeclarator var: ((FieldDeclaration)wrappedNode).getVariables())
|
||||
{
|
||||
if (var.getName().getIdentifier().equals(e.getName().getIdentifier()))
|
||||
{
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(var, m_typeSolver).toSerializedNameHierarchy();
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.USAGE, qualifiedName, context.getName(),
|
||||
e.getName().getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (wrappedNode instanceof Parameter)
|
||||
{
|
||||
SimpleName name = ((Parameter)wrappedNode).getName();
|
||||
if (name.getBegin().isPresent())
|
||||
{
|
||||
String qualifiedName = m_filePath + "<" + name.getBegin().get().line + ":" + name.getBegin().get().column + ">";
|
||||
|
||||
m_client.recordLocalSymbol(
|
||||
qualifiedName,
|
||||
e.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (wrappedNode instanceof VariableDeclarator)
|
||||
{
|
||||
if (wrappedNode.getAncestorOfType(FieldDeclaration.class).isPresent())
|
||||
{
|
||||
String qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName((VariableDeclarator)wrappedNode, m_typeSolver).toSerializedNameHierarchy();
|
||||
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.USAGE, qualifiedName, context.getName(),
|
||||
e.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleName name = ((VariableDeclarator)wrappedNode).getName();
|
||||
if (name.getBegin().isPresent())
|
||||
{
|
||||
String qualifiedName = m_filePath + "<" + name.getBegin().get().line + ":" + name.getBegin().get().column + ">";
|
||||
|
||||
m_client.recordLocalSymbol(
|
||||
qualifiedName,
|
||||
e.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visit(final MethodCallExpr n, final Void v)
|
||||
{
|
||||
String qualifiedName = "";
|
||||
if (m_context.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
SymbolReference<com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration> solvedSymbol = JavaParserFacade.get(m_typeSolver).solve(n);
|
||||
if (solvedSymbol.isSolved())
|
||||
{
|
||||
qualifiedName = getQualifiedName(solvedSymbol.getCorrespondingDeclaration());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnsolvedSymbolException(n.getNameAsString());
|
||||
}
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
catch (MethodAmbiguityException e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
catch(StackOverflowError e)
|
||||
{
|
||||
recordError(e, n);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
}
|
||||
|
||||
if (!qualifiedName.isEmpty())
|
||||
{
|
||||
SimpleName name = n.getName();
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.CALL, qualifiedName, context.getName(),
|
||||
name.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
|
||||
private void recordException(Exception e, Node n)
|
||||
{
|
||||
recordExceptionOrError(e.getClass().getSimpleName(), n);
|
||||
}
|
||||
|
||||
private void recordError(Error e, Node n)
|
||||
{
|
||||
recordExceptionOrError(e.getClass().getSimpleName(), n);
|
||||
}
|
||||
|
||||
private void recordExceptionOrError(String e, Node n)
|
||||
{
|
||||
String beginLine = "?";
|
||||
String beginColumn = "?";
|
||||
|
||||
if (n.getBegin().isPresent())
|
||||
{
|
||||
beginLine = n.getBegin().get().line + "";
|
||||
beginColumn = n.getBegin().get().column + "";
|
||||
}
|
||||
|
||||
m_client.logError(e + " at " + m_filePath + "<"+ beginLine + ", " + beginColumn + ">");
|
||||
m_client.recordSymbolWithLocation(
|
||||
".\tmunsolved-symbol\ts\tp", SymbolKind.TYPE_MAX,
|
||||
n.getRange(),
|
||||
AccessKind.DEFAULT,
|
||||
DefinitionKind.EXPLICIT
|
||||
);
|
||||
}
|
||||
|
||||
@Override public void visit(final ObjectCreationExpr n, final Void v)
|
||||
{
|
||||
String qualifiedName = "";
|
||||
if (m_context.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
SymbolReference<com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration> solvedSymbol = JavaParserFacade.get(m_typeSolver).solve(n);
|
||||
if (solvedSymbol.isSolved())
|
||||
{
|
||||
qualifiedName = getQualifiedName(solvedSymbol.getCorrespondingDeclaration());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnsolvedSymbolException("constructor for " + n.getType().getNameAsString());
|
||||
}
|
||||
}
|
||||
catch (UnsupportedOperationException e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
catch (MethodAmbiguityException e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
catch(StackOverflowError e)
|
||||
{
|
||||
recordError(e, n);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
recordException(e, n);
|
||||
}
|
||||
}
|
||||
|
||||
if (!qualifiedName.isEmpty())
|
||||
{
|
||||
ClassOrInterfaceType type = n.getType();
|
||||
for (DeclContext context: m_context)
|
||||
{
|
||||
m_client.recordReference(
|
||||
ReferenceKind.CALL, qualifiedName, context.getName(),
|
||||
type.getRange()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
private String getQualifiedName(com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration method)
|
||||
{
|
||||
String qualifiedName = "";
|
||||
if (method instanceof JavaParserMethodDeclaration)
|
||||
{
|
||||
MethodDeclaration wrappedNode = ((JavaParserMethodDeclaration)method).getWrappedNode();
|
||||
qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(wrappedNode, m_typeSolver).toSerializedNameHierarchy();
|
||||
}
|
||||
else // todo: move this implementation somewhere else
|
||||
{
|
||||
qualifiedName = ".\tm" + method.declaringType().getQualifiedName();
|
||||
qualifiedName = qualifiedName.replace(".", "\ts\tp\tn");
|
||||
|
||||
qualifiedName += "\ts\tp\tn" + method.getName() + "\ts";
|
||||
|
||||
String returnType = method.getReturnType().describe();
|
||||
qualifiedName += returnType;
|
||||
// qualifiedName += returnType.substring(returnType.lastIndexOf(".") + 1);
|
||||
|
||||
qualifiedName += "\tp(";
|
||||
for (int i = 0; i < method.getNumberOfParams(); i++)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
qualifiedName += (", ");
|
||||
}
|
||||
String paramType = method.getParam(i).describeType();
|
||||
qualifiedName += paramType;
|
||||
// qualifiedName += paramType.substring(paramType.lastIndexOf(".") + 1);
|
||||
}
|
||||
qualifiedName = qualifiedName.concat(")");
|
||||
}
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
private String getQualifiedName(com.github.javaparser.symbolsolver.model.declarations.ConstructorDeclaration constructor)
|
||||
{
|
||||
String qualifiedName = "";
|
||||
if (constructor instanceof JavaParserConstructorDeclaration)
|
||||
{
|
||||
ConstructorDeclaration wrappedNode = ((JavaParserConstructorDeclaration)constructor).getWrappedNode();
|
||||
qualifiedName = JavaparserDeclNameResolver.getQualifiedDeclName(wrappedNode, m_typeSolver).toSerializedNameHierarchy();
|
||||
}
|
||||
else // todo: move this implementation somewhere else
|
||||
{
|
||||
qualifiedName = ".\tm" + constructor.declaringType().getQualifiedName();
|
||||
qualifiedName = qualifiedName.replace(".", "\ts\tp\tn");
|
||||
|
||||
qualifiedName += "\ts\tp\tn" + constructor.getName() + "\ts\tp(";
|
||||
for (int i = 0; i < constructor.getNumberOfParams(); i++)
|
||||
{
|
||||
if(i != 0)
|
||||
{
|
||||
qualifiedName += (", ");
|
||||
}
|
||||
String paramType = constructor.getParam(i).describeType();
|
||||
qualifiedName += paramType;
|
||||
// qualifiedName += paramType.substring(paramType.lastIndexOf(".") + 1);
|
||||
}
|
||||
qualifiedName = qualifiedName.concat(")");
|
||||
}
|
||||
return qualifiedName;
|
||||
}
|
||||
|
||||
@Override public void visit(final BlockStmt n, final Void v)
|
||||
{
|
||||
recordScope(n.getRange());
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final ArrayInitializerExpr n, final Void v)
|
||||
{
|
||||
recordScope(n.getRange());
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final SwitchStmt n, final Void v)
|
||||
{
|
||||
if (n.getRange().isPresent())
|
||||
{
|
||||
FileContent.Location scopeStartLocation = m_fileContent.find("{", n.getBegin());
|
||||
recordScope(Range.range(scopeStartLocation.line, scopeStartLocation.column, n.getRange().get().end.line, n.getRange().get().end.column));
|
||||
}
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
private void recordScope(Optional<Range> range)
|
||||
{
|
||||
if (range.isPresent())
|
||||
{
|
||||
recordScope(range.get());
|
||||
}
|
||||
}
|
||||
|
||||
private void recordScope(Range range)
|
||||
{
|
||||
String qualifiedName = m_filePath + "<" + range.begin.line + ":" + range.begin.column + ">";
|
||||
m_client.recordLocalSymbol(qualifiedName, Range.range(range.begin, range.begin));
|
||||
m_client.recordLocalSymbol(qualifiedName, Range.range(range.end, range.end));
|
||||
}
|
||||
|
||||
@Override public void visit(final LineComment n, final Void v)
|
||||
{
|
||||
m_client.recordComment(n.getRange());
|
||||
super.visit(n, v);
|
||||
}
|
||||
|
||||
@Override public void visit(final BlockComment n, final Void v)
|
||||
{
|
||||
m_client.recordComment(n.getRange());
|
||||
super.visit(n, v);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import com.github.javaparser.ast.visitor.VoidVisitorAdapter;
|
||||
|
||||
import com.github.javaparser.ast.*;
|
||||
import com.github.javaparser.ast.body.*;
|
||||
import com.github.javaparser.ast.comments.Comment;
|
||||
import com.github.javaparser.ast.expr.*;
|
||||
import com.github.javaparser.ast.nodeTypes.NodeWithAnnotations;
|
||||
import com.github.javaparser.ast.stmt.*;
|
||||
import com.github.javaparser.ast.type.*;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
|
||||
public abstract class AstVisitorAdapter extends VoidVisitorAdapter<Void>
|
||||
{
|
||||
private Stack<ReferenceKind> m_typeRefKind = new Stack<ReferenceKind>();
|
||||
|
||||
protected ReferenceKind getTypeReferenceKind()
|
||||
{
|
||||
if (!m_typeRefKind.isEmpty())
|
||||
{
|
||||
return m_typeRefKind.peek();
|
||||
}
|
||||
return ReferenceKind.TYPE_USAGE;
|
||||
}
|
||||
|
||||
//- Compilation Unit ----------------------------------
|
||||
|
||||
@Override public void visit(final CompilationUnit n, Void arg)
|
||||
{
|
||||
m_typeRefKind.push(ReferenceKind.TYPE_USAGE);
|
||||
visitComment(n.getComment(), arg);
|
||||
if (n.getPackageDeclaration().isPresent())
|
||||
{
|
||||
n.getPackageDeclaration().get().accept(this, arg);
|
||||
}
|
||||
if (n.getImports() != null)
|
||||
{
|
||||
for (final ImportDeclaration i : n.getImports())
|
||||
{
|
||||
i.accept(this, arg);
|
||||
}
|
||||
}
|
||||
if (n.getTypes() != null)
|
||||
{
|
||||
for (final TypeDeclaration<?> typeDeclaration : n.getTypes())
|
||||
{
|
||||
typeDeclaration.accept(this, arg);
|
||||
}
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
}
|
||||
|
||||
//- Body ----------------------------------------------
|
||||
|
||||
@Override public void visit(ClassOrInterfaceDeclaration n, Void arg)
|
||||
{
|
||||
visitComment(n.getComment(), arg);
|
||||
visitAnnotations(n, arg);
|
||||
n.getName().accept(this, arg);
|
||||
for (final TypeParameter t : n.getTypeParameters())
|
||||
{
|
||||
t.accept(this, arg);
|
||||
}
|
||||
|
||||
m_typeRefKind.push(ReferenceKind.INHERITANCE);
|
||||
for (final ClassOrInterfaceType c : n.getExtendedTypes())
|
||||
{
|
||||
c.accept(this, arg);
|
||||
}
|
||||
for (final ClassOrInterfaceType c : n.getImplementedTypes())
|
||||
{
|
||||
c.accept(this, arg);
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
|
||||
for (final BodyDeclaration<?> member : n.getMembers())
|
||||
{
|
||||
member.accept(this, arg);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visit(EnumDeclaration n, Void arg)
|
||||
{
|
||||
visitComment(n.getComment(), arg);
|
||||
visitAnnotations(n, arg);
|
||||
n.getName().accept(this, arg);
|
||||
|
||||
m_typeRefKind.push(ReferenceKind.INHERITANCE);
|
||||
if (n.getImplementedTypes() != null)
|
||||
{
|
||||
for (final ClassOrInterfaceType c : n.getImplementedTypes())
|
||||
{
|
||||
c.accept(this, arg);
|
||||
}
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
|
||||
if (n.getEntries() != null)
|
||||
{
|
||||
for (final EnumConstantDeclaration e : n.getEntries())
|
||||
{
|
||||
e.accept(this, arg);
|
||||
}
|
||||
}
|
||||
if (n.getMembers() != null)
|
||||
{
|
||||
for (final BodyDeclaration<?> member : n.getMembers())
|
||||
{
|
||||
member.accept(this, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- Type ----------------------------------------------
|
||||
|
||||
@Override public void visit(ClassOrInterfaceType n, Void arg)
|
||||
{
|
||||
visitComment(n.getComment(), arg);
|
||||
visitAnnotations(n, arg);
|
||||
// don't visit the qualifier here.
|
||||
// if (n.getScope().isPresent())
|
||||
// {
|
||||
// n.getScope().get().accept(this, arg);
|
||||
// }
|
||||
m_typeRefKind.push(ReferenceKind.TYPE_ARGUMENT);
|
||||
if (n.getTypeArguments().isPresent())
|
||||
{
|
||||
for (final Type t : n.getTypeArguments().get())
|
||||
{
|
||||
t.accept(this, arg);
|
||||
}
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
}
|
||||
|
||||
//- Expression ----------------------------------------
|
||||
|
||||
@Override public void visit(MethodCallExpr n, Void arg)
|
||||
{
|
||||
visitComment(n.getComment(), arg);
|
||||
if (n.getScope().isPresent())
|
||||
{
|
||||
n.getScope().get().accept(this, arg);
|
||||
}
|
||||
|
||||
m_typeRefKind.push(ReferenceKind.TYPE_ARGUMENT);
|
||||
if (n.getTypeArguments().isPresent())
|
||||
{
|
||||
for (final Type t : n.getTypeArguments().get())
|
||||
{
|
||||
t.accept(this, arg);
|
||||
}
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
|
||||
n.getName().accept(this, arg);
|
||||
if (n.getArguments() != null)
|
||||
{
|
||||
for (final Expression e : n.getArguments())
|
||||
{
|
||||
e.accept(this, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void visit(ObjectCreationExpr n, Void arg)
|
||||
{
|
||||
visitComment(n.getComment(), arg);
|
||||
if (n.getScope().isPresent())
|
||||
{
|
||||
n.getScope().get().accept(this, arg);
|
||||
}
|
||||
|
||||
m_typeRefKind.push(ReferenceKind.TYPE_ARGUMENT);
|
||||
if (n.getTypeArguments().isPresent())
|
||||
{
|
||||
for (final Type t : n.getTypeArguments().get())
|
||||
{
|
||||
t.accept(this, arg);
|
||||
}
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
|
||||
// n.getType().accept(this, arg);
|
||||
if (n.getArguments() != null)
|
||||
{
|
||||
for (final Expression e : n.getArguments())
|
||||
{
|
||||
e.accept(this, arg);
|
||||
}
|
||||
}
|
||||
if (n.getAnonymousClassBody().isPresent())
|
||||
{
|
||||
for (final BodyDeclaration<?> member : n.getAnonymousClassBody().get())
|
||||
{
|
||||
member.accept(this, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- Statements ----------------------------------------
|
||||
|
||||
@Override public void visit(ExplicitConstructorInvocationStmt n, Void arg)
|
||||
{
|
||||
visitComment(n.getComment(), arg);
|
||||
if (!n.isThis() && n.getExpression().isPresent())
|
||||
{
|
||||
n.getExpression().get().accept(this, arg);
|
||||
}
|
||||
|
||||
m_typeRefKind.push(ReferenceKind.TYPE_ARGUMENT);
|
||||
if (n.getTypeArguments().isPresent())
|
||||
{
|
||||
for (final Type t : n.getTypeArguments().get())
|
||||
{
|
||||
t.accept(this, arg);
|
||||
}
|
||||
}
|
||||
m_typeRefKind.pop();
|
||||
|
||||
if (n.getArguments() != null)
|
||||
{
|
||||
for (final Expression e : n.getArguments())
|
||||
{
|
||||
e.accept(this, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void visitComment(final Optional<Comment> n, final Void arg)
|
||||
{
|
||||
if (n.isPresent())
|
||||
{
|
||||
n.get().accept(this, arg);
|
||||
}
|
||||
}
|
||||
|
||||
private void visitAnnotations(NodeWithAnnotations<?> n, final Void arg)
|
||||
{
|
||||
for (AnnotationExpr annotation : n.getAnnotations())
|
||||
{
|
||||
annotation.accept(this, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
|
||||
public abstract class AstVisitorClient
|
||||
{
|
||||
public void recordSymbolWithLocation(
|
||||
String symbolName, SymbolKind symbolType,
|
||||
Optional<Range> range,
|
||||
AccessKind access, DefinitionKind definitionKind
|
||||
)
|
||||
{
|
||||
recordSymbolWithLocation(
|
||||
symbolName, symbolType,
|
||||
range.orElse(Range.range(0, 0, 0, 0)),
|
||||
access, definitionKind
|
||||
);
|
||||
}
|
||||
|
||||
public void recordSymbolWithLocationAndScope(
|
||||
String symbolName, SymbolKind symbolType,
|
||||
Optional<Range> range,
|
||||
Optional<Range> scopeRange,
|
||||
AccessKind access, DefinitionKind definitionKind
|
||||
)
|
||||
{
|
||||
recordSymbolWithLocationAndScope(
|
||||
symbolName, symbolType,
|
||||
range.orElse(Range.range(0, 0, 0, 0)),
|
||||
scopeRange.orElse(Range.range(0, 0, 0, 0)),
|
||||
access, definitionKind
|
||||
);
|
||||
}
|
||||
|
||||
public void recordReference(
|
||||
ReferenceKind referenceKind, String referencedName, String contextName,
|
||||
Optional<Range> range
|
||||
)
|
||||
{
|
||||
recordReference(
|
||||
referenceKind, referencedName, contextName,
|
||||
range.orElse(Range.range(0, 0, 0, 0))
|
||||
);
|
||||
}
|
||||
|
||||
public void recordLocalSymbol(
|
||||
String symbolName,
|
||||
Optional<Range> range
|
||||
)
|
||||
{
|
||||
recordLocalSymbol(symbolName, range.orElse(Range.range(0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
public void recordComment(
|
||||
Optional<Range> range
|
||||
)
|
||||
{
|
||||
recordComment(range.orElse(Range.range(0, 0, 0, 0)));
|
||||
}
|
||||
|
||||
public void recordError(
|
||||
String message, boolean fatal, boolean indexed,
|
||||
Optional<Range> range
|
||||
)
|
||||
{
|
||||
recordError(
|
||||
message, fatal, indexed,
|
||||
range.orElse(Range.range(0, 0, 0, 0))
|
||||
);
|
||||
}
|
||||
|
||||
public abstract void logInfo(String info);
|
||||
|
||||
public abstract void logWarning(String warning);
|
||||
|
||||
public abstract void logError(String error);
|
||||
|
||||
public abstract void recordSymbol(
|
||||
String symbolName, SymbolKind symbolType,
|
||||
AccessKind access, DefinitionKind definitionKind
|
||||
);
|
||||
|
||||
public abstract void recordSymbolWithLocation(
|
||||
String symbolName, SymbolKind symbolType,
|
||||
Range range,
|
||||
AccessKind access, DefinitionKind definitionKind
|
||||
);
|
||||
|
||||
public abstract void recordSymbolWithLocationAndScope(
|
||||
String symbolName, SymbolKind symbolType,
|
||||
Range range,
|
||||
Range scopeRange,
|
||||
AccessKind access, DefinitionKind definitionKind
|
||||
);
|
||||
|
||||
public abstract void recordReference(
|
||||
ReferenceKind referenceKind, String referencedName, String contextName,
|
||||
Range range
|
||||
);
|
||||
|
||||
public abstract void recordLocalSymbol(
|
||||
String symbolName,
|
||||
Range range
|
||||
);
|
||||
|
||||
public abstract void recordComment(
|
||||
Range range
|
||||
);
|
||||
|
||||
public abstract void recordError(
|
||||
String message, boolean fatal, boolean indexed,
|
||||
Range range
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.github.javaparser.ast.type.TypeParameter;
|
||||
import com.github.javaparser.ast.NodeList;
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
import com.github.javaparser.ast.body.ConstructorDeclaration;
|
||||
import com.github.javaparser.ast.body.Parameter;
|
||||
import com.github.javaparser.ast.type.Type;
|
||||
import com.github.javaparser.ast.type.UnknownType;
|
||||
|
||||
public class CallableConstructorDecl implements CallableDecl
|
||||
{
|
||||
private ConstructorDeclaration m_decl;
|
||||
|
||||
public CallableConstructorDecl(ConstructorDeclaration decl)
|
||||
{
|
||||
m_decl = decl;
|
||||
}
|
||||
|
||||
public BodyDeclaration getWrappedNode()
|
||||
{
|
||||
return m_decl;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return m_decl.getNameAsString();
|
||||
}
|
||||
|
||||
public NodeList<TypeParameter> getTypeParameters()
|
||||
{
|
||||
return m_decl.getTypeParameters();
|
||||
}
|
||||
|
||||
public NodeList<Parameter> getParameters()
|
||||
{
|
||||
return m_decl.getParameters();
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return new UnknownType();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import com.github.javaparser.ast.type.TypeParameter;
|
||||
import com.github.javaparser.ast.NodeList;
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
import com.github.javaparser.ast.body.Parameter;
|
||||
import com.github.javaparser.ast.type.Type;
|
||||
|
||||
public interface CallableDecl
|
||||
{
|
||||
public BodyDeclaration getWrappedNode();
|
||||
public String getName();
|
||||
public NodeList<TypeParameter> getTypeParameters();
|
||||
public NodeList<Parameter> getParameters();
|
||||
public Type getType();
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.github.javaparser.ast.type.TypeParameter;
|
||||
import com.github.javaparser.ast.NodeList;
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
import com.github.javaparser.ast.body.MethodDeclaration;
|
||||
import com.github.javaparser.ast.body.Parameter;
|
||||
import com.github.javaparser.ast.type.Type;
|
||||
|
||||
public class CallableMethodDecl implements CallableDecl
|
||||
{
|
||||
private MethodDeclaration m_decl;
|
||||
|
||||
public CallableMethodDecl(MethodDeclaration decl)
|
||||
{
|
||||
m_decl = decl;
|
||||
}
|
||||
|
||||
public BodyDeclaration getWrappedNode()
|
||||
{
|
||||
return m_decl;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return m_decl.getNameAsString();
|
||||
}
|
||||
|
||||
public NodeList<TypeParameter> getTypeParameters()
|
||||
{
|
||||
return m_decl.getTypeParameters();
|
||||
}
|
||||
|
||||
public NodeList<Parameter> getParameters()
|
||||
{
|
||||
return m_decl.getParameters();
|
||||
}
|
||||
|
||||
public Type getType()
|
||||
{
|
||||
return m_decl.getType();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
public class DeclContext
|
||||
{
|
||||
private String m_name = null;
|
||||
|
||||
public DeclContext(String name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
public enum DefinitionKind
|
||||
{ // these values need to be the same as DefinitionKind in C++ code
|
||||
NONE(0),
|
||||
IMPLICIT(1),
|
||||
EXPLICIT(2);
|
||||
|
||||
private final int m_value;
|
||||
|
||||
private DefinitionKind(int value)
|
||||
{
|
||||
this.m_value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.github.javaparser.Position;
|
||||
|
||||
public class FileContent
|
||||
{
|
||||
public class Location
|
||||
{
|
||||
public int line;
|
||||
public int column;
|
||||
|
||||
Location(int line, int column)
|
||||
{
|
||||
this.line = line;
|
||||
this.column = column;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> m_lines;
|
||||
|
||||
public FileContent(String text)
|
||||
{
|
||||
m_lines = Arrays.asList(text.split("\\r?\\n"));
|
||||
}
|
||||
|
||||
public Location find(String s)
|
||||
{
|
||||
return find(s, Position.pos(1, 1));
|
||||
}
|
||||
|
||||
public Location find(String s, Optional<Position> from)
|
||||
{
|
||||
return find(s, from.orElse(Position.pos(1, 1)));
|
||||
}
|
||||
|
||||
public Location find(String s, Position from)
|
||||
{
|
||||
int lineIndex = from.line - 1;
|
||||
int startColumn = from.column - 1;
|
||||
int column = -1;
|
||||
while (lineIndex < m_lines.size())
|
||||
{
|
||||
column = m_lines.get(lineIndex).indexOf(s, startColumn);
|
||||
if (column != -1)
|
||||
{
|
||||
return new Location(lineIndex + 1, column + 1);
|
||||
}
|
||||
startColumn = 0;
|
||||
lineIndex++;
|
||||
}
|
||||
return new Location(0, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class JavaDeclName
|
||||
{
|
||||
private JavaDeclName m_parent = null;
|
||||
private String m_name = "";
|
||||
private List<String> m_typeParameterNames = null;
|
||||
private JavaTypeName m_returnTypeName = null;
|
||||
private List<JavaTypeName> m_parameterNames = null;
|
||||
|
||||
public static JavaDeclName fromDotSeparatedString(String s)
|
||||
{
|
||||
|
||||
JavaDeclName declName = null;
|
||||
|
||||
int separatorIndex = s.lastIndexOf('.');
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
declName = new JavaDeclName(s.substring(separatorIndex + 1));
|
||||
declName.setParent(JavaDeclName.fromDotSeparatedString(s.substring(0, separatorIndex)));
|
||||
}
|
||||
else
|
||||
{
|
||||
declName = new JavaDeclName(s, null);
|
||||
}
|
||||
|
||||
return declName;
|
||||
}
|
||||
|
||||
public JavaDeclName(String name)
|
||||
{
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
public JavaDeclName(String name, JavaTypeName returnTypeName, List<JavaTypeName> parameterNames)
|
||||
{
|
||||
m_name = name;
|
||||
m_returnTypeName = returnTypeName;
|
||||
m_parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
public JavaDeclName(String name, List<String> typeParameterNames)
|
||||
{
|
||||
m_name = name;
|
||||
m_typeParameterNames = typeParameterNames;
|
||||
}
|
||||
public JavaDeclName(String name, List<String> typeParameterNames, JavaTypeName returnTypeName, List<JavaTypeName> parameterNames)
|
||||
{
|
||||
m_name = name;
|
||||
m_typeParameterNames = typeParameterNames;
|
||||
m_returnTypeName = returnTypeName;
|
||||
m_parameterNames = parameterNames;
|
||||
}
|
||||
|
||||
public void setParent(JavaDeclName parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
public JavaDeclName getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
public String toSerializedNameHierarchy()
|
||||
{
|
||||
String nameHierarchy = ".\tm";
|
||||
if (m_parent != null)
|
||||
{
|
||||
nameHierarchy = m_parent.toSerializedNameHierarchy();
|
||||
nameHierarchy += "\tn";
|
||||
}
|
||||
|
||||
nameHierarchy += m_name;
|
||||
nameHierarchy += getTypeParameterString();
|
||||
|
||||
nameHierarchy += "\ts";
|
||||
if (m_returnTypeName != null)
|
||||
{
|
||||
nameHierarchy += m_returnTypeName.toString();
|
||||
}
|
||||
|
||||
nameHierarchy += "\tp";
|
||||
nameHierarchy += getParameterString();
|
||||
return nameHierarchy;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String string = "";
|
||||
if (m_parent != null)
|
||||
{
|
||||
string = m_parent.toString();
|
||||
string += ".";
|
||||
}
|
||||
|
||||
string += m_name;
|
||||
string += getTypeParameterString();
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
private String getParameterString()
|
||||
{
|
||||
String string = "";
|
||||
if (m_parameterNames != null)
|
||||
{
|
||||
string += "(";
|
||||
for (int i = 0; i < m_parameterNames.size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
string += ", ";
|
||||
}
|
||||
string += m_parameterNames.get(i).toString();
|
||||
}
|
||||
string += ")";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
public String getTypeParameterString()
|
||||
{
|
||||
String string = "";
|
||||
if (m_typeParameterNames != null && !m_typeParameterNames.isEmpty())
|
||||
{
|
||||
string += "<";
|
||||
for (int i = 0; i < m_typeParameterNames.size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
string += ", ";
|
||||
}
|
||||
string += m_typeParameterNames.get(i);
|
||||
}
|
||||
string += ">";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.lang.String;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.ast.PackageDeclaration;
|
||||
import com.github.javaparser.JavaParser;
|
||||
import com.github.javaparser.ParseProblemException;
|
||||
import com.github.javaparser.Problem;
|
||||
import com.github.javaparser.Range;
|
||||
import com.github.javaparser.symbolsolver.javaparser.Navigator;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
|
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver;
|
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
|
||||
import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
|
||||
|
||||
public class JavaIndexer
|
||||
{
|
||||
private static Map<String, TypeSolver> typeSolvers = new HashMap<>();
|
||||
|
||||
public static void processFile(int address, String filePath, String fileContent, String classPath, int verbose)
|
||||
{
|
||||
AstVisitorClient astVisitorClient = new JavaIndexerAstVisitorClient(address);
|
||||
|
||||
astVisitorClient.logInfo( "indexing source file: " + filePath);
|
||||
|
||||
try
|
||||
{
|
||||
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
|
||||
|
||||
combinedTypeSolver.add(new ReflectionTypeSolver());
|
||||
for (String path: classPath.split("\\;"))
|
||||
{
|
||||
if (typeSolvers.containsKey(path))
|
||||
{
|
||||
combinedTypeSolver.add(typeSolvers.get(path));
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeSolver typeSolver = null;
|
||||
|
||||
if (path.endsWith(".jar"))
|
||||
{
|
||||
try
|
||||
{
|
||||
typeSolver = new JarTypeSolver(path);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
System.out.println("unable to add jar file: " + path);
|
||||
}
|
||||
}
|
||||
else if (!path.isEmpty())
|
||||
{
|
||||
typeSolver = new JavaParserTypeSolver(new File(path));
|
||||
}
|
||||
|
||||
if (typeSolver != null)
|
||||
{
|
||||
typeSolvers.put(path, typeSolver);
|
||||
combinedTypeSolver.add(typeSolver);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompilationUnit cu = JavaParser.parse(new StringReader(fileContent));
|
||||
|
||||
AstVisitor astVisitor = (
|
||||
verbose == 1 ?
|
||||
new VerboseAstVisitor(astVisitorClient, filePath, new FileContent(fileContent), combinedTypeSolver) :
|
||||
new AstVisitor(astVisitorClient, filePath, new FileContent(fileContent), combinedTypeSolver)
|
||||
);
|
||||
|
||||
cu.accept(astVisitor, null);
|
||||
}
|
||||
catch (ParseProblemException e)
|
||||
{
|
||||
for (Problem problem: e.getProblems())
|
||||
{
|
||||
String message = problem.toString();
|
||||
if (message.startsWith("(line "))
|
||||
{
|
||||
int startLine = Integer.parseInt(message.substring(
|
||||
message.indexOf("line ") + ("line ").length(),
|
||||
message.indexOf(",")
|
||||
));
|
||||
|
||||
int startColumn = Integer.parseInt(message.substring(
|
||||
message.indexOf("col ") + ("col ").length(),
|
||||
message.indexOf(")")
|
||||
));
|
||||
|
||||
astVisitorClient.recordError(
|
||||
"Encountered unexpected token.", true, true,
|
||||
Range.range(startLine, startColumn, startLine, startColumn)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Optional<Range> range = problem.getRange();
|
||||
if (range.isPresent())
|
||||
{
|
||||
astVisitorClient.recordError(
|
||||
problem.toString(), true, true,
|
||||
range.get()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static String getPackageName(String fileContent)
|
||||
{
|
||||
String packageName = "";
|
||||
try
|
||||
{
|
||||
CompilationUnit cu = JavaParser.parse(new StringReader(fileContent));
|
||||
PackageDeclaration pd = Navigator.findNodeOfGivenClass(cu, PackageDeclaration.class);
|
||||
if (pd != null)
|
||||
{
|
||||
packageName = JavaparserDeclNameResolver.getQualifiedName(pd.getName()).toString();
|
||||
}
|
||||
}
|
||||
catch (ParseProblemException e)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
catch (IllegalArgumentException e)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
return packageName;
|
||||
}
|
||||
|
||||
public static void clearCaches()
|
||||
{
|
||||
typeSolvers.clear();
|
||||
JavaParserFacade.clearInstances();
|
||||
Runtime.getRuntime().gc();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// the following methods are defined in the native c++ code
|
||||
|
||||
static public native void logInfo(int address, String info);
|
||||
|
||||
static public native void logWarning(int address, String warning);
|
||||
|
||||
static public native void logError(int address, String error);
|
||||
|
||||
static public native void recordSymbol(
|
||||
int address, String symbolName, int symbolType,
|
||||
int access, int definitionKind
|
||||
);
|
||||
|
||||
static public native void recordSymbolWithLocation(
|
||||
int address, String symbolName, int symbolType,
|
||||
int beginLine, int beginColumn, int endLine, int endColumn,
|
||||
int access, int definitionKind
|
||||
);
|
||||
|
||||
static public native void recordSymbolWithLocationAndScope(
|
||||
int address, String symbolName, int symbolType,
|
||||
int beginLine, int beginColumn, int endLine, int endColumn,
|
||||
int scopeBeginLine, int scopeBeginColumn, int scopeEndLine, int scopeEndColumn,
|
||||
int access, int definitionKind
|
||||
);
|
||||
|
||||
static public native void recordReference(
|
||||
int address, int referenceKind, String referencedName, String contextName, int beginLine, int beginColumn, int endLine, int endColumn
|
||||
);
|
||||
|
||||
static public native void recordLocalSymbol(
|
||||
int address, String symbolName, int beginLine, int beginColumn, int endLine, int endColumn
|
||||
);
|
||||
|
||||
static public native void recordComment(
|
||||
int address, int beginLine, int beginColumn, int endLine, int endColumn
|
||||
);
|
||||
|
||||
static public native void recordError(
|
||||
int address, String message, int fatal, int indexed, int beginLine, int beginColumn, int endLine, int endColumn
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import com.github.javaparser.Range;
|
||||
|
||||
public class JavaIndexerAstVisitorClient extends AstVisitorClient
|
||||
{
|
||||
private int m_address;
|
||||
|
||||
public JavaIndexerAstVisitorClient(int address)
|
||||
{
|
||||
m_address = address;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logInfo(String info)
|
||||
{
|
||||
JavaIndexer.logInfo(m_address, info);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logWarning(String warning)
|
||||
{
|
||||
JavaIndexer.logWarning(m_address, warning);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logError(String error)
|
||||
{
|
||||
JavaIndexer.logError(m_address, error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordSymbol(
|
||||
String symbolName, SymbolKind symbolType,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
{
|
||||
JavaIndexer.recordSymbol(
|
||||
m_address, symbolName, symbolType.getValue(),
|
||||
access.getValue(), definitionKind.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordSymbolWithLocation(
|
||||
String symbolName, SymbolKind symbolType, Range range,
|
||||
AccessKind access, DefinitionKind definitionKind)
|
||||
{
|
||||
JavaIndexer.recordSymbolWithLocation(
|
||||
m_address, symbolName, symbolType.getValue(),
|
||||
range.begin.line, range.begin.column, range.end.line, range.end.column,
|
||||
access.getValue(), definitionKind.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordSymbolWithLocationAndScope(
|
||||
String symbolName, SymbolKind symbolType, Range range,
|
||||
Range scopeRange, AccessKind access, DefinitionKind definitionKind)
|
||||
{
|
||||
JavaIndexer.recordSymbolWithLocationAndScope(
|
||||
m_address, symbolName, symbolType.getValue(),
|
||||
range.begin.line, range.begin.column, range.end.line, range.end.column,
|
||||
scopeRange.begin.line, scopeRange.begin.column, scopeRange.end.line, scopeRange.end.column,
|
||||
access.getValue(), definitionKind.getValue()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordReference(
|
||||
ReferenceKind referenceKind, String referencedName,
|
||||
String contextName, Range range)
|
||||
{
|
||||
JavaIndexer.recordReference(
|
||||
m_address, referenceKind.getValue(), referencedName, contextName,
|
||||
range.begin.line, range.begin.column, range.end.line, range.end.column
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordLocalSymbol(String symbolName, Range range)
|
||||
{
|
||||
JavaIndexer.recordLocalSymbol(
|
||||
m_address, symbolName,
|
||||
range.begin.line, range.begin.column, range.end.line, range.end.column
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordComment(Range range)
|
||||
{
|
||||
JavaIndexer.recordComment(
|
||||
m_address,
|
||||
range.begin.line, range.begin.column, range.end.line, range.end.column
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recordError(String message, boolean fatal, boolean indexed, Range range)
|
||||
{
|
||||
JavaIndexer.recordError(
|
||||
m_address, message, (fatal ? 1 : 0), (indexed ? 1 : 0),
|
||||
range.begin.line, range.begin.column, range.end.line, range.end.column
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
|
||||
public abstract class JavaNameResolver
|
||||
{
|
||||
TypeSolver m_typeSolver = null;
|
||||
ArrayList<BodyDeclaration> m_ignoredContexts = null;
|
||||
|
||||
public JavaNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
m_typeSolver = typeSolver;
|
||||
if (ignoredContexts != null)
|
||||
{
|
||||
m_ignoredContexts = ignoredContexts;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ignoredContexts = new ArrayList<BodyDeclaration>();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean ignoresContext(BodyDeclaration context)
|
||||
{
|
||||
if (m_ignoredContexts != null)
|
||||
{
|
||||
for (BodyDeclaration ignoredContext: m_ignoredContexts)
|
||||
{
|
||||
if (ignoredContext.equals(context))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
|
||||
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserClassDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserInterfaceDeclaration;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserMethodDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.Declaration;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.MethodDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
|
||||
public class JavaSymbolSolverDeclNameResolver extends JavaNameResolver
|
||||
{
|
||||
public JavaSymbolSolverDeclNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
super(typeSolver, ignoredContexts);
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedDeclName(Declaration decl, TypeSolver typeSolver)
|
||||
{
|
||||
return getQualifiedDeclName(decl, typeSolver, null);
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedDeclName(Declaration decl, TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
JavaSymbolSolverDeclNameResolver resolver = new JavaSymbolSolverDeclNameResolver(typeSolver, ignoredContexts);
|
||||
return resolver.getQualifiedDeclName(decl);
|
||||
}
|
||||
|
||||
public JavaDeclName getQualifiedDeclName(Declaration decl)
|
||||
{
|
||||
JavaDeclName declName = null;
|
||||
|
||||
if (decl != null)
|
||||
{
|
||||
if (decl instanceof TypeDeclaration)
|
||||
{
|
||||
TypeDeclaration typeDecl = (TypeDeclaration)decl;
|
||||
|
||||
ClassOrInterfaceDeclaration javaparserDecl = null;
|
||||
if (typeDecl instanceof JavaParserClassDeclaration)
|
||||
{
|
||||
javaparserDecl = ((JavaParserClassDeclaration)typeDecl).getWrappedNode();
|
||||
}
|
||||
else if (typeDecl instanceof JavaParserInterfaceDeclaration)
|
||||
{
|
||||
javaparserDecl = ((JavaParserInterfaceDeclaration)typeDecl).getWrappedNode();
|
||||
}
|
||||
|
||||
if (javaparserDecl != null)
|
||||
{
|
||||
declName = JavaparserDeclNameResolver.getQualifiedDeclName(javaparserDecl, m_typeSolver, m_ignoredContexts);
|
||||
}
|
||||
else
|
||||
{
|
||||
declName = JavaDeclName.fromDotSeparatedString(typeDecl.getQualifiedName());
|
||||
}
|
||||
}
|
||||
else if (decl instanceof MethodDeclaration)
|
||||
{
|
||||
MethodDeclaration methodDecl = (MethodDeclaration)decl;
|
||||
|
||||
if (methodDecl instanceof JavaParserMethodDeclaration)
|
||||
{
|
||||
declName = JavaparserDeclNameResolver.getQualifiedDeclName(
|
||||
((JavaParserMethodDeclaration)methodDecl).getWrappedNode(),
|
||||
m_typeSolver,
|
||||
m_ignoredContexts
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: what about endless recursion regarding type parameters and return type??
|
||||
|
||||
List<JavaTypeName> parameterNames = new ArrayList<>();
|
||||
for (int i = 0; i < methodDecl.getNumberOfParams(); i++)
|
||||
{
|
||||
parameterNames.add(JavaSymbolSolverTypeNameResolver.getQualifiedTypeName(
|
||||
methodDecl.getParam(i).getType(), m_typeSolver, m_ignoredContexts
|
||||
));
|
||||
}
|
||||
|
||||
declName = new JavaDeclName(
|
||||
methodDecl.getName(),
|
||||
getTypeParameterNames(methodDecl.getTypeParameters()),
|
||||
JavaSymbolSolverTypeNameResolver.getQualifiedTypeName(methodDecl.getReturnType(), m_typeSolver, m_ignoredContexts),
|
||||
parameterNames
|
||||
);
|
||||
|
||||
declName.setParent(
|
||||
getQualifiedDeclName(methodDecl.declaringType(), m_typeSolver, m_ignoredContexts)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return declName;
|
||||
}
|
||||
|
||||
private static List<String> getTypeParameterNames(List<TypeParameterDeclaration> typeParameters)
|
||||
{
|
||||
List<String> typeParameterNames = new ArrayList<>();
|
||||
if (typeParameters != null && typeParameters.size() > 0)
|
||||
{
|
||||
for (int i = 0; i < typeParameters.size(); i++)
|
||||
{
|
||||
typeParameterNames.add(typeParameters.get(i).getName());
|
||||
}
|
||||
}
|
||||
return typeParameterNames;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.github.javaparser.ast.Node;
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.LambdaArgumentTypePlaceholder;
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.declarations.JavaParserTypeParameter;
|
||||
import com.github.javaparser.symbolsolver.logic.InferenceVariableType;
|
||||
import com.github.javaparser.symbolsolver.model.declarations.TypeParameterDeclaration;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.ArrayType;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.NullType;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.PrimitiveType;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.ReferenceType;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.Type;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.TypeVariable;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.VoidType;
|
||||
import com.github.javaparser.symbolsolver.model.typesystem.Wildcard;
|
||||
|
||||
public class JavaSymbolSolverTypeNameResolver extends JavaNameResolver
|
||||
{
|
||||
public JavaSymbolSolverTypeNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
super(typeSolver, ignoredContexts);
|
||||
}
|
||||
|
||||
public static JavaTypeName getQualifiedTypeName(Type type, TypeSolver typeSolver)
|
||||
{
|
||||
return getQualifiedTypeName(type, typeSolver, null);
|
||||
}
|
||||
|
||||
public static JavaTypeName getQualifiedTypeName(Type type, TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
JavaSymbolSolverTypeNameResolver resolver = new JavaSymbolSolverTypeNameResolver(typeSolver, ignoredContexts);
|
||||
return resolver.getQualifiedTypeName(type);
|
||||
}
|
||||
|
||||
public JavaTypeName getQualifiedTypeName(Type type)
|
||||
{
|
||||
if (type instanceof ArrayType)
|
||||
{
|
||||
return getQualifiedTypeName(((ArrayType)type).getComponentType());
|
||||
}
|
||||
else if (type instanceof LambdaArgumentTypePlaceholder)
|
||||
{
|
||||
|
||||
}
|
||||
else if (type instanceof InferenceVariableType)
|
||||
{
|
||||
|
||||
}
|
||||
else if (type instanceof NullType)
|
||||
{
|
||||
return JavaTypeName.fromDotSeparatedString(type.describe());
|
||||
}
|
||||
else if (type instanceof PrimitiveType)
|
||||
{
|
||||
return JavaTypeName.fromDotSeparatedString(type.describe());
|
||||
}
|
||||
else if (type instanceof ReferenceType)
|
||||
{
|
||||
ReferenceType refTypeUsage = (ReferenceType)type;
|
||||
|
||||
JavaDeclName declName = JavaSymbolSolverDeclNameResolver.getQualifiedDeclName(
|
||||
refTypeUsage.getTypeDeclaration(),
|
||||
m_typeSolver,
|
||||
m_ignoredContexts
|
||||
);
|
||||
|
||||
return new JavaTypeName(declName.getName() + declName.getTypeParameterString(), new ArrayList<JavaTypeName>(), declName.getParent());
|
||||
/*
|
||||
if (declName != null)
|
||||
{
|
||||
List<JavaTypeName> typeArgumentNames = new ArrayList<>();
|
||||
|
||||
for (TypeUsage typeArgument: refTypeUsage.parameters()) // don't know why this method is called "parameters()"
|
||||
{
|
||||
typeArgumentNames.add(getQualifiedTypeName(typeArgument, m_typeSolver, m_ignoredContexts));
|
||||
}
|
||||
return new JavaTypeName(declName.getName(), typeArgumentNames, declName.getParent());
|
||||
}
|
||||
*/
|
||||
}
|
||||
else if (type instanceof TypeVariable)
|
||||
{
|
||||
TypeParameterDeclaration typeParam = ((TypeVariable)type).asTypeParameter();
|
||||
if (typeParam instanceof JavaParserTypeParameter)
|
||||
{
|
||||
com.github.javaparser.ast.type.TypeParameter jpTypeParameter = ((JavaParserTypeParameter)typeParam).getWrappedNode();
|
||||
Optional<BodyDeclaration> genericDecl = jpTypeParameter.getAncestorOfType(BodyDeclaration.class);
|
||||
if (genericDecl.isPresent())
|
||||
{
|
||||
JavaDeclName genericName = null;
|
||||
if (!ignoresContext(genericDecl.get()))
|
||||
{
|
||||
genericName = JavaparserDeclNameResolver.getQualifiedDeclName(genericDecl.get(), m_typeSolver, m_ignoredContexts);
|
||||
}
|
||||
return new JavaTypeName(jpTypeParameter.getName().getId(), genericName);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// do we need to handle using type parameters of external code? YES! so: TODO: do this!
|
||||
}
|
||||
}
|
||||
else if (type instanceof VoidType)
|
||||
{
|
||||
return JavaTypeName.fromDotSeparatedString(type.describe());
|
||||
}
|
||||
else if (type instanceof Wildcard)
|
||||
{
|
||||
return new JavaTypeName("?", null);
|
||||
}
|
||||
|
||||
System.out.println("Unable to resolve qualified name of " + type.getClass().toString() + ": " + type.toString());
|
||||
return new JavaTypeName("unresolved-type", null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class JavaTypeName
|
||||
{
|
||||
private JavaDeclName m_parent = null;
|
||||
private String m_name = "";
|
||||
private List<JavaTypeName> m_typeArgumentNames = null;
|
||||
|
||||
public static JavaTypeName fromDotSeparatedString(String s)
|
||||
{
|
||||
JavaTypeName typeName = null;
|
||||
|
||||
int separatorIndex = s.lastIndexOf('.');
|
||||
if (separatorIndex != -1)
|
||||
{
|
||||
typeName = new JavaTypeName(s.substring(separatorIndex + 1), JavaDeclName.fromDotSeparatedString(s.substring(0, separatorIndex)));
|
||||
}
|
||||
else
|
||||
{
|
||||
typeName = new JavaTypeName(s, null);
|
||||
}
|
||||
|
||||
return typeName;
|
||||
}
|
||||
|
||||
public JavaTypeName(String name, JavaDeclName parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_name = name;
|
||||
}
|
||||
|
||||
public JavaTypeName(String name, List<JavaTypeName> typeArgumentNames, JavaDeclName parent)
|
||||
{
|
||||
m_parent = parent;
|
||||
m_name = name;
|
||||
m_typeArgumentNames = typeArgumentNames;
|
||||
}
|
||||
|
||||
public JavaDeclName getParent()
|
||||
{
|
||||
return m_parent;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
public String toSerializedNameHierarchy()
|
||||
{
|
||||
String nameHierarchy = ".\tm";
|
||||
if (m_parent != null)
|
||||
{
|
||||
nameHierarchy = m_parent.toSerializedNameHierarchy();
|
||||
nameHierarchy += "\tn";
|
||||
}
|
||||
|
||||
nameHierarchy += m_name;
|
||||
nameHierarchy += getTypeArgumentString();
|
||||
nameHierarchy += "\ts\tp";
|
||||
|
||||
return nameHierarchy;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
String string = "";
|
||||
if (m_parent != null)
|
||||
{
|
||||
string = m_parent.toString();
|
||||
string += ".";
|
||||
}
|
||||
|
||||
string += m_name;
|
||||
string += getTypeArgumentString();
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
private String getTypeArgumentString()
|
||||
{
|
||||
String string = "";
|
||||
if (m_typeArgumentNames != null && !m_typeArgumentNames.isEmpty())
|
||||
{
|
||||
string += "<";
|
||||
for (int i = 0; i < m_typeArgumentNames.size(); i++)
|
||||
{
|
||||
if (i != 0)
|
||||
{
|
||||
string += ", ";
|
||||
}
|
||||
string += m_typeArgumentNames.get(i).toString();
|
||||
}
|
||||
string += ">";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.github.javaparser.ast.CompilationUnit;
|
||||
import com.github.javaparser.ast.Node;
|
||||
import com.github.javaparser.ast.NodeList;
|
||||
import com.github.javaparser.ast.PackageDeclaration;
|
||||
import com.github.javaparser.ast.body.AnnotationMemberDeclaration;
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
|
||||
import com.github.javaparser.ast.body.ConstructorDeclaration;
|
||||
import com.github.javaparser.ast.body.EmptyMemberDeclaration;
|
||||
import com.github.javaparser.ast.body.EnumConstantDeclaration;
|
||||
import com.github.javaparser.ast.body.FieldDeclaration;
|
||||
import com.github.javaparser.ast.body.InitializerDeclaration;
|
||||
import com.github.javaparser.ast.body.MethodDeclaration;
|
||||
import com.github.javaparser.ast.body.Parameter;
|
||||
import com.github.javaparser.ast.body.TypeDeclaration;
|
||||
import com.github.javaparser.ast.body.VariableDeclarator;
|
||||
import com.github.javaparser.ast.expr.Name;
|
||||
import com.github.javaparser.ast.type.TypeParameter;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
|
||||
public class JavaparserDeclNameResolver extends JavaNameResolver
|
||||
{
|
||||
public JavaparserDeclNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
super(typeSolver, ignoredContexts);
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedDeclName(VariableDeclarator decl, TypeSolver typeSolver)
|
||||
{
|
||||
return getQualifiedDeclName(decl, typeSolver, null);
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedDeclName(VariableDeclarator decl, TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
JavaparserDeclNameResolver resolver = new JavaparserDeclNameResolver(typeSolver, ignoredContexts);
|
||||
return resolver.getQualifiedDeclName(decl);
|
||||
}
|
||||
|
||||
public JavaDeclName getQualifiedDeclName(VariableDeclarator decl)
|
||||
{
|
||||
JavaDeclName declName = null;
|
||||
|
||||
if (decl != null)
|
||||
{
|
||||
declName = getDeclName(decl);
|
||||
|
||||
BodyDeclaration declContext = getBodyDeclContext(decl);
|
||||
if (declContext != null)
|
||||
{
|
||||
if (!ignoresContext(declContext))
|
||||
{
|
||||
declName.setParent(getQualifiedDeclName(declContext));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Optional<CompilationUnit> compilationUnit = decl.getAncestorOfType(CompilationUnit.class);
|
||||
|
||||
if (compilationUnit.isPresent())
|
||||
{
|
||||
Optional<PackageDeclaration> packageDecl = compilationUnit.get().getPackageDeclaration();
|
||||
if (packageDecl.isPresent())
|
||||
{
|
||||
declName.setParent(getQualifiedName(packageDecl.get().getName()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
return declName;
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedDeclName(BodyDeclaration decl, TypeSolver typeSolver)
|
||||
{
|
||||
return getQualifiedDeclName(decl, typeSolver, null);
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedDeclName(BodyDeclaration decl, TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
JavaparserDeclNameResolver resolver = new JavaparserDeclNameResolver(typeSolver, ignoredContexts);
|
||||
return resolver.getQualifiedDeclName(decl);
|
||||
}
|
||||
|
||||
public JavaDeclName getQualifiedDeclName(BodyDeclaration<?> decl)
|
||||
{
|
||||
JavaDeclName declName = null;
|
||||
|
||||
if (decl != null)
|
||||
{
|
||||
declName = getDeclName(decl);
|
||||
|
||||
BodyDeclaration declContext = getBodyDeclContext(decl);
|
||||
if (declContext != null)
|
||||
{
|
||||
if (!ignoresContext(declContext))
|
||||
{
|
||||
declName.setParent(getQualifiedDeclName(declContext));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Optional<CompilationUnit> compilationUnit = decl.getAncestorOfType(CompilationUnit.class);
|
||||
|
||||
if (compilationUnit.isPresent())
|
||||
{
|
||||
Optional<PackageDeclaration> packageDecl = compilationUnit.get().getPackageDeclaration();
|
||||
if (packageDecl.isPresent())
|
||||
{
|
||||
declName.setParent(getQualifiedName(packageDecl.get().getName()));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
}
|
||||
return declName;
|
||||
}
|
||||
|
||||
public JavaDeclName getDeclName(VariableDeclarator decl)
|
||||
{
|
||||
return new JavaDeclName(decl.getNameAsString());
|
||||
}
|
||||
|
||||
public JavaDeclName getDeclName(BodyDeclaration decl)
|
||||
{
|
||||
JavaDeclName declName = null;
|
||||
|
||||
if (decl != null)
|
||||
{
|
||||
if (decl instanceof AnnotationMemberDeclaration)
|
||||
{
|
||||
declName = new JavaDeclName("AnnotationMemberDeclaration");
|
||||
}
|
||||
else if (decl instanceof ConstructorDeclaration)
|
||||
{
|
||||
CallableConstructorDecl callableDecl = new CallableConstructorDecl((ConstructorDeclaration)decl);
|
||||
declName = getDeclNameOfCallable(callableDecl);
|
||||
}
|
||||
else if (decl instanceof EmptyMemberDeclaration)
|
||||
{
|
||||
declName = new JavaDeclName("EmptyMemberDeclaration");
|
||||
}
|
||||
else if (decl instanceof EnumConstantDeclaration)
|
||||
{
|
||||
declName = new JavaDeclName(((EnumConstantDeclaration)decl).getNameAsString());
|
||||
}
|
||||
else if (decl instanceof FieldDeclaration)
|
||||
{
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
else if (decl instanceof InitializerDeclaration)
|
||||
{
|
||||
declName = new JavaDeclName("InitializerDeclaration");
|
||||
}
|
||||
else if (decl instanceof MethodDeclaration)
|
||||
{
|
||||
CallableMethodDecl callableDecl = new CallableMethodDecl((MethodDeclaration)decl);
|
||||
declName = getDeclNameOfCallable(callableDecl);
|
||||
}
|
||||
else if (decl instanceof TypeDeclaration)
|
||||
{
|
||||
declName = new JavaDeclName(((TypeDeclaration)decl).getNameAsString(), getTypeParameterNames((TypeDeclaration)decl));
|
||||
}
|
||||
}
|
||||
|
||||
return declName;
|
||||
}
|
||||
|
||||
private static List<String> getTypeParameterNames(TypeDeclaration decl)
|
||||
{
|
||||
NodeList<TypeParameter> typeParameters = null;
|
||||
if (decl instanceof ClassOrInterfaceDeclaration)
|
||||
{
|
||||
typeParameters = (NodeList<TypeParameter>) ((ClassOrInterfaceDeclaration)decl).getTypeParameters();
|
||||
}
|
||||
|
||||
return getTypeParameterNames(typeParameters);
|
||||
}
|
||||
|
||||
private static List<String> getTypeParameterNames(NodeList<TypeParameter> typeParameters)
|
||||
{
|
||||
List<String> typeParameterNames = new ArrayList<>();
|
||||
if (typeParameters != null && typeParameters.size() > 0)
|
||||
{
|
||||
for (int i = 0; i < typeParameters.size(); i++)
|
||||
{
|
||||
typeParameterNames.add(typeParameters.get(i).getNameAsString());
|
||||
}
|
||||
}
|
||||
return typeParameterNames;
|
||||
}
|
||||
|
||||
public static JavaDeclName getQualifiedName(Name name)
|
||||
{
|
||||
JavaDeclName declName = new JavaDeclName(name.getId());
|
||||
if (name.getQualifier().isPresent())
|
||||
{
|
||||
declName.setParent(getQualifiedName(name.getQualifier().get()));
|
||||
}
|
||||
return declName;
|
||||
}
|
||||
|
||||
private <T extends CallableDecl> JavaDeclName getDeclNameOfCallable(T decl)
|
||||
{
|
||||
ArrayList<BodyDeclaration> ignoredContextsForTypes = new ArrayList<BodyDeclaration>(m_ignoredContexts);
|
||||
ignoredContextsForTypes.add(decl.getWrappedNode()); // adding own decl
|
||||
|
||||
String name = decl.getName();
|
||||
List<String> typeParameterNames = getTypeParameterNames(decl.getTypeParameters());
|
||||
JavaTypeName returnTypeName = JavaparserTypeNameResolver.getQualifiedTypeName(decl.getType(), m_typeSolver, ignoredContextsForTypes);
|
||||
List<JavaTypeName> parameterNames = new ArrayList<>();
|
||||
for (Parameter parameter: decl.getParameters())
|
||||
{
|
||||
parameterNames.add(JavaparserTypeNameResolver.getQualifiedTypeName(parameter.getType(), m_typeSolver, ignoredContextsForTypes));
|
||||
}
|
||||
|
||||
return new JavaDeclName(name, typeParameterNames, returnTypeName, parameterNames);
|
||||
}
|
||||
|
||||
private static BodyDeclaration getBodyDeclContext(Node decl)
|
||||
{
|
||||
BodyDeclaration context = null;
|
||||
|
||||
Optional<Node> parentNode = decl.getParentNode();
|
||||
while (
|
||||
parentNode.isPresent() &&
|
||||
!(
|
||||
parentNode.get() instanceof BodyDeclaration &&
|
||||
(!(parentNode.get() instanceof FieldDeclaration))
|
||||
)
|
||||
)
|
||||
{
|
||||
parentNode = parentNode.get().getParentNode();
|
||||
}
|
||||
|
||||
if (parentNode.isPresent())
|
||||
{
|
||||
context = (BodyDeclaration)parentNode.get();
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.github.javaparser.ast.body.BodyDeclaration;
|
||||
import com.github.javaparser.ast.type.*;
|
||||
|
||||
import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
|
||||
public class JavaparserTypeNameResolver extends JavaNameResolver
|
||||
{
|
||||
public JavaparserTypeNameResolver(TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
super(typeSolver, ignoredContexts);
|
||||
}
|
||||
|
||||
public static JavaTypeName getQualifiedTypeName(Type type, TypeSolver typeSolver)
|
||||
{
|
||||
return getQualifiedTypeName(type, typeSolver, null);
|
||||
}
|
||||
|
||||
public static JavaTypeName getQualifiedTypeName(Type type, TypeSolver typeSolver, ArrayList<BodyDeclaration> ignoredContexts)
|
||||
{
|
||||
JavaparserTypeNameResolver resolver = new JavaparserTypeNameResolver(typeSolver, ignoredContexts);
|
||||
return resolver.getQualifiedTypeName(type);
|
||||
}
|
||||
|
||||
public JavaTypeName getQualifiedTypeName(Type type)
|
||||
{
|
||||
String fallbackTypeName = type.toString();
|
||||
|
||||
if (type instanceof ClassOrInterfaceType)
|
||||
{
|
||||
try
|
||||
{
|
||||
return JavaSymbolSolverTypeNameResolver.getQualifiedTypeName(
|
||||
JavaParserFacade.get(m_typeSolver).convert(type, type),
|
||||
m_typeSolver,
|
||||
m_ignoredContexts
|
||||
);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// log...
|
||||
}
|
||||
}
|
||||
else if (type instanceof ArrayType)
|
||||
{
|
||||
ArrayType arrayType = (ArrayType)type;
|
||||
|
||||
// TODO: regard array info!
|
||||
return getQualifiedTypeName(arrayType.getComponentType());
|
||||
}
|
||||
else if (type instanceof TypeParameter)
|
||||
{
|
||||
return JavaSymbolSolverTypeNameResolver.getQualifiedTypeName(
|
||||
JavaParserFacade.get(m_typeSolver).convert(type, type),
|
||||
m_typeSolver,
|
||||
m_ignoredContexts
|
||||
);
|
||||
}
|
||||
else if (type instanceof IntersectionType)
|
||||
{
|
||||
// System.out.println(" IntersectionType: " + fallbackTypeName);
|
||||
|
||||
return JavaTypeName.fromDotSeparatedString(type.toString());
|
||||
}
|
||||
else if (type instanceof PrimitiveType)
|
||||
{
|
||||
return JavaTypeName.fromDotSeparatedString(type.toString());
|
||||
}
|
||||
else if (type instanceof UnionType)
|
||||
{
|
||||
// System.out.println(" UnionType: " + fallbackTypeName);
|
||||
return JavaTypeName.fromDotSeparatedString(type.toString());
|
||||
}
|
||||
else if (type instanceof UnknownType)
|
||||
{
|
||||
// System.out.println(" UnknownType: " + fallbackTypeName);
|
||||
return JavaTypeName.fromDotSeparatedString(type.toString());
|
||||
}
|
||||
else if (type instanceof VoidType)
|
||||
{
|
||||
return JavaTypeName.fromDotSeparatedString(type.toString());
|
||||
}
|
||||
else if (type instanceof WildcardType)
|
||||
{
|
||||
// System.out.println(" WildcardType: " + fallbackTypeName);
|
||||
return JavaTypeName.fromDotSeparatedString(type.toString());
|
||||
}
|
||||
|
||||
System.out.println("Unable to resolve qualified name of " + type.getClass().toString() + ": " + fallbackTypeName);
|
||||
return new JavaTypeName("unresolved-type", null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
public enum ReferenceKind
|
||||
{ // these values need to be the same as ReferenceKind in C++ code
|
||||
UNDEFINED(0),
|
||||
TYPE_USAGE(1),
|
||||
USAGE(2),
|
||||
CALL(3),
|
||||
INHERITANCE(4),
|
||||
OVERRIDE(5),
|
||||
TEMPLATE_ARGUMENT(6),
|
||||
TYPE_ARGUMENT(7),
|
||||
TEMPLATE_DEFAULT_ARGUMENT(8),
|
||||
TEMPLATE_SPECIALIZATION_OF(9),
|
||||
TEMPLATE_MEMBER_SPECIALIZATION_OF(10),
|
||||
INCLUDE(11),
|
||||
IMPORT(12),
|
||||
MACRO_USAGE(13);
|
||||
|
||||
private final int m_value;
|
||||
|
||||
private ReferenceKind(int value)
|
||||
{
|
||||
this.m_value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
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);
|
||||
|
||||
private final int m_value;
|
||||
|
||||
private SymbolKind(int value)
|
||||
{
|
||||
this.m_value = value;
|
||||
}
|
||||
|
||||
public int getValue()
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
package com.sourcetrail;
|
||||
|
||||
import com.github.javaparser.ast.*;
|
||||
import com.github.javaparser.ast.body.*;
|
||||
import com.github.javaparser.ast.comments.*;
|
||||
import com.github.javaparser.ast.expr.*;
|
||||
import com.github.javaparser.ast.nodeTypes.NodeWithName;
|
||||
import com.github.javaparser.ast.stmt.*;
|
||||
import com.github.javaparser.ast.type.*;
|
||||
import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
|
||||
|
||||
public class VerboseAstVisitor extends AstVisitor{
|
||||
|
||||
public VerboseAstVisitor(AstVisitorClient client, String filePath, FileContent fileContent, TypeSolver typeSolver) {
|
||||
super(client, filePath, fileContent, typeSolver);
|
||||
}
|
||||
|
||||
int indent = 0;
|
||||
String indentSymbol = "| ";
|
||||
|
||||
private String obfuscate(final String s)
|
||||
{
|
||||
if (s.isEmpty())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
else if (s.length() <= 2)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
return s.substring(0, 1) + ".." + s.substring(s.length() - 1, s.length());
|
||||
}
|
||||
|
||||
private void dump(Node n)
|
||||
{
|
||||
String line = "";
|
||||
|
||||
for (int i = 0; i < this.indent; i++)
|
||||
{
|
||||
line += this.indentSymbol;
|
||||
}
|
||||
|
||||
line += n.getClass().getName();
|
||||
if (n instanceof NodeWithName<?>)
|
||||
{
|
||||
line += " [" + obfuscate(((NodeWithName<?>)n).getNameAsString()) + "]";
|
||||
}
|
||||
|
||||
if (n.getBegin().isPresent())
|
||||
{
|
||||
line += " line: " + n.getBegin().get().line;
|
||||
}
|
||||
|
||||
m_client.logInfo(line);
|
||||
}
|
||||
|
||||
//- Compilation Unit ----------------------------------
|
||||
|
||||
public void visit(CompilationUnit n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(PackageDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ImportDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(TypeParameter n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(LineComment n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(BlockComment n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
//- Body ----------------------------------------------
|
||||
|
||||
public void visit(ClassOrInterfaceDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(EnumDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(EnumConstantDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(AnnotationDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(AnnotationMemberDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(FieldDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(VariableDeclarator n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ConstructorDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(MethodDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(Parameter n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(EmptyMemberDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(InitializerDeclaration n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(JavadocComment n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
//- Type ----------------------------------------------
|
||||
|
||||
public void visit(ClassOrInterfaceType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(PrimitiveType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ArrayType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ArrayCreationLevel n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(IntersectionType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(UnionType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(VoidType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(WildcardType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(UnknownType n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
//- Expression ----------------------------------------
|
||||
|
||||
public void visit(ArrayAccessExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ArrayCreationExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ArrayInitializerExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(AssignExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(BinaryExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(CastExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ClassExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ConditionalExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(EnclosedExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(FieldAccessExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(InstanceOfExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(StringLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(IntegerLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(LongLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(CharLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(DoubleLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(BooleanLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(NullLiteralExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(MethodCallExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(NameExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ObjectCreationExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ThisExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(SuperExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(UnaryExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(VariableDeclarationExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(MarkerAnnotationExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(SingleMemberAnnotationExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(NormalAnnotationExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(MemberValuePair n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
//- Statements ----------------------------------------
|
||||
|
||||
public void visit(ExplicitConstructorInvocationStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(AssertStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(BlockStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(LabeledStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(EmptyStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ExpressionStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(SwitchStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(SwitchEntryStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(BreakStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ReturnStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(IfStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(WhileStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ContinueStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(DoStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ForeachStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ForStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(ThrowStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(SynchronizedStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(TryStmt n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(CatchClause n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(LambdaExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(MethodReferenceExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
|
||||
public void visit(TypeExpr n, Void v) { dump(n); indent++; super.visit(n, v); indent--; }
|
||||
}
|
||||
Reference in New Issue
Block a user