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 ec3958f02..55834d311 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
@@ -182,9 +182,13 @@ public final class FieldInfo {
}
// Use documentation if available
- String documentation = jsField.getDocumentation();
+ JSDocInfo jsDocInfo = jsField.getJsDocInfo();
+ String jsDocDesc = jsDocInfo != null ? jsDocInfo.getDescription() : null;
+ String documentation = jsDocDesc != null ? jsDocDesc : jsField.getDocumentation();
- return new FieldInfo(name, Scope.GLOBAL, type, -1, true, null, documentation, -1, -1, modifiers, null);
+ FieldInfo fieldInfo = new FieldInfo(name, Scope.GLOBAL, type, -1, true, null, documentation, -1, -1, modifiers, null);
+ fieldInfo.setJSDocInfo(jsDocInfo);
+ return fieldInfo;
}
/**
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverInfo.java
index 2a1cece89..216a9102d 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverInfo.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/hover/TokenHoverInfo.java
@@ -666,6 +666,23 @@ public class TokenHoverInfo {
}
}
+ } else if (typeInfo.isJSType()) {
+ JSTypeInfo jsType = typeInfo.getJSTypeInfo();
+
+ iconIndicator = "I";
+ addSegment("interface ", TokenType.MODIFIER.getHexColor());
+ addSegment(getName(typeInfo), TokenType.INTERFACE_DECL.getHexColor());
+
+ if (jsType.getExtendsType() != null) {
+ addSegment(" extends ", TokenType.MODIFIER.getHexColor());
+ addSegment(jsType.getExtendsType(), TokenType.INTERFACE_DECL.getHexColor());
+ }
+
+ JSDocInfo jsDocInfo = typeInfo.getJSDocInfo();
+ if (jsDocInfo != null) {
+ formatJSDocumentation(jsDocInfo, null);
+ }
+
} else {
// Unresolved type
iconIndicator = "?";
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 fc1ccd642..afcb09a6b 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
@@ -1,5 +1,6 @@
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocInfo;
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
/**
@@ -11,7 +12,7 @@ public class JSFieldInfo {
private final String type; // Raw type string for display
private TypeInfo typeInfo; // Resolved TypeInfo
private final boolean readonly;
- private String documentation;
+ private JSDocInfo jsDocInfo;
private JSTypeInfo containingType; // The type that contains this field
public JSFieldInfo(String name, String type, boolean readonly) {
@@ -20,8 +21,8 @@ public class JSFieldInfo {
this.readonly = readonly;
}
- public JSFieldInfo setDocumentation(String documentation) {
- this.documentation = documentation;
+ public JSFieldInfo setJsDocInfo(JSDocInfo jsDocInfo) {
+ this.jsDocInfo = jsDocInfo;
return this;
}
@@ -66,9 +67,17 @@ public class JSFieldInfo {
public String getType() { return type; }
public TypeInfo getTypeInfo() { return typeInfo; }
public boolean isReadonly() { return readonly; }
- public String getDocumentation() { return documentation; }
+ public JSDocInfo getJsDocInfo() { return jsDocInfo; }
public JSTypeInfo getContainingType() { return containingType; }
+ /**
+ * Get documentation string (backward compatibility).
+ * Extracts description from JSDocInfo if available.
+ */
+ public String getDocumentation() {
+ return jsDocInfo != null ? jsDocInfo.getDescription() : null;
+ }
+
/**
* Get display name - uses resolved TypeInfo simple name if available.
*/
@@ -89,8 +98,8 @@ public class JSFieldInfo {
}
sb.append("").append(name).append(": ").append(type).append("");
- if (documentation != null && !documentation.isEmpty()) {
- sb.append("
").append(documentation);
+ if (jsDocInfo != null && jsDocInfo.getDescription() != null && !jsDocInfo.getDescription().isEmpty()) {
+ sb.append("
").append(jsDocInfo.getDescription());
}
return sb.toString();
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 8999582de..6aef02b7f 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
@@ -1,5 +1,6 @@
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocInfo;
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
@@ -14,7 +15,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 String documentation;
+ private JSDocInfo jsDocInfo;
private JSTypeInfo containingType; // The type that contains this method
public JSMethodInfo(String name, String returnType, List parameters) {
@@ -23,8 +24,8 @@ public class JSMethodInfo {
this.parameters = parameters != null ? new ArrayList<>(parameters) : new ArrayList<>();
}
- public JSMethodInfo setDocumentation(String documentation) {
- this.documentation = documentation;
+ public JSMethodInfo setJsDocInfo(JSDocInfo jsDocInfo) {
+ this.jsDocInfo = jsDocInfo;
return this;
}
@@ -74,10 +75,18 @@ public class JSMethodInfo {
public String getReturnType() { return returnType; }
public TypeInfo getReturnTypeInfo() { return returnTypeInfo; }
public List getParameters() { return parameters; }
- public String getDocumentation() { return documentation; }
+ public JSDocInfo getJsDocInfo() { return jsDocInfo; }
public int getParameterCount() { return parameters.size(); }
public JSTypeInfo getContainingType() { return containingType; }
+ /**
+ * Get documentation string (backward compatibility).
+ * Extracts description from JSDocInfo if available.
+ */
+ public String getDocumentation() {
+ return jsDocInfo != null ? jsDocInfo.getDescription() : null;
+ }
+
/**
* Get a formatted signature string for display.
*/
@@ -106,8 +115,8 @@ public class JSMethodInfo {
}
sb.append("): ").append(returnType).append("");
- if (documentation != null && !documentation.isEmpty()) {
- sb.append("
").append(documentation);
+ if (jsDocInfo != null && jsDocInfo.getDescription() != null && !jsDocInfo.getDescription().isEmpty()) {
+ sb.append("
").append(jsDocInfo.getDescription());
}
return sb.toString();
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeInfo.java
index f25e63a6b..8bdab8493 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeInfo.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeInfo.java
@@ -1,5 +1,9 @@
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocInfo;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocParamTag;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocReturnTag;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocTypeTag;
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
@@ -31,7 +35,7 @@ public class JSTypeInfo {
private JSTypeInfo parentType; // The containing type (for inner types)
// Documentation
- private String documentation;
+ private JSDocInfo jsDocInfo;
public JSTypeInfo(String simpleName, String namespace) {
this.simpleName = simpleName;
@@ -45,8 +49,8 @@ public class JSTypeInfo {
return this;
}
- public JSTypeInfo setDocumentation(String documentation) {
- this.documentation = documentation;
+ public JSTypeInfo setJsDocInfo(JSDocInfo jsDocInfo) {
+ this.jsDocInfo = jsDocInfo;
return this;
}
@@ -86,7 +90,7 @@ public class JSTypeInfo {
public String getNamespace() { return namespace; }
public String getExtendsType() { return extendsType; }
public JSTypeInfo getResolvedParent() { return resolvedParent; }
- public String getDocumentation() { return documentation; }
+ public JSDocInfo getJsDocInfo() { return jsDocInfo; }
public JSTypeInfo getParentType() { return parentType; }
public List getTypeParams() { return typeParams; }
@@ -148,6 +152,49 @@ public class JSTypeInfo {
}
}
+ public void resolveJSDocTypes() {
+ TypeResolver resolver = TypeResolver.getInstance();
+
+ if (jsDocInfo != null) {
+ resolveJSDocInfoTypes(jsDocInfo, resolver);
+ }
+
+ for (JSMethodInfo method : methods.values()) {
+ JSDocInfo methodDoc = method.getJsDocInfo();
+ if (methodDoc != null) {
+ resolveJSDocInfoTypes(methodDoc, resolver);
+ }
+ }
+
+ for (JSFieldInfo field : fields.values()) {
+ JSDocInfo fieldDoc = field.getJsDocInfo();
+ if (fieldDoc != null) {
+ resolveJSDocInfoTypes(fieldDoc, resolver);
+ }
+ }
+ }
+
+ private void resolveJSDocInfoTypes(JSDocInfo jsDoc, TypeResolver resolver) {
+ JSDocTypeTag typeTag = jsDoc.getTypeTag();
+ if (typeTag != null && typeTag.hasType() && typeTag.getTypeInfo() == null) {
+ TypeInfo resolved = resolver.resolveJSType(typeTag.getTypeName());
+ typeTag.setType(typeTag.getTypeName(), resolved, typeTag.getTypeStart(), typeTag.getTypeEnd());
+ }
+
+ for (JSDocParamTag paramTag : jsDoc.getParamTags()) {
+ if (paramTag.hasType() && paramTag.getTypeInfo() == null) {
+ TypeInfo resolved = resolver.resolveJSType(paramTag.getTypeName());
+ paramTag.setType(paramTag.getTypeName(), resolved, paramTag.getTypeStart(), paramTag.getTypeEnd());
+ }
+ }
+
+ JSDocReturnTag returnTag = jsDoc.getReturnTag();
+ if (returnTag != null && returnTag.hasType() && returnTag.getTypeInfo() == null) {
+ TypeInfo resolved = resolver.resolveJSType(returnTag.getTypeName());
+ returnTag.setType(returnTag.getTypeName(), resolved, returnTag.getTypeStart(), returnTag.getTypeEnd());
+ }
+ }
+
/**
* Resolves a type parameter to its bound TypeInfo.
* For example, if this type has "T extends EntityPlayerMP", resolveTypeParam("T") returns the TypeInfo for EntityPlayerMP.
diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeRegistry.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeRegistry.java
index 680172f99..89624c1d4 100644
--- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeRegistry.java
+++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/js_parser/JSTypeRegistry.java
@@ -97,6 +97,9 @@ public class JSTypeRegistry {
// Phase 2b: Resolve member types (return types, field types, param types)
resolveAllMemberTypes();
+ // Phase 2c: Resolve JSDoc types (@param, @return, @type type references)
+ resolveAllJSDocTypes();
+
resolveInheritance();
registerEngineGlobalObjects();
@@ -239,6 +242,7 @@ public class JSTypeRegistry {
parser.parseDirectory(directory);
resolveAllTypeParameters();
resolveAllMemberTypes();
+ resolveAllJSDocTypes();
resolveInheritance();
initialized = true;
System.out.println("[JSTypeRegistry] Loaded " + types.size() + " types, " + hooks.size() + " hooks");
@@ -259,6 +263,7 @@ public class JSTypeRegistry {
parser.parseVsixArchive(vsixFile);
resolveAllTypeParameters();
resolveAllMemberTypes();
+ resolveAllJSDocTypes();
resolveInheritance();
initialized = true;
System.out.println("[JSTypeRegistry] Loaded " + types.size() + " types, " + hooks.size() + " hooks from VSIX");
@@ -594,6 +599,11 @@ public class JSTypeRegistry {
type.resolveMemberTypes();
}
+ public void resolveAllJSDocTypes() {
+ for (JSTypeInfo type : types.values())
+ type.resolveJSDocTypes();
+ }
+
/**
* Resolve inheritance relationships between types.
* For each type, walks up the parent chain and resolves all ancestors.
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 3e0d8b440..32b832ba9 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
@@ -1,5 +1,7 @@
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocInfo;
+
import java.io.*;
import java.util.*;
import java.util.regex.*;
@@ -216,6 +218,11 @@ public class TypeScriptDefinitionParser {
JSTypeInfo typeInfo = new JSTypeInfo(interfaceName, parentNamespace);
+ JSDocInfo jsDoc = extractJSDocBefore(content, interfaceMatcher.start());
+ if (jsDoc != null) {
+ typeInfo.setJsDocInfo(jsDoc);
+ }
+
// Parse type parameters
if (typeParamsStr != null && !typeParamsStr.isEmpty()) {
parseTypeParameters(typeParamsStr, typeInfo);
@@ -261,6 +268,11 @@ public class TypeScriptDefinitionParser {
JSTypeInfo typeInfo = new JSTypeInfo(interfaceName, parentNamespace);
+ JSDocInfo jsDoc = extractJSDocBefore(content, nestedInterfaceMatcher.start());
+ if (jsDoc != null) {
+ typeInfo.setJsDocInfo(jsDoc);
+ }
+
// Parse type parameters
if (typeParamsStr != null && !typeParamsStr.isEmpty()) {
parseTypeParameters(typeParamsStr, typeInfo);
@@ -296,6 +308,11 @@ public class TypeScriptDefinitionParser {
JSTypeInfo typeInfo = new JSTypeInfo(className, parentNamespace);
+ JSDocInfo jsDoc = extractJSDocBefore(content, classMatcher.start());
+ if (jsDoc != null) {
+ typeInfo.setJsDocInfo(jsDoc);
+ }
+
// Parse type parameters
if (typeParamsStr != null && !typeParamsStr.isEmpty()) {
parseTypeParameters(typeParamsStr, typeInfo);
@@ -445,6 +462,12 @@ public class TypeScriptDefinitionParser {
List parameters = parseParameters(params);
JSMethodInfo method = new JSMethodInfo(methodName, returnType, parameters);
+
+ JSDocInfo jsDoc = extractJSDocBefore(body, methodMatcher.start());
+ if (jsDoc != null) {
+ method.setJsDocInfo(jsDoc);
+ }
+
typeInfo.addMethod(method);
}
@@ -460,6 +483,12 @@ public class TypeScriptDefinitionParser {
String fieldType = cleanType(fieldMatcher.group(3));
JSFieldInfo field = new JSFieldInfo(fieldName, fieldType, readonly);
+
+ JSDocInfo jsDoc = extractJSDocBefore(body, fieldMatcher.start());
+ if (jsDoc != null) {
+ field.setJsDocInfo(jsDoc);
+ }
+
typeInfo.addField(field);
}
}
@@ -568,4 +597,12 @@ public class TypeScriptDefinitionParser {
}
return sb.toString();
}
+
+ private JSDocInfo extractJSDocBefore(String content, int elementStart) {
+ String jsDocBlock = DTSJSDocParser.extractJSDocBefore(content, elementStart);
+ if (jsDocBlock != null) {
+ return DTSJSDocParser.parseJSDocBlock(jsDocBlock);
+ }
+ return 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 ababd9816..859d3c0e9 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
@@ -205,9 +205,14 @@ public final class MethodInfo {
int modifiers = Modifier.PUBLIC;
// Use the documentation from the method if available
- String documentation = jsMethod.getDocumentation();
-
- return new MethodInfo(name, returnType, containingType, params, -1, -1, -1, -1, -1, true, false, modifiers, documentation, null);
+ JSDocInfo jsDocInfo = jsMethod.getJsDocInfo();
+ String jsDocDesc = jsDocInfo != null ? jsDocInfo.getDescription() : null;
+ String documentation = jsDocDesc != null ? jsDocDesc : jsMethod.getDocumentation();
+
+ MethodInfo methodInfo = new MethodInfo(name, returnType, containingType, params, -1, -1, -1, -1, -1, true,
+ false, modifiers, documentation, null);
+ methodInfo.setJSDocInfo(jsDocInfo);
+ return methodInfo;
}
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 14f4c6242..cb0800ebb 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
@@ -6,6 +6,7 @@ import noppes.npcs.client.gui.util.script.interpreter.js_parser.JSFieldInfo;
import noppes.npcs.client.gui.util.script.interpreter.js_parser.JSMethodInfo;
import noppes.npcs.client.gui.util.script.interpreter.js_parser.JSTypeInfo;
import noppes.npcs.client.gui.util.script.interpreter.js_parser.TypeParamInfo;
+import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocInfo;
import noppes.npcs.client.gui.util.script.interpreter.method.MethodInfo;
import noppes.npcs.client.gui.util.script.interpreter.token.TokenType;
@@ -227,6 +228,10 @@ public class TypeInfo {
return jsTypeInfo;
}
+ public JSDocInfo getJSDocInfo() {
+ return jsTypeInfo != null ? jsTypeInfo.getJsDocInfo() : null;
+ }
+
// Getters
public String getSimpleName() { return simpleName; }
public String getFullName() { return fullName; }