Skip to content

fix: leave out a braced-list member initialiser that has no value [patch] - #173

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/112-empty-member-initialiser
Oct 6, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/112-empty-member-initialiser

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Summary

new MemberInitialiser("x") has a null value. That is legal, and the graph editor holds exactly this between adding a member initialiser and filling it in. Every braced-list writer fell back to new VariableReference(string.Empty) for a null value, and that constructor throws on an empty name. So all seven generators threw ArgumentException: Name cannot be null or whitespace, and the preview broke mid-edit.

Following the triage note, the element is skipped:

  • New LanguageGeneratorBase.WrittenElements(construction) returns the list's elements without any MemberInitialiser { Value: null }.
  • The shared StandardLanguageGenerator.WriteElementList / WriteStackedList (C, C++, Go, Rust), CSharpGenerator.WriteBracedList, PythonGenerator.WriteLiteral / WriteArguments and JavaScriptGenerator.WriteLiteral now write those elements.
  • Every caller now filters first, so the ?? new VariableReference(string.Empty) fallbacks could no longer be reached and are removed.
  • The shape of the list (designated initialiser, object initialiser, keyword arguments, object literal) is still decided by every argument. A list whose only element is unfilled therefore stays the designated form: Point{} in Go, new Point { } in C#, {} in Python.

The same fix also covers the Go, Rust and C constructor bodies that route initialisers through these list writers.

Example, Point { unfilled = <none>, y = 2 }:

Target Output
C Point p = { .y = 2 };
C++ Point p = Point{ .y = 2 };
C# Point p = new Point { y = 2 };
Go var p Point = Point{y: 2}
Rust let mut p: Point = Point { y: 2 };
Python p = Point(y=2)
JavaScript let p = new Point({ y: 2 });

Out of scope, possible follow-up: the Python and JavaScript constructor initialiser paths (WriteInitialiserAssignments) don't throw. On a null value they write self.x = / this.x = ; instead.

Tests

  • New UnfilledMemberInitialiserTests, run against all 7 generators:
    • UnfilledMember_IsLeftOut: the unfilled member is left out and its filled sibling is still written.
    • OnlyElementUnfilled_IsAnEmptyList: a typeless list whose only element is unfilled.
  • On main, all 14 cases fail with ArgumentException: Name cannot be null or whitespace. With this change they pass.
  • Full Coder.Test suite: 1085 passed, 0 failed.

Fixes #112

🤖 Generated with Claude Code

https://claude.ai/code/session_017USYdQkEy3VLP48Dd4JadP


Generated by Claude Code

…tch]

A MemberInitialiser's value may be null, which is how the graph editor
holds one between adding it and filling it in. Every braced-list writer
fell back to `new VariableReference(string.Empty)` for a null value, and
that constructor throws on an empty name, so all seven generators threw
ArgumentException as soon as the preview saw one.

LanguageGeneratorBase.WrittenElements now gives the elements of a list
without its unfilled member initialisers. The C#, Python and JavaScript
list writers and the shared WriteElementList (C, C++, Go, Rust) write
those elements. The list's shape (designated, keyword, object literal) is
still decided by every argument, so a list whose only element is unfilled
comes out as that language's empty designated list.

Fixes #112

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017USYdQkEy3VLP48Dd4JadP
@sonarqubecloud

sonarqubecloud Bot commented Oct 6, 2026

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 331206d into main Oct 6, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/112-empty-member-initialiser branch October 6, 2026 06:55
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.

Every generator throws ArgumentException on a braced-list MemberInitialiser with no value (new MemberInitialiser("x"))

2 participants