From ede4ca5a3563185834842411e21899e1c484d066 Mon Sep 17 00:00:00 2001 From: swapnil <78632212+swapnilpaliwal-sd@users.noreply.github.com> Date: Mon, 28 Sep 2026 20:52:33 -0700 Subject: [PATCH] hooks: a lowercase word behind a bare dot is an extension or a directive, not a name the directive names `\.json` or a Datalog `\.decl` named a same-named function; `.name(` still does. Co-authored-by: axiomcode-bot[bot] <334110751+axiomcode-bot[bot]@users.noreply.github.com> Co-Authored-By: Claude --- plugins/axiomcode/hooks/direct.py | 7 ++++--- tests/directive.py | 8 ++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/plugins/axiomcode/hooks/direct.py b/plugins/axiomcode/hooks/direct.py index 4857a2157..37eaf8d3e 100755 --- a/plugins/axiomcode/hooks/direct.py +++ b/plugins/axiomcode/hooks/direct.py @@ -68,11 +68,12 @@ def identifiers(pat): if COMMON.fullmatch(n) or re.fullmatch(r'[A-Z0-9_]+', n) or n in out: continue # a keyword or a CONSTANT_SHAPED word is not a callable's name # a plain lowercase word (`once`, `path`, `session`) is as likely prose or a flag as a name, unless THAT - # word is written as code: `locate\(`, `def locate`, `.locate`, `function render`. Code elsewhere in the - # pattern does not count: in `expr_child("client"` the name is expr_child, and client is a string. + # word is written as code: `locate\(`, `def locate`, `obj.locate(`, `function render`. Code elsewhere in the + # pattern does not count: in `expr_child("client"` the name is expr_child, and client is a string. A dot + # alone is not code either: `\.json` is an extension and `\.decl` a Datalog directive. if n.islower() and '_' not in n and not ( re.match(r'\\?\(', br[m.end():]) - or re.search(r'(\b(def|function|fn|func|void|class)\s+|\\?\.|::|->)$', br[:m.start()])): + or re.search(r'(\b(def|function|fn|func|void|class)\s+|::|->)$', br[:m.start()])): continue out.append(n) return out[:6] diff --git a/tests/directive.py b/tests/directive.py index 20462f5a1..7c572f168 100644 --- a/tests/directive.py +++ b/tests/directive.py @@ -121,6 +121,14 @@ def check(why, cond, detail=''): check('CONTROL: a name declared in more than a handful of places says nothing about which one, and is not named', rc == 0 and out == '', f'out={out[:120]}') + rc, out, _ = fire(repo, 'Grep', {'pattern': r'^\.work ref|\.work\b'}, session='s3') + check('CONTROL: a lowercase word behind a dot alone (`\\.json`, a Datalog `.decl`) is an extension or a directive, not named', + rc == 0 and out == '', f'out={out[:120]}') + + rc, out, _ = fire(repo, 'Grep', {'pattern': r'\.work\('}, session='s10') + check('the same word called behind a dot (`.work(`) is a name, and is told', + rc == 0 and ctx(out) and 'src/util.py:1' in ctx(out), f'out={out[:200]}') + rc, out, _ = fire(repo, 'Grep', {'pattern': 'def render(', 'path': 'lib'}, session='s9') check('the declaration inside the searched path is the one named, not the first in the repository', rc == 0 and ctx(out) and 'lib/view.py:5' in ctx(out) and 'src/' not in ctx(out), f'out={out[:200]}')