Skip to content

Commit

Permalink
Merge branch 'master' of github.com:micronaut-projects/micronaut-core
Browse files Browse the repository at this point in the history
  • Loading branch information
graemerocher committed Sep 11, 2018
2 parents 0d47192 + 736c032 commit e0c522a
Show file tree
Hide file tree
Showing 15 changed files with 300 additions and 153 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,23 @@

package io.micronaut.ast.groovy.visitor;

import io.micronaut.ast.groovy.utils.AstAnnotationUtils;
import io.micronaut.ast.groovy.utils.AstClassUtils;
import io.micronaut.ast.groovy.utils.PublicMethodVisitor;
import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.inject.visitor.ClassElement;
import io.micronaut.inject.visitor.Element;
import io.micronaut.inject.visitor.VisitorContext;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.Variable;

import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* A class element returning data from a {@link ClassNode}.
Expand Down Expand Up @@ -86,4 +97,32 @@ public Object getNativeType() {
public boolean isAssignable(String type) {
return AstClassUtils.isSubclassOf(classNode, type);
}

@Override
public List<Element> getElements(VisitorContext visitorContext) {
List<Element> elements = new ArrayList<>();
new PublicMethodVisitor(((GroovyVisitorContext) visitorContext).getSourceUnit()) {

private final Set<String> processed = new HashSet<>();

protected boolean isAcceptable(MethodNode node) {
return true;
}

public void visitField(FieldNode node) {
super.visitField(node);
String key = node.getText();
if (!processed.contains(key)) {
processed.add(key);
elements.add(new GroovyFieldElement(node, AstAnnotationUtils.getAnnotationMetadata(node)));
}
}
@Override
public void accept(ClassNode classNode, MethodNode methodNode) {
elements.add(new GroovyMethodElement(methodNode, AstAnnotationUtils.getAnnotationMetadata(methodNode)));
}
}.accept(classNode);

return elements;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public void warn(String message, Element element) {

}

SourceUnit getSourceUnit() {
return sourceUnit;
}

private SyntaxErrorMessage buildErrorMessage(String message, Element element) {
ASTNode expr = (ASTNode) element.getNativeType();
return new SyntaxErrorMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,8 @@ public Object visitType(TypeElement classElement, Object o) {
private void visitIntroductionAdviceInterface(TypeElement classElement, AnnotationMetadata typeAnnotationMetadata, AopProxyWriter aopProxyWriter) {
classElement.asType().accept(new PublicAbstractMethodVisitor<Object, AopProxyWriter>(classElement, modelUtils, elementUtils) {
@Override
protected void accept(DeclaredType type, ExecutableElement method, AopProxyWriter aopProxyWriter) {
protected void accept(DeclaredType type, Element element, AopProxyWriter aopProxyWriter) {
ExecutableElement method = (ExecutableElement) element;
Map<String, Object> boundTypes = genericUtils.resolveBoundTypes(type);
ExecutableElementParamInfo params = populateParameterData(method);
Object owningType = modelUtils.resolveTypeReference(method.getEnclosingElement());
Expand Down Expand Up @@ -681,7 +682,8 @@ void visitBeanFactoryMethod(ExecutableElement beanMethod) {

returnType.accept(new PublicMethodVisitor<Object, AopProxyWriter>() {
@Override
protected void accept(DeclaredType type, ExecutableElement method, AopProxyWriter aopProxyWriter) {
protected void accept(DeclaredType type, Element element, AopProxyWriter aopProxyWriter) {
ExecutableElement method = (ExecutableElement) element;
ExecutableElementParamInfo params = populateParameterData(method);
Object owningType = modelUtils.resolveTypeReference(method.getEnclosingElement());
if (owningType == null) {
Expand Down Expand Up @@ -740,7 +742,8 @@ protected void accept(DeclaredType type, ExecutableElement method, AopProxyWrite

returnType.accept(new PublicMethodVisitor<Object, BeanDefinitionWriter>() {
@Override
protected void accept(DeclaredType type, ExecutableElement method, BeanDefinitionWriter beanWriter) {
protected void accept(DeclaredType type, Element element, BeanDefinitionWriter beanWriter) {
ExecutableElement method = (ExecutableElement) element;
ExecutableElementParamInfo params = populateParameterData(method);
Object owningType = modelUtils.resolveTypeReference(method.getEnclosingElement());
if (owningType == null) {
Expand Down Expand Up @@ -931,12 +934,13 @@ private void visitAdaptedMethod(ExecutableElement method, AnnotationMetadata met
boolean first = true;

@Override
protected void accept(DeclaredType type, ExecutableElement targetMethod, AopProxyWriter aopProxyWriter) {
protected void accept(DeclaredType type, Element element, AopProxyWriter aopProxyWriter) {
if (!first) {
error(method, "Interface to adapt [" + typeToImplement + "] is not a SAM type. More than one abstract method declared.");
return;
}
first = false;
ExecutableElement targetMethod = (ExecutableElement) element;
List<? extends VariableElement> targetParameters = targetMethod.getParameters();
List<? extends VariableElement> sourceParameters = method.getParameters();

Expand Down Expand Up @@ -1381,7 +1385,8 @@ private void visitConfigurationBuilder(Element builderElement, TypeMirror builde

PublicMethodVisitor visitor = new PublicMethodVisitor() {
@Override
protected void accept(DeclaredType type, ExecutableElement method, Object o) {
protected void accept(DeclaredType type, Element element, Object o) {
ExecutableElement method = (ExecutableElement) element;
List<? extends VariableElement> params = method.getParameters();
String methodName = method.getSimpleName().toString();
String prefix = getMethodPrefix(prefixes, methodName);
Expand Down Expand Up @@ -1432,14 +1437,19 @@ protected void accept(DeclaredType type, ExecutableElement method, Object o) {

@SuppressWarnings("MagicNumber")
@Override
protected boolean isAcceptable(ExecutableElement executableElement) {
protected boolean isAcceptable(Element element) {
// ignore deprecated methods
if (annotationUtils.hasStereotype(executableElement, Deprecated.class)) {
if (annotationUtils.hasStereotype(element, Deprecated.class)) {
return false;
}
Set<Modifier> modifiers = element.getModifiers();
if (element.getKind() == ElementKind.METHOD) {
ExecutableElement method = (ExecutableElement) element;
int paramCount = method.getParameters().size();
return modifiers.contains(Modifier.PUBLIC) && ((paramCount > 0 && paramCount < 3) || allowZeroArgs && paramCount == 0) && isPrefixedWith(method, prefixes);
} else {
return false;
}
Set<Modifier> modifiers = executableElement.getModifiers();
int paramCount = executableElement.getParameters().size();
return modifiers.contains(Modifier.PUBLIC) && ((paramCount > 0 && paramCount < 3) || allowZeroArgs && paramCount == 0) && isPrefixedWith(executableElement, prefixes);
}

private boolean isPrefixedWith(Element enclosedElement, List<String> prefixes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
* @since 1.0
*/
@Internal
class ModelUtils {
public class ModelUtils {

private final Elements elementUtils;
private final Types typeUtils;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,7 @@

package io.micronaut.annotation.processing;

import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.*;
import javax.lang.model.util.Elements;
import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -55,22 +53,27 @@ public abstract class PublicAbstractMethodVisitor<R, P> extends PublicMethodVisi
}

@Override
protected boolean isAcceptable(ExecutableElement executableElement) {
Set<Modifier> modifiers = executableElement.getModifiers();
String methodName = executableElement.getSimpleName().toString();
boolean acceptable = modelUtils.isAbstract(executableElement) && !modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.STATIC);
boolean isDeclared = executableElement.getEnclosingElement().equals(classElement);
if (acceptable && !isDeclared && declaredMethods.containsKey(methodName)) {
// check method is not overridden already
for (ExecutableElement element : declaredMethods.get(methodName)) {
if (elementUtils.overrides(element, executableElement, classElement)) {
return false;
protected boolean isAcceptable(Element element) {
if (element.getKind() == ElementKind.METHOD) {
ExecutableElement executableElement = (ExecutableElement) element;
Set<Modifier> modifiers = executableElement.getModifiers();
String methodName = executableElement.getSimpleName().toString();
boolean acceptable = modelUtils.isAbstract(executableElement) && !modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.STATIC);
boolean isDeclared = executableElement.getEnclosingElement().equals(classElement);
if (acceptable && !isDeclared && declaredMethods.containsKey(methodName)) {
// check method is not overridden already
for (ExecutableElement ex : declaredMethods.get(methodName)) {
if (elementUtils.overrides(ex, executableElement, classElement)) {
return false;
}
}
} else if (!acceptable && !modelUtils.isStatic(executableElement)) {
List<ExecutableElement> declaredMethodList = declaredMethods.computeIfAbsent(methodName, s -> new ArrayList<>());
declaredMethodList.add(executableElement);
}
} else if (!acceptable && !modelUtils.isStatic(executableElement)) {
List<ExecutableElement> declaredMethodList = declaredMethods.computeIfAbsent(methodName, s -> new ArrayList<>());
declaredMethodList.add(executableElement);
return acceptable;
} else {
return false;
}
return acceptable;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,7 @@

import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ErrorType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.AbstractTypeVisitor8;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
Expand All @@ -48,113 +31,22 @@
* @see javax.lang.model.util.AbstractTypeVisitor8
* @since 1.0
*/
public abstract class PublicMethodVisitor<R, P> extends AbstractTypeVisitor8<R, P> {
private final Set<String> processed = new HashSet<>();
public abstract class PublicMethodVisitor<R, P> extends SuperclassAwareTypeVisitor<R, P> {

@Override
public R visitIntersection(IntersectionType t, P p) {
return null;
}

@Override
public R visitPrimitive(PrimitiveType t, P p) {
return null;
}

@Override
public R visitNull(NullType t, P p) {
return null;
}

@Override
public R visitArray(ArrayType t, P p) {
return null;
}

@Override
public R visitDeclared(DeclaredType type, P p) {
Element element = type.asElement();

while ((element.getKind() == ElementKind.CLASS || element.getKind() == ElementKind.INTERFACE) && !element.toString().equals(Object.class.getName())) {
TypeElement typeElement = (TypeElement) element;
List<? extends Element> enclosedElements = typeElement.getEnclosedElements();
for (Element enclosedElement : enclosedElements) {
if (enclosedElement.getKind() == ElementKind.METHOD) {
boolean isAcceptable = isAcceptable((ExecutableElement) enclosedElement);
ExecutableElement theMethod = (ExecutableElement) enclosedElement;
if (isAcceptable) {
String qualifiedName = theMethod.toString();
// if the method has already been processed then it is overridden so ignore
if (!processed.contains(qualifiedName)) {
processed.add(qualifiedName);
accept(type, theMethod, p);
}
}

}
}
List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
for (TypeMirror anInterface : interfaces) {
if (anInterface instanceof DeclaredType) {

DeclaredType interfaceType = (DeclaredType) anInterface;
visitDeclared(interfaceType, p);
}
}
TypeMirror superMirror = typeElement.getSuperclass();
if (superMirror instanceof DeclaredType) {
element = ((DeclaredType) superMirror).asElement();
} else {
break;
}
}

return null;
}

/**
* @param executableElement The {@link ExecutableElement}
* @return Whether the element is public and final
*/
protected boolean isAcceptable(ExecutableElement executableElement) {
Set<Modifier> modifiers = executableElement.getModifiers();
return modifiers.contains(Modifier.PUBLIC) && !modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.STATIC);
}

/**
* @param type The {@link DeclaredType}
* @param method The {@link ExecutableElement}
* @param p The additional type
* Only accepts public non file or static methods
*
* @param element The {@link Element}
* @return If the element is acceptable
*/
protected abstract void accept(DeclaredType type, ExecutableElement method, P p);

@Override
public R visitError(ErrorType t, P p) {
return null;
}

@Override
public R visitTypeVariable(TypeVariable t, P p) {
return null;
}

@Override
public R visitWildcard(WildcardType t, P p) {
return null;
}

@Override
public R visitExecutable(ExecutableType t, P p) {
return null;
}

@Override
public R visitNoType(NoType t, P p) {
return null;
}

@Override
public R visitUnion(UnionType t, P p) {
return null;
protected boolean isAcceptable(Element element) {
if (element.getKind() == ElementKind.METHOD) {
Set<Modifier> modifiers = element.getModifiers();
return modifiers.contains(Modifier.PUBLIC) && !modifiers.contains(Modifier.FINAL) && !modifiers.contains(Modifier.STATIC);
} else {
return false;
}
}
}
Loading

0 comments on commit e0c522a

Please sign in to comment.