Skip to content

fix(completion): surface INCLUDE/MEMBER/OMIT/COMPILE/PRAGMA as keyword completions - #394

Open
geircodes wants to merge 1 commit into
msarson:version-1.0.1from
geircodes:fix/word-completion-missing-directives
Open

fix(completion): surface INCLUDE/MEMBER/OMIT/COMPILE/PRAGMA as keyword completions#394
geircodes wants to merge 1 commit into
msarson:version-1.0.1from
geircodes:fix/word-completion-missing-directives

Conversation

@geircodes

Copy link
Copy Markdown

fix(completion): surface INCLUDE/MEMBER/OMIT/COMPILE/PRAGMA as keyword completions

What happened

Reported live: typing INCL at column 2, near the top of a real PROGRAM file (before any procedure), never offered the INCLUDE keyword — only unrelated variables from elsewhere in the project that happened to share the Incl prefix (e.g. IncludeAddress, IncludeCriteria, IncludeIncomplete ), with nothing named INCLUDE itself to compete
against.

Root cause

INCLUDE is modeled in this codebase as a "Compiler Directive" — it's defined in server/src/data/clarion-directives.json (alongside MEMBER, OMIT, COMPILE, PRAGMA, EQUATE, ITEMIZE, SECTION) and served by DirectiveService, which is already wired into hover (HoverRouter.ts:37, alongside BuiltinFunctionService/AttributeService/PropertyService/
EventService/KeywordService).

WordCompletionProvider.ts, however, never queries DirectiveService at all. Its keyword completion only comes from two hardcoded local collections:

private static readonly BLOCK_STRUCTURES = new Set([
    'ACCEPT', 'APPLICATION', 'BEGIN', 'CASE', 'CLASS', 'DETAIL', ...
]);
private static readonly PLAIN_KEYWORDS = [
    'BREAK', 'CYCLE', 'EXIT', 'RETURN', ...
];

Neither list contains INCLUDE (or MEMBER/OMIT/COMPILE/PRAGMA), so none of them could ever appear in word completion — a gap unrelated to any scoping/parsing logic, just a missing data source.

Fix

Wire DirectiveService into WordCompletionProvider, following the exact same pattern already used for AttributeService/BuiltinFunctionService/DataTypeService/ControlService in this same file — a collectDirectives() step added to the seen-map pipeline, run before collectKeywords() so directive descriptions take priority over the bare keyword fallback for anything they overlap with (e.g. SECTION/ITEMIZE, which are also in BLOCK_STRUCTURES):

private collectDirectives(seen: Map<string, CompletionItem>): void {
    for (const d of this.directiveService.getAllByPrefix('')) {
        const key = d.name.toUpperCase();
        if (!seen.has(key)) {
            seen.set(key, {
                label: d.name,
                kind: CompletionItemKind.Keyword,
                detail: d.syntax,
                documentation: d.description,
            });
        }
    }
}

This also fixes the identical missing-completion gap for MEMBER, OMIT, COMPILE, and PRAGMA
— same root cause, same file, same fix.

Testing

New test in WordCompletionProvider.test.ts: a document with an INCLUDE(...) line before any procedure — asserts INCLUDE appears in the completion list for prefix INCL.

Harness against the real repro file: completion for INCL/incl (case-insensitively) at the top of the file now returns INCLUDE — previously returned nothing at all for that keyword. Full suite in an isolated worktree off origin/version-1.0.1: 2341 passing, 0 failing, 4 pending (pre-existing, unrelated).

Deployed and confirmed working live.

Scope

Two files: server/src/providers/WordCompletionProvider.ts,
server/src/test/WordCompletionProvider.test.ts (new test only). Independent of the companion fix/pragma-directive-misclassified-as-function PR — different files, different bug, safe to merge in either order.

Known follow-up (not part of this PR)

The IncludeAddress/IncludeCriteria/etc. noise reported alongside this bug turned out to be two separate issues, not fixed here:

  • A tokenizer bug (PRAGMA mistyped as Function) — see the companion PR above.
  • A client-side bug in ClarionAssistant's SharedLspBridge.cs (MergeDbBarePrefix): its
    solution-wide CodeGraph bare-prefix merge never filters out local-scoped symbols, so a
    procedure-private variable in one file gets merged into completion anywhere in the solution. Not
    a Clarion-Extension bug — tracked separately in the ClarionAssistant repo.

…d completions

WordCompletionProvider's keyword completion only pulled from two hardcoded
local lists (BLOCK_STRUCTURES / PLAIN_KEYWORDS). Compiler directives like
INCLUDE were never in either list, so they could never appear in completion
-- typing "INCL" at the top of a file only surfaced unrelated variables that
happened to share the prefix, with no INCLUDE entry to compete against.

DirectiveService (clarion-directives.json) already exists and is wired into
hover (HoverRouter) but was never consulted by word completion. Add a
collectDirectives() step, following the same seen-map/JSON-service pattern
already used for collectAttributes/collectBuiltins/collectDataTypes, so
directive entries get their syntax/description as detail/documentation just
like every other completion source in this file.
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.

1 participant