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 e00e1160e..7b6543266 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 @@ -3816,20 +3816,25 @@ public class ScriptDocument { } if (typeName != null && !typeName.contains(".")) { + TypeStringNormalizer.ArraySplit arraySplit = TypeStringNormalizer.splitArraySuffixes(typeName); + String baseTypeName = arraySplit.base; + int arrayDims = arraySplit.dimensions; + ScriptTypeInfo enclosing = findEnclosingScriptType(position); while (enclosing != null) { // Check if the name is a declared type parameter on this class (e.g., E in class Box) - TypeParamInfo typeParam = enclosing.getDeclaredTypeParam(typeName); + TypeParamInfo typeParam = enclosing.getDeclaredTypeParam(baseTypeName); if (typeParam != null) { TypeInfo boundType = typeParam.getBoundTypeInfo(); if (boundType == null) { typeParam.resolveBoundType(); boundType = typeParam.getBoundTypeInfo(); } - if (boundType != null && boundType.isResolved()) { - return TypeInfo.typeParameter(typeName, boundType); - } - return TypeInfo.typeParameter(typeName); + TypeInfo result = (boundType != null && boundType.isResolved()) + ? TypeInfo.typeParameter(baseTypeName, boundType) + : TypeInfo.typeParameter(baseTypeName); + for (int i = 0; i < arrayDims; i++) result = TypeInfo.arrayOf(result); + return result; } // Check inner classes diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/AssignmentInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/AssignmentInfo.java index 565dd9717..8089ebe27 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/AssignmentInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/AssignmentInfo.java @@ -1,6 +1,7 @@ package noppes.npcs.client.gui.util.script.interpreter.field; import noppes.npcs.client.gui.util.script.ScopeInfo; +import noppes.npcs.client.gui.util.script.interpreter.method.MethodCallInfo; import noppes.npcs.client.gui.util.script.interpreter.type.TypeChecker; import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo; @@ -139,8 +140,8 @@ public class AssignmentInfo { // Check type compatibility if (targetType != null && sourceType != null) { if (!TypeChecker.isTypeCompatible(targetType, sourceType)) { - this.requiredType = targetType.getSimpleName(); - this.providedType = sourceType.getSimpleName(); + this.requiredType = MethodCallInfo.getTypeDisplayName(targetType); + this.providedType = MethodCallInfo.getTypeDisplayName(sourceType); setError(ErrorType.TYPE_MISMATCH, buildTypeMismatchMessage()); } } diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodCallInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodCallInfo.java index 4654b8f8b..1a744d215 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodCallInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodCallInfo.java @@ -443,7 +443,7 @@ public class MethodCallInfo { * in error "Expect T but got String", if T has a resolved bound aka "int" show it instead of T to avoid confusion. * So the error would be "Expect int but got String" */ - private String getTypeDisplayName(TypeInfo type) { + public static String getTypeDisplayName(TypeInfo type) { if(type.isTypeParameter()) { TypeInfo bound = type.getBoundType(); if (bound != null) diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ScriptTypeInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ScriptTypeInfo.java index bf9dd7590..c4b8ff7f1 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ScriptTypeInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/ScriptTypeInfo.java @@ -178,12 +178,15 @@ public class ScriptTypeInfo extends TypeInfo { result.outerClass = this.outerClass; GenericContext ctx = GenericContext.forReceiver(result); - // Parameterize methods and fields with the generic context of this type. + // Parameterize methods, constructors, and fields with the generic context of this type. for (Map.Entry> entry : this.methods.entrySet()) { List substituted = new ArrayList<>(); for (MethodInfo m : entry.getValue()) substituted.add(substituteMethod(m, ctx)); result.methods.put(entry.getKey(), substituted); } + for (MethodInfo ctor : this.constructors) { + result.constructors.add(substituteMethod(ctor, ctx)); + } for (Map.Entry entry : this.fields.entrySet()) { FieldInfo f = entry.getValue(); TypeInfo subType = ctx.substitute(f.getTypeInfo()); diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java index ca5d18fbd..8f310eb12 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/type/TypeInfo.java @@ -490,14 +490,18 @@ public class TypeInfo { // Fallback to Object array if we can't create the specific array type } } - - TypeInfo arr = new TypeInfo(simpleName, fullName, pkg, elementType.kind, arrayClass, true, null, null, null, null, elementType); + TypeInfo arr = new TypeInfo(simpleName, fullName, pkg, elementType.kind, arrayClass, elementType.isResolved(), + null, null, null, null, elementType); arr.setPrimitive(elementType.isPrimitive()); arr.syntheticFields.add(FieldInfo.external("length", TypeInfo.fromPrimitive("int"), null, Modifier.PUBLIC | Modifier.FINAL)); arr.syntheticMethods.add(MethodInfo.external("clone", arr, null, Collections.emptyList(), Modifier.PUBLIC, null)); - return arr; + + arr.typeParameterName = elementType.typeParameterName; + if (elementType.boundType != null) + arr.boundType = arrayOf(elementType.boundType); + return arr; } /**