Skip to content

fix(checker): Tcl/iRules script bodies are reported as string literals #1381

Description

@dekobon

Summary

Checker::is_string calls a Tcl / iRules braced_word a string literal
whatever role it plays, so bca find --type string reports a proc
body, an if body and an iRules when handler as string literals.

#1318 built the predicate that settles this — a braced word is a value
when the command it is passed to takes a value, and a script otherwise
— but it could not apply it here, because Checker::is_string takes
neither code nor ancestors.

Evidence

At the pinned grammars, after #1318:

$ cat p.tcl
proc p {x} { puts $x }

$ bca find --type string --no-config -p p.tcl
== p.tcl ==
╰─ {braced_word:88} from (1, 12) to (1, 23) : { puts $x }

That is a proc body — the block whose commands the walk descends into
— reported as a string literal. The literal half is already right: after
#1318 the same command reports {a b} and {c d} for
lappend x {a b} / puts {c d}, which are strings. Only the script
role is wrong.

src/checker/tcl.rs and src/checker/irules.rs both carry

impl_simple_is_string!(Tcl, QuotedWord, BracedWord, BracedWordSimple);

and BracedWord is the script kind. Alterator::alterate lists the
same three.

Why this is not a Tcl-only edit

fn is_string(node: &Node) -> bool

is the trait signature (src/checker.rs), and impl_simple_is_string!
generates it for most of the twenty-odd languages. Deciding a Tcl braced
word's role needs the source bytes (the enclosing command's leading
word) and the ancestor chain, so honouring it means widening the
signature — either by adding an is_string_with_code sibling with a
forwarding default, the shape Getter::get_op_type_with_code and
Getter::get_space_kind_with_code already use, or by widening
is_string itself and updating every impl and call site.

Note the _with_code trap in .claude/rules/grammar-dispatch.md §7:
if a sibling method is added, every call site on the walk must use the
_with_code spelling, or the override silently never fires.

Scope

  • Decide between a _with_code sibling and a signature widening, and
    enumerate the call sites either way.
  • Route Tcl and iRules BracedWord through the fix(getter): Tcl/iRules braced literals still fabricate a block outside special-cased commands #1318 role predicate
    (Getter::is_value_braced_word), which currently lives on Getter
    and would need to be reachable from Checker or hoisted.
  • Cross-walk Alterator::alterate, which lists the same kinds
    (grammar-dispatch §7).
  • Pin the answer with a bca find --type string test per dialect: a
    script body must not be reported, and the lappend x {a b} literal
    that is reported today must stay reported.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions