From b84ada3a30f218a407818d2c3600463119ffba04 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Tue, 30 Dec 2025 19:08:30 +0200 Subject: [PATCH] Fixed class type detection using Character.isUpperCase in most contexts instead of more robust resolution --- .../gui/util/script/ClassPathFinder.java | 13 +++-- .../client/gui/util/script/FormatHelper.java | 11 ++-- .../script/interpreter/ScriptDocument.java | 50 +++++++++++++------ 3 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/util/script/ClassPathFinder.java b/src/main/java/noppes/npcs/client/gui/util/script/ClassPathFinder.java index e54f5d878..04f765cf5 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/ClassPathFinder.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/ClassPathFinder.java @@ -368,7 +368,8 @@ public class ClassPathFinder { if (p == null || p.isEmpty()) continue; String[] segs = p.split("\\."); String last = segs[segs.length - 1]; - boolean lastIsClass = last.length() > 0 && Character.isUpperCase(last.charAt(0)); + // Check if last segment is actually a class (try to resolve it) + boolean lastIsClass = last.length() > 0 && tryResolveClass(p) != null; // Try package wildcard: pkg.SimpleName if (!lastIsClass) { @@ -532,6 +533,8 @@ public class ClassPathFinder { private int findFirstUppercaseSegment(String[] segments) { for (int i = 0; i < segments.length; i++) { if (segments[i].length() > 0 && Character.isUpperCase(segments[i].charAt(0))) { + // Keep uppercase check here as it's a heuristic for package splitting + // This is about Java naming conventions, not actual type resolution return i; } } @@ -646,10 +649,10 @@ public class ClassPathFinder { } String typeName = content.substring(start, i); - // Only process if it looks like a type name (starts with uppercase) - if (Character.isUpperCase(typeName.charAt(0))) { - // Resolve the type - ClassInfo info = resolveSimpleName(typeName, importedClasses, importedPackages); + // Try to resolve as an actual type + ClassInfo info = resolveSimpleName(typeName, importedClasses, importedPackages); + if (info != null) { + // Only process if it actually resolves to a type ClassType classType = (info != null) ? info.type : ClassType.CLASS; results.add(new TypeOccurrence(baseOffset + start, baseOffset + i, typeName, classType)); diff --git a/src/main/java/noppes/npcs/client/gui/util/script/FormatHelper.java b/src/main/java/noppes/npcs/client/gui/util/script/FormatHelper.java index 5c534cc94..31a1dae9c 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/FormatHelper.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/FormatHelper.java @@ -625,9 +625,14 @@ public class FormatHelper { start--; } String before = code.substring(start, pos); - // Common generic types or capital letter start (type name) - if (!before.isEmpty() && Character.isUpperCase(before.charAt(0))) { - return true; + // Check if it's actually a type name (more robust than just checking uppercase) + if (!before.isEmpty()) { + // For FormatHelper, we don't have access to ScriptDocument's resolveType, + // so we check common patterns: uppercase start or known generic types + if (Character.isUpperCase(before.charAt(0)) || + before.equals("var") || before.equals("let") || before.equals("const")) { + return true; + } } } // Check if there's a matching > 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 5e676f0ca..7443cc308 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 @@ -999,9 +999,10 @@ public class ScriptDocument { TypeInfo currentType = null; // Resolve the first segment - if (Character.isUpperCase(firstIdent.charAt(0))) { - // Static access like Event.player - currentType = resolveType(firstIdent); + TypeInfo typeCheck = resolveType(firstIdent); + if (typeCheck != null && typeCheck.isResolved()) { + // Static access like Event.player or scriptType.field + currentType = typeCheck; } else { // Variable access FieldInfo varInfo = resolveVariable(firstIdent, identStart); @@ -1804,8 +1805,9 @@ public class ScriptDocument { } String typeName = content.substring(start, i); - // Only process if it looks like a type name (starts with uppercase) - if (Character.isUpperCase(typeName.charAt(0))) { + // Only process if it's an actual type (check via resolveType) + TypeInfo typeCheck = resolveType(typeName); + if (typeCheck != null && typeCheck.isResolved()) { int absStart = baseOffset + start; int absEnd = baseOffset + i; @@ -2044,8 +2046,10 @@ public class ScriptDocument { return false; } - // It's static access if the identifier starts with uppercase - return !ident.isEmpty() && Character.isUpperCase(ident.charAt(0)); + // It's static access if the identifier resolves to a type + if (ident.isEmpty()) return false; + TypeInfo typeCheck = resolveType(ident); + return typeCheck != null && typeCheck.isResolved(); } /** @@ -2371,10 +2375,15 @@ public class ScriptDocument { return currentType; } } - } else if (Character.isUpperCase(first.name.charAt(0))) { - // Uppercase first letter - could be a class name for static access - currentType = resolveType(first.name); - } else if (!first.isMethodCall) { + } else { + // Check if first segment is a type name for static access + TypeInfo typeCheck = resolveType(first.name); + if (typeCheck != null && typeCheck.isResolved()) { + currentType = typeCheck; + } + } + + if (currentType == null && !first.isMethodCall) { // Regular variable FieldInfo varInfo = resolveVariable(first.name, position); if (varInfo != null) { @@ -2850,8 +2859,11 @@ public class ScriptDocument { } // Try as a class name (for static access) - if (name.length() > 0 && Character.isUpperCase(name.charAt(0))) { - return resolveType(name); + if (name.length() > 0) { + TypeInfo typeCheck = resolveType(name); + if (typeCheck != null && typeCheck.isResolved()) { + return typeCheck; + } } return null; @@ -2986,9 +2998,15 @@ public class ScriptDocument { if (first.name.equals("this")) { currentType = findEnclosingScriptType(position); - } else if (Character.isUpperCase(first.name.charAt(0))) { - currentType = resolveType(first.name); - } else if (!first.isMethodCall) { + } else { + // Check if first segment is a type name + TypeInfo typeCheck = resolveType(first.name); + if (typeCheck != null && typeCheck.isResolved()) { + currentType = typeCheck; + } + } + + if (currentType == null && !first.isMethodCall) { FieldInfo varInfo = resolveVariable(first.name, position); if (varInfo != null) { currentType = varInfo.getTypeInfo();