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:
claude@clouddev1
2026-05-29 22:07:18 +00:00
parent 46a31284c5
commit d20f765325
10 changed files with 195 additions and 13 deletions
+2 -2
View File
@@ -18,7 +18,7 @@ use crate::dsl::command::{
};
use crate::dsl::value::Value;
use crate::dsl::grammar::{
CommandNode, HintMode, IdentSource, Node, ValidationError, Word,
CommandNode, HighlightClass, HintMode, IdentSource, Node, ValidationError, Word,
shared::{REFERENTIAL_CLAUSES, TYPE_SLOT, TYPE_VALIDATOR},
};
@@ -1079,7 +1079,7 @@ const COL_SPEC_NODES: &[Node] = &[
source: IdentSource::Types,
role: "col_type",
validator: Some(TYPE_VALIDATOR),
highlight_override: None,
highlight_override: Some(HighlightClass::Type),
writes_table: false,
writes_column: false,
writes_user_listed_column: false,
+21
View File
@@ -47,6 +47,12 @@ use crate::dsl::walker::outcome::MatchedPath;
pub enum HighlightClass {
Keyword,
Identifier,
/// Column data-type keyword (`int`, `serial`, `text`, …).
/// Distinct from `Keyword` and `Identifier` so learners can
/// tell "this is a type" from a clause keyword or a name they
/// invented (ADR-0022 Amendment 4). Assigned via a type slot's
/// `highlight_override`, not by byte shape.
Type,
Number,
String,
Punct,
@@ -191,6 +197,21 @@ impl Word {
}
}
/// A keyword that highlights as a column **type** rather than a
/// clause keyword (ADR-0022 Amendment 4). The one user today is
/// the two-word `double precision` SQL alias (ADR-0035 §3): it
/// is matched as keyword tokens, not an `IdentSource::Types`
/// `Ident`, so without this it would render keyword-coloured
/// while its single-word synonyms (`float`, `real`) render as
/// types.
pub const fn type_keyword(primary: &'static str) -> Self {
Self {
primary,
aliases: &[],
highlight_override: Some(HighlightClass::Type),
}
}
/// Case-insensitive match against the primary or any alias.
pub fn matches(&self, candidate: &str) -> bool {
if candidate.eq_ignore_ascii_case(self.primary) {
+3 -3
View File
@@ -7,8 +7,8 @@
use crate::completion::TableColumn;
use crate::dsl::grammar::{
HintMode, IdentSource, IdentValidator, Node, NumberValidator,
ValidationError, Word,
HighlightClass, HintMode, IdentSource, IdentValidator, Node,
NumberValidator, ValidationError, Word,
};
use crate::dsl::types::Type;
use crate::dsl::walker::context::WalkContext;
@@ -50,7 +50,7 @@ pub const TYPE_SLOT: Node = Node::Ident {
source: IdentSource::Types,
role: "type",
validator: Some(TYPE_VALIDATOR),
highlight_override: None,
highlight_override: Some(HighlightClass::Type),
writes_table: false,
writes_column: false,
writes_user_listed_column: false,
+6 -4
View File
@@ -24,7 +24,9 @@
//! `sql_insert::SQL_INSERT_SHAPE`, which starts at `INTO`).
use crate::dsl::grammar::sql_select::reject_internal_table;
use crate::dsl::grammar::{IdentSource, Node, ValidationError, Word, shared, sql_expr};
use crate::dsl::grammar::{
HighlightClass, IdentSource, Node, ValidationError, Word, shared, sql_expr,
};
use crate::dsl::types::Type;
static COMMA: Node = Node::Punct(',');
@@ -60,7 +62,7 @@ const SQL_TYPE_NAME: Node = Node::Ident {
source: IdentSource::Types,
role: "col_type",
validator: Some(validate_sql_type_name),
highlight_override: None,
highlight_override: Some(HighlightClass::Type),
writes_table: false,
writes_column: false,
writes_user_listed_column: false,
@@ -86,8 +88,8 @@ const LENGTH_OPT: Node = Node::Optional(&Node::Seq(LENGTH_NODES));
// on its own (ADR-0035 §6.3). The builder maps the pair to
// `Type::Real`.
static DOUBLE_PRECISION_NODES: &[Node] = &[
Node::Word(Word::keyword("double")),
Node::Word(Word::keyword("precision")),
Node::Word(Word::type_keyword("double")),
Node::Word(Word::type_keyword("precision")),
];
static TYPE_WITH_LENGTH_NODES: &[Node] = &[SQL_TYPE_NAME, LENGTH_OPT];
static SQL_TYPE_CHOICES: &[Node] = &[