mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 23:37:32 +00:00
-Java class types can are now functional in JS API. (Autocomplete and marking)
-Revamped JSMethodInfo/ParamInfo/FieldInfo/TypeInfo to allow for the above change
This commit is contained in:
1 parent
99f7d05948
commit
869dda34a5
6 files changed
+210
-26
No files matched your search
+53
-1
@@ -1,14 +1,18 @@
|
||||
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
|
||||
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
|
||||
/**
|
||||
* Represents a field/property in a TypeScript interface.
|
||||
*/
|
||||
public class JSFieldInfo {
|
||||
|
||||
private final String name;
|
||||
private final String type; // Raw type string
|
||||
private final String type; // Raw type string for display
|
||||
private TypeInfo typeInfo; // Resolved TypeInfo
|
||||
private final boolean readonly;
|
||||
private String documentation;
|
||||
private JSTypeInfo containingType; // The type that contains this field
|
||||
|
||||
public JSFieldInfo(String name, String type, boolean readonly) {
|
||||
this.name = name;
|
||||
@@ -21,11 +25,59 @@ public class JSFieldInfo {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the containing type (the JSTypeInfo that owns this field).
|
||||
*/
|
||||
public void setContainingType(JSTypeInfo containingType) {
|
||||
this.containingType = containingType;
|
||||
}
|
||||
|
||||
public void setTypeInfo(TypeInfo typeInfo) {
|
||||
this.typeInfo = typeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resolved type, with fallback resolution using type parameters.
|
||||
* @param contextType The TypeInfo context for resolving type parameters
|
||||
* @return The resolved TypeInfo for the field type
|
||||
*/
|
||||
public TypeInfo getResolvedType(TypeInfo contextType) {
|
||||
// Use pre-resolved if available
|
||||
if (typeInfo != null && typeInfo.isResolved())
|
||||
return typeInfo;
|
||||
|
||||
// Fall back to resolving from string
|
||||
TypeResolver resolver = TypeResolver.getInstance();
|
||||
TypeInfo resolved = typeInfo = resolver.resolveJSType(type);
|
||||
|
||||
// If not resolved and contextType has type parameters, try to resolve as type parameter
|
||||
if (contextType != null && !resolved.isResolved()) {
|
||||
TypeInfo paramResolution = contextType.resolveTypeParamToTypeInfo(type);
|
||||
if (paramResolution != null)
|
||||
resolved = typeInfo = paramResolution; // cache it to typeInfo
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public String getName() { return name; }
|
||||
public String getType() { return type; }
|
||||
public TypeInfo getTypeInfo() { return typeInfo; }
|
||||
public boolean isReadonly() { return readonly; }
|
||||
public String getDocumentation() { return documentation; }
|
||||
public JSTypeInfo getContainingType() { return containingType; }
|
||||
|
||||
/**
|
||||
* Get display name - uses resolved TypeInfo simple name if available.
|
||||
*/
|
||||
public String getDisplayType() {
|
||||
if (typeInfo != null && typeInfo.isResolved()) {
|
||||
return typeInfo.getSimpleName();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build hover info HTML for this field.
|
||||
|
||||
+95
-1
@@ -1,5 +1,8 @@
|
||||
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
|
||||
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@@ -8,9 +11,11 @@ import java.util.*;
|
||||
public class JSMethodInfo {
|
||||
|
||||
private final String name;
|
||||
private final String returnType; // Raw type string, e.g., "number", "IEntity", "void"
|
||||
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 JSTypeInfo containingType; // The type that contains this method
|
||||
|
||||
public JSMethodInfo(String name, String returnType, List<JSParameterInfo> parameters) {
|
||||
this.name = name;
|
||||
@@ -22,13 +27,56 @@ public class JSMethodInfo {
|
||||
this.documentation = documentation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resolved return type info (called during Phase 2 type resolution).
|
||||
*/
|
||||
public void setReturnTypeInfo(TypeInfo typeInfo) {
|
||||
this.returnTypeInfo = typeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the containing type (the JSTypeInfo that owns this method).
|
||||
*/
|
||||
public void setContainingType(JSTypeInfo containingType) {
|
||||
this.containingType = containingType;
|
||||
// Also set for all parameters
|
||||
for (JSParameterInfo param : parameters)
|
||||
param.setContainingMethod(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resolved return type, with fallback resolution using type parameters.
|
||||
* @param contextType The TypeInfo context for resolving type parameters (e.g., IPlayer to resolve T → EntityPlayerMP)
|
||||
* @return The resolved TypeInfo for the return type
|
||||
*/
|
||||
public TypeInfo getResolvedReturnType(TypeInfo contextType) {
|
||||
// Use pre-resolved if available
|
||||
if (returnTypeInfo != null && returnTypeInfo.isResolved())
|
||||
return returnTypeInfo;
|
||||
|
||||
// Fall back to resolving from string
|
||||
TypeResolver resolver = TypeResolver.getInstance();
|
||||
TypeInfo resolved = returnTypeInfo = resolver.resolveJSType(returnType);
|
||||
|
||||
// If not resolved and contextType has type parameters, try to resolve as type parameter
|
||||
if (contextType != null && !resolved.isResolved()) {
|
||||
TypeInfo paramResolution = contextType.resolveTypeParamToTypeInfo(returnType);
|
||||
if (paramResolution != null)
|
||||
resolved = returnTypeInfo = paramResolution; //cache it to returnTypeInfo
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// Getters
|
||||
public String getName() { return name; }
|
||||
public String getReturnType() { return returnType; }
|
||||
public TypeInfo getReturnTypeInfo() { return returnTypeInfo; }
|
||||
public List<JSParameterInfo> getParameters() { return parameters; }
|
||||
public String getDocumentation() { return documentation; }
|
||||
public int getParameterCount() { return parameters.size(); }
|
||||
public JSTypeInfo getContainingType() { return containingType; }
|
||||
|
||||
/**
|
||||
* Get a formatted signature string for display.
|
||||
@@ -76,14 +124,60 @@ public class JSMethodInfo {
|
||||
public static class JSParameterInfo {
|
||||
private final String name;
|
||||
private final String type;
|
||||
private TypeInfo typeInfo; // Resolved TypeInfo (set during Phase 2)
|
||||
private JSMethodInfo containingMethod; // The type that contains the method with this parameter
|
||||
|
||||
public JSParameterInfo(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public void setContainingMethod(JSMethodInfo containingMethod) {
|
||||
this.containingMethod = containingMethod;
|
||||
}
|
||||
|
||||
public void setTypeInfo(TypeInfo typeInfo) {
|
||||
this.typeInfo = typeInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resolved type, with fallback resolution using type parameters.
|
||||
* @param contextType The TypeInfo context for resolving type parameters
|
||||
* @return The resolved TypeInfo for the parameter type
|
||||
*/
|
||||
public TypeInfo getResolvedType(TypeInfo contextType) {
|
||||
// Use pre-resolved if available
|
||||
if (typeInfo != null && typeInfo.isResolved())
|
||||
return typeInfo;
|
||||
|
||||
// Fall back to resolving from string
|
||||
TypeResolver resolver = TypeResolver.getInstance();
|
||||
TypeInfo resolved = typeInfo = resolver.resolveJSType(type);
|
||||
|
||||
// If not resolved and contextType has type parameters, try to resolve as type parameter
|
||||
if (contextType != null && !resolved.isResolved()) {
|
||||
TypeInfo paramResolution = contextType.resolveTypeParamToTypeInfo(type);
|
||||
if (paramResolution != null)
|
||||
resolved = typeInfo = paramResolution; //cache it to typeInfo
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
public String getType() { return type; }
|
||||
public TypeInfo getTypeInfo() {return typeInfo;}
|
||||
public JSMethodInfo getContainingMethod() {return containingMethod;}
|
||||
|
||||
/**
|
||||
* Get display name - uses resolved TypeInfo simple name if available.
|
||||
*/
|
||||
public String getDisplayType() {
|
||||
if (typeInfo != null && typeInfo.isResolved()) {
|
||||
return typeInfo.getSimpleName();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
+30
@@ -1,6 +1,7 @@
|
||||
package noppes.npcs.client.gui.util.script.interpreter.js_parser;
|
||||
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -50,6 +51,7 @@ public class JSTypeInfo {
|
||||
}
|
||||
|
||||
public void addMethod(JSMethodInfo method) {
|
||||
method.setContainingType(this);
|
||||
// Handle overloads - store with index if name already exists
|
||||
String key = method.getName();
|
||||
if (methods.containsKey(key)) {
|
||||
@@ -65,6 +67,7 @@ public class JSTypeInfo {
|
||||
}
|
||||
|
||||
public void addField(JSFieldInfo field) {
|
||||
field.setContainingType(this);
|
||||
fields.put(field.getName(), field);
|
||||
}
|
||||
|
||||
@@ -118,6 +121,33 @@ public class JSTypeInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all member types (return types, field types, parameter types).
|
||||
* Called during Phase 2 after all types are loaded into the registry.
|
||||
* This resolves types like "Java.java.io.File" to proper TypeInfo objects.
|
||||
*/
|
||||
public void resolveMemberTypes() {
|
||||
TypeResolver resolver = TypeResolver.getInstance();
|
||||
|
||||
// Resolve method return types and parameter types
|
||||
for (JSMethodInfo method : methods.values()) {
|
||||
TypeInfo returnTypeInfo = resolver.resolveJSType(method.getReturnType());
|
||||
method.setReturnTypeInfo(returnTypeInfo);
|
||||
|
||||
// Resolve parameter types
|
||||
for (JSMethodInfo.JSParameterInfo param : method.getParameters()) {
|
||||
TypeInfo paramTypeInfo = resolver.resolveJSType(param.getType());
|
||||
param.setTypeInfo(paramTypeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve field types
|
||||
for (JSFieldInfo field : fields.values()) {
|
||||
TypeInfo fieldTypeInfo = resolver.resolveJSType(field.getType());
|
||||
field.setTypeInfo(fieldTypeInfo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a type parameter to its bound TypeInfo.
|
||||
* For example, if this type has "T extends EntityPlayerMP", resolveTypeParam("T") returns the TypeInfo for EntityPlayerMP.
|
||||
|
||||
+15
@@ -86,6 +86,9 @@ public class JSTypeRegistry {
|
||||
// Phase 2: Resolve all type parameters now that all types are loaded
|
||||
resolveAllTypeParameters();
|
||||
|
||||
// Phase 2b: Resolve member types (return types, field types, param types)
|
||||
resolveAllMemberTypes();
|
||||
|
||||
resolveInheritance();
|
||||
registerEngineGlobalObjects();
|
||||
|
||||
@@ -227,6 +230,7 @@ public class JSTypeRegistry {
|
||||
TypeScriptDefinitionParser parser = new TypeScriptDefinitionParser(this);
|
||||
parser.parseDirectory(directory);
|
||||
resolveAllTypeParameters();
|
||||
resolveAllMemberTypes();
|
||||
resolveInheritance();
|
||||
initialized = true;
|
||||
System.out.println("[JSTypeRegistry] Loaded " + types.size() + " types, " + hooks.size() + " hooks");
|
||||
@@ -246,6 +250,7 @@ public class JSTypeRegistry {
|
||||
TypeScriptDefinitionParser parser = new TypeScriptDefinitionParser(this);
|
||||
parser.parseVsixArchive(vsixFile);
|
||||
resolveAllTypeParameters();
|
||||
resolveAllMemberTypes();
|
||||
resolveInheritance();
|
||||
initialized = true;
|
||||
System.out.println("[JSTypeRegistry] Loaded " + types.size() + " types, " + hooks.size() + " hooks from VSIX");
|
||||
@@ -376,6 +381,16 @@ public class JSTypeRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve all member types (return types, field types, parameter types) for all types.
|
||||
* Called after resolveAllTypeParameters (Phase 2b).
|
||||
* This resolves types like "Java.java.io.File" to proper TypeInfo objects.
|
||||
*/
|
||||
public void resolveAllMemberTypes() {
|
||||
for (JSTypeInfo type : types.values())
|
||||
type.resolveMemberTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve inheritance relationships between types.
|
||||
* For each type, walks up the parent chain and resolves all ancestors.
|
||||
|
||||
+4
-23
@@ -175,19 +175,9 @@ public final class MethodInfo {
|
||||
*/
|
||||
public static MethodInfo fromJSMethod(JSMethodInfo jsMethod, TypeInfo containingType) {
|
||||
String name = jsMethod.getName();
|
||||
noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver resolver = noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver.getInstance();
|
||||
|
||||
// Resolve the return type - first from TypeResolver, then check for type parameters
|
||||
String returnTypeName = jsMethod.getReturnType();
|
||||
TypeInfo returnType = resolver.resolveJSType(returnTypeName);
|
||||
|
||||
// If not resolved and containingType has type parameters, try to resolve as type parameter
|
||||
if (containingType != null && !returnType.isResolved()) {
|
||||
TypeInfo paramResolution = containingType.resolveTypeParamToTypeInfo(returnTypeName);
|
||||
if (paramResolution != null) {
|
||||
returnType = paramResolution;
|
||||
}
|
||||
}
|
||||
// Use the new getResolvedReturnType method
|
||||
TypeInfo returnType = jsMethod.getResolvedReturnType(containingType);
|
||||
|
||||
// Convert JS parameters to FieldInfo
|
||||
List<FieldInfo> params = new ArrayList<>();
|
||||
@@ -195,18 +185,9 @@ public final class MethodInfo {
|
||||
|
||||
for (JSMethodInfo.JSParameterInfo param : jsParams) {
|
||||
String paramName = param.getName();
|
||||
String paramTypeName = param.getType();
|
||||
|
||||
// Resolve parameter type - first from TypeResolver, then check for type parameters
|
||||
TypeInfo paramType = resolver.resolveJSType(paramTypeName);
|
||||
|
||||
// If not resolved and containingType has type parameters, try to resolve as type parameter
|
||||
if (containingType != null && !paramType.isResolved()) {
|
||||
TypeInfo paramResolution = containingType.resolveTypeParamToTypeInfo(paramTypeName);
|
||||
if (paramResolution != null) {
|
||||
paramType = paramResolution;
|
||||
}
|
||||
}
|
||||
// Use the new getResolvedType method
|
||||
TypeInfo paramType = param.getResolvedType(containingType);
|
||||
|
||||
params.add(FieldInfo.reflectionParam(paramName, paramType));
|
||||
}
|
||||
|
||||
+13
-1
@@ -129,7 +129,7 @@ public class TypeResolver {
|
||||
* Resolve a type name for JavaScript context.
|
||||
* Handles JS primitives, .d.ts types, and falls back to Java types.
|
||||
*
|
||||
* @param jsTypeName The JS type name (e.g., "IPlayer", "string", "number")
|
||||
* @param jsTypeName The JS type name (e.g., "IPlayer", "string", "number", "Java.java.io.File")
|
||||
* @return TypeInfo for the resolved type, or unresolved TypeInfo if not found
|
||||
*/
|
||||
public TypeInfo resolveJSType(String jsTypeName) {
|
||||
@@ -148,6 +148,18 @@ public class TypeResolver {
|
||||
// Strip array brackets for base type resolution
|
||||
boolean isArray = jsTypeName.endsWith("[]");
|
||||
String baseName = isArray ? jsTypeName.substring(0, jsTypeName.length() - 2) : jsTypeName;
|
||||
|
||||
// Handle "Java." prefix - convert to actual Java type
|
||||
// e.g., "Java.java.io.File" -> "java.io.File"
|
||||
if (baseName.startsWith("Java.")) {
|
||||
String javaFullName = baseName.substring(5); // Remove "Java."
|
||||
TypeInfo javaType = resolveFullName(javaFullName);
|
||||
if (javaType != null && javaType.isResolved()) {
|
||||
return isArray ? TypeInfo.arrayOf(javaType) : javaType;
|
||||
}
|
||||
// Still return unresolved with the cleaned-up name
|
||||
return TypeInfo.unresolved(javaFullName.substring(javaFullName.lastIndexOf('.') + 1), javaFullName);
|
||||
}
|
||||
|
||||
switch (baseName.toLowerCase()) {
|
||||
case "string":
|
||||
|
||||
Reference in new issue
Block a user