From 8f0489fcd1c8393062512768f92d6ff0816d8f0a Mon Sep 17 00:00:00 2001 From: Jared Date: Fri, 16 Jun 2023 14:16:15 +0200 Subject: [PATCH] Start working on event support --- .../api/event/BusCarrierWrapper.java | 106 ++++++++++ .../crafttweaker/api/event/BusWrapper.java | 139 +++++++++++++ .../api/event/ZenEventWrapper.java | 106 ++++++++++ .../eventbus/api/CancelableWrapper.java | 106 ++++++++++ .../converter/DocumentConversionRegistry.java | 2 + .../converter/event/EventConverter.java | 185 ++++++++++++++++++ .../NativeRegistrationConverter.java | 44 ++--- .../document/page/page/EventPage.java | 138 +++++++++++++ .../event/ZenEventValidationProcessor.java | 40 ++++ .../event/validator/ZenEventValidator.java | 65 ++++++ .../validator/rules/CancelableEventRule.java | 55 ++++++ .../validator/rules/ZenEventHasBusRule.java | 36 ++++ .../rules/ZenEventValidationRule.java | 12 ++ .../visitors/CancelableTreeVisitor.java | 36 ++++ .../crafttweaker/api/event/ZenEvent.java | 25 +++ .../crafttweaker/api/event/package-info.java | 8 + .../eventbus/api/Cancelable.java | 10 + .../eventbus/api/package-info.java | 6 + 18 files changed, 1093 insertions(+), 26 deletions(-) create mode 100644 src/generated/java/com/blamejared/crafttweaker/api/event/BusCarrierWrapper.java create mode 100644 src/generated/java/com/blamejared/crafttweaker/api/event/BusWrapper.java create mode 100644 src/generated/java/com/blamejared/crafttweaker/api/event/ZenEventWrapper.java create mode 100644 src/generated/java/net/minecraftforge/eventbus/api/CancelableWrapper.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/event/EventConverter.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/document/page/page/EventPage.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/ZenEventValidationProcessor.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/ZenEventValidator.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/CancelableEventRule.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventHasBusRule.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventValidationRule.java create mode 100644 src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/visitors/CancelableTreeVisitor.java create mode 100644 src/stub/java/com/blamejared/crafttweaker/api/event/ZenEvent.java create mode 100644 src/stub/java/com/blamejared/crafttweaker/api/event/package-info.java create mode 100644 src/stub/java/net/minecraftforge/eventbus/api/Cancelable.java create mode 100644 src/stub/java/net/minecraftforge/eventbus/api/package-info.java diff --git a/src/generated/java/com/blamejared/crafttweaker/api/event/BusCarrierWrapper.java b/src/generated/java/com/blamejared/crafttweaker/api/event/BusCarrierWrapper.java new file mode 100644 index 0000000..f437590 --- /dev/null +++ b/src/generated/java/com/blamejared/crafttweaker/api/event/BusCarrierWrapper.java @@ -0,0 +1,106 @@ +package com.blamejared.crafttweaker.api.event; +import com.blamejared.crafttweaker.api.event.ZenEvent.BusCarrier; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import java.util.ArrayList; +import java.util.List; +import io.toolisticon.aptk.tools.AnnotationUtils; +import io.toolisticon.aptk.tools.TypeMirrorWrapper; +import io.toolisticon.aptk.tools.TypeUtils; + + +/** + * Wrapper class to read attribute values from Annotation BusCarrier. + */ +public class BusCarrierWrapper { + + private final Element annotatedElement; + private final AnnotationMirror annotationMirror; + + /** + * Private constructor. + * Used to read annotation from Element. + * @param annotatedElement the annotated Element to annotated with this wrapper annotation + */ + private BusCarrierWrapper (Element annotatedElement) { + this.annotatedElement = annotatedElement; + this.annotationMirror = AnnotationUtils.getAnnotationMirror(annotatedElement, BusCarrier.class); + } + + /** + * Private constructor. + * Mainly used for embedded annotations. + * @param element the element related with the passed annotationMirror + * @param annotationMirror the AnnotationMirror to wrap + */ + private BusCarrierWrapper (Element element, AnnotationMirror annotationMirror) { + this.annotatedElement = element; + this.annotationMirror = annotationMirror; + } + + /** + * Gets the element on which the wrapped annotation is used. + */ + public Element _annotatedElement() { + return this.annotatedElement; + } + + /** + * Gets the wrapped AnnotationMirror. + */ + public AnnotationMirror _annotationMirror() { + return this.annotationMirror; + } + + + + /** + * Checks if passed element is annotated with this wrapper annotation type : BusCarrier + * @param element The element to check for wrapped annotation type + * @return true, if passed element is annotated with BusCarrier annotation, otherwise false + */ + public static boolean isAnnotated(Element element) { + return element != null && element.getAnnotation(BusCarrier.class) != null; + } + + /** + * Gets the AnnotationMirror from passed element for this wrappers annotation type and creates a wrapper instance. + * @param element The element to read the annotations from + * @return The wrapped AnnotationMirror if Element is annotated with this wrappers annotation type, otherwise null. + */ + public static BusCarrierWrapper wrap(Element element) { + return isAnnotated(element) ? new BusCarrierWrapper(element) : null; + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param annotationMirror The element annotated with the annotation to wrap + * @return The wrapper instance + */ + public static BusCarrierWrapper wrap(AnnotationMirror annotationMirror) { + return new BusCarrierWrapper(null, annotationMirror); + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param element the element bound to the usage of passed AnnotationMirror + * @param annotationMirror The AnnotationMirror to wrap + * @return The wrapper instance + */ + public static BusCarrierWrapper wrap(Element element, AnnotationMirror annotationMirror) { + return new BusCarrierWrapper(element, annotationMirror); + } + +} \ No newline at end of file diff --git a/src/generated/java/com/blamejared/crafttweaker/api/event/BusWrapper.java b/src/generated/java/com/blamejared/crafttweaker/api/event/BusWrapper.java new file mode 100644 index 0000000..fe07a3b --- /dev/null +++ b/src/generated/java/com/blamejared/crafttweaker/api/event/BusWrapper.java @@ -0,0 +1,139 @@ +package com.blamejared.crafttweaker.api.event; +import com.blamejared.crafttweaker.api.event.ZenEvent.Bus; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import java.util.ArrayList; +import java.util.List; +import io.toolisticon.aptk.tools.AnnotationUtils; +import io.toolisticon.aptk.tools.TypeMirrorWrapper; +import io.toolisticon.aptk.tools.TypeUtils; + + +/** + * Wrapper class to read attribute values from Annotation Bus. + */ +public class BusWrapper { + + private final Element annotatedElement; + private final AnnotationMirror annotationMirror; + + /** + * Private constructor. + * Used to read annotation from Element. + * @param annotatedElement the annotated Element to annotated with this wrapper annotation + */ + private BusWrapper (Element annotatedElement) { + this.annotatedElement = annotatedElement; + this.annotationMirror = AnnotationUtils.getAnnotationMirror(annotatedElement, Bus.class); + } + + /** + * Private constructor. + * Mainly used for embedded annotations. + * @param element the element related with the passed annotationMirror + * @param annotationMirror the AnnotationMirror to wrap + */ + private BusWrapper (Element element, AnnotationMirror annotationMirror) { + this.annotatedElement = element; + this.annotationMirror = annotationMirror; + } + + /** + * Gets the element on which the wrapped annotation is used. + */ + public Element _annotatedElement() { + return this.annotatedElement; + } + + /** + * Gets the wrapped AnnotationMirror. + */ + public AnnotationMirror _annotationMirror() { + return this.annotationMirror; + } + + /** + * Gets the Bus.value from wrapped annotation. + * @return the attribute value as a TypeMirror + */ + public TypeMirror valueAsTypeMirror() { + return (TypeMirror)AnnotationUtils.getAnnotationValueOfAttributeWithDefaults(annotationMirror, "value").getValue(); + } + + /** + * Gets the Bus.value from wrapped annotation. + * @return the attribute value as a TypeMirror + */ + public TypeMirrorWrapper valueAsTypeMirrorWrapper() { + return TypeMirrorWrapper.wrap((TypeMirror)AnnotationUtils.getAnnotationValueOfAttributeWithDefaults(annotationMirror, "value").getValue()); + } + + /** + * Gets the Bus.value from wrapped annotation. + * @return the attribute value as a fqn + */ + public String valueAsFqn() { + return TypeUtils.TypeConversion.convertToFqn(valueAsTypeMirror()); + } + + + /** + * Allows to check if attribute was explicitly set or if default value is used. + * @return true, if default value is used, otherwise false + */ + public boolean valueIsDefaultValue(){ + return AnnotationUtils.getAnnotationValueOfAttribute(annotationMirror,"value") == null; + } + + + + /** + * Checks if passed element is annotated with this wrapper annotation type : Bus + * @param element The element to check for wrapped annotation type + * @return true, if passed element is annotated with Bus annotation, otherwise false + */ + public static boolean isAnnotated(Element element) { + return element != null && element.getAnnotation(Bus.class) != null; + } + + /** + * Gets the AnnotationMirror from passed element for this wrappers annotation type and creates a wrapper instance. + * @param element The element to read the annotations from + * @return The wrapped AnnotationMirror if Element is annotated with this wrappers annotation type, otherwise null. + */ + public static BusWrapper wrap(Element element) { + return isAnnotated(element) ? new BusWrapper(element) : null; + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param annotationMirror The element annotated with the annotation to wrap + * @return The wrapper instance + */ + public static BusWrapper wrap(AnnotationMirror annotationMirror) { + return new BusWrapper(null, annotationMirror); + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param element the element bound to the usage of passed AnnotationMirror + * @param annotationMirror The AnnotationMirror to wrap + * @return The wrapper instance + */ + public static BusWrapper wrap(Element element, AnnotationMirror annotationMirror) { + return new BusWrapper(element, annotationMirror); + } + +} \ No newline at end of file diff --git a/src/generated/java/com/blamejared/crafttweaker/api/event/ZenEventWrapper.java b/src/generated/java/com/blamejared/crafttweaker/api/event/ZenEventWrapper.java new file mode 100644 index 0000000..0ef886f --- /dev/null +++ b/src/generated/java/com/blamejared/crafttweaker/api/event/ZenEventWrapper.java @@ -0,0 +1,106 @@ +package com.blamejared.crafttweaker.api.event; +import com.blamejared.crafttweaker.api.event.ZenEvent; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import java.util.ArrayList; +import java.util.List; +import io.toolisticon.aptk.tools.AnnotationUtils; +import io.toolisticon.aptk.tools.TypeMirrorWrapper; +import io.toolisticon.aptk.tools.TypeUtils; + + +/** + * Wrapper class to read attribute values from Annotation ZenEvent. + */ +public class ZenEventWrapper { + + private final Element annotatedElement; + private final AnnotationMirror annotationMirror; + + /** + * Private constructor. + * Used to read annotation from Element. + * @param annotatedElement the annotated Element to annotated with this wrapper annotation + */ + private ZenEventWrapper (Element annotatedElement) { + this.annotatedElement = annotatedElement; + this.annotationMirror = AnnotationUtils.getAnnotationMirror(annotatedElement, ZenEvent.class); + } + + /** + * Private constructor. + * Mainly used for embedded annotations. + * @param element the element related with the passed annotationMirror + * @param annotationMirror the AnnotationMirror to wrap + */ + private ZenEventWrapper (Element element, AnnotationMirror annotationMirror) { + this.annotatedElement = element; + this.annotationMirror = annotationMirror; + } + + /** + * Gets the element on which the wrapped annotation is used. + */ + public Element _annotatedElement() { + return this.annotatedElement; + } + + /** + * Gets the wrapped AnnotationMirror. + */ + public AnnotationMirror _annotationMirror() { + return this.annotationMirror; + } + + + + /** + * Checks if passed element is annotated with this wrapper annotation type : ZenEvent + * @param element The element to check for wrapped annotation type + * @return true, if passed element is annotated with ZenEvent annotation, otherwise false + */ + public static boolean isAnnotated(Element element) { + return element != null && element.getAnnotation(ZenEvent.class) != null; + } + + /** + * Gets the AnnotationMirror from passed element for this wrappers annotation type and creates a wrapper instance. + * @param element The element to read the annotations from + * @return The wrapped AnnotationMirror if Element is annotated with this wrappers annotation type, otherwise null. + */ + public static ZenEventWrapper wrap(Element element) { + return isAnnotated(element) ? new ZenEventWrapper(element) : null; + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param annotationMirror The element annotated with the annotation to wrap + * @return The wrapper instance + */ + public static ZenEventWrapper wrap(AnnotationMirror annotationMirror) { + return new ZenEventWrapper(null, annotationMirror); + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param element the element bound to the usage of passed AnnotationMirror + * @param annotationMirror The AnnotationMirror to wrap + * @return The wrapper instance + */ + public static ZenEventWrapper wrap(Element element, AnnotationMirror annotationMirror) { + return new ZenEventWrapper(element, annotationMirror); + } + +} \ No newline at end of file diff --git a/src/generated/java/net/minecraftforge/eventbus/api/CancelableWrapper.java b/src/generated/java/net/minecraftforge/eventbus/api/CancelableWrapper.java new file mode 100644 index 0000000..2154f48 --- /dev/null +++ b/src/generated/java/net/minecraftforge/eventbus/api/CancelableWrapper.java @@ -0,0 +1,106 @@ +package net.minecraftforge.eventbus.api; +import net.minecraftforge.eventbus.api.Cancelable; + +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import java.util.ArrayList; +import java.util.List; +import io.toolisticon.aptk.tools.AnnotationUtils; +import io.toolisticon.aptk.tools.TypeMirrorWrapper; +import io.toolisticon.aptk.tools.TypeUtils; + + +/** + * Wrapper class to read attribute values from Annotation Cancelable. + */ +public class CancelableWrapper { + + private final Element annotatedElement; + private final AnnotationMirror annotationMirror; + + /** + * Private constructor. + * Used to read annotation from Element. + * @param annotatedElement the annotated Element to annotated with this wrapper annotation + */ + private CancelableWrapper (Element annotatedElement) { + this.annotatedElement = annotatedElement; + this.annotationMirror = AnnotationUtils.getAnnotationMirror(annotatedElement, Cancelable.class); + } + + /** + * Private constructor. + * Mainly used for embedded annotations. + * @param element the element related with the passed annotationMirror + * @param annotationMirror the AnnotationMirror to wrap + */ + private CancelableWrapper (Element element, AnnotationMirror annotationMirror) { + this.annotatedElement = element; + this.annotationMirror = annotationMirror; + } + + /** + * Gets the element on which the wrapped annotation is used. + */ + public Element _annotatedElement() { + return this.annotatedElement; + } + + /** + * Gets the wrapped AnnotationMirror. + */ + public AnnotationMirror _annotationMirror() { + return this.annotationMirror; + } + + + + /** + * Checks if passed element is annotated with this wrapper annotation type : Cancelable + * @param element The element to check for wrapped annotation type + * @return true, if passed element is annotated with Cancelable annotation, otherwise false + */ + public static boolean isAnnotated(Element element) { + return element != null && element.getAnnotation(Cancelable.class) != null; + } + + /** + * Gets the AnnotationMirror from passed element for this wrappers annotation type and creates a wrapper instance. + * @param element The element to read the annotations from + * @return The wrapped AnnotationMirror if Element is annotated with this wrappers annotation type, otherwise null. + */ + public static CancelableWrapper wrap(Element element) { + return isAnnotated(element) ? new CancelableWrapper(element) : null; + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param annotationMirror The element annotated with the annotation to wrap + * @return The wrapper instance + */ + public static CancelableWrapper wrap(AnnotationMirror annotationMirror) { + return new CancelableWrapper(null, annotationMirror); + } + + /** + * Wraps an AnnotationMirror. + * Throws an IllegalArgumentException if passed AnnotationMirror type doesn't match the wrapped annotation type. + * @param element the element bound to the usage of passed AnnotationMirror + * @param annotationMirror The AnnotationMirror to wrap + * @return The wrapper instance + */ + public static CancelableWrapper wrap(Element element, AnnotationMirror annotationMirror) { + return new CancelableWrapper(element, annotationMirror); + } + +} \ No newline at end of file diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/DocumentConversionRegistry.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/DocumentConversionRegistry.java index 7638379..2a14a03 100644 --- a/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/DocumentConversionRegistry.java +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/DocumentConversionRegistry.java @@ -1,6 +1,7 @@ package com.blamejared.crafttweaker.annotation.processor.document.conversion.converter; import com.blamejared.crafttweaker.annotation.processor.document.DocumentRegistry; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.event.EventConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.expansion.ExpansionConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.named_type.NamedTypeConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.native_registration.NativeRegistrationConverter; @@ -23,6 +24,7 @@ public DocumentConversionRegistry(DocumentRegistry documentRegistry, DependencyC this.documentRegistry = documentRegistry; // // TODO: Add converters + converters.add((dependencyContainer.getInstanceOfClass(EventConverter.class))); converters.add(dependencyContainer.getInstanceOfClass(NativeRegistrationConverter.class)); converters.add(dependencyContainer.getInstanceOfClass(ExpansionConverter.class)); converters.add(dependencyContainer.getInstanceOfClass(NamedTypeConverter.class)); diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/event/EventConverter.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/event/EventConverter.java new file mode 100644 index 0000000..f13993d --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/event/EventConverter.java @@ -0,0 +1,185 @@ +package com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.event; + +import com.blamejared.crafttweaker.annotation.processor.document.NativeConversionRegistry; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.DocumentConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.comment.CommentConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.member.EnumConstantConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.member.header.GenericParameterConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.member.static_member.StaticMemberConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.named_type.*; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.native_registration.member.NativeTypeVirtualMemberConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.element.ClassTypeConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.mods.KnownModList; +import com.blamejared.crafttweaker.annotation.processor.document.page.info.*; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.enum_constant.DocumentedEnumConstants; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.header.examples.Example; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker.annotation.processor.document.page.page.*; +import com.blamejared.crafttweaker.annotation.processor.document.page.type.*; +import com.blamejared.crafttweaker.api.event.ZenEventWrapper; +import com.blamejared.crafttweaker_annotations.annotations.*; + +import javax.annotation.Nonnull; +import javax.lang.model.element.*; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import java.util.List; +import java.util.stream.Collectors; + +public class EventConverter extends DocumentConverter { + + private final StaticMemberConverter staticMemberConverter; + private final NativeTypeVirtualMemberConverter virtualMemberConverter; + private final SuperTypeConverter superTypeConverter; + private final ImplementationConverter implementationConverter; + private final GenericParameterConverter genericParameterConverter; + private final NativeConversionRegistry nativeConversionRegistry; + private final Types typeUtils; + private final ClassTypeConverter classTypeConverter; + private final EnumConstantConverter enumConstantConverter; + + public EventConverter(KnownModList knownModList, CommentConverter commentConverter, StaticMemberConverter staticMemberConverter, NativeTypeVirtualMemberConverter virtualMemberConverter, SuperTypeConverter superTypeConverter, ImplementationConverter implementationConverter, GenericParameterConverter genericParameterConverter, NativeConversionRegistry nativeConversionRegistry, Types typeUtils, ClassTypeConverter classTypeConverter, EnumConstantConverter enumConstantConverter) { + + super(knownModList, commentConverter); + this.staticMemberConverter = staticMemberConverter; + this.virtualMemberConverter = virtualMemberConverter; + this.superTypeConverter = superTypeConverter; + this.implementationConverter = implementationConverter; + this.genericParameterConverter = genericParameterConverter; + this.nativeConversionRegistry = nativeConversionRegistry; + this.typeUtils = typeUtils; + this.classTypeConverter = classTypeConverter; + this.enumConstantConverter = enumConstantConverter; + } + + @Override + public boolean canConvert(TypeElement typeElement) { + + return getNativeAnnotation(typeElement) != null && ZenEventWrapper.isAnnotated(typeElement); + } + + private NativeTypeRegistrationWrapper getNativeAnnotation(TypeElement typeElement) { + + return NativeTypeRegistrationWrapper.wrap(typeElement); + } + + @Override + protected TypePageInfo prepareConversion(TypeElement element) { + + final TypePageInfo typePageInfo = createTypePageInfo(element); + registerNativeType(element, typePageInfo); + return typePageInfo; + } + + @Override + protected Example getFallbackThisInformationFor(TypeElement typeElement) { + + final String text = "my" + getName(typeElement).getSimpleName(); + return new Example("this", text); + } + + private void registerNativeType(TypeElement element, TypePageInfo typePageInfo) { + + final AbstractTypeInfo typeInfo = new TypePageTypeInfo(typePageInfo); + final TypeElement nativeType = getNativeType(element); + + nativeConversionRegistry.addNativeConversion(nativeType, typeInfo); + } + + private TypeElement getNativeType(TypeElement element) { + + final NativeTypeRegistrationWrapper annotation = getNativeAnnotation(element); + final TypeMirror nativeType = annotation.valueAsTypeMirror(); + return getTypeElementFromMirror(nativeType); + } + + private TypeElement getTypeElementFromMirror(TypeMirror nativeType) { + + final Element element = typeUtils.asElement(nativeType); + if(element instanceof TypeElement) { + return (TypeElement) element; + } + + throw new IllegalArgumentException("Could not get typeElement from mirror: " + nativeType); + } + + @Nonnull + private TypePageInfo createTypePageInfo(TypeElement element) { + + final DocumentationPageInfo documentationPageInfo = super.prepareConversion(element); + + final TypeName name = getName(element); + final String declaringModId = documentationPageInfo.declaringModId; + final String outputPath = documentationPageInfo.getOutputPath(); + return new TypePageInfo(declaringModId, outputPath, name); + } + + @Nonnull + private TypeName getName(TypeElement element) { + + return new TypeName(getNativeAnnotation(element).zenCodeName()); + } + + @Override + public DocumentationPage convert(TypeElement typeElement, DocumentationPageInfo pageInfo) { + + final DocumentedVirtualMembers virtualMembers = convertVirtualMembers(typeElement, pageInfo); + final AbstractTypeInfo superType = convertSuperType(typeElement); + final List implementedInterfaces = convertImplementedInterfaces(typeElement); + final DocumentedStaticMembers staticMembers = convertStaticMembers(typeElement, pageInfo); + final List genericParameters = convertGenericParameters(typeElement); + return new EventPage((TypePageInfo) pageInfo, virtualMembers, superType, implementedInterfaces, staticMembers, genericParameters); + } + + protected DocumentedVirtualMembers convertVirtualMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + + return virtualMemberConverter.convertFor(typeElement, pageInfo); + } + + protected AbstractTypeInfo convertSuperType(TypeElement typeElement) { + + if(isNativeEnum(typeElement)) { + // we should not print redundant information "extending Enum" + return null; + } + final TypeElement nativeType = getNativeType(typeElement); + return superTypeConverter.convertSuperTypeFor(nativeType).orElse(null); + } + + protected List convertImplementedInterfaces(TypeElement typeElement) { + + final TypeElement nativeType = getNativeType(typeElement); + return implementationConverter.convertInterfacesFor(nativeType); + } + + protected AbstractTypeInfo convertThisType(TypeElement typeElement) { + + return superTypeConverter.getTypeConverter().convertByName(getName(typeElement)); + } + + protected DocumentedStaticMembers convertStaticMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + + return staticMemberConverter.convertFor(typeElement, pageInfo); + } + + protected void convertNativeEnumMembers(TypeElement typeElement, DocumentedEnumConstants documentedEnumConstants) { + + enumConstantConverter.convertAndAddTo(getNativeType(typeElement), documentedEnumConstants, typeElement.getAnnotation(BracketEnum.class)); + } + + private List convertGenericParameters(TypeElement typeElement) { + + return typeElement.getTypeParameters() + .stream() + .map(genericParameterConverter::convertGenericParameter) + .collect(Collectors.toList()); + } + + private boolean isNativeEnum(TypeElement typeElement) { + + return getNativeType(typeElement).getKind() == ElementKind.ENUM; + } + +} \ No newline at end of file diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/native_registration/NativeRegistrationConverter.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/native_registration/NativeRegistrationConverter.java index 9fc515a..fda2786 100644 --- a/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/native_registration/NativeRegistrationConverter.java +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/conversion/converter/native_registration/NativeRegistrationConverter.java @@ -7,31 +7,23 @@ import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.member.EnumConstantConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.member.header.GenericParameterConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.member.static_member.StaticMemberConverter; -import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.named_type.ImplementationConverter; -import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.named_type.SuperTypeConverter; +import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.named_type.*; import com.blamejared.crafttweaker.annotation.processor.document.conversion.converter.native_registration.member.NativeTypeVirtualMemberConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.element.ClassTypeConverter; import com.blamejared.crafttweaker.annotation.processor.document.conversion.mods.KnownModList; -import com.blamejared.crafttweaker.annotation.processor.document.page.info.DocumentationPageInfo; -import com.blamejared.crafttweaker.annotation.processor.document.page.info.TypeName; -import com.blamejared.crafttweaker.annotation.processor.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker.annotation.processor.document.page.info.*; import com.blamejared.crafttweaker.annotation.processor.document.page.member.enum_constant.DocumentedEnumConstants; import com.blamejared.crafttweaker.annotation.processor.document.page.member.header.DocumentedGenericParameter; import com.blamejared.crafttweaker.annotation.processor.document.page.member.header.examples.Example; import com.blamejared.crafttweaker.annotation.processor.document.page.member.static_member.DocumentedStaticMembers; import com.blamejared.crafttweaker.annotation.processor.document.page.member.virtual_member.DocumentedVirtualMembers; -import com.blamejared.crafttweaker.annotation.processor.document.page.page.DocumentationPage; -import com.blamejared.crafttweaker.annotation.processor.document.page.page.EnumTypePage; -import com.blamejared.crafttweaker.annotation.processor.document.page.page.TypePage; -import com.blamejared.crafttweaker.annotation.processor.document.page.type.AbstractTypeInfo; -import com.blamejared.crafttweaker.annotation.processor.document.page.type.TypePageTypeInfo; -import com.blamejared.crafttweaker_annotations.annotations.BracketEnum; -import com.blamejared.crafttweaker_annotations.annotations.NativeTypeRegistration; +import com.blamejared.crafttweaker.annotation.processor.document.page.page.*; +import com.blamejared.crafttweaker.annotation.processor.document.page.type.*; +import com.blamejared.crafttweaker.api.event.ZenEventWrapper; +import com.blamejared.crafttweaker_annotations.annotations.*; import javax.annotation.Nonnull; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.*; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.Types; import java.util.List; @@ -66,12 +58,12 @@ public NativeRegistrationConverter(KnownModList knownModList, CommentConverter c @Override public boolean canConvert(TypeElement typeElement) { - return getNativeAnnotation(typeElement) != null; + return getNativeAnnotation(typeElement) != null && !ZenEventWrapper.isAnnotated(typeElement); } - private NativeTypeRegistration getNativeAnnotation(TypeElement typeElement) { + private NativeTypeRegistrationWrapper getNativeAnnotation(TypeElement typeElement) { - return typeElement.getAnnotation(NativeTypeRegistration.class); + return NativeTypeRegistrationWrapper.wrap(typeElement); } @Override @@ -99,8 +91,8 @@ private void registerNativeType(TypeElement element, TypePageInfo typePageInfo) private TypeElement getNativeType(TypeElement element) { - final NativeTypeRegistration annotation = getNativeAnnotation(element); - final TypeMirror nativeType = classTypeConverter.getTypeMirror(annotation, NativeTypeRegistration::value); + final NativeTypeRegistrationWrapper annotation = getNativeAnnotation(element); + final TypeMirror nativeType = annotation.valueAsTypeMirror(); return getTypeElementFromMirror(nativeType); } @@ -148,12 +140,12 @@ public DocumentationPage convert(TypeElement typeElement, DocumentationPageInfo } } - private DocumentedVirtualMembers convertVirtualMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + protected DocumentedVirtualMembers convertVirtualMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { return virtualMemberConverter.convertFor(typeElement, pageInfo); } - private AbstractTypeInfo convertSuperType(TypeElement typeElement) { + protected AbstractTypeInfo convertSuperType(TypeElement typeElement) { if(isNativeEnum(typeElement)) { // we should not print redundant information "extending Enum" @@ -163,23 +155,23 @@ private AbstractTypeInfo convertSuperType(TypeElement typeElement) { return superTypeConverter.convertSuperTypeFor(nativeType).orElse(null); } - private List convertImplementedInterfaces(TypeElement typeElement) { + protected List convertImplementedInterfaces(TypeElement typeElement) { final TypeElement nativeType = getNativeType(typeElement); return implementationConverter.convertInterfacesFor(nativeType); } - private AbstractTypeInfo convertThisType(TypeElement typeElement) { + protected AbstractTypeInfo convertThisType(TypeElement typeElement) { return superTypeConverter.getTypeConverter().convertByName(getName(typeElement)); } - private DocumentedStaticMembers convertStaticMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { + protected DocumentedStaticMembers convertStaticMembers(TypeElement typeElement, DocumentationPageInfo pageInfo) { return staticMemberConverter.convertFor(typeElement, pageInfo); } - private void convertNativeEnumMembers(TypeElement typeElement, DocumentedEnumConstants documentedEnumConstants) { + protected void convertNativeEnumMembers(TypeElement typeElement, DocumentedEnumConstants documentedEnumConstants) { enumConstantConverter.convertAndAddTo(getNativeType(typeElement), documentedEnumConstants, typeElement.getAnnotation(BracketEnum.class)); } diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/page/page/EventPage.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/page/page/EventPage.java new file mode 100644 index 0000000..9c07ceb --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/document/page/page/EventPage.java @@ -0,0 +1,138 @@ +package com.blamejared.crafttweaker.annotation.processor.document.page.page; + +import com.blamejared.crafttweaker.annotation.processor.document.file.PageOutputWriter; +import com.blamejared.crafttweaker.annotation.processor.document.meta.DocumentMeta; +import com.blamejared.crafttweaker.annotation.processor.document.page.info.TypePageInfo; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.header.DocumentedGenericParameter; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.static_member.DocumentedStaticMembers; +import com.blamejared.crafttweaker.annotation.processor.document.page.member.virtual_member.DocumentedVirtualMembers; +import com.blamejared.crafttweaker.annotation.processor.document.page.type.*; + +import javax.annotation.Nullable; +import java.util.List; +import java.util.stream.Collectors; + +public class EventPage extends DocumentationPage { + + final TypePageInfo typePageInfo; + + @Nullable + private final AbstractTypeInfo superType; + private final List implementedTypes; + private final List genericParameters; + + public EventPage(TypePageInfo typePageInfo, DocumentedVirtualMembers members, @Nullable AbstractTypeInfo superType, List implementedTypes, DocumentedStaticMembers staticMembers, List genericParameters) { + + super(typePageInfo, members, staticMembers); + this.typePageInfo = typePageInfo; + this.superType = superType; + this.implementedTypes = implementedTypes; + this.genericParameters = genericParameters; + } + + @Override + protected void writeTitle(PageOutputWriter writer) { + + if(genericParameters.isEmpty()) { + writer.printf("# %s%n%n", getSimpleName()); + } else { + final String genericParameters = this.genericParameters.stream() + .map(DocumentedGenericParameter::formatForSignatureExample) + .collect(Collectors.joining(", ")); + writer.printf("# %s<%s>%n%n", getSimpleName(), genericParameters); + } + } + + @Override + protected void writeOwnerModId(PageOutputWriter writer) { + + writer.printf("This event was added by a mod with mod-id `%s`. So you need to have this mod installed if you want to use this feature.%n%n", typePageInfo.declaringModId); + } + + @Override + protected void beforeWritingMembers(PageOutputWriter writer) { + + super.beforeWritingMembers(writer); + writeImport(writer); + writeListener(writer); + writeSuperClass(writer); + writeImplementedInterfaces(writer); + } + + private void writeImport(PageOutputWriter writer) { + + writer.printf("## Importing the class%n%n"); + writer.println("Importing the class is recommended for events, simply add this line to the top of your script file."); + writer.zenBlock(() -> writer.printf("import %s;%n", typePageInfo.zenCodeName.getZenCodeName())); + writer.println(); + writer.println(); + } + + private void writeListener(PageOutputWriter writer) { + + writer.printf("## Listening to the event%n%n"); + writer.zenBlock(() -> writer.printf(""" + events.register<%s>(event => { + println("%s ran!"); + }); + """, typePageInfo.zenCodeName.getZenCodeName(), typePageInfo.zenCodeName.getSimpleName())); + writer.println(); + writer.println(); + } + + private void writeSuperClass(PageOutputWriter writer) { + + if(superType == null) { + return; + } + writer.printf("## Supertype%n%n"); + final String simpleName = getSimpleName(); + final String superTypeMarkDown = superType.getClickableMarkdown(); + + final String format = "%1$s extends %2$s. That means all methods available in %2$s are also available in %1$s%n%n"; + writer.printf(format, simpleName, superTypeMarkDown); + } + + private void writeImplementedInterfaces(PageOutputWriter writer) { + + if(implementedTypes.isEmpty()) { + return; + } + + writer.println("## Implemented Interfaces"); + final String format = "%1$s implements the following interfaces. That means all methods defined in these interfaces are also available in %1$s%n%n"; + writer.printf(format, getSimpleName()); + + for(AbstractTypeInfo implementedType : implementedTypes) { + writer.printf("- %s%n", implementedType.getClickableMarkdown()); + } + writer.println(); + } + + + @Override + public void fillMeta(DocumentMeta meta) { + + meta.setZenCodeName(typePageInfo.zenCodeName.getZenCodeName()); + meta.setOwnerModId(typePageInfo.declaringModId); + if(superType instanceof TypePageTypeInfo) { + String zenCodeName = ((TypePageTypeInfo) superType).getZenCodeName().getZenCodeName(); + meta.addSearchTerms(zenCodeName); + meta.setZenCodeName(zenCodeName); + } + if(!implementedTypes.isEmpty()) { + for(AbstractTypeInfo implementedType : implementedTypes) { + if(implementedType instanceof TypePageTypeInfo) { + // Determine if we should include parents in the search terms. + meta.addSearchTerms(((TypePageTypeInfo) implementedType).getZenCodeName().getZenCodeName()); + } + } + } + } + + private String getSimpleName() { + + return typePageInfo.getSimpleName(); + } + +} diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/ZenEventValidationProcessor.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/ZenEventValidationProcessor.java new file mode 100644 index 0000000..f1d676c --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/ZenEventValidationProcessor.java @@ -0,0 +1,40 @@ +package com.blamejared.crafttweaker.annotation.processor.validation.event; + +import com.blamejared.crafttweaker.annotation.processor.CraftTweakerProcessor; +import com.blamejared.crafttweaker.annotation.processor.validation.event.validator.ZenEventValidator; +import com.blamejared.crafttweaker.api.event.ZenEvent; +import com.google.auto.service.AutoService; + +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.TypeElement; +import java.lang.annotation.Annotation; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +@AutoService(Processor.class) +public class ZenEventValidationProcessor extends CraftTweakerProcessor { + + private ZenEventValidator virtualTypeValidator; + + @Override + public Collection> getSupportedAnnotationClasses() { + + return List.of(ZenEvent.class, ZenEvent.BusCarrier.class); + } + + @Override + public synchronized void performInitialization() { + + virtualTypeValidator = dependencyContainer.getInstanceOfClass(ZenEventValidator.class); + } + + @Override + public boolean performProcessing(Set annotations, RoundEnvironment roundEnv) { + + virtualTypeValidator.validateAll(roundEnv.getElementsAnnotatedWithAny(Set.of(ZenEvent.class, ZenEvent.BusCarrier.class))); + return false; + } + +} diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/ZenEventValidator.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/ZenEventValidator.java new file mode 100644 index 0000000..5ecbfe1 --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/ZenEventValidator.java @@ -0,0 +1,65 @@ +package com.blamejared.crafttweaker.annotation.processor.validation.event.validator; + + +import com.blamejared.crafttweaker.annotation.processor.util.dependencies.DependencyContainer; +import com.blamejared.crafttweaker.annotation.processor.util.dependencies.IHasPostCreationCall; +import com.blamejared.crafttweaker.annotation.processor.validation.event.validator.rules.CancelableEventRule; +import com.blamejared.crafttweaker.annotation.processor.validation.event.validator.rules.ZenEventHasBusRule; +import com.blamejared.crafttweaker.annotation.processor.validation.event.validator.rules.ZenEventValidationRule; +import io.toolisticon.aptk.tools.ElementUtils; + +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.TypeElement; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class ZenEventValidator implements IHasPostCreationCall { + + private final List rules = new ArrayList<>(); + private final DependencyContainer dependencyContainer; + + public ZenEventValidator(DependencyContainer dependencyContainer) { + + this.dependencyContainer = dependencyContainer; + } + + public void validateAll(Collection elements) { + + for(Element element : elements) { + if(!isTypeElement(element)) { + throw new IllegalArgumentException("Invalid typeElement annotated: " + element); + } + validate((TypeElement) element); + } + } + + private boolean isTypeElement(Element element) { + + return ElementUtils.CheckKindOfElement.isClass(element) || ElementUtils.CheckKindOfElement.isEnum(element) || ElementUtils.CheckKindOfElement.isOfKind(element, ElementKind.RECORD) || ElementUtils.CheckKindOfElement.isInterface(element); + } + + private void validate(TypeElement element) { + + for(ZenEventValidationRule rule : rules) { + if(rule.canValidate(element)) { + rule.validate(element); + } + } + } + + @Override + public void afterCreation() { + + addRule(ZenEventHasBusRule.class); + addRule(CancelableEventRule.class); + } + + public void addRule(Class ruleClass) { + + final ZenEventValidationRule rule = dependencyContainer.getInstanceOfClass(ruleClass); + rules.add(rule); + } + +} diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/CancelableEventRule.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/CancelableEventRule.java new file mode 100644 index 0000000..42bcaf2 --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/CancelableEventRule.java @@ -0,0 +1,55 @@ +package com.blamejared.crafttweaker.annotation.processor.validation.event.validator.rules; + +import com.blamejared.crafttweaker.annotation.processor.validation.event.validator.visitors.CancelableTreeVisitor; +import com.blamejared.crafttweaker.api.event.BusCarrierWrapper; +import com.blamejared.crafttweaker.api.event.BusWrapper; +import com.blamejared.crafttweaker.api.event.ZenEventWrapper; +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.SimpleTreeVisitor; +import io.toolisticon.aptk.tools.ElementUtils; +import io.toolisticon.aptk.tools.MessagerUtils; +import io.toolisticon.aptk.tools.ProcessingEnvironmentUtils; +import io.toolisticon.aptk.tools.TypeMirrorWrapper; +import io.toolisticon.aptk.tools.TypeUtils; +import net.minecraftforge.eventbus.api.CancelableWrapper; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import java.util.Collection; + +public class CancelableEventRule implements ZenEventValidationRule { + + @Override + public boolean canValidate(TypeElement enclosedElement) { + + + return (ZenEventWrapper.isAnnotated(enclosedElement) || BusCarrierWrapper.isAnnotated(enclosedElement)) + && ElementUtils.AccessEnclosedElements.getEnclosedFields(enclosedElement) + .stream() + .filter(BusWrapper::isAnnotated) + .map(VariableElement::asType) + .map(TypeMirrorWrapper::getTypeArguments) + .flatMap(Collection::stream) + .map(TypeUtils.TypeRetrieval::getTypeElement) + .anyMatch(CancelableWrapper::isAnnotated); + } + + @Override + public void validate(TypeElement enclosedElement) { + + ElementUtils.AccessEnclosedElements.getEnclosedFields(enclosedElement) + .stream() + .filter(BusWrapper::isAnnotated).forEach(variableElement -> { + Tree tree = ProcessingEnvironmentUtils.getTrees().getTree(variableElement); + Boolean cancelable = tree.accept(new CancelableTreeVisitor(), null); + if(!cancelable) { + MessagerUtils.error(enclosedElement, "@Cancelable event is not implemented as cancelable! Use 'IEventBus.cancelable' instead!"); + } + + }); + } + +} diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventHasBusRule.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventHasBusRule.java new file mode 100644 index 0000000..36956d8 --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventHasBusRule.java @@ -0,0 +1,36 @@ +package com.blamejared.crafttweaker.annotation.processor.validation.event.validator.rules; + +import com.blamejared.crafttweaker.api.event.BusCarrierWrapper; +import com.blamejared.crafttweaker.api.event.BusWrapper; +import com.blamejared.crafttweaker.api.event.ZenEventWrapper; +import io.toolisticon.aptk.tools.ElementUtils; +import io.toolisticon.aptk.tools.MessagerUtils; + +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import java.util.Set; +import java.util.stream.Collectors; + +public class ZenEventHasBusRule implements ZenEventValidationRule { + + @Override + public boolean canValidate(TypeElement enclosedElement) { + + return ZenEventWrapper.isAnnotated(enclosedElement) || BusCarrierWrapper.isAnnotated(enclosedElement); + } + + @Override + public void validate(TypeElement enclosedElement) { + + Set buses = ElementUtils.AccessEnclosedElements.getEnclosedFields(enclosedElement) + .stream() + .filter(BusWrapper::isAnnotated) + .collect(Collectors.toSet()); + if(buses.isEmpty()) { + MessagerUtils.error(enclosedElement, "Expected a single '@ZenEvent.Bus' annotation but none was found!"); + } else if(buses.size() > 1) { + MessagerUtils.error(enclosedElement, "Expected a single '@ZenEvent.Bus' annotation but {0} were found!", buses.size()); + } + } + +} diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventValidationRule.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventValidationRule.java new file mode 100644 index 0000000..3b2c5be --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/rules/ZenEventValidationRule.java @@ -0,0 +1,12 @@ +package com.blamejared.crafttweaker.annotation.processor.validation.event.validator.rules; + +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; + +public interface ZenEventValidationRule { + + boolean canValidate(TypeElement enclosedElement); + + void validate(TypeElement enclosedElement); + +} diff --git a/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/visitors/CancelableTreeVisitor.java b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/visitors/CancelableTreeVisitor.java new file mode 100644 index 0000000..1dbe036 --- /dev/null +++ b/src/main/java/com/blamejared/crafttweaker/annotation/processor/validation/event/validator/visitors/CancelableTreeVisitor.java @@ -0,0 +1,36 @@ +package com.blamejared.crafttweaker.annotation.processor.validation.event.validator.visitors; + +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.SimpleTreeVisitor; + +public class CancelableTreeVisitor extends SimpleTreeVisitor { + + @Override + public Boolean visitVariable(VariableTree node, Void object) { + + return node.getInitializer().accept(this, object); + } + + @Override + public Boolean visitMethodInvocation(MethodInvocationTree node, Void object) { + + return node.getMethodSelect().accept(this, object); + } + + @Override + public Boolean visitMemberSelect(MemberSelectTree node, Void object) { + + return node.getExpression().accept(this, object) && node.getIdentifier().contentEquals("cancelable"); + } + + @Override + public Boolean visitIdentifier(IdentifierTree node, Void unused) { + + return node.getName().contentEquals("IEventBus"); + } + + +} diff --git a/src/stub/java/com/blamejared/crafttweaker/api/event/ZenEvent.java b/src/stub/java/com/blamejared/crafttweaker/api/event/ZenEvent.java new file mode 100644 index 0000000..47451cd --- /dev/null +++ b/src/stub/java/com/blamejared/crafttweaker/api/event/ZenEvent.java @@ -0,0 +1,25 @@ +package com.blamejared.crafttweaker.api.event; + +import java.lang.annotation.*; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface ZenEvent { + + @Target(ElementType.TYPE) + @Retention(RetentionPolicy.RUNTIME) + @interface BusCarrier {} + + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.RUNTIME) + @interface Bus { + + Class value() default Auto.class; + + @Target({}) + @Retention(RetentionPolicy.RUNTIME) + @interface Auto {} + + } + +} diff --git a/src/stub/java/com/blamejared/crafttweaker/api/event/package-info.java b/src/stub/java/com/blamejared/crafttweaker/api/event/package-info.java new file mode 100644 index 0000000..5a240a2 --- /dev/null +++ b/src/stub/java/com/blamejared/crafttweaker/api/event/package-info.java @@ -0,0 +1,8 @@ +@AnnotationWrapper(value = { + ZenEvent.class, + ZenEvent.Bus.class, + ZenEvent.BusCarrier.class +}, usePublicVisibility = true) +package com.blamejared.crafttweaker.api.event; + +import io.toolisticon.aptk.annotationwrapper.api.AnnotationWrapper; \ No newline at end of file diff --git a/src/stub/java/net/minecraftforge/eventbus/api/Cancelable.java b/src/stub/java/net/minecraftforge/eventbus/api/Cancelable.java new file mode 100644 index 0000000..99a8b44 --- /dev/null +++ b/src/stub/java/net/minecraftforge/eventbus/api/Cancelable.java @@ -0,0 +1,10 @@ +package net.minecraftforge.eventbus.api; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = ElementType.TYPE) +public @interface Cancelable {} \ No newline at end of file diff --git a/src/stub/java/net/minecraftforge/eventbus/api/package-info.java b/src/stub/java/net/minecraftforge/eventbus/api/package-info.java new file mode 100644 index 0000000..70b52e8 --- /dev/null +++ b/src/stub/java/net/minecraftforge/eventbus/api/package-info.java @@ -0,0 +1,6 @@ +@AnnotationWrapper(value = { + Cancelable.class +}, usePublicVisibility = true) +package net.minecraftforge.eventbus.api; + +import io.toolisticon.aptk.annotationwrapper.api.AnnotationWrapper; \ No newline at end of file