feat: give column data types a dedicated syntax-highlight colour
Both Node::Ident and Word carried a highlight_override field, and both were dead — the walker driver discarded the Ident's and walk_word hardcoded Keyword. So column types (int, serial, …) rendered identically to table/column names. Wire both overrides through, and add a dedicated HighlightClass::Type with its own theme colour (tok_type), distinct from keyword-purple and identifier-teal. The three type Ident slots opt in, so canonical types and the advanced-mode single-word SQL aliases (float, varchar, …) render as types; the two-word `double precision` alias opts in via a new Word::type_keyword constructor. ADR-0022 Amendment 4.
This commit is contained in:
@@ -587,6 +587,61 @@ guard above, and three re-baselined `typing_surface` snapshots
|
||||
(`form_a_in_progress_one_value`, `form_b_too_few_values`,
|
||||
`form_c_wrong_count`).
|
||||
|
||||
## Amendment 4 — Column types get a dedicated highlight class (2026-05-29)
|
||||
|
||||
§3 introduced **seven** token-class colour fields and the matching
|
||||
`HighlightClass` enum. Column data-type keywords (`int`, `serial`,
|
||||
`text`, …) had no class of their own: the walker driver hardcoded
|
||||
`HighlightClass::Identifier` for every matched `Node::Ident`, so a
|
||||
type rendered identical to a table/column name (clause keywords were
|
||||
already distinct, in `tok_keyword`). A user-reported bug (issue #8)
|
||||
noted that in `create table Orders (count int, id serial PRIMARY KEY)`
|
||||
the identifiers and the type keywords were indistinguishably teal.
|
||||
|
||||
Both terminal kinds already carried a `highlight_override:
|
||||
Option<HighlightClass>` field — `Node::Ident` and the `Word` struct
|
||||
alike — but **both were dead**: the driver destructured the Ident's to
|
||||
`_`, and `walk_word` hardcoded `Keyword`, neither ever consulting the
|
||||
field. This amendment wires both through.
|
||||
|
||||
**Change:**
|
||||
|
||||
1. **New class.** `HighlightClass::Type` (the eighth variant) and a
|
||||
matching eighth `Theme` field `tok_type`, populated in both
|
||||
`dark()` and `light()` with a tone deliberately distinct from both
|
||||
`tok_keyword` and `tok_identifier` (a pink / deep-magenta in the
|
||||
red-purple range — the only free slot in the existing palette).
|
||||
`highlight_class_color` maps the new variant.
|
||||
2. **Overrides are now live.** `walk_ident` emits
|
||||
`override.unwrap_or(Identifier)` and `walk_word` emits
|
||||
`override.unwrap_or(Keyword)` for the matched byte range. Every
|
||||
slot that leaves the field `None` is unchanged.
|
||||
3. **Type slots opt in.** The three `IdentSource::Types` slots —
|
||||
`shared::TYPE_SLOT` (`add column` / `change column`), the inline
|
||||
create-table column-type Ident (`ddl.rs`), and `sql_create_table::
|
||||
SQL_TYPE_NAME` (advanced) — set `highlight_override: Some(Type)`.
|
||||
In advanced mode, every single-word SQL type-name *alias*
|
||||
(`float`, `varchar`, `integer`, … — ADR-0035 §3) flows through
|
||||
`SQL_TYPE_NAME` and so is type-coloured for free.
|
||||
4. **`double precision` too.** The lone two-word alias (ADR-0035 §3)
|
||||
is matched as keyword tokens, not an `IdentSource::Types` Ident, so
|
||||
it cannot ride rule 3. Its `double` / `precision` grammar nodes use
|
||||
the new `Word::type_keyword` constructor (`highlight_override:
|
||||
Some(Type)`) so the spelling renders type-coloured like its
|
||||
single-word synonyms `float` / `real`.
|
||||
|
||||
**Pedagogy:** a dedicated colour (over the lighter option of reusing
|
||||
`tok_keyword`) lets a learner tell *"this is a type"* from a clause
|
||||
keyword and from a name they invented — three distinct roles, three
|
||||
distinct colours.
|
||||
|
||||
**Coverage:** `dsl_type_keyword_classified_as_type`,
|
||||
`advanced_type_keywords_classified_as_type` (the ticket's exact
|
||||
example), `advanced_double_precision_classified_as_type`,
|
||||
`type_colour_is_distinct_from_keyword_and_identifier`, and the
|
||||
extended theme mapping/contrast tests. Text snapshots are colour-blind
|
||||
(`render_to_string` strips style), so none churned.
|
||||
|
||||
## Out of scope
|
||||
|
||||
Deliberately deferred to keep this ADR shippable as a single
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ This directory contains the project's ADRs, recorded per
|
||||
- [ADR-0019 — Friendly error layer (H1) and i18n message catalog](0019-friendly-error-layer-and-i18n.md)
|
||||
- [ADR-0020 — Tokenization layer for the DSL parser](0020-tokenization-layer-for-the-dsl-parser.md)
|
||||
- [ADR-0021 — Parser-as-source-of-truth for H1a (per-command usage in parse errors)](0021-parser-as-source-of-truth-for-h1a.md)
|
||||
- [ADR-0022 — Ambient typing assistance: colour, hint panel, completion (I3 + I4)](0022-ambient-typing-assistance.md) — **Amendment 1 supersedes §12's simple-mode-only carve-out**: the unified mode-aware walker (ADR-0030/0031/0032) now speaks SQL, so advanced-mode ambient assistance is re-enabled. `ambient_hint_in_mode` + `hint_resolution_at_input_in_mode` + `expected_for_hint_snapshot` thread `Mode`; `render_hint_panel` calls ambient for all modes (no more advanced-mode `None`); the one-shot `:` sigil is stripped before the ambient walk. Fixes a live bug where advanced-mode SQL hinting/completion-preview were dead despite Phase 2 marking them green (validated at the engine layer, not the UI). Simple-mode gating, highlighting, and the §13 performance posture are unchanged; covered by an app-level render test plus ambient-layer regression locks; **Amendment 2 reverses the handoff-14 keywords-first candidate ordering** — schema identifiers (table/column/relationship names) now sort *before* keywords so a name the user would have to look up stays visible in the single-row, window-scrolled candidate line (keywords are learned over time; the `tok_identifier`/`tok_keyword` colour split marks the boundary); shipped with a `walk_repeated` fix that surfaces a list item's trailing optionals at a clean boundary (`order by Name ` → `asc`/`desc`, `select Name ` → `as`, `create table … Code(text) ` → `not`/`unique`/`default`/`check`; the `,` separator deliberately not surfaced); records a deferred two-line hint box for growing lists; **Amendment 3 makes the ambient-hint fallback rung schema-aware** — Amendment 1's bottom-rung `parse_command_in_mode` was schemaless while every earlier rung was not, so between-values insert hints pointed at `)` (type-blind close) instead of `,` and wrong-arity closed tuples read "submit with Enter" for an input the schema-aware parse rejects (issue #2); now uses `parse_command_with_schema_in_mode`, no extra walk, with the friendly arity diagnostic still winning at its higher rung
|
||||
- [ADR-0022 — Ambient typing assistance: colour, hint panel, completion (I3 + I4)](0022-ambient-typing-assistance.md) — **Amendment 1 supersedes §12's simple-mode-only carve-out**: the unified mode-aware walker (ADR-0030/0031/0032) now speaks SQL, so advanced-mode ambient assistance is re-enabled. `ambient_hint_in_mode` + `hint_resolution_at_input_in_mode` + `expected_for_hint_snapshot` thread `Mode`; `render_hint_panel` calls ambient for all modes (no more advanced-mode `None`); the one-shot `:` sigil is stripped before the ambient walk. Fixes a live bug where advanced-mode SQL hinting/completion-preview were dead despite Phase 2 marking them green (validated at the engine layer, not the UI). Simple-mode gating, highlighting, and the §13 performance posture are unchanged; covered by an app-level render test plus ambient-layer regression locks; **Amendment 2 reverses the handoff-14 keywords-first candidate ordering** — schema identifiers (table/column/relationship names) now sort *before* keywords so a name the user would have to look up stays visible in the single-row, window-scrolled candidate line (keywords are learned over time; the `tok_identifier`/`tok_keyword` colour split marks the boundary); shipped with a `walk_repeated` fix that surfaces a list item's trailing optionals at a clean boundary (`order by Name ` → `asc`/`desc`, `select Name ` → `as`, `create table … Code(text) ` → `not`/`unique`/`default`/`check`; the `,` separator deliberately not surfaced); records a deferred two-line hint box for growing lists; **Amendment 3 makes the ambient-hint fallback rung schema-aware** — Amendment 1's bottom-rung `parse_command_in_mode` was schemaless while every earlier rung was not, so between-values insert hints pointed at `)` (type-blind close) instead of `,` and wrong-arity closed tuples read "submit with Enter" for an input the schema-aware parse rejects (issue #2); now uses `parse_command_with_schema_in_mode`, no extra walk, with the friendly arity diagnostic still winning at its higher rung; **Amendment 4 gives column types a dedicated highlight class** — both `Node::Ident.highlight_override` *and* the `Word.highlight_override` field were dead (driver destructured the former to `_`, `walk_word` hardcoded `Keyword`); now both wired through, with a new `HighlightClass::Type` + eighth `Theme` field `tok_type` (a pink/deep-magenta distinct from both keyword purple and identifier teal) so types no longer render identically to identifiers (issue #8); the three `IdentSource::Types` slots opt in via `Some(Type)` (advanced-mode single-word SQL aliases — `float`, `varchar`, … per ADR-0035 §3 — ride along for free), and the two-word `double precision` alias opts in via the new `Word::type_keyword` constructor so it matches its synonyms
|
||||
- [ADR-0023 — Unified declarative grammar tree](0023-unified-grammar-tree.md) — direction (superseded for execution detail by ADR-0024)
|
||||
- [ADR-0024 — Unified grammar tree: execution plan](0024-unified-grammar-tree-execution-plan.md) — **Accepted**, the executable spec — implemented (Phases A–F; Phase F shipped "minimal", `parser.rs` retained as the router — see the ADR's Phase F implementation note)
|
||||
- [ADR-0025 — Indexes](0025-indexes.md) — **Accepted** (**Amendment 1, 2026-05-25**: UNIQUE indexes admitted on the **advanced-mode** surface via `CREATE UNIQUE INDEX` — ADR-0035 §4d; the `IndexSchema.unique` flag round-trips through `project.yaml` with no new metadata table since the engine reports uniqueness natively; simple-mode `add unique index` stays deferred), `add index` / `drop index`, persistence, rebuild-table preservation, and items-list display (`C3` index portion + `S2`)
|
||||
|
||||
Reference in New Issue
Block a user