diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/AnnotationUtils.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/AnnotationUtils.java index f5daeaf2f..34d36b608 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/AnnotationUtils.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/AnnotationUtils.java @@ -39,6 +39,7 @@ import static io.microsphere.lang.function.Predicates.EMPTY_PREDICATE_ARRAY; import static io.microsphere.lang.function.Streams.filterAll; import static io.microsphere.lang.function.Streams.filterFirst; +import static io.microsphere.util.ClassLoaderUtils.resolveClass; import static java.lang.Enum.valueOf; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toList; @@ -49,58 +50,58 @@ * @author Mercy * @since 1.0.0 */ -public abstract class AnnotationUtils { +public interface AnnotationUtils { - public static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, Class annotationClass) { + static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, Class annotationClass) { return annotationClass == null ? null : getAnnotation(annotatedConstruct, annotationClass.getTypeName()); } - public static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) { + static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) { List annotations = getAnnotations(annotatedConstruct, annotationClassName); return annotations.isEmpty() ? null : annotations.get(0); } - public static List getAnnotations(AnnotatedConstruct annotatedConstruct, Class annotationClass) { + static List getAnnotations(AnnotatedConstruct annotatedConstruct, Class annotationClass) { return annotationClass == null ? emptyList() : getAnnotations(annotatedConstruct, annotationClass.getTypeName()); } - public static List getAnnotations(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) { + static List getAnnotations(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) { return findAnnotations(annotatedConstruct, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName)); } - public static List getAnnotations(AnnotatedConstruct annotatedConstruct) { + static List getAnnotations(AnnotatedConstruct annotatedConstruct) { return findAnnotations(annotatedConstruct, EMPTY_PREDICATE_ARRAY); } - public static List getAllAnnotations(TypeMirror type) { + static List getAllAnnotations(TypeMirror type) { return getAllAnnotations(ofTypeElement(type)); } - public static List getAllAnnotations(Element element) { + static List getAllAnnotations(Element element) { return findAllAnnotations(element, EMPTY_PREDICATE_ARRAY); } - public static List getAllAnnotations(TypeMirror type, Class annotationClass) { + static List getAllAnnotations(TypeMirror type, Class annotationClass) { return getAllAnnotations(ofTypeElement(type), annotationClass); } - public static List getAllAnnotations(Element element, Class annotationClass) { + static List getAllAnnotations(Element element, Class annotationClass) { return element == null || annotationClass == null ? emptyList() : getAllAnnotations(element, annotationClass.getTypeName()); } - public static List getAllAnnotations(TypeMirror type, CharSequence annotationClassName) { + static List getAllAnnotations(TypeMirror type, CharSequence annotationClassName) { return getAllAnnotations(ofTypeElement(type), annotationClassName); } - public static List getAllAnnotations(Element element, CharSequence annotationClassName) { + static List getAllAnnotations(Element element, CharSequence annotationClassName) { return findAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName)); } - public static List getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType) { + static List getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType) { return findAllAnnotations(processingEnv, annotatedType, EMPTY_PREDICATE_ARRAY); } - public static List findAnnotations(AnnotatedConstruct annotatedConstruct, Predicate... annotationFilters) { + static List findAnnotations(AnnotatedConstruct annotatedConstruct, Predicate... annotationFilters) { AnnotatedConstruct actualAnnotatedConstruct = annotatedConstruct; @@ -111,19 +112,19 @@ public static List findAnnotations(AnnotatedConstruct annotate return actualAnnotatedConstruct == null ? emptyList() : filterAll((List) actualAnnotatedConstruct.getAnnotationMirrors(), annotationFilters); } - public static List findAllAnnotations(TypeMirror type, Predicate... annotationFilters) { + static List findAllAnnotations(TypeMirror type, Predicate... annotationFilters) { return findAllAnnotations(ofTypeElement(type), annotationFilters); } - public static List findAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType, Predicate... annotationFilters) { + static List findAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType, Predicate... annotationFilters) { return annotatedType == null ? emptyList() : findAllAnnotations(processingEnv, annotatedType.getTypeName(), annotationFilters); } - public static List findAllAnnotations(ProcessingEnvironment processingEnv, CharSequence annotatedTypeName, Predicate... annotationFilters) { + static List findAllAnnotations(ProcessingEnvironment processingEnv, CharSequence annotatedTypeName, Predicate... annotationFilters) { return findAllAnnotations(TypeUtils.getTypeElement(processingEnv, annotatedTypeName), annotationFilters); } - public static List findAllAnnotations(Element element, Predicate... annotationFilters) { + static List findAllAnnotations(Element element, Predicate... annotationFilters) { List allAnnotations = isTypeElement(element) ? TypeUtils.getAllTypeElements(ofTypeElement(element)) @@ -135,35 +136,35 @@ public static List findAllAnnotations(Element element, Predica return filterAll(allAnnotations, annotationFilters); } - public static AnnotationMirror findAnnotation(TypeMirror type, Class annotationClass) { + static AnnotationMirror findAnnotation(TypeMirror type, Class annotationClass) { return annotationClass == null ? null : findAnnotation(type, annotationClass.getTypeName()); } - public static AnnotationMirror findAnnotation(TypeMirror type, CharSequence annotationClassName) { + static AnnotationMirror findAnnotation(TypeMirror type, CharSequence annotationClassName) { return findAnnotation(ofTypeElement(type), annotationClassName); } - public static AnnotationMirror findAnnotation(Element element, Class annotationClass) { + static AnnotationMirror findAnnotation(Element element, Class annotationClass) { return annotationClass == null ? null : findAnnotation(element, annotationClass.getTypeName()); } - public static AnnotationMirror findAnnotation(Element element, CharSequence annotationClassName) { + static AnnotationMirror findAnnotation(Element element, CharSequence annotationClassName) { return filterFirst(findAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName))); } - public static AnnotationMirror findMetaAnnotation(Element annotatedConstruct, CharSequence metaAnnotationClassName) { + static AnnotationMirror findMetaAnnotation(Element annotatedConstruct, CharSequence metaAnnotationClassName) { return annotatedConstruct == null ? null : getAnnotations(annotatedConstruct).stream().map(annotation -> findAnnotation(annotation.getAnnotationType(), metaAnnotationClassName)).filter(Objects::nonNull).findFirst().orElse(null); } - public static boolean isAnnotationPresent(Element element, CharSequence annotationClassName) { + static boolean isAnnotationPresent(Element element, CharSequence annotationClassName) { return findAnnotation(element, annotationClassName) != null || findMetaAnnotation(element, annotationClassName) != null; } - public static T getAttribute(AnnotationMirror annotation, String attributeName) { + static T getAttribute(AnnotationMirror annotation, String attributeName) { return annotation == null ? null : getAttribute(annotation.getElementValues(), attributeName); } - public static T getAttribute(Map attributesMap, String attributeName) { + static T getAttribute(Map attributesMap, String attributeName) { T annotationValue = null; for (Map.Entry entry : attributesMap.entrySet()) { ExecutableElement attributeMethod = entry.getKey(); @@ -172,25 +173,21 @@ public static T getAttribute(Map values = (List) value.getValue(); int size = values.size(); - try { - Class componentClass = classLoader.loadClass(componentType); - boolean isEnum = componentClass.isEnum(); - Object array = Array.newInstance(componentClass, values.size()); - for (int i = 0; i < size; i++) { - Object element = values.get(i).getValue(); - if (isEnum) { - element = valueOf(componentClass, element.toString()); - } - Array.set(array, i, element); + Class componentClass = resolveClass(componentTypeName, classLoader); + boolean isEnum = componentClass.isEnum(); + Object array = Array.newInstance(componentClass, values.size()); + for (int i = 0; i < size; i++) { + Object element = values.get(i).getValue(); + if (isEnum) { + element = valueOf(componentClass, element.toString()); } - annotationValue = (T) array; - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); + Array.set(array, i, element); } + annotationValue = (T) array; } else { annotationValue = (T) value.getValue(); } @@ -200,7 +197,7 @@ public static T getAttribute(Map T getValue(AnnotationMirror annotation) { - return (T) getAttribute(annotation, "value"); + static T getValue(AnnotationMirror annotation) { + return getAttribute(annotation, "value"); } } diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/ExecutableElementComparator.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/ExecutableElementComparator.java index 6bd308c60..a487bfbb7 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/ExecutableElementComparator.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/ExecutableElementComparator.java @@ -37,6 +37,9 @@ */ public class ExecutableElementComparator implements Comparator { + /** + * The singleton instance + */ public static final ExecutableElementComparator INSTANCE = new ExecutableElementComparator(); private ExecutableElementComparator() { @@ -61,7 +64,7 @@ public int compare(ExecutableElement e1, ExecutableElement e2) { if (value == 0) { // Step 3 for (int i = 0; i < ps1.size(); i++) { - value = CharSequenceComparator.INSTANCE.compare(ps1.get(i).getSimpleName(), ps2.get(i).getSimpleName()); + value = CharSequenceComparator.INSTANCE.compare(ps1.get(i).asType().toString(), ps2.get(i).asType().toString()); if (value != 0) { break; } diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/FieldUtils.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/FieldUtils.java index 46ea30e80..83cdce076 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/FieldUtils.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/FieldUtils.java @@ -27,7 +27,7 @@ import static io.microsphere.annotation.processor.util.MemberUtils.getDeclaredMembers; import static io.microsphere.annotation.processor.util.MemberUtils.hasModifiers; -import static io.microsphere.annotation.processor.util.MemberUtils.matches; +import static io.microsphere.annotation.processor.util.MemberUtils.matchesElementKind; import static io.microsphere.annotation.processor.util.TypeUtils.getAllDeclaredTypes; import static io.microsphere.annotation.processor.util.TypeUtils.isEnumType; import static io.microsphere.lang.function.Predicates.EMPTY_PREDICATE_ARRAY; @@ -117,7 +117,7 @@ static boolean isNonStaticField(VariableElement field) { } static boolean isField(VariableElement field) { - return matches(field, FIELD) || isEnumMemberField(field); + return matchesElementKind(field, FIELD) || isEnumMemberField(field); } static boolean isField(VariableElement field, Modifier... modifiers) { diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MemberUtils.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MemberUtils.java index d50a8bc6c..260a40935 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MemberUtils.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MemberUtils.java @@ -22,13 +22,21 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; +import java.lang.reflect.Type; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.Set; +import java.util.function.Predicate; import static io.microsphere.annotation.processor.util.TypeUtils.getAllDeclaredTypes; +import static io.microsphere.annotation.processor.util.TypeUtils.isSameType; import static io.microsphere.annotation.processor.util.TypeUtils.ofTypeElement; +import static io.microsphere.collection.CollectionUtils.isEmpty; +import static io.microsphere.lang.function.Predicates.EMPTY_PREDICATE_ARRAY; +import static io.microsphere.lang.function.Predicates.and; +import static io.microsphere.reflect.TypeUtils.getTypeNames; +import static io.microsphere.util.ArrayUtils.isNotEmpty; +import static io.microsphere.util.ArrayUtils.length; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.toList; import static javax.lang.model.element.Modifier.PUBLIC; @@ -42,7 +50,7 @@ */ public interface MemberUtils { - static boolean matches(Element member, ElementKind kind) { + static boolean matchesElementKind(Element member, ElementKind kind) { return member == null || kind == null ? false : kind.equals(member.getKind()); } @@ -64,29 +72,78 @@ static boolean hasModifiers(Element member, Modifier... modifiers) { } static List getDeclaredMembers(TypeMirror type) { - TypeElement element = ofTypeElement(type); - return element == null ? emptyList() : element.getEnclosedElements(); + return type == null ? emptyList() : getDeclaredMembers(ofTypeElement(type)); + } + + static List getDeclaredMembers(TypeElement type) { + return type == null ? emptyList() : findDeclaredMembers(type, EMPTY_PREDICATE_ARRAY); } static List getAllDeclaredMembers(TypeMirror type) { - return getAllDeclaredTypes(type) + return type == null ? emptyList() : findAllDeclaredMembers(ofTypeElement(type), EMPTY_PREDICATE_ARRAY); + } + + static List getAllDeclaredMembers(TypeElement type) { + return type == null ? emptyList() : findAllDeclaredMembers(type, EMPTY_PREDICATE_ARRAY); + } + + static List findDeclaredMembers(TypeMirror type, Predicate... memberFilters) { + return type == null ? emptyList() : findDeclaredMembers(ofTypeElement(type), memberFilters); + } + + static List findDeclaredMembers(TypeElement type, Predicate... memberFilters) { + if (type == null) { + return emptyList(); + } + return filterMembers(type.getEnclosedElements(), memberFilters); + } + + static List findAllDeclaredMembers(TypeMirror type, Predicate... memberFilters) { + return type == null ? emptyList() : findAllDeclaredMembers(ofTypeElement(type), memberFilters); + } + + static List findAllDeclaredMembers(TypeElement type, Predicate... memberFilters) { + if (type == null) { + return emptyList(); + } + List declaredMembers = getAllDeclaredTypes(type) .stream() .map(MemberUtils::getDeclaredMembers) .flatMap(Collection::stream) .collect(toList()); + return filterMembers(declaredMembers, memberFilters); } - static boolean matchParameterTypes(List parameters, CharSequence... parameterTypes) { + static List filterMembers(List members, Predicate... memberFilters) { + if (isEmpty(members)) { + return emptyList(); + } + if (isNotEmpty(memberFilters)) { + Predicate predicate = and(memberFilters); + members = (List) members.stream().filter(predicate).collect(toList()); + } + return members.isEmpty() ? emptyList() : members; + } + + static boolean matchParameterTypes(List parameters, Type... parameterTypes) { + return parameters == null || parameterTypes == null ? false : matchParameterTypeNames(parameters, getTypeNames(parameterTypes)); + } + + static boolean matchParameterTypeNames(List parameters, CharSequence... parameterTypeNames) { + if (parameters == null || parameterTypeNames == null) { + return false; + } + int length = length(parameterTypeNames); int size = parameters.size(); - if (size != parameterTypes.length) { + if (size != length) { return false; } for (int i = 0; i < size; i++) { VariableElement parameter = parameters.get(i); - if (!Objects.equals(parameter.asType().toString(), parameterTypes[i])) { + if (!isSameType(parameter, parameterTypeNames[i])) { return false; } } diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MethodUtils.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MethodUtils.java index 6a737a443..078004abc 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MethodUtils.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/MethodUtils.java @@ -18,6 +18,7 @@ import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.Element; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; @@ -25,22 +26,26 @@ import javax.lang.model.util.Elements; import java.lang.reflect.Type; import java.util.Collection; -import java.util.LinkedList; import java.util.List; +import java.util.Objects; import java.util.function.Predicate; -import java.util.stream.Collectors; import static io.microsphere.annotation.processor.util.MemberUtils.getDeclaredMembers; import static io.microsphere.annotation.processor.util.MemberUtils.isPublicNonStatic; +import static io.microsphere.annotation.processor.util.MemberUtils.matchParameterTypeNames; import static io.microsphere.annotation.processor.util.MemberUtils.matchParameterTypes; import static io.microsphere.annotation.processor.util.TypeUtils.getAllDeclaredTypes; +import static io.microsphere.annotation.processor.util.TypeUtils.isSameType; import static io.microsphere.annotation.processor.util.TypeUtils.ofDeclaredType; -import static io.microsphere.collection.CollectionUtils.addAll; -import static io.microsphere.filter.FilterUtils.filter; +import static io.microsphere.collection.CollectionUtils.isEmpty; import static io.microsphere.lang.function.Predicates.EMPTY_PREDICATE_ARRAY; -import static io.microsphere.lang.function.Streams.filterAll; +import static io.microsphere.lang.function.Predicates.and; import static io.microsphere.lang.function.Streams.filterFirst; +import static io.microsphere.util.ArrayUtils.EMPTY_STRING_ARRAY; +import static io.microsphere.util.ArrayUtils.EMPTY_TYPE_ARRAY; +import static io.microsphere.util.ArrayUtils.isNotEmpty; import static java.util.Collections.emptyList; +import static java.util.stream.Collectors.toList; import static javax.lang.model.element.ElementKind.METHOD; import static javax.lang.model.util.ElementFilter.methodsIn; @@ -69,19 +74,28 @@ static List getAllDeclaredMethods(TypeMirror type) { } static List findDeclaredMethods(TypeElement type, Predicate... methodFilters) { - return type == null ? emptyList() : findDeclaredMethods(type.asType(), methodFilters); + if (type == null) { + return emptyList(); + } + return findDeclaredMethods(type.asType(), methodFilters); } static List findDeclaredMethods(TypeMirror type, Predicate... methodFilters) { - return filterAll(methodsIn(getDeclaredMembers(type)), methodFilters); - } + if (type == null) { + return emptyList(); + } - static List findAllDeclaredMethods(TypeElement type, Predicate... methodFilters) { - return type == null ? emptyList() : findAllDeclaredMethods(type.asType(), methodFilters); - } + List declaredMembers = getDeclaredMembers(type); + if (declaredMembers.isEmpty()) { + return emptyList(); + } - static List findAllDeclaredMethods(TypeMirror type, Predicate... methodFilters) { - return getAllDeclaredTypes(type).stream().map(t -> findDeclaredMethods(t, methodFilters)).flatMap(Collection::stream).collect(Collectors.toList()); + List declaredMethods = methodsIn(declaredMembers); + if (declaredMethods.isEmpty()) { + return emptyList(); + } + + return filterMethods(declaredMethods, methodFilters); } static List findAllDeclaredMethods(TypeElement type, Type... excludedTypes) { @@ -89,15 +103,46 @@ static List findAllDeclaredMethods(TypeElement type, Type... } static List findAllDeclaredMethods(TypeMirror type, Type... excludedTypes) { - return TypeUtils.findAllDeclaredTypes(type, excludedTypes).stream().map(t -> findDeclaredMethods(t)).flatMap(Collection::stream).collect(Collectors.toList()); + if (type == null) { + return emptyList(); + } + return findAllDeclaredMethods(type, methodPredicateForExcludedTypes(excludedTypes)); } static List findPublicNonStaticMethods(TypeElement type, Type... excludedTypes) { - return findPublicNonStaticMethods(ofDeclaredType(type), excludedTypes); + return type == null ? emptyList() : findPublicNonStaticMethods(ofDeclaredType(type), excludedTypes); + } static List findPublicNonStaticMethods(TypeMirror type, Type... excludedTypes) { - return filter(findAllDeclaredMethods(type, excludedTypes), MethodUtils::isPublicNonStaticMethod); + if (type == null) { + return emptyList(); + } + + Predicate predicate = and(methodPredicateForExcludedTypes(excludedTypes), MethodUtils::isPublicNonStaticMethod); + + return findAllDeclaredMethods(type, predicate); + } + + static List findAllDeclaredMethods(TypeElement type, Predicate... methodFilters) { + return type == null ? emptyList() : findAllDeclaredMethods(type.asType(), methodFilters); + } + + static List findAllDeclaredMethods(TypeMirror type, Predicate... methodFilters) { + if (type == null) { + return emptyList(); + } + + List allDeclaredMethods = getAllDeclaredTypes(type).stream() + .map(MethodUtils::getDeclaredMethods) + .flatMap(Collection::stream) + .collect(toList()); + + if (allDeclaredMethods.isEmpty()) { + return emptyList(); + } + + return filterMethods(allDeclaredMethods, methodFilters); } static boolean isMethod(ExecutableElement method) { @@ -108,23 +153,36 @@ static boolean isPublicNonStaticMethod(ExecutableElement method) { return isMethod(method) && isPublicNonStatic(method); } - static ExecutableElement findMethod(TypeElement type, String methodName, Type oneParameterType, Type... otherParameterTypes) { - return type == null ? null : findMethod(type.asType(), methodName, oneParameterType, otherParameterTypes); + static ExecutableElement findMethod(TypeElement type, String methodName) { + return findMethod(type, methodName, EMPTY_TYPE_ARRAY); } - static ExecutableElement findMethod(TypeMirror type, String methodName, Type oneParameterType, Type... otherParameterTypes) { - List parameterTypes = new LinkedList<>(); - parameterTypes.add(oneParameterType); - addAll(parameterTypes, otherParameterTypes); - return findMethod(type, methodName, parameterTypes.stream().map(Type::getTypeName).toArray(String[]::new)); + static ExecutableElement findMethod(TypeMirror type, String methodName) { + return findMethod(type, methodName, EMPTY_TYPE_ARRAY); } - static ExecutableElement findMethod(TypeElement type, String methodName, CharSequence... parameterTypes) { + static ExecutableElement findMethod(TypeElement type, String methodName, Type... parameterTypes) { return type == null ? null : findMethod(type.asType(), methodName, parameterTypes); } - static ExecutableElement findMethod(TypeMirror type, String methodName, CharSequence... parameterTypes) { - return filterFirst(getAllDeclaredMethods(type), method -> methodName.equals(method.getSimpleName().toString()), method -> matchParameterTypes(method.getParameters(), parameterTypes)); + static ExecutableElement findMethod(TypeMirror type, String methodName, Type... parameterTypes) { + if (type == null || methodName == null || parameterTypes == null) { + return null; + } + List allDeclaredMethods = findAllDeclaredMethods(type, method -> matches(method, methodName, parameterTypes)); + return allDeclaredMethods.isEmpty() ? null : allDeclaredMethods.get(0); + } + + static ExecutableElement findMethod(TypeElement type, String methodName, CharSequence... parameterTypeNames) { + return type == null ? null : findMethod(type.asType(), methodName, parameterTypeNames); + } + + static ExecutableElement findMethod(TypeMirror type, String methodName, CharSequence... parameterTypeNames) { + if (type == null || methodName == null || parameterTypeNames == null) { + return null; + } + List allDeclaredMethods = findAllDeclaredMethods(type, method -> matches(method, methodName, parameterTypeNames)); + return allDeclaredMethods.isEmpty() ? null : allDeclaredMethods.get(0); } static ExecutableElement getOverrideMethod(ProcessingEnvironment processingEnv, TypeElement type, ExecutableElement declaringMethod) { @@ -132,15 +190,113 @@ static ExecutableElement getOverrideMethod(ProcessingEnvironment processingEnv, return filterFirst(getAllDeclaredMethods(type), method -> elements.overrides(method, declaringMethod, type)); } + static List filterMethods(List methods, Predicate... methodFilters) { + if (isEmpty(methods)) { + return emptyList(); + } + + List filteredMethods = methods; + if (isNotEmpty(methodFilters)) { + Predicate predicate = and(methodFilters); + filteredMethods = (List) methods.stream().filter(predicate).collect(toList()); + } + + return filteredMethods.isEmpty() ? emptyList() : filteredMethods; + } + static String getMethodName(ExecutableElement method) { return method == null ? null : method.getSimpleName().toString(); } - static String getReturnType(ExecutableElement method) { + static String getReturnTypeName(ExecutableElement method) { return method == null ? null : TypeUtils.toString(method.getReturnType()); } - static String[] getMethodParameterTypes(ExecutableElement method) { - return method == null ? new String[0] : method.getParameters().stream().map(VariableElement::asType).map(TypeUtils::toString).toArray(String[]::new); + static List getMethodParameterTypeMirrors(ExecutableElement method) { + if (method == null) { + return emptyList(); + } + + List parameters = method.getParameters(); + if (parameters.isEmpty()) { + return emptyList(); + } + + List parameterTypes = parameters.stream() + .map(VariableElement::asType) + .collect(toList()); + + return parameterTypes; + } + + static String[] getMethodParameterTypeNames(ExecutableElement method) { + List parameterTypes = getMethodParameterTypeMirrors(method); + return parameterTypes.isEmpty() ? EMPTY_STRING_ARRAY : parameterTypes.stream().map(TypeUtils::toString).toArray(String[]::new); + } + + static boolean matches(ExecutableElement method, String methodName, Type... parameterTypes) { + return matchesMethod(method, methodName, parameterTypes); + } + + static boolean matches(ExecutableElement method, String methodName, CharSequence... parameterTypeNames) { + return matchesMethod(method, methodName, parameterTypeNames); + } + + static boolean matchesMethod(ExecutableElement method, String methodName, Type... parameterTypes) { + if (method == null || methodName == null || parameterTypes == null) { + return false; + } + + // matches the name of method + if (!Objects.equals(getMethodName(method), methodName)) { + return false; + } + + if (!matchParameterTypes(method.getParameters(), parameterTypes)) { + return false; + } + + return true; + } + + static boolean matchesMethod(ExecutableElement method, String methodName, CharSequence... parameterTypeNames) { + if (method == null || methodName == null || parameterTypeNames == null) { + return false; + } + + // matches the name of method + if (!Objects.equals(getMethodName(method), methodName)) { + return false; + } + + if (!matchParameterTypeNames(method.getParameters(), parameterTypeNames)) { + return false; + } + + return true; + } + + /** + * Returns the class or interface defining the executable. + * + * @param method {@link ExecutableElement} + * @return null if method is null + */ + static Element getEnclosingElement(ExecutableElement method) { + return method == null ? null : method.getEnclosingElement(); + } + + static Predicate methodPredicateForExcludedTypes(Type... excludedTypes) { + return method -> { + boolean excluded = true; + Element declaredType = getEnclosingElement(method); + for (Type excludedType : excludedTypes) { + if (isSameType(declaredType, excludedType)) { + excluded = false; + break; + } + } + return excluded; + }; } } diff --git a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/TypeUtils.java b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/TypeUtils.java index 134a22676..b72ef264e 100644 --- a/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/TypeUtils.java +++ b/microsphere-annotation-processor/src/main/java/io/microsphere/annotation/processor/util/TypeUtils.java @@ -34,6 +34,7 @@ import static io.microsphere.collection.CollectionUtils.isEmpty; import static io.microsphere.collection.Lists.ofList; +import static io.microsphere.constants.SymbolConstants.COMMA_CHAR; import static io.microsphere.lang.function.Predicates.EMPTY_PREDICATE_ARRAY; import static io.microsphere.lang.function.Predicates.and; import static io.microsphere.lang.function.Streams.filterFirst; @@ -597,6 +598,13 @@ static DeclaredType getDeclaredType(ProcessingEnvironment processingEnv, CharSeq } static String toString(TypeMirror type) { + return getTypeName(type); + } + + static String getTypeName(TypeMirror type) { + if (type == null) { + return null; + } TypeElement element = ofTypeElement(type); if (element != null) { List typeParameterElements = element.getTypeParameters(); @@ -606,7 +614,7 @@ static String toString(TypeMirror type) { typeBuilder.append("<"); for (int i = 0; i < typeMirrors.size(); i++) { if (i > 0) { - typeBuilder.append(", "); + typeBuilder.append(COMMA_CHAR); } typeBuilder.append(toString(typeMirrors.get(i))); } diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/AbstractAnnotationProcessingTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/AbstractAnnotationProcessingTest.java index 6be66969a..64b4b49df 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/AbstractAnnotationProcessingTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/AbstractAnnotationProcessingTest.java @@ -30,9 +30,12 @@ import javax.lang.model.util.Types; import java.lang.annotation.Annotation; import java.lang.reflect.Type; +import java.util.Collection; import java.util.List; import java.util.Set; +import static io.microsphere.annotation.processor.util.TypeUtils.ofDeclaredType; + /** * Abstract {@link Annotation} Processing Test case * @@ -42,6 +45,36 @@ @ExtendWith(CompilerInvocationInterceptor.class) public abstract class AbstractAnnotationProcessingTest { + protected static final TypeMirror NULL_TYPE_MIRROR = null; + + protected static final TypeMirror[] EMPTY_TYPE_MIRROR_ARRAY = new TypeMirror[0]; + + protected static final TypeMirror[] NULL_TYPE_MIRROR_ARRAY = null; + + protected static final Collection[] EMPTY_COLLECTION_ARRAY = new Collection[0]; + + protected static final Collection NULL_COLLECTION = null; + + protected static final Element NULL_ELEMENT = null; + + protected static final Element[] EMPTY_ELEMENT_ARRAY = new Element[0]; + + protected static final Element[] NULL_ELEMENT_ARRAY = null; + + protected static final TypeElement NULL_TYPE_ELEMENT = null; + + protected static final Type[] NULL_TYPE_ARRAY = null; + + protected static final Type[] EMPTY_TYPE_ARRAY = new Type[0]; + + protected static final Type NULL_TYPE = null; + + protected static final ProcessingEnvironment NULL_PROCESSING_ENVIRONMENT = null; + + protected static final String NULL_STRING = null; + + protected static final String[] NULL_STRING_ARRAY = null; + static ThreadLocal testInstanceHolder = new ThreadLocal<>(); protected ProcessingEnvironment processingEnv; @@ -50,6 +83,16 @@ public abstract class AbstractAnnotationProcessingTest { protected Types types; + protected Class testClass; + + protected String testClassName; + + protected TypeElement testTypeElement; + + protected TypeMirror testTypeMirror; + + protected DeclaredType testDeclaredType; + @BeforeEach public final void init() { testInstanceHolder.set(this); @@ -64,6 +107,11 @@ protected void addCompiledClasses(Set> compiledClasses) { } protected void beforeTest() { + this.testClass = TestServiceImpl.class; + this.testClassName = TestServiceImpl.class.getName(); + this.testTypeElement = getTypeElement(testClass); + this.testTypeMirror = this.testTypeElement.asType(); + this.testDeclaredType = ofDeclaredType(this.testTypeElement); } protected void afterTest() { diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/TestServiceImpl.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/TestServiceImpl.java index 76f718c0f..9bf49bbf1 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/TestServiceImpl.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/TestServiceImpl.java @@ -16,6 +16,7 @@ */ package io.microsphere.annotation.processor; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import javax.xml.ws.ServiceMode; @@ -30,6 +31,7 @@ public class TestServiceImpl extends GenericTestService implements TestService, AutoCloseable, Serializable { @Override + @Cacheable(cacheNames = {"cache-1", "cache-2"}) public String echo(String message) { return "[ECHO] " + message; } diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/AnnotationUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/AnnotationUtilsTest.java index 978b59624..60b04e7ed 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/AnnotationUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/AnnotationUtilsTest.java @@ -20,16 +20,20 @@ import io.microsphere.annotation.processor.TestService; import io.microsphere.annotation.processor.TestServiceImpl; import org.junit.jupiter.api.Test; +import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.type.DeclaredType; import javax.lang.model.type.TypeMirror; import javax.ws.rs.Path; import javax.xml.ws.ServiceMode; import java.lang.annotation.Annotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; import java.util.Iterator; import java.util.List; @@ -42,7 +46,12 @@ import static io.microsphere.annotation.processor.util.AnnotationUtils.getAttribute; import static io.microsphere.annotation.processor.util.AnnotationUtils.getValue; import static io.microsphere.annotation.processor.util.AnnotationUtils.isAnnotationPresent; +import static io.microsphere.annotation.processor.util.MethodUtils.findMethod; import static io.microsphere.annotation.processor.util.MethodUtils.getAllDeclaredMethods; +import static io.microsphere.util.ArrayUtils.ofArray; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -55,13 +64,6 @@ */ public class AnnotationUtilsTest extends AbstractAnnotationProcessingTest { - private TypeElement testType; - - @Override - protected void beforeTest() { - testType = getTypeElement(TestServiceImpl.class); - } - @Test public void testGetAnnotation() { asserGetAnnotation(Service.class); @@ -74,11 +76,11 @@ public void testGetAnnotationWithClassName() { @Test public void testGetAnnotationOnNull() { - assertNull(getAnnotation(testType, (Class) null)); - assertNull(getAnnotation(testType, (String) null)); + assertNull(getAnnotation(testTypeElement, (Class) null)); + assertNull(getAnnotation(testTypeElement, (String) null)); - assertNull(getAnnotation(testType.asType(), (Class) null)); - assertNull(getAnnotation(testType.asType(), (String) null)); + assertNull(getAnnotation(testTypeElement.asType(), (Class) null)); + assertNull(getAnnotation(testTypeElement.asType(), (String) null)); assertNull(getAnnotation(null, (Class) null)); assertNull(getAnnotation(null, (String) null)); @@ -89,7 +91,7 @@ public void testGetAnnotationOnNull() { @Test public void testGetAnnotations() { - List annotations = getAnnotations(testType); + List annotations = getAnnotations(testTypeElement); Iterator iterator = annotations.iterator(); assertEquals(2, annotations.size()); @@ -105,7 +107,7 @@ public void testGetAnnotationsWithAnnotationType() { @Test public void testGetAnnotationsWithAnnotationTypeOnNotFound() { - List annotations = getAnnotations(testType, Override.class); + List annotations = getAnnotations(testTypeElement, Override.class); assertEquals(0, annotations.size()); } @@ -119,8 +121,8 @@ public void testGetAnnotationsWithAnnotationClassName() { public void testGetAnnotationsOnNull() { assertTrue(getAnnotations(null, (Class) null).isEmpty()); assertTrue(getAnnotations(null, (String) null).isEmpty()); - assertTrue(getAnnotations(testType, (Class) null).isEmpty()); - assertTrue(getAnnotations(testType, (String) null).isEmpty()); + assertTrue(getAnnotations(testTypeElement, (Class) null).isEmpty()); + assertTrue(getAnnotations(testTypeElement, (String) null).isEmpty()); assertTrue(getAnnotations(null, Service.class).isEmpty()); assertTrue(getAnnotations(null, Service.class.getTypeName()).isEmpty()); @@ -129,19 +131,19 @@ public void testGetAnnotationsOnNull() { @Test public void testGetAllAnnotations() { - List annotations = getAllAnnotations(testType); + List annotations = getAllAnnotations(testTypeElement); assertEquals(3, annotations.size()); - annotations = findAllAnnotations(testType.asType(), annotation -> true); + annotations = findAllAnnotations(testTypeElement.asType(), annotation -> true); assertEquals(3, annotations.size()); annotations = getAllAnnotations(processingEnv, TestServiceImpl.class); assertEquals(3, annotations.size()); - annotations = getAllAnnotations(testType.asType(), Service.class); + annotations = getAllAnnotations(testTypeElement.asType(), Service.class); assertEquals(1, annotations.size()); - annotations = getAllAnnotations(testType, Override.class); + annotations = getAllAnnotations(testTypeElement, Override.class); assertEquals(0, annotations.size()); assertTrue(getAllAnnotations((Element) null, (Class) null).isEmpty()); @@ -155,11 +157,11 @@ public void testGetAllAnnotations() { assertTrue(findAllAnnotations(processingEnv, (String) null).isEmpty()); - assertTrue(getAllAnnotations(testType, (Class) null).isEmpty()); - assertTrue(getAllAnnotations(testType.asType(), (Class) null).isEmpty()); + assertTrue(getAllAnnotations(testTypeElement, (Class) null).isEmpty()); + assertTrue(getAllAnnotations(testTypeElement.asType(), (Class) null).isEmpty()); - assertTrue(getAllAnnotations(testType, (String) null).isEmpty()); - assertTrue(getAllAnnotations(testType.asType(), (String) null).isEmpty()); + assertTrue(getAllAnnotations(testTypeElement, (String) null).isEmpty()); + assertTrue(getAllAnnotations(testTypeElement.asType(), (String) null).isEmpty()); assertTrue(getAllAnnotations((Element) null, Service.class).isEmpty()); assertTrue(getAllAnnotations((TypeMirror) null, Service.class.getTypeName()).isEmpty()); @@ -169,21 +171,21 @@ public void testGetAllAnnotations() { @Test public void testFindAnnotation() { - assertEquals("org.springframework.stereotype.Service", findAnnotation(testType, Service.class).getAnnotationType().toString()); - assertEquals("javax.ws.rs.Path", findAnnotation(testType, Path.class).getAnnotationType().toString()); - assertEquals("javax.ws.rs.Path", findAnnotation(testType.asType(), Path.class).getAnnotationType().toString()); - assertEquals("javax.ws.rs.Path", findAnnotation(testType.asType(), Path.class.getTypeName()).getAnnotationType().toString()); - assertNull(findAnnotation(testType, Override.class)); + assertEquals("org.springframework.stereotype.Service", findAnnotation(testTypeElement, Service.class).getAnnotationType().toString()); + assertEquals("javax.ws.rs.Path", findAnnotation(testTypeElement, Path.class).getAnnotationType().toString()); + assertEquals("javax.ws.rs.Path", findAnnotation(testTypeElement.asType(), Path.class).getAnnotationType().toString()); + assertEquals("javax.ws.rs.Path", findAnnotation(testTypeElement.asType(), Path.class.getTypeName()).getAnnotationType().toString()); + assertNull(findAnnotation(testTypeElement, Override.class)); assertNull(findAnnotation((Element) null, (Class) null)); assertNull(findAnnotation((Element) null, (String) null)); assertNull(findAnnotation((TypeMirror) null, (Class) null)); assertNull(findAnnotation((TypeMirror) null, (String) null)); - assertNull(findAnnotation(testType, (Class) null)); - assertNull(findAnnotation(testType, (String) null)); - assertNull(findAnnotation(testType.asType(), (Class) null)); - assertNull(findAnnotation(testType.asType(), (String) null)); + assertNull(findAnnotation(testTypeElement, (Class) null)); + assertNull(findAnnotation(testTypeElement, (String) null)); + assertNull(findAnnotation(testTypeElement.asType(), (Class) null)); + assertNull(findAnnotation(testTypeElement.asType(), (String) null)); } @Test @@ -195,19 +197,23 @@ public void testFindMetaAnnotation() { @Test public void testGetAttribute() { - assertEquals("testService", getAttribute(findAnnotation(testType, Service.class), "value")); - assertEquals("testService", getAttribute(findAnnotation(testType, Service.class).getElementValues(), "value")); - assertEquals("/echo", getAttribute(findAnnotation(testType, Path.class), "value")); - - assertNull(getAttribute(findAnnotation(testType, Path.class), null)); - assertNull(getAttribute(findAnnotation(testType, (Class) null), null)); - -// ExecutableElement method = findMethod(getType(SpringRestService.class), "param", String.class); -// -// AnnotationMirror annotation = findAnnotation(method, GetMapping.class); -// -// assertArrayEquals(new String[]{"/param"}, (String[]) getAttribute(annotation, "value")); -// assertNull(getAttribute(annotation, "path")); + assertEquals("testService", getAttribute(findAnnotation(testTypeElement, Service.class), "value")); + assertEquals("testService", getAttribute(findAnnotation(testTypeElement, Service.class).getElementValues(), "value")); + assertEquals("/echo", getAttribute(findAnnotation(testTypeElement, Path.class), "value")); + + assertNull(getAttribute(findAnnotation(testTypeElement, Path.class), null)); + assertNull(getAttribute(findAnnotation(testTypeElement, (Class) null), null)); + + ExecutableElement echoMethod = findMethod(testTypeElement, "echo", String.class); + AnnotationMirror cacheableAnnotation = findAnnotation(echoMethod, Cacheable.class); + String[] cacheNames = getAttribute(cacheableAnnotation, "cacheNames"); + assertArrayEquals(ofArray("cache-1", "cache-2"), cacheNames); + + DeclaredType cacheableAnnotationType = cacheableAnnotation.getAnnotationType(); + AnnotationMirror targetAnnotation = findAnnotation(cacheableAnnotationType, Target.class); + ElementType[] elementTypes = getAttribute(targetAnnotation, "value"); + assertArrayEquals(ofArray(TYPE, METHOD), elementTypes); + } @Test @@ -218,38 +224,38 @@ public void testGetValue() { @Test public void testIsAnnotationPresent() { - assertTrue(isAnnotationPresent(testType, "org.springframework.stereotype.Service")); - assertTrue(isAnnotationPresent(testType, "javax.xml.ws.ServiceMode")); - assertTrue(isAnnotationPresent(testType, "javax.ws.rs.Path")); + assertTrue(isAnnotationPresent(testTypeElement, "org.springframework.stereotype.Service")); + assertTrue(isAnnotationPresent(testTypeElement, "javax.xml.ws.ServiceMode")); + assertTrue(isAnnotationPresent(testTypeElement, "javax.ws.rs.Path")); } private void asserGetAnnotation(Class annotationClass) { - AnnotationMirror serviceAnnotation = getAnnotation(testType, annotationClass); + AnnotationMirror serviceAnnotation = getAnnotation(testTypeElement, annotationClass); assertEquals(annotationClass.getName(), serviceAnnotation.getAnnotationType().toString()); } private void asserGetAnnotation(String annotationClassName) { - AnnotationMirror serviceAnnotation = getAnnotation(testType, annotationClassName); + AnnotationMirror serviceAnnotation = getAnnotation(testTypeElement, annotationClassName); assertEquals(annotationClassName, serviceAnnotation.getAnnotationType().toString()); } private void assertGetAnnotations(Class annotationType) { - List annotations = getAnnotations(testType, annotationType); + List annotations = getAnnotations(testTypeElement, annotationType); assertEquals(1, annotations.size()); assertEquals(annotationType.getName(), annotations.get(0).getAnnotationType().toString()); - annotations = getAnnotations(testType.asType(), annotationType); + annotations = getAnnotations(testTypeElement.asType(), annotationType); assertEquals(1, annotations.size()); assertEquals(annotationType.getName(), annotations.get(0).getAnnotationType().toString()); } private void assertGetAnnotations(String annotationClassName) { - List annotations = getAnnotations(testType, annotationClassName); + List annotations = getAnnotations(testTypeElement, annotationClassName); assertEquals(1, annotations.size()); assertEquals(annotationClassName, annotations.get(0).getAnnotationType().toString()); - annotations = getAnnotations(testType.asType(), annotationClassName); + annotations = getAnnotations(testTypeElement.asType(), annotationClassName); assertEquals(1, annotations.size()); assertEquals(annotationClassName, annotations.get(0).getAnnotationType().toString()); } diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/ExecutableElementComparatorTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/ExecutableElementComparatorTest.java new file mode 100644 index 000000000..a9e734a3b --- /dev/null +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/ExecutableElementComparatorTest.java @@ -0,0 +1,54 @@ +package io.microsphere.annotation.processor.util; + +import io.microsphere.annotation.processor.AbstractAnnotationProcessingTest; +import io.microsphere.annotation.processor.model.Model; +import org.junit.jupiter.api.Test; + +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.TypeElement; +import java.util.Set; + +import static io.microsphere.annotation.processor.util.ExecutableElementComparator.INSTANCE; +import static io.microsphere.annotation.processor.util.MethodUtils.findMethod; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link ExecutableElementComparator} Test + * + * @author Mercy + * @see ExecutableElementComparator + * @since 1.0.0 + */ +public class ExecutableElementComparatorTest extends AbstractAnnotationProcessingTest { + + private final ExecutableElementComparator comparator = INSTANCE; + + @Override + protected void addCompiledClasses(Set> compiledClasses) { + compiledClasses.add(Model.class); + } + + @Test + public void testCompare() { + TypeElement type = getTypeElement(Model.class); + // Test methods from java.lang.Object + // Object#toString() + String toStringMethodName = "toString"; + ExecutableElement toStringMethod = findMethod(type.asType(), toStringMethodName); + + String hashCodeMethodName = "hashCode"; + ExecutableElement hashCodeMethod = findMethod(type.asType(), hashCodeMethodName); + assertEquals(0, comparator.compare(toStringMethod, toStringMethod)); + assertEquals(0, comparator.compare(hashCodeMethod, hashCodeMethod)); + assertEquals(toStringMethodName.compareTo(hashCodeMethodName), comparator.compare(toStringMethod, hashCodeMethod)); + + // Object#equals + assertEquals(0, comparator.compare(findMethod(getTypeMirror(getClass()), "equals", Object.class), + findMethod(getTypeMirror(Object.class), "equals", Object.class))); + } + + @Override + public boolean equals(Object object) { + return super.equals(object); + } +} \ No newline at end of file diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java index 472cf033d..f9b9f6e6e 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/FieldUtilsTest.java @@ -17,7 +17,6 @@ package io.microsphere.annotation.processor.util; import io.microsphere.annotation.processor.AbstractAnnotationProcessingTest; -import io.microsphere.annotation.processor.TestServiceImpl; import io.microsphere.annotation.processor.model.Color; import io.microsphere.annotation.processor.model.Model; import org.junit.jupiter.api.Test; @@ -60,13 +59,6 @@ */ public class FieldUtilsTest extends AbstractAnnotationProcessingTest { - private TypeElement testType; - - @Override - protected void beforeTest() { - testType = getTypeElement(TestServiceImpl.class); - } - @Test public void testGetDeclaredFields() { TypeElement type = getTypeElement(Model.class); diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MemberUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MemberUtilsTest.java index c35be148a..27df17e95 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MemberUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MemberUtilsTest.java @@ -17,27 +17,37 @@ package io.microsphere.annotation.processor.util; import io.microsphere.annotation.processor.AbstractAnnotationProcessingTest; -import io.microsphere.annotation.processor.TestServiceImpl; import io.microsphere.annotation.processor.model.Model; import org.junit.jupiter.api.Test; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; import java.util.List; +import static io.microsphere.annotation.processor.util.MemberUtils.filterMembers; +import static io.microsphere.annotation.processor.util.MemberUtils.findAllDeclaredMembers; +import static io.microsphere.annotation.processor.util.MemberUtils.findDeclaredMembers; import static io.microsphere.annotation.processor.util.MemberUtils.getAllDeclaredMembers; import static io.microsphere.annotation.processor.util.MemberUtils.getDeclaredMembers; import static io.microsphere.annotation.processor.util.MemberUtils.hasModifiers; import static io.microsphere.annotation.processor.util.MemberUtils.isPublicNonStatic; +import static io.microsphere.annotation.processor.util.MemberUtils.matchParameterTypeNames; import static io.microsphere.annotation.processor.util.MemberUtils.matchParameterTypes; +import static io.microsphere.annotation.processor.util.MemberUtils.matchesElementKind; import static io.microsphere.annotation.processor.util.MethodUtils.findMethod; +import static io.microsphere.collection.ListUtils.ofList; +import static io.microsphere.lang.function.Predicates.alwaysFalse; +import static io.microsphere.lang.function.Predicates.alwaysTrue; +import static java.util.Collections.emptyList; import static javax.lang.model.element.Modifier.PRIVATE; import static javax.lang.model.util.ElementFilter.fieldsIn; import static javax.lang.model.util.ElementFilter.methodsIn; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -48,31 +58,157 @@ */ public class MemberUtilsTest extends AbstractAnnotationProcessingTest { - private TypeElement testType; + private ExecutableElement echoMethod; @Override protected void beforeTest() { - testType = getTypeElement(TestServiceImpl.class); + super.beforeTest(); + this.echoMethod = findMethod(testTypeElement, "echo", "java.lang.String"); + } + + @Test + public void testMatchesElementKind() { + assertTrue(matchesElementKind(echoMethod, ElementKind.METHOD)); + assertFalse(matchesElementKind(echoMethod, ElementKind.FIELD)); + } + + @Test + public void testMatchesElementKindOnNull() { + assertFalse(matchesElementKind(null, ElementKind.FIELD)); + assertFalse(matchesElementKind(echoMethod, null)); } @Test public void testIsPublicNonStatic() { assertFalse(isPublicNonStatic(null)); - methodsIn(getDeclaredMembers(testType.asType())).forEach(method -> assertTrue(isPublicNonStatic(method))); + methodsIn(getDeclaredMembers(testTypeElement.asType())).forEach(method -> assertTrue(isPublicNonStatic(method))); } @Test public void testHasModifiers() { assertFalse(hasModifiers(null)); - List members = getAllDeclaredMembers(testType.asType()); + List members = getAllDeclaredMembers(testTypeElement.asType()); List fields = fieldsIn(members); assertTrue(hasModifiers(fields.get(0), PRIVATE)); } @Test - public void testDeclaredMembers() { + public void testGetDeclaredMembers() { + assertGetDeclaredMembersOfModel(); + } + + @Test + public void testGetDeclaredMembersOnNul() { + assertSame(emptyList(), getDeclaredMembers(NULL_TYPE_ELEMENT)); + assertSame(emptyList(), getDeclaredMembers(NULL_TYPE_MIRROR)); + } + + @Test + public void testGetAllDeclaredMembers() { + assertGetAllDeclaredMembersOfModel(); + } + + @Test + public void testGetAllDeclaredMembersOnNul() { + assertSame(emptyList(), getAllDeclaredMembers(NULL_TYPE_ELEMENT)); + assertSame(emptyList(), getAllDeclaredMembers(NULL_TYPE_MIRROR)); + } + + @Test + public void testFindDeclaredMembers() { + assertFindDeclaredMembersOfModel(); + } + + @Test + public void testFindDeclaredMembersOnNul() { + assertSame(emptyList(), findDeclaredMembers(NULL_TYPE_ELEMENT, alwaysTrue())); + assertSame(emptyList(), findDeclaredMembers(NULL_TYPE_ELEMENT, alwaysFalse())); + assertSame(emptyList(), findDeclaredMembers(NULL_TYPE_MIRROR, alwaysTrue())); + assertSame(emptyList(), findDeclaredMembers(NULL_TYPE_MIRROR, alwaysFalse())); + } + + @Test + public void testFindAllDeclaredMembers() { + assertFindAllDeclaredMembersOfModel(); + } + + @Test + public void testFindAllDeclaredMembersOnNul() { + assertSame(emptyList(), findAllDeclaredMembers(NULL_TYPE_ELEMENT, alwaysTrue())); + assertSame(emptyList(), findAllDeclaredMembers(NULL_TYPE_ELEMENT, alwaysFalse())); + assertSame(emptyList(), findAllDeclaredMembers(NULL_TYPE_MIRROR, alwaysTrue())); + assertSame(emptyList(), findAllDeclaredMembers(NULL_TYPE_MIRROR, alwaysFalse())); + } + + @Test + public void testFilterMembers() { + assertSame(emptyList(), filterMembers(ofList(testTypeElement), alwaysFalse())); + + } + + @Test + public void testFilterMembersOnNull() { + assertSame(emptyList(), filterMembers(null, alwaysTrue())); + List methods = ofList(echoMethod); + assertSame(methods, filterMembers(methods, null)); + } + + @Test + public void testFilterMembersOnEmpty() { + assertSame(emptyList(), filterMembers(emptyList(), alwaysTrue())); + List methods = ofList(echoMethod); + assertSame(methods, filterMembers(methods)); + } + + @Test + public void testMatchParameterTypes() { + assertTrue(matchParameterTypes(echoMethod.getParameters(), String.class)); + assertFalse(matchParameterTypes(echoMethod.getParameters(), Object.class)); + } + + @Test + public void testMatchParameterTypesOnNull() { + assertFalse(matchParameterTypes(null, String.class)); + assertFalse(matchParameterTypes(emptyList(), null)); + } + + @Test + public void testMatchParameterTypeNames() { + assertTrue(matchParameterTypeNames(echoMethod.getParameters(), "java.lang.String")); + assertFalse(matchParameterTypeNames(echoMethod.getParameters(), "java.lang.Object")); + } + + @Test + public void testMatchParameterTypeNamesOnNull() { + assertFalse(matchParameterTypeNames(null, "java.lang.String")); + assertFalse(matchParameterTypeNames(emptyList(), null)); + } + + private void assertFindDeclaredMembersOfModel() { TypeElement type = getTypeElement(Model.class); - List members = getDeclaredMembers(type.asType()); + assertGetDeclaredMembersOfModel(findDeclaredMembers(type, alwaysTrue(), alwaysTrue())); + assertGetDeclaredMembersOfModel(findDeclaredMembers(type.asType(), alwaysTrue())); + + assertSame(emptyList(), findDeclaredMembers(type, alwaysFalse())); + assertSame(emptyList(), findDeclaredMembers(type.asType(), alwaysFalse())); + } + + private void assertFindAllDeclaredMembersOfModel() { + TypeElement type = getTypeElement(Model.class); + assertGetAllDeclaredMembersOfModel(findAllDeclaredMembers(type, alwaysTrue(), alwaysTrue())); + assertGetAllDeclaredMembersOfModel(findAllDeclaredMembers(type.asType(), alwaysTrue())); + + assertSame(emptyList(), findAllDeclaredMembers(type, alwaysFalse())); + assertSame(emptyList(), findAllDeclaredMembers(type.asType(), alwaysFalse())); + } + + private void assertGetDeclaredMembersOfModel() { + TypeElement type = getTypeElement(Model.class); + assertGetDeclaredMembersOfModel(getDeclaredMembers(type)); + assertGetDeclaredMembersOfModel(getDeclaredMembers(type.asType())); + } + + private void assertGetDeclaredMembersOfModel(List members) { List fields = fieldsIn(members); assertEquals(19, members.size()); assertEquals(6, fields.size()); @@ -82,9 +218,16 @@ public void testDeclaredMembers() { assertEquals("str", fields.get(3).getSimpleName().toString()); assertEquals("bi", fields.get(4).getSimpleName().toString()); assertEquals("bd", fields.get(5).getSimpleName().toString()); + } - members = getAllDeclaredMembers(type.asType()); - fields = fieldsIn(members); + private void assertGetAllDeclaredMembersOfModel() { + TypeElement type = getTypeElement(Model.class); + assertGetAllDeclaredMembersOfModel(getAllDeclaredMembers(type)); + assertGetAllDeclaredMembersOfModel(getAllDeclaredMembers(type.asType())); + } + + private void assertGetAllDeclaredMembersOfModel(List members) { + List fields = fieldsIn(members); assertEquals(11, fields.size()); assertEquals("f", fields.get(0).getSimpleName().toString()); assertEquals("d", fields.get(1).getSimpleName().toString()); @@ -98,11 +241,4 @@ public void testDeclaredMembers() { assertEquals("l", fields.get(9).getSimpleName().toString()); assertEquals("z", fields.get(10).getSimpleName().toString()); } - - @Test - public void testMatchParameterTypes() { - ExecutableElement method = findMethod(testType, "echo", "java.lang.String"); - assertTrue(matchParameterTypes(method.getParameters(), "java.lang.String")); - assertFalse(matchParameterTypes(method.getParameters(), "java.lang.Object")); - } } diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java index 12199852e..159d765d5 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java @@ -18,27 +18,47 @@ import io.microsphere.annotation.processor.AbstractAnnotationProcessingTest; import io.microsphere.annotation.processor.TestService; -import io.microsphere.annotation.processor.TestServiceImpl; import io.microsphere.annotation.processor.model.Model; +import io.microsphere.constants.Constants; +import io.microsphere.constants.PropertyConstants; import org.junit.jupiter.api.Test; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; import javax.lang.model.type.TypeMirror; +import java.io.Serializable; +import java.lang.reflect.Type; import java.util.List; +import java.util.Set; +import static io.microsphere.annotation.processor.util.MethodUtils.filterMethods; import static io.microsphere.annotation.processor.util.MethodUtils.findAllDeclaredMethods; +import static io.microsphere.annotation.processor.util.MethodUtils.findDeclaredMethods; import static io.microsphere.annotation.processor.util.MethodUtils.findMethod; import static io.microsphere.annotation.processor.util.MethodUtils.findPublicNonStaticMethods; import static io.microsphere.annotation.processor.util.MethodUtils.getAllDeclaredMethods; import static io.microsphere.annotation.processor.util.MethodUtils.getDeclaredMethods; +import static io.microsphere.annotation.processor.util.MethodUtils.getEnclosingElement; import static io.microsphere.annotation.processor.util.MethodUtils.getMethodName; -import static io.microsphere.annotation.processor.util.MethodUtils.getMethodParameterTypes; +import static io.microsphere.annotation.processor.util.MethodUtils.getMethodParameterTypeMirrors; +import static io.microsphere.annotation.processor.util.MethodUtils.getMethodParameterTypeNames; import static io.microsphere.annotation.processor.util.MethodUtils.getOverrideMethod; -import static io.microsphere.annotation.processor.util.MethodUtils.getReturnType; +import static io.microsphere.annotation.processor.util.MethodUtils.getReturnTypeName; +import static io.microsphere.annotation.processor.util.MethodUtils.isMethod; +import static io.microsphere.annotation.processor.util.MethodUtils.isPublicNonStaticMethod; +import static io.microsphere.annotation.processor.util.MethodUtils.matches; +import static io.microsphere.collection.Lists.ofList; +import static io.microsphere.lang.function.Predicates.alwaysFalse; +import static io.microsphere.lang.function.Predicates.alwaysTrue; +import static io.microsphere.reflect.TypeUtils.getTypeNames; +import static io.microsphere.util.ArrayUtils.EMPTY_STRING_ARRAY; +import static io.microsphere.util.ArrayUtils.ofArray; +import static java.util.Collections.emptyList; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -49,11 +69,22 @@ */ public class MethodUtilsTest extends AbstractAnnotationProcessingTest { - private TypeElement testType; + private List objectMethods; + + private int objectMethodsSize; + + @Override + protected void addCompiledClasses(Set> compiledClasses) { + compiledClasses.add(PropertyConstants.class); + } @Override protected void beforeTest() { - testType = getTypeElement(TestServiceImpl.class); + super.beforeTest(); + TypeElement type = getTypeElement(Object.class); + List methods = getDeclaredMethods(type); + this.objectMethods = methods; + this.objectMethodsSize = methods.size(); } @Test @@ -62,130 +93,354 @@ public void testDeclaredMethods() { List methods = getDeclaredMethods(type); assertEquals(12, methods.size()); - methods = getAllDeclaredMethods(type); - assertTrue(methods.size() >= 33); + methods = getDeclaredMethods(type.asType()); + assertEquals(12, methods.size()); + } - assertTrue(getAllDeclaredMethods((TypeElement) null).isEmpty()); - assertTrue(getAllDeclaredMethods((TypeMirror) null).isEmpty()); + @Test + public void testDeclaredMethodsOnNull() { + assertTrue(getDeclaredMethods(NULL_TYPE_ELEMENT).isEmpty()); + assertTrue(getDeclaredMethods(NULL_TYPE_MIRROR).isEmpty()); } - private List doFindAllDeclaredMethods() { - return findAllDeclaredMethods(testType, Object.class); + @Test + public void testGetAllDeclaredMethods() { + TypeElement type = getTypeElement(Model.class); + List methods = getAllDeclaredMethods(type); + assertEquals(objectMethodsSize + 22, methods.size()); + + methods = getAllDeclaredMethods(type.asType()); + assertEquals(objectMethodsSize + 22, methods.size()); + } + + @Test + public void testGetAllDeclaredMethodsOnNull() { + assertTrue(getAllDeclaredMethods(NULL_TYPE_ELEMENT).isEmpty()); + assertTrue(getAllDeclaredMethods(NULL_TYPE_MIRROR).isEmpty()); + } + + @Test + public void testFindDeclaredMethods() { + List methods = findDeclaredMethods(testTypeElement, alwaysTrue()); + assertEquals(2, methods.size()); + + methods = findDeclaredMethods(testTypeMirror, alwaysTrue()); + assertEquals(2, methods.size()); + + methods = findDeclaredMethods(testTypeElement, alwaysFalse()); + assertSame(emptyList(), methods); + + methods = findDeclaredMethods(testTypeMirror, alwaysFalse()); + assertSame(emptyList(), methods); + } + + @Test + public void testFindDeclaredMethodsOnNoMemberType() { + TypeElement typeElement = getTypeElement(Serializable.class); + List methods = findDeclaredMethods(typeElement, alwaysTrue()); + assertSame(emptyList(), methods); + } + + @Test + public void testFindDeclaredMethodsOnNoMethodType() { + TypeElement typeElement = getTypeElement(PropertyConstants.class); + List methods = findDeclaredMethods(typeElement, alwaysTrue()); + assertSame(emptyList(), methods); } @Test public void testFindAllDeclaredMethods() { - List methods = doFindAllDeclaredMethods(); + List methods = findAllDeclaredMethods(testTypeElement, alwaysTrue()); + assertEquals(objectMethodsSize + 14, methods.size()); + + methods = findAllDeclaredMethods(testTypeMirror, alwaysTrue()); + assertEquals(objectMethodsSize + 14, methods.size()); + + methods = findAllDeclaredMethods(testTypeElement, alwaysFalse()); + assertSame(emptyList(), methods); + + methods = findAllDeclaredMethods(testTypeMirror, alwaysFalse()); + assertSame(emptyList(), methods); + } + + @Test + public void testFindAllDeclaredMethodsOnNoMemberType() { + TypeElement typeElement = getTypeElement(Serializable.class); + List methods = findAllDeclaredMethods(typeElement, alwaysTrue()); + assertSame(emptyList(), methods); + } + + @Test + public void testFindAllDeclaredMethodsOnNoMethodType() { + TypeElement typeElement = getTypeElement(Constants.class); + List methods = findAllDeclaredMethods(typeElement, alwaysTrue()); + assertSame(emptyList(), methods); + } + + @Test + public void testFindAllDeclaredMethodsOnNull() { + assertSame(emptyList(), findAllDeclaredMethods(NULL_TYPE_ELEMENT, alwaysTrue())); + assertSame(emptyList(), findAllDeclaredMethods(NULL_TYPE_ELEMENT, alwaysFalse())); + assertSame(emptyList(), findAllDeclaredMethods(NULL_TYPE_MIRROR, alwaysTrue())); + assertSame(emptyList(), findAllDeclaredMethods(NULL_TYPE_MIRROR, alwaysFalse())); + } + + @Test + public void testFindAllDeclaredMethodsWithExcludedTypes() { + List methods = findAllDeclaredMethodsWithoutObjectType(); assertEquals(14, methods.size()); } + @Test + public void testFindAllDeclaredMethodsWithExcludedTypesOnNull() { + assertSame(emptyList(), findAllDeclaredMethods(NULL_TYPE_ELEMENT, Object.class)); + assertSame(emptyList(), findAllDeclaredMethods(NULL_TYPE_MIRROR, Object.class)); + } + @Test public void testFindPublicNonStaticMethods() { - List methods = findPublicNonStaticMethods(testType, Object.class); + List methods = findPublicNonStaticMethods(testTypeElement, Object.class); assertEquals(14, methods.size()); - methods = findPublicNonStaticMethods(testType.asType(), Object.class); + methods = findPublicNonStaticMethods(testTypeElement.asType(), Object.class); assertEquals(14, methods.size()); } + @Test + public void testFindPublicNonStaticMethodsOnNull() { + assertSame(emptyList(), findPublicNonStaticMethods(NULL_TYPE_ELEMENT, Object.class)); + assertSame(emptyList(), findPublicNonStaticMethods(NULL_TYPE_MIRROR, Object.class)); + } + @Test public void testIsMethod() { - List methods = findPublicNonStaticMethods(testType, Object.class); + List methods = findPublicNonStaticMethods(testTypeElement, Object.class); assertEquals(14, methods.stream().map(MethodUtils::isMethod).count()); } + @Test + public void testIsMethodOnNull() { + assertFalse(isMethod(null)); + } + @Test public void testIsPublicNonStaticMethod() { - List methods = findPublicNonStaticMethods(testType, Object.class); + List methods = findPublicNonStaticMethods(testTypeElement, Object.class); assertEquals(14, methods.stream().map(MethodUtils::isPublicNonStaticMethod).count()); } + @Test + public void testIsPublicNonStaticMethodOnNull() { + assertFalse(isPublicNonStaticMethod(null)); + } + @Test public void testFindMethod() { - TypeElement type = getTypeElement(Model.class); // Test methods from java.lang.Object // Object#toString() - String methodName = "toString"; - ExecutableElement method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + Type type = Model.class; + assertFindMethod(type, "toString"); // Object#hashCode() - methodName = "hashCode"; - method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "hashCode"); // Object#getClass() - methodName = "getClass"; - method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "getClass"); // Object#finalize() - methodName = "finalize"; - method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "finalize"); // Object#clone() - methodName = "clone"; - method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "clone"); // Object#notify() - methodName = "notify"; - method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "notify"); // Object#notifyAll() - methodName = "notifyAll"; - method = findMethod(type.asType(), methodName); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "notifyAll"); // Object#wait(long) - methodName = "wait"; - method = findMethod(type.asType(), methodName, long.class); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "wait", long.class); // Object#wait(long,int) - methodName = "wait"; - method = findMethod(type.asType(), methodName, long.class, int.class); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "wait", long.class, int.class); // Object#equals(Object) - methodName = "equals"; - method = findMethod(type.asType(), methodName, Object.class); - assertEquals(method.getSimpleName().toString(), methodName); + assertFindMethod(type, "equals", Object.class); + } + + @Test + public void testFindMethodOnNull() { + assertNull(findMethod(NULL_TYPE_ELEMENT, "toString")); + assertNull(findMethod(NULL_TYPE_MIRROR, "toString")); + assertNull(findMethod(testTypeElement, null)); + assertNull(findMethod(testTypeMirror, null)); + assertNull(findMethod(testTypeElement, "toString", NULL_TYPE_ARRAY)); + assertNull(findMethod(testTypeMirror, "toString", NULL_STRING_ARRAY)); } @Test public void testGetOverrideMethod() { - List methods = doFindAllDeclaredMethods(); + List methods = findAllDeclaredMethodsWithoutObjectType(); - ExecutableElement overrideMethod = getOverrideMethod(processingEnv, testType, methods.get(0)); + ExecutableElement overrideMethod = getOverrideMethod(processingEnv, testTypeElement, methods.get(0)); assertNull(overrideMethod); ExecutableElement declaringMethod = findMethod(getTypeElement(TestService.class), "echo", "java.lang.String"); - overrideMethod = getOverrideMethod(processingEnv, testType, declaringMethod); + overrideMethod = getOverrideMethod(processingEnv, testTypeElement, declaringMethod); assertEquals(methods.get(0), overrideMethod); } + @Test + public void testFilterMethods() { + + } + + @Test + public void testFilterMethodsOnNull() { + assertSame(emptyList(), filterMethods(null, alwaysTrue())); + assertSame(emptyList(), filterMethods(null, null)); + } + + @Test + public void testFilterMethodsOnEmpty() { + assertSame(emptyList(), filterMethods(emptyList(), alwaysTrue())); + assertSame(emptyList(), filterMethods(emptyList(), null)); + } + + @Test + public void testFilterMethodsOnReturningEmptyList() { + List methods = getDeclaredMethods(testTypeElement); + assertSame(emptyList(), filterMethods(methods, alwaysFalse())); + assertSame(methods, filterMethods(methods)); + } + @Test public void testGetMethodName() { - ExecutableElement method = findMethod(testType, "echo", "java.lang.String"); + ExecutableElement method = findMethod(testTypeElement, "echo", "java.lang.String"); assertEquals("echo", getMethodName(method)); assertNull(getMethodName(null)); } @Test - public void testReturnType() { - ExecutableElement method = findMethod(testType, "echo", "java.lang.String"); - assertEquals("java.lang.String", getReturnType(method)); - assertNull(getReturnType(null)); + public void testGetMethodNameOnNull() { + assertNull(getMethodName(null)); + } + + @Test + public void testReturnTypeName() { + ExecutableElement method = findMethod(testTypeElement, "echo", "java.lang.String"); + assertEquals("java.lang.String", getReturnTypeName(method)); + } + + @Test + public void testReturnTypeNameOnNull() { + assertNull(getReturnTypeName(null)); + } + + @Test + public void testMatchParameterTypeNames() { + String[] parameterTypeNames = ofArray("java.lang.String"); + ExecutableElement method = findMethod(testTypeElement, "echo", parameterTypeNames); + assertArrayEquals(parameterTypeNames, getMethodParameterTypeNames(method)); + } + + @Test + public void testMatchParameterTypeNamesOnNull() { + assertSame(EMPTY_STRING_ARRAY, getMethodParameterTypeNames(null)); } @Test public void testMatchParameterTypes() { - ExecutableElement method = findMethod(testType, "echo", "java.lang.String"); - assertArrayEquals(new String[]{"java.lang.String"}, getMethodParameterTypes(method)); - assertTrue(getMethodParameterTypes(null).length == 0); + ExecutableElement method = findMethod(testTypeElement, "toString"); + assertSame(emptyList(), getMethodParameterTypeMirrors(method)); + + method = findMethod(testTypeElement, "equals", Object.class); + List parameterTypes = getMethodParameterTypeMirrors(method); + assertEquals(ofList(parameterTypes.toArray(EMPTY_TYPE_MIRROR_ARRAY)), parameterTypes); + } + + @Test + public void testMatchParameterTypesOnNull() { + assertSame(emptyList(), getMethodParameterTypeMirrors(null)); + } + + @Test + public void testMatches() { + assertFindMethod(testClass, "echo", String.class); + } + + @Test + public void tstMatchesOnFalse() { + ExecutableElement method = findMethod(testTypeElement, "echo", String.class); + + Type[] parameterTypes = ofArray(String.class, String.class); + String[] parameterTypeNames = getTypeNames(parameterTypes); + assertFalse(matches(method, "echo", parameterTypes)); + assertFalse(matches(method, "echo", parameterTypeNames)); + + parameterTypes = ofArray(Object.class); + parameterTypeNames = getTypeNames(parameterTypes); + assertFalse(matches(method, "echo", parameterTypes)); + assertFalse(matches(method, "echo", parameterTypeNames)); + } + + @Test + public void testMatchesOnNull() { + String methodName = "echo"; + Type[] parameterTypes = ofArray(String.class); + String[] parameterTypeNames = getTypeNames(parameterTypes); + ExecutableElement method = findMethod(testTypeElement, methodName, parameterTypes); + + assertFalse(matches(null, NULL_STRING, parameterTypes)); + assertFalse(matches(method, NULL_STRING, parameterTypes)); + assertFalse(matches(method, methodName, NULL_TYPE_ARRAY)); + + assertFalse(matches(null, NULL_STRING, parameterTypeNames)); + assertFalse(matches(method, NULL_STRING, parameterTypeNames)); + assertFalse(matches(method, methodName, NULL_STRING_ARRAY)); + } + + @Test + public void testGetEnclosingElement() { + String methodName = "echo"; + Type[] parameterTypes = ofArray(String.class); + ExecutableElement method = findMethod(testTypeElement, methodName, parameterTypes); + assertSame(testTypeElement, getEnclosingElement(method)); + } + + @Test + public void testGetEnclosingElementOnNull() { + assertNull(getEnclosingElement(null)); + } + + private void assertFindMethod(Type type, String methodName, Type... parameterTypes) { + TypeElement typeElement = getTypeElement(type); + String[] parameterTypeNames = getTypeNames(parameterTypes); + + ExecutableElement method = findMethod(typeElement, methodName, parameterTypes); + assertMatchesMethod(method, methodName, parameterTypes); + + method = findMethod(typeElement, methodName, parameterTypeNames); + assertMatchesMethod(method, methodName, parameterTypes); + + method = findMethod(typeElement.asType(), methodName, parameterTypes); + assertMatchesMethod(method, methodName, parameterTypes); + + method = findMethod(typeElement.asType(), methodName, parameterTypeNames); + assertMatchesMethod(method, methodName, parameterTypeNames); + } + + private void assertMatchesMethod(ExecutableElement method, String methodName, Type... parameterTypes) { + assertTrue(matches(method, methodName, parameterTypes)); + } + + private void assertMatchesMethod(ExecutableElement method, String methodName, String... parameterTypeNames) { + assertTrue(matches(method, methodName, parameterTypeNames)); + } + + private List findAllDeclaredMethodsWithoutObjectType() { + return findAllDeclaredMethods(testTypeElement, Object.class); } } diff --git a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/TypeUtilsTest.java b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/TypeUtilsTest.java index bf640ada5..064926f12 100644 --- a/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/TypeUtilsTest.java +++ b/microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/TypeUtilsTest.java @@ -29,7 +29,6 @@ import io.microsphere.annotation.processor.model.PrimitiveTypeModel; import org.junit.jupiter.api.Test; -import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import javax.lang.model.element.VariableElement; @@ -40,7 +39,6 @@ import java.lang.reflect.Type; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.Collection; import java.util.Date; import java.util.EventListener; import java.util.List; @@ -115,34 +113,6 @@ */ public class TypeUtilsTest extends AbstractAnnotationProcessingTest { - private static final TypeMirror NULL_TYPE_MIRROR = null; - - private static final TypeMirror[] EMPTY_TYPE_MIRROR_ARRAY = new TypeMirror[0]; - - private static final TypeMirror[] NULL_TYPE_MIRROR_ARRAY = null; - - private static final Collection[] EMPTY_COLLECTION_ARRAY = new Collection[0]; - - private static final Collection NULL_COLLECTION = null; - - private static final Element NULL_ELEMENT = null; - - private static final Element[] EMPTY_ELEMENT_ARRAY = new Element[0]; - - private static final Element[] NULL_ELEMENT_ARRAY = null; - - private static final TypeElement NULL_TYPE_ELEMENT = null; - - private static final Type[] NULL_TYPE_ARRAY = null; - - private static final Type[] EMPTY_TYPE_ARRAY = new Type[0]; - - private static final Type NULL_TYPE = null; - - private static final ProcessingEnvironment NULL_PROCESSING_ENVIRONMENT = null; - - private static final String NULL_STRING = null; - /** * self type */ @@ -213,17 +183,6 @@ public class TypeUtilsTest extends AbstractAnnotationProcessingTest { */ private static final Type[] SELF_TYPE_PLUS_SUPER_CLASS_PLUS_SUPER_INTERFACES = combine(SELF_TYPE, SUPER_TYPES); - - private Class testClass; - - private String testClassName; - - private TypeElement testTypeElement; - - private TypeMirror testTypeMirror; - - private DeclaredType testDeclaredType; - @Override protected void addCompiledClasses(Set> compiledClasses) { compiledClasses.add(ArrayTypeModel.class); @@ -232,15 +191,6 @@ protected void addCompiledClasses(Set> compiledClasses) { compiledClasses.add(MapTypeModel.class); } - @Override - protected void beforeTest() { - this.testClass = SELF_TYPE; - this.testClassName = SELF_TYPE.getName(); - this.testTypeElement = getTypeElement(testClass); - this.testTypeMirror = this.testTypeElement.asType(); - this.testDeclaredType = ofDeclaredType(this.testTypeElement); - } - @Test public void testIsSimpleType() { assertTrue(isSimpleType(getTypeElement(Void.class))); @@ -1591,9 +1541,14 @@ public void testToStringOnCollectionTypes() { assertToStringOnCollectionTypes(); } + @Test + public void testToStringMapTypes() { + assertToStringOnMapTypes(); + } + @Test public void testToStringOnNull() { - // TODO + assertNull(TypeUtils.toString(NULL_TYPE_MIRROR)); } @Test @@ -1776,6 +1731,14 @@ private void assertGetDeclaredTypeOnNullProcessingEnvironment(Type... types) { } } + private void assertToStringOnMapTypes() { + assertToString(getFieldType(MapTypeModel.class, "strings")); + assertToString(getFieldType(MapTypeModel.class, "colors")); + assertToString(getFieldType(MapTypeModel.class, "primitiveTypeModels")); + assertToString(getFieldType(MapTypeModel.class, "models")); + assertToString(getFieldType(MapTypeModel.class, "modelArrays")); + } + private void assertToStringOnCollectionTypes() { assertToString(getFieldType(CollectionTypeModel.class, "strings")); assertToString(getFieldType(CollectionTypeModel.class, "colors"));