Properly marked type parameters and outbounds (T extends Number) + new type param color and TokenType

This commit is contained in:
bigguy345 committed 2026-03-10 17:55:18 +02:00
1 parent 54d8aa48fb
commit 62c15cceff
5 files changed
+77 -12

No files matched your search

@@ -907,14 +907,16 @@ public class ScriptDocument {
String trimmed = param.trim();
if (trimmed.isEmpty()) continue;
int extendsIdx = trimmed.indexOf(" extends ");
int extendsIdx = trimmed.indexOf("extends");
if (extendsIdx >= 0) {
String paramName = trimmed.substring(0, extendsIdx).trim();
String boundName = trimmed.substring(extendsIdx + 9).trim();
TypeParamInfo typeParam = new TypeParamInfo(paramName, boundName, null);
TypeInfo boundTypeInfo = resolveType(boundName, declOffset);
if (boundTypeInfo != null && boundTypeInfo.isResolved()) {
typeParam.setBoundTypeInfo(boundTypeInfo);
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);
}
}
scriptType.addDeclaredTypeParam(typeParam);
} else {
@@ -953,10 +955,33 @@ public class ScriptDocument {
int paramIdx = clause.indexOf(param.getName(), offset - (ltPos + 1));
if (paramIdx >= 0) {
int paramStart = ltPos + 1 + paramIdx;
int paramEnd = paramStart + param.getName().length();
marks.add(new ScriptLine.Mark(paramStart, paramEnd, TokenType.IMPORTED_CLASS, param));
int paramLen = param.getName().length();
int paramEnd = paramStart + paramLen;
marks.add(new ScriptLine.Mark(paramStart, paramEnd, TokenType.GENERIC_TYPE_PARAM, param));
int searchFrom = paramIdx + param.getName().length();
int extendsIdx = clause.indexOf("extends", searchFrom);
if (extendsIdx >= 0) {
int extendsStart = ltPos + 1 + extendsIdx;
marks.add(new ScriptLine.Mark(extendsStart, extendsStart + 7, TokenType.KEYWORD));
TypeInfo boundType = param.getBoundTypeInfo();
if (boundType != null) {
String remaining = clause.substring(extendsIdx + 7).trim();
if (!remaining.isEmpty()) {
int boundEnd = remaining.indexOf(',');
if (boundEnd < 0) boundEnd = remaining.indexOf('&');
String boundName = boundEnd < 0 ? remaining : remaining.substring(0, boundEnd).trim();
if (!boundName.isEmpty()) {
int boundStart = extendsStart + 7;
while (boundStart < gtPos && Character.isWhitespace(text.charAt(boundStart))) boundStart++;
marks.add(new ScriptLine.Mark(boundStart, boundStart + boundName.length(), TokenType.getByType(boundType), boundType));
}
}
}
}
}
}
}
}
/**
* Parse fields and methods inside a script-defined type.
@@ -4,6 +4,7 @@ import noppes.npcs.client.ClientProxy;
import noppes.npcs.client.gui.util.script.interpreter.field.EnumConstantInfo;
import noppes.npcs.client.gui.util.script.interpreter.field.FieldAccessInfo;
import noppes.npcs.client.gui.util.script.interpreter.field.FieldInfo;
import noppes.npcs.client.gui.util.script.interpreter.js_parser.TypeParamInfo;
import noppes.npcs.client.gui.util.script.interpreter.method.MethodCallInfo;
import noppes.npcs.client.gui.util.script.interpreter.method.MethodInfo;
import noppes.npcs.client.gui.util.script.interpreter.token.Token;
@@ -180,6 +181,14 @@ public class ScriptLine {
public void applyTokenMetadata(Token token, Object metadata) {
if (metadata instanceof TypeInfo) {
token.setTypeInfo((TypeInfo) metadata);
} else if (metadata instanceof TypeParamInfo) {
TypeParamInfo typeParam = (TypeParamInfo) metadata;
TypeInfo boundType = typeParam.getBoundTypeInfo();
if (boundType != null) {
token.setTypeInfo(TypeInfo.typeParameter(typeParam.getName(), boundType));
} else {
token.setTypeInfo(TypeInfo.typeParameter(typeParam.getName()));
}
} else if (metadata instanceof MethodCallInfo) {
MethodCallInfo callInfo = (MethodCallInfo) metadata;
if (callInfo.isConstructor()) {
@@ -5,6 +5,7 @@ import noppes.npcs.client.gui.util.script.interpreter.field.AssignmentInfo;
import noppes.npcs.client.gui.util.script.interpreter.field.EnumConstantInfo;
import noppes.npcs.client.gui.util.script.interpreter.field.FieldAccessInfo;
import noppes.npcs.client.gui.util.script.interpreter.field.FieldInfo;
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.jsdoc.JSDocParamTag;
import noppes.npcs.client.gui.util.script.interpreter.jsdoc.JSDocReturnTag;
@@ -153,6 +154,7 @@ public class TokenHoverInfo {
case INTERFACE_DECL:
case ENUM_DECL:
case TYPE_DECL:
case GENERIC_TYPE_PARAM:
info.extractClassInfo(token);
break;
@@ -562,6 +564,7 @@ public class TokenHoverInfo {
: TokenType.IMPORTED_CLASS.getHexColor();
// Render generics with correct segment colors if present
addTypeSegments(typeInfo);
addDeclaredTypeParamSegments(typeInfo);
// Extends
Class<?> superclass = clazz.getSuperclass();
@@ -621,8 +624,7 @@ public class TokenHoverInfo {
: scriptType.getKind() == TypeInfo.Kind.ENUM ? TokenType.ENUM_DECL.getHexColor()
: TokenType.IMPORTED_CLASS.getHexColor();
addTypeSegments(typeInfo);
// Extends clause for ScriptTypeInfo
addDeclaredTypeParamSegments(typeInfo);
if (scriptType.hasSuperClass()) {
addSegment(" extends ", TokenType.MODIFIER.getHexColor());
TypeInfo superClass = scriptType.getSuperClass();
@@ -693,6 +695,7 @@ public class TokenHoverInfo {
iconIndicator = "I";
addSegment("interface ", TokenType.MODIFIER.getHexColor());
addTypeSegments(typeInfo);
addDeclaredTypeParamSegments(typeInfo);
if (jsType.getExtendsType() != null) {
addSegment(" extends ", TokenType.MODIFIER.getHexColor());
@@ -728,7 +731,7 @@ public class TokenHoverInfo {
String paramName = typeInfo.getTypeParameterName();
addSegment("type parameter ", TokenType.MODIFIER.getHexColor());
addSegment(paramName, TokenType.IMPORTED_CLASS.getHexColor());
addSegment(paramName, TokenType.GENERIC_TYPE_PARAM.getHexColor());
if (typeInfo.getJavaClass() != null && typeInfo.getJavaClass() != Object.class) {
addSegment(" extends ", TokenType.MODIFIER.getHexColor());
@@ -1058,6 +1061,29 @@ public class TokenHoverInfo {
splitAndAddTypeName(typeName, getColorForTypeInfo(typeInfo));
}
private void addDeclaredTypeParamSegments(TypeInfo typeInfo) {
List<TypeParamInfo> params = typeInfo.getTypeParams();
if (params == null || params.isEmpty()) return;
if (typeInfo.isParameterized()) return;
addSegment("<", TokenType.DEFAULT.getHexColor());
for (int i = 0; i < params.size(); i++) {
if (i > 0) addSegment(", ", TokenType.DEFAULT.getHexColor());
TypeParamInfo param = params.get(i);
addSegment(param.getName(), TokenType.GENERIC_TYPE_PARAM.getHexColor());
if (param.getBoundTypeName() != null && !"Object".equals(param.getBoundTypeName())) {
addSegment(" extends ", TokenType.MODIFIER.getHexColor());
TypeInfo boundType = param.getBoundTypeInfo();
if (boundType != null && boundType.isResolved()) {
addTypeSegments(boundType);
} else {
addSegment(param.getBoundTypeName(), TokenType.IMPORTED_CLASS.getHexColor());
}
}
}
addSegment(">", TokenType.DEFAULT.getHexColor());
}
private void splitAndAddTypeName(String typeName, int typeColor) {
if (typeName == null || !typeName.endsWith("[]")) {
addSegment(typeName, typeColor);
@@ -30,6 +30,7 @@ public enum TokenType {
ENUM_CONSTANT(0x55FFFF, 84, true, false), // enum constant values (blue, bold+italic) - like IntelliJ
CLASS_DECL(0x00AAAA, 85), // class names in declarations
IMPORTED_CLASS(0x00AAAA, 75), // imported class usages
GENERIC_TYPE_PARAM(0x00FA9A, 76), // generic type parameters like T, E, K, V (light green)
TYPE_DECL(0x00AAAA, 70), // package paths, type references
// Methods
@@ -127,6 +128,8 @@ public enum TokenType {
case INTERFACE_DECL:
case GLOBAL_FIELD:
return 'b'; // aqua
case GENERIC_TYPE_PARAM:
return 'a'; // green (distinct from class types)
case CLASS_DECL:
case IMPORTED_CLASS:
case TYPE_DECL:
@@ -683,6 +683,8 @@ public class TypeInfo {
public TokenType getTokenType() {
if (!resolved)
return TokenType.UNDEFINED_VAR;
if (isTypeParameter())
return TokenType.GENERIC_TYPE_PARAM;
if(isPrimitive())
return TokenType.KEYWORD;