diff --git a/build.gradle b/build.gradle index 41ba86c..4006496 100644 --- a/build.gradle +++ b/build.gradle @@ -83,6 +83,16 @@ dependencies { testImplementation 'org.hamcrest:hamcrest:2.2' } +task buildResources { + doLast { + File to = new File("${buildDir}/classes/java/main/META-INF/services/javax.annotation.processing.Processor") + to.parentFile.mkdirs() + to.createNewFile() + to.append("de.steamwar.linkage.LinkageProcessor\n") + } +} +classes.finalizedBy(buildResources) + task buildProject { description 'Build this project' group "Steamwar" diff --git a/src/de/steamwar/linkage/LinkageProcessor.java b/src/de/steamwar/linkage/LinkageProcessor.java index b0e8303..ee18e5a 100644 --- a/src/de/steamwar/linkage/LinkageProcessor.java +++ b/src/de/steamwar/linkage/LinkageProcessor.java @@ -19,21 +19,36 @@ package de.steamwar.linkage; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.FieldBuilder; +import de.steamwar.linkage.plan.MethodBuilder; +import de.steamwar.linkage.plan.ParameterBuilder; +import de.steamwar.linkage.types.ListenerLink; +import lombok.Getter; import lombok.SneakyThrows; import javax.annotation.processing.*; import javax.lang.model.SourceVersion; -import javax.lang.model.element.TypeElement; +import javax.lang.model.element.*; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic; -import javax.tools.StandardLocation; -import java.io.BufferedReader; -import java.io.InputStreamReader; +import java.io.BufferedWriter; +import java.io.File; import java.io.Writer; -import java.util.Set; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.Stream; -@SupportedAnnotationTypes("de.steamwar.linkage.Linked") +@SupportedAnnotationTypes({"de.steamwar.linkage.Linked", "de.steamwar.linkage.Linked$Linkages"}) public class LinkageProcessor extends AbstractProcessor { + @Getter + private static LinkageType.Context context; + + private String packageName; + private String className; + private Messager messager; private Writer writer; private boolean processed = false; @@ -48,24 +63,168 @@ public class LinkageProcessor extends AbstractProcessor { public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); - String name = new BufferedReader(new InputStreamReader(processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", "plugin.yml").openInputStream())) - .lines() - .filter(s -> s.startsWith("name: ")) - .map(s -> s.substring(6)) - .map(String::toLowerCase) - .findFirst() - .orElse(null); - if (name == null) { - messager.printMessage(Diagnostic.Kind.ERROR, "Could not find plugin name in plugin.yml"); - return; - } + String name = new File(System.getProperty("user.dir")).getName(); + if (name.contains(".")) name = name.substring(0, name.indexOf('.')); + name = name.toLowerCase(); + context = name.contains("bungee") ? LinkageType.Context.BUNGEE : LinkageType.Context.SPIGOT; writer = processingEnv.getFiler().createSourceFile("de.steamwar." + name + ".linkage.LinkageUtils").openWriter(); messager = processingEnv.getMessager(); + + packageName = "de.steamwar." + name + ".linkage"; + className = "LinkageUtils"; } + @SneakyThrows @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { - return false; + messager.printMessage(Diagnostic.Kind.NOTE, "Processing linkage types"); + if (processed) return false; + processed = true; + BuildPlan buildPlan = new BuildPlan(packageName, className); + buildPlan.addImport("java.util.Set"); + buildPlan.addImport("java.lang.Class"); + buildPlan.addImport("de.steamwar.linkage.LinkageType"); + buildPlan.addImport("java.util.HashSet"); + buildPlan.addField(new FieldBuilder("Set>", "enabled", "new HashSet<>()")); + + MethodBuilder runMethod = new MethodBuilder("run", "void"); + buildPlan.addMethod(runMethod); + runMethod.addParameter(new ParameterBuilder("Class", "type")); + runMethod.addLine("if (!enabled.add(type)) return;"); + Set> alreadyGenerated = new HashSet<>(); + + Set elements = roundEnv.getElementsAnnotatedWith(Linked.class); + elements.addAll((Set) roundEnv.getElementsAnnotatedWith(Linked.Linkages.class)); + + Map neededFields = new HashMap<>(); + for (Element element : elements) { + if (element.getKind() != ElementKind.CLASS) { + continue; + } + TypeElement typeElement = (TypeElement) element; + Linked[] linkeds = element.getAnnotationsByType(Linked.class); + if (linkeds.length == 0) { + continue; + } + + if (linkeds.length > 1) { + neededFields.put(typeElement.getQualifiedName().toString(), typeElement); + } + + List variableElements = typeElement.getEnclosedElements().stream().filter(e -> e.getKind() == ElementKind.FIELD).map(VariableElement.class::cast).filter(e -> { + return e.getAnnotation(LinkedInstance.class) != null; + }).collect(Collectors.toList()); + if (variableElements.isEmpty()) { + continue; + } + + for (VariableElement variableElement : variableElements) { + if (!variableElement.getModifiers().contains(Modifier.PUBLIC)) { + messager.printMessage(Diagnostic.Kind.ERROR, "Field " + variableElement.getSimpleName() + " must be public", variableElement); + continue; + } + if (variableElement.getModifiers().contains(Modifier.STATIC)) { + messager.printMessage(Diagnostic.Kind.ERROR, "Field " + variableElement.getSimpleName() + " must be non static", variableElement); + continue; + } + if (variableElement.getModifiers().contains(Modifier.FINAL)) { + messager.printMessage(Diagnostic.Kind.ERROR, "Field " + variableElement.getSimpleName() + " must be non final", variableElement); + continue; + } + neededFields.put(typeElement.getQualifiedName().toString(), typeElement); + TypeElement fieldType = (TypeElement) ((DeclaredType) variableElement.asType()).asElement(); + neededFields.put(fieldType.getQualifiedName().toString(), fieldType); + + buildPlan.addStaticLine(getElement(typeElement, neededFields) + "." + variableElement.getSimpleName().toString() + " = " + getElement((TypeElement) ((DeclaredType) variableElement.asType()).asElement(), neededFields) + ";"); + } + } + neededFields.forEach((s, typeElement) -> { + buildPlan.addImport(typeElement.getQualifiedName().toString()); + buildPlan.addField(new FieldBuilder(typeElement.getSimpleName().toString(), typeElement.getSimpleName().toString())); + + MethodBuilder initializer = new MethodBuilder(typeElement.getSimpleName().toString(), typeElement.getSimpleName().toString()); + initializer.addLine("if (" + typeElement.getSimpleName().toString() + " == null) {"); + initializer.addLine(" " + typeElement.getSimpleName().toString() + " = new " + typeElement.getSimpleName().toString() + "();"); + initializer.addLine("}"); + initializer.addLine("return " + typeElement.getSimpleName().toString() + ";"); + buildPlan.addMethod(initializer); + }); + + Map, MethodBuilder> methods = new HashMap<>(); + for (Element element : elements) { + if (element.getKind() != ElementKind.CLASS) { + continue; + } + TypeElement typeElement = (TypeElement) element; + MinVersion minVersion = element.getAnnotation(MinVersion.class); + + System.out.println("Found element: " + typeElement.getQualifiedName().toString()); + element.getAnnotationMirrors().forEach(annotationMirror -> { + if (!annotationMirror.getAnnotationType().asElement().getSimpleName().toString().equals("Linked")) return; + Class clazz = annotationMirror.getElementValues().entrySet().stream() + .filter(entry -> entry.getKey().getSimpleName().toString().equals("value")) + .map(Map.Entry::getValue) + .map(AnnotationValue::getValue) + .map(Object::toString) + .map(s -> { + try { + return Class.forName(s); + } catch (ClassNotFoundException e) { + return null; + } + }) + .findFirst() + .orElse(null); + if (clazz == null) { + messager.printMessage(Diagnostic.Kind.ERROR, "No class specified", element); + return; + } + + LinkageType type = null; + try { + type = (LinkageType) clazz.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + messager.printMessage(Diagnostic.Kind.ERROR, "Could not instantiate class", element); + return; + } + + if (!type.requirements(typeElement.getSuperclass().toString(), typeElement.getInterfaces().stream().map(TypeMirror::toString).collect(Collectors.toSet()))) { + return; + } + + if (alreadyGenerated.add((Class) clazz)) { + runMethod.addLine("if (type == " + clazz.getTypeName() + ".class) {"); + runMethod.addLine(" run" + clazz.getSimpleName() + "();"); + runMethod.addLine("}"); + } + + MethodBuilder method = methods.computeIfAbsent(clazz, t -> { + MethodBuilder methodBuilder = new MethodBuilder("run" + t.getSimpleName(), "void"); + methodBuilder.setPrivate(true); + buildPlan.addMethod(methodBuilder); + return methodBuilder; + }); + if (context == LinkageType.Context.SPIGOT && minVersion != null) { + method.addLine("if (de.steamwar.core.Core.getVersion() >= " + minVersion.value() + ") {"); + } + type.generateCode(buildPlan, method, getElement(typeElement, neededFields), typeElement); + if (context == LinkageType.Context.SPIGOT && minVersion != null) { + method.addLine("}"); + } + }); + } + + BufferedWriter writer = new BufferedWriter(this.writer); + buildPlan.write(writer); + writer.close(); + return true; + } + + private String getElement(TypeElement typeElement, Map neededFields) { + if (neededFields.containsKey(typeElement.getQualifiedName().toString())) { + return typeElement.getSimpleName().toString() + "()"; + } + return "new " + typeElement.getQualifiedName().toString() + "()"; } } diff --git a/src/de/steamwar/linkage/LinkageType.java b/src/de/steamwar/linkage/LinkageType.java index f71ca2f..9308905 100644 --- a/src/de/steamwar/linkage/LinkageType.java +++ b/src/de/steamwar/linkage/LinkageType.java @@ -22,14 +22,22 @@ package de.steamwar.linkage; import de.steamwar.linkage.plan.BuildPlan; import de.steamwar.linkage.plan.MethodBuilder; +import javax.lang.model.element.TypeElement; +import java.util.OptionalInt; +import java.util.Set; + public interface LinkageType { - default Class clazzType() { - return null; - } - default Class interfaceType() { - return null; + Context context = LinkageProcessor.getContext(); + + enum Context { + BUNGEE, + SPIGOT } - void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance); + default boolean requirements(String superClass, Set interfaces) { + return true; + } + + void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement); } diff --git a/src/de/steamwar/linkage/Linked.java b/src/de/steamwar/linkage/Linked.java index fd091d3..b352982 100644 --- a/src/de/steamwar/linkage/Linked.java +++ b/src/de/steamwar/linkage/Linked.java @@ -25,7 +25,7 @@ import java.lang.annotation.*; @Target({ElementType.TYPE}) @Repeatable(Linked.Linkages.class) public @interface Linked { - Class value(); + Class value(); @Retention(RetentionPolicy.SOURCE) @Target({ElementType.TYPE}) diff --git a/src/de/steamwar/linkage/plan/BuildPlan.java b/src/de/steamwar/linkage/plan/BuildPlan.java index 97c9aee..d53eeb8 100644 --- a/src/de/steamwar/linkage/plan/BuildPlan.java +++ b/src/de/steamwar/linkage/plan/BuildPlan.java @@ -24,27 +24,32 @@ import lombok.RequiredArgsConstructor; import java.io.BufferedWriter; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; +import java.util.*; @RequiredArgsConstructor public class BuildPlan implements Writer { private final String packageName; + private Set imports = new HashSet<>(); private final String className; - private Map, FieldBuilder> fieldBuilderMap = new HashMap<>(); + private Map fieldBuilderMap = new HashMap<>(); private Map methodBuilderMap = new HashMap<>(); + private List staticLines = new ArrayList<>(); + + public void addImport(String importName) { + imports.add(importName); + } public void addField(FieldBuilder fieldBuilder) { fieldBuilderMap.putIfAbsent(fieldBuilder.getType(), fieldBuilder); } - public boolean hasField(Class type) { + public boolean hasField(String type) { return fieldBuilderMap.containsKey(type); } - public String getFieldName(Class type) { + public String getFieldName(String type) { return fieldBuilderMap.get(type).getFieldName(); } @@ -56,19 +61,38 @@ public class BuildPlan implements Writer { return methodBuilderMap.containsKey(methodName); } + public void addStaticLine(String line) { + staticLines.add(line); + } + @Override public void write(BufferedWriter writer) throws IOException { writer.write("package " + packageName + ";\n"); + if (!imports.isEmpty()) { + writer.write("\n"); + for (String importName : imports) { + writer.write("import " + importName + ";\n"); + } + } writer.write("\n"); writer.write("public class " + className + " {\n"); - for (FieldBuilder fieldBuilder : fieldBuilderMap.values()) { - fieldBuilder.write(writer); + if (!fieldBuilderMap.isEmpty()) { + for (FieldBuilder fieldBuilder : fieldBuilderMap.values()) { + fieldBuilder.write(writer); + } + writer.write("\n"); } - if (!fieldBuilderMap.isEmpty() && !methodBuilderMap.isEmpty()) { + if (!staticLines.isEmpty()) { + writer.write(" static {\n"); + for (String line : staticLines) { + writer.write(" " + line + "\n"); + } + writer.write(" }\n"); writer.write("\n"); } for (MethodBuilder methodBuilder : methodBuilderMap.values()) { methodBuilder.write(writer); + writer.write("\n"); } writer.write("}\n"); } diff --git a/src/de/steamwar/linkage/plan/FieldBuilder.java b/src/de/steamwar/linkage/plan/FieldBuilder.java index cb67b50..e45bdb2 100644 --- a/src/de/steamwar/linkage/plan/FieldBuilder.java +++ b/src/de/steamwar/linkage/plan/FieldBuilder.java @@ -22,21 +22,25 @@ package de.steamwar.linkage.plan; import de.steamwar.linkage.Writer; import lombok.AllArgsConstructor; import lombok.Getter; +import lombok.RequiredArgsConstructor; import java.io.BufferedWriter; import java.io.IOException; +@RequiredArgsConstructor @AllArgsConstructor public class FieldBuilder implements Writer { @Getter - private Class type; + private final String type; + private final String name; + private String initializer; public String getFieldName() { - return type.getSimpleName(); + return name; } @Override public void write(BufferedWriter writer) throws IOException { - writer.write(" private static " + type.getTypeName() + " " + getFieldName() + ";\n"); + writer.write(" private static " + type + " " + getFieldName() + (initializer == null ? "" : " = " + initializer) + ";\n"); } } diff --git a/src/de/steamwar/linkage/plan/MethodBuilder.java b/src/de/steamwar/linkage/plan/MethodBuilder.java index 68ae453..a1d4a05 100644 --- a/src/de/steamwar/linkage/plan/MethodBuilder.java +++ b/src/de/steamwar/linkage/plan/MethodBuilder.java @@ -31,9 +31,10 @@ import java.util.List; public class MethodBuilder implements Writer { private final String name; - private final Class returnType; + private final String returnType; private List parameters = new ArrayList<>(); private List lines = new ArrayList<>(); + private boolean isPrivate = false; public void addParameter(ParameterBuilder parameterBuilder) { parameters.add(parameterBuilder); @@ -47,9 +48,13 @@ public class MethodBuilder implements Writer { return name; } + public void setPrivate(boolean isPrivate) { + this.isPrivate = isPrivate; + } + @Override public void write(BufferedWriter writer) throws IOException { - writer.write(" public static " + returnType.getTypeName() + " " + getMethodName() + "("); + writer.write(" " + (isPrivate ? "private" : "public") + " static " + returnType + " " + getMethodName() + "("); for (int i = 0; i < parameters.size(); i++) { parameters.get(i).write(writer); if (i < parameters.size() - 1) { @@ -58,8 +63,10 @@ public class MethodBuilder implements Writer { } writer.write(") {"); for (String line : lines) { + writer.write("\n"); writer.write(" " + line); } + writer.write("\n"); writer.write(" }\n"); } } diff --git a/src/de/steamwar/linkage/plan/ParameterBuilder.java b/src/de/steamwar/linkage/plan/ParameterBuilder.java index d856726..192b8a2 100644 --- a/src/de/steamwar/linkage/plan/ParameterBuilder.java +++ b/src/de/steamwar/linkage/plan/ParameterBuilder.java @@ -27,11 +27,11 @@ import java.io.IOException; @AllArgsConstructor public class ParameterBuilder implements Writer { - private Class type; + private String type; private String name; @Override public void write(BufferedWriter writer) throws IOException { - writer.write(type.getTypeName() + " " + name); + writer.write(type + " " + name); } } diff --git a/src/de/steamwar/linkage/types/Command.java b/src/de/steamwar/linkage/types/Command.java index 31b1491..fc522da 100644 --- a/src/de/steamwar/linkage/types/Command.java +++ b/src/de/steamwar/linkage/types/Command.java @@ -19,19 +19,15 @@ package de.steamwar.linkage.types; -import de.steamwar.command.AbstractSWCommand; import de.steamwar.linkage.LinkageType; import de.steamwar.linkage.plan.BuildPlan; import de.steamwar.linkage.plan.MethodBuilder; +import javax.lang.model.element.TypeElement; + public class Command implements LinkageType { @Override - public Class clazzType() { - return AbstractSWCommand.class; - } - - @Override - public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance) { + public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) { } } diff --git a/src/de/steamwar/linkage/types/DisableLink.java b/src/de/steamwar/linkage/types/DisableLink.java index 15175a7..c3cc54a 100644 --- a/src/de/steamwar/linkage/types/DisableLink.java +++ b/src/de/steamwar/linkage/types/DisableLink.java @@ -20,20 +20,21 @@ package de.steamwar.linkage.types; import de.steamwar.linkage.LinkageType; -import de.steamwar.linkage.api.Disable; -import de.steamwar.linkage.api.Enable; import de.steamwar.linkage.plan.BuildPlan; import de.steamwar.linkage.plan.MethodBuilder; +import javax.lang.model.element.TypeElement; +import java.util.Set; + public class DisableLink implements LinkageType { @Override - public Class interfaceType() { - return Disable.class; + public boolean requirements(String superClass, Set interfaces) { + return interfaces.contains("de.steamwar.linkage.api.Disable"); } @Override - public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance) { + public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) { linkageTypeMethod.addLine(instance + ".disable();"); } } diff --git a/src/de/steamwar/linkage/types/EnableLink.java b/src/de/steamwar/linkage/types/EnableLink.java index 400c96d..4b42f86 100644 --- a/src/de/steamwar/linkage/types/EnableLink.java +++ b/src/de/steamwar/linkage/types/EnableLink.java @@ -24,15 +24,18 @@ import de.steamwar.linkage.api.Enable; import de.steamwar.linkage.plan.BuildPlan; import de.steamwar.linkage.plan.MethodBuilder; +import javax.lang.model.element.TypeElement; +import java.util.Set; + public class EnableLink implements LinkageType { @Override - public Class interfaceType() { - return Enable.class; + public boolean requirements(String superClass, Set interfaces) { + return interfaces.contains("de.steamwar.linkage.api.Enable"); } @Override - public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance) { + public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) { linkageTypeMethod.addLine(instance + ".enable();"); } } diff --git a/src/de/steamwar/linkage/types/ListenerLink.java b/src/de/steamwar/linkage/types/ListenerLink.java new file mode 100644 index 0000000..350c944 --- /dev/null +++ b/src/de/steamwar/linkage/types/ListenerLink.java @@ -0,0 +1,114 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.FieldBuilder; +import de.steamwar.linkage.plan.MethodBuilder; +import de.steamwar.linkage.plan.ParameterBuilder; +import lombok.SneakyThrows; + +import javax.lang.model.element.*; +import javax.lang.model.type.DeclaredType; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class ListenerLink implements LinkageType { + + @Override + public boolean requirements(String superClass, Set interfaces) { + if (context == Context.BUNGEE) { + return interfaces.contains("net.md_5.bungee.api.plugin.Listener"); + } else { + return interfaces.contains("org.bukkit.event.Listener"); + } + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) { + if (context == Context.BUNGEE) { + buildPlan.addImport("net.md_5.bungee.api.ProxyServer"); + buildPlan.addImport("de.steamwar.bungeecore.BungeeCore"); + linkageTypeMethod.addLine("ProxyServer.getInstance().getPluginManager().registerListener(BungeeCore.get(), " + instance + ");"); + } else { + Map eventClasses = new HashMap<>(); + Map eventMethods = new HashMap<>(); + + typeElement.getEnclosedElements().stream().filter(e -> e.getKind() == ElementKind.METHOD).map(ExecutableElement.class::cast).filter(e -> { + return e.getAnnotationMirrors().stream().anyMatch(annotationMirror -> { + return annotationMirror.getAnnotationType().asElement().getSimpleName().toString().equals("EventHandler"); + }); + }).forEach(e -> { + TypeElement current = ((TypeElement)((DeclaredType) e.getParameters().get(0).asType()).asElement()); + eventClasses.put(current.getQualifiedName().toString(), current); + eventMethods.put(current, e); + }); + + eventClasses.forEach((s, eventType) -> { + if (buildPlan.hasMethod(s)) return; + buildPlan.addImport("org.bukkit.event.HandlerList"); + buildPlan.addImport("org.bukkit.event.Listener"); + buildPlan.addImport("java.util.function.Consumer"); + buildPlan.addImport("org.bukkit.event.EventPriority"); + buildPlan.addImport("org.bukkit.plugin.RegisteredListener"); + buildPlan.addImport("org.bukkit.plugin.EventExecutor"); + buildPlan.addImport("de.steamwar.core.Core"); + buildPlan.addImport(s); + buildPlan.addField(new FieldBuilder("HandlerList", "handlerList" + eventType.getSimpleName())); + MethodBuilder methodBuilder = new MethodBuilder(eventType.getSimpleName().toString(), "void"); + methodBuilder.addParameter(new ParameterBuilder("Listener", "listener")); + methodBuilder.addParameter(new ParameterBuilder("Consumer<" + eventType.getSimpleName() + ">", "consumer")); + methodBuilder.addParameter(new ParameterBuilder("EventPriority", "eventPriority")); + methodBuilder.addParameter(new ParameterBuilder("boolean", "ignoreCancelled")); + methodBuilder.setPrivate(true); + methodBuilder.addLine("EventExecutor eventExecutor = (l, event) -> {"); + methodBuilder.addLine(" if (event instanceof " + eventType.getSimpleName() + ") {"); + methodBuilder.addLine(" consumer.accept((" + eventType.getSimpleName() + ") event);"); + methodBuilder.addLine(" }"); + methodBuilder.addLine("};"); + methodBuilder.addLine("handlerList" + eventType.getSimpleName() + ".register(new RegisteredListener(listener, eventExecutor, eventPriority, Core.getInstance(), ignoreCancelled));"); + buildPlan.addMethod(methodBuilder); + linkageTypeMethod.addLine("handlerList" + eventType.getSimpleName() + " = " + s + ".getHandlerList();"); + }); + + buildPlan.addImport(typeElement.getQualifiedName().toString()); + String localInstance = "local" + typeElement.getSimpleName().toString(); + linkageTypeMethod.addLine(typeElement.getSimpleName() + " " + localInstance + " = " + instance + ";"); + eventMethods.forEach((type, executableElement) -> { + AnnotationMirror eventHandler = executableElement.getAnnotationMirrors().stream().filter(annotationMirror -> annotationMirror.getAnnotationType().asElement().getSimpleName().toString().equals("EventHandler")).findFirst().orElse(null); + if (eventHandler == null) { + return; + } + String priority = "NORMAL"; + String ignoreCancelled = "false"; + for (Map.Entry entry : eventHandler.getElementValues().entrySet()) { + if (entry.getKey().getSimpleName().toString().equals("priority")) { + priority = entry.getValue().getValue().toString(); + } else if (entry.getKey().getSimpleName().toString().equals("ignoreCancelled")) { + ignoreCancelled = entry.getValue().getValue().toString(); + } + } + linkageTypeMethod.addLine(type.getSimpleName().toString() + "(" + localInstance + ", " + localInstance + "::" + executableElement.getSimpleName().toString() + ", EventPriority." + priority + ", " + ignoreCancelled + ");"); + }); + } + } +} diff --git a/src/de/steamwar/linkage/types/Plain.java b/src/de/steamwar/linkage/types/Plain.java index d25fa48..1890521 100644 --- a/src/de/steamwar/linkage/types/Plain.java +++ b/src/de/steamwar/linkage/types/Plain.java @@ -23,10 +23,12 @@ import de.steamwar.linkage.LinkageType; import de.steamwar.linkage.plan.BuildPlan; import de.steamwar.linkage.plan.MethodBuilder; +import javax.lang.model.element.TypeElement; + public class Plain implements LinkageType { @Override - public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance) { + public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) { linkageTypeMethod.addLine(instance + ";"); } } diff --git a/src/de/steamwar/linkage/types/UnlinkListener.java b/src/de/steamwar/linkage/types/UnlinkListener.java new file mode 100644 index 0000000..73966a7 --- /dev/null +++ b/src/de/steamwar/linkage/types/UnlinkListener.java @@ -0,0 +1,51 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2020 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.linkage.types; + +import de.steamwar.linkage.LinkageType; +import de.steamwar.linkage.plan.BuildPlan; +import de.steamwar.linkage.plan.MethodBuilder; + +import javax.lang.model.element.TypeElement; +import java.util.Set; + +public class UnlinkListener implements LinkageType { + + @Override + public boolean requirements(String superClass, Set interfaces) { + if (context == Context.BUNGEE) { + return interfaces.contains("net.md_5.bungee.api.plugin.Listener"); + } else { + return interfaces.contains("org.bukkit.event.Listener"); + } + } + + @Override + public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) { + if (context == Context.BUNGEE) { + buildPlan.addImport("net.md_5.bungee.api.ProxyServer"); + buildPlan.addImport("de.steamwar.bungeecore.BungeeCore"); + linkageTypeMethod.addLine("ProxyServer.getInstance().getPluginManager().registerListener(" + instance + ");"); + } else { + buildPlan.addImport("org.bukkit.event.HandlerList"); + linkageTypeMethod.addLine("HandlerList.unregisterAll(" + instance + ");"); + } + } +}