mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 17:27:38 +00:00
Add new annotations from upstream
This commit is contained in:
parent
1e80c0429a
commit
204de7eab5
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.internal.util;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.base.Throwables;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class DeprecationUtil {
|
||||
|
||||
private DeprecationUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that one of the two functions is overridden. Caller method must be the new method,
|
||||
* annotated with {@link NonAbstractForCompatibility}.
|
||||
*
|
||||
* @param implementingClass the result of calling {@link Object#getClass()}
|
||||
*/
|
||||
public static void checkDelegatingOverride(Class<?> implementingClass) {
|
||||
// pull the information about the caller
|
||||
StackTraceElement caller = Throwables.lazyStackTrace(new Throwable()).get(1);
|
||||
// find the matching caller method
|
||||
Method callingMethod = getCallingMethod(caller);
|
||||
NonAbstractForCompatibility annotation =
|
||||
callingMethod.getAnnotation(NonAbstractForCompatibility.class);
|
||||
// get the deprecated method
|
||||
Method deprecatedMethod;
|
||||
try {
|
||||
deprecatedMethod = implementingClass.getMethod(
|
||||
annotation.delegateName(), annotation.delegateParams()
|
||||
);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new AssertionError(
|
||||
"Missing method referenced by " + NonAbstractForCompatibility.class, e
|
||||
);
|
||||
}
|
||||
// Check if the deprecated method was overridden. If the declaring class is the caller's
|
||||
// class, then it wasn't. That means that the caller method (i.e. the new method) should be
|
||||
// overridden by the implementing class.
|
||||
// There's no need to check if the new method has been overridden, since the only other
|
||||
// way this could be reached is if someone calls `super.xyz`, which they have no reason to.
|
||||
if (deprecatedMethod.getDeclaringClass().getName().equals(caller.getClassName())) {
|
||||
throw new IllegalStateException("Class " + implementingClass.getName()
|
||||
+ " must override " + methodToString(callingMethod));
|
||||
}
|
||||
}
|
||||
|
||||
private static Method getCallingMethod(StackTraceElement callerInfo) {
|
||||
Method[] declaredMethods;
|
||||
try {
|
||||
declaredMethods = Class.forName(callerInfo.getClassName()).getDeclaredMethods();
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new AssertionError("Caller class missing?", e);
|
||||
}
|
||||
for (Method declaredMethod : declaredMethods) {
|
||||
if (declaredMethod.isAnnotationPresent(NonAbstractForCompatibility.class) &&
|
||||
declaredMethod.getName().equals(callerInfo.getMethodName())) {
|
||||
return declaredMethod;
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("Failed to find caller method " +
|
||||
callerInfo.getMethodName() + " annotated with " + NonAbstractForCompatibility.class);
|
||||
}
|
||||
|
||||
private static String methodToString(Method method) {
|
||||
StringBuilder builder = new StringBuilder(method.getDeclaringClass().getCanonicalName())
|
||||
.append('.')
|
||||
.append(method.getName())
|
||||
.append('(');
|
||||
Joiner.on(", ").appendTo(builder, Stream.of(method.getParameterTypes())
|
||||
.map(Class::getSimpleName)
|
||||
.iterator());
|
||||
builder.append(')');
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser 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 Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.internal.util;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* The annotated method is only non-{@code abstract} for compatibility with old subclasses,
|
||||
* and will be made {@code abstract} in the next major version of WorldEdit.
|
||||
*
|
||||
* <p>
|
||||
* Any new subclasses <em>must</em> override the annotated method, failing to do so will result in
|
||||
* an exception at runtime.
|
||||
* </p>
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface NonAbstractForCompatibility {
|
||||
|
||||
// Note that this annotation only functions properly if no other method in the same class
|
||||
// shares the name of the annotated function AND is also annotated with this annotation.
|
||||
// Otherwise, we cannot uniquely determine the calling method via reflection hacks.
|
||||
// This could be changed, but it's not currently necessary.
|
||||
|
||||
/**
|
||||
* The name of the method delegated to by the annotated method.
|
||||
*/
|
||||
String delegateName();
|
||||
|
||||
/**
|
||||
* The parameter types of the method delegated to by the annotated method.
|
||||
*/
|
||||
Class<?>[] delegateParams();
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user