diff --git a/README.adoc b/README.adoc index 478e669fa..c7a8a0eae 100644 --- a/README.adoc +++ b/README.adoc @@ -22,6 +22,10 @@ SmallRye GraphQL is an implementation of mvn clean install ---- +Note that some tests perform locale-sensitive assertions. +If you use non-English locale, you need to adjust the command above. +For example: `LANG=C mvn clean install` + === Testing against the unreleased v 2.0-SNAPSHOT of MicroProfile GraphQL (You need to build that version of MicroProfile GraphQL locally first to make the snapshot versions available in your repository) diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/Annotations.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/Annotations.java index 52ee6e35a..d36fe7dc2 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/Annotations.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/Annotations.java @@ -217,12 +217,12 @@ public static Annotations getAnnotationsForArray(org.jboss.jandex.Type typeInCol * @return annotation for this argument */ public static Annotations getAnnotationsForArgument(MethodInfo methodInfo, short pos) { - if (pos >= methodInfo.parameters().size()) { + if (pos >= methodInfo.parametersCount()) { throw new IndexOutOfBoundsException( "Parameter at position " + pos + " not found on method " + methodInfo.name()); } - final org.jboss.jandex.Type parameterType = methodInfo.parameters().get(pos); + final org.jboss.jandex.Type parameterType = methodInfo.parameterType(pos); Map annotationMap = getAnnotations(parameterType); @@ -447,7 +447,7 @@ private static Annotations getAnnotationsForInputField(FieldInfo fieldInfo, Meth annotationsForField.putAll(getTypeUseAnnotations(fieldInfo.type())); } if (methodInfo != null) { - List parameters = methodInfo.parameters(); + List parameters = methodInfo.parameterTypes(); if (!parameters.isEmpty()) { org.jboss.jandex.Type param = parameters.get(ZERO); annotationsForField.putAll(getTypeUseAnnotations(param)); diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/ArgumentCreator.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/ArgumentCreator.java index 2d2b9e0b9..4fd2b6b9a 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/ArgumentCreator.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/ArgumentCreator.java @@ -45,11 +45,11 @@ public ArgumentCreator(ReferenceCreator referenceCreator) { * @return an Argument */ public Optional createArgument(Operation operation, MethodInfo methodInfo, short position) { - if (position >= methodInfo.parameters().size()) { + if (position >= methodInfo.parametersCount()) { throw new SchemaBuilderException( "Can not create argument for parameter [" + position + "] " + "on method [" + methodInfo.declaringClass().name() + "#" + methodInfo.name() + "]: " - + "method has only " + methodInfo.parameters().size() + " parameters"); + + "method has only " + methodInfo.parametersCount() + " parameters"); } Annotations annotationsForThisArgument = Annotations.getAnnotationsForArgument(methodInfo, position); @@ -59,7 +59,7 @@ public Optional createArgument(Operation operation, MethodInfo methodI } // Argument Type - Type argumentType = methodInfo.parameters().get(position); + Type argumentType = methodInfo.parameterType(position); // Name String defaultName = methodInfo.parameterName(position); diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/FieldCreator.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/FieldCreator.java index 265fa06b6..9757bc918 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/FieldCreator.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/FieldCreator.java @@ -114,15 +114,15 @@ public Optional createFieldForParameter(MethodInfo method, short position String name = getFieldName(Direction.IN, annotationsForPojo, method.parameterName(position)); // Field Type - Type fieldType = getFieldType(fieldInfo, method.parameters().get(position)); + Type fieldType = getFieldType(fieldInfo, method.parameterType(position)); Reference reference = referenceCreator.createReferenceForPojoField(fieldType, - method.parameters().get(position), annotationsForPojo, Direction.IN, parentObjectReference); + method.parameterType(position), annotationsForPojo, Direction.IN, parentObjectReference); String fieldName = fieldInfo != null ? fieldInfo.name() : null; Field field = new Field(null, fieldName, name, reference); addDirectivesForBeanValidationConstraints(annotationsForPojo, field, parentObjectReference); - populateField(Direction.IN, field, fieldType, method.parameters().get(position), annotationsForPojo); + populateField(Direction.IN, field, fieldType, method.parameterType(position), annotationsForPojo); return Optional.of(field); @@ -249,7 +249,7 @@ private static void validateFieldType(Direction direction, MethodInfo methodInfo private static Type getMethodType(MethodInfo method, Direction direction) { if (direction.equals(Direction.IN)) { - return method.parameters().get(0); + return method.parameterType(0); } return getReturnType(method); } diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/OperationCreator.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/OperationCreator.java index 798238ed1..dc733ac33 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/OperationCreator.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/OperationCreator.java @@ -78,7 +78,7 @@ public Operation createOperation(MethodInfo methodInfo, OperationType operationT } // Arguments - List parameters = methodInfo.parameters(); + List parameters = methodInfo.parameterTypes(); for (short i = 0; i < parameters.size(); i++) { Optional maybeArgument = argumentCreator.createArgument(operation, methodInfo, i); maybeArgument.ifPresent(operation::addArgument); diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/type/InputTypeCreator.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/type/InputTypeCreator.java index 8baefff57..7a3cd82c9 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/type/InputTypeCreator.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/creator/type/InputTypeCreator.java @@ -102,7 +102,7 @@ public MethodInfo findCreator(ClassInfo classInfo) { for (final MethodInfo constructor : classInfo.constructors()) { if (!Modifier.isPublic(constructor.flags())) continue; - if (constructor.parameters().isEmpty()) { + if (constructor.parameterTypes().isEmpty()) { return constructor; } if (constructor.hasAnnotation(Annotations.JSONB_CREATOR) @@ -143,7 +143,7 @@ private void addFields(InputType inputType, ClassInfo classInfo, Reference refer } //Parameters of JsonbCreator - for (short i = 0; i < creator.parameters().size(); i++) { + for (short i = 0; i < creator.parametersCount(); i++) { String fieldName = creator.parameterName(i); FieldInfo fieldInfo = allFields.remove(fieldName); final Optional maybeField = fieldCreator.createFieldForParameter(creator, i, fieldInfo, reference); diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/GroupHelper.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/GroupHelper.java index 1d6ecf897..402fe7f96 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/GroupHelper.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/GroupHelper.java @@ -64,8 +64,8 @@ private static Optional getName(AnnotationInstance graphQLApiAnnotation) */ private static Optional getDescription(AnnotationInstance graphQLApiAnnotation) { ClassInfo apiClass = graphQLApiAnnotation.target().asClass(); - if (apiClass.annotations().containsKey(Annotations.DESCRIPTION)) { - List descriptionAnnotations = apiClass.annotations().get(Annotations.DESCRIPTION); + if (apiClass.annotationsMap().containsKey(Annotations.DESCRIPTION)) { + List descriptionAnnotations = apiClass.annotationsMap().get(Annotations.DESCRIPTION); if (descriptionAnnotations != null && !descriptionAnnotations.isEmpty()) { AnnotationValue value = descriptionAnnotations.get(0).value(); if (value != null && value.asString() != null && !value.asString().isEmpty()) { diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/MethodHelper.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/MethodHelper.java index 3b0311b60..0d463479e 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/MethodHelper.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/MethodHelper.java @@ -80,7 +80,7 @@ public static boolean isPropertyMethod(Direction direction, MethodInfo method) { */ private static boolean isSetter(MethodInfo method) { return method.returnType().kind() == Type.Kind.VOID - && method.parameters().size() == 1 + && method.parametersCount() == 1 && isSetterName(method.name()); } @@ -102,7 +102,7 @@ private static boolean isSetter(MethodInfo method) { */ private static boolean isPropertyAccessor(MethodInfo method) { return method.returnType().kind() != Type.Kind.VOID - && method.parameters().isEmpty() + && method.parameterTypes().isEmpty() && (method.hasAnnotation(Annotations.QUERY) || isGetterName(method.name())); } diff --git a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/SourceOperationHelper.java b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/SourceOperationHelper.java index 59d87d2a4..0cbe9f761 100644 --- a/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/SourceOperationHelper.java +++ b/common/schema-builder/src/main/java/io/smallrye/graphql/schema/helper/SourceOperationHelper.java @@ -54,7 +54,7 @@ private Map> scanAllSourceAnnotations(boolean if (target.kind().equals(AnnotationTarget.Kind.METHOD_PARAMETER)) { MethodParameterInfo methodParameter = target.asMethodParameter(); short position = methodParameter.position(); - Type returnType = methodParameter.method().parameters().get(position); + Type returnType = methodParameter.method().parameterType(position); if (forReturnType == null || Arrays.asList(forReturnType).contains(returnType.kind())) { DotName name = getName(returnType); sourceFields.computeIfAbsent(name, k -> new ArrayList<>()).add(methodParameter); diff --git a/docs/power-annotations.md b/docs/power-annotations.md deleted file mode 100644 index fee451da8..000000000 --- a/docs/power-annotations.md +++ /dev/null @@ -1,87 +0,0 @@ -Power Annotations -=========== - -Power-Annotations is actually independent of GraphQL. It’s a generic -mechanism for meta annotations. It consists of annotations you can put -on your code (these are meant to become a separate standard) and the -following implementations: - -1. A maven plugin to build a Jandex index file (and resolve all power - annotations). This replaces the `jandex-maven-plugin`. It currently - has fewer options, but as we only want to build what people actually - need, give us a call if you need more! - -2. A classpath scanner to build a Jandex index at runtime (and resolve - all power annotations). - -There’s also a TCK to test, if an implementation adheres to the standard -defined by the annotations. It uses an Utils API, so the TCK can also -verify implementations not using Jandex. This Annotation Utils API may -be convenient for your usage as well, as, e.g., it also resolves -repeated annotations. - -Annotations -=========== - -Stereotypes ------------ - -The simplest use-case for Stereotypes is renaming annotations, e.g. -`@Property` instead of `@JsonbProperty` (assuming your JSON-B -implementation supported Power Annotations). - -``` java -@Retention(RUNTIME) -@Stereotype -@JsonbProperty -public @interface Property {} -``` - -It gets much more interesting, when you add more annotations from other -(supporting) frameworks to your stereotype, e.g. `@XmlAttribute` from -JAX-B. Now you have one annotation instead of two with both having the -same semantics. - -Properly used, stereotypes are shortcuts describing the role the -annotated element has; functionally as well as a documentation. - -This is exactly what -[CDI-Stereotypes](https://jakarta.ee/specifications/cdi/2.0/cdi-spec-2.0.html#stereotypes) -do, but not restricted to CDI, i.e. the annotations used by any -framework that supports Power Annotations can be used with stereotypes. -We have our own `Stereotype` class; but as we don’t want to depend on -CDI and still not exclude CDI, any annotation named `Stereotype` will -work. - -Mixins ------- - -Say you have a class you want to add annotations to, but you can’t; -e.g., because it’s a class from some library or even from the JDK. You -can create your own class (or interface or even annotation) and annotate -it as `@MixinFor` the target class. The annotations you put on your -mixin class will work as if they were on the target class (if your -framework supports Power Annotations). - -This also works for annotations: say we’re developing an application -packed with annotations from JPA, which doesn’t support mixins (yet). -The application also uses a library that supports mixins but doesn’t -know about JPA, e.g. libraries like SmallRye GraphQL that use Jandex, -and you build the index with the `power-jandex-maven-plugin`. We want -all JPA `@Id` annotations to be recognized as synonyms for GraphQL `@Id` -annotations. We could create a simple mixin for the JPA annotation: - -``` java -@MixinFor(javax.persistence.Id.class) -@org.eclipse.microprofile.graphql.Id -public class PersistenceIdMixin {} -``` - -Voilà! MP GraphQL work as if all JPA `@Id` annotations were its own. - -> **Note** -> -> Mixins are a very powerful kind of magic: use them with caution and -> only when strictly necessary. Otherwise, the readers of your code will -> have a hard time to find out why something behaves as if an annotation -> was there, but it’s clearly not. If you can, use Stereotypes instead. diff --git a/mkdocs.yml b/mkdocs.yml index 9f71d7089..72741412d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -8,8 +8,6 @@ nav: - Customizing JSON deserializers: 'custom-json-deserializers.md' - Directives: 'directives.md' - Custom error extensions: 'custom-error-extensions.md' -# - Power annotations: # Power annotations are unused right now -# - Power annotations: 'power-annotations.md' - Typesafe client: - Basic usage: 'typesafe-client-usage.md' - Reactive: 'typesafe-client-reactive-types.md' diff --git a/pom.xml b/pom.xml index 8e2a5f3bc..ae4c121ea 100644 --- a/pom.xml +++ b/pom.xml @@ -21,6 +21,7 @@ 3.0 1.3 + 2.4.3.Final 2.10.0 3.0.4 1.11.0 @@ -81,7 +82,6 @@ server client tools - power-annotations docs @@ -417,13 +417,6 @@ server/integration-tests-jdk16 - - - --add-opens java.base/java.util=ALL-UNNAMED - - true - diff --git a/power-annotations/annotations/pom.xml b/power-annotations/annotations/pom.xml deleted file mode 100644 index 82f29d9b3..000000000 --- a/power-annotations/annotations/pom.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-parent - 1.6.1-SNAPSHOT - - - power-annotations - Power Annotations Annotations - The Annotations resolved by Power Annotations - diff --git a/power-annotations/annotations/src/main/java/com/github/t1/annotations/MixinFor.java b/power-annotations/annotations/src/main/java/com/github/t1/annotations/MixinFor.java deleted file mode 100644 index 24cc3fc05..000000000 --- a/power-annotations/annotations/src/main/java/com/github/t1/annotations/MixinFor.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.github.t1.annotations; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Add annotations to another class that you can't change; if you can change that class, - * use explicit {@link Stereotype}s instead. Using Mixins is very implicit and difficult to trace back; - * it is often better to actually copy the target class, so you can directly add your annotations, - * instead of working with mixins. You have been warned! - * - * If you have a class that you don't control, e.g.: - * - *
- *     public class ImportedClass {
- *         ...
- *     }
- * 
- * - * And you need it to be annotated as @SomeAnnotation. Then you can write a mixin (the name is arbitrary): - * - *
- *     @MixinFor(ImportedClass.class)
- *     @SomeAnnotation
- *     public class ImportedClassMixin {
- *         ...
- *     }
- * 
- * - * After the Power Annotations have been resolved, the target class looks as if it had another annotation: - * - *
- *     @SomeAnnotation
- *     public class ImportedClass {
- *         ...
- *     }
- * 
- */ -@Retention(RUNTIME) -@Target(TYPE) -public @interface MixinFor { - Class value(); -} diff --git a/power-annotations/annotations/src/main/java/com/github/t1/annotations/Stereotype.java b/power-annotations/annotations/src/main/java/com/github/t1/annotations/Stereotype.java deleted file mode 100644 index 4eeb3daf7..000000000 --- a/power-annotations/annotations/src/main/java/com/github/t1/annotations/Stereotype.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.t1.annotations; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Documented; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -/** - * Marks an annotation to be a meta annotation, i.e. the annotations on the stereotype (i.e. the annotation that is - * annotated as Stereotype) are logically copied to all targets (i.e. the classes/fields/methods that are - * annotated with the stereotype). - * - * Power Annotations doesn't depend on CDI, so it handles all classes named Stereotype the same. - * You can use this class if you don't have another stereotype class on your classpath, - * but in JEE/MP applications you should have javax.enterprise.inject.Stereotype. - */ -@Retention(RUNTIME) -@Target(ANNOTATION_TYPE) -@Documented -public @interface Stereotype { -} diff --git a/power-annotations/common/pom.xml b/power-annotations/common/pom.xml deleted file mode 100644 index 087287f42..000000000 --- a/power-annotations/common/pom.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-parent - 1.6.1-SNAPSHOT - - - power-annotations-jandex-common - Power Annotations Jandex Common - Common Jandex specific Power Annotations code used by build plugins and the runtime scanner. - - - - org.jboss - jandex - - - diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/CommonUtils.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/CommonUtils.java deleted file mode 100644 index 45e581f4e..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/CommonUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.github.t1.powerannotations.common; - -import static java.util.stream.Collectors.joining; - -import java.util.Arrays; -import java.util.stream.Stream; - -import org.jboss.jandex.DotName; - -public class CommonUtils { - private CommonUtils() { - } - - public static DotName toDotName(Class type) { - return toDotName(type.getName()); - } - - public static DotName toDotName(String typeName) { - return DotName.createSimple(typeName); - } - - public static String signature(String methodName, String... argTypeNames) { - return methodName + Stream.of(argTypeNames).collect(joining(", ", "(", ")")); - } - - public static T[] with(T[] original, T newInstance) { - T[] copy = Arrays.copyOf(original, original.length + 1); - copy[original.length] = newInstance; - return copy; - } - - public static void replace(T[] array, T original, T replacement) { - for (int i = 0; i < array.length; i++) { - if (array[i] == original) { - array[i] = replacement; - return; - } - } - throw new RuntimeException("original element " + original + " not in array " + Arrays.toString(array)); - } -} diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/Jandex.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/Jandex.java deleted file mode 100644 index 993d39099..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/Jandex.java +++ /dev/null @@ -1,218 +0,0 @@ -package com.github.t1.powerannotations.common; - -import static com.github.t1.powerannotations.common.PowerAnnotations.log; -import static java.lang.reflect.Modifier.PUBLIC; -import static java.util.Arrays.asList; -import static java.util.Collections.emptyMap; -import static org.jboss.jandex.AnnotationValue.createNestedAnnotationValue; -import static org.jboss.jandex.JandexBackdoor.annotations; -import static org.jboss.jandex.JandexBackdoor.classes; -import static org.jboss.jandex.Type.Kind.ARRAY; -import static org.jboss.jandex.Type.Kind.CLASS; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.Index; -import org.jboss.jandex.JandexBackdoor; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.Type; - -public class Jandex { - final Index index; - - private final Map> annotations; - private final Map classes; - - public Jandex(Index index) { - this.index = index; - - this.annotations = annotations(index); - this.classes = classes(index); - } - - List getAnnotationInstances(DotName annotationName) { - return index.getAnnotations(annotationName); - } - - Set allAnnotationNames() { - return annotations.keySet(); - } - - ClassInfo getClassInfo(DotName className) { - ClassInfo classInfo = classes.get(className); - return (classInfo == null) ? mock(className) : classInfo; - } - - @SuppressWarnings("deprecation") - private static org.jboss.jandex.ClassInfo mock(DotName name) { - log.info("create mock for " + name); - return org.jboss.jandex.ClassInfo.create( - name, null, (short) PUBLIC, new DotName[0], emptyMap(), true); - } - - boolean isNotTargetable(DotName annotationName, AnnotationTarget annotationTarget) { - return !isTargetable(annotationName, annotationTarget); - } - - private boolean isTargetable(DotName annotationName, AnnotationTarget annotationTarget) { - AnnotationInstance target = getClassInfo(annotationName).classAnnotation(TARGET); - if (target == null) - return true; - List allowedTypes = asList(target.value().asEnumArray()); - switch (annotationTarget.kind()) { - case CLASS: - return allowedTypes.contains("TYPE"); - case FIELD: - return allowedTypes.contains("FIELD"); - case METHOD: - return allowedTypes.contains("METHOD"); - } - throw new UnsupportedOperationException("unexpected annotation kind " + annotationTarget.kind()); - } - - AnnotationInstance copyAnnotationInstance(AnnotationInstance original, AnnotationTarget annotationTarget) { - AnnotationValue[] values = original.values().toArray(new AnnotationValue[0]); - return AnnotationInstance.create(original.name(), annotationTarget, values); - } - - void addOrSkip(ClassInfo targetClass, AnnotationInstance annotation) { - List annotationInstances = get(annotations(targetClass), annotation.name()); - if (isRepeatable(annotation) || isRepeatedAnnotation(annotation) || indexOfType(annotationInstances, annotation) < 0) - add(annotationInstances, annotation); - } - - boolean addOrReplace(ClassInfo targetClass, AnnotationInstance annotation) { - List annotationInstances = get(annotations(targetClass), annotation.name()); - if (isRepeatable(annotation)) { - add(annotationInstances, annotation); - return false; - } else { - boolean replaced = replace(annotationInstances, annotation); - if (!replaced) - add(annotationInstances, annotation); - return replaced; - } - } - - void addOrSkip(FieldInfo targetField, AnnotationInstance annotation) { - List annotationInstances = get(annotations(targetField.declaringClass()), annotation.name()); - if (isRepeatable(annotation) || indexOfType(annotationInstances, annotation) < 0) { - add(annotationInstances, annotation); - JandexBackdoor.add(targetField, annotation); - } - } - - void addOrReplace(FieldInfo targetField, AnnotationInstance copy) { - boolean replaced = addOrReplace(targetField.declaringClass(), copy); - if (replaced) - JandexBackdoor.replace(targetField, copy); - else - JandexBackdoor.add(targetField, copy); - } - - void addOrReplace(MethodInfo targetMethod, AnnotationInstance copy) { - boolean replaced = addOrReplace(targetMethod.declaringClass(), copy); - if (replaced) - JandexBackdoor.replace(copy, targetMethod); - else - JandexBackdoor.add(targetMethod, copy); - } - - void addOrSkip(MethodInfo targetMethod, AnnotationInstance annotation) { - List annotationInstances = get(annotations(targetMethod.declaringClass()), annotation.name()); - if (isRepeatable(annotation) || indexOfType(annotationInstances, annotation) < 0) { - add(annotationInstances, annotation); - JandexBackdoor.add(targetMethod, annotation); - } - } - - private void add(List existingAnnotations, AnnotationInstance newAnnotation) { - if (isRepeatable(newAnnotation)) { - for (int i = 0; i < existingAnnotations.size(); i++) { - AnnotationInstance existingAnnotation = existingAnnotations.get(i); - if (existingAnnotation.name().equals(newAnnotation.name())) { - existingAnnotations.remove(i); - AnnotationValue values = AnnotationValue.createArrayValue("value", new AnnotationValue[] { - createNestedAnnotationValue("", existingAnnotation), - createNestedAnnotationValue("", newAnnotation) - }); - newAnnotation = AnnotationInstance.create( - repeaterTypeName(newAnnotation.name()), - newAnnotation.target(), - new AnnotationValue[] { values }); - break; - } - } - } - existingAnnotations.add(newAnnotation); - } - - private DotName repeaterTypeName(DotName repeatedType) { - ClassInfo repeatedClass = getClassInfo(repeatedType); - AnnotationInstance repeatableAnnotation = repeatedClass.classAnnotation(REPEATABLE); - return repeatableAnnotation.value().asClass().name(); - } - - public boolean isRepeatedAnnotation(AnnotationInstance annotationInstance) { - ClassInfo annotationType = getClassInfo(annotationInstance.name()); - if (annotationType.methods().size() == 1 && annotationType.method("value") != null) { - Type returnType = annotationType.method("value").returnType(); - if (returnType.kind() == ARRAY && returnType.asArrayType().component().kind() == CLASS) { - ClassInfo returnClassInfo = getClassInfo(returnType.asArrayType().component().name()); - return returnClassInfo != null && isRepeatable(returnClassInfo); - } - } - return false; - } - - private boolean isRepeatable(AnnotationInstance annotationInstance) { - ClassInfo annotationType = getClassInfo(annotationInstance.name()); - return annotationType != null && isRepeatable(annotationType); - } - - private boolean isRepeatable(ClassInfo annotationType) { - return annotationType.classAnnotation(REPEATABLE) != null; - } - - private static boolean replace(List instances, AnnotationInstance newInstance) { - // we can't use `instances.replaceAll()`, because Maven plugins can't run with lambdas and fail with IndexOutOfBounds - int index = indexOfType(instances, newInstance); - if (index < 0) - return false; - instances.set(index, newInstance); - return true; - } - - private static List get(Map> map, K name) { - // we can't use `map.computeIfAbsent()`, because Maven plugins can't run with lambdas and fail with IndexOutOfBounds - if (!map.containsKey(name)) - map.put(name, new ArrayList<>()); - return map.get(name); - } - - private static int indexOfType(List instances, AnnotationInstance annotation) { - for (int i = 0; i < instances.size(); i++) - if (instances.get(i).name().equals(annotation.name()) - // AnnotationInstance subclasses don't override equals/hashCode - && instances.get(i).target().toString().equals(annotation.target().toString())) - return i; - return -1; - } - - static boolean isAnnotationType(ClassInfo classInfo) { - return classInfo.interfaceNames().contains(ANNOTATION); - } - - private static final DotName REPEATABLE = DotName.createSimple("java.lang.annotation.Repeatable"); - private static final DotName ANNOTATION = DotName.createSimple("java.lang.annotation.Annotation"); - private static final DotName TARGET = DotName.createSimple("java.lang.annotation.Target"); -} diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/JandexPrinter.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/JandexPrinter.java deleted file mode 100644 index e319a3bb6..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/JandexPrinter.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.github.t1.powerannotations.common; - -import static com.github.t1.powerannotations.common.PowerAnnotations.log; - -import java.util.function.Consumer; - -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.Index; -import org.jboss.jandex.IndexView; -import org.jboss.jandex.MethodInfo; - -public class JandexPrinter { - - private final IndexView index; - - public JandexPrinter(IndexView index) { - this.index = index; - } - - public void run() { - log.info("------------------------------------------------------------"); - ((Index) index).printAnnotations(); - log.info("------------------------------------------------------------"); - ((Index) index).printSubclasses(); - log.info("------------------------------------------------------------"); - index.getKnownClasses().forEach(new Consumer() { - @Override - public void accept(ClassInfo classInfo) { - if (!classInfo.name().toString().startsWith("test.")) - return; - log.info(classInfo.name() + ":"); - classInfo.methods().forEach(new Consumer() { - @Override - public void accept(MethodInfo method) { - log.info(" " + method.name() + " [" + method.defaultValue() + "]"); - } - }); - } - }); - log.info("------------------------------------------------------------"); - } -} diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/Logger.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/Logger.java deleted file mode 100644 index e9292cac6..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/Logger.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.t1.powerannotations.common; - -public interface Logger { - void info(String message); -} diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/MixinResolver.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/MixinResolver.java deleted file mode 100644 index 6be226205..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/MixinResolver.java +++ /dev/null @@ -1,106 +0,0 @@ -package com.github.t1.powerannotations.common; - -import static com.github.t1.powerannotations.common.PowerAnnotations.log; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.Type; - -class MixinResolver implements Runnable { - private final Jandex jandex; - - MixinResolver(Jandex jandex) { - this.jandex = jandex; - } - - @Override - public void run() { - for (AnnotationInstance mixin : jandex.getAnnotationInstances(MIXIN_FOR)) { - ClassInfo mixinTarget = jandex.getClassInfo(mixin.value().asClass().name()); - ClassInfo mixinClass = mixin.target().asClass(); - log.info("mix " + mixinClass + " into " + mixinTarget); - if (Jandex.isAnnotationType(mixinTarget)) - resolveAnnotationMixin(mixinTarget, mixinClass); - else - resolveMixinAnnotations(mixinTarget, mixinClass); - } - } - - private void resolveAnnotationMixin(ClassInfo mixinTarget, ClassInfo mixinClass) { - for (AnnotationInstance annotationInstance : new ArrayList<>(jandex.getAnnotationInstances(mixinTarget.name()))) { - resolveMixinAnnotations(annotationInstance.target(), mixinClass); - } - } - - private void resolveMixinAnnotations(AnnotationTarget mixinTarget, ClassInfo mixinClass) { - Map> annotations = mixinClass.annotations(); - for (DotName annotationName : annotations.keySet()) { - if (MIXIN_FOR.equals(annotationName)) - continue; - for (AnnotationInstance annotationInstance : annotations.get(annotationName)) { - AnnotationTarget annotation = annotationInstance.target(); - log.info("- " + annotationInstance + " -> " + annotation.kind().name().toLowerCase() + " " + annotation); - switch (annotation.kind()) { - case CLASS: - switch (mixinTarget.kind()) { - case CLASS: - resolveClassMixin(annotationInstance, mixinTarget.asClass()); - continue; - case FIELD: - resolveFieldMixin(annotationInstance, mixinTarget.asField()); - continue; - case METHOD: - try { - MethodInfo targetMethod = getTargetMethod(mixinTarget.asMethod().declaringClass(), - mixinTarget.asMethod()); - resolveMethodMixin(annotationInstance, targetMethod); - } catch (Exception e) { - e.printStackTrace(); - } - continue; - default: - throw new RuntimeException( - "can't resolve an annotation mixin for the " + mixinTarget.kind() + ": " + mixinTarget); - } - case FIELD: - resolveFieldMixin(annotationInstance, mixinTarget.asClass().field(annotation.asField().name())); - continue; - case METHOD: - resolveMethodMixin(annotationInstance, getTargetMethod(mixinTarget.asClass(), annotation.asMethod())); - continue; - } - throw new UnsupportedOperationException("don't know how to resolve a " + annotation.kind() + " mixin: " - + annotationInstance); - } - } - } - - private MethodInfo getTargetMethod(ClassInfo classInfo, MethodInfo method) { - return classInfo.method(method.name(), method.parameters().toArray(new Type[0])); - } - - private void resolveClassMixin(AnnotationInstance annotationInstance, ClassInfo mixinTarget) { - AnnotationInstance copy = jandex.copyAnnotationInstance(annotationInstance, mixinTarget); - jandex.addOrReplace(mixinTarget, copy); - } - - private void resolveFieldMixin(AnnotationInstance annotationInstance, FieldInfo targetField) { - AnnotationInstance copy = jandex.copyAnnotationInstance(annotationInstance, targetField); - jandex.addOrReplace(targetField, copy); - } - - private void resolveMethodMixin(AnnotationInstance annotationInstance, MethodInfo targetMethod) { - AnnotationInstance copy = jandex.copyAnnotationInstance(annotationInstance, targetMethod); - jandex.addOrReplace(targetMethod, copy); - } - - private static final DotName MIXIN_FOR = DotName.createSimple("com.github.t1.annotations.MixinFor"); -} diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/PowerAnnotations.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/PowerAnnotations.java deleted file mode 100644 index a09b3d9a8..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/PowerAnnotations.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.github.t1.powerannotations.common; - -import org.jboss.jandex.Index; - -public class PowerAnnotations { - private final Jandex jandex; - @SuppressWarnings({ "Convert2Lambda", "Anonymous2MethodRef" }) // wouldn't work in a Maven Plugin - public static Logger log = new Logger() { - @Override - public void info(String message) { - System.out.println(message); - } - }; - - public PowerAnnotations(Index index) { - this.jandex = new Jandex(index); - } - - public void resolveAnnotations() { - new MixinResolver(jandex).run(); - new StereotypeResolver(jandex).run(); - } -} diff --git a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/StereotypeResolver.java b/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/StereotypeResolver.java deleted file mode 100644 index 1c440a9db..000000000 --- a/power-annotations/common/src/main/java/com/github/t1/powerannotations/common/StereotypeResolver.java +++ /dev/null @@ -1,126 +0,0 @@ -package com.github.t1.powerannotations.common; - -import static com.github.t1.powerannotations.common.PowerAnnotations.log; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationTarget; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.MethodInfo; - -class StereotypeResolver implements Runnable { - private static final Map STEREOTYPE_NESTING_LEVELS = new TreeMap<>(); - - private final Jandex jandex; - - StereotypeResolver(Jandex jandex) { - this.jandex = jandex; - } - - @Override - public void run() { - for (DotName stereotypeTypeName : jandex.allAnnotationNames()) { - if (!stereotypeTypeName.withoutPackagePrefix().equals("Stereotype")) - continue; - log.info("stereotype type " + stereotypeTypeName); - for (ClassInfo stereotype : stereotypes(stereotypeTypeName)) { - log.info("stereotype " + stereotype); - for (AnnotationInstance stereotypeTargetAnnotationInstance : new ArrayList<>( - jandex.getAnnotationInstances(stereotype.asClass().name()))) { - AnnotationTarget annotationTarget = stereotypeTargetAnnotationInstance.target(); - log.info("-> " + annotationTarget.kind().name().toLowerCase() + " " + annotationTarget); - Map> annotations = stereotype.annotations(); - for (DotName annotationName : annotations.keySet()) { - if (stereotypeTypeName.equals(annotationName) || RETENTION.equals(annotationName) - || jandex.isNotTargetable(annotationName, annotationTarget)) - continue; - for (AnnotationInstance annotationInstance : annotations.get(annotationName)) { - log.info(" - " + annotationInstance); - switch (annotationTarget.kind()) { - case CLASS: - resolveClassStereotype(annotationInstance, annotationTarget.asClass()); - continue; - case FIELD: - resolveFieldStereotype(annotationInstance, annotationTarget.asField()); - continue; - case METHOD: - resolveMethodStereotype(annotationInstance, annotationTarget.asMethod()); - continue; - } - throw new UnsupportedOperationException("don't know how to resolve a " + annotationTarget.kind() - + " stereotype: " + stereotypeTargetAnnotationInstance); - } - } - } - } - } - } - - private List stereotypes(DotName stereotypeTypeName) { - // we can't use streams, because Maven plugins can't run with lambdas and fail with IndexOutOfBounds - List list = new ArrayList<>(); - for (AnnotationInstance annotationInstance : jandex.getAnnotationInstances(stereotypeTypeName)) { - ClassInfo classInfo = annotationInstance.target().asClass(); - list.add(classInfo); - } - list.sort(new StereotypeLevel()); // resolve indirect stereotypes first - return list; - } - - private class StereotypeLevel implements Comparator { - @Override - public int compare(ClassInfo left, ClassInfo right) { - int leftLevel = stereotypeLevel(left); - int rightLevel = stereotypeLevel(right); - return (leftLevel == rightLevel) - ? left.name().compareTo(right.name()) - : (leftLevel - rightLevel); - } - } - - private int stereotypeLevel(ClassInfo stereotypeType) { - // we can't use streams, because Maven plugins can't run with lambdas and fail with IndexOutOfBounds - int max = 0; - for (AnnotationInstance annotationInstance : stereotypeType.classAnnotations()) { - int annotationLevel = stereotypeLevel(annotationInstance); - if (annotationLevel > max) { - max = annotationLevel; - } - } - return max + 1; - } - - private int stereotypeLevel(AnnotationInstance annotationInstance) { - if (STEREOTYPE_NESTING_LEVELS.containsKey(annotationInstance.name())) - return STEREOTYPE_NESTING_LEVELS.get(annotationInstance.name()); - STEREOTYPE_NESTING_LEVELS.put(annotationInstance.name(), 0); // prevent recursion - ClassInfo type = jandex.getClassInfo(annotationInstance.name()); - int annotationLevel = stereotypeLevel(type); - STEREOTYPE_NESTING_LEVELS.put(annotationInstance.name(), annotationLevel); - return annotationLevel; - } - - private void resolveClassStereotype(AnnotationInstance annotationInstance, ClassInfo targetClass) { - AnnotationInstance copy = jandex.copyAnnotationInstance(annotationInstance, targetClass); - jandex.addOrSkip(targetClass, copy); - } - - private void resolveFieldStereotype(AnnotationInstance annotationInstance, FieldInfo targetField) { - AnnotationInstance copy = jandex.copyAnnotationInstance(annotationInstance, targetField); - jandex.addOrSkip(targetField, copy); - } - - private void resolveMethodStereotype(AnnotationInstance annotationInstance, MethodInfo targetMethod) { - AnnotationInstance copy = jandex.copyAnnotationInstance(annotationInstance, targetMethod); - jandex.addOrSkip(targetMethod, copy); - } - - private static final DotName RETENTION = DotName.createSimple("java.lang.annotation.Retention"); -} diff --git a/power-annotations/common/src/main/java/org/jboss/jandex/JandexBackdoor.java b/power-annotations/common/src/main/java/org/jboss/jandex/JandexBackdoor.java deleted file mode 100644 index 496434ff3..000000000 --- a/power-annotations/common/src/main/java/org/jboss/jandex/JandexBackdoor.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.jboss.jandex; - -import static com.github.t1.powerannotations.common.CommonUtils.with; -import static org.jboss.jandex.ReflectionUtils.get; -import static org.jboss.jandex.ReflectionUtils.isArraysArrayList; -import static org.jboss.jandex.ReflectionUtils.isUnmodifiable; -import static org.jboss.jandex.ReflectionUtils.modifiable; -import static org.jboss.jandex.ReflectionUtils.set; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import com.github.t1.powerannotations.common.CommonUtils; - -/** - * A lot of methods or fields in Jandex are package private. The methods in here "add functionality to Jandex" - * that needs access to the internals of Jandex, - * which is much better than using reflection or putting all of our own stuff in the same package. - * Sometimes even that is not enough and we need reflection. - */ -public class JandexBackdoor { - private JandexBackdoor() { - } - - public static Map> annotations(Index index) { - return modifiable(index.annotations); - } - - public static Map classes(Index index) { - return modifiable(index.classes); - } - - public static Map> annotations(ClassInfo classInfo) { - Map> map = get(classInfo, "annotations"); - if (map.isEmpty()) { // EMPTY_MAP is immutable - map = new HashMap<>(); - set(classInfo, "annotations", map); - } else if (isUnmodifiable(map)) - map = modifiable(map); - return map; - } - - public static void add(MethodInfo targetMethod, AnnotationInstance newInstance) { - AnnotationInstance[] copy = with(targetMethod.methodInternal().annotationArray(), newInstance); - replaceAnnotations(targetMethod, copy); - } - - public static void replace(AnnotationInstance newInstance, MethodInfo targetMethod) { - AnnotationInstance[] copy = replace(targetMethod.methodInternal().annotationArray(), newInstance); - replaceAnnotations(targetMethod, copy); - } - - private static void replaceAnnotations(MethodInfo targetMethod, AnnotationInstance[] copy) { - MethodInternal originalMethodInternal = targetMethod.methodInternal(); - MethodInternal newMethodInternal = withAnnotations(originalMethodInternal, copy); - targetMethod.setMethodInternal(newMethodInternal); - CommonUtils.replace(targetMethod.declaringClass().methodArray(), originalMethodInternal, newMethodInternal); - } - - private static MethodInternal withAnnotations(MethodInternal methodInternal, AnnotationInstance[] annotations) { - return new MethodInternal( - methodInternal.nameBytes(), - methodInternal.parameterNamesBytes(), - methodInternal.parameterArray(), - methodInternal.returnType(), - methodInternal.flags(), - methodInternal.receiverTypeField(), - methodInternal.typeParameterArray(), - methodInternal.exceptionArray(), - annotations, - methodInternal.defaultValue()); - } - - public static void add(FieldInfo targetField, AnnotationInstance newInstance) { - AnnotationInstance[] copy = with(targetField.fieldInternal().annotationArray(), newInstance); - replaceAnnotations(targetField, copy); - } - - public static void replace(FieldInfo targetField, AnnotationInstance newInstance) { - AnnotationInstance[] copy = replace(targetField.fieldInternal().annotationArray(), newInstance); - replaceAnnotations(targetField, copy); - } - - private static void replaceAnnotations(FieldInfo targetField, AnnotationInstance[] copy) { - FieldInternal originalFieldInternal = targetField.fieldInternal(); - FieldInternal newFieldInternal = new FieldInternal(originalFieldInternal.nameBytes(), originalFieldInternal.type(), - originalFieldInternal.flags(), copy); - targetField.setFieldInternal(newFieldInternal); - CommonUtils.replace(targetField.declaringClass().fieldArray(), originalFieldInternal, newFieldInternal); - } - - private static AnnotationInstance[] replace(AnnotationInstance[] original, AnnotationInstance newInstance) { - AnnotationInstance[] copy = Arrays.copyOf(original, original.length); - for (int i = 0; i < original.length; i++) { - if (copy[i].name().equals(newInstance.name())) { - copy[i] = newInstance; - return copy; - } - } - throw new RuntimeException("original element " + newInstance.name() + " not in array " + Arrays.toString(original)); - } - - public static List annotations(MethodInfo methodInfo) { - List list = methodInfo.methodInternal().annotations(); - if (isUnmodifiable(list)) - list = modifiable(list); - if (isArraysArrayList(list)) { - list = new ArrayList<>(list); - set(methodInfo.methodInternal(), "annotations", list); - } - return list; - } -} diff --git a/power-annotations/common/src/main/java/org/jboss/jandex/ReflectionUtils.java b/power-annotations/common/src/main/java/org/jboss/jandex/ReflectionUtils.java deleted file mode 100644 index 0211a6005..000000000 --- a/power-annotations/common/src/main/java/org/jboss/jandex/ReflectionUtils.java +++ /dev/null @@ -1,81 +0,0 @@ -package org.jboss.jandex; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; - -class ReflectionUtils { - private ReflectionUtils() { - } - - static T get(Object object, String fieldName) { - return get(object.getClass(), object, fieldName); - } - - static T get(Class type, Object object, String fieldName) { - try { - Field field = type.getDeclaredField(fieldName); - field.setAccessible(true); - @SuppressWarnings("unchecked") - T value = (T) field.get(object); - return value; - } catch (ReflectiveOperationException e) { - throw new RuntimeException("can't get field '" + fieldName + "'", e); - } - } - - static void set(Object object, String fieldName, Object value) { - set(object.getClass(), object, fieldName, value); - } - - static void set(Class type, Object object, String fieldName, Object value) { - try { - Field field = type.getDeclaredField(fieldName); - field.setAccessible(true); - field.set(object, value); - } catch (ReflectiveOperationException e) { - throw new RuntimeException("can't get field '" + fieldName + "'", e); - } - } - - static boolean isUnmodifiable(Map> map) { - return UNMODIFIABLE_MAP.equals(map.getClass()); - } - - static Map modifiable(Map map) { - return get(map, "m"); - } - - static boolean isUnmodifiable(List list) { - return UNMODIFIABLE_LIST.equals(list.getClass()) || UNMODIFIABLE_RANDOM_ACCESS_LIST.equals(list.getClass()); - } - - static List modifiable(List list) { - // UnmodifiableRandomAccessList is a subclass of UnmodifiableList - list = get(UNMODIFIABLE_LIST, list, "list"); - return list; - } - - static boolean isArraysArrayList(List list) { - return ARRAY_LIST.equals(list.getClass()); - } - - private static final Class UNMODIFIABLE_MAP = unmodifiableCollectionClass("Map"); - private static final Class UNMODIFIABLE_LIST = unmodifiableCollectionClass("List"); - private static final Class UNMODIFIABLE_RANDOM_ACCESS_LIST = unmodifiableCollectionClass("RandomAccessList"); - private static final Class ARRAY_LIST = classForName(Arrays.class.getName() + "$ArrayList"); - - private static Class unmodifiableCollectionClass(String type) { - return classForName(Collections.class.getName() + "$Unmodifiable" + type); - } - - private static Class classForName(String className) { - try { - return Class.forName(className); - } catch (ClassNotFoundException e) { - throw new RuntimeException(e); - } - } -} diff --git a/power-annotations/maven-plugin/pom.xml b/power-annotations/maven-plugin/pom.xml deleted file mode 100644 index 62df942ec..000000000 --- a/power-annotations/maven-plugin/pom.xml +++ /dev/null @@ -1,62 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-parent - 1.6.1-SNAPSHOT - - - power-jandex-maven-plugin - maven-plugin - Power Annotations Jandex Maven Plugin - Replaces the `jandex-maven-plugin` to generate a Jandex index file, but with the Power Annotations resolved. - - - 3.5 - - - - true - - 3.8.5 - - - - - org.apache.maven.plugin-tools - maven-plugin-annotations - 3.6.4 - provided - - - org.apache.maven - maven-plugin-api - ${maven.version} - provided - - - org.apache.maven - maven-core - ${maven.version} - provided - - - - io.smallrye - power-annotations-jandex-common - ${project.version} - - - - - - - org.apache.maven.plugins - maven-plugin-plugin - ${version.maven-plugin-plugin} - - - - diff --git a/power-annotations/maven-plugin/src/main/java/com/github/t1/powerjandex/PowerJandexMojo.java b/power-annotations/maven-plugin/src/main/java/com/github/t1/powerjandex/PowerJandexMojo.java deleted file mode 100644 index d8adfc761..000000000 --- a/power-annotations/maven-plugin/src/main/java/com/github/t1/powerjandex/PowerJandexMojo.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.github.t1.powerjandex; - -import static java.nio.file.FileVisitResult.CONTINUE; -import static java.nio.file.Files.createDirectories; -import static java.nio.file.Files.newInputStream; -import static java.nio.file.Files.newOutputStream; -import static java.nio.file.Files.walkFileTree; -import static org.apache.maven.plugins.annotations.LifecyclePhase.PROCESS_CLASSES; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.FileVisitResult; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; - -import javax.inject.Inject; - -import org.apache.maven.plugin.AbstractMojo; -import org.apache.maven.plugins.annotations.Mojo; -import org.apache.maven.project.MavenProject; -import org.jboss.jandex.Index; -import org.jboss.jandex.IndexWriter; -import org.jboss.jandex.Indexer; - -import com.github.t1.powerannotations.common.JandexPrinter; -import com.github.t1.powerannotations.common.Logger; -import com.github.t1.powerannotations.common.PowerAnnotations; - -@Mojo(name = "power-jandex", defaultPhase = PROCESS_CLASSES, threadSafe = true) -public class PowerJandexMojo extends AbstractMojo { - - @Inject - @SuppressWarnings("CdiInjectionPointsInspection") - MavenProject project; - - private final MojoLogger log = new MojoLogger(); - - private class MojoLogger implements Logger { - @Override - public void info(String message) { - getLog().info(message); - } - } - - @Override - public void execute() { - PowerAnnotations.log = log; - - Index index = new Scanner().createIndex(); - - new PowerAnnotations(index).resolveAnnotations(); - - new JandexPrinter(index).run(); - - write(index); - } - - private Path baseDir() { - return project.getBasedir().toPath().resolve("target/classes"); - } - - private class Scanner { - private final Indexer indexer = new Indexer(); - - public Index createIndex() { - scanDirectory(baseDir()); - return indexer.complete(); - } - - public void scanDirectory(Path path) { - try { - walkFileTree(path, new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - if (isClassFile(file)) - scanClassFile(file); - return CONTINUE; - } - }); - } catch (IOException e) { - throw new RuntimeException("failed to index " + path, e); - } - } - - private boolean isClassFile(Path file) { - return file.toString().endsWith(".class"); - } - - private void scanClassFile(Path path) { - try (InputStream inputStream = newInputStream(path)) { - indexer.index(inputStream); - } catch (IOException e) { - throw new RuntimeException("failed to index " + path, e); - } - } - } - - private void write(Index index) { - Path filePath = baseDir().resolve("META-INF/jandex.idx"); - log.info("write index to " + filePath); - try { - createDirectories(filePath.getParent()); - try (OutputStream outputStream = newOutputStream(filePath)) { - new IndexWriter(outputStream).write(index); - } - } catch (IOException e) { - throw new RuntimeException("can't write jandex to " + filePath, e); - } - } -} diff --git a/power-annotations/pom.xml b/power-annotations/pom.xml deleted file mode 100644 index fda20b6f3..000000000 --- a/power-annotations/pom.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-graphql-parent - 1.6.1-SNAPSHOT - - - smallrye-power-annotations-parent - pom - Power Annotations Parent POM - Power-Annotations is a generic mechanism for meta annotations, most notably stereotypes and mixins. - - - annotations - utils - tck - common - maven-plugin - scanner - - - - install - - - org.apache.maven.plugins - maven-compiler-plugin - - 8 - 8 - true - - - - org.apache.maven.plugins - maven-surefire-plugin - - - *Behavior - - - - - - diff --git a/power-annotations/scanner/pom.xml b/power-annotations/scanner/pom.xml deleted file mode 100644 index 1209c207c..000000000 --- a/power-annotations/scanner/pom.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-parent - 1.6.1-SNAPSHOT - - - power-annotations-scanner - Power Annotations Jandex Runtime Scanner - Build a Jandex index at runtime from the classpath and resolve power annotations - - - - org.jboss - jandex - 2.4.2.Final - - - io.smallrye - power-annotations-jandex-common - ${project.version} - - - - org.junit.jupiter - junit-jupiter - 5.8.2 - test - - - org.assertj - assertj-core - 3.22.0 - test - - - diff --git a/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/IndexBuilder.java b/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/IndexBuilder.java deleted file mode 100644 index f710ddb04..000000000 --- a/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/IndexBuilder.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.github.t1.powerannotations.scanner; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Optional; - -import org.jboss.jandex.Index; -import org.jboss.jandex.IndexReader; - -import com.github.t1.powerannotations.common.PowerAnnotations; - -public class IndexBuilder { - public static Index loadOrScan() { - return load().orElseGet(IndexBuilder::scan); - } - - @SuppressWarnings("UnusedReturnValue") - private static Optional load() { - try (InputStream inputStream = getClassLoader().getResourceAsStream("META-INF/jandex.idx")) { - return Optional.ofNullable(inputStream).map(IndexBuilder::load); - } catch (RuntimeException | IOException e) { - throw new RuntimeException("can't read index file", e); - } - } - - private static Index load(InputStream inputStream) { - try { - return new IndexReader(inputStream).read(); - } catch (RuntimeException | IOException e) { - throw new RuntimeException("can't read Jandex input stream", e); - } - } - - private static ClassLoader getClassLoader() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - return (classLoader == null) ? ClassLoader.getSystemClassLoader() : classLoader; - } - - private static Index scan() { - Index index = new Scanner().scanClassPath(); - new PowerAnnotations(index).resolveAnnotations(); - return index; - } -} diff --git a/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/IndexerConfig.java b/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/IndexerConfig.java deleted file mode 100644 index 72a890d67..000000000 --- a/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/IndexerConfig.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.github.t1.powerannotations.scanner; - -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -class IndexerConfig { - private final List exclude = new ArrayList<>(); - - IndexerConfig() { - this("META-INF/jandex.properties"); - } - - IndexerConfig(String resource) { - try (InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(resource)) { - if (inputStream == null) - return; - Properties properties = new Properties(); - properties.load(inputStream); - loadExcludeConfig(properties); - } catch (IOException e) { - throw new RuntimeException("can't load " + resource, e); - } - } - - private void loadExcludeConfig(Properties properties) { - String excludeString = properties.getProperty("exclude", null); - if (excludeString != null) { - try { - Stream.of(excludeString.split("\\s+")) - .map(this::gavToRegex) - .forEach(this.exclude::add); - } catch (Exception e) { - throw new RuntimeException("can't parse exclude config", e); - } - } - } - - private String gavToRegex(String groupArtifact) { - Matcher matcher = Pattern.compile("(?[^:]+):(?[^:]+)").matcher(groupArtifact); - if (!matcher.matches()) - throw new RuntimeException("expect `group:artifact` but found `" + groupArtifact + "`"); - return ".*/" + matcher.group("group") + "/.*/" + matcher.group("artifact") + "-.*\\.jar"; - } - - public Stream excludes() { - return exclude.stream(); - } -} diff --git a/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/Scanner.java b/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/Scanner.java deleted file mode 100644 index 08f79001a..000000000 --- a/power-annotations/scanner/src/main/java/com/github/t1/powerannotations/scanner/Scanner.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.github.t1.powerannotations.scanner; - -import static com.github.t1.powerannotations.common.PowerAnnotations.*; -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.stream.Stream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import org.jboss.jandex.Index; -import org.jboss.jandex.Indexer; - -public class Scanner { - - private final Indexer indexer = new Indexer(); - private final IndexerConfig config = new IndexerConfig(); - private int archivesIndexed; - private int classesIndexed; - - public Index scanClassPath() { - long t = System.currentTimeMillis(); - urls() - .distinct() - .filter(this::include) - .forEach(this::index); - Index index = indexer.complete(); - log.info("scanned " + archivesIndexed + " archives with " + classesIndexed + " classes " + - "in " + (System.currentTimeMillis() - t) + "ms"); - return index; - } - - private Stream urls() { - return Stream.of(System.getProperty("java.class.path") - .split(System.getProperty("path.separator"))) - .map(Scanner::toUrl); - } - - private static URL toUrl(String url) { - try { - return Paths.get(url).toUri().toURL(); - } catch (MalformedURLException e) { - throw new RuntimeException("invalid classpath url " + url, e); - } - } - - private boolean include(URL url) { - String urlString = url.toString(); - return config.excludes().noneMatch(urlString::matches); - } - - private void index(URL url) { - try { - long t0 = System.currentTimeMillis(); - int classesIndexedBefore = classesIndexed; - if (url.toString().endsWith(".jar") || url.toString().endsWith(".war")) - indexArchive(url.openStream()); - else - indexFolder(url); - log.info("indexed " + (classesIndexed - classesIndexedBefore) + " classes in " + url - + " in " + (System.currentTimeMillis() - t0) + " ms"); - } catch (IOException e) { - throw new RuntimeException("can't index " + url, e); - } - } - - private void indexArchive(InputStream inputStream) throws IOException { - archivesIndexed++; - ZipInputStream zipInputStream = new ZipInputStream(inputStream, UTF_8); - while (true) { - ZipEntry entry = zipInputStream.getNextEntry(); - if (entry == null) - break; - String entryName = entry.getName(); - indexFile(entryName, zipInputStream); - } - } - - private void indexFile(String fileName, InputStream inputStream) throws IOException { - if (fileName.endsWith(".class")) { - classesIndexed++; - indexer.index(inputStream); - } else if (fileName.endsWith(".war")) { - // necessary because of the Thorntail arquillian adapter - indexArchive(inputStream); - } - } - - private void indexFolder(URL url) throws IOException { - try { - Path folderPath = Paths.get(url.toURI()); - if (Files.isDirectory(folderPath)) { - try (Stream walk = Files.walk(folderPath)) { - walk.filter(Files::isRegularFile) - .forEach(this::indexFile); - } - } - } catch (URISyntaxException e) { - throw new RuntimeException("invalid folder url " + url, e); - } - } - - private void indexFile(Path path) { - try { - String entryName = path.getFileName().toString(); - indexFile(entryName, Files.newInputStream(path)); - } catch (IOException e) { - throw new RuntimeException("can't index path " + path, e); - } - } -} diff --git a/power-annotations/scanner/src/test/java/com/github/t1/powerannotations/scanner/IndexerConfigBehavior.java b/power-annotations/scanner/src/test/java/com/github/t1/powerannotations/scanner/IndexerConfigBehavior.java deleted file mode 100644 index b111834ee..000000000 --- a/power-annotations/scanner/src/test/java/com/github/t1/powerannotations/scanner/IndexerConfigBehavior.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.github.t1.powerannotations.scanner; - -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.assertj.core.api.BDDAssertions.then; - -import org.junit.jupiter.api.Test; - -class IndexerConfigBehavior { - @Test - void shouldIgnoreUnknownResource() { - IndexerConfig unknown = new IndexerConfig("unknown"); - - then(unknown.excludes()).isEmpty(); - } - - @Test - void shouldLoadEmptyResource() { - IndexerConfig unknown = new IndexerConfig("META-INF/empty.properties"); - - then(unknown.excludes()).isEmpty(); - } - - @Test - void shouldLoadOtherPropertiesResource() { - IndexerConfig unknown = new IndexerConfig("META-INF/other.properties"); - - then(unknown.excludes()).isEmpty(); - } - - @Test - void shouldLoadOneExcludeConfig() { - IndexerConfig unknown = new IndexerConfig("META-INF/one-exclude.properties"); - - then(unknown.excludes()).containsExactly(".*/foo/.*/bar-.*\\.jar"); - } - - @Test - void shouldFailToLoadInvalidExcludeConfig() { - Throwable throwable = catchThrowable(() -> new IndexerConfig("META-INF/invalid-exclude.properties")); - - then(throwable) - .hasMessage("can't parse exclude config") - .hasRootCauseMessage("expect `group:artifact` but found `invalid`"); - } - - @Test - void shouldLoadMultiExcludeConfig() { - IndexerConfig unknown = new IndexerConfig("META-INF/multi-exclude.properties"); - - then(unknown.excludes()).containsExactly( - ".*/foo/.*/bar-.*\\.jar", - ".*/baz/.*/bee-.*\\.jar"); - } -} diff --git a/power-annotations/scanner/src/test/resources/META-INF/empty.properties b/power-annotations/scanner/src/test/resources/META-INF/empty.properties deleted file mode 100644 index e69de29bb..000000000 diff --git a/power-annotations/scanner/src/test/resources/META-INF/invalid-exclude.properties b/power-annotations/scanner/src/test/resources/META-INF/invalid-exclude.properties deleted file mode 100644 index b654114c1..000000000 --- a/power-annotations/scanner/src/test/resources/META-INF/invalid-exclude.properties +++ /dev/null @@ -1 +0,0 @@ -exclude=invalid diff --git a/power-annotations/scanner/src/test/resources/META-INF/multi-exclude.properties b/power-annotations/scanner/src/test/resources/META-INF/multi-exclude.properties deleted file mode 100644 index 287f2d33b..000000000 --- a/power-annotations/scanner/src/test/resources/META-INF/multi-exclude.properties +++ /dev/null @@ -1,2 +0,0 @@ -exclude=foo:bar \ - baz:bee diff --git a/power-annotations/scanner/src/test/resources/META-INF/one-exclude.properties b/power-annotations/scanner/src/test/resources/META-INF/one-exclude.properties deleted file mode 100644 index 9f2e4ab7b..000000000 --- a/power-annotations/scanner/src/test/resources/META-INF/one-exclude.properties +++ /dev/null @@ -1 +0,0 @@ -exclude=foo:bar diff --git a/power-annotations/scanner/src/test/resources/META-INF/other.properties b/power-annotations/scanner/src/test/resources/META-INF/other.properties deleted file mode 100644 index 0fb7e9ef0..000000000 --- a/power-annotations/scanner/src/test/resources/META-INF/other.properties +++ /dev/null @@ -1,2 +0,0 @@ -# suppress inspection "UnusedProperty" for whole file -something.else = true diff --git a/power-annotations/tck/pom.xml b/power-annotations/tck/pom.xml deleted file mode 100644 index 69687bdb9..000000000 --- a/power-annotations/tck/pom.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-parent - 1.6.1-SNAPSHOT - - - power-annotations-tck - Power Annotations TCK - Test Compatibility Kit for Power Annotations, i.e. verifies that a Power Annotations implementation complies to the standard. - - - - io.smallrye - power-annotations - ${project.version} - - - - org.junit.jupiter - junit-jupiter - 5.8.2 - test - - - org.assertj - assertj-core - 3.22.0 - test - - - org.jboss - jandex - 2.4.2.Final - test - - - io.smallrye - smallrye-power-annotations-utils-api - ${project.version} - test - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - !InheritedAnnotationsTestSuite & !TypeToMemberAnnotationsTestSuite - - ${powerannotations.tck.argLine} - - - - - - - - utils-jandex - - true - - - - io.smallrye - smallrye-power-annotations-utils-jandex - ${project.version} - test - - - - - power-jandex-maven-plugin - - - - io.smallrye - power-jandex-maven-plugin - ${project.version} - - - - power-jandex - - - - - - - - - diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/AnnotationValueTypeClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/AnnotationValueTypeClasses.java deleted file mode 100644 index d447e41d4..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/AnnotationValueTypeClasses.java +++ /dev/null @@ -1,158 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.RetentionPolicy.CLASS; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static java.lang.annotation.RetentionPolicy.SOURCE; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -public class AnnotationValueTypeClasses { - @Retention(RUNTIME) - public @interface DifferentValueTypesAnnotation { - boolean booleanValue() default false; - - byte byteValue() default 0; - - char charValue() default 0; - - short shortValue() default 0; - - int intValue() default 0; - - long longValue() default 0; - - float floatValue() default 0; - - double doubleValue() default 0; - - String stringValue() default ""; - - RetentionPolicy enumValue() default SOURCE; - - Class classValue() default Void.class; - - SomeAnnotation annotationValue() default @SomeAnnotation(""); - - boolean[] booleanArrayValue() default false; - - byte[] byteArrayValue() default 0; - - char[] charArrayValue() default 0; - - short[] shortArrayValue() default 0; - - int[] intArrayValue() default 0; - - long[] longArrayValue() default 0; - - double[] doubleArrayValue() default 0; - - float[] floatArrayValue() default 0; - - String[] stringArrayValue() default ""; - - RetentionPolicy[] enumArrayValue() default SOURCE; - - Class[] classArrayValue() default Void.class; - - SomeAnnotation[] annotationArrayValue() default @SomeAnnotation(""); - } - - @DifferentValueTypesAnnotation(booleanValue = true) - public static class AnnotatedWithBooleanValueClass { - } - - @DifferentValueTypesAnnotation(byteValue = 1) - public static class AnnotatedWithByteValueClass { - } - - @DifferentValueTypesAnnotation(charValue = 'a') - public static class AnnotatedWithCharValueClass { - } - - @DifferentValueTypesAnnotation(shortValue = 1234) - public static class AnnotatedWithShortValueClass { - } - - @DifferentValueTypesAnnotation(intValue = 42) - public static class AnnotatedWithIntValueClass { - } - - @DifferentValueTypesAnnotation(longValue = 44L) - public static class AnnotatedWithLongValueClass { - } - - @DifferentValueTypesAnnotation(floatValue = 1.2F) - public static class AnnotatedWithFloatValueClass { - } - - @DifferentValueTypesAnnotation(doubleValue = 12.34D) - public static class AnnotatedWithDoubleValueClass { - } - - @DifferentValueTypesAnnotation(stringValue = "foo") - public static class AnnotatedWithStringValueClass { - } - - @DifferentValueTypesAnnotation(enumValue = RUNTIME) - public static class AnnotatedWithEnumValueClass { - } - - @DifferentValueTypesAnnotation(classValue = String.class) - public static class AnnotatedWithClassValueClass { - } - - @DifferentValueTypesAnnotation(annotationValue = @SomeAnnotation("annotation-value")) - public static class AnnotatedWithAnnotationValueClass { - } - - @DifferentValueTypesAnnotation(booleanArrayValue = { true, false }) - public static class AnnotatedWithBooleanArrayValueClass { - } - - @DifferentValueTypesAnnotation(byteArrayValue = { 1, 2 }) - public static class AnnotatedWithByteArrayValueClass { - } - - @DifferentValueTypesAnnotation(charArrayValue = { 'a', 'b' }) - public static class AnnotatedWithCharArrayValueClass { - } - - @DifferentValueTypesAnnotation(shortArrayValue = { 1234, 1235 }) - public static class AnnotatedWithShortArrayValueClass { - } - - @DifferentValueTypesAnnotation(intArrayValue = { 42, 43 }) - public static class AnnotatedWithIntArrayValueClass { - } - - @DifferentValueTypesAnnotation(longArrayValue = { 44L, 45L }) - public static class AnnotatedWithLongArrayValueClass { - } - - @DifferentValueTypesAnnotation(floatArrayValue = { 1.2F, 1.3F }) - public static class AnnotatedWithFloatArrayValueClass { - } - - @DifferentValueTypesAnnotation(doubleArrayValue = { 12.34D, 12.35D }) - public static class AnnotatedWithDoubleArrayValueClass { - } - - @DifferentValueTypesAnnotation(stringArrayValue = { "foo", "bar" }) - public static class AnnotatedWithStringArrayValueClass { - } - - @DifferentValueTypesAnnotation(enumArrayValue = { RUNTIME, CLASS }) - public static class AnnotatedWithEnumArrayValueClass { - } - - @DifferentValueTypesAnnotation(classArrayValue = { String.class, Integer.class }) - public static class AnnotatedWithClassArrayValueClass { - } - - @DifferentValueTypesAnnotation(annotationArrayValue = { @SomeAnnotation("annotation-value1"), - @SomeAnnotation("annotation-value2") }) - public static class AnnotatedWithAnnotationArrayValueClass { - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/CombinedAnnotationClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/CombinedAnnotationClasses.java deleted file mode 100644 index 35659fbdb..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/CombinedAnnotationClasses.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; - -import com.github.t1.annotations.Stereotype; - -public class CombinedAnnotationClasses { - @Stereotype - @SomeAnnotation("from-stereotype") - @Retention(RUNTIME) - public @interface SomeStereotype { - } - - @SomeStereotype - public interface SomeStereotypedInterface { - @SuppressWarnings("unused") - void foo(); - } - - @SomeStereotype - public static class SomeStereotypedClass { - @SuppressWarnings("unused") - public void foo() { - } - } - - @SomeAnnotation("from-sub-interface") - public interface SomeInheritingInterface extends SomeInheritedInterface { - } - - public interface SomeInheritedInterface { - @SuppressWarnings("unused") - void foo(); - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/ContainingTypeClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/ContainingTypeClasses.java deleted file mode 100644 index 906d3ef2f..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/ContainingTypeClasses.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -public class ContainingTypeClasses { - - @Retention(RUNTIME) - public @interface SomeAnnotationWithoutTargetAnnotation { - } - - @Retention(RUNTIME) - @Target(TYPE) - public @interface SomeAnnotationWithOnlyTypeTargetAnnotation { - } - - @SomeAnnotation("class-annotation") - @SomeAnnotationWithoutTargetAnnotation - @SomeAnnotationWithOnlyTypeTargetAnnotation - public static class ClassWithField { - @SuppressWarnings("unused") - String someField; - } - - @RepeatableAnnotation(1) - @RepeatableAnnotation(2) - public static class ClassWithRepeatedAnnotationsForField { - @SuppressWarnings("unused") - String someField; - } - - @RepeatableAnnotation(2) - public static class ClassWithRepeatableAnnotationOnClassAndField { - @RepeatableAnnotation(1) - @SuppressWarnings("unused") - String someField; - } - - @SomeAnnotation("class-annotation") - public static class ClassWithAnnotationsOnClassAndField { - @SuppressWarnings("unused") - @RepeatableAnnotation(1) - String someField; - } - - @SomeAnnotation("class-annotation") - @SomeAnnotationWithoutTargetAnnotation - @SomeAnnotationWithOnlyTypeTargetAnnotation - public static class ClassWithMethod { - @SuppressWarnings("unused") - void someMethod() { - } - } - - @RepeatableAnnotation(1) - @RepeatableAnnotation(2) - public static class ClassWithRepeatedAnnotationsForMethod { - @SuppressWarnings("unused") - void someMethod() { - } - } - - @RepeatableAnnotation(2) - public static class ClassWithRepeatableAnnotationOnClassAndMethod { - @RepeatableAnnotation(1) - @SuppressWarnings("unused") - void someMethod() { - } - } - - @SomeAnnotation("class-annotation") - public static class ClassWithAnnotationsOnClassAndMethod { - @SuppressWarnings("unused") - @RepeatableAnnotation(1) - void someMethod() { - } - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/DirectAnnotationClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/DirectAnnotationClasses.java deleted file mode 100644 index c857a8dd3..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/DirectAnnotationClasses.java +++ /dev/null @@ -1,55 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; - -import com.github.t1.annotations.tck.MixinClasses.AnotherAnnotation; - -public class DirectAnnotationClasses { - @Retention(RUNTIME) - public @interface SomeAnnotationWithDefaultValue { - String valueWithDefault() default "default-value"; - } - - public static class SomeUnannotatedClass { - } - - @SomeAnnotation("class-annotation") - public static class SomeAnnotatedClass { - } - - @SomeAnnotation("interface-annotation") - @SomeAnnotationWithDefaultValue - public interface SomeAnnotatedInterface { - } - - public static class SomeClassWithUnannotatedField { - @SuppressWarnings("unused") - String foo; - } - - public static class SomeClassWithAnnotatedField { - @SuppressWarnings("unused") - @SomeAnnotation("field-annotation") - private String foo; - } - - public static class SomeClassWithUnannotatedMethod { - @SuppressWarnings("unused") - void foo(String x) { - } - } - - public static class SomeClassWithAnnotatedMethod { - @SuppressWarnings("unused") - @SomeAnnotation("method-annotation") - void foo(String x) { - } - } - - public interface SomeInterfaceWithAnnotatedMethod { - @SomeAnnotation("method-annotation") - void foo(@AnotherAnnotation String x); - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/InheritedAnnotationClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/InheritedAnnotationClasses.java deleted file mode 100644 index dd2e5aa3f..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/InheritedAnnotationClasses.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.github.t1.annotations.tck; - -public class InheritedAnnotationClasses { - - @SomeAnnotation("1") - @RepeatableAnnotation(1) - public interface InheritingInterface extends Base, SideBase { - } - - @SomeAnnotation("2") - @RepeatableAnnotation(2) - public static class InheritingClass extends Super implements Base, SideBase { - } - - @SomeAnnotation("3") - @RepeatableAnnotation(3) - public static class Super { - @SomeAnnotation("4") - @RepeatableAnnotation(4) - public String field; - - @SomeAnnotation("5") - @RepeatableAnnotation(5) - public String method() { - return null; - } - } - - @SomeAnnotation("6") - @RepeatableAnnotation(6) - public interface Base extends SuperBase { - @SomeAnnotation("7") - @RepeatableAnnotation(7) - @Override - String method(); - } - - @SomeAnnotation("8") - @RepeatableAnnotation(8) - public interface SideBase { - } - - @SomeAnnotation("9") - @RepeatableAnnotation(9) - public interface SuperBase { - @SomeAnnotation("10") - @RepeatableAnnotation(10) - default String method() { - return null; - } - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/MixinClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/MixinClasses.java deleted file mode 100644 index 12085c483..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/MixinClasses.java +++ /dev/null @@ -1,304 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import com.github.t1.annotations.MixinFor; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.SomeAnnotationWithoutValue; - -public class MixinClasses { - @Retention(RUNTIME) - public @interface AnotherAnnotation { - } - - public static class TypeAnnotationMixinClasses { - @Retention(RUNTIME) - public @interface SomeAnnotationWithoutValue { - } - - @SomeAnnotationWithoutValue - @SomeAnnotation("to-be-replaced") - @RepeatableAnnotation(2) - public static class SomeClassWithVariousAnnotations { - } - - @MixinFor(SomeClassWithVariousAnnotations.class) - @AnotherAnnotation - @SomeAnnotation("replacing") - @RepeatableAnnotation(1) - public static class MixinForSomeClassWithVariousAnnotations { - } - - @SomeAnnotationTargetedByMixin - @RepeatableAnnotation(1) - public static class SomeClassWithAnnotationTargetedByMixin { - } - - @Retention(RUNTIME) - @RepeatableAnnotation(3) - public @interface SomeAnnotationTargetedByMixin { - } - - @MixinFor(SomeAnnotationTargetedByMixin.class) - @SomeAnnotation("annotation-mixin") - @RepeatableAnnotation(2) - public static class MixinForAnnotation { - } - - @SomeAnnotationTargetedByMixin - @SomeAnnotation("original") - public static class OriginalAnnotatedTarget { - } - - public static class TargetClassWithTwoMixins { - } - - @MixinFor(TargetClassWithTwoMixins.class) - @SomeAnnotation("one") - static class MixinForTargetClassWithTwoMixins1 { - } - - @MixinFor(TargetClassWithTwoMixins.class) - @RepeatableAnnotation(2) - static class MixinForTargetClassWithTwoMixins2 { - } - - public static class TargetClassWithTwoNonRepeatableMixins { - } - - @MixinFor(TargetClassWithTwoNonRepeatableMixins.class) - @SomeAnnotation("two") - static class MixinForTargetClassWithTwoNonRepeatableMixins1 { - } - - @MixinFor(TargetClassWithTwoNonRepeatableMixins.class) - @SomeAnnotation("three") - static class MixinForTargetClassWithTwoNonRepeatableMixins2 { - } - - public static class TargetClassWithTwoRepeatableMixins { - } - - @MixinFor(TargetClassWithTwoRepeatableMixins.class) - @RepeatableAnnotation(1) - static class MixinForTargetClassWithTwoRepeatableMixins1 { - } - - @MixinFor(TargetClassWithTwoRepeatableMixins.class) - @RepeatableAnnotation(2) - static class MixinForTargetClassWithTwoRepeatableMixins2 { - } - } - - public static class AnnotatedFieldMixinClasses { - public static class SomeClassWithFieldWithVariousAnnotations { - @SuppressWarnings("unused") - @SomeAnnotationWithoutValue - @SomeAnnotation("to-be-replaced") - @RepeatableAnnotation(2) - String foo; - - @SuppressWarnings("unused") - String bar; - } - - @MixinFor(SomeClassWithFieldWithVariousAnnotations.class) - public static class MixinForSomeClassWithFieldWithVariousAnnotations { - @SuppressWarnings("unused") - @AnotherAnnotation - @SomeAnnotation("replacing") - @RepeatableAnnotation(1) - String foo; - } - - public static class TargetFieldClassWithTwoMixins { - @SuppressWarnings("unused") - String foo; - } - - @MixinFor(TargetFieldClassWithTwoMixins.class) - static class MixinForTargetFieldClassWithTwoMixins1 { - @SomeAnnotation("four") - @SuppressWarnings("unused") - String foo; - } - - @MixinFor(TargetFieldClassWithTwoMixins.class) - static class MixinForTargetFieldClassWithTwoMixins2 { - @RepeatableAnnotation(2) - @SuppressWarnings("unused") - String foo; - } - - public static class TargetFieldClassWithTwoNonRepeatableMixins { - @SuppressWarnings("unused") - String foo; - } - - @MixinFor(TargetFieldClassWithTwoNonRepeatableMixins.class) - static class MixinForTargetFieldClassWithTwoNonRepeatableMixins1 { - @SomeAnnotation("five") - @SuppressWarnings("unused") - String foo; - } - - @MixinFor(TargetFieldClassWithTwoNonRepeatableMixins.class) - static class MixinForTargetFieldClassWithTwoNonRepeatableMixins2 { - @SomeAnnotation("six") - @SuppressWarnings("unused") - String foo; - } - - public static class TargetFieldClassWithTwoRepeatableMixins { - @SuppressWarnings("unused") - String foo; - } - - @MixinFor(TargetFieldClassWithTwoRepeatableMixins.class) - static class MixinForTargetFieldClassWithTwoRepeatableMixins1 { - @RepeatableAnnotation(1) - @SuppressWarnings("unused") - String foo; - } - - @MixinFor(TargetFieldClassWithTwoRepeatableMixins.class) - static class MixinForTargetFieldClassWithTwoRepeatableMixins2 { - @RepeatableAnnotation(2) - @SuppressWarnings("unused") - String foo; - } - } - - public static class AnnotatedMethodMixinClasses { - public static class SomeClassWithMethodWithVariousAnnotations { - @SuppressWarnings("unused") - @SomeAnnotationWithoutValue - @SomeAnnotation("to-be-replaced") - @RepeatableAnnotation(2) - String foo() { - return "foo"; - } - - @SuppressWarnings("unused") - String bar() { - return "bar"; - } - } - - @MixinFor(SomeClassWithMethodWithVariousAnnotations.class) - public static class MixinForSomeClassWithMethodWithVariousAnnotations { - @SuppressWarnings("unused") - @AnotherAnnotation - @SomeAnnotation("replacing") - @RepeatableAnnotation(1) - String foo() { - return "foo"; - } - } - - public static class TargetMethodClassWithTwoMixins { - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - - @MixinFor(TargetMethodClassWithTwoMixins.class) - static class MixinForTargetMethodClassWithTwoMixins1 { - @SomeAnnotation("seven") - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - - @MixinFor(TargetMethodClassWithTwoMixins.class) - static class MixinForTargetMethodClassWithTwoMixins2 { - @RepeatableAnnotation(2) - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - - public static class TargetMethodClassWithTwoNonRepeatableMixins { - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - - @MixinFor(TargetMethodClassWithTwoNonRepeatableMixins.class) - interface MixinForTargetMethodClassWithTwoNonRepeatableMixins1 { - @SomeAnnotation("eight") - @SuppressWarnings("unused") - String foo(); - } - - @MixinFor(TargetMethodClassWithTwoNonRepeatableMixins.class) - interface MixinTargetMethodClassWithTwoNonRepeatableMixins2 { - @SomeAnnotation("nine") - @SuppressWarnings("unused") - String foo(); - } - - public static class TargetMethodClassWithTwoRepeatableMixins { - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - - @MixinFor(TargetMethodClassWithTwoRepeatableMixins.class) - static class MixinForTargetMethodClassWithTwoRepeatableMixins1 { - @RepeatableAnnotation(1) - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - - @MixinFor(TargetMethodClassWithTwoRepeatableMixins.class) - static class MixinForTargetMethodClassWithTwoRepeatableMixins2 { - @RepeatableAnnotation(2) - @SuppressWarnings("unused") - String foo() { - return "foo"; - } - } - } - - public static class AnnotationMixinClasses { - public static class ClassWithAnnotationsExtendedByMixIn { - @DirectAnnotation - @SuppressWarnings("unused") - Long field; - - @DirectAnnotation - @SuppressWarnings("unused") - Long method() { - return null; - } - } - - @Target({ METHOD, FIELD }) - @Retention(RUNTIME) - public @interface DirectAnnotation { - } - - @Retention(RUNTIME) - @Target({ ElementType.PARAMETER, FIELD, METHOD, ElementType.ANNOTATION_TYPE, ElementType.TYPE }) - public @interface MixedInAnnotation { - } - - @MixinFor(DirectAnnotation.class) - @MixedInAnnotation - public interface DirectAnnotationMixin { - } - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/RepeatableAnnotation.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/RepeatableAnnotation.java deleted file mode 100644 index b78453193..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/RepeatableAnnotation.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Repeatable; -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import com.github.t1.annotations.tck.RepeatableAnnotation.RepeatableAnnotations; - -@Retention(RUNTIME) -@Target({ TYPE, FIELD, METHOD }) -@Repeatable(RepeatableAnnotations.class) -public @interface RepeatableAnnotation { - int value(); - - @Target({ TYPE, FIELD, METHOD }) - @Retention(RUNTIME) - @interface RepeatableAnnotations { - @SuppressWarnings("unused") - RepeatableAnnotation[] value(); - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/RepeatableAnnotationClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/RepeatableAnnotationClasses.java deleted file mode 100644 index 555a69014..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/RepeatableAnnotationClasses.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.github.t1.annotations.tck; - -public class RepeatableAnnotationClasses { - @RepeatableAnnotation(1) - public static class UnrepeatedAnnotationClass { - @RepeatableAnnotation(10) - public String foo; - - @RepeatableAnnotation(20) - public void bar() { - } - } - - @RepeatableAnnotation(1) - @RepeatableAnnotation(2) - public static class RepeatedAnnotationClass { - @RepeatableAnnotation(11) - @RepeatableAnnotation(12) - public String foo; - - @RepeatableAnnotation(21) - @RepeatableAnnotation(22) - public void bar() { - } - } -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/SomeAnnotation.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/SomeAnnotation.java deleted file mode 100644 index 3c47b99d5..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/SomeAnnotation.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.ElementType.FIELD; -import static java.lang.annotation.ElementType.METHOD; -import static java.lang.annotation.ElementType.TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -@Retention(RUNTIME) -@Target({ TYPE, FIELD, METHOD }) -public @interface SomeAnnotation { - String value(); -} diff --git a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/StereotypeClasses.java b/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/StereotypeClasses.java deleted file mode 100644 index 7a00a6265..000000000 --- a/power-annotations/tck/src/main/java/com/github/t1/annotations/tck/StereotypeClasses.java +++ /dev/null @@ -1,186 +0,0 @@ -package com.github.t1.annotations.tck; - -import static java.lang.annotation.ElementType.ANNOTATION_TYPE; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; -import java.lang.annotation.Target; - -import com.github.t1.annotations.Stereotype; -import com.github.t1.annotations.tck.MixinClasses.AnotherAnnotation; - -public class StereotypeClasses { - @Retention(RUNTIME) - @Target(ANNOTATION_TYPE) - // i.e. not on TYPE - public @interface SomeMetaAnnotation { - } - - @Stereotype - @Retention(RUNTIME) - @AnotherAnnotation - @SomeAnnotation("from-stereotype") - @RepeatableAnnotation(1) - @RepeatableAnnotation(2) - @SomeMetaAnnotation - public @interface SomeStereotype { - } - - @Stereotype - @Retention(RUNTIME) - @SomeAnnotation("from-another-stereotype") - public @interface AnotherStereotype { - } - - @Stereotype - @Retention(RUNTIME) - @RepeatableAnnotation(1) - public @interface StereotypeWithOne { - } - - @Stereotype - @Retention(RUNTIME) - @RepeatableAnnotation(1) - @RepeatableAnnotation(2) - public @interface StereotypeWithTwo { - } - - @Stereotype - @Retention(RUNTIME) - @RepeatableAnnotation(1) - @RepeatableAnnotation(2) - @RepeatableAnnotation(3) - public @interface StereotypeWithThree { - } - - @Stereotype - @Retention(RUNTIME) - @RepeatableAnnotation(11) - public @interface AnotherStereotypeWithOne { - } - - @Stereotype - @Retention(RUNTIME) - @RepeatableAnnotation(11) - @RepeatableAnnotation(12) - public @interface AnotherStereotypeWithTwo { - } - - @Stereotype - @Retention(RUNTIME) - @SomeStereotype - public @interface SomeIndirectedStereotype { - } - - @Stereotype - @Retention(RUNTIME) - @SomeStereotype - public @interface SomeTardyIndirectedStereotype { - } - - @Stereotype - @Retention(RUNTIME) - @SomeIndirectedStereotype - public @interface SomeDoubleIndirectedStereotype { - } - - @SomeStereotype - @RepeatableAnnotation(5) - public static class StereotypedClass { - } - - @SomeStereotype - @SomeAnnotation("on-class") - public static class StereotypedClassWithSomeAnnotation { - } - - @SomeIndirectedStereotype - public static class IndirectlyStereotypedClass { - } - - @SomeTardyIndirectedStereotype - public static class TardyIndirectlyStereotypedClass { - } - - @SomeDoubleIndirectedStereotype - public static class DoubleIndirectlyStereotypedClass { - } - - @SomeStereotype - @AnotherStereotype - @RepeatableAnnotation(6) - public static class DoubleStereotypedClass { - } - - @StereotypeWithOne - @AnotherStereotypeWithOne - public static class MergeRepeatableAnnotationFromOneAndOne { - } - - @StereotypeWithOne - @AnotherStereotypeWithTwo - public static class MergeRepeatableAnnotationFromOneAndTwo { - } - - @StereotypeWithTwo - @AnotherStereotypeWithOne - public static class MergeRepeatableAnnotationFromTwoAndOne { - } - - @StereotypeWithTwo - @AnotherStereotypeWithTwo - public static class MergeRepeatableAnnotationFromTwoAndTwo { - } - - @StereotypeWithOne - @RepeatableAnnotation(2) - public static class MergeOneRepeatableAnnotationIntoOne { - } - - @StereotypeWithOne - @RepeatableAnnotation(21) - @RepeatableAnnotation(22) - public static class MergeOneRepeatableAnnotationIntoTwo { - } - - @StereotypeWithTwo - @RepeatableAnnotation(21) - public static class MergeTwoRepeatableAnnotationIntoOne { - } - - @StereotypeWithTwo - @RepeatableAnnotation(21) - @RepeatableAnnotation(22) - public static class MergeTwoRepeatableAnnotationIntoTwo { - } - - @StereotypeWithThree - @RepeatableAnnotation(21) - @RepeatableAnnotation(22) - @RepeatableAnnotation(23) - public static class MergeThreeRepeatableAnnotationIntoThree { - } - - @SuppressWarnings("unused") - public static class ClassWithStereotypedField { - @SomeStereotype - @SomeAnnotation("on-field") - @RepeatableAnnotation(7) - String foo; - boolean bar; - } - - @SuppressWarnings("unused") - public static class ClassWithStereotypedMethod { - @SomeStereotype - @SomeAnnotation("on-method") - @RepeatableAnnotation(7) - String foo() { - return "foo"; - } - - String bar() { - return "bar"; - } - } -} diff --git a/power-annotations/tck/src/test/java/test/AnnotationValueTypeBehavior.java b/power-annotations/tck/src/test/java/test/AnnotationValueTypeBehavior.java deleted file mode 100644 index 1a5588a12..000000000 --- a/power-annotations/tck/src/test/java/test/AnnotationValueTypeBehavior.java +++ /dev/null @@ -1,222 +0,0 @@ -package test; - -import static java.lang.annotation.RetentionPolicy.CLASS; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import static org.assertj.core.api.BDDAssertions.then; - -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithAnnotationArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithAnnotationValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithBooleanArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithBooleanValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithByteArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithByteValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithCharArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithCharValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithClassArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithClassValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithDoubleArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithDoubleValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithEnumArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithEnumValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithFloatArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithFloatValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithIntArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithIntValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithLongArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithLongValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithShortArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithShortValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithStringArrayValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.AnnotatedWithStringValueClass; -import com.github.t1.annotations.tck.AnnotationValueTypeClasses.DifferentValueTypesAnnotation; -import com.github.t1.annotations.tck.SomeAnnotation; - -class AnnotationValueTypeBehavior { - - @Test - void shouldGetBooleanAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithBooleanValueClass.class); - - then(annotation.booleanValue()).isTrue(); - } - - @Test - void shouldGetByteAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithByteValueClass.class); - - then(annotation.byteValue()).isEqualTo((byte) 1); - } - - @Test - void shouldGetCharAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithCharValueClass.class); - - then(annotation.charValue()).isEqualTo('a'); - } - - @Test - void shouldGetShortAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithShortValueClass.class); - - then(annotation.shortValue()).isEqualTo((short) 1234); - } - - @Test - void shouldGetIntAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithIntValueClass.class); - - then(annotation.intValue()).isEqualTo(42); - } - - @Test - void shouldGetLongAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithLongValueClass.class); - - then(annotation.longValue()).isEqualTo(44L); - } - - @Test - void shouldGetFloatAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithFloatValueClass.class); - - then(annotation.floatValue()).isEqualTo(1.2F); - } - - @Test - void shouldGetDoubleAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithDoubleValueClass.class); - - then(annotation.doubleValue()).isEqualTo(12.34); - } - - @Test - void shouldGetStringAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithStringValueClass.class); - - then(annotation.stringValue()).isEqualTo("foo"); - } - - @Test - void shouldGetEnumAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithEnumValueClass.class); - - then(annotation.enumValue()).isEqualTo(RUNTIME); - } - - @Test - void shouldGetClassAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithClassValueClass.class); - - then(annotation.classValue()).isEqualTo(String.class); - } - - @Test - void shouldGetAnnotationAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithAnnotationValueClass.class); - - then(annotation.annotationValue().value()).isEqualTo("annotation-value"); - } - - @Test - void shouldGetBooleanArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithBooleanArrayValueClass.class); - - then(annotation.booleanArrayValue()).contains(true, false); - } - - @Test - void shouldGetByteArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithByteArrayValueClass.class); - - then(annotation.byteArrayValue()).containsExactly((byte) 1, (byte) 2); - } - - @Test - void shouldGetCharArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithCharArrayValueClass.class); - - then(annotation.charArrayValue()).containsExactly('a', 'b'); - } - - @Test - void shouldGetShortArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithShortArrayValueClass.class); - - then(annotation.shortArrayValue()).containsExactly((short) 1234, (short) 1235); - } - - @Test - void shouldGetIntArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithIntArrayValueClass.class); - - then(annotation.intArrayValue()).containsExactly(42, 43); - } - - @Test - void shouldGetLongArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithLongArrayValueClass.class); - - then(annotation.longArrayValue()).containsExactly(44L, 45L); - } - - @Test - void shouldGetFloatArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithFloatArrayValueClass.class); - - then(annotation.floatArrayValue()).containsExactly(1.2F, 1.3F); - } - - @Test - void shouldGetDoubleArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithDoubleArrayValueClass.class); - - then(annotation.doubleArrayValue()).containsExactly(12.34, 12.35); - } - - @Test - void shouldGetStringArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithStringArrayValueClass.class); - - then(annotation.stringArrayValue()).containsExactly("foo", "bar"); - } - - @Test - void shouldGetEnumArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithEnumArrayValueClass.class); - - then(annotation.enumArrayValue()).containsExactly(RUNTIME, CLASS); - } - - @Test - void shouldGetClassArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation(AnnotatedWithClassArrayValueClass.class); - - then(annotation.classArrayValue()).containsExactly(String.class, Integer.class); - } - - @Test - void shouldGetAnnotationArrayAnnotationValue() { - DifferentValueTypesAnnotation annotation = getDifferentValueTypesAnnotation( - AnnotatedWithAnnotationArrayValueClass.class); - - then(Stream.of(annotation.annotationArrayValue()).map(SomeAnnotation::value)) - .containsExactly("annotation-value1", "annotation-value2"); - } - - private DifferentValueTypesAnnotation getDifferentValueTypesAnnotation(Class type) { - Annotations annotations = Annotations.on(type); - - Optional annotation = annotations.get(DifferentValueTypesAnnotation.class); - - assert annotation.isPresent(); - DifferentValueTypesAnnotation someAnnotation = annotation.get(); - then(someAnnotation.annotationType()).isEqualTo(DifferentValueTypesAnnotation.class); - return someAnnotation; - } -} diff --git a/power-annotations/tck/src/test/java/test/CombinedBehavior.java b/power-annotations/tck/src/test/java/test/CombinedBehavior.java deleted file mode 100644 index 84e4becef..000000000 --- a/power-annotations/tck/src/test/java/test/CombinedBehavior.java +++ /dev/null @@ -1,47 +0,0 @@ -package test; - -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.CombinedAnnotationClasses.SomeInheritingInterface; -import com.github.t1.annotations.tck.CombinedAnnotationClasses.SomeStereotypedClass; -import com.github.t1.annotations.tck.CombinedAnnotationClasses.SomeStereotypedInterface; -import com.github.t1.annotations.tck.SomeAnnotation; - -@TypeToMemberAnnotationsTestSuite -public class CombinedBehavior { - @Test - void shouldResolveInterfaceStereotypesBeforeTypeToMember() { - Annotations fooAnnotations = Annotations.onMethod(SomeStereotypedInterface.class, "foo"); - - Stream all = fooAnnotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")"); - } - - @Test - void shouldResolveClassStereotypesBeforeTypeToMember() { - Annotations fooAnnotations = Annotations.onMethod(SomeStereotypedClass.class, "foo"); - - Stream all = fooAnnotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")"); - } - - @Test - void shouldResolveInterfaceInheritedBeforeTypeToMember() { - Annotations fooAnnotations = Annotations.onMethod(SomeInheritingInterface.class, "foo"); - - Stream all = fooAnnotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-sub-interface\")"); - } -} diff --git a/power-annotations/tck/src/test/java/test/ContainingTypeBehavior.java b/power-annotations/tck/src/test/java/test/ContainingTypeBehavior.java deleted file mode 100644 index 7810b9891..000000000 --- a/power-annotations/tck/src/test/java/test/ContainingTypeBehavior.java +++ /dev/null @@ -1,159 +0,0 @@ -package test; - -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithAnnotationsOnClassAndField; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithAnnotationsOnClassAndMethod; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithField; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithMethod; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithRepeatableAnnotationOnClassAndField; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithRepeatableAnnotationOnClassAndMethod; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithRepeatedAnnotationsForField; -import com.github.t1.annotations.tck.ContainingTypeClasses.ClassWithRepeatedAnnotationsForMethod; -import com.github.t1.annotations.tck.ContainingTypeClasses.SomeAnnotationWithOnlyTypeTargetAnnotation; -import com.github.t1.annotations.tck.ContainingTypeClasses.SomeAnnotationWithoutTargetAnnotation; -import com.github.t1.annotations.tck.RepeatableAnnotation; -import com.github.t1.annotations.tck.SomeAnnotation; - -@TypeToMemberAnnotationsTestSuite -public class ContainingTypeBehavior { - @Nested - class FieldAnnotations { - Annotations fieldAnnotations = Annotations.onField(ClassWithField.class, "someField"); - - @Test - void shouldGetFieldAnnotationFromClass() { - Optional annotation = fieldAnnotations.get(SomeAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo("class-annotation"); - } - - @Test - void shouldNotGetFieldAnnotationWithoutTargetAnnotationFromClass() { - Optional annotation = fieldAnnotations - .get(SomeAnnotationWithoutTargetAnnotation.class); - - then(annotation).isEmpty(); - } - - @Test - void shouldNotGetFieldAnnotationWithOnlyTypeTargetAnnotationFromClass() { - Optional annotation = fieldAnnotations - .get(SomeAnnotationWithOnlyTypeTargetAnnotation.class); - - then(annotation).isEmpty(); - } - - @Test - void shouldNotGetAllFieldAnnotationFromClass() { - Optional annotation = fieldAnnotations.get(SomeAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo("class-annotation"); - } - - @Test - void shouldGetRepeatableFieldAnnotationFromClass() { - Annotations annotations = Annotations.onField(ClassWithRepeatedAnnotationsForField.class, "someField"); - - Stream annotation = annotations.all(RepeatableAnnotation.class); - - then(annotation.map(RepeatableAnnotation::value)).containsExactly(1, 2); - } - - @Test - void shouldGetMoreRepeatableFieldAnnotationsFromClass() { - Annotations annotations = Annotations.onField(ClassWithRepeatableAnnotationOnClassAndField.class, "someField"); - - Stream annotation = annotations.all(RepeatableAnnotation.class); - - then(annotation.map(RepeatableAnnotation::value)).containsExactly(1, 2); - } - - @Test - void shouldOnlyGetAllFieldAnnotationAndNotFromClass() { - Annotations annotations = Annotations.onField(ClassWithAnnotationsOnClassAndField.class, "someField"); - - Stream list = annotations.all(); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + SomeAnnotation.class.getName() + "(value = \"class-annotation\")"); - } - } - - @Nested - class MethodAnnotations { - Annotations methodAnnotations = Annotations.onMethod(ClassWithMethod.class, "someMethod"); - - @Test - void shouldGetMethodAnnotationFromClass() { - Optional annotation = methodAnnotations.get(SomeAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo("class-annotation"); - } - - @Test - void shouldNotGetMethodAnnotationWithoutTargetAnnotationFromClass() { - Optional annotation = methodAnnotations - .get(SomeAnnotationWithoutTargetAnnotation.class); - - then(annotation).isEmpty(); - } - - @Test - void shouldNotGetMethodAnnotationWithOnlyTypeTargetAnnotationFromClass() { - Optional annotation = methodAnnotations - .get(SomeAnnotationWithOnlyTypeTargetAnnotation.class); - - then(annotation).isEmpty(); - } - - @Test - void shouldNotGetAllMethodAnnotationFromClass() { - Optional annotation = methodAnnotations.get(SomeAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo("class-annotation"); - } - - @Test - void shouldGetRepeatableMethodAnnotationFromClass() { - Annotations annotations = Annotations.onMethod(ClassWithRepeatedAnnotationsForMethod.class, "someMethod"); - - Stream annotation = annotations.all(RepeatableAnnotation.class); - - then(annotation.map(RepeatableAnnotation::value)).containsExactly(1, 2); - } - - @Test - void shouldGetMoreRepeatableMethodAnnotationsFromClass() { - Annotations annotations = Annotations.onMethod(ClassWithRepeatableAnnotationOnClassAndMethod.class, "someMethod"); - - Stream annotation = annotations.all(RepeatableAnnotation.class); - - then(annotation.map(RepeatableAnnotation::value)).containsExactly(1, 2); - } - - @Test - void shouldGetAllMethodAndClassAnnotations() { - Annotations annotations = Annotations.onMethod(ClassWithAnnotationsOnClassAndMethod.class, "someMethod"); - - Stream list = annotations.all(); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + SomeAnnotation.class.getName() + "(value = \"class-annotation\")"); - } - } -} diff --git a/power-annotations/tck/src/test/java/test/DirectAnnotationsBehavior.java b/power-annotations/tck/src/test/java/test/DirectAnnotationsBehavior.java deleted file mode 100644 index 0b1383765..000000000 --- a/power-annotations/tck/src/test/java/test/DirectAnnotationsBehavior.java +++ /dev/null @@ -1,206 +0,0 @@ -package test; - -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Method; -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeAnnotatedClass; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeAnnotatedInterface; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeAnnotationWithDefaultValue; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeClassWithAnnotatedField; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeClassWithAnnotatedMethod; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeClassWithUnannotatedField; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeClassWithUnannotatedMethod; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeInterfaceWithAnnotatedMethod; -import com.github.t1.annotations.tck.DirectAnnotationClasses.SomeUnannotatedClass; -import com.github.t1.annotations.tck.MixinClasses.AnotherAnnotation; -import com.github.t1.annotations.tck.SomeAnnotation; - -public class DirectAnnotationsBehavior { - - @Nested - class ClassAnnotations { - @Test - void shouldGetNoClassAnnotation() { - Annotations annotations = Annotations.on(SomeUnannotatedClass.class); - - thenEmpty(annotations); - } - - @Test - void shouldGetClassAnnotation() { - Annotations annotations = Annotations.on(SomeAnnotatedClass.class); - - Optional annotation = annotations.get(SomeAnnotation.class); - - thenIsSomeAnnotation(annotation, "class-annotation"); - } - - @Test - void shouldGetInterfaceAnnotation() { - Annotations annotations = Annotations.on(SomeAnnotatedInterface.class); - - Optional annotation = annotations.get(SomeAnnotation.class); - - thenIsSomeAnnotation(annotation, "interface-annotation"); - } - - @Test - void shouldGetDefaultValueOfClassAnnotation() { - Annotations annotations = Annotations.on(SomeAnnotatedInterface.class); - - Optional annotation = annotations.get(SomeAnnotationWithDefaultValue.class); - - assert annotation.isPresent(); - SomeAnnotationWithDefaultValue someAnnotation = annotation.get(); - then(someAnnotation.annotationType()).isEqualTo(SomeAnnotationWithDefaultValue.class); - then(someAnnotation.valueWithDefault()).isEqualTo("default-value"); - then(someAnnotation).isNotSameAs(SomeAnnotatedInterface.class.getAnnotation(SomeAnnotation.class)); - } - - @Test - void shouldGetAllTypeAnnotations() { - Annotations annotations = Annotations.on(SomeAnnotatedInterface.class); - - Stream list = annotations.all(); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotationWithDefaultValue.class.getName(), - "@" + SomeAnnotation.class.getName() + "(value = \"interface-annotation\")"); - } - } - - @Nested - class FieldAnnotations { - @Test - void shouldGetNoFieldAnnotation() { - Annotations annotations = Annotations.onField(SomeClassWithUnannotatedField.class, "foo"); - - thenEmpty(annotations); - } - - @Test - void shouldFailToGetUnknownFieldAnnotation() { - Throwable throwable = catchThrowable(() -> Annotations.onField(SomeClassWithAnnotatedField.class, "bar")); - - then(throwable) - .isInstanceOf(RuntimeException.class) - .hasMessage("no field 'bar' in " + SomeClassWithAnnotatedField.class); // implementation detail? - } - - @Test - void shouldGetFieldAnnotation() { - Annotations annotations = Annotations.onField(SomeClassWithAnnotatedField.class, "foo"); - - Optional annotation = annotations.get(SomeAnnotation.class); - - thenIsSomeAnnotation(annotation, "field-annotation"); - } - } - - @Nested - class MethodAnnotations { - @Test - void shouldGetNoMethodAnnotation() { - Annotations annotations = Annotations.onMethod(SomeClassWithUnannotatedMethod.class, "foo", String.class); - - thenEmpty(annotations); - } - - @Test - void shouldGetMethodAnnotation() { - Annotations annotations = Annotations.onMethod(SomeClassWithAnnotatedMethod.class, "foo", String.class); - - Optional annotation = annotations.get(SomeAnnotation.class); - - thenIsSomeAnnotation(annotation, "method-annotation"); - } - - @Test - void shouldGetInterfaceMethodAnnotation() { - Annotations annotations = Annotations.onMethod(SomeInterfaceWithAnnotatedMethod.class, "foo", String.class); - - Optional annotation = annotations.get(SomeAnnotation.class); - - thenIsSomeAnnotation(annotation, "method-annotation"); - } - - @Test - void shouldGetAllMethodAnnotations() throws NoSuchMethodException { - Annotations annotations = Annotations.onMethod(SomeInterfaceWithAnnotatedMethod.class, "foo", String.class); - - Stream all = annotations.all(); - - // the parameter annotation must be there, but not represented as method annotation - then(fooMethod().getParameterAnnotations()[0][0].toString()) - .startsWith("@" + AnotherAnnotation.class.getName()); // `since` and `forRemoval` are JDK 9+ - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"method-annotation\")"); - } - - private Method fooMethod() throws NoSuchMethodException { - return SomeInterfaceWithAnnotatedMethod.class.getDeclaredMethod("foo", String.class); - } - - @Test - void shouldFailToGetAnnotationsFromUnknownMethodName() { - Throwable throwable = catchThrowable( - () -> Annotations.onMethod(SomeClassWithAnnotatedMethod.class, "bar", String.class)); - - then(throwable) - .isInstanceOf(RuntimeException.class) - .hasMessage("no method bar(java.lang.String) in " + SomeClassWithAnnotatedMethod.class); // implementation detail? - } - - @Test - void shouldFailToGetAnnotationsFromMethodWithTooManyArguments() { - Throwable throwable = catchThrowable(() -> Annotations.onMethod(SomeClassWithAnnotatedMethod.class, "foo")); - - then(throwable) - .isInstanceOf(RuntimeException.class) - .hasMessage("no method foo() in " + SomeClassWithAnnotatedMethod.class); // implementation detail? - } - - @Test - void shouldFailToGetAnnotationsFromMethodWithTooFewArguments() { - Throwable throwable = catchThrowable( - () -> Annotations.onMethod(SomeClassWithAnnotatedMethod.class, "foo", String.class, int.class)); - - then(throwable) - .isInstanceOf(RuntimeException.class) - .hasMessage("no method foo(java.lang.String, int) in " + SomeClassWithAnnotatedMethod.class); // implementation detail? - } - - @Test - void shouldFailToGetAnnotationsFromMethodWithWrongArgumentType() { - Throwable throwable = catchThrowable( - () -> Annotations.onMethod(SomeClassWithAnnotatedMethod.class, "foo", int.class)); - - then(throwable) - .isInstanceOf(RuntimeException.class) - .hasMessage("no method foo(int) in " + SomeClassWithAnnotatedMethod.class); // implementation detail? - } - } - - void thenEmpty(Annotations annotations) { - then(annotations.all()).isEmpty(); - then(annotations.get(SomeAnnotation.class)).isEmpty(); - } - - void thenIsSomeAnnotation( - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional annotation, - String expectedValue) { - assert annotation.isPresent(); - SomeAnnotation someAnnotation = annotation.get(); - then(someAnnotation.annotationType()).isEqualTo(SomeAnnotation.class); - then(someAnnotation.value()).isEqualTo(expectedValue); - } -} diff --git a/power-annotations/tck/src/test/java/test/InheritedAnnotationsTestSuite.java b/power-annotations/tck/src/test/java/test/InheritedAnnotationsTestSuite.java deleted file mode 100644 index e77a3c187..000000000 --- a/power-annotations/tck/src/test/java/test/InheritedAnnotationsTestSuite.java +++ /dev/null @@ -1,12 +0,0 @@ -package test; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; - -import org.junit.jupiter.api.Tag; - -@Tag("InheritedAnnotationsTestSuite") -@Retention(RUNTIME) -public @interface InheritedAnnotationsTestSuite { -} diff --git a/power-annotations/tck/src/test/java/test/InheritedBehavior.java b/power-annotations/tck/src/test/java/test/InheritedBehavior.java deleted file mode 100644 index 654074dcf..000000000 --- a/power-annotations/tck/src/test/java/test/InheritedBehavior.java +++ /dev/null @@ -1,95 +0,0 @@ -package test; - -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.InheritedAnnotationClasses.InheritingClass; -import com.github.t1.annotations.tck.InheritedAnnotationClasses.InheritingInterface; -import com.github.t1.annotations.tck.RepeatableAnnotation; -import com.github.t1.annotations.tck.SomeAnnotation; - -@InheritedAnnotationsTestSuite -public class InheritedBehavior { - - @Test - void shouldGetAllOnInterface() { - Annotations annotations = Annotations.on(InheritingInterface.class); - - Stream all = annotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"1\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 6)", - "@" + RepeatableAnnotation.class.getName() + "(value = 8)", - "@" + RepeatableAnnotation.class.getName() + "(value = 9)"); - } - - @Test - void shouldGetAllOnInterfaceMethod() { - Annotations annotations = Annotations.onMethod(InheritingInterface.class, "method"); - - Stream all = annotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"10\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 6)", - "@" + RepeatableAnnotation.class.getName() + "(value = 8)", - "@" + RepeatableAnnotation.class.getName() + "(value = 9)", - "@" + RepeatableAnnotation.class.getName() + "(value = 10)"); - } - - @Test - void shouldGetAllOnClass() { - Annotations annotations = Annotations.on(InheritingClass.class); - - Stream all = annotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"2\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 3)", - "@" + RepeatableAnnotation.class.getName() + "(value = 6)", - "@" + RepeatableAnnotation.class.getName() + "(value = 8)", - "@" + RepeatableAnnotation.class.getName() + "(value = 9)"); - } - - @Test - void shouldGetAllOnField() { - Annotations annotations = Annotations.onField(InheritingClass.class, "field"); - - Stream all = annotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"4\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 3)", - "@" + RepeatableAnnotation.class.getName() + "(value = 4)", - "@" + RepeatableAnnotation.class.getName() + "(value = 6)", - "@" + RepeatableAnnotation.class.getName() + "(value = 8)", - "@" + RepeatableAnnotation.class.getName() + "(value = 9)"); - } - - @Test - void shouldGetAllOnClassMethod() { - Annotations annotations = Annotations.onMethod(InheritingClass.class, "method"); - - Stream all = annotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"5\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 3)", - "@" + RepeatableAnnotation.class.getName() + "(value = 5)", - "@" + RepeatableAnnotation.class.getName() + "(value = 6)", - "@" + RepeatableAnnotation.class.getName() + "(value = 8)", - "@" + RepeatableAnnotation.class.getName() + "(value = 10)", - "@" + RepeatableAnnotation.class.getName() + "(value = 9)"); - } -} diff --git a/power-annotations/tck/src/test/java/test/MixinBehavior.java b/power-annotations/tck/src/test/java/test/MixinBehavior.java deleted file mode 100644 index 07037db29..000000000 --- a/power-annotations/tck/src/test/java/test/MixinBehavior.java +++ /dev/null @@ -1,380 +0,0 @@ -package test; - -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.AmbiguousAnnotationResolutionException; -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedFieldMixinClasses.SomeClassWithFieldWithVariousAnnotations; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedFieldMixinClasses.TargetFieldClassWithTwoMixins; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedFieldMixinClasses.TargetFieldClassWithTwoNonRepeatableMixins; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedFieldMixinClasses.TargetFieldClassWithTwoRepeatableMixins; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedMethodMixinClasses.SomeClassWithMethodWithVariousAnnotations; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedMethodMixinClasses.TargetMethodClassWithTwoMixins; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedMethodMixinClasses.TargetMethodClassWithTwoNonRepeatableMixins; -import com.github.t1.annotations.tck.MixinClasses.AnnotatedMethodMixinClasses.TargetMethodClassWithTwoRepeatableMixins; -import com.github.t1.annotations.tck.MixinClasses.AnnotationMixinClasses.ClassWithAnnotationsExtendedByMixIn; -import com.github.t1.annotations.tck.MixinClasses.AnnotationMixinClasses.DirectAnnotation; -import com.github.t1.annotations.tck.MixinClasses.AnnotationMixinClasses.MixedInAnnotation; -import com.github.t1.annotations.tck.MixinClasses.AnotherAnnotation; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.OriginalAnnotatedTarget; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.SomeAnnotationTargetedByMixin; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.SomeAnnotationWithoutValue; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.SomeClassWithAnnotationTargetedByMixin; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.SomeClassWithVariousAnnotations; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.TargetClassWithTwoMixins; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.TargetClassWithTwoNonRepeatableMixins; -import com.github.t1.annotations.tck.MixinClasses.TypeAnnotationMixinClasses.TargetClassWithTwoRepeatableMixins; -import com.github.t1.annotations.tck.RepeatableAnnotation; -import com.github.t1.annotations.tck.SomeAnnotation; - -public class MixinBehavior { - - @Nested - class ClassAnnotations { - Annotations annotations = Annotations.on(SomeClassWithVariousAnnotations.class); - - @Test - void shouldGetTargetClassAnnotation() { - Optional annotation = annotations.get(SomeAnnotationWithoutValue.class); - - then(annotation).isPresent(); - } - - @Test - void shouldGetMixinClassAnnotation() { - Optional annotation = annotations.get(AnotherAnnotation.class); - - then(annotation).isPresent(); - } - - @Test - void shouldGetReplacedClassAnnotation() { - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("replacing"); - } - - @Test - void shouldFailToGetRepeatedClassAnnotation() { - Throwable throwable = catchThrowable(() -> annotations.get(RepeatableAnnotation.class)); - - then(throwable).isInstanceOf(AmbiguousAnnotationResolutionException.class); - } - - @Test - void shouldGetAllClassAnnotations() { - Stream list = annotations.all(); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + SomeAnnotation.class.getName() + "(value = \"replacing\")", - "@" + AnotherAnnotation.class.getName(), - "@" + SomeAnnotationWithoutValue.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllRepeatableClassAnnotations() { - Stream list = annotations.all(RepeatableAnnotation.class); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - Annotations annotationsFromAnnotationTargetedByMixin = Annotations.on(SomeClassWithAnnotationTargetedByMixin.class); - - @Test - void shouldGetMixedInAnnotation() { - Optional someAnnotation = annotationsFromAnnotationTargetedByMixin.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("annotation-mixin"); - } - - @Test - void shouldGetAllNonRepeatableMixedInAnnotations() { - Stream someAnnotation = annotationsFromAnnotationTargetedByMixin.all(SomeAnnotation.class); - - then(someAnnotation.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"annotation-mixin\")"); - } - - @Test - void shouldGetAllRepeatableMixedInAnnotations() { - Stream repeatableAnnotations = annotationsFromAnnotationTargetedByMixin - .all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllMixedInAnnotation() { - Stream all = annotationsFromAnnotationTargetedByMixin.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotationTargetedByMixin.class.getName(), - "@" + SomeAnnotation.class.getName() + "(value = \"annotation-mixin\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldOverwriteAnnotationWithAnnotationMixedIn() { - Annotations annotations = Annotations.on(OriginalAnnotatedTarget.class); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("annotation-mixin"); - } - - @Test - void shouldGetClassAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.on(TargetClassWithTwoMixins.class); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("one"); - } - - @Test - void shouldGetOneOfDuplicateNonRepeatableClassAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.on(TargetClassWithTwoNonRepeatableMixins.class); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isIn("two", "three"); - } - - @Test - void shouldFailToGetDuplicateRepeatableClassAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.on(TargetClassWithTwoRepeatableMixins.class); - - Throwable throwable = catchThrowable(() -> annotations.get(RepeatableAnnotation.class)); - - then(throwable).isInstanceOf(AmbiguousAnnotationResolutionException.class); - } - } - - @Nested - class FieldAnnotations { - Annotations annotations = Annotations.onField(SomeClassWithFieldWithVariousAnnotations.class, "foo"); - - @Test - void shouldSkipUndefinedMixinFieldAnnotation() { - Annotations annotations = Annotations.onField(SomeClassWithFieldWithVariousAnnotations.class, "bar"); - - Optional someAnnotationWithoutValue = annotations.get(SomeAnnotationWithoutValue.class); - - then(someAnnotationWithoutValue).isNotPresent(); - } - - @Test - void shouldGetTargetFieldAnnotation() { - Optional someAnnotationWithoutValue = annotations.get(SomeAnnotationWithoutValue.class); - - then(someAnnotationWithoutValue).isPresent(); - } - - @Test - void shouldGetMixinFieldAnnotation() { - Optional anotherAnnotation = annotations.get(AnotherAnnotation.class); - - then(anotherAnnotation).isPresent(); - } - - @Test - void shouldGetReplacedFieldAnnotation() { - Optional annotation = annotations.get(SomeAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo("replacing"); - } - - @Test - void shouldFailToGetRepeatableFieldAnnotation() { - Throwable throwable = catchThrowable(() -> annotations.get(RepeatableAnnotation.class)); - - then(throwable).isInstanceOf(AmbiguousAnnotationResolutionException.class); - } - - @Test - void shouldGetAllFieldAnnotations() { - Stream list = annotations.all(); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + AnotherAnnotation.class.getName(), - "@" + SomeAnnotationWithoutValue.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + SomeAnnotation.class.getName() + "(value = \"replacing\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllRepeatableFieldAnnotations() { - Stream list = annotations.all(RepeatableAnnotation.class); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetOneOfDuplicateFieldAnnotationsFromMultipleMixins() { - Annotations annotations = Annotations.onField(TargetFieldClassWithTwoMixins.class, "foo"); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("four"); - } - - @Test - void shouldGetOneRepeatableFieldAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.onField(TargetFieldClassWithTwoNonRepeatableMixins.class, "foo"); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isIn("five", "six"); - } - - @Test - void shouldFailToGetDuplicateRepeatableFieldAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.onField(TargetFieldClassWithTwoRepeatableMixins.class, "foo"); - - Throwable throwable = catchThrowable(() -> annotations.get(RepeatableAnnotation.class)); - - then(throwable).isInstanceOf(AmbiguousAnnotationResolutionException.class); - } - - @Test - void shouldMixIntoAnnotationUsedOnField() { - Annotations annotations = Annotations.onField(ClassWithAnnotationsExtendedByMixIn.class, "field"); - - then(annotations.get(DirectAnnotation.class)).isPresent(); - then(annotations.get(MixedInAnnotation.class)).isPresent(); - } - - // TODO test unknown field mixin - } - - @Nested - class MethodAnnotations { - Annotations annotations = Annotations.onMethod(SomeClassWithMethodWithVariousAnnotations.class, "foo"); - - @Test - void shouldSkipUndefinedMixinMethodAnnotation() { - Annotations annotations = Annotations.onMethod(SomeClassWithMethodWithVariousAnnotations.class, "bar"); - - Optional someAnnotationWithoutValue = annotations.get(SomeAnnotationWithoutValue.class); - - then(someAnnotationWithoutValue).isNotPresent(); - } - - @Test - void shouldGetTargetMethodAnnotation() { - Optional someAnnotationWithoutValue = annotations.get(SomeAnnotationWithoutValue.class); - - then(someAnnotationWithoutValue).isPresent(); - } - - @Test - void shouldGetMixinMethodAnnotation() { - Optional anotherAnnotation = annotations.get(AnotherAnnotation.class); - - then(anotherAnnotation).isPresent(); - } - - @Test - void shouldGetReplacedMethodAnnotation() { - Optional annotation = annotations.get(SomeAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo("replacing"); - } - - @Test - void shouldFailToGetRepeatableMethodAnnotation() { - Throwable throwable = catchThrowable(() -> annotations.get(RepeatableAnnotation.class)); - - then(throwable).isInstanceOf(AmbiguousAnnotationResolutionException.class); - } - - @Test - void shouldGetAllMethodAnnotations() { - Stream list = annotations.all(); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + AnotherAnnotation.class.getName(), - "@" + SomeAnnotationWithoutValue.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + SomeAnnotation.class.getName() + "(value = \"replacing\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllRepeatableMethodAnnotations() { - Stream list = annotations.all(RepeatableAnnotation.class); - - then(list.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetMethodAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.onMethod(TargetMethodClassWithTwoMixins.class, "foo"); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("seven"); - } - - @Test - void shouldGetOneOfDuplicateNonRepeatableMethodAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.onMethod(TargetMethodClassWithTwoNonRepeatableMixins.class, "foo"); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isIn("eight", "nine"); - } - - @Test - void shouldFailToGetDuplicateRepeatableMethodAnnotationFromMultipleMixins() { - Annotations annotations = Annotations.onMethod(TargetMethodClassWithTwoRepeatableMixins.class, "foo"); - - Throwable throwable = catchThrowable(() -> annotations.get(RepeatableAnnotation.class)); - - then(throwable).isInstanceOf(AmbiguousAnnotationResolutionException.class); - } - - @Test - void shouldMixIntoAnnotationUsedOnMethod() { - Annotations annotations = Annotations.onMethod(ClassWithAnnotationsExtendedByMixIn.class, "method"); - - then(annotations.get(DirectAnnotation.class)).isPresent(); - then(annotations.get(MixedInAnnotation.class)).isPresent(); - } - - // TODO constructor mixins - // TODO parameter mixins - // TODO test unknown method mixin (name or args) - } -} diff --git a/power-annotations/tck/src/test/java/test/RepeatableAnnotationBehavior.java b/power-annotations/tck/src/test/java/test/RepeatableAnnotationBehavior.java deleted file mode 100644 index d4bbda0e3..000000000 --- a/power-annotations/tck/src/test/java/test/RepeatableAnnotationBehavior.java +++ /dev/null @@ -1,147 +0,0 @@ -package test; - -import static org.assertj.core.api.Assertions.catchThrowable; -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.AmbiguousAnnotationResolutionException; -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.RepeatableAnnotation; -import com.github.t1.annotations.tck.RepeatableAnnotationClasses.RepeatedAnnotationClass; -import com.github.t1.annotations.tck.RepeatableAnnotationClasses.UnrepeatedAnnotationClass; - -/** - * Actually tests how the Annotations utils resolve repeatable annotations, not the power annotations implementation, - * but this is a prerequisite for many other tests. - */ -public class RepeatableAnnotationBehavior { - - @Test - void shouldGetSingleRepeatedClassAnnotation() { - Annotations annotations = Annotations.on(UnrepeatedAnnotationClass.class); - - Optional annotation = annotations.get(RepeatableAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo(1); - } - - @Test - void shouldGetSingleRepeatedFieldAnnotation() { - Annotations annotations = Annotations.onField(UnrepeatedAnnotationClass.class, "foo"); - - Optional annotation = annotations.get(RepeatableAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo(10); - } - - @Test - void shouldGetSingleRepeatedMethodAnnotation() { - Annotations annotations = Annotations.onMethod(UnrepeatedAnnotationClass.class, "bar"); - - Optional annotation = annotations.get(RepeatableAnnotation.class); - - assert annotation.isPresent(); - then(annotation.get().value()).isEqualTo(20); - } - - @Nested - class RepeatedClassAnnotationBehavior { - Annotations repeatedAnnotations = Annotations.on(RepeatedAnnotationClass.class); - - @Test - void shouldFailToGetRepeatingAnnotation() { - Throwable throwable = catchThrowable(() -> repeatedAnnotations.get(RepeatableAnnotation.class)); - - then(throwable) - .isInstanceOf(AmbiguousAnnotationResolutionException.class) - // TODO message detail about the target .hasMessageContaining(SomeClass.class.getName()) - .hasMessageContaining(RepeatableAnnotation.class.getName()); - } - - @Test - void shouldGetAll() { - Stream all = repeatedAnnotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetTypedAll() { - Stream all = repeatedAnnotations.all(RepeatableAnnotation.class); - - then(all.map(RepeatableAnnotation::value)).containsExactlyInAnyOrder(1, 2); - } - } - - @Nested - class RepeatedFieldAnnotationBehavior { - Annotations repeatedAnnotations = Annotations.onField(RepeatedAnnotationClass.class, "foo"); - - @Test - void shouldFailToGetRepeatingAnnotation() { - Throwable throwable = catchThrowable(() -> repeatedAnnotations.get(RepeatableAnnotation.class)); - - then(throwable) - .isInstanceOf(AmbiguousAnnotationResolutionException.class) - // TODO message detail about the target .hasMessageContaining(SomeClass.class.getName()) - .hasMessageContaining(RepeatableAnnotation.class.getName()); - } - - @Test - void shouldGetAll() { - Stream all = repeatedAnnotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 11)", - "@" + RepeatableAnnotation.class.getName() + "(value = 12)"); - } - - @Test - void shouldGetTypedAll() { - Stream all = repeatedAnnotations.all(RepeatableAnnotation.class); - - then(all.map(RepeatableAnnotation::value)).containsExactlyInAnyOrder(11, 12); - } - } - - @Nested - class RepeatedMethodAnnotationBehavior { - Annotations repeatedAnnotations = Annotations.onMethod(RepeatedAnnotationClass.class, "bar"); - - @Test - void shouldFailToGetRepeatingAnnotation() { - Throwable throwable = catchThrowable(() -> repeatedAnnotations.get(RepeatableAnnotation.class)); - - then(throwable) - .isInstanceOf(AmbiguousAnnotationResolutionException.class) - // TODO message detail about the target .hasMessageContaining(SomeClass.class.getName()) - .hasMessageContaining(RepeatableAnnotation.class.getName()); - } - - @Test - void shouldGetAll() { - Stream all = repeatedAnnotations.all(); - - then(all.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 21)", - "@" + RepeatableAnnotation.class.getName() + "(value = 22)"); - } - - @Test - void shouldGetTypedAll() { - Stream all = repeatedAnnotations.all(RepeatableAnnotation.class); - - then(all.map(RepeatableAnnotation::value)).containsExactlyInAnyOrder(21, 22); - } - } -} diff --git a/power-annotations/tck/src/test/java/test/StereotypeBehavior.java b/power-annotations/tck/src/test/java/test/StereotypeBehavior.java deleted file mode 100644 index dec416abc..000000000 --- a/power-annotations/tck/src/test/java/test/StereotypeBehavior.java +++ /dev/null @@ -1,382 +0,0 @@ -package test; - -import static java.util.stream.Collectors.toList; -import static org.assertj.core.api.BDDAssertions.then; - -import java.lang.annotation.Annotation; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Stream; - -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; - -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.tck.MixinClasses.AnotherAnnotation; -import com.github.t1.annotations.tck.RepeatableAnnotation; -import com.github.t1.annotations.tck.SomeAnnotation; -import com.github.t1.annotations.tck.StereotypeClasses.AnotherStereotype; -import com.github.t1.annotations.tck.StereotypeClasses.ClassWithStereotypedField; -import com.github.t1.annotations.tck.StereotypeClasses.ClassWithStereotypedMethod; -import com.github.t1.annotations.tck.StereotypeClasses.DoubleIndirectlyStereotypedClass; -import com.github.t1.annotations.tck.StereotypeClasses.DoubleStereotypedClass; -import com.github.t1.annotations.tck.StereotypeClasses.IndirectlyStereotypedClass; -import com.github.t1.annotations.tck.StereotypeClasses.MergeOneRepeatableAnnotationIntoOne; -import com.github.t1.annotations.tck.StereotypeClasses.MergeOneRepeatableAnnotationIntoTwo; -import com.github.t1.annotations.tck.StereotypeClasses.MergeRepeatableAnnotationFromOneAndOne; -import com.github.t1.annotations.tck.StereotypeClasses.MergeRepeatableAnnotationFromOneAndTwo; -import com.github.t1.annotations.tck.StereotypeClasses.MergeRepeatableAnnotationFromTwoAndOne; -import com.github.t1.annotations.tck.StereotypeClasses.MergeRepeatableAnnotationFromTwoAndTwo; -import com.github.t1.annotations.tck.StereotypeClasses.MergeThreeRepeatableAnnotationIntoThree; -import com.github.t1.annotations.tck.StereotypeClasses.MergeTwoRepeatableAnnotationIntoOne; -import com.github.t1.annotations.tck.StereotypeClasses.MergeTwoRepeatableAnnotationIntoTwo; -import com.github.t1.annotations.tck.StereotypeClasses.SomeDoubleIndirectedStereotype; -import com.github.t1.annotations.tck.StereotypeClasses.SomeIndirectedStereotype; -import com.github.t1.annotations.tck.StereotypeClasses.SomeStereotype; -import com.github.t1.annotations.tck.StereotypeClasses.SomeTardyIndirectedStereotype; -import com.github.t1.annotations.tck.StereotypeClasses.StereotypedClass; -import com.github.t1.annotations.tck.StereotypeClasses.StereotypedClassWithSomeAnnotation; -import com.github.t1.annotations.tck.StereotypeClasses.TardyIndirectlyStereotypedClass; - -public class StereotypeBehavior { - - @Nested - class StereotypedClasses { - Annotations annotations = Annotations.on(StereotypedClass.class); - - @Test - void shouldGetAnnotationFromClassStereotype() { - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("from-stereotype"); - } - - @Test - void shouldGetAllAnnotationsFromClassStereotype() { - Stream someAnnotation = annotations.all(); - - then(someAnnotation.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 5)", - "@" + AnotherAnnotation.class.getName(), - "@" + SomeStereotype.class.getName(), - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllNonRepeatableAnnotationsFromClassStereotype() { - Stream someAnnotation = annotations.all(SomeAnnotation.class); - - then(someAnnotation.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")"); - } - - @Test - void shouldGetAllRepeatableAnnotationFromClassStereotype() { - Stream someAnnotation = annotations.all(RepeatableAnnotation.class); - - then(someAnnotation.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 5)", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllFromIndirectClassStereotype() { - Annotations annotations = Annotations.on(IndirectlyStereotypedClass.class); - - Stream all = annotations.all(); - - then(all.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")", - "@" + AnotherAnnotation.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + SomeStereotype.class.getName(), - "@" + SomeIndirectedStereotype.class.getName()); - } - - @Test - void shouldGetAllFromIndirectClassStereotypeResolvedAlphabeticallyAfterSomeStereotype() { - Annotations annotations = Annotations.on(TardyIndirectlyStereotypedClass.class); - - Stream all = annotations.all(); - - then(all.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")", - "@" + AnotherAnnotation.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + SomeStereotype.class.getName(), - "@" + SomeTardyIndirectedStereotype.class.getName()); - } - - @Test - void shouldGetAllFromDoubleIndirectClassStereotype() { - Annotations annotations = Annotations.on(DoubleIndirectlyStereotypedClass.class); - - Stream all = annotations.all(); - - then(all.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")", - "@" + AnotherAnnotation.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + SomeStereotype.class.getName(), - "@" + SomeIndirectedStereotype.class.getName(), - "@" + SomeDoubleIndirectedStereotype.class.getName()); - } - - @Test - void shouldNotReplaceClassAnnotationWithStereotypedNonRepeatableAnnotation() { - Annotations annotations = Annotations.on(StereotypedClassWithSomeAnnotation.class); - - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("on-class"); - } - } - - @Nested - class DoubleStereotypedClasses { - Annotations annotations = Annotations.on(DoubleStereotypedClass.class); - - @Test - void shouldGetFirstOfAmbiguousAnnotationFromTwoStereotypes() { - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isIn( // both are allowed: - "from-stereotype", - "from-another-stereotype"); - } - - @Test - void shouldGetAllNonRepeatableAnnotationsFromTwoStereotypes() { - Stream someAnnotations = annotations.all(SomeAnnotation.class); - - then(someAnnotations.map(Objects::toString)).containsAnyOf( // both are allowed: - "@" + SomeAnnotation.class.getName() + "(value = \"from-stereotype\")", - "@" + SomeAnnotation.class.getName() + "(value = \"from-another-stereotype\")"); - } - } - - @Nested - class StereotypeMerging { - @Test - void shouldMergeRepeatableAnnotationFromOneAndOne() { - Annotations annotations = Annotations.on(MergeRepeatableAnnotationFromOneAndOne.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 11)"); - } - - @Test - void shouldMergeRepeatableAnnotationFromOneAndTwo() { - Annotations annotations = Annotations.on(MergeRepeatableAnnotationFromOneAndTwo.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 11)", - "@" + RepeatableAnnotation.class.getName() + "(value = 12)"); - } - - @Test - void shouldMergeRepeatableAnnotationFromTwoAndOne() { - Annotations annotations = Annotations.on(MergeRepeatableAnnotationFromTwoAndOne.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 11)"); - } - - @Test - void shouldMergeRepeatableAnnotationFromTwoAndTwo() { - Annotations annotations = Annotations.on(MergeRepeatableAnnotationFromTwoAndTwo.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 11)", - "@" + RepeatableAnnotation.class.getName() + "(value = 12)"); - } - - @Test - void shouldMergeOneRepeatableAnnotationIntoOne() { - Annotations annotations = Annotations.on(MergeOneRepeatableAnnotationIntoOne.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldMergeOneRepeatableAnnotationIntoTwo() { - Annotations annotations = Annotations.on(MergeOneRepeatableAnnotationIntoTwo.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 21)", - "@" + RepeatableAnnotation.class.getName() + "(value = 22)"); - } - - @Test - void shouldMergeTwoRepeatableAnnotationIntoOne() { - Annotations annotations = Annotations.on(MergeTwoRepeatableAnnotationIntoOne.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 21)"); - } - - @Test - void shouldMergeTwoRepeatableAnnotationIntoTwo() { - Annotations annotations = Annotations.on(MergeTwoRepeatableAnnotationIntoTwo.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 21)", - "@" + RepeatableAnnotation.class.getName() + "(value = 22)"); - } - - @Test - void shouldMergeThreeRepeatableAnnotationIntoThree() { - Annotations annotations = Annotations.on(MergeThreeRepeatableAnnotationIntoThree.class); - - Stream repeatableAnnotations = annotations.all(RepeatableAnnotation.class); - - then(repeatableAnnotations.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 3)", - "@" + RepeatableAnnotation.class.getName() + "(value = 21)", - "@" + RepeatableAnnotation.class.getName() + "(value = 22)", - "@" + RepeatableAnnotation.class.getName() + "(value = 23)"); - } - - @Test - void shouldGetAllAnnotationsFromTwoStereotypes() { - Annotations annotations = Annotations.on(DoubleStereotypedClass.class); - - Stream all = annotations.all(); - - List list = all.map(Objects::toString).collect(toList()); - then(list).containsExactlyInAnyOrder( - "@" + SomeStereotype.class.getName(), - "@" + AnotherStereotype.class.getName(), - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)", - "@" + RepeatableAnnotation.class.getName() + "(value = 6)", - "@" + AnotherAnnotation.class.getName(), - "@" + SomeAnnotation.class.getName() + "(value = \"from-another-stereotype\")"); - } - } - - @Nested - class StereotypedFields { - Annotations annotations = Annotations.onField(ClassWithStereotypedField.class, "foo"); - - @Test - void shouldGetAnnotationFromFieldStereotype() { - Optional someAnnotation = annotations.get(AnotherAnnotation.class); - - assert someAnnotation.isPresent(); - } - - @Test - void shouldNotReplaceFieldAnnotationWithStereotypedNonRepeatableAnnotation() { - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("on-field"); - } - - @Test - void shouldGetAllAnnotationsFromFieldStereotype() { - Stream someAnnotation = annotations.all(); - - then(someAnnotation.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 7)", - "@" + AnotherAnnotation.class.getName(), - "@" + SomeStereotype.class.getName(), - "@" + SomeAnnotation.class.getName() + "(value = \"on-field\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllAnnotationNonRepeatableTypedFromFieldStereotype() { - Stream someAnnotation = annotations.all(SomeAnnotation.class); - - then(someAnnotation.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"on-field\")"); - } - } - - @Nested - class StereotypedMethods { - Annotations annotations = Annotations.onMethod(ClassWithStereotypedMethod.class, "foo"); - - @Test - void shouldGetAnnotationFromMethodStereotype() { - Optional someAnnotation = annotations.get(AnotherAnnotation.class); - - assert someAnnotation.isPresent(); - } - - @Test - void shouldNotReplaceMethodAnnotationWithStereotypedNonRepeatableAnnotation() { - Optional someAnnotation = annotations.get(SomeAnnotation.class); - - assert someAnnotation.isPresent(); - then(someAnnotation.get().value()).isEqualTo("on-method"); - } - - @Test - void shouldGetAllAnnotationsFromMethodStereotype() { - Stream someAnnotation = annotations.all(); - - then(someAnnotation.map(Object::toString)).containsExactlyInAnyOrder( - "@" + RepeatableAnnotation.class.getName() + "(value = 7)", - "@" + AnotherAnnotation.class.getName(), - "@" + SomeStereotype.class.getName(), - "@" + SomeAnnotation.class.getName() + "(value = \"on-method\")", - "@" + RepeatableAnnotation.class.getName() + "(value = 1)", - "@" + RepeatableAnnotation.class.getName() + "(value = 2)"); - } - - @Test - void shouldGetAllAnnotationNonRepeatableTypedFromMethodStereotype() { - Stream someAnnotation = annotations.all(SomeAnnotation.class); - - then(someAnnotation.map(Objects::toString)).containsExactlyInAnyOrder( - "@" + SomeAnnotation.class.getName() + "(value = \"on-method\")"); - } - } - - // TODO parameter stereotypes -} diff --git a/power-annotations/tck/src/test/java/test/TypeToMemberAnnotationsTestSuite.java b/power-annotations/tck/src/test/java/test/TypeToMemberAnnotationsTestSuite.java deleted file mode 100644 index 9968b67de..000000000 --- a/power-annotations/tck/src/test/java/test/TypeToMemberAnnotationsTestSuite.java +++ /dev/null @@ -1,12 +0,0 @@ -package test; - -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; - -import org.junit.jupiter.api.Tag; - -@Tag("TypeToMemberAnnotationsTestSuite") -@Retention(RUNTIME) -public @interface TypeToMemberAnnotationsTestSuite { -} diff --git a/power-annotations/utils/api/pom.xml b/power-annotations/utils/api/pom.xml deleted file mode 100644 index a29014ac0..000000000 --- a/power-annotations/utils/api/pom.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - 4.0.0 - - io.smallrye - smallrye-power-annotations-utils-parent - 1.6.1-SNAPSHOT - - - smallrye-power-annotations-utils-api - Power Annotations Utils API - The Utils API for working with annotations. Used by the TCK. - diff --git a/power-annotations/utils/api/src/main/java/com/github/t1/annotations/AmbiguousAnnotationResolutionException.java b/power-annotations/utils/api/src/main/java/com/github/t1/annotations/AmbiguousAnnotationResolutionException.java deleted file mode 100644 index 0a1e4c595..000000000 --- a/power-annotations/utils/api/src/main/java/com/github/t1/annotations/AmbiguousAnnotationResolutionException.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.github.t1.annotations; - -/** - * @see Annotations#get(Class) - */ -@SuppressWarnings("unused") -public class AmbiguousAnnotationResolutionException extends RuntimeException { - public AmbiguousAnnotationResolutionException() { - } - - public AmbiguousAnnotationResolutionException(String message) { - super(message); - } - - public AmbiguousAnnotationResolutionException(String message, Throwable cause) { - super(message, cause); - } - - public AmbiguousAnnotationResolutionException(Throwable cause) { - super(cause); - } - - public AmbiguousAnnotationResolutionException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/power-annotations/utils/api/src/main/java/com/github/t1/annotations/Annotations.java b/power-annotations/utils/api/src/main/java/com/github/t1/annotations/Annotations.java deleted file mode 100644 index 7d8460357..000000000 --- a/power-annotations/utils/api/src/main/java/com/github/t1/annotations/Annotations.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.github.t1.annotations; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Optional; -import java.util.stream.Stream; - -public interface Annotations { - static Annotations on(Class type) { - return AnnotationsLoader.INSTANCE.onType(type); - } - - static Annotations on(Field field) { - return onField(field.getDeclaringClass(), field.getName()); - } - - static Annotations onField(Class type, String fieldName) { - return AnnotationsLoader.INSTANCE.onField(type, fieldName); - } - - static Annotations on(Method method) { - return onMethod(method.getDeclaringClass(), method.getName(), method.getParameterTypes()); - } - - static Annotations onMethod(Class type, String methodName, Class... argTypes) { - return AnnotationsLoader.INSTANCE.onMethod(type, methodName, argTypes); - } - - /** - * Get all {@link Annotation} instances. - * If the annotation type is {@link java.lang.annotation.Repeatable}, the same type - * can show up several times, eventually with different properties. - */ - Stream all(); - - /** - * Get the 'strongest' {@link Annotation} instance of this type. - * Multiple annotations may be applicable, e.g. from several mixins or stereotypes. - * The annotation will be picked in this order: - *
    - *
  1. mixin
  2. - *
  3. target
  4. - *
  5. target stereotypes
  6. - *
  7. containing class
  8. - *
  9. containing class stereotypes
  10. - *
  11. containing package (TODO not yet implemented)
  12. - *
  13. containing package stereotypes (TODO not yet implemented)
  14. - *
- * If this order not sufficiently defined, e.g. because there are multiple repeatable annotations, - * or because there are multiple mixins or stereotypes with the same annotation, - * an {@link AmbiguousAnnotationResolutionException} is thrown. I.e. when an annotation is changed - * to be repeatable, all frameworks using this annotation will have to use {@link #all(Class)} instead - * (of course), but the semantics for the client code changes, which may break existing code. - */ - Optional get(Class type); - - /** - * Get all (eventually {@link java.lang.annotation.Repeatable repeatable}) - * {@link Annotation} instances of this type. - */ - Stream all(Class type); -} diff --git a/power-annotations/utils/api/src/main/java/com/github/t1/annotations/AnnotationsLoader.java b/power-annotations/utils/api/src/main/java/com/github/t1/annotations/AnnotationsLoader.java deleted file mode 100644 index 4e4b2f3be..000000000 --- a/power-annotations/utils/api/src/main/java/com/github/t1/annotations/AnnotationsLoader.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.github.t1.annotations; - -import java.util.Iterator; -import java.util.ServiceConfigurationError; -import java.util.ServiceLoader; - -/** - * SPI + Singleton for loading the implementation - */ -public abstract class AnnotationsLoader { - static final AnnotationsLoader INSTANCE = load(); - - private static AnnotationsLoader load() { - ServiceLoader loader = ServiceLoader.load(AnnotationsLoader.class); - Iterator iterator = loader.iterator(); - if (!iterator.hasNext()) - throw new ServiceConfigurationError("no " + AnnotationsLoader.class.getName() + " in classpath"); - AnnotationsLoader graphQlClientBuilder = iterator.next(); - if (iterator.hasNext()) - throw new ServiceConfigurationError("more than one " + AnnotationsLoader.class.getName() + " in classpath"); - return graphQlClientBuilder; - } - - public abstract Annotations onType(Class type); - - public abstract Annotations onField(Class type, String fieldName); - - public abstract Annotations onMethod(Class type, String methodName, Class... argTypes); -} diff --git a/power-annotations/utils/jandex/pom.xml b/power-annotations/utils/jandex/pom.xml deleted file mode 100644 index 8e5252041..000000000 --- a/power-annotations/utils/jandex/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-utils-parent - 1.6.1-SNAPSHOT - - - smallrye-power-annotations-utils-jandex - Power Annotations Utils Impl for Jandex - Implementation of the utils for working with annotations base od Jandex. - - - - io.smallrye - smallrye-power-annotations-utils-api - ${project.version} - - - io.smallrye - power-annotations-scanner - ${project.version} - - - diff --git a/power-annotations/utils/jandex/src/main/java/com/github/t1/powerannotations/utils/jandex/AnnotationProxy.java b/power-annotations/utils/jandex/src/main/java/com/github/t1/powerannotations/utils/jandex/AnnotationProxy.java deleted file mode 100644 index c03dfaae0..000000000 --- a/power-annotations/utils/jandex/src/main/java/com/github/t1/powerannotations/utils/jandex/AnnotationProxy.java +++ /dev/null @@ -1,114 +0,0 @@ -package com.github.t1.powerannotations.utils.jandex; - -import static com.github.t1.powerannotations.utils.jandex.JandexAnnotationsLoader.jandex; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.function.Function; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.AnnotationValue; -import org.jboss.jandex.ClassType; - -/** - * {@link #build() Builds} a {@link Proxy dynamic proxy} that delegates to three - * function objects for the implementation. - */ -class AnnotationProxy { - static Annotation proxy(AnnotationInstance annotationInstance) { - return new AnnotationProxy( - annotationInstance.name().toString(), - annotationInstance.toString(false), - name -> annotationInstance.valueWithDefault(jandex, name).value()) - .build(); - } - - private final String typeName; - private final String toString; - private final Function property; - - private AnnotationProxy(String typeName, String toString, Function property) { - this.typeName = typeName; - this.toString = toString; - this.property = property; - } - - private Annotation build() { - Class[] interfaces = new Class[] { getAnnotationType(), Annotation.class }; - return (Annotation) Proxy.newProxyInstance(getClassLoader(), interfaces, this::invoke); - } - - private Class getAnnotationType() { - return loadClass(typeName); - } - - private static Class loadClass(String typeName) { - try { - return getClassLoader().loadClass(typeName); - } catch (ClassNotFoundException e) { - throw new RuntimeException("can't load annotation type " + typeName, e); - } - } - - private static ClassLoader getClassLoader() { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - return (classLoader == null) ? ClassLoader.getSystemClassLoader() : classLoader; - } - - Object invoke(Object proxy, Method method, Object... args) { - String name = method.getName(); - if (method.getParameterCount() == 1 && "equals".equals(name)) - return toString.equals(args[0].toString()); - // no other methods on annotations can have arguments (except for one `wait`) - assert method.getParameterCount() == 0; - assert args == null || args.length == 0; - if ("hashCode".equals(name)) - return toString.hashCode(); - if ("annotationType".equals(name)) - return getAnnotationType(); - if ("toString".equals(name)) - return toString; - - Object value = property.apply(name); - - return toType(value, method.getReturnType()); - } - - private static Object toType(Object value, Class returnType) { - if (returnType.isAnnotation()) - return proxy((AnnotationInstance) value); - if (returnType.isEnum()) - return enumValue(returnType, (String) value); - if (returnType.equals(Class.class)) - return toClass(value); - if (returnType.isArray()) - return toArray(returnType.getComponentType(), (Object[]) value); - return value; - } - - private static > Enum enumValue(Class type, String value) { - @SuppressWarnings("unchecked") - Class enumType = (Class) type; - return Enum.valueOf(enumType, value); - } - - private static Class toClass(Object value) { - String className = ((ClassType) value).name().toString(); - - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - try { - return Class.forName(className, true, loader); - } catch (ClassNotFoundException e) { - throw new RuntimeException("class not found '" + className + "'", e); - } - } - - private static Object toArray(Class componentType, Object[] values) { - Object array = Array.newInstance(componentType, values.length); - for (int i = 0; i < values.length; i++) - Array.set(array, i, toType(((AnnotationValue) values[i]).value(), componentType)); - return array; - } -} diff --git a/power-annotations/utils/jandex/src/main/java/com/github/t1/powerannotations/utils/jandex/JandexAnnotationsLoader.java b/power-annotations/utils/jandex/src/main/java/com/github/t1/powerannotations/utils/jandex/JandexAnnotationsLoader.java deleted file mode 100644 index 3996e7217..000000000 --- a/power-annotations/utils/jandex/src/main/java/com/github/t1/powerannotations/utils/jandex/JandexAnnotationsLoader.java +++ /dev/null @@ -1,178 +0,0 @@ -package com.github.t1.powerannotations.utils.jandex; - -import static com.github.t1.powerannotations.common.CommonUtils.signature; -import static com.github.t1.powerannotations.common.CommonUtils.toDotName; -import static org.jboss.jandex.AnnotationTarget.Kind.METHOD; - -import java.lang.annotation.Annotation; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import java.util.function.Supplier; -import java.util.stream.Collector; -import java.util.stream.Stream; - -import org.jboss.jandex.AnnotationInstance; -import org.jboss.jandex.ClassInfo; -import org.jboss.jandex.DotName; -import org.jboss.jandex.FieldInfo; -import org.jboss.jandex.Index; -import org.jboss.jandex.MethodInfo; -import org.jboss.jandex.Type; -import org.jboss.jandex.Type.Kind; - -import com.github.t1.annotations.AmbiguousAnnotationResolutionException; -import com.github.t1.annotations.Annotations; -import com.github.t1.annotations.AnnotationsLoader; -import com.github.t1.powerannotations.common.Jandex; -import com.github.t1.powerannotations.scanner.IndexBuilder; - -public class JandexAnnotationsLoader extends AnnotationsLoader { - static final Index jandex = IndexBuilder.loadOrScan(); - - @Override - public Annotations onType(Class type) { - ClassInfo classInfo = getClassInfo(type); - - return new Annotations() { - @Override - public Stream all() { - return classInfo.classAnnotations().stream() - .flatMap(JandexAnnotationsLoader::resolveRepeatableAnnotations) - .map(JandexAnnotationsLoader::proxy); - } - - @Override - public Optional get(Class type) { - return all(type) - .collect(toOptionalOrThrow()); - } - - @Override - public Stream all(Class type) { - DotName typeName = toDotName(type); - return classInfo.classAnnotations().stream() - .flatMap(JandexAnnotationsLoader::resolveRepeatableAnnotations) - .filter(annotationInstance -> annotationInstance.name().equals(typeName)) - .map(JandexAnnotationsLoader::proxy); - } - }; - } - - @Override - public Annotations onField(Class type, String fieldName) { - ClassInfo classInfo = getClassInfo(type); - FieldInfo fieldInfo = classInfo.field(fieldName); - if (fieldInfo == null) - throw new RuntimeException("no field '" + fieldName + "' in class " + classInfo.name()); - - // Looks like a code duplicate, but ClassInfo, FieldInfo, and MethodInfo don't have a common interface - //noinspection DuplicatedCode - return new Annotations() { - @Override - public Stream all() { - return fieldInfo.annotations().stream() - .flatMap(JandexAnnotationsLoader::resolveRepeatableAnnotations) - .map(JandexAnnotationsLoader::proxy); - } - - @Override - public Optional get(Class type) { - return all(type).collect(toOptionalOrThrow()); - } - - @Override - public Stream all(Class type) { - DotName typeName = toDotName(type); - return fieldInfo.annotations().stream() - .flatMap(JandexAnnotationsLoader::resolveRepeatableAnnotations) - .filter(annotationInstance -> annotationInstance.name().equals(typeName)) - .map(JandexAnnotationsLoader::proxy); - } - }; - } - - @Override - public Annotations onMethod(Class type, String methodName, Class... argTypes) { - ClassInfo classInfo = getClassInfo(type); - Type[] jandexArgTypes = Stream.of(argTypes).map(Class::getName).map(JandexAnnotationsLoader::createClassType) - .toArray(Type[]::new); - MethodInfo methodInfo = classInfo.method(methodName, jandexArgTypes); - if (methodInfo == null) { - String[] argTypeNames = Stream.of(argTypes).map(Class::getName).toArray(String[]::new); - throw new RuntimeException("no method " + signature(methodName, argTypeNames) + " in class " + classInfo.name()); - } - - // Looks like a code duplicate, but ClassInfo, FieldInfo, and MethodInfo don't have a common interface - //noinspection DuplicatedCode - return new Annotations() { - @Override - public Stream all() { - return methodInfo.annotations().stream() - .filter(annotationInstance -> annotationInstance.target().kind() == METHOD) // not params - .flatMap(JandexAnnotationsLoader::resolveRepeatableAnnotations) - .map(JandexAnnotationsLoader::proxy); - } - - @Override - public Optional get(Class type) { - return all(type).collect(toOptionalOrThrow()); - } - - @Override - public Stream all(Class type) { - DotName typeName = toDotName(type); - return methodInfo.annotations().stream() - .flatMap(JandexAnnotationsLoader::resolveRepeatableAnnotations) - .filter(annotationInstance -> annotationInstance.name().equals(typeName)) - .map(JandexAnnotationsLoader::proxy); - } - }; - } - - private static Stream resolveRepeatableAnnotations(AnnotationInstance annotationInstance) { - return new Jandex(jandex).isRepeatedAnnotation(annotationInstance) - ? resolveRepeatableAnnotationsDo(annotationInstance) - : Stream.of(annotationInstance); - } - - private static Stream resolveRepeatableAnnotationsDo(AnnotationInstance annotationInstance) { - return Stream.of(annotationInstance.value().asNestedArray()); - } - - private ClassInfo getClassInfo(Class type) { - ClassInfo classInfo = jandex.getClassByName(toDotName(type)); - if (classInfo == null) - throw new RuntimeException("class not found in index: " + type.getName()); - return classInfo; - } - - private static Type createClassType(String name) { - return Type.create(DotName.createSimple(name), Kind.CLASS); - } - - private static T proxy(AnnotationInstance annotationInstance) { - //noinspection unchecked - return (T) AnnotationProxy.proxy(annotationInstance); - } - - private static Collector> toOptionalOrThrow() { - return Collector.of( - (Supplier>) ArrayList::new, - List::add, - (left, right) -> { - left.addAll(right); - return left; - }, - list -> { - switch (list.size()) { - case 0: - return Optional.empty(); - case 1: - return Optional.of(list.get(0)); - default: - throw new AmbiguousAnnotationResolutionException("expected one element maximum, but found " + list); - } - }); - } -} diff --git a/power-annotations/utils/jandex/src/main/resources/META-INF/jandex.properties b/power-annotations/utils/jandex/src/main/resources/META-INF/jandex.properties deleted file mode 100644 index 4786f2862..000000000 --- a/power-annotations/utils/jandex/src/main/resources/META-INF/jandex.properties +++ /dev/null @@ -1,16 +0,0 @@ -exclude=\ - net.bytebuddy:byte-buddy-agent \ - net.bytebuddy:byte-buddy \ - org.apiguardian:apiguardian-api \ - org.assertj:assertj-core \ - org.jboss:jandex \ - org.junit.jupiter:junit-jupiter-api \ - org.junit.jupiter:junit-jupiter-engine \ - org.junit.jupiter:junit-jupiter-params \ - org.junit.jupiter:junit-jupiter \ - org.junit.platform:junit-platform-commons \ - org.junit.platform:junit-platform-engine \ - org.mockito:mockito-core \ - org.mockito:mockito-junit-jupiter \ - org.objenesis:objenesis \ - org.opentest4j:opentest4j diff --git a/power-annotations/utils/jandex/src/main/resources/META-INF/services/com.github.t1.annotations.AnnotationsLoader b/power-annotations/utils/jandex/src/main/resources/META-INF/services/com.github.t1.annotations.AnnotationsLoader deleted file mode 100644 index c47a8f632..000000000 --- a/power-annotations/utils/jandex/src/main/resources/META-INF/services/com.github.t1.annotations.AnnotationsLoader +++ /dev/null @@ -1 +0,0 @@ -com.github.t1.powerannotations.utils.jandex.JandexAnnotationsLoader diff --git a/power-annotations/utils/pom.xml b/power-annotations/utils/pom.xml deleted file mode 100644 index 19852ab08..000000000 --- a/power-annotations/utils/pom.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - 4.0.0 - - - io.smallrye - smallrye-power-annotations-parent - 1.6.1-SNAPSHOT - - - smallrye-power-annotations-utils-parent - pom - Power Annotations Utils Parent POM - Utils for working with annotations, i.e. currently an abstraction of the Jandex API. Used by the TCK. - - - api - jandex - - diff --git a/server/federation/runtime/src/main/java/io/smallrye/graphql/federation/impl/Federation.java b/server/federation/runtime/src/main/java/io/smallrye/graphql/federation/impl/Federation.java index c09f90b0f..03a728d56 100644 --- a/server/federation/runtime/src/main/java/io/smallrye/graphql/federation/impl/Federation.java +++ b/server/federation/runtime/src/main/java/io/smallrye/graphql/federation/impl/Federation.java @@ -303,7 +303,7 @@ private void addFederatedEntityResolvers() { private static Method toReflectionMethod(MethodInfo methodInfo) { try { Class declaringClass = Class.forName(methodInfo.declaringClass().name().toString()); - Class[] parameterTypes = methodInfo.parameters().stream() + Class[] parameterTypes = methodInfo.parameterTypes().stream() .map(Type::asClassType) .map(Type::name) .map(DotName::toString)