package ru.naumen.gintonic.utils;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
public class MethodDeclarationUtils {
/**
* Returns true if the given {@link ASTNode} is a constructor, otherwise
* false.
*/
public static boolean isConstructor(ASTNode node) {
if (node instanceof MethodDeclaration) {
MethodDeclaration methodDecl = (MethodDeclaration) node;
return methodDecl.isConstructor();
}
return false;
}
/**
* Returns the first constructor for the given CompilationUnit if it is
* annotated with @Inject or null if not. (Note: There may only be one
* constructor with @Inject, see
* http://code.google.com/p/google-guice/wiki/InjectionPoints)
*/
public static MethodDeclaration getConstructorAnnotatedWithInject(
CompilationUnit compilationUnit) {
ASTVisitorFindConstructor visitor = new ASTVisitorFindConstructor();
compilationUnit.accept(visitor);
List<MethodDeclaration> constructors = visitor.constructors;
for (MethodDeclaration constructor : constructors) {
@SuppressWarnings("unchecked")
List<ASTNode> modifiers = constructor.modifiers();
AnnotationList markerAnnotationList = ASTNodeUtils.getAnnotationList(modifiers);
if (markerAnnotationList.containsInjectType()) {
return constructor;
}
}
return null;
}
/**
* Returns the <b>first</b> constructor if one parameter is annotated with
* an @Assisted annotation. Returns null if noone could be found.
*/
public static MethodDeclaration getConstructorAnnotatedWithAssisted(
ASTNode astNode) {
ASTVisitorFindConstructor visitor = new ASTVisitorFindConstructor();
astNode.accept(visitor);
List<MethodDeclaration> constructors = visitor.constructors;
for (MethodDeclaration constructor : constructors) {
@SuppressWarnings("unchecked")
List<SingleVariableDeclaration> parameters = constructor.parameters();
for (SingleVariableDeclaration singleVariableDeclaration : parameters) {
@SuppressWarnings("unchecked")
List<ASTNode> modifiers = singleVariableDeclaration.modifiers();
AnnotationList markerAnnotationList = ASTNodeUtils.getAnnotationList(modifiers);
if (markerAnnotationList.containsAssistedAnnotation()) {
return constructor;
}
}
}
return null;
}
public static List<SingleVariableDeclaration> getVariableDeclAnnotatedWithAssisted(
MethodDeclaration methodDeclaration) {
final List<SingleVariableDeclaration> variableDeclarations = new ArrayList<SingleVariableDeclaration>();
methodDeclaration.accept(new ASTVisitor(false) {
@Override
public boolean visit(final SingleVariableDeclaration declNode) {
declNode.accept(new ASTVisitor(false) {
@Override
public boolean visit(MarkerAnnotation node) {
if (ASTNodeUtils.isAssistedAnnotation(node)) {
variableDeclarations.add(declNode);
}
return false;
}
});
return false;
}
});
return variableDeclarations;
}
public static SingleVariableDeclaration getVariableDeclarationsByName(
MethodDeclaration methodDeclaration, final String fieldNameFQ) {
Preconditions.checkNotNull(methodDeclaration);
Preconditions.checkNotNull(fieldNameFQ);
FindVariableDeclWithName variableDeclWithName = new FindVariableDeclWithName(
fieldNameFQ);
methodDeclaration.accept(variableDeclWithName);
return variableDeclWithName.declaration;
}
private static MethodDeclaration getMethodDeclarationByName(
CompilationUnit compilationUnit, String name) {
ASTVisitorExtension visitorExtension = new ASTVisitorExtension(name);
compilationUnit.accept(visitorExtension);
return visitorExtension.getMethodDeclaration();
}
public static MethodDeclaration getConfigureMethodDeclaration(
CompilationUnit compilationUnit) {
return getMethodDeclarationByName(compilationUnit, "configure");
}
private final static class ASTVisitorExtension extends ASTVisitor {
private String methodnameToFind;
private MethodDeclaration methodDeclaration;
public ASTVisitorExtension(String methodnameToFinde) {
super();
this.methodnameToFind = methodnameToFinde;
}
public MethodDeclaration getMethodDeclaration() {
return methodDeclaration;
}
@SuppressWarnings("synthetic-access")
@Override
public boolean visit(MethodDeclaration method) {
SimpleName simpleName = method.getName();
String methodname = simpleName.toString();
if (methodname.equals(methodnameToFind)) {
this.methodDeclaration = method;
}
return false;
}
}
private static final class ASTVisitorFindConstructor extends ASTVisitor {
public List<MethodDeclaration> constructors = ListUtils.newArrayList();
private ASTVisitorFindConstructor() {
super(false);
}
@Override
public boolean visit(MethodDeclaration node) {
boolean isConstructor = isConstructor(node);
if (isConstructor) {
constructors.add(node);
}
return false;
}
}
private static final class FindVariableDeclWithName extends ASTVisitor {
private final String fieldNameFQ;
SingleVariableDeclaration declaration;
private FindVariableDeclWithName(String fieldNameFQ) {
super(false);
this.fieldNameFQ = fieldNameFQ;
}
@Override
public boolean visit(final SingleVariableDeclaration declNode) {
SimpleName name = declNode.getName();
String fullyQualifiedName = name.getFullyQualifiedName();
if (fullyQualifiedName.equals(fieldNameFQ)) {
declaration = declNode;
}
return false;
}
}
}