feat(parser): support ES6-style shorthand entries in config/schema literals (fixes #1275) - #2163
Merged
Merged
Conversation
…terals (fixes #1275) A bare identifier inside a config or schema-instance literal is now treated as shorthand for `key = key`. For example, `{ name, age }` parses to two ConfigEntry nodes with `is_shorthand = true`, equivalent to `{ name = name, age = age }`. Mixed forms like `Person { name, age = 99 }` are accepted. Dotted keys like `{ a.b }` are still rejected via the existing "expected `:`/`=`/`+=`" diagnostic so key-flattening keeps its current semantics. - AST: new `is_shorthand: bool` field on `ConfigEntry` with `#[serde(default, skip_serializing_if = "is_false")]` so existing AST-JSON fixtures keep deserializing. - Parser: `parse_config_entry` now reuses the parsed identifier as both key and value when no separator follows a single-segment `Identifier` key. - Formatter: `write_entry` short-circuits on `is_shorthand` to round-trip `{name}` exactly; we never rewrite explicit `name = name` into shorthand. - Struct-literal call sites updated to set `is_shorthand: false`. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Claude Opus 4.6 <noreply@anthropic.com>
Peefy
force-pushed
the
worktree-feat/issue-1275-shorthand
branch
from
August 30, 2026 13:44
5959258 to
98c79d0
Compare
The shorthand test main.k declares top-level name/age variables and three schema/config instances (p, m, n). libkcl emits all top-level variables in order, including the source of the shorthand. Single-letter 'n' is quoted in YAML output (consistent with KCL's standard dump). Verified locally against /target/release/libkcl: all 1603 grammar tests pass, including schema/shorthand, schema/shorthand_dotted_fail, and schema/shorthand_format. Signed-off-by: Peefy <xpf6677@163.com>
The shorthand parser change makes the previous test data file — which relied on parser errors to leave each entry incomplete — now parse as seven valid shorthand entries (`a = a`, `b = b`, etc.). The value side of each entry resolves to an undefined variable, so the resolver never registers the attribute on the schema, breaking LSP completion. Switch the test data to `a:` style separators so each entry stays incomplete (`a: <cursor>`) just like a user typing in the IDE. This matches the LSP's actual use case without depending on parser-error recovery. Signed-off-by: Peefy <xpf6677@163.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds ES6-style shorthand for config/schema literals (issue #1275). A bare
identifier inside
{ ... }now stands forkey = key:This is purely additive: every existing entry carries an explicit
separator, so any program that parses today still parses tomorrow. The
new arm fills the parser-error gap that appeared when the separator was
missing.
Implementation
crates/ast/src/ast.rs): newis_shorthand: boolfield onConfigEntrywith#[serde(default, skip_serializing_if = "is_false")]so existing AST-JSON fixtures continue to deserialize.
crates/parser/src/parser/expr.rs):parse_config_entrynow reuses the parsed identifier as both key and value when no
separator follows a single-segment
Identifierkey. Dotted keyslike
{ a.b }still hit the existing "expected one of:/=/+="diagnostic so
ConfigNestAttrTransformerkey-flattening keeps itscurrent semantics.
crates/ast_pretty/src/node.rs):write_entryshort-circuits on
is_shorthandto round-trip{name}exactly. We neverrewrite explicit
name = nameinto shorthand (avoids silentlyflipping semantics inside schema bodies where
namecould resolveto a local).
is_shorthand: falseadded incrates/parser/src/parser/expr.rs(3 sites inparse_body_item),crates/sema/src/pre_process/config.rs,crates/query/src/override.rs(3), andcrates/tools/src/vet/expr_builder.rs(4).No evaluator, walker, sema transformer, or loader changes needed —
existing consumers walk
key+valueand ignore the new flag.Tests
config_shorthand_stmt_0..3) coveringthe all-shorthand, mixed, and explicit-baseline cases.
new field (no behaviour change; just the additive
is_shorthand: false).tests/grammar/schema/:shorthand/— positive caseshorthand_dotted_fail/— dotted-key rejectionshorthand_format/— formatter round-tripcargo test -p kcl-parser→ 514 passed, 0 failedcargo test -p kcl-tools --lib→ 60 passed, 0 failedcargo test -p kcl-query --lib→ 15 passed, 0 failedcargo test -p kcl-sema --lib→ 61 passed, 0 failedOut of scope (follow-ups)
DiskOptions { 32, "ssd" }).{a.b}).name = name→{name}viakcl fmt.🤖 Generated with Claude Code