diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/MethodCallInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/MethodCallInfo.java index cae368d4d..12582cc63 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/MethodCallInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/MethodCallInfo.java @@ -99,6 +99,8 @@ public class MethodCallInfo { private String errorMessage; private int errorArgIndex = -1; // Index of the problematic argument (for WRONG_ARG_TYPE) private List argumentTypeErrors = new ArrayList<>(); + + private boolean isConstructor; public MethodCallInfo(String methodName, int methodNameStart, int methodNameEnd, int openParenOffset, int closeParenOffset, @@ -123,6 +125,27 @@ public class MethodCallInfo { this.isStaticAccess = isStaticAccess; } + /** + * Factory method to create a MethodCallInfo for a constructor call. + * Constructors are represented as method calls where the type itself is the receiver. + */ + public static MethodCallInfo constructor(TypeInfo typeInfo, MethodInfo constructor, + int typeNameStart, int typeNameEnd, + int openParenOffset, int closeParenOffset, + List arguments) { + return new MethodCallInfo( + typeInfo.getSimpleName(), // Constructor name is the type name + typeNameStart, + typeNameEnd, + openParenOffset, + closeParenOffset, + arguments, + typeInfo, // The type itself is the receiver + constructor, // The constructor MethodInfo + false // Constructors are not static access + ).setConstructor(true); + } + // Getters public String getMethodName() { return methodName; @@ -171,6 +194,15 @@ public class MethodCallInfo { public void setExpectedType(TypeInfo expectedType) { this.expectedType = expectedType; } + + public boolean isConstructor() { + return isConstructor; + } + + public MethodCallInfo setConstructor(boolean isConstructor) { + this.isConstructor = isConstructor; + return this; + } public ErrorType getErrorType() { return errorType; @@ -276,9 +308,9 @@ public class MethodCallInfo { setError(ErrorType.UNRESOLVED_METHOD, "Cannot resolve method '" + methodName + "'"); return; } - - // Check static/instance access - if (isStaticAccess && !resolvedMethod.isStatic()) { + + // Check static/instance access (skip for constructors) + if (!isConstructor && isStaticAccess && !resolvedMethod.isStatic()) { setError(ErrorType.STATIC_ACCESS_ERROR, "Cannot call instance method '" + methodName + "' on a class type"); return; diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java index 0ec1b8502..1ca326445 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java @@ -1572,18 +1572,7 @@ public class ScriptDocument { } } - /** - * Wrapper class to hold both TypeInfo and constructor MethodInfo for "new" expressions. - */ - static class NewExpressionInfo { - final TypeInfo typeInfo; - final MethodInfo constructor; - - NewExpressionInfo(TypeInfo typeInfo, MethodInfo constructor) { - this.typeInfo = typeInfo; - this.constructor = constructor; - } - } + /** * Recursively parse and mark generic type parameters. @@ -3392,9 +3381,12 @@ public class ScriptDocument { if (info.hasConstructors()) { MethodInfo constructor = info.findConstructor(argCount); if (constructor != null) { - // Attach both type info and constructor - NewExpressionInfo newExpr = new NewExpressionInfo(info, constructor); - marks.add(new ScriptLine.Mark(start, end, info.getTokenType(), newExpr)); + // Create MethodCallInfo for constructor + MethodCallInfo ctorCall = MethodCallInfo.constructor( + info, constructor, start, end, openParen, closeParen, arguments + ); + ctorCall.validate(); + marks.add(new ScriptLine.Mark(start, end, info.getTokenType(), ctorCall)); continue; } } diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java index 4fd6d5cdc..ae5f6d0ab 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptLine.java @@ -152,10 +152,13 @@ public class ScriptLine { if (mark.metadata != null) { if (mark.metadata instanceof TypeInfo) { token.setTypeInfo((TypeInfo) mark.metadata); - } else if (mark.metadata instanceof ScriptDocument.NewExpressionInfo) { - ScriptDocument.NewExpressionInfo newExpr = (ScriptDocument.NewExpressionInfo) mark.metadata; - token.setTypeInfo(newExpr.typeInfo); - token.setMethodInfo(newExpr.constructor); + } else if (mark.metadata instanceof MethodCallInfo) { + MethodCallInfo callInfo = (MethodCallInfo) mark.metadata; + if (callInfo.isConstructor()) { + token.setTypeInfo(callInfo.getReceiverType()); + token.setMethodInfo(callInfo.getResolvedMethod()); + } + token.setMethodCallInfo(callInfo); } else if (mark.metadata instanceof FieldInfo.ArgInfo) { FieldInfo.ArgInfo ctx = (FieldInfo.ArgInfo) mark.metadata; token.setFieldInfo(ctx.fieldInfo); @@ -164,8 +167,6 @@ public class ScriptLine { token.setFieldInfo((FieldInfo) mark.metadata); } else if (mark.metadata instanceof MethodInfo) { token.setMethodInfo((MethodInfo) mark.metadata); - } else if (mark.metadata instanceof MethodCallInfo) { - token.setMethodCallInfo((MethodCallInfo) mark.metadata); } else if (mark.metadata instanceof ImportData) { token.setImportData((ImportData) mark.metadata); } else if (mark.metadata instanceof FieldAccessInfo) {