Skip to content

Give the language service a keyword for every construct - #199

Merged
woksin merged 2 commits into
mainfrom
fix/language-service-construct-keywords
Sep 17, 2026
Merged

woksin merged 2 commits into
mainfrom
fix/language-service-construct-keywords

Conversation

@woksin

@woksin woksin commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Fixed

  • The language service now highlights and completes every construct the compiler accepts. capture, projection, reducer, contribute, dialog, form, theme and ui had no keyword entry, so they appeared unrecognized in the editor despite compiling (Language service misses six host constructs the compiler accepts #198)
  • The projection grammar reference no longer describes syntax more strictly than the compiler accepts: every takes a bare automap, composite-key braces are optional, and $causedBy is a valid expression root

The language service and the compiler are two descriptions of one
grammar, and nothing kept them honest. Eight constructs the parsers
dispatch on had no keyword entry at all - capture, projection, reducer,
contribute, dialog, form, theme and ui - so they got neither syntax
highlighting nor completion.

Absent highlighting reads as "this construct is wrong", which is the
worst signal to give someone about something that compiles, and it
landed hardest on the UI-composition constructs a newcomer is least
sure of.

Add all eight to constructKeywords, and `profile` to clauseKeywords so
`ui profile` reads the way `screen template` already does. A construct
keyword also ends an indented sub-language block, which is the correct
behavior for each of these.

Add a specification that derives the dispatched set from
ScreenplayParser and SliceParser and fails when this list has drifted
from it, naming the missing constructs and the file to fix. It asserts
both sets are non-empty first, so a moved file or a changed `case` shape
cannot turn it into a comparison of nothing against nothing.

The specification lives in the C# suite rather than beside the language
service because `dotnet-build.yml` is the only workflow that runs tests
on a pull request; a vitest guard here would never have run.

Fixes #198
The EBNF said things the compiler does not enforce, so a reader working
from it would avoid syntax that is perfectly valid:

- `EveryBlock` allowed only `no automap`, though `from-every.md` shows a
  bare `automap` in an example and `ParseMappingBlock` accepts both.
- `CompositeKeyDecl` wrote the braces as required. A composite key with
  and without them both compile clean.
- `DollarExpr` omitted `$causedBy`, which `ExpressionParser` resolves
  and `keys.md` uses in a worked example.

Verified by compiling each form rather than by reading the parser.
@woksin woksin added the patch Bug fixes, docs, refactoring label Sep 17, 2026
@woksin
woksin merged commit df2de40 into main Sep 17, 2026
3 of 4 checks passed
@woksin
woksin deleted the fix/language-service-construct-keywords branch September 17, 2026 13:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

patch Bug fixes, docs, refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant