fix if var exits for incr
This commit is contained in:
@@ -144,16 +144,25 @@ class UndeclaredVariableCheck(Visitor):
|
|||||||
|
|
||||||
# Second pass: flag VarSub usages that are not accounted for
|
# Second pass: flag VarSub usages that are not accounted for
|
||||||
def _scan(node):
|
def _scan(node):
|
||||||
|
# 1) Variable substitutions like $var
|
||||||
if isinstance(node, VarSub):
|
if isinstance(node, VarSub):
|
||||||
var_name = node.value or ""
|
var_name = node.value or ""
|
||||||
# Strip leading namespace separator for comparison; treat only leading :: as global
|
|
||||||
if var_name.startswith("::"):
|
if var_name.startswith("::"):
|
||||||
return
|
return
|
||||||
base = var_name
|
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:
|
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}'"
|
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))
|
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", []):
|
for ch in getattr(node, "children", []):
|
||||||
_scan(ch)
|
_scan(ch)
|
||||||
|
|
||||||
|
|||||||
@@ -133,7 +133,21 @@ class _Highlighter(Visitor):
|
|||||||
if len(command.args) == 1 and token_info:
|
if len(command.args) == 1 and token_info:
|
||||||
(line, col), length = token_info
|
(line, col), length = token_info
|
||||||
mods = [TokenModifier.reference]
|
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))
|
self._tokens.append(((line, col), length, "variable", mods))
|
||||||
if routine.contents == "proc" and command.args:
|
if routine.contents == "proc" and command.args:
|
||||||
first_arg = command.args[0]
|
first_arg = command.args[0]
|
||||||
|
|||||||
Reference in New Issue
Block a user