fix if var exits for incr

This commit is contained in:
Christoph Brandau
2025-08-13 12:45:46 +02:00
parent 781b240128
commit 4a94f1aea8
2 changed files with 26 additions and 3 deletions
+11 -2
View File
@@ -144,16 +144,25 @@ class UndeclaredVariableCheck(Visitor):
# Second pass: flag VarSub usages that are not accounted for
def _scan(node):
# 1) Variable substitutions like $var
if isinstance(node, VarSub):
var_name = node.value or ""
# Strip leading namespace separator for comparison; treat only leading :: as global
if var_name.startswith("::"):
return
base = var_name
# VarSub.value does not include index; indices are separate children
if base not in locals_set and base not in declared_globals:
msg = f"Variable '{base}' used in proc is not set locally and not declared global; use 'global {base}' or '$::{base}'"
self._violations.append(Violation(Rules.UNDECLARED_VARIABLE, msg, node.pos, node.end_pos))
# 2) Commands that take a variable name as first argument, e.g., 'incr var [amount]'
elif isinstance(node, Command) and hasattr(node.routine, "contents"):
if node.routine.contents == "incr" and node.args:
first_arg = node.args[0]
text = _word_text(first_arg) or ""
base = text.split("(", 1)[0]
if base and not base.startswith("::"):
if base not in locals_set and base not in declared_globals:
msg = f"Variable '{base}' used in proc is not set locally and not declared global; use 'global {base}'"
self._violations.append(Violation(Rules.UNDECLARED_VARIABLE, msg, first_arg.pos, first_arg.end_pos))
for ch in getattr(node, "children", []):
_scan(ch)
+15 -1
View File
@@ -133,7 +133,21 @@ class _Highlighter(Visitor):
if len(command.args) == 1 and token_info:
(line, col), length = token_info
mods = [TokenModifier.reference]
# Mark as reference (read); remove write/declaration (keep simple: we still keep declaration above for consistency)
self._tokens.append(((line, col), length, "variable", mods))
# Variable modification via 'incr var [amount]'
if routine.contents == "incr" and command.args:
first_arg = command.args[0]
token_info = self._get_token_info(first_arg)
if token_info:
(line, col), length = token_info
mods = [TokenModifier.write]
# Add global flag if explicitly namespaced
try:
name_text = getattr(first_arg, "value", None) or getattr(first_arg, "contents", None) or ""
if isinstance(name_text, str) and name_text.startswith("::"):
mods.append(TokenModifier.globalvar)
except Exception:
pass
self._tokens.append(((line, col), length, "variable", mods))
if routine.contents == "proc" and command.args:
first_arg = command.args[0]