diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/FieldInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/FieldInfo.java index 48c55c94c..65dbb165c 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/FieldInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/field/FieldInfo.java @@ -216,6 +216,9 @@ public final class FieldInfo { if (jsField.isReadonly()) { modifiers |= Modifier.FINAL; } + if (jsField.isStatic()) { + modifiers |= Modifier.STATIC; + } // Use documentation if available JSDocInfo jsDocInfo = jsField.getJsDocInfo(); diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSFieldInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSFieldInfo.java index 7cec4dd6c..27e8c589c 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSFieldInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSFieldInfo.java @@ -13,6 +13,7 @@ public class JSFieldInfo { private final String type; // Raw type string for display private TypeInfo typeInfo; // Resolved TypeInfo private final boolean readonly; + private boolean isStatic; private JSDocInfo jsDocInfo; private JSTypeInfo containingType; // The type that contains this field @@ -26,6 +27,13 @@ public class JSFieldInfo { this.jsDocInfo = jsDocInfo; return this; } + + public boolean isStatic() { return isStatic; } + + public JSFieldInfo setStatic(boolean isStatic) { + this.isStatic = isStatic; + return this; + } /** diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSMethodInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSMethodInfo.java index bfb783849..6228f0c0f 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSMethodInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSMethodInfo.java @@ -16,6 +16,7 @@ public class JSMethodInfo { private final String returnType; // Raw type string for display, e.g., "number", "IEntity", "void" private TypeInfo returnTypeInfo; // Resolved TypeInfo (set during Phase 2) private final List parameters; + private boolean isStatic; private JSDocInfo jsDocInfo; private JSTypeInfo containingType; // The type that contains this method @@ -30,6 +31,13 @@ public class JSMethodInfo { return this; } + public boolean isStatic() { return isStatic; } + + public JSMethodInfo setStatic(boolean isStatic) { + this.isStatic = isStatic; + return this; + } + /** * Set the resolved return type info (called during Phase 2 type resolution). */ diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/TypeScriptDefinitionParser.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/TypeScriptDefinitionParser.java index 1b7d22c89..f67eea480 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/TypeScriptDefinitionParser.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/TypeScriptDefinitionParser.java @@ -41,10 +41,10 @@ public class TypeScriptDefinitionParser { "export\\s+type\\s+(\\w+)\\s*=\\s*([^;\\n]+);?"); private static final Pattern METHOD_PATTERN = Pattern.compile( - "(?m)^\\s*(\\w+)\\??\\s*\\((.*)\\)\\s*:\\s*([^;]+);", Pattern.MULTILINE); + "(?m)^\\s*(static\\s+)?(\\w+)\\??\\s*\\((.*)\\)\\s*:\\s*([^;]+);", Pattern.MULTILINE); private static final Pattern FIELD_PATTERN = Pattern.compile( - "^\\s*(readonly\\s+)?(\\w+)\\??\\s*:\\s*([^;]+);", Pattern.MULTILINE); + "^\\s*(static\\s+)?(readonly\\s+)?(\\w+)\\??\\s*:\\s*([^;]+);", Pattern.MULTILINE); private static final Pattern GLOBAL_FUNCTION_PATTERN = Pattern.compile( "function\\s+(\\w+)\\s*\\((.*)\\)\\s*:\\s*([^;]+);"); @@ -570,12 +570,14 @@ public class TypeScriptDefinitionParser { // Parse methods Matcher methodMatcher = METHOD_PATTERN.matcher(body); while (methodMatcher.find()) { - String methodName = methodMatcher.group(1); - String params = methodMatcher.group(2); - String returnType = cleanType(methodMatcher.group(3)); + boolean isStatic = methodMatcher.group(1) != null; + String methodName = methodMatcher.group(2); + String params = methodMatcher.group(3); + String returnType = cleanType(methodMatcher.group(4)); List parameters = parseParameters(params); JSMethodInfo method = new JSMethodInfo(methodName, returnType, parameters); + method.setStatic(isStatic); JSDocInfo jsDoc = extractJSDocBefore(body, methodMatcher.start()); if (jsDoc != null) { @@ -588,7 +590,8 @@ public class TypeScriptDefinitionParser { // Parse fields (that aren't method signatures) Matcher fieldMatcher = FIELD_PATTERN.matcher(body); while (fieldMatcher.find()) { - String fieldName = fieldMatcher.group(2); + boolean isStatic = fieldMatcher.group(1) != null; + String fieldName = fieldMatcher.group(3); // CNPC+ base event implementation CustomNPCsEvent exposes a public "API" field that // ends up polluting autocomplete on every event via ICustomNPCsEvent inheritance. @@ -596,10 +599,11 @@ public class TypeScriptDefinitionParser { if ("ICustomNPCsEvent".equals(typeInfo.getSimpleName()) && "API".equals(fieldName)) continue; - String fieldType = cleanType(fieldMatcher.group(3)); - boolean readonly = fieldMatcher.group(1) != null; + String fieldType = cleanType(fieldMatcher.group(4)); + boolean readonly = fieldMatcher.group(2) != null; JSFieldInfo field = new JSFieldInfo(fieldName, fieldType, readonly); + field.setStatic(isStatic); JSDocInfo jsDoc = extractJSDocBefore(body, fieldMatcher.start()); if (jsDoc != null) { diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodInfo.java index d97d6026c..b06264d1f 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/method/MethodInfo.java @@ -277,6 +277,9 @@ public final class MethodInfo { // JS methods are always public (no access modifiers in .d.ts) int modifiers = Modifier.PUBLIC; + if (jsMethod.isStatic()) { + modifiers |= Modifier.STATIC; + } // Use the documentation from the method if available JSDocInfo jsDocInfo = jsMethod.getJsDocInfo();