mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 20:44:08 +00:00
ScriptTypeInfo is now properly compared to TypeInfo parents + removed parent constructor mismatch errors from interfaces
This commit is contained in:
1 parent
1289778874
commit
c88bd50be9
2 files changed
+54
-9
No files matched your search
+4
-9
@@ -979,20 +979,18 @@ public class ScriptTypeInfo extends TypeInfo {
|
||||
// If no constructors defined in script type, it has an implicit default constructor
|
||||
// Check if parent has a no-arg constructor
|
||||
if (!hasConstructors()) {
|
||||
boolean parentHasNoArg = false;
|
||||
|
||||
if (superClass instanceof ScriptTypeInfo) {
|
||||
ScriptTypeInfo parentScript = (ScriptTypeInfo) superClass;
|
||||
if (!parentScript.hasConstructors() || parentScript.findConstructor(0) != null) {
|
||||
parentHasNoArg = true;
|
||||
if (!parentScript.isInterface() && (!parentScript.hasConstructors() || parentScript.findConstructor(0) != null)) {
|
||||
addConstructorMismatchError(superClass, superClass.getSimpleName());
|
||||
}
|
||||
} else {
|
||||
Class<?> javaClass = superClass.getJavaClass();
|
||||
if (javaClass != null) {
|
||||
if (javaClass != null && !javaClass.isInterface()) {
|
||||
try {
|
||||
for (java.lang.reflect.Constructor<?> ctor : javaClass.getConstructors()) {
|
||||
if (ctor.getParameterCount() == 0) {
|
||||
parentHasNoArg = true;
|
||||
addConstructorMismatchError(superClass, superClass.getSimpleName());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1002,9 +1000,6 @@ public class ScriptTypeInfo extends TypeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
if (!parentHasNoArg) {
|
||||
addConstructorMismatchError(superClass, superClass.getSimpleName());
|
||||
}
|
||||
}
|
||||
// If script type has constructors, we'd need to check super() calls - that's more complex
|
||||
// For now, we just validate the implicit default constructor case
|
||||
|
||||
@@ -2,6 +2,8 @@ package noppes.npcs.client.gui.util.script.interpreter.type;
|
||||
|
||||
import noppes.npcs.client.gui.util.script.interpreter.js_parser.JSTypeInfo;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Deque;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -110,6 +112,14 @@ public final class TypeChecker {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ScriptTypeInfo inheritance: actual is a script-defined type that may extend/implement expected.
|
||||
// ScriptTypeInfo.getJavaClass() returns null, so the Java isAssignableFrom gate below won't fire.
|
||||
if (actual instanceof ScriptTypeInfo) {
|
||||
if (isScriptTypeAssignableTo((ScriptTypeInfo) actual, expected)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Object type compatibility (check inheritance)
|
||||
if (expected.getJavaClass() != null && actual.getJavaClass() != null) {
|
||||
Class<?> expectedClass = expected.getJavaClass();
|
||||
@@ -165,6 +175,46 @@ public final class TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check assignability for ScriptTypeInfo by iteratively walking the extends/implements chain.
|
||||
* Handles both direct and indirect inheritance (A extends B extends C implements D).
|
||||
*/
|
||||
private static boolean isScriptTypeAssignableTo(ScriptTypeInfo actual, TypeInfo expected) {
|
||||
String expectedFull = expected.getFullName();
|
||||
String expectedSimple = expected.getSimpleName();
|
||||
|
||||
Deque<TypeInfo> worklist = new ArrayDeque<>();
|
||||
worklist.add(actual);
|
||||
|
||||
while (!worklist.isEmpty()) {
|
||||
TypeInfo current = worklist.poll();
|
||||
if (current == null || !current.isResolved()) continue;
|
||||
|
||||
String currentFull = current.getFullName();
|
||||
if (currentFull != null) {
|
||||
if (expectedFull != null && expectedFull.equals(currentFull)) return true;
|
||||
if (expectedSimple != null && expectedSimple.equals(current.getSimpleName())) return true;
|
||||
}
|
||||
|
||||
if (current instanceof ScriptTypeInfo) {
|
||||
ScriptTypeInfo scriptCurrent = (ScriptTypeInfo) current;
|
||||
TypeInfo superClass = scriptCurrent.getSuperClass();
|
||||
if (superClass != null) {
|
||||
worklist.add(superClass);
|
||||
}
|
||||
for (TypeInfo iface : scriptCurrent.getImplementedInterfaces()) {
|
||||
worklist.add(iface);
|
||||
}
|
||||
} else if (current.getJavaClass() != null && expected.getJavaClass() != null) {
|
||||
if (expected.getJavaClass().isAssignableFrom(current.getJavaClass())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean areTypeArgumentsCompatible(TypeInfo expected, TypeInfo actual) {
|
||||
java.util.List<TypeInfo> expectedArgs = expected.getAppliedTypeArgs();
|
||||
java.util.List<TypeInfo> actualArgs = actual.getAppliedTypeArgs();
|
||||
|
||||
Reference in new issue
Block a user