mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 21:17:32 +00:00
Got classes defined in script fully functional
This commit is contained in:
1 parent
992aea663b
commit
dfc0232e99
3 files changed
+100
-21
No files matched your search
@@ -336,9 +336,11 @@ public class ScriptDocument {
|
||||
* Creates ScriptTypeInfo instances and stores them for later resolution.
|
||||
*/
|
||||
private void parseScriptTypes() {
|
||||
// Pattern: (class|interface|enum) ClassName { ... }
|
||||
// Pattern: [modifiers] (class|interface|enum) ClassName [optional ()] { ... }
|
||||
// Matches optional modifiers (public, private, static, final, abstract) before class/interface/enum
|
||||
// Also allows optional () after the class name (common mistake)
|
||||
Pattern typeDecl = Pattern.compile(
|
||||
"\\b(class|interface|enum)\\s+([A-Za-z_][a-zA-Z0-9_]*)\\s*(?:extends\\s+[A-Za-z_][a-zA-Z0-9_.]*)?\\s*(?:implements\\s+[A-Za-z_][a-zA-Z0-9_.,\\s]*)?\\s*\\{");
|
||||
"(?:(?:public|private|protected|static|final|abstract)\\s+)*(class|interface|enum)\\s+([A-Za-z_][a-zA-Z0-9_]*)\\s*(?:\\(\\))?\\s*(?:extends\\s+[A-Za-z_][a-zA-Z0-9_.]*)?\\s*(?:implements\\s+[A-Za-z_][a-zA-Z0-9_.,\\s]*)?\\s*\\{");
|
||||
|
||||
Matcher m = typeDecl.matcher(text);
|
||||
while (m.find()) {
|
||||
@@ -361,8 +363,12 @@ public class ScriptDocument {
|
||||
default: kind = TypeInfo.Kind.CLASS; break;
|
||||
}
|
||||
|
||||
// Extract modifiers from the matched text
|
||||
String fullMatch = text.substring(m.start(), m.end());
|
||||
int modifiers = parseModifiers(fullMatch);
|
||||
|
||||
ScriptTypeInfo scriptType = ScriptTypeInfo.create(
|
||||
typeName, kind, m.start(), bodyStart, bodyEnd);
|
||||
typeName, kind, m.start(), bodyStart, bodyEnd, modifiers);
|
||||
|
||||
// Parse fields and methods inside this type
|
||||
parseScriptTypeMembers(scriptType);
|
||||
@@ -1697,22 +1703,30 @@ public class ScriptDocument {
|
||||
} else {
|
||||
if (isScriptMethod(methodName)) {
|
||||
resolvedMethod = getScriptMethodInfo(methodName);
|
||||
MethodCallInfo callInfo = new MethodCallInfo(
|
||||
methodName, nameStart, nameEnd, openParen, closeParen,
|
||||
arguments, null, resolvedMethod
|
||||
);
|
||||
|
||||
// Only set expected type if this is the final expression (not followed by .field or .method)
|
||||
if (!isFollowedByDot(closeParen)) {
|
||||
TypeInfo expectedType = findExpectedTypeAtPosition(nameStart);
|
||||
if (expectedType != null) {
|
||||
callInfo.setExpectedType(expectedType);
|
||||
// Check if this is a method from a script type
|
||||
// Instance methods from script types cannot be called without a receiver
|
||||
if (resolvedMethod != null && isMethodFromScriptType(resolvedMethod) && !resolvedMethod.isStatic()) {
|
||||
// Instance method called without receiver - mark as undefined
|
||||
marks.add(new ScriptLine.Mark(nameStart, nameEnd, TokenType.UNDEFINED_VAR));
|
||||
} else {
|
||||
MethodCallInfo callInfo = new MethodCallInfo(
|
||||
methodName, nameStart, nameEnd, openParen, closeParen,
|
||||
arguments, null, resolvedMethod
|
||||
);
|
||||
|
||||
// Only set expected type if this is the final expression (not followed by .field or .method)
|
||||
if (!isFollowedByDot(closeParen)) {
|
||||
TypeInfo expectedType = findExpectedTypeAtPosition(nameStart);
|
||||
if (expectedType != null) {
|
||||
callInfo.setExpectedType(expectedType);
|
||||
}
|
||||
}
|
||||
|
||||
callInfo.validate();
|
||||
methodCalls.add(callInfo);
|
||||
marks.add(new ScriptLine.Mark(nameStart, nameEnd, TokenType.METHOD_CALL, callInfo));
|
||||
}
|
||||
|
||||
callInfo.validate();
|
||||
methodCalls.add(callInfo);
|
||||
marks.add(new ScriptLine.Mark(nameStart, nameEnd, TokenType.METHOD_CALL, callInfo));
|
||||
} else {
|
||||
marks.add(new ScriptLine.Mark(nameStart, nameEnd, TokenType.UNDEFINED_VAR));
|
||||
}
|
||||
@@ -2476,6 +2490,30 @@ public class ScriptDocument {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a method belongs to a script-defined type (class/interface/enum).
|
||||
* Returns true if the method is defined inside a script type.
|
||||
*/
|
||||
private boolean isMethodFromScriptType(MethodInfo method) {
|
||||
if (method == null || !method.isDeclaration()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int declPos = method.getDeclarationOffset();
|
||||
if (declPos < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the method's declaration position is inside any script type's body
|
||||
for (ScriptTypeInfo scriptType : scriptTypes.values()) {
|
||||
if (scriptType.containsPosition(declPos)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void markVariables(List<ScriptLine.Mark> marks) {
|
||||
Set<String> knownKeywords = new HashSet<>(Arrays.asList(
|
||||
|
||||
@@ -18,6 +18,7 @@ public class ScriptTypeInfo extends TypeInfo {
|
||||
private final int declarationOffset;
|
||||
private final int bodyStart;
|
||||
private final int bodyEnd;
|
||||
private final int modifiers; // Java reflection modifiers (public, static, final, etc.)
|
||||
|
||||
// Script-defined members
|
||||
private final Map<String, FieldInfo> fields = new HashMap<>();
|
||||
@@ -28,24 +29,25 @@ public class ScriptTypeInfo extends TypeInfo {
|
||||
private ScriptTypeInfo outerClass;
|
||||
|
||||
private ScriptTypeInfo(String simpleName, String fullName, Kind kind,
|
||||
int declarationOffset, int bodyStart, int bodyEnd) {
|
||||
int declarationOffset, int bodyStart, int bodyEnd, int modifiers) {
|
||||
super(simpleName, fullName, "", kind, null, true, null, true);
|
||||
this.scriptClassName = simpleName;
|
||||
this.declarationOffset = declarationOffset;
|
||||
this.bodyStart = bodyStart;
|
||||
this.bodyEnd = bodyEnd;
|
||||
this.modifiers = modifiers;
|
||||
}
|
||||
|
||||
// Factory method
|
||||
public static ScriptTypeInfo create(String simpleName, Kind kind,
|
||||
int declarationOffset, int bodyStart, int bodyEnd) {
|
||||
return new ScriptTypeInfo(simpleName, simpleName, kind, declarationOffset, bodyStart, bodyEnd);
|
||||
int declarationOffset, int bodyStart, int bodyEnd, int modifiers) {
|
||||
return new ScriptTypeInfo(simpleName, simpleName, kind, declarationOffset, bodyStart, bodyEnd, modifiers);
|
||||
}
|
||||
|
||||
public static ScriptTypeInfo createInner(String simpleName, Kind kind, ScriptTypeInfo outer,
|
||||
int declarationOffset, int bodyStart, int bodyEnd) {
|
||||
int declarationOffset, int bodyStart, int bodyEnd, int modifiers) {
|
||||
String fullName = outer.getFullName() + "$" + simpleName;
|
||||
ScriptTypeInfo inner = new ScriptTypeInfo(simpleName, fullName, kind, declarationOffset, bodyStart, bodyEnd);
|
||||
ScriptTypeInfo inner = new ScriptTypeInfo(simpleName, fullName, kind, declarationOffset, bodyStart, bodyEnd, modifiers);
|
||||
inner.outerClass = outer;
|
||||
outer.innerClasses.add(inner);
|
||||
return inner;
|
||||
@@ -56,6 +58,7 @@ public class ScriptTypeInfo extends TypeInfo {
|
||||
public int getDeclarationOffset() { return declarationOffset; }
|
||||
public int getBodyStart() { return bodyStart; }
|
||||
public int getBodyEnd() { return bodyEnd; }
|
||||
public int getModifiers() { return modifiers; }
|
||||
public ScriptTypeInfo getOuterClass() { return outerClass; }
|
||||
public List<ScriptTypeInfo> getInnerClasses() { return innerClasses; }
|
||||
|
||||
|
||||
+38
@@ -351,6 +351,44 @@ public class TokenHoverInfo {
|
||||
addSegment(", ...", TokenType.DEFAULT.getHexColor());
|
||||
}
|
||||
}
|
||||
} else if (typeInfo instanceof ScriptTypeInfo) {
|
||||
// Script-defined type
|
||||
ScriptTypeInfo scriptType = (ScriptTypeInfo) typeInfo;
|
||||
|
||||
// Icon
|
||||
if (scriptType.getKind() == TypeInfo.Kind.INTERFACE) {
|
||||
iconIndicator = "I";
|
||||
} else if (scriptType.getKind() == TypeInfo.Kind.ENUM) {
|
||||
iconIndicator = "E";
|
||||
} else {
|
||||
iconIndicator = "C";
|
||||
}
|
||||
|
||||
// Build declaration with modifiers
|
||||
int mods = scriptType.getModifiers();
|
||||
|
||||
// Modifiers
|
||||
if (Modifier.isPublic(mods)) addSegment("public ", TokenType.MODIFIER.getHexColor());
|
||||
if (Modifier.isAbstract(mods) && scriptType.getKind() != TypeInfo.Kind.INTERFACE)
|
||||
addSegment("abstract ", TokenType.MODIFIER.getHexColor());
|
||||
if (Modifier.isFinal(mods)) addSegment("final ", TokenType.MODIFIER.getHexColor());
|
||||
if (Modifier.isStatic(mods)) addSegment("static ", TokenType.MODIFIER.getHexColor());
|
||||
|
||||
// Class type keyword
|
||||
if (scriptType.getKind() == TypeInfo.Kind.INTERFACE) {
|
||||
addSegment("interface ", TokenType.MODIFIER.getHexColor());
|
||||
} else if (scriptType.getKind() == TypeInfo.Kind.ENUM) {
|
||||
addSegment("enum ", TokenType.MODIFIER.getHexColor());
|
||||
} else {
|
||||
addSegment("class ", TokenType.MODIFIER.getHexColor());
|
||||
}
|
||||
|
||||
// Class name
|
||||
int classColor = scriptType.getKind() == TypeInfo.Kind.INTERFACE ? TokenType.INTERFACE_DECL.getHexColor()
|
||||
: scriptType.getKind() == TypeInfo.Kind.ENUM ? TokenType.ENUM_DECL.getHexColor()
|
||||
: TokenType.IMPORTED_CLASS.getHexColor();
|
||||
addSegment(typeInfo.getSimpleName(), classColor);
|
||||
|
||||
} else {
|
||||
// Unresolved type
|
||||
iconIndicator = "?";
|
||||
|
||||
Reference in new issue
Block a user