The Graphitron LSP surfaces two layers the schema author normally cannot see: inference (the canonical-argument value Graphitron fills in for @table / @field / @reference when the author omits it) and classification (the sealed-variant identity the classifier assigns to every field and type, fully determining the generated code). Both layers are off by default and light up through editor-side config.
Three config keys
All three live under the graphitron.inlayHints (and graphitron.hover) namespace and default to false. The LSP pulls them via workspace/configuration on initialisation and refreshes them on workspace/didChangeConfiguration. A client that does not implement workspace/configuration leaves the defaults in effect; no error is surfaced.
| Key | Default | Effect |
|---|---|---|
|
|
Renders a ghost annotation at |
|
|
Renders a compact classification label at every field declaration and every object / interface / input / union / scalar / enum type declaration. Labels include |
|
|
Enables rich hover content on field-declaration and type-declaration name tokens. Where the inlay hint shows a compact label, the hover popup unpacks the variant’s load-bearing payload (table, column, FK path, target type, error channel, DML verb, …) as markdown. |
The three toggles are independent: a user who wants ghost annotations for inferred directives but not classification labels gets exactly that.
Inferred-directive hints
Renders only when the canonical argument is absent from the SDL source. The LSP asks the live tree-sitter parse tree whether the argument node exists in the buffer; when it does not, the LSP looks up the resolved value on the classification projection the build pipeline shipped to it. Three sites today:
-
@tablewithoutname:— showsname: "<table>"(the table name the classifier resolved). -
@fieldwithoutname:— showsname: "<column>"(the column name the classifier resolved). -
@referencewithoutpath:— showspath: [{key: "…"}]orpath: [{table: "…"}]for each step in the resolved FK chain.
Adding the canonical argument to the directive removes the hint immediately on next paint, without waiting for a regenerate cycle.
Classification hints
Renders on every field declaration and every type declaration. Labels are 1:1 with the generator-side sealed permits and are stable across renames of the underlying types; the user-facing label vocabulary is owned by the LSP module, not by the generator-side type names.
Classification hover
Renders the projection’s load-bearing payload as markdown when the cursor is on a field-declaration or type-declaration name token (outside any directive). The hover content includes:
-
The friendly label (matching the inlay hint).
-
The qualified coordinate (
ParentType.fieldNamefor fields; the type name for types). -
Per-permit payload: target table, column name, FK chain, participant set, discriminator column, DML verb, error-channel constant, input type name, accessor / column duality for
@record-parent fields, and so on.
Hover stays distinct from the directive-argument-keyed dispatch (@table(name:), ExternalCodeReference.method, …): the existing directive-arg hovers keep firing when the cursor sits inside a directive, and the classification hover fires only as a fallback on declaration coordinates.
Stale-snapshot behaviour
Mirroring the existing userArgHover and columnHover arms, hints render under both LspSchemaSnapshot.Built.Current and LspSchemaSnapshot.Built.Previous indistinguishably (the "prefer stale info over silence" policy). The next successful generator pass replaces stale with current; the gap is bounded by the dev-pipeline’s regenerate cadence, typically a save away.
Under LspSchemaSnapshot.Unavailable (pre-build), no hints render. The editor simply does not see the inlay-hint kind, and the classification hover is empty.
Editor configuration
The keys live under the workspace’s settings root. In a VS Code-style settings.json:
{
"graphitron.inlayHints.inferredDirectives": true,
"graphitron.inlayHints.classification": true,
"graphitron.hover.classification": true
}
The editor’s LSP client forwards these to the Graphitron LSP through the workspace/configuration request on initialisation and the workspace/didChangeConfiguration notification on subsequent flips.