mirror of
https://github.com/IntellectualSites/PlotSquared.git
synced 2025-10-25 15:43:44 +02:00
chore: improve readability of method retrieval
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.plotsquared.bukkit.schematic;
|
package com.plotsquared.bukkit.schematic;
|
||||||
|
|
||||||
|
import com.plotsquared.core.util.ReflectionHelper;
|
||||||
import com.plotsquared.core.util.ReflectionUtils;
|
import com.plotsquared.core.util.ReflectionUtils;
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
|
||||||
@@ -236,13 +237,11 @@ final class StateWrapperSpigot implements StateWrapper {
|
|||||||
|
|
||||||
private static MethodHandle findCraftBlockEntityStateUpdateMethodHandle(Class<?> craftBlockEntityStateClass) throws
|
private static MethodHandle findCraftBlockEntityStateUpdateMethodHandle(Class<?> craftBlockEntityStateClass) throws
|
||||||
NoSuchMethodException, IllegalAccessException {
|
NoSuchMethodException, IllegalAccessException {
|
||||||
for (final Method method : craftBlockEntityStateClass.getMethods()) {
|
return LOOKUP.unreflect(ReflectionHelper.findMethod(
|
||||||
if (method.getReturnType().equals(Boolean.TYPE) && method.getParameterCount() == 2 &&
|
craftBlockEntityStateClass,
|
||||||
method.getParameterTypes()[0] == Boolean.TYPE && method.getParameterTypes()[1] == Boolean.TYPE) {
|
MethodType.methodType(Boolean.TYPE, Boolean.TYPE, Boolean.TYPE),
|
||||||
return LOOKUP.unreflect(method);
|
Modifier.PUBLIC
|
||||||
}
|
).orElseThrow(() -> new NoSuchMethodException("Couldn't lookup CraftBlockEntityState#update(boolean, boolean) boolean")));
|
||||||
}
|
|
||||||
throw new NoSuchMethodException("Couldn't find method for #update(boolean, boolean) in " + craftBlockEntityStateClass.getName());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static MethodHandle findCraftBlockEntityStateSnapshotMethodHandle(Class<?> craftBlockEntityStateClass) throws
|
private static MethodHandle findCraftBlockEntityStateSnapshotMethodHandle(Class<?> craftBlockEntityStateClass) throws
|
||||||
@@ -254,13 +253,11 @@ final class StateWrapperSpigot implements StateWrapper {
|
|||||||
|
|
||||||
private static MethodHandle findSignBlockEntitySetTextMethodHandle(Class<?> signBlockEntity, Class<?> signText) throws
|
private static MethodHandle findSignBlockEntitySetTextMethodHandle(Class<?> signBlockEntity, Class<?> signText) throws
|
||||||
NoSuchMethodException, IllegalAccessException {
|
NoSuchMethodException, IllegalAccessException {
|
||||||
for (final Method method : signBlockEntity.getMethods()) {
|
return LOOKUP.unreflect(ReflectionHelper.findMethod(
|
||||||
if (method.getReturnType() == Boolean.TYPE && method.getParameterCount() == 2
|
signBlockEntity,
|
||||||
&& method.getParameterTypes()[0] == signText && method.getParameterTypes()[1] == Boolean.TYPE) {
|
MethodType.methodType(Boolean.TYPE, signText, Boolean.TYPE),
|
||||||
return LOOKUP.unreflect(method);
|
Modifier.PUBLIC
|
||||||
}
|
).orElseThrow(() -> new NoSuchMethodException("Couldn't lookup SignBlockEntity#setText(SignText, boolean) boolean")));
|
||||||
}
|
|
||||||
throw new NoSuchMethodException("Couldn't lookup SignBlockEntity#setText(SignText, boolean) boolean");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* PlotSquared, a land and world management plugin for Minecraft.
|
||||||
|
* Copyright (C) IntellectualSites <https://intellectualsites.com>
|
||||||
|
* Copyright (C) IntellectualSites team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.plotsquared.core.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.ApiStatus;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ApiStatus.Internal
|
||||||
|
public final class ReflectionHelper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a (declared) method with an unknown or potentially obfuscated name by its signature and optional modifiers.
|
||||||
|
* <br>
|
||||||
|
* The method - if private - is not made accessible. Either call {@link Method#setAccessible(boolean)} or
|
||||||
|
* use a {@link java.lang.invoke.MethodHandles.Lookup#privateLookupIn(Class, MethodHandles.Lookup) private lookup}.
|
||||||
|
*
|
||||||
|
* @param holder The class providing the method.
|
||||||
|
* @param signature The signature of the method, identified by parameter types and the return type.
|
||||||
|
* @param modifiers All possible modifiers of the method that should be validated.
|
||||||
|
* @return The method, if one has been found. Otherwise, an empty Optional.
|
||||||
|
* @throws RuntimeException if multiple matching methods have been found.
|
||||||
|
* @see java.lang.reflect.Modifier
|
||||||
|
*/
|
||||||
|
public static Optional<Method> findMethod(Class<?> holder, MethodType signature, int... modifiers) {
|
||||||
|
Method found = null;
|
||||||
|
outer:
|
||||||
|
for (final Method method : holder.getDeclaredMethods()) {
|
||||||
|
if (method.getParameterCount() != signature.parameterCount()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!signature.returnType().isAssignableFrom(method.getReturnType())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final int modifier : modifiers) {
|
||||||
|
if ((method.getModifiers() & modifier) == 0) {
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<?>[] parameterTypes = signature.parameterArray();
|
||||||
|
for (int i = 0; i < parameterTypes.length; i++) {
|
||||||
|
// validate expected parameter is either the same type or subtype of actual parameter
|
||||||
|
if (!parameterTypes[i].isAssignableFrom(method.getParameterTypes()[i])) {
|
||||||
|
continue outer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found != null) {
|
||||||
|
throw new RuntimeException("Found ambiguous method by selector: " + method + " vs " + found);
|
||||||
|
}
|
||||||
|
found = method;
|
||||||
|
}
|
||||||
|
return Optional.ofNullable(found);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* PlotSquared, a land and world management plugin for Minecraft.
|
||||||
|
* Copyright (C) IntellectualSites <https://intellectualsites.com>
|
||||||
|
* Copyright (C) IntellectualSites team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package com.plotsquared.core.util;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodType;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
class ReflectionHelperTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void findMethod() throws NoSuchMethodException {
|
||||||
|
assertThrows(
|
||||||
|
RuntimeException.class, () ->
|
||||||
|
ReflectionHelper.findMethod(MethodTesterClass.class, MethodType.methodType(String.class))
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
MethodTesterClass.class.getMethod("methodThree"),
|
||||||
|
ReflectionHelper.findMethod(MethodTesterClass.class, MethodType.methodType(String.class), Modifier.PUBLIC)
|
||||||
|
.orElse(null)
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
MethodTesterClass.class.getDeclaredMethod("methodFour", String.class, Collection.class),
|
||||||
|
ReflectionHelper.findMethod(MethodTesterClass.class, MethodType.methodType(
|
||||||
|
String.class, String.class, Collection.class
|
||||||
|
)).orElse(null)
|
||||||
|
);
|
||||||
|
// check that helper allows super classes of parameters when searching
|
||||||
|
assertEquals(
|
||||||
|
MethodTesterClass.class.getDeclaredMethod("methodFour", String.class, Collection.class),
|
||||||
|
ReflectionHelper.findMethod(MethodTesterClass.class, MethodType.methodType(
|
||||||
|
String.class, String.class, Object.class
|
||||||
|
)).orElse(null)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static class MethodTesterClass {
|
||||||
|
|
||||||
|
private static String methodOne() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String methodTwo() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String methodThree() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static String methodFour(String param, Collection<String> paramList) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user