mirror of
https://github.com/KAMKEEL/CustomNPC-Plus.git
synced 2026-11-12 21:17:32 +00:00
Stored MethodCallInfo and FieldCallInfo properly for method call args, and underlined them when errored for 2 error types; wrong method call args count and wrong arg type
This commit is contained in:
1 parent
9cb4c96eb3
commit
d9f16fef8a
5 files changed
+83
-44
No files matched your search
@@ -125,4 +125,18 @@ public final class FieldInfo {
|
||||
public int hashCode() {
|
||||
return name.hashCode() * 31 + scope.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper class that holds both FieldInfo and MethodCallInfo for a variable usage.
|
||||
* This is used when a variable is used as an argument to a method call.
|
||||
*/
|
||||
public static class ArgInfo {
|
||||
public final FieldInfo fieldInfo;
|
||||
public final MethodCallInfo methodCallInfo;
|
||||
|
||||
public ArgInfo(FieldInfo fieldInfo, MethodCallInfo methodCallInfo) {
|
||||
this.fieldInfo = fieldInfo;
|
||||
this.methodCallInfo = methodCallInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,6 +202,7 @@ public class MethodCallInfo {
|
||||
public boolean hasArgTypeError() {
|
||||
return !this.argumentTypeErrors.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasArgTypeError(Token t) {
|
||||
for (ArgumentTypeError ate : this.argumentTypeErrors) {
|
||||
if (ate.getArg().equals(t)) {
|
||||
@@ -211,6 +212,10 @@ public class MethodCallInfo {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasArgCountError(Token t) {
|
||||
return hasArgCountError() && t.isMethodCall();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is a static access error (underline method name).
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package noppes.npcs.client.gui.util.script.interpreter;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import noppes.npcs.client.ClientProxy;
|
||||
|
||||
import java.util.*;
|
||||
@@ -74,6 +73,9 @@ public class ScriptDocument {
|
||||
// Local variables per method (methodStartOffset -> {varName -> FieldInfo})
|
||||
private final Map<Integer, Map<String, FieldInfo>> methodLocals = new HashMap<>();
|
||||
|
||||
// Method calls - stores all parsed method call information
|
||||
private final List<MethodCallInfo> methodCalls = new ArrayList<>();
|
||||
|
||||
// Excluded regions (strings/comments) - positions where other patterns shouldn't match
|
||||
private final List<int[]> excludedRanges = new ArrayList<>();
|
||||
|
||||
@@ -180,6 +182,7 @@ public class ScriptDocument {
|
||||
excludedRanges.clear();
|
||||
methodLocals.clear();
|
||||
scriptTypes.clear();
|
||||
methodCalls.clear();
|
||||
|
||||
// Phase 1: Find excluded regions (strings/comments)
|
||||
findExcludedRanges();
|
||||
@@ -858,13 +861,14 @@ public class ScriptDocument {
|
||||
// Numbers
|
||||
addPatternMarks(marks, NUMBER_PATTERN, TokenType.NUMBER);
|
||||
|
||||
// Method calls (parse before variables so we can attach context)
|
||||
markMethodCalls(marks);
|
||||
|
||||
// Variables and fields
|
||||
markVariables(marks);
|
||||
|
||||
// Chained field accesses (e.g., mc.player.world, this.field)
|
||||
markChainedFieldAccesses(marks);
|
||||
|
||||
markMethodCalls(marks);
|
||||
|
||||
// Imported class usages
|
||||
markImportedClassUsages(marks);
|
||||
@@ -1321,6 +1325,9 @@ public class ScriptDocument {
|
||||
arguments, receiverType, resolvedMethod, isStaticAccess
|
||||
);
|
||||
callInfo.validate();
|
||||
|
||||
// Store in collection for later lookup
|
||||
methodCalls.add(callInfo);
|
||||
|
||||
// Always mark method call as green (METHOD_CALL), with error info attached for underline
|
||||
// The MethodCallInfo is attached so rendering can draw curly underline if there's an error
|
||||
@@ -1349,6 +1356,9 @@ public class ScriptDocument {
|
||||
arguments, null, resolvedMethod
|
||||
);
|
||||
callInfo.validate();
|
||||
|
||||
// Store in collection for later lookup
|
||||
methodCalls.add(callInfo);
|
||||
|
||||
// Always mark method call as green (METHOD_CALL), with error info attached for underline
|
||||
marks.add(new ScriptLine.Mark(nameStart, nameEnd, TokenType.METHOD_CALL, callInfo));
|
||||
@@ -1422,6 +1432,25 @@ public class ScriptDocument {
|
||||
return !ident.isEmpty() && Character.isUpperCase(ident.charAt(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the MethodCallInfo that contains the given position as an argument.
|
||||
* Returns null if the position is not inside any method call's argument list.
|
||||
*/
|
||||
private MethodCallInfo findMethodCallContainingPosition(int position) {
|
||||
for (MethodCallInfo call : methodCalls) {
|
||||
// Check if position is within the argument list (between open and close parens)
|
||||
if (position >= call.getOpenParenOffset() && position <= call.getCloseParenOffset()) {
|
||||
// Check if it's within any of the arguments
|
||||
for (MethodCallInfo.Argument arg : call.getArguments()) {
|
||||
if (position >= arg.getStartOffset() && position <= arg.getEndOffset()) {
|
||||
return call;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the matching closing parenthesis for an opening parenthesis.
|
||||
* Handles nested parentheses, strings, and comments.
|
||||
@@ -1951,6 +1980,8 @@ public class ScriptDocument {
|
||||
|
||||
// Find containing method
|
||||
MethodInfo containingMethod = findMethodAtPosition(position);
|
||||
// Check if this variable is an argument to a method call
|
||||
MethodCallInfo callInfo = findMethodCallContainingPosition(position);
|
||||
|
||||
// For uppercase identifiers, only process if it's a known field
|
||||
// Otherwise, let type handling (markImportedClassUsages) handle it
|
||||
@@ -1970,15 +2001,17 @@ public class ScriptDocument {
|
||||
FieldInfo localInfo = locals.get(name);
|
||||
// Only highlight if the position is after the declaration
|
||||
if (localInfo.isVisibleAt(position)) {
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.LOCAL_FIELD, localInfo));
|
||||
Object metadata = callInfo != null ? new FieldInfo.ArgInfo(localInfo, callInfo) : localInfo;
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.LOCAL_FIELD, metadata));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// Check global fields
|
||||
if (globalFields.containsKey(name)) {
|
||||
FieldInfo fieldInfo = globalFields.get(name);
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.GLOBAL_FIELD, fieldInfo));
|
||||
Object metadata = callInfo != null ? new FieldInfo.ArgInfo(fieldInfo, callInfo) : fieldInfo;
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.GLOBAL_FIELD, metadata));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1987,22 +2020,7 @@ public class ScriptDocument {
|
||||
continue;
|
||||
|
||||
// Unknown variable inside method - mark as undefined
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.UNDEFINED_VAR));
|
||||
} else {
|
||||
// Outside any method
|
||||
// Check global fields
|
||||
if (globalFields.containsKey(name)) {
|
||||
FieldInfo fieldInfo = globalFields.get(name);
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.GLOBAL_FIELD, fieldInfo));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip uppercase if not a known field - type handling will deal with it
|
||||
if (isUppercase)
|
||||
continue;
|
||||
|
||||
// Unknown variable outside method - mark as undefined
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.UNDEFINED_VAR));
|
||||
marks.add(new ScriptLine.Mark(m.start(1), m.end(1), TokenType.UNDEFINED_VAR, callInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package noppes.npcs.client.gui.util.script.interpreter;
|
||||
|
||||
import net.minecraft.client.gui.Gui;
|
||||
import noppes.npcs.client.ClientProxy;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
@@ -144,6 +143,10 @@ public class ScriptLine {
|
||||
if (mark.metadata != null) {
|
||||
if (mark.metadata instanceof TypeInfo) {
|
||||
token.setTypeInfo((TypeInfo) mark.metadata);
|
||||
} else if (mark.metadata instanceof FieldInfo.ArgInfo) {
|
||||
FieldInfo.ArgInfo ctx = (FieldInfo.ArgInfo) mark.metadata;
|
||||
token.setFieldInfo(ctx.fieldInfo);
|
||||
token.setMethodCallInfo(ctx.methodCallInfo);
|
||||
} else if (mark.metadata instanceof FieldInfo) {
|
||||
token.setFieldInfo((FieldInfo) mark.metadata);
|
||||
} else if (mark.metadata instanceof MethodInfo) {
|
||||
@@ -206,7 +209,6 @@ public class ScriptLine {
|
||||
int lastIndex = 0;
|
||||
|
||||
// Track positions for underlines
|
||||
List<int[]> underlines = new ArrayList<>(); // [startX, endX, color]
|
||||
int currentX = x;
|
||||
|
||||
for (Token t : tokens) {
|
||||
@@ -222,18 +224,10 @@ public class ScriptLine {
|
||||
// Track underline position if token has one
|
||||
if (t.hasUnderline()) {
|
||||
int tokenWidth = ClientProxy.Font.width(t.getText());
|
||||
underlines.add(new int[]{currentX, currentX + tokenWidth, t.getUnderlineColor()});
|
||||
int currentY = y + ClientProxy.Font.height() - 1;
|
||||
drawCurlyUnderline(currentX + 1, currentY, tokenWidth + 1, t.getUnderlineColor());
|
||||
}
|
||||
|
||||
if (t.getMethodCallInfo() != null) {
|
||||
MethodCallInfo callInfo = t.getMethodCallInfo();
|
||||
if (callInfo.hasArgTypeError(t)) {
|
||||
underlines.add(
|
||||
new int[]{currentX, currentX + ClientProxy.Font.width(t.getText()), t.getUnderlineColor()});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Append the colored token
|
||||
builder.append(COLOR_CHAR)
|
||||
.append(t.getColorCode())
|
||||
@@ -252,11 +246,6 @@ public class ScriptLine {
|
||||
|
||||
// Draw the text
|
||||
ClientProxy.Font.drawString(builder.toString(), x, y, defaultColor);
|
||||
|
||||
// Draw curly underlines for error tokens
|
||||
for (int[] ul : underlines) {
|
||||
drawCurlyUnderline(ul[0], y + ClientProxy.Font.height() - 1, ul[1] - ul[0], ul[2]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -288,12 +277,12 @@ public class ScriptLine {
|
||||
|
||||
GL11.glBegin(GL11.GL_LINE_STRIP);
|
||||
// Wave parameters: 2 pixels amplitude, 4 pixels wavelength
|
||||
int waveHeight = 2;
|
||||
int waveHeight = 1;
|
||||
int waveLength = 4;
|
||||
for (int i = 0; i <= width; i++) {
|
||||
// Create a sine-like wave pattern
|
||||
double phase = (double) i / waveLength * Math.PI * 2;
|
||||
int yOffset = (int) (Math.sin(phase) * waveHeight);
|
||||
float yOffset = (float) (Math.sin(phase) * waveHeight) - 0.5f;
|
||||
GL11.glVertex2f(x + i, y + yOffset);
|
||||
}
|
||||
GL11.glEnd();
|
||||
|
||||
@@ -26,7 +26,7 @@ public class Token {
|
||||
|
||||
// Rendering flags
|
||||
private boolean hasUnderline; // True if this token should be underlined (for errors)
|
||||
private int underlineColor; // Color of the underline (if any)
|
||||
private int underlineColor = 0xFF5555; // Color of the underline (if any)
|
||||
|
||||
// Navigation - set by ScriptLine
|
||||
private Token prev;
|
||||
@@ -119,8 +119,21 @@ public class Token {
|
||||
public MethodCallInfo getMethodCallInfo() { return methodCallInfo; }
|
||||
public ImportData getImportData() { return importData; }
|
||||
public ScriptLine getParentLine() { return parentLine; }
|
||||
public boolean hasUnderline() { return hasUnderline; }
|
||||
public int getUnderlineColor() { return underlineColor; }
|
||||
|
||||
public boolean hasUnderline() {
|
||||
if (methodCallInfo != null) {
|
||||
if (methodCallInfo.hasArgCountError(this))
|
||||
return true;
|
||||
else if (methodCallInfo.hasArgTypeError(this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getUnderlineColor() {
|
||||
return underlineColor;
|
||||
}
|
||||
|
||||
// ==================== SETTERS ====================
|
||||
|
||||
|
||||
Reference in new issue
Block a user