mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-13 06:37:34 +00:00
Type Arg class ScriptTypeInfo + TokenHoverInfo + display fixes
This commit is contained in:
1 parent
a88fed137a
commit
eef4e9a922
6 files changed
+65
-25
No files matched your search
@@ -908,20 +908,38 @@ public class ScriptDocument {
|
||||
if (trimmed.isEmpty()) continue;
|
||||
|
||||
int extendsIdx = trimmed.indexOf("extends");
|
||||
String paramName = extendsIdx >= 0 ? trimmed.substring(0, extendsIdx).trim() : trimmed;
|
||||
|
||||
int endIdx = 0;
|
||||
while (endIdx < paramName.length() &&
|
||||
(Character.isJavaIdentifierPart(paramName.charAt(endIdx)) || paramName.charAt(endIdx) == '.')) {
|
||||
endIdx++;
|
||||
}
|
||||
paramName = paramName.substring(0, endIdx);
|
||||
|
||||
String boundName = null;
|
||||
if (extendsIdx >= 0) {
|
||||
String paramName = trimmed.substring(0, extendsIdx).trim();
|
||||
String boundName = trimmed.substring(extendsIdx + 7).trim();
|
||||
TypeParamInfo typeParam = new TypeParamInfo(paramName, boundName.isEmpty() ? null : boundName, null);
|
||||
if (!boundName.isEmpty()) {
|
||||
TypeInfo boundTypeInfo = resolveType(boundName, declOffset);
|
||||
if (boundTypeInfo != null && boundTypeInfo.isResolved()) {
|
||||
typeParam.setBoundTypeInfo(boundTypeInfo);
|
||||
String afterExtends = trimmed.substring(extendsIdx + 7).trim();
|
||||
if (!afterExtends.isEmpty()) {
|
||||
int boundEndIdx = 0;
|
||||
while (boundEndIdx < afterExtends.length() &&
|
||||
(Character.isJavaIdentifierPart(afterExtends.charAt(boundEndIdx)) || afterExtends.charAt(boundEndIdx) == '.')) {
|
||||
boundEndIdx++;
|
||||
}
|
||||
if (boundEndIdx > 0) {
|
||||
boundName = afterExtends.substring(0, boundEndIdx);
|
||||
}
|
||||
}
|
||||
scriptType.addDeclaredTypeParam(typeParam);
|
||||
} else {
|
||||
scriptType.addDeclaredTypeParam(new TypeParamInfo(trimmed, null, null));
|
||||
}
|
||||
|
||||
TypeParamInfo typeParam = new TypeParamInfo(paramName, boundName, null);
|
||||
if (boundName != null) {
|
||||
TypeInfo boundTypeInfo = resolveType(boundName, declOffset);
|
||||
if (boundTypeInfo != null && boundTypeInfo.isResolved()) {
|
||||
typeParam.setBoundTypeInfo(boundTypeInfo);
|
||||
}
|
||||
}
|
||||
scriptType.addDeclaredTypeParam(typeParam);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -733,9 +733,10 @@ public class TokenHoverInfo {
|
||||
addSegment("type parameter ", TokenType.MODIFIER.getHexColor());
|
||||
addSegment(paramName, TokenType.GENERIC_TYPE_PARAM.getHexColor());
|
||||
|
||||
if (typeInfo.getJavaClass() != null && typeInfo.getJavaClass() != Object.class) {
|
||||
TypeInfo bound = typeInfo.getBoundType();
|
||||
if (bound != null && bound.getJavaClass() != null && bound.getJavaClass() != Object.class) {
|
||||
addSegment(" extends ", TokenType.MODIFIER.getHexColor());
|
||||
addSegment(typeInfo.getSimpleName(), getColorForTypeInfo(typeInfo));
|
||||
addSegment(bound.getSimpleName(), getColorForTypeInfo(bound));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+16
-2
@@ -428,8 +428,8 @@ public class MethodCallInfo {
|
||||
TypeInfo argType = arg.getResolvedType();
|
||||
if (argType != null && paramType != null) {
|
||||
if (!TypeChecker.isTypeCompatible(paramType, argType)) {
|
||||
setArgTypeError(i, "Expected " + paramType.getDisplayName() +
|
||||
" but got " + argType.getDisplayName());
|
||||
setArgTypeError(i, "Expected " + getTypeDisplayName(paramType) +
|
||||
" but got " + getTypeDisplayName(argType));
|
||||
}
|
||||
} else if (paramType == null) {
|
||||
setArgTypeError(i, "Parameter type of '" + para.getName() + "' is unresolved");
|
||||
@@ -439,6 +439,20 @@ public class MethodCallInfo {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* in error "Expect T but got String", if T has a resolved bound aka "int" show it instead of T to avoid confusion.
|
||||
* So the error would be "Expect int but got String"
|
||||
*/
|
||||
private String getTypeDisplayName(TypeInfo type) {
|
||||
if(type.isTypeParameter()) {
|
||||
TypeInfo bound = type.getBoundType();
|
||||
if (bound != null)
|
||||
return bound.getDisplayName();
|
||||
}
|
||||
|
||||
return type.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("MethodCallInfo{");
|
||||
|
||||
@@ -152,7 +152,6 @@ public final class GenericContext {
|
||||
|
||||
// Direct type variable substitution.
|
||||
// Handles unresolved types (Java reflection path) and TypeInfo.typeParameter() (script-defined path).
|
||||
// Bounded type parameters have the bound's simpleName, so use getTypeParameterName() for the lookup.
|
||||
if (!type.isResolved() || type.isTypeParameter()) {
|
||||
String lookupKey = type.isTypeParameter() ? type.getTypeParameterName() : type.getSimpleName();
|
||||
TypeInfo substitution = resolveTypeVariable(lookupKey);
|
||||
|
||||
@@ -87,6 +87,7 @@ public class TypeInfo {
|
||||
private boolean isPrimitive; // Whether this is a primitive type (e.g., int, boolean)
|
||||
private boolean isObjectLiteral;
|
||||
private String typeParameterName; // Non-null if this TypeInfo represents a type parameter (e.g., "T")
|
||||
private TypeInfo boundType; // For type parameters with bounds, stores the bound for resolution
|
||||
|
||||
// JavaScript/TypeScript type info (for types from .d.ts files)
|
||||
private final JSTypeInfo jsTypeInfo; // The JS type info (null if Java type)
|
||||
@@ -191,12 +192,15 @@ public class TypeInfo {
|
||||
|
||||
/**
|
||||
* Create a TypeInfo representing a bounded type parameter (e.g., {@code T extends Entity}).
|
||||
* Delegates member lookup to the bound type but records the original parameter name for display.
|
||||
* Keeps the type parameter's own identity (paramName as simpleName/fullName) but stores the
|
||||
* bound separately for display. Uses the bound's javaClass/kind for member resolution (erasure semantics).
|
||||
*/
|
||||
public static TypeInfo typeParameter(String paramName, TypeInfo boundType) {
|
||||
TypeInfo ti = new TypeInfo(boundType.simpleName, boundType.fullName, boundType.packageName,
|
||||
boundType.kind, boundType.javaClass, true, boundType.enclosingType, boundType.jsTypeInfo);
|
||||
Class<?> javaClass = (boundType != null && boundType.javaClass != null) ? boundType.javaClass : Object.class;
|
||||
Kind kind = (boundType != null) ? boundType.kind : Kind.CLASS;
|
||||
TypeInfo ti = new TypeInfo(paramName, paramName, "", kind, javaClass, true, null);
|
||||
ti.typeParameterName = paramName;
|
||||
ti.boundType = boundType;
|
||||
return ti;
|
||||
}
|
||||
|
||||
@@ -208,6 +212,10 @@ public class TypeInfo {
|
||||
return typeParameterName;
|
||||
}
|
||||
|
||||
public TypeInfo getBoundType() {
|
||||
return boundType;
|
||||
}
|
||||
|
||||
public static TypeInfo fromClass(Class<?> clazz) {
|
||||
if (clazz == null) return null;
|
||||
|
||||
@@ -307,12 +315,14 @@ public class TypeInfo {
|
||||
}
|
||||
|
||||
if (type instanceof TypeVariable<?>) {
|
||||
// Type variable like T, E, K, V
|
||||
TypeVariable<?> typeVar = (TypeVariable<?>) type;
|
||||
String varName = typeVar.getName();
|
||||
// Create an unresolved type representing the type variable
|
||||
// The substitution system will handle replacing this with the actual type
|
||||
return TypeInfo.unresolved(varName, varName);
|
||||
// Check for bounds - if bounded, create typeParameter with bound
|
||||
Type[] bounds = typeVar.getBounds();
|
||||
if (bounds != null && bounds.length > 0 && bounds[0] != Object.class) {
|
||||
return TypeInfo.typeParameter(varName, fromGenericType(bounds[0]));
|
||||
}
|
||||
return TypeInfo.typeParameter(varName);
|
||||
}
|
||||
|
||||
if (type instanceof WildcardType) {
|
||||
|
||||
+1
-3
@@ -96,9 +96,7 @@ public class TypeSubstitutor {
|
||||
// Two cases:
|
||||
// 1. Unresolved TypeInfo (Java reflection path: TypeInfo.fromGenericType creates these for T, E, K, V)
|
||||
// 2. TypeInfo.typeParameter() (script-defined path: resolved but tagged as a type parameter)
|
||||
// For tagged type parameters, use getTypeParameterName() as the lookup key — bounded params have
|
||||
// the bound's simpleName as their simpleName (e.g., "Entity" for T extends Entity), so using
|
||||
// simpleName would incorrectly look up "Entity" instead of "T".
|
||||
// For tagged type parameters, use getTypeParameterName() as the lookup key.
|
||||
if (!type.isResolved() || type.isTypeParameter()) {
|
||||
String lookupKey = type.isTypeParameter() ? type.getTypeParameterName() : typeName;
|
||||
TypeInfo substitution = bindings.get(lookupKey);
|
||||
|
||||
Reference in new issue
Block a user