Linkage #22

Zusammengeführt
Lixfel hat 4 Commits von Linkage nach master 2022-09-24 19:44:12 +02:00 zusammengeführt
16 geänderte Dateien mit 137 neuen und 168 gelöschten Zeilen
Nur Änderungen aus Commit 75ff0c3d45 werden angezeigt - Alle Commits anzeigen

Datei anzeigen

@ -31,6 +31,6 @@ public @interface AllowedContexts {
/**
* The context in which this annotation is valid.
*/
LinkageType.Context[] value();
Context[] value();
}

Datei anzeigen

@ -19,13 +19,7 @@
package de.steamwar.linkage;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@AllowedContexts(LinkageType.Context.BUNGEE)
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface DiscordMode {
public enum Context {
BUNGEE,
SPIGOT
}

Datei anzeigen

@ -27,7 +27,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@AllowedContexts(LinkageType.Context.BUNGEE)
@AllowedContexts(Context.BUNGEE)
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface EventMode {

Datei anzeigen

@ -22,33 +22,27 @@ 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 lombok.Getter;
import lombok.SneakyThrows;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.*;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import java.io.*;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@SupportedAnnotationTypes("de.steamwar.linkage.Linked")
public class LinkageProcessor extends AbstractProcessor {
@Getter
private static LinkageType.Context context;
private static Context context;
@Getter
private static String pluginMain;
@ -65,13 +59,6 @@ public class LinkageProcessor extends AbstractProcessor {
return SourceVersion.latestSupported();
}
@Override
public Set<String> getSupportedAnnotationTypes() {
return Stream.of(Linked.class, Linked.Linkages.class)
.map(Class::getCanonicalName)
.collect(Collectors.toSet());
}
@SneakyThrows
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
@ -101,7 +88,7 @@ public class LinkageProcessor extends AbstractProcessor {
messager.printMessage(Diagnostic.Kind.ERROR, "Could not find plugin.yml or bungee.yml");
return;
}
context = pluginYMLFile.get().getName().equals("bungee.yml") ? LinkageType.Context.BUNGEE : LinkageType.Context.SPIGOT;
context = pluginYMLFile.get().getName().equals("bungee.yml") ? Context.BUNGEE : Context.SPIGOT;
Optional<String> mainName = getMainName(pluginYMLFile.get());
if (!mainName.isPresent()) {
messager.printMessage(Diagnostic.Kind.ERROR, "Could not find main class in plugin.yml or bungee.yml");
@ -134,36 +121,19 @@ public class LinkageProcessor extends AbstractProcessor {
buildPlan.addImport("java.lang.Class");
buildPlan.addImport("de.steamwar.linkage.LinkageType");
buildPlan.addImport("java.util.HashSet");
buildPlan.addField(new FieldBuilder("Set<Class<? extends LinkageType>>", "enabled", "new HashSet<>()"));
MethodBuilder runsMethod = new MethodBuilder("run", "void");
runsMethod.addParameter(new ParameterBuilder("Class<? extends LinkageType>...", "types"));
runsMethod.addLine("for (Class<? extends LinkageType> type : types) _run(type);");
buildPlan.addMethod(runsMethod);
MethodBuilder runMethod = new MethodBuilder("_run", "void");
runMethod.setPrivate(true);
buildPlan.addMethod(runMethod);
runMethod.addParameter(new ParameterBuilder("Class<? extends LinkageType>", "type"));
runMethod.addLine("if (!enabled.add(type)) return;");
Set<Class<? extends LinkageType>> alreadyGenerated = new HashSet<>();
Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(Linked.class);
elements.addAll((Set) roundEnv.getElementsAnnotatedWith(Linked.Linkages.class));
Map<String, TypeElement> 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) {
Linked linked = element.getAnnotation(Linked.class);
if (linked == null) {
continue;
}
if (linkeds.length > 1) {
if (getLinkagesOfType(typeElement).size() > 1) {
neededFields.put(typeElement.getQualifiedName().toString(), typeElement);
}
@ -211,7 +181,7 @@ public class LinkageProcessor extends AbstractProcessor {
buildPlan.addMethod(initializer);
});
Map<Class<?>, MethodBuilder> methods = new HashMap<>();
Map<String, MethodBuilder> methods = new HashMap<>();
for (Element element : elements) {
if (element.getKind() != ElementKind.CLASS) {
continue;
@ -219,65 +189,21 @@ public class LinkageProcessor extends AbstractProcessor {
TypeElement typeElement = (TypeElement) element;
System.out.println("Found element: " + typeElement.getQualifiedName().toString());
element.getAnnotationMirrors().stream()
.filter(annotationMirror -> {
String annotationNames = annotationMirror.getAnnotationType().asElement().getSimpleName().toString();
return annotationNames.equals("Linked") || annotationNames.equals("Linkages");
})
.flatMap(annotationMirror -> annotationMirror.getElementValues().values().stream())
.map(AnnotationValue::getValue)
.flatMap(o -> {
if (o instanceof List) {
return ((List<Object>) o).stream()
.map(AnnotationMirror.class::cast)
.map(AnnotationMirror::getElementValues)
.map(Map::values)
.flatMap(Collection::stream)
.map(AnnotationValue::getValue);
}
return Stream.of(o);
})
.map(Object::toString)
.map(s -> {
try {
return Class.forName(s);
} catch (Exception e) {
messager.printMessage(Diagnostic.Kind.ERROR, "Could not find class " + s, element);
return null;
}
})
.filter(Objects::nonNull)
.map(clazz -> {
try {
return (LinkageType) clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
messager.printMessage(Diagnostic.Kind.ERROR, "Could not create instance of " + clazz.getName(), element);
return null;
}
})
.filter(Objects::nonNull)
.forEach(type -> {
Class<? extends LinkageType> clazz = type.getClass();
if (!type.requirements(typeElement.getSuperclass().toString(), typeElement.getInterfaces().stream().map(TypeMirror::toString).collect(Collectors.toSet()), typeElement)) {
return;
}
Map<String, List<LinkageType>> linkages = getLinkagesOfType(typeElement);
if (linkages.isEmpty()) {
continue;
}
if (alreadyGenerated.add(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;
});
specialElements(typeElement, buildPlan, method::addLine, () -> {
type.generateCode(buildPlan, method, getElement(typeElement, neededFields), typeElement);
});
for (Map.Entry<String, List<LinkageType>> entry : linkages.entrySet()) {
MethodBuilder method = methods.computeIfAbsent(entry.getKey(), s -> {
return new MethodBuilder(s, "void");
});
for (LinkageType type : entry.getValue()) {
specialElements(typeElement, buildPlan, method::addLine, () -> {
type.generateCode(buildPlan, method, getElement(typeElement, neededFields), typeElement);
});
}
}
}
BufferedWriter bufferedWriter = new BufferedWriter(writer);
@ -297,10 +223,9 @@ public class LinkageProcessor extends AbstractProcessor {
MinVersion minVersion = typeElement.getAnnotation(MinVersion.class);
MaxVersion maxVersion = typeElement.getAnnotation(MaxVersion.class);
EventMode eventMode = typeElement.getAnnotation(EventMode.class);
DiscordMode discordMode = typeElement.getAnnotation(DiscordMode.class);
PluginCheck[] pluginChecks = typeElement.getAnnotationsByType(PluginCheck.class);
if (context == LinkageType.Context.SPIGOT) {
errorOnNonNull(typeElement, eventMode, discordMode);
if (context == Context.SPIGOT) {
errorOnNonNull(typeElement, eventMode);
List<String> checks = new ArrayList<>();
if (minVersion != null) {
buildPlan.addImport("de.steamwar.core.Core");
@ -326,10 +251,6 @@ public class LinkageProcessor extends AbstractProcessor {
buildPlan.addImport("de.steamwar.bungeecore.BungeeCore");
checks.add(eventMode.value().getPrefix() + "BungeeCore.EVENT_MODE");
}
if (discordMode != null) {
buildPlan.addImport("de.steamwar.bungeecore.bot.config.SteamwarDiscordBotConfig");
checks.add("SteamwarDiscordBotConfig.loaded");
}
if (pluginChecks.length != 0) {
buildPlan.addImport("net.md_5.bungee.BungeeCord");
Arrays.stream(pluginChecks).map(pluginCheck -> {
@ -349,4 +270,35 @@ public class LinkageProcessor extends AbstractProcessor {
}
}
}
private Map<String, List<LinkageType>> getLinkagesOfType(TypeElement typeElement) {
Map<String, List<LinkageType>> linkages = new HashMap<>();
LinkageType superClassType = resolveSingle(typeElement.getSuperclass());
if (superClassType != null) {
linkages.computeIfAbsent(superClassType.method(), s -> new ArrayList<>()).add(superClassType);
}
for (TypeMirror typeMirror : typeElement.getInterfaces()) {
LinkageType interfaceType = resolveSingle(typeMirror);
if (interfaceType != null) {
linkages.computeIfAbsent(interfaceType.method(), s -> new ArrayList<>()).add(interfaceType);
}
}
return linkages;
}
private LinkageType resolveSingle(TypeMirror typeMirror) {
String qualifier = typeMirror.toString();
qualifier = qualifier.substring(qualifier.lastIndexOf('.') + 1);
try {
return (LinkageType) Class.forName("de.steamwar.linkage.types." + qualifier + context.name()).getDeclaredConstructor().newInstance();
} catch (Exception e) {
// Ignore
}
try {
return (LinkageType) Class.forName("de.steamwar.linkage.types." + qualifier).getDeclaredConstructor().newInstance();
} catch (Exception e) {
// Ignore
}
return null;
}
}

Datei anzeigen

@ -23,36 +23,14 @@ import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
import java.util.Set;
public interface LinkageType {
Context context = LinkageProcessor.getContext();
default String getPluginMain() {
return LinkageProcessor.getPluginMain();
}
enum Context {
BUNGEE,
SPIGOT
}
String method();
YoyoNow markierte diese Unterhaltung als gelöst
Review

Hier werden soweit ich gesehen immer nur "link" oder "unlink" übergeben. Wie wäre es stattdessen in der generateCode-Methode einfach beide MethodBuilder "link" und "unlink" reinzureichen?

Hier werden soweit ich gesehen immer nur "link" oder "unlink" übergeben. Wie wäre es stattdessen in der generateCode-Methode einfach beide MethodBuilder "link" und "unlink" reinzureichen?
Review

Nein, dies geht nicht weil ich im BauSystem eigene brauche, welche in eigenen methoden landen sollen!

Nein, dies geht nicht weil ich im BauSystem eigene brauche, welche in eigenen methoden landen sollen!
default boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {
return true;
}
default void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
switch (context) {
case BUNGEE:
generateCodeBungee(buildPlan, linkageTypeMethod, instance, typeElement);
break;
case SPIGOT:
generateCodeSpigot(buildPlan, linkageTypeMethod, instance, typeElement);
break;
}
}
default void generateCodeBungee(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
}
default void generateCodeSpigot(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
}
void generateCode(BuildPlan buildPlan, MethodBuilder method, String instance, TypeElement typeElement);
}

Datei anzeigen

@ -0,0 +1,52 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2022 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 <https://www.gnu.org/licenses/>.
*/
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.Set;
public interface LinkageTypeOld {
default String getPluginMain() {
return LinkageProcessor.getPluginMain();
}
default boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {
return true;
}
default void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
switch (context) {
case BUNGEE:
generateCodeBungee(buildPlan, linkageTypeMethod, instance, typeElement);
break;
case SPIGOT:
generateCodeSpigot(buildPlan, linkageTypeMethod, instance, typeElement);
break;
}
}
default void generateCodeBungee(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
}
default void generateCodeSpigot(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
}
}

Datei anzeigen

@ -23,13 +23,5 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
@Repeatable(Linked.Linkages.class)
public @interface Linked {
Class<? extends LinkageType> value();
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
@interface Linkages {
@SuppressWarnings("unused") Linked[] value() default {};
}
}

Datei anzeigen

@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@AllowedContexts(LinkageType.Context.SPIGOT)
@AllowedContexts(Context.SPIGOT)
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface MaxVersion {

Datei anzeigen

@ -24,7 +24,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@AllowedContexts(LinkageType.Context.SPIGOT)
@AllowedContexts(Context.SPIGOT)
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
public @interface MinVersion {

Datei anzeigen

@ -21,7 +21,7 @@ package de.steamwar.linkage;
import java.lang.annotation.*;
@AllowedContexts({LinkageType.Context.BUNGEE, LinkageType.Context.SPIGOT})
@AllowedContexts({Context.BUNGEE, Context.SPIGOT})
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE})
@Repeatable(PluginCheck.PluginChecks.class)

Datei anzeigen

@ -17,16 +17,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
package de.steamwar.linkage.typesold;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.LinkageTypeOld;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
import java.util.Set;
public class Command implements LinkageType {
public class Command implements LinkageTypeOld {
@Override
public boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {

Datei anzeigen

@ -17,16 +17,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
package de.steamwar.linkage.typesold;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.LinkageTypeOld;
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 {
public class DisableLink implements LinkageTypeOld {
@Override
public boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {

Datei anzeigen

@ -17,16 +17,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
package de.steamwar.linkage.typesold;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.LinkageTypeOld;
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 {
public class EnableLink implements LinkageTypeOld {
@Override
public boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {

Datei anzeigen

@ -17,9 +17,10 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
package de.steamwar.linkage.typesold;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.Context;
import de.steamwar.linkage.LinkageTypeOld;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.FieldBuilder;
import de.steamwar.linkage.plan.MethodBuilder;
@ -31,7 +32,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class ListenerLink implements LinkageType {
public class ListenerLink implements LinkageTypeOld {
@Override
public boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {

Datei anzeigen

@ -17,15 +17,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
package de.steamwar.linkage.typesold;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.LinkageTypeOld;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
public class Plain implements LinkageType {
public class Plain implements LinkageTypeOld {
@Override
public void generateCode(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {

Datei anzeigen

@ -17,17 +17,17 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.linkage.types;
package de.steamwar.linkage.typesold;
import de.steamwar.linkage.LinkageType;
import de.steamwar.linkage.Context;
import de.steamwar.linkage.LinkageTypeOld;
import de.steamwar.linkage.plan.BuildPlan;
import de.steamwar.linkage.plan.MethodBuilder;
import javax.lang.model.element.TypeElement;
import java.lang.reflect.Type;
import java.util.Set;
public class UnlinkListener implements LinkageType {
public class UnlinkListener implements LinkageTypeOld {
@Override
public boolean requirements(String superClass, Set<String> interfaces, TypeElement typeElement) {
@ -42,7 +42,7 @@ public class UnlinkListener implements LinkageType {
public void generateCodeBungee(BuildPlan buildPlan, MethodBuilder linkageTypeMethod, String instance, TypeElement typeElement) {
buildPlan.addImport("net.md_5.bungee.api.ProxyServer");
buildPlan.addImport("de.steamwar.bungeecore.BungeeCore");
linkageTypeMethod.addLine("ProxyServer.getInstance().getPluginManager().registerListener(" + instance + ");");
linkageTypeMethod.addLine("ProxyServer.getInstance().getPluginManager().unregisterListener(" + instance + ");");
}
@Override