Diff
checker
文本
文本
图像
文档
Excel
文件夹
Legal
Enterprise
桌面版
定价
登录
下载 Diffchecker 桌面版
比较文本
查找两个文本文件之间的差异
工具
历史
实时编辑器
折叠未更改行
关闭换行
视图
拆分
统一
比对精度
智能
单词
字符
语法高亮
选择语法
忽略
文本转换
转到第一个差异
编辑输入
Diffchecker Desktop
运行Diffchecker最安全的方式。获取Diffchecker桌面应用:您的差异永远不会离开您的电脑!
获取桌面版
Untitled diff
创建于
9年前
差异永不过期
清除
导出
分享
解释
0 删除
行
总计
删除
字符
总计
删除
要继续使用此功能,请升级到
Diff
checker
Pro
查看价格
375 行
全部复制
5 添加
行
总计
添加
字符
总计
添加
要继续使用此功能,请升级到
Diff
checker
Pro
查看价格
377 行
全部复制
/*
/*
* Minecraft Forge
* Minecraft Forge
* Copyright (c) 2016.
* Copyright (c) 2016.
*
*
* This library is free software; you can redistribute it and/or
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* License as published by the Free Software Foundation version 2.1
* of the License.
* of the License.
*
*
* This library is distributed in the hope that it will be useful,
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
*/
package net.minecraftforge.common.util;
package net.minecraftforge.common.util;
import java.lang.reflect.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.*;
复制
已复制
复制
已复制
import com.google.common.base.Predicate;
import com.google.common.collect.Lists;
import com.google.common.collect.Lists;
import net.minecraftforge.fml.common.EnhancedRuntimeException;
import net.minecraftforge.fml.common.EnhancedRuntimeException;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraftforge.fml.common.FMLLog;
import net.minecraft.block.BlockPressurePlate.Sensitivity;
import net.minecraft.block.BlockPressurePlate.Sensitivity;
import net.minecraft.block.material.Material;
import net.minecraft.block.material.Material;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.enchantment.EnumEnchantmentType;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.item.EntityPainting.EnumArt;
import net.minecraft.entity.item.EntityPainting.EnumArt;
import net.minecraft.entity.player.EntityPlayer.SleepResult;
import net.minecraft.entity.player.EntityPlayer.SleepResult;
import net.minecraft.item.EnumAction;
import net.minecraft.item.EnumAction;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.EnumRarity;
复制
已复制
复制
已复制
import net.minecraft.item.Item;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.item.ItemArmor.ArmorMaterial;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.EnumSkyBlock;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door;
import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door;
import net.minecraftforge.classloading.FMLForgePlugin;
import net.minecraftforge.classloading.FMLForgePlugin;
public class EnumHelper
public class EnumHelper
{
{
private static Object reflectionFactory = null;
private static Object reflectionFactory = null;
private static Method newConstructorAccessor = null;
private static Method newConstructorAccessor = null;
private static Method newInstance = null;
private static Method newInstance = null;
private static Method newFieldAccessor = null;
private static Method newFieldAccessor = null;
private static Method fieldAccessorSet = null;
private static Method fieldAccessorSet = null;
private static boolean isSetup = false;
private static boolean isSetup = false;
//Some enums are decompiled with extra arguments, so lets check for that
//Some enums are decompiled with extra arguments, so lets check for that
private static Class<?>[][] commonTypes =
private static Class<?>[][] commonTypes =
{
{
{EnumAction.class},
{EnumAction.class},
{ArmorMaterial.class, String.class, int.class, int[].class, int.class, SoundEvent.class, float.class},
{ArmorMaterial.class, String.class, int.class, int[].class, int.class, SoundEvent.class, float.class},
{EnumArt.class, String.class, int.class, int.class, int.class, int.class},
{EnumArt.class, String.class, int.class, int.class, int.class, int.class},
{EnumCreatureAttribute.class},
{EnumCreatureAttribute.class},
{EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class},
{EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class},
{Door.class},
{Door.class},
复制
已复制
复制
已复制
{EnumEnchantmentType.class
},
{EnumEnchantmentType.class
, Predicate.class
},
{Sensitivity.class},
{Sensitivity.class},
{RayTraceResult.Type.class},
{RayTraceResult.Type.class},
{EnumSkyBlock.class, int.class},
{EnumSkyBlock.class, int.class},
{SleepResult.class},
{SleepResult.class},
{ToolMaterial.class, int.class, int.class, float.class, float.class, int.class},
{ToolMaterial.class, int.class, int.class, float.class, float.class, int.class},
{EnumRarity.class, TextFormatting.class, String.class}
{EnumRarity.class, TextFormatting.class, String.class}
};
};
public static EnumAction addAction(String name)
public static EnumAction addAction(String name)
{
{
return addEnum(EnumAction.class, name);
return addEnum(EnumAction.class, name);
}
}
public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability, SoundEvent soundOnEquip, float toughness)
public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability, SoundEvent soundOnEquip, float toughness)
{
{
return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability, soundOnEquip, toughness);
return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability, soundOnEquip, toughness);
}
}
public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY)
public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY)
{
{
return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY);
return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY);
}
}
public static EnumCreatureAttribute addCreatureAttribute(String name)
public static EnumCreatureAttribute addCreatureAttribute(String name)
{
{
return addEnum(EnumCreatureAttribute.class, name);
return addEnum(EnumCreatureAttribute.class, name);
}
}
public static EnumCreatureType addCreatureType(String name, Class<?> typeClass, int maxNumber, Material material, boolean peaceful, boolean animal)
public static EnumCreatureType addCreatureType(String name, Class<?> typeClass, int maxNumber, Material material, boolean peaceful, boolean animal)
{
{
return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal);
return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal);
}
}
public static Door addDoor(String name)
public static Door addDoor(String name)
{
{
return addEnum(Door.class, name);
return addEnum(Door.class, name);
}
}
复制
已复制
复制
已复制
public static EnumEnchantmentType addEnchantmentType(String name
)
public static EnumEnchantmentType addEnchantmentType(String name
, Predicate<Item> delegate
)
{
{
复制
已复制
复制
已复制
return addEnum(EnumEnchantmentType.class, name
);
return addEnum(EnumEnchantmentType.class, name
, delegate
);
}
}
public static Sensitivity addSensitivity(String name)
public static Sensitivity addSensitivity(String name)
{
{
return addEnum(Sensitivity.class, name);
return addEnum(Sensitivity.class, name);
}
}
public static RayTraceResult.Type addMovingObjectType(String name)
public static RayTraceResult.Type addMovingObjectType(String name)
{
{
return addEnum(RayTraceResult.Type.class, name);
return addEnum(RayTraceResult.Type.class, name);
}
}
public static EnumSkyBlock addSkyBlock(String name, int lightValue)
public static EnumSkyBlock addSkyBlock(String name, int lightValue)
{
{
return addEnum(EnumSkyBlock.class, name, lightValue);
return addEnum(EnumSkyBlock.class, name, lightValue);
}
}
public static SleepResult addStatus(String name)
public static SleepResult addStatus(String name)
{
{
return addEnum(SleepResult.class, name);
return addEnum(SleepResult.class, name);
}
}
public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability)
public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability)
{
{
return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability);
return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability);
}
}
public static EnumRarity addRarity(String name, TextFormatting color, String displayName)
public static EnumRarity addRarity(String name, TextFormatting color, String displayName)
{
{
return addEnum(EnumRarity.class, name, color, displayName);
return addEnum(EnumRarity.class, name, color, displayName);
}
}
private static void setup()
private static void setup()
{
{
if (isSetup)
if (isSetup)
{
{
return;
return;
}
}
try
try
{
{
Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory");
reflectionFactory = getReflectionFactory.invoke(null);
reflectionFactory = getReflectionFactory.invoke(null);
newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class);
newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class);
newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class);
newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class);
fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
isSetup = true;
isSetup = true;
}
}
/*
/*
* Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+
* Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+
* Also modified for use in decompiled code.
* Also modified for use in decompiled code.
* Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically
* Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically
*/
*/
private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception
private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception
{
{
Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
parameterTypes[0] = String.class;
parameterTypes[0] = String.class;
parameterTypes[1] = int.class;
parameterTypes[1] = int.class;
System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes));
return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes));
}
}
private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception
private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception
{
{
Object[] params = new Object[additionalValues.length + 2];
Object[] params = new Object[additionalValues.length + 2];
params[0] = value;
params[0] = value;
params[1] = ordinal;
params[1] = ordinal;
System.arraycopy(additionalValues, 0, params, 2, additionalValues.length);
System.arraycopy(additionalValues, 0, params, 2, additionalValues.length);
return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params}));
return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params}));
}
}
public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception
public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception
{
{
field.setAccessible(true);
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false);
fieldAccessorSet.invoke(fieldAccessor, target, value);
fieldAccessorSet.invoke(fieldAccessor, target, value);
}
}
private static void blankField(Class<?> enumClass, String fieldName) throws Exception
private static void blankField(Class<?> enumClass, String fieldName) throws Exception
{
{
for (Field field : Class.class.getDeclaredFields())
for (Field field : Class.class.getDeclaredFields())
{
{
if (field.getName().contains(fieldName))
if (field.getName().contains(fieldName))
{
{
field.setAccessible(true);
field.setAccessible(true);
setFailsafeFieldValue(field, enumClass, null);
setFailsafeFieldValue(field, enumClass, null);
break;
break;
}
}
}
}
}
}
private static void cleanEnumCache(Class<?> enumClass) throws Exception
private static void cleanEnumCache(Class<?> enumClass) throws Exception
{
{
blankField(enumClass, "enumConstantDirectory");
blankField(enumClass, "enumConstantDirectory");
blankField(enumClass, "enumConstants");
blankField(enumClass, "enumConstants");
}
}
private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues)
private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues)
{
{
setup();
setup();
return addEnum(commonTypes, enumType, enumName, paramValues);
return addEnum(commonTypes, enumType, enumName, paramValues);
}
}
protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues)
protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues)
{
{
for (Class<?>[] lookup : map)
for (Class<?>[] lookup : map)
{
{
if (lookup[0] == enumType)
if (lookup[0] == enumType)
{
{
Class<?>[] paramTypes = new Class<?>[lookup.length - 1];
Class<?>[] paramTypes = new Class<?>[lookup.length - 1];
if (paramTypes.length > 0)
if (paramTypes.length > 0)
{
{
System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length);
System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length);
}
}
return addEnum(enumType, enumName, paramTypes, paramValues);
return addEnum(enumType, enumName, paramTypes, paramValues);
}
}
}
}
return null;
return null;
}
}
//Tests an enum is compatible with these args, throws an error if not.
//Tests an enum is compatible with these args, throws an error if not.
public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes)
public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes)
{
{
addEnum(true, enumType, null, paramTypes, (Object[])null);
addEnum(true, enumType, null, paramTypes, (Object[])null);
}
}
public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues)
public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues)
{
{
return addEnum(false, enumType, enumName, paramTypes, paramValues);
return addEnum(false, enumType, enumName, paramTypes, paramValues);
}
}
@SuppressWarnings({ "unchecked", "serial" })
@SuppressWarnings({ "unchecked", "serial" })
private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues)
private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues)
{
{
if (!isSetup)
if (!isSetup)
{
{
setup();
setup();
}
}
Field valuesField = null;
Field valuesField = null;
Field[] fields = enumType.getDeclaredFields();
Field[] fields = enumType.getDeclaredFields();
for (Field field : fields)
for (Field field : fields)
{
{
String name = field.getName();
String name = field.getName();
if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards
if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards
{
{
valuesField = field;
valuesField = field;
break;
break;
}
}
}
}
int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/;
int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/;
if (valuesField == null)
if (valuesField == null)
{
{
String valueType = String.format("[L%s;", enumType.getName().replace('.', '/'));
String valueType = String.format("[L%s;", enumType.getName().replace('.', '/'));
for (Field field : fields)
for (Field field : fields)
{
{
if ((field.getModifiers() & flags) == flags &&
if ((field.getModifiers() & flags) == flags &&
field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't..
field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't..
{
{
valuesField = field;
valuesField = field;
break;
break;
}
}
}
}
}
}
if (valuesField == null)
if (valuesField == null)
{
{
final List<String> lines = Lists.newArrayList();
final List<String> lines = Lists.newArrayList();
lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName()));
lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName()));
lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF));
lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF));
lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')));
lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0')));
lines.add( "Fields:");
lines.add( "Fields:");
for (Field field : fields)
for (Field field : fields)
{
{
String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0');
String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0');
lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName()));
lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName()));
}
}
for (String line : lines)
for (String line : lines)
FMLLog.severe(line);
FMLLog.severe(line);
if (test)
if (test)
{
{
throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName())
throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName())
{
{
@Override
@Override
protected void printStackTrace(WrappedPrintStream stream)
protected void printStackTrace(WrappedPrintStream stream)
{
{
for (String line : lines)
for (String line : lines)
stream.println(line);
stream.println(line);
}
}
};
};
}
}
return null;
return null;
}
}
if (test)
if (test)
{
{
Object ctr = null;
Object ctr = null;
Exception ex = null;
Exception ex = null;
try
try
{
{
ctr = getConstructorAccessor(enumType, paramTypes);
ctr = getConstructorAccessor(enumType, paramTypes);
}
}
catch (Exception e)
catch (Exception e)
{
{
ex = e;
ex = e;
}
}
if (ctr == null || ex != null)
if (ctr == null || ex != null)
{
{
throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex)
throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex)
{
{
private String toString(Class<?>[] cls)
private String toString(Class<?>[] cls)
{
{
StringBuilder b = new StringBuilder();
StringBuilder b = new StringBuilder();
for (int x = 0; x < cls.length; x++)
for (int x = 0; x < cls.length; x++)
{
{
b.append(cls[x].getName());
b.append(cls[x].getName());
if (x != cls.length - 1)
if (x != cls.length - 1)
b.append(", ");
b.append(", ");
}
}
return b.toString();
return b.toString();
}
}
@Override
@Override
protected void printStackTrace(WrappedPrintStream stream)
protected void printStackTrace(WrappedPrintStream stream)
{
{
stream.println("Target Arguments:");
stream.println("Target Arguments:");
stream.println(" java.lang.String, int, " + toString(paramTypes));
stream.println(" java.lang.String, int, " + toString(paramTypes));
stream.println("Found Constructors:");
stream.println("Found Constructors:");
for (Constructor<?> ctr : enumType.getDeclaredConstructors())
for (Constructor<?> ctr : enumType.getDeclaredConstructors())
{
{
stream.println(" " + toString(ctr.getParameterTypes()));
stream.println(" " + toString(ctr.getParameterTypes()));
}
}
}
}
};
};
}
}
return null;
return null;
}
}
valuesField.setAccessible(true);
valuesField.setAccessible(true);
try
try
{
{
T[] previousValues = (T[])valuesField.get(enumType);
T[] previousValues = (T[])valuesField.get(enumType);
List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues);
T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues);
values.add(newValue);
values.add(newValue);
setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));
setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));
cleanEnumCache(enumType);
cleanEnumCache(enumType);
return newValue;
return newValue;
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
throw new RuntimeException(e.getMessage(), e);
}
}
}
}
static
static
{
{
if (!isSetup)
if (!isSetup)
{
{
setup();
setup();
}
}
}
}
}
}
已保存差异
原始文本
打开文件
/* * Minecraft Forge * Copyright (c) 2016. * * This library 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 version 2.1 * of the License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.minecraftforge.common.util; import java.lang.reflect.*; import java.util.*; import com.google.common.collect.Lists; import net.minecraftforge.fml.common.EnhancedRuntimeException; import net.minecraftforge.fml.common.FMLLog; import net.minecraft.block.BlockPressurePlate.Sensitivity; import net.minecraft.block.material.Material; import net.minecraft.enchantment.EnumEnchantmentType; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.item.EntityPainting.EnumArt; import net.minecraft.entity.player.EntityPlayer.SleepResult; import net.minecraft.item.EnumAction; import net.minecraft.item.EnumRarity; import net.minecraft.item.Item.ToolMaterial; import net.minecraft.item.ItemArmor.ArmorMaterial; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door; import net.minecraftforge.classloading.FMLForgePlugin; public class EnumHelper { private static Object reflectionFactory = null; private static Method newConstructorAccessor = null; private static Method newInstance = null; private static Method newFieldAccessor = null; private static Method fieldAccessorSet = null; private static boolean isSetup = false; //Some enums are decompiled with extra arguments, so lets check for that private static Class<?>[][] commonTypes = { {EnumAction.class}, {ArmorMaterial.class, String.class, int.class, int[].class, int.class, SoundEvent.class, float.class}, {EnumArt.class, String.class, int.class, int.class, int.class, int.class}, {EnumCreatureAttribute.class}, {EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class}, {Door.class}, {EnumEnchantmentType.class}, {Sensitivity.class}, {RayTraceResult.Type.class}, {EnumSkyBlock.class, int.class}, {SleepResult.class}, {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, {EnumRarity.class, TextFormatting.class, String.class} }; public static EnumAction addAction(String name) { return addEnum(EnumAction.class, name); } public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability, SoundEvent soundOnEquip, float toughness) { return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability, soundOnEquip, toughness); } public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY) { return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY); } public static EnumCreatureAttribute addCreatureAttribute(String name) { return addEnum(EnumCreatureAttribute.class, name); } public static EnumCreatureType addCreatureType(String name, Class<?> typeClass, int maxNumber, Material material, boolean peaceful, boolean animal) { return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal); } public static Door addDoor(String name) { return addEnum(Door.class, name); } public static EnumEnchantmentType addEnchantmentType(String name) { return addEnum(EnumEnchantmentType.class, name); } public static Sensitivity addSensitivity(String name) { return addEnum(Sensitivity.class, name); } public static RayTraceResult.Type addMovingObjectType(String name) { return addEnum(RayTraceResult.Type.class, name); } public static EnumSkyBlock addSkyBlock(String name, int lightValue) { return addEnum(EnumSkyBlock.class, name, lightValue); } public static SleepResult addStatus(String name) { return addEnum(SleepResult.class, name); } public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability) { return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability); } public static EnumRarity addRarity(String name, TextFormatting color, String displayName) { return addEnum(EnumRarity.class, name, color, displayName); } private static void setup() { if (isSetup) { return; } try { Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); reflectionFactory = getReflectionFactory.invoke(null); newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class); newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class); newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); } catch (Exception e) { e.printStackTrace(); } isSetup = true; } /* * Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+ * Also modified for use in decompiled code. * Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically */ private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception { Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2]; parameterTypes[0] = String.class; parameterTypes[1] = int.class; System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length); return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes)); } private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception { Object[] params = new Object[additionalValues.length + 2]; params[0] = value; params[1] = ordinal; System.arraycopy(additionalValues, 0, params, 2, additionalValues.length); return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params})); } public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); fieldAccessorSet.invoke(fieldAccessor, target, value); } private static void blankField(Class<?> enumClass, String fieldName) throws Exception { for (Field field : Class.class.getDeclaredFields()) { if (field.getName().contains(fieldName)) { field.setAccessible(true); setFailsafeFieldValue(field, enumClass, null); break; } } } private static void cleanEnumCache(Class<?> enumClass) throws Exception { blankField(enumClass, "enumConstantDirectory"); blankField(enumClass, "enumConstants"); } private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues) { setup(); return addEnum(commonTypes, enumType, enumName, paramValues); } protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues) { for (Class<?>[] lookup : map) { if (lookup[0] == enumType) { Class<?>[] paramTypes = new Class<?>[lookup.length - 1]; if (paramTypes.length > 0) { System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length); } return addEnum(enumType, enumName, paramTypes, paramValues); } } return null; } //Tests an enum is compatible with these args, throws an error if not. public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes) { addEnum(true, enumType, null, paramTypes, (Object[])null); } public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues) { return addEnum(false, enumType, enumName, paramTypes, paramValues); } @SuppressWarnings({ "unchecked", "serial" }) private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues) { if (!isSetup) { setup(); } Field valuesField = null; Field[] fields = enumType.getDeclaredFields(); for (Field field : fields) { String name = field.getName(); if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards { valuesField = field; break; } } int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; if (valuesField == null) { String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); for (Field field : fields) { if ((field.getModifiers() & flags) == flags && field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. { valuesField = field; break; } } } if (valuesField == null) { final List<String> lines = Lists.newArrayList(); lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName())); lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF)); lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0'))); lines.add( "Fields:"); for (Field field : fields) { String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName())); } for (String line : lines) FMLLog.severe(line); if (test) { throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName()) { @Override protected void printStackTrace(WrappedPrintStream stream) { for (String line : lines) stream.println(line); } }; } return null; } if (test) { Object ctr = null; Exception ex = null; try { ctr = getConstructorAccessor(enumType, paramTypes); } catch (Exception e) { ex = e; } if (ctr == null || ex != null) { throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex) { private String toString(Class<?>[] cls) { StringBuilder b = new StringBuilder(); for (int x = 0; x < cls.length; x++) { b.append(cls[x].getName()); if (x != cls.length - 1) b.append(", "); } return b.toString(); } @Override protected void printStackTrace(WrappedPrintStream stream) { stream.println("Target Arguments:"); stream.println(" java.lang.String, int, " + toString(paramTypes)); stream.println("Found Constructors:"); for (Constructor<?> ctr : enumType.getDeclaredConstructors()) { stream.println(" " + toString(ctr.getParameterTypes())); } } }; } return null; } valuesField.setAccessible(true); try { T[] previousValues = (T[])valuesField.get(enumType); List<T> values = new ArrayList<T>(Arrays.asList(previousValues)); T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues); values.add(newValue); setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0))); cleanEnumCache(enumType); return newValue; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage(), e); } } static { if (!isSetup) { setup(); } } }
更改后文本
打开文件
/* * Minecraft Forge * Copyright (c) 2016. * * This library 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 version 2.1 * of the License. * * This library 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ package net.minecraftforge.common.util; import java.lang.reflect.*; import java.util.*; import com.google.common.base.Predicate; import com.google.common.collect.Lists; import net.minecraftforge.fml.common.EnhancedRuntimeException; import net.minecraftforge.fml.common.FMLLog; import net.minecraft.block.BlockPressurePlate.Sensitivity; import net.minecraft.block.material.Material; import net.minecraft.enchantment.EnumEnchantmentType; import net.minecraft.entity.EnumCreatureAttribute; import net.minecraft.entity.EnumCreatureType; import net.minecraft.entity.item.EntityPainting.EnumArt; import net.minecraft.entity.player.EntityPlayer.SleepResult; import net.minecraft.item.EnumAction; import net.minecraft.item.EnumRarity; import net.minecraft.item.Item; import net.minecraft.item.Item.ToolMaterial; import net.minecraft.item.ItemArmor.ArmorMaterial; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.EnumSkyBlock; import net.minecraft.world.gen.structure.StructureStrongholdPieces.Stronghold.Door; import net.minecraftforge.classloading.FMLForgePlugin; public class EnumHelper { private static Object reflectionFactory = null; private static Method newConstructorAccessor = null; private static Method newInstance = null; private static Method newFieldAccessor = null; private static Method fieldAccessorSet = null; private static boolean isSetup = false; //Some enums are decompiled with extra arguments, so lets check for that private static Class<?>[][] commonTypes = { {EnumAction.class}, {ArmorMaterial.class, String.class, int.class, int[].class, int.class, SoundEvent.class, float.class}, {EnumArt.class, String.class, int.class, int.class, int.class, int.class}, {EnumCreatureAttribute.class}, {EnumCreatureType.class, Class.class, int.class, Material.class, boolean.class, boolean.class}, {Door.class}, {EnumEnchantmentType.class, Predicate.class}, {Sensitivity.class}, {RayTraceResult.Type.class}, {EnumSkyBlock.class, int.class}, {SleepResult.class}, {ToolMaterial.class, int.class, int.class, float.class, float.class, int.class}, {EnumRarity.class, TextFormatting.class, String.class} }; public static EnumAction addAction(String name) { return addEnum(EnumAction.class, name); } public static ArmorMaterial addArmorMaterial(String name, String textureName, int durability, int[] reductionAmounts, int enchantability, SoundEvent soundOnEquip, float toughness) { return addEnum(ArmorMaterial.class, name, textureName, durability, reductionAmounts, enchantability, soundOnEquip, toughness); } public static EnumArt addArt(String name, String tile, int sizeX, int sizeY, int offsetX, int offsetY) { return addEnum(EnumArt.class, name, tile, sizeX, sizeY, offsetX, offsetY); } public static EnumCreatureAttribute addCreatureAttribute(String name) { return addEnum(EnumCreatureAttribute.class, name); } public static EnumCreatureType addCreatureType(String name, Class<?> typeClass, int maxNumber, Material material, boolean peaceful, boolean animal) { return addEnum(EnumCreatureType.class, name, typeClass, maxNumber, material, peaceful, animal); } public static Door addDoor(String name) { return addEnum(Door.class, name); } public static EnumEnchantmentType addEnchantmentType(String name, Predicate<Item> delegate) { return addEnum(EnumEnchantmentType.class, name, delegate); } public static Sensitivity addSensitivity(String name) { return addEnum(Sensitivity.class, name); } public static RayTraceResult.Type addMovingObjectType(String name) { return addEnum(RayTraceResult.Type.class, name); } public static EnumSkyBlock addSkyBlock(String name, int lightValue) { return addEnum(EnumSkyBlock.class, name, lightValue); } public static SleepResult addStatus(String name) { return addEnum(SleepResult.class, name); } public static ToolMaterial addToolMaterial(String name, int harvestLevel, int maxUses, float efficiency, float damage, int enchantability) { return addEnum(ToolMaterial.class, name, harvestLevel, maxUses, efficiency, damage, enchantability); } public static EnumRarity addRarity(String name, TextFormatting color, String displayName) { return addEnum(EnumRarity.class, name, color, displayName); } private static void setup() { if (isSetup) { return; } try { Method getReflectionFactory = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("getReflectionFactory"); reflectionFactory = getReflectionFactory.invoke(null); newConstructorAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newConstructorAccessor", Constructor.class); newInstance = Class.forName("sun.reflect.ConstructorAccessor").getDeclaredMethod("newInstance", Object[].class); newFieldAccessor = Class.forName("sun.reflect.ReflectionFactory").getDeclaredMethod("newFieldAccessor", Field.class, boolean.class); fieldAccessorSet = Class.forName("sun.reflect.FieldAccessor").getDeclaredMethod("set", Object.class, Object.class); } catch (Exception e) { e.printStackTrace(); } isSetup = true; } /* * Everything below this is found at the site below, and updated to be able to compile in Eclipse/Java 1.6+ * Also modified for use in decompiled code. * Found at: http://niceideas.ch/roller2/badtrash/entry/java_create_enum_instances_dynamically */ private static Object getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes) throws Exception { Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2]; parameterTypes[0] = String.class; parameterTypes[1] = int.class; System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length); return newConstructorAccessor.invoke(reflectionFactory, enumClass.getDeclaredConstructor(parameterTypes)); } private static < T extends Enum<? >> T makeEnum(Class<T> enumClass, String value, int ordinal, Class<?>[] additionalTypes, Object[] additionalValues) throws Exception { Object[] params = new Object[additionalValues.length + 2]; params[0] = value; params[1] = ordinal; System.arraycopy(additionalValues, 0, params, 2, additionalValues.length); return enumClass.cast(newInstance.invoke(getConstructorAccessor(enumClass, additionalTypes), new Object[] {params})); } public static void setFailsafeFieldValue(Field field, Object target, Object value) throws Exception { field.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); Object fieldAccessor = newFieldAccessor.invoke(reflectionFactory, field, false); fieldAccessorSet.invoke(fieldAccessor, target, value); } private static void blankField(Class<?> enumClass, String fieldName) throws Exception { for (Field field : Class.class.getDeclaredFields()) { if (field.getName().contains(fieldName)) { field.setAccessible(true); setFailsafeFieldValue(field, enumClass, null); break; } } } private static void cleanEnumCache(Class<?> enumClass) throws Exception { blankField(enumClass, "enumConstantDirectory"); blankField(enumClass, "enumConstants"); } private static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Object... paramValues) { setup(); return addEnum(commonTypes, enumType, enumName, paramValues); } protected static <T extends Enum<? >> T addEnum(Class<?>[][] map, Class<T> enumType, String enumName, Object... paramValues) { for (Class<?>[] lookup : map) { if (lookup[0] == enumType) { Class<?>[] paramTypes = new Class<?>[lookup.length - 1]; if (paramTypes.length > 0) { System.arraycopy(lookup, 1, paramTypes, 0, paramTypes.length); } return addEnum(enumType, enumName, paramTypes, paramValues); } } return null; } //Tests an enum is compatible with these args, throws an error if not. public static void testEnum(Class<? extends Enum<?>> enumType, Class<?>[] paramTypes) { addEnum(true, enumType, null, paramTypes, (Object[])null); } public static <T extends Enum<? >> T addEnum(Class<T> enumType, String enumName, Class<?>[] paramTypes, Object... paramValues) { return addEnum(false, enumType, enumName, paramTypes, paramValues); } @SuppressWarnings({ "unchecked", "serial" }) private static <T extends Enum<? >> T addEnum(boolean test, final Class<T> enumType, String enumName, final Class<?>[] paramTypes, Object[] paramValues) { if (!isSetup) { setup(); } Field valuesField = null; Field[] fields = enumType.getDeclaredFields(); for (Field field : fields) { String name = field.getName(); if (name.equals("$VALUES") || name.equals("ENUM$VALUES")) //Added 'ENUM$VALUES' because Eclipse's internal compiler doesn't follow standards { valuesField = field; break; } } int flags = (FMLForgePlugin.RUNTIME_DEOBF ? Modifier.PUBLIC : Modifier.PRIVATE) | Modifier.STATIC | Modifier.FINAL | 0x1000 /*SYNTHETIC*/; if (valuesField == null) { String valueType = String.format("[L%s;", enumType.getName().replace('.', '/')); for (Field field : fields) { if ((field.getModifiers() & flags) == flags && field.getType().getName().replace('.', '/').equals(valueType)) //Apparently some JVMs return .'s and some don't.. { valuesField = field; break; } } } if (valuesField == null) { final List<String> lines = Lists.newArrayList(); lines.add(String.format("Could not find $VALUES field for enum: %s", enumType.getName())); lines.add(String.format("Runtime Deobf: %s", FMLForgePlugin.RUNTIME_DEOBF)); lines.add(String.format("Flags: %s", String.format("%16s", Integer.toBinaryString(flags)).replace(' ', '0'))); lines.add( "Fields:"); for (Field field : fields) { String mods = String.format("%16s", Integer.toBinaryString(field.getModifiers())).replace(' ', '0'); lines.add(String.format(" %s %s: %s", mods, field.getName(), field.getType().getName())); } for (String line : lines) FMLLog.severe(line); if (test) { throw new EnhancedRuntimeException("Could not find $VALUES field for enum: " + enumType.getName()) { @Override protected void printStackTrace(WrappedPrintStream stream) { for (String line : lines) stream.println(line); } }; } return null; } if (test) { Object ctr = null; Exception ex = null; try { ctr = getConstructorAccessor(enumType, paramTypes); } catch (Exception e) { ex = e; } if (ctr == null || ex != null) { throw new EnhancedRuntimeException(String.format("Could not find constructor for Enum %s", enumType.getName()), ex) { private String toString(Class<?>[] cls) { StringBuilder b = new StringBuilder(); for (int x = 0; x < cls.length; x++) { b.append(cls[x].getName()); if (x != cls.length - 1) b.append(", "); } return b.toString(); } @Override protected void printStackTrace(WrappedPrintStream stream) { stream.println("Target Arguments:"); stream.println(" java.lang.String, int, " + toString(paramTypes)); stream.println("Found Constructors:"); for (Constructor<?> ctr : enumType.getDeclaredConstructors()) { stream.println(" " + toString(ctr.getParameterTypes())); } } }; } return null; } valuesField.setAccessible(true); try { T[] previousValues = (T[])valuesField.get(enumType); List<T> values = new ArrayList<T>(Arrays.asList(previousValues)); T newValue = makeEnum(enumType, enumName, values.size(), paramTypes, paramValues); values.add(newValue); setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0))); cleanEnumCache(enumType); return newValue; } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e.getMessage(), e); } } static { if (!isSetup) { setup(); } } }
查找差异