mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 22:27:32 +00:00
- Set vars assigned with type ClassTypeInfo (e.g.Java.type("")) as static access
- Unified isStaticAccess checkers to TypeResolver.isStaticAccessExpression
This commit is contained in:
1 parent
176a3b6d50
commit
bfcdd3c47c
4 files changed
+143
-21
No files matched your search
+3
-4
@@ -343,12 +343,11 @@ public class JavaAutocompleteProvider implements AutocompleteProvider {
|
||||
|
||||
/**
|
||||
* Check if the receiver expression represents static access (class type).
|
||||
* Similar logic to FieldChainMarker.isStaticContext().
|
||||
* Returns true if the expression is a TYPE NAME (not a variable).
|
||||
*/
|
||||
protected boolean isStaticAccess(String receiverExpr, int position) {
|
||||
// Try to resolve the receiver expression as a type
|
||||
TypeInfo typeCheck = document.resolveType(receiverExpr);
|
||||
return typeCheck != null && typeCheck.isResolved();
|
||||
// Use unified static access checker
|
||||
return TypeResolver.isStaticAccessExpression(receiverExpr, position, document);
|
||||
}
|
||||
|
||||
protected UsageTracker getUsageTracker() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package noppes.npcs.client.gui.util.script.interpreter;
|
||||
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.TypeResolver;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.type.ScriptTypeInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.field.FieldInfo;
|
||||
import noppes.npcs.client.gui.util.script.interpreter.field.FieldAccessInfo;
|
||||
@@ -477,9 +478,9 @@ public class FieldChainMarker {
|
||||
return false;
|
||||
|
||||
String previousSegment = ctx.chain.segments.get(ctx.currentIndex - 1);
|
||||
|
||||
// Try to resolve the previous segment as a type
|
||||
TypeInfo typeCheck = document.resolveType(previousSegment);
|
||||
return typeCheck != null && typeCheck.isResolved();
|
||||
int prevPos = ctx.chain.positions.get(ctx.currentIndex - 1)[0];
|
||||
|
||||
// Use unified static access checker
|
||||
return TypeResolver.isStaticAccessExpression(previousSegment, prevPos, document);
|
||||
}
|
||||
}
|
||||
@@ -2789,6 +2789,10 @@ public class ScriptDocument {
|
||||
* Check if a method call is a static access (Class.method() style).
|
||||
* Returns true if the immediate receiver before the dot is a class name (uppercase).
|
||||
*/
|
||||
/**
|
||||
* Check if a method call at the given position is static access.
|
||||
* Walks backward from the method name to analyze the receiver.
|
||||
*/
|
||||
private boolean isStaticAccessCall(int methodNameStart) {
|
||||
// Walk backward to find the dot
|
||||
int pos = methodNameStart - 1;
|
||||
@@ -2813,7 +2817,8 @@ public class ScriptDocument {
|
||||
|
||||
char c = text.charAt(pos);
|
||||
if (c == ')' || c == ']') {
|
||||
// Method call or array - this is instance access
|
||||
// Method call or array - would need complex expression resolution
|
||||
// For now, conservatively treat as instance access
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2828,24 +2833,20 @@ public class ScriptDocument {
|
||||
|
||||
String ident = text.substring(identStart, identEnd);
|
||||
|
||||
// Check if this is a class name (starts with uppercase)
|
||||
// AND check if there's no dot before it (making it a direct class reference)
|
||||
// If there's a chain like "obj.SomeClass.method()", we need to check further
|
||||
|
||||
// Skip whitespace before the identifier
|
||||
while (pos >= 0 && Character.isWhitespace(text.charAt(pos)))
|
||||
pos--;
|
||||
|
||||
// If preceded by a dot, this might be part of a longer chain
|
||||
// In that case, it's not a direct static access
|
||||
|
||||
// If preceded by a dot, this is part of a chain - treat as instance for now
|
||||
if (pos >= 0 && text.charAt(pos) == '.') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// It's static access if the identifier resolves to a type
|
||||
|
||||
// Direct identifier - check if it resolves to a type (static) or variable (instance)
|
||||
if (ident.isEmpty()) return false;
|
||||
TypeInfo typeCheck = resolveType(ident);
|
||||
return typeCheck != null && typeCheck.isResolved();
|
||||
|
||||
// Use unified static access checker
|
||||
return TypeResolver.isStaticAccessExpression(ident, identStart, this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3486,6 +3487,14 @@ public class ScriptDocument {
|
||||
if (currentType == null || !currentType.isResolved()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if current type is a synthetic type
|
||||
if (isJavaScript()) {
|
||||
SyntheticType syntheticType = typeResolver.getSyntheticType(currentType.getSimpleName());
|
||||
if (syntheticType != null) {
|
||||
return resolveSyntheticChainSegment(syntheticType, segment);
|
||||
}
|
||||
}
|
||||
|
||||
if (segment.isMethodCall) {
|
||||
// Method call - get return type with argument-based overload resolution
|
||||
@@ -5323,7 +5332,7 @@ public class ScriptDocument {
|
||||
* Resolve a variable by name at a given position.
|
||||
* Works for BOTH Java and JavaScript using unified data structures.
|
||||
*/
|
||||
FieldInfo resolveVariable(String name, int position) {
|
||||
public FieldInfo resolveVariable(String name, int position) {
|
||||
// Find containing method/function
|
||||
MethodInfo containingMethod = findMethodAtPosition(position);
|
||||
|
||||
|
||||
@@ -668,4 +668,117 @@ public class TypeResolver {
|
||||
return typeInfo.getTokenType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if an expression represents static access (accessing a Class, not an instance).
|
||||
* This checks if the expression STRING resolves to a TYPE name.
|
||||
*
|
||||
* Examples:
|
||||
* - "String" -> true (it's a class name)
|
||||
* - "myVar" -> false (it's a variable, even if myVar holds a ClassTypeInfo)
|
||||
* - "Java" -> true (it's a synthetic type)
|
||||
*
|
||||
* Note: This is different from checking if a variable's TYPE is ClassTypeInfo.
|
||||
* For variables holding ClassTypeInfo (like `var File = Java.type("File")`),
|
||||
* the receiver type itself should be checked separately.
|
||||
*
|
||||
* @param typeInfo The resolved TypeInfo (can be null)
|
||||
* @param wasResolvedAsType true if this was resolved as a type name (not a variable)
|
||||
* @return true if this represents static access (direct class reference)
|
||||
*/
|
||||
public static boolean isStaticAccess(TypeInfo typeInfo, boolean wasResolvedAsType) {
|
||||
// If explicitly resolved as a type name, it's static access
|
||||
if (wasResolvedAsType)
|
||||
return true;
|
||||
|
||||
if (typeInfo == null)
|
||||
return false;
|
||||
|
||||
// If the typeInfo itself is a ClassTypeInfo (e.g., result of Java.type()),
|
||||
// then accessing members on it should be static
|
||||
if (typeInfo.isClassReference())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified static access checker for expressions.
|
||||
* Determines if an identifier represents static access (type name) or instance access (variable).
|
||||
*
|
||||
* This method is used by ScriptDocument, JavaAutocompleteProvider, and FieldChainMarker.
|
||||
*
|
||||
* @param identifier The identifier to check (e.g., "String", "myVar", "Java")
|
||||
* @param position The position in the document for context
|
||||
* @param document The script document for resolution
|
||||
* @return true if this represents static access
|
||||
*/
|
||||
public static boolean isStaticAccessExpression(String identifier, int position, ScriptDocument document) {
|
||||
if (identifier == null || identifier.isEmpty() || document == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// First check if it's a variable/field (instance access)
|
||||
FieldInfo fieldInfo = document.resolveVariable(identifier, position);
|
||||
if (fieldInfo != null && fieldInfo.isResolved()) {
|
||||
// It's a variable - check if its type is a ClassTypeInfo
|
||||
return isStaticAccess(fieldInfo.getTypeInfo(), false);
|
||||
}
|
||||
|
||||
// Not a variable - check if it's a type name
|
||||
TypeInfo typeCheck = document.resolveExpressionType(identifier,position);
|
||||
boolean isType = typeCheck != null && typeCheck.isResolved();
|
||||
return isStaticAccess(typeCheck, isType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse string literal arguments from a method call.
|
||||
* Used for resolving dynamic return types like Java.type("className").
|
||||
*
|
||||
* @param argumentsStr The arguments string (e.g., "\"java.io.File\", 123")
|
||||
* @return Array of parsed arguments
|
||||
*/
|
||||
public static String[] parseStringArguments(String argumentsStr) {
|
||||
if (argumentsStr == null || argumentsStr.isEmpty()) {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
List<String> args = new ArrayList<>();
|
||||
StringBuilder current = new StringBuilder();
|
||||
int depth = 0;
|
||||
boolean inString = false;
|
||||
char stringChar = 0;
|
||||
|
||||
for (int i = 0; i < argumentsStr.length(); i++) {
|
||||
char c = argumentsStr.charAt(i);
|
||||
|
||||
if (inString) {
|
||||
current.append(c);
|
||||
if (c == stringChar && (i == 0 || argumentsStr.charAt(i - 1) != '\\')) {
|
||||
inString = false;
|
||||
}
|
||||
} else if (c == '"' || c == '\'') {
|
||||
current.append(c);
|
||||
inString = true;
|
||||
stringChar = c;
|
||||
} else if (c == '(' || c == '[' || c == '{') {
|
||||
depth++;
|
||||
current.append(c);
|
||||
} else if (c == ')' || c == ']' || c == '}') {
|
||||
depth--;
|
||||
current.append(c);
|
||||
} else if (c == ',' && depth == 0) {
|
||||
args.add(current.toString().trim());
|
||||
current = new StringBuilder();
|
||||
} else {
|
||||
current.append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (current.length() > 0) {
|
||||
args.add(current.toString().trim());
|
||||
}
|
||||
|
||||
return args.toArray(new String[0]);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user