Skip to content

fix: recognize embedded-argument keywords as used (#34)#35

Open
EAnathos wants to merge 3 commits into
viadee:mainfrom
EAnathos:fix/embedded-argument-keyword-usage
Open

fix: recognize embedded-argument keywords as used (#34)#35
EAnathos wants to merge 3 commits into
viadee:mainfrom
EAnathos:fix/embedded-argument-keyword-usage

Conversation

@EAnathos

@EAnathos EAnathos commented Jul 9, 2026

Copy link
Copy Markdown

Summary

Fixes #34.

Keywords defined with embedded (parameterized) arguments — e.g. Click On ${element} — were never counted as used. Usage detection compared keyword names by exact string equality, so a call like Click On ${something} (or with a literal value, Click On Button) did not match the definition, and the keyword was wrongly reported as unused (also skewing the reusage rate).

Changes

  • schemas/domain/keywords.py
    • Add normalize_keyword_name() (single source of truth for the existing lowercase / strip-spaces / strip-underscores normalization).
    • Add KeywordProperties.matches(called_name) which resolves both exact and embedded-argument keyword names by building a regex where each ${...} becomes a wildcard.
  • registries/keyword_registry.py
    • resolve() now falls back to matches() for embedded keywords (exact matches still take precedence).
    • _normalize_keyword_name() delegates to the shared helper.
  • services/keyword_usage_service.py
    • The three usage counters now use keyword.matches(called) instead of literal list.count() lookups.

Tests

  • Unit tests for KeywordProperties.matches() (exact, embedded with differing variable name, literal value, prefix variants, and non-matches).
  • Regression tests for the usage counters and the "unused keywords" list.

Full backend suite: no new failures versus main (the pre-existing failures are unrelated, caused by optional export dependencies not installed locally).

Manual verification

Reproducer project (Click On ${element} defined, called as Click On ${something}):

before after
roboview analyze → Unused Keywords 1 0

Keywords defined with embedded arguments (e.g. `Click On ${element}`) were
never counted as used, because usage detection compared keyword names by exact
string equality. A call such as `Click On ${something}` (or with a literal
value, `Click On Button`) therefore did not match the definition and the
keyword was wrongly reported as unused.

Robot Framework resolves embedded arguments statically by treating them as
wildcards; this mirrors that behavior:

- Add `KeywordProperties.matches()` which resolves both exact and
  embedded-argument keyword names, plus a shared `normalize_keyword_name()`
  helper (now reused by `KeywordRegistry`).
- Use `matches()` in `KeywordRegistry.resolve()` (as a fallback after exact
  matches) and in the usage counters of `KeywordUsageService`, replacing the
  literal `list.count()` lookups.

Adds unit tests for `matches()` and regression tests for the usage counters.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@EAnathos EAnathos closed this Jul 9, 2026
@EAnathos EAnathos deleted the fix/embedded-argument-keyword-usage branch July 9, 2026 18:49
@EAnathos EAnathos restored the fix/embedded-argument-keyword-usage branch July 9, 2026 18:50
@EAnathos EAnathos reopened this Jul 9, 2026
EAnathos and others added 2 commits July 9, 2026 21:03
…view)

Counting usages via KeywordProperties.matches() ignored Robot Framework's
resolution precedence: a call to an exact keyword (e.g. `Open Browser`) was also
counted for any embedded keyword whose pattern happened to match it (e.g.
`Open ${page}`), so a genuinely unused embedded keyword could be reported as
used and metrics were skewed.

Count a call for a keyword only when it actually resolves to it, using the
registry (exact match wins over embedded) as the single source of truth. A cheap
matches() pre-filter keeps the registry-wide resolve off the hot path.

Also simplifies the matching helpers (single loop over the prefix variants, no
redundant regex anchors now that callers use fullmatch).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…iadee#34 review)

The exact-wins refactor routed usage counting through resolve(), which returns a
single keyword. That also arbitrated exact-vs-exact collisions: when the same
keyword name is defined in several resources and called unqualified, resolve()
picks the first-registered one, so the others were counted as 0 usages and
wrongly reported as unused ("candidate for removal").

Only embedded matches need the resolve() precedence gate. An exact name
reference is a genuine reference to every keyword sharing that name, so count it
unconditionally; keep the resolve() gate for embedded-argument matches only.

Adds a regression test for a duplicately-named keyword called unprefixed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Keywords with parameterized names not detected as used

1 participant