Skip to content

Commit

Permalink
ReflectionParser changes
Browse files Browse the repository at this point in the history
* Added Object and CharSequence as predefined classes for ReflectionParser.
* ReflectionParser class declarations now support simple generics.
  • Loading branch information
CryptoMorin committed Jul 18, 2024
1 parent 5788570 commit ac44e5e
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 31 deletions.
3 changes: 2 additions & 1 deletion src/main/java/com/cryptomorin/xseries/XEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -404,7 +404,8 @@ private static void fourteen(Entity entity, ConfigurationSection config) {
if (config.isSet("is-patrol-leader")) raider.setCanJoinRaid(config.getBoolean("is-patrol-leader"));
} else if (entity instanceof Cat) {
Cat cat = (Cat) entity;
cat.setCatType(Enums.getIfPresent(Cat.Type.class, config.getString("variant")).or(Cat.Type.TABBY));
// They changed this to an interface...
// TODO cat.setCatType(Enums.getIfPresent(Cat.Type.class, config.getString("variant")).or(Cat.Type.TABBY));
cat.setCollarColor(Enums.getIfPresent(DyeColor.class, config.getString("color")).or(DyeColor.GREEN));
} else if (entity instanceof Fox) {
Fox fox = (Fox) entity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public FieldMemberHandle named(@Pattern(PackageHandle.JAVA_IDENTIFIER_PATTERN) S
protected <T extends AccessibleObject & Member> T handleAccessible(T field) throws ReflectiveOperationException {
field = super.handleAccessible(field);
if (field == null) return null;
if (isFinal && isStatic) {
if (!getter && isFinal && isStatic) {
try {
int unfinalModifiers = field.getModifiers() & ~Modifier.FINAL;
if (MODIFIERS_VAR_HANDLE != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,35 @@ private enum Flag {
}

@Language("RegExp")
private static final String JAVA_TYPE_REGEX = PackageHandle.JAVA_PACKAGE_PATTERN + "(?:<[.\\w<>\\[\\], ]+>)?((?:\\[])*)";
private static final String
GENERIC = "(?:\\s*<\\s*[.\\w<>\\[\\], ]+\\s*>)?",
ARRAY = "((?:\\[])*)",
PACKAGE_REGEX = "(?:package\\s+(?<package>" + PackageHandle.JAVA_PACKAGE_PATTERN + ")\\s*;\\s*)?",
CLASS_TYPES = "(?<classType>class|interface|enum)",
PARAMETERS = "\\s*\\(\\s*(?<parameters>[\\w$_,. ]+)?\\s*\\)",
END_DECL = "\\s*;?\\s*";

private static final Pattern
CLASS = Pattern.compile(PACKAGE_REGEX + Flag.FLAGS_REGEX + CLASS_TYPES + "\\s+" + type("className") +
"(?:\\s+extends\\s+" + id("superclasses") + ")?\\s+(implements\\s+" + id("interfaces") + ")?(?:\\s*\\{\\s*})?\\s*");
private static final Pattern METHOD = Pattern.compile(Flag.FLAGS_REGEX + type("methodReturnType") + "\\s+"
+ id("methodName") + PARAMETERS + END_DECL);
private static final Pattern CONSTRUCTOR = Pattern.compile(Flag.FLAGS_REGEX + "\\s+"
+ id("className") + PARAMETERS + END_DECL);
private static final Pattern FIELD = Pattern.compile(Flag.FLAGS_REGEX + type("fieldType") + "\\s+"
+ id("fieldName") + END_DECL);

@Language("RegExp")
private static String id(@Language("RegExp") String groupName) {
if (groupName == null) return PackageHandle.JAVA_IDENTIFIER_PATTERN;
return "(?<" + groupName + '>' + PackageHandle.JAVA_IDENTIFIER_PATTERN + ')';
}

@SuppressWarnings("LanguageMismatch")
@Language("RegExp")
private static String type(@Language("RegExp") String groupName) {
if (groupName == null) return JAVA_TYPE_REGEX;
return "(?<" + groupName + '>' + JAVA_TYPE_REGEX + ')';
String type = PackageHandle.JAVA_PACKAGE_PATTERN + GENERIC + ARRAY;
return "(?<" + groupName + '>' + type + ')';
}

private Class<?>[] parseTypes(String[] typeNames) {
Expand All @@ -84,7 +101,7 @@ private Class<?>[] parseTypes(String[] typeNames) {
Arrays.asList(
byte.class, short.class, int.class, long.class, float.class, double.class, boolean.class, char.class, void.class,
Byte.class, Short.class, Integer.class, Long.class, Float.class, Double.class, Boolean.class, Character.class, Void.class,
String.class, Optional.class, StringBuilder.class, StringBuffer.class, UUID.class,
Object.class, String.class, CharSequence.class, StringBuilder.class, StringBuffer.class, UUID.class, Optional.class,
Map.class, HashMap.class, ConcurrentHashMap.class, LinkedHashMap.class, WeakHashMap.class,
List.class, ArrayList.class, Set.class, HashSet.class, Deque.class, Queue.class, LinkedList.class,
Date.class, Calendar.class, Duration.class
Expand All @@ -97,14 +114,17 @@ private Class<?> parseType(String typeName) {
}

String firstTypeName = typeName;
typeName = typeName.replace(" ", "");
int arrayDimension = 0;
if (typeName.endsWith("[]")) { // Arrays
String replaced = typeName.replace("[]", "");
arrayDimension = (typeName.length() - replaced.length()) / 2;
typeName = replaced;
}
System.out.println(typeName + "| ends with it?");
if (typeName.endsWith(">")) { // Generic
typeName = typeName.substring(0, typeName.indexOf('<'));
System.out.println(typeName + " -> " + typeName);
}

Class<?> clazz = null;
Expand All @@ -127,28 +147,6 @@ private Class<?> parseType(String typeName) {
return clazz;
}

// TODO support generics. Using RegEx might be impossible because Java doesn't support (?R) recursion.
@Language("RegExp")
private static final String GENERIC = "(?:<" + id(null) + ">)*";

@Language("RegExp")
private static final String PACKAGE_REGEX = "(?:package\\s+(?<package>" + PackageHandle.JAVA_PACKAGE_PATTERN + ")\\s*;\\s*)?";
@Language("RegExp")
private static final String CLASS_TYPES = "(?<classType>class|interface|enum)";
@Language("RegExp")
private static final String PARAMETERS = "\\s*\\(\\s*(?<parameters>[\\w$_,. ]+)?\\s*\\)";
@Language("RegExp")
private static final String END_DECL = "\\s*;?\\s*";

private static final Pattern CLASS = Pattern.compile(PACKAGE_REGEX + Flag.FLAGS_REGEX + CLASS_TYPES + "\\s+" + id("className") +
"(?:\\s+extends\\s+" + id("superclasses") + ")?\\s+(implements\\s+" + id("interfaces") + ")?(?:\\s*\\{\\s*})?\\s*");
private static final Pattern METHOD = Pattern.compile(Flag.FLAGS_REGEX + type("methodReturnType") + "\\s+"
+ id("methodName") + PARAMETERS + END_DECL);
private static final Pattern CONSTRUCTOR = Pattern.compile(Flag.FLAGS_REGEX + "\\s+"
+ id("className") + PARAMETERS + END_DECL);
private static final Pattern FIELD = Pattern.compile(Flag.FLAGS_REGEX + type("fieldType") + "\\s+"
+ id("fieldName") + END_DECL);

public ReflectionParser imports(ReflectiveNamespace namespace) {
this.namespace = namespace;
return this;
Expand Down Expand Up @@ -178,7 +176,9 @@ public <T extends DynamicClassHandle> T parseClass(T classHandle) {
}

// String classGeneric = parser.group("generic");
classHandle.named(group("className").split("\\$"));
String className = group("className");
if (className.contains("<")) className = className.substring(0, className.indexOf('<'));
classHandle.named(className);

return classHandle;
}
Expand Down
4 changes: 2 additions & 2 deletions src/test/com/github/cryptomorin/test/ReflectionTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
public final class ReflectionTests {
private final String test = "A";

private static final class A {
private static final class A<T> {
private static final class B {
private static final class C {
public final AtomicInteger atomicField = new AtomicInteger();
Expand Down Expand Up @@ -84,7 +84,7 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwabl
// Inner class test
MethodHandle innerinnerinnerField = XReflection.namespaced().imports(AtomicInteger.class)
.of(ReflectionTests.class)
.inner("private static final class A {}")
.inner("private static final class A<T> {}")
.inner("private static final class B {}")
.inner("private static final class C {}")
.field("public final AtomicInteger atomicField;")
Expand Down

0 comments on commit ac44e5e

Please sign in to comment.