From 458162901e7aaef7a6da7e6fedd5dcdd6a663ea5 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 7 Mar 2026 05:03:12 +0200 Subject: [PATCH] Added 'constructor()' method and 'class' field to Java.type() --- .../interpreter/type/ClassTypeInfo.java | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ClassTypeInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ClassTypeInfo.java index c19faeb2c..ab0888d5d 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ClassTypeInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ClassTypeInfo.java @@ -1,5 +1,13 @@ package noppes.npcs.client.gui.util.script.interpreter.type; +import noppes.npcs.client.gui.util.script.interpreter.field.FieldInfo; +import noppes.npcs.client.gui.util.script.interpreter.method.MethodInfo; + +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + /** * Represents a reference to a Java Class itself (not an instance). * Used for patterns like: var File = Java.type("java.io.File"); @@ -7,12 +15,15 @@ package noppes.npcs.client.gui.util.script.interpreter.type; * When you have a ClassTypeInfo: * - Accessing members should show ONLY static members (File.listRoots()) * - Using 'new' should return an instance of the wrapped class (new File("path")) + * - Calling .constructor(...) should return an instance of the wrapped class * * This is distinct from a regular TypeInfo which represents an instance of that type. */ public class ClassTypeInfo extends TypeInfo { private final TypeInfo instanceType; // The type you get when you do 'new' on this class + private List constructorMethod; + private List classField; /** * Create a ClassTypeInfo wrapping a Java class. @@ -66,6 +77,80 @@ public class ClassTypeInfo extends TypeInfo { return instanceType; } + @Override + public List getSyntheticMethods() { + List base = super.getSyntheticMethods(); + + // if (constructorMethod == null) { + constructorMethod = buildConstructorMethod(); + //} + + if (constructorMethod.isEmpty()) { + return base; + } + + List merged = new ArrayList<>(base.size() + constructorMethod.size()); + merged.addAll(base); + merged.addAll(constructorMethod); + return merged; + } + + @Override + public List getSyntheticFields() { + List base = super.getSyntheticFields(); + + if (classField == null) { + classField = buildClassField(); + } + + if (classField.isEmpty()) { + return base; + } + + List merged = new ArrayList<>(base.size() + classField.size()); + merged.addAll(base); + merged.addAll(classField); + return merged; + } + + private List buildConstructorMethod() { + if (instanceType == null) { + return Collections.emptyList(); + } + + FieldInfo argsParam = FieldInfo.parameter("args", TypeInfo.OBJECT, -1, null); + argsParam.setVarArg(true); + + List params = new ArrayList<>(); + params.add(argsParam); + + MethodInfo ctor = MethodInfo.external( + "constructor", + instanceType, + this, + params, + Modifier.PUBLIC | Modifier.STATIC, + "Creates a new instance of " + instanceType.getSimpleName() + ".\n\n" + + "Equivalent to using the 'new' operator on this class reference." + ); + + return Collections.singletonList(ctor); + } + + private List buildClassField() { + if (getJavaClass() == null) { + return Collections.emptyList(); + } + try { + TypeInfo classType = TypeInfo.fromClass(Class.class).parameterize(instanceType); + FieldInfo classField = FieldInfo.external("class", classType, + "The Class object for " + getSimpleName(), Modifier.PUBLIC | Modifier.STATIC); + return Collections.singletonList(classField); + } catch (Exception e) { + return Collections.emptyList(); + } + } + @Override public String toString() { return "Class<" + getSimpleName() + ">";