Skip to content

feat: add @context attribute for context-based output splitting#77

Open
keithharvey wants to merge 7 commits into
rhys-vdw:mainfrom
keithharvey:contexts
Open

feat: add @context attribute for context-based output splitting#77
keithharvey wants to merge 7 commits into
rhys-vdw:mainfrom
keithharvey:contexts

Conversation

@keithharvey
Copy link
Copy Markdown
Collaborator

@keithharvey keithharvey commented Mar 15, 2026

Part of BAR type-error cleanup. Tooling

Summary

Allow doc comments to declare @context tags (e.g. synced, unsynced) that partition the generated Lua library into mutually exclusive output files per context. Functions tagged with multiple contexts are placed into a shared base type, and EmmyLua class inheritance is generated so that context-specific types extend the shared one. Table names are only remapped when their members span more than one context bucket.

Motivation

The Recoil engine exposes a single Spring table in Lua, but different contexts (synced vs unsynced) have access to different subsets of functions. These options allow generating SpringSynced and SpringUnsynced type libraries from the same C++ sources without duplicating shared helper types that already exist in the per-file output.

Enabled Recoil PR

beyond-all-reason/RecoilEngine#2799

Note on Backward Comparability

If you don't add contexts, no projection happens and file structure is maintained.

LLM Disclosure

Prompt was pretty detailed but Opus 4.6 typed most of this one. I read the specs too. I think it checks out.

keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 15, 2026
Use lua-doc-extractors @context feature to group output files into synced, unsynced and shared, see rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 17, 2026
Use lua-doc-extractors @context feature to group output files into synced, unsynced and shared, see rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 17, 2026
Use lua-doc-extractors @context feature to group output files into synced, unsynced and shared, see rhys-vdw/lua-doc-extractor#77
@keithharvey
Copy link
Copy Markdown
Collaborator Author

keithharvey commented Mar 17, 2026

Ok so a couple changes to the generation today. I was just throwing everything not-context'ed into shared, which led to shared being out of control huge. So I changed it to preserve the file mapping for anything without a specified context. That keeps shared smol. This is more of a hybrid approach but keeps us non-breaking.
Screenshot 2026-03-17 at 1 07 32 AM

Verified the Recoil CI working https://github.com/keithharvey/RecoilEngine/actions/runs/23181438332/job/67357579048

keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 17, 2026
Use lua-doc-extractors @context feature to group output files into synced, unsynced and shared, see rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 19, 2026
Use lua-doc-extractors @context feature to group output files into synced, unsynced and shared, see rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 20, 2026
Use lua-doc-extractors @context feature to group output files into synced, unsynced and shared, see rhys-vdw/lua-doc-extractor#77
@keithharvey
Copy link
Copy Markdown
Collaborator Author

keithharvey commented Mar 22, 2026

@rhys-vdw So I took another look at this after our discord conversation, then refactored the output layer. No more explicit "shared" handling in the CLI. It's internal to the bucket naming now. The CLI just gets a flat FileOutput[] from projectContextOutputs, and --file is a merge step on that same list, not a separate code path. Single write loop, no branching.

I also pulled isStandaloneContextDoc into a generic isFileAttributeDoc backed by a FILE_ATTRIBUTE_TYPES constant, so @context is just the first entry. Future file-level meta attrs just add to the constant and get the validation for free (must be first doc, only one per file). Plus combinatorial tests for 3 contexts covering all subset combinations.

keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 23, 2026
Use lua-doc-extractor's @context attribute to partition Lua API
documentation into synced, unsynced, and shared output files.
Tables appearing in multiple contexts (e.g. Spring) are remapped
to context-specific classes (SpringSynced, SpringUnsynced) that
inherit from a shared base (SpringShared).

Also adds CI support for overriding lua-doc-extractor repo/branch
via workflow_dispatch inputs and repository variables.

Depends on: rhys-vdw/lua-doc-extractor#77

Made-with: Cursor
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 23, 2026
Use lua-doc-extractor's @context attribute to partition Lua API
documentation into synced, unsynced, and shared output files.
Tables appearing in multiple contexts (e.g. Spring) are remapped
to context-specific classes (SpringSynced, SpringUnsynced) that
inherit from a shared base (SpringShared).

Also adds CI support for overriding lua-doc-extractor repo/branch
via workflow_dispatch inputs and repository variables.

Depends on: rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 23, 2026
Use lua-doc-extractor's @context attribute to partition Lua API
documentation into synced, unsynced, and shared output files.
Tables appearing in multiple contexts (e.g. Spring) are remapped
to context-specific classes (SpringSynced, SpringUnsynced) that
inherit from a shared base (SpringShared).

Also adds CI support for overriding lua-doc-extractor repo/branch
via workflow_dispatch inputs and repository variables.

