Parsed all JSDoc info for all members of all .d.ts files. Documentations for all API classes now renders properly in hover info

-Added proper TokenHoverInfo for JS classes
This commit is contained in:
bigguy345 committed 2026-01-23 23:10:26 +02:00
1 parent b7a46cab1d
commit ff68dc9258
9 files changed
+164 -21

No files matched your search

@@ -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;
}
/**
@@ -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 = "?";
@@ -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("<b>").append(name).append("</b>: <i>").append(type).append("</i>");
if (documentation != null && !documentation.isEmpty()) {
sb.append("<br><br>").append(documentation);
if (jsDocInfo != null && jsDocInfo.getDescription() != null && !jsDocInfo.getDescription().isEmpty()) {
sb.append("<br><br>").append(jsDocInfo.getDescription());
}
return sb.toString();
@@ -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<JSParameterInfo> parameters;
private String documentation;
private JSDocInfo jsDocInfo;
private JSTypeInfo containingType; // The type that contains this method
public JSMethodInfo(String name, String returnType, List<JSParameterInfo> 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<JSParameterInfo> 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("): <i>").append(returnType).append("</i>");
if (documentation != null && !documentation.isEmpty()) {
sb.append("<br><br>").append(documentation);
if (jsDocInfo != null && jsDocInfo.getDescription() != null && !jsDocInfo.getDescription().isEmpty()) {
sb.append("<br><br>").append(jsDocInfo.getDescription());
}
return sb.toString();
@@ -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<TypeParamInfo> 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.
@@ -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.
@@ -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<JSMethodInfo.JSParameterInfo> 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;
}
}
@@ -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;
}
@@ -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; }