Skip to content

rdl: replace class body interface list with colon-list syntax#4006

Open
Copilot wants to merge 6 commits intomasterfrom
copilot/refactor-class-interface-syntax
Open

rdl: replace class body interface list with colon-list syntax#4006
Copilot wants to merge 6 commits intomasterfrom
copilot/refactor-class-interface-syntax

Conversation

Copy link
Contributor

Copilot AI commented Mar 15, 2026

The windows-rdl class syntax listed implemented interfaces inside the class body with an explicit #[default] attribute marker. This changes the syntax to a cleaner colon-separated inheritance list where position implies default, freeing the body for future use.

Old syntax:

class Derived: Base {
    #[default]
    IDerived,
    IDerived2,
}

New syntax:

class Derived: Base, IDerived, IDerived2 {}

The first interface in the colon list is implicitly the default — no attribute needed. The base class (if any) must appear before interfaces and is distinguished at encode time by checking whether the resolved type is a class or interface.

Reader (src/reader/class.rs)

  • Removed ClassInterface struct; Class now holds colon_list: Vec<syn::Path>
  • Parser accepts class Name: Path1, Path2 {} — body is parsed but must be empty
  • Encoder resolves each path via encode_path(), uses new is_class_type() helper (checks local Index for Item::Class, reference for TypeCategory::Class) to route each entry to either extends or InterfaceImpl; first interface automatically receives DefaultAttribute
  • Validates: at most one base class, base must precede interfaces, body must be empty

Writer (src/writer/class.rs)

  • Sorts interface_impls() so the default interface leads, then emits a single colon list with an empty {} body

Formatter (src/formatter/mod.rs)

  • Added in_colon_list flag that is set when a : token is encountered inside a mod/namespace body and outside parentheses/angle-brackets, cleared on { or ;
  • While in_colon_list is active, commas emit a space instead of a newline, keeping the entire inheritance list on one line (e.g. class Derived: Base, IDerived, IDerived2 {})
  • Added body_stack: Vec<bool> and last_keyword_is_mod flag to correctly classify open braces: only mod introduces a namespace body (false) where : is an inheritance separator; all other bodies — struct, union, attribute, fn, class, interface, and anonymous inline types — are classified as field bodies (true) where : is a field-name-to-type separator and must not trigger in_colon_list

Samples (crates/samples/components/json_validator_winrt/src/sample.rdl)

  • Updated sample.rdl to use the new colon-list class syntax (class JsonValidator: IJsonValidator {})

Tests & docs

  • tests/class.rdl updated to new syntax
  • rdl.md updated with new grammar description and example

🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Copilot AI and others added 2 commits March 15, 2026 03:38
Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Comment on lines +9 to +11
class Derived: Base,
IDerived,
IDerived2 {}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot the line breaks here are weird. I think it should be Base, IDerived, IDerived2 all on one line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a25cdff. The root cause was the formatter's Token::Comma handler always emitting a newline when outside parentheses/angles. I added an in_colon_list flag to the formatter that gets set when a : is encountered outside parens/angles and cleared on { or ;, so commas in the class header now emit a space instead of a newline. class Derived: Base, IDerived, IDerived2 {} is now all on one line.

Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Copilot AI requested a review from kennykerr March 15, 2026 04:11
base: super::super::Base,
a: super::AS,
}
base: super::super::Base, a: super::AS, }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot this looks like a formatting regression.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in cbcb3f9. The previous in_colon_list fix was too broad — it also triggered on struct field colons (base: Type), causing fields to be formatted on a single line. I added a body_stack: Vec<bool> to the formatter that records whether each { opens a struct/enum body (true) or a mod/namespace body (false). in_colon_list is now only set when the : is outside parentheses/angles and the current body is not a struct/enum body. Struct fields are back on separate lines while class header inheritance lists remain on one line.

…ggering colon-list mode

Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Copilot AI requested a review from kennykerr March 15, 2026 04:22
},
a2: u32,
}
b1: u16, b2: i32, },
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot more formatting regressions - may want to consider simplifying the formatter...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 4ce659e. The root cause was the same as the previous regression but more pervasive: union, attribute, class, and interface are all Identifier tokens in the lexer (not keywords), so any body opened after them was incorrectly classified as a namespace/mod body, causing field colons to trigger in_colon_list.

Simplified the approach: instead of trying to track all "struct-like" keywords, I now only track last_keyword_is_mod. Only mod introduces a namespace body where : is an inheritance separator — all other bodies suppress in_colon_list. The body_stack stores false for mod bodies and true for everything else, and in_colon_list is only set when body_stack.last() == Some(&false).

This is both simpler and correct for all body types including union, attribute, anonymous inline struct/union fields, and nested unions.

…fication

Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Copilot AI requested a review from kennykerr March 15, 2026 04:29
@kennykerr kennykerr marked this pull request as ready for review March 15, 2026 04:32
@kennykerr
Copy link
Collaborator

@copilot fix the build

…yntax

Co-authored-by: kennykerr <9845234+kennykerr@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Mar 15, 2026

@copilot fix the build

Fixed in 78675de. The crates/samples/components/json_validator_winrt/src/sample.rdl sample was still using the old class body syntax. Updated to the new colon-list syntax: class JsonValidator: IJsonValidator {}

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