From 3b2ac768c646dbb9d4d1f6fe1ce803657180afc8 Mon Sep 17 00:00:00 2001 From: bigguy345 Date: Sat, 27 Dec 2025 22:44:41 +0200 Subject: [PATCH] Error "var already defined in scope" --- .../script/interpreter/AssignmentInfo.java | 31 ++++++++++++-- .../script/interpreter/ScriptDocument.java | 40 +++++++++++++++++-- 2 files changed, 65 insertions(+), 6 deletions(-) diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/AssignmentInfo.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/AssignmentInfo.java index dd7c15f44..d6c5e0995 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/AssignmentInfo.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/AssignmentInfo.java @@ -25,7 +25,8 @@ public class AssignmentInfo { PRIVATE_ACCESS, // Attempting to access private field PROTECTED_ACCESS, // Attempting to access protected field from invalid context UNRESOLVED_TARGET, // Target variable/field doesn't exist - STATIC_CONTEXT_ERROR // Accessing instance field from static context + STATIC_CONTEXT_ERROR, // Accessing instance field from static context + DUPLICATE_DECLARATION // Variable is already defined in the scope } // Statement position @@ -74,6 +75,29 @@ public class AssignmentInfo { this.reflectionField = reflectionField; this.isFinal = isFinal; } + + /** + * Factory method to create an AssignmentInfo representing a duplicate declaration error. + * Only the LHS (variable name) position is relevant for underlining. + */ + public static AssignmentInfo duplicateDeclaration(String varName, int nameStart, int nameEnd, String errorMessage) { + AssignmentInfo info = new AssignmentInfo( + varName, + nameStart, // statementStart = nameStart for underline positioning + nameStart, // lhsStart + nameEnd, // lhsEnd + null, // targetType + -1, // rhsStart (not applicable) + -1, // rhsEnd (not applicable) + null, // sourceType + null, // sourceExpr + null, // receiverType + null, // reflectionField + false // isFinal + ); + info.setError(ErrorType.DUPLICATE_DECLARATION, errorMessage); + return info; + } // ==================== VALIDATION ==================== @@ -258,14 +282,15 @@ public class AssignmentInfo { // ==================== ERROR TYPE CHECKS ==================== /** - * Check if this is an LHS error (final reassignment, access errors). + * Check if this is an LHS error (final reassignment, access errors, duplicate declarations). * These errors should underline the LHS. */ public boolean isLhsError() { return errorType == ErrorType.FINAL_REASSIGNMENT || errorType == ErrorType.PRIVATE_ACCESS || errorType == ErrorType.PROTECTED_ACCESS || - errorType == ErrorType.STATIC_CONTEXT_ERROR; + errorType == ErrorType.STATIC_CONTEXT_ERROR || + errorType == ErrorType.DUPLICATE_DECLARATION; } /** diff --git a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java index 9201ca4e4..f44f8c9d6 100644 --- a/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java +++ b/src/main/java/noppes/npcs/client/gui/util/script/interpreter/ScriptDocument.java @@ -83,6 +83,9 @@ public class ScriptDocument { // Assignments to external fields (fields from reflection, not script-defined) private final List externalFieldAssignments = new ArrayList<>(); + // Declaration errors (duplicate declarations, etc.) + private final List declarationErrors = new ArrayList<>(); + // Excluded regions (strings/comments) - positions where other patterns shouldn't match private final List excludedRanges = new ArrayList<>(); @@ -191,6 +194,7 @@ public class ScriptDocument { scriptTypes.clear(); methodCalls.clear(); externalFieldAssignments.clear(); + declarationErrors.clear(); // Phase 1: Find excluded regions (strings/comments) findExcludedRanges(); @@ -626,7 +630,16 @@ public class ScriptDocument { int declPos = bodyStart + m.start(2); FieldInfo fieldInfo = FieldInfo.localField(varName, typeInfo, declPos, method, initStart, initEnd, modifiers); - locals.put(varName, fieldInfo); + + // Check for duplicate declaration (in locals or globals) + if (locals.containsKey(varName) || globalFields.containsKey(varName)) { + // Create a declaration error for this duplicate + AssignmentInfo dupError = AssignmentInfo.duplicateDeclaration( + varName, declPos, declPos + varName.length(), + "Variable '" + varName + "' is already defined in the scope"); + declarationErrors.add(dupError); + } else if (!locals.containsKey(varName)) + locals.put(varName, fieldInfo); } } } @@ -865,7 +878,19 @@ public class ScriptDocument { TypeInfo typeInfo = resolveType(typeName); FieldInfo fieldInfo = FieldInfo.globalField(fieldName, typeInfo, position, documentation, initStart, initEnd, modifiers); - globalFields.put(fieldName, fieldInfo); + + // Check for duplicate declaration + if (globalFields.containsKey(fieldName)) { + // Create a declaration error for this duplicate + AssignmentInfo dupError = AssignmentInfo.duplicateDeclaration( + fieldName, position, position + fieldName.length(), + "Variable '" + fieldName + "' is already defined in the scope"); + declarationErrors.add(dupError); + } else { + globalFields.put(fieldName, fieldInfo); + } + + } } } @@ -3152,7 +3177,7 @@ public class ScriptDocument { // Resolve the target field (should already exist from parseGlobalFields or parseLocalVariables) FieldInfo targetField = resolveVariable(varName, varNameStart); - if (targetField == null) { + if (targetField == null || targetField.getDeclarationAssignment() != null) { return; // Field doesn't exist, can't attach assignment } @@ -3506,6 +3531,12 @@ public class ScriptDocument { } } } + + for (AssignmentInfo assign : declarationErrors) { + if (assign.containsLhsPosition(position)) { + return assign; + } + } // Check external field assignments with same LHS-first priority for (AssignmentInfo assign : externalFieldAssignments) { @@ -3552,6 +3583,9 @@ public class ScriptDocument { errored.add(assign); } } + + // Include declaration errors (duplicates, etc.) + errored.addAll(declarationErrors); return errored; }