Depends on: rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Mar 23, 2026
Use lua-doc-extractor's @context attribute to partition Lua API
documentation into synced, unsynced, and shared output files.
Tables appearing in multiple contexts (e.g. Spring) are remapped
to context-specific classes (SpringSynced, SpringUnsynced) that
inherit from a shared base (SpringShared).

Also adds CI support for overriding lua-doc-extractor repo/branch
via workflow_dispatch inputs and repository variables.

Depends on: rhys-vdw/lua-doc-extractor#77
Allow doc comments to declare @context tags (e.g. synced, unsynced)
that partition the generated Lua library into mutually exclusive
output files per context. Functions tagged with multiple contexts
are placed into a shared base type, and EmmyLua class inheritance
is generated so that context-specific types extend the shared one.
Table names are only remapped when their members span more than one
context bucket.
shared was out of control big
So I took another look at this and refactored the output layer. No more explicit shared handling in the CLI — it's internal to the bucket naming now. The CLI just gets a flat  from , and  is a merge step on that same list, not a separate code path. Single write loop, no branching.

I also pulled  into a generic  backed by a  constant — so  is just the first entry. Future file-level meta attrs just add to the constant and get the validation for free (must be first doc, only one per file). Plus combinatorial tests for 3 contexts covering all subset combinations.
Realized that my AST was producing Shared for all shared functions, and that was accuate. We dont want devs to have to memorize whats in SpringShared and whats in SpringSynced, we want callers to be unambiguous and 1:1
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Apr 3, 2026
Use lua-doc-extractor's @context attribute to partition Lua API
documentation into synced, unsynced, and shared output files.
Tables appearing in multiple contexts (e.g. Spring) are remapped
to context-specific classes (SpringSynced, SpringUnsynced) that
inherit from a shared base (SpringShared).

Also adds CI support for overriding lua-doc-extractor repo/branch
via workflow_dispatch inputs and repository variables.

Depends on: rhys-vdw/lua-doc-extractor#77
keithharvey added a commit to keithharvey/RecoilEngine that referenced this pull request Apr 12, 2026
Use lua-doc-extractor's @context attribute to partition Lua API
documentation into synced, unsynced, and shared output files.
Tables appearing in multiple contexts (e.g. Spring) are remapped
to context-specific classes (SpringSynced, SpringUnsynced) that
inherit from a shared base (SpringShared).

Also adds CI support for overriding lua-doc-extractor repo/branch
via workflow_dispatch inputs and repository variables.

Depends on: rhys-vdw/lua-doc-extractor#77
keithharvey and others added 2 commits April 15, 2026 12:27
…rection

Previously the extractor partitioned output files via a file-level
@context tag and rewrote Spring.X → SpringShared/SpringSynced/
SpringUnsynced.X at emit time. Now that every Recoil binding
authors its table prefix directly (e.g. @function SpringSynced.X),
the remap and partition steps are no longer load-bearing — doc
comments can serve as the single source of truth for bucketing.

Delete: partitionDocsByContext, remapDocTableNames,
promoteMultiContextDocs, findMultiContextTables,
generateClassDeclarations, applyFileContexts.

Add: projectOutputs (group by literal table prefix in @function)
and lintDuplicateDeclarations (error on the same @function name
declared across multiple files, replacing the previous auto-promote-
to-shared magic). removeContextAttributes stays as a defensive no-op
stripper in case a stray @context sneaks in.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The primary simplification (65b71fd) routed output files purely by the
table prefix of each doc's @function/@table/@field declaration. That
works for the three Spring* tables, but non-Spring tables like
UnitScriptTable and ObjectRenderingTable carry no bucket prefix —
their docs all fell through to shared.lua instead of landing in
synced.lua / unsynced.lua as the pinned stubs had them.

Resurrect the minimum needed: applyFileContexts() to propagate a
standalone file-level `@context` doc onto every other doc in the same
file, and a fallback tier in outputFileFor() that routes by that
`@context` when no Spring prefix is present. Spring prefix still wins
on any doc that carries one, so a stray `@context` in a Spring file
can't drag its decls out of their declared bucket.

What stays deleted from the old model: multi-context partitioning,
Spring.X -> SpringBucket.X name-rewriting, auto-dedup of multi-context
duplicates, class-inheritance preamble generation, per-file filename-
based output. None of those are needed once authors write bucket
prefixes explicitly.

Recoil source now keeps @context on exactly two files
(LuaObjectRendering.cpp, LuaUnitScript.cpp) — both contain non-Spring
tables that would otherwise have no bucket signal.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@keithharvey
Copy link
Copy Markdown
Collaborator Author

Stripped a lot of complexity out. Because we switched to the exclusive buckets being the first-class recoil example/decorator pattern, a lot of complexity over here (such as auto-bucketing) became worth removing.

@rhys-vdw
Copy link
Copy Markdown
Owner

I'm just going to leave this PR open until everything settles. Cool?

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.

2 participants