Skip to content

VariableReference.Clone() throws on an empty name, crashing C/C++/Rust/Go generation (and the editor preview) for any class with a property #161

Closed

Description

@matt-edmondson

What's wrong

  • VariableReference.Clone() builds its copy with new(Name) (Coder/Ast/VariableReference.cs:40), and that constructor throws ArgumentException on an empty or whitespace name (L20).
  • Empty names are easy to produce legitimately:
    • The parameterless constructor sets Name = string.Empty.
    • new AssignmentStatement() sets Target = new VariableReference() (Coder/Ast/AssignmentStatement.cs:49).
    • YamlDeserializer.DeserializeVariableReference sets Name = ReadString(...) ?? "" (Coder/Serialization/YamlDeserializer.cs ~L1298-1310).
  • StandardLanguageGenerator.Separated clones the whole class whenever it has a property, and also clones property bodies (Coder/Languages/StandardLanguageGenerator.cs ~L494, ~L558, ~L571).
  • AstSchema.IsUnfilled (Coder.Graph/AstSchema.cs ~L631) only flags empty string literals, so Validate() reports nothing.

Reproduction

Deserialize a class with one propertyDeclaration and a method whose body contains an assignmentStatement that has only a value: and no target. A new assignment node dropped in the editor is in the same state. C#, Python and JavaScript generate fine. C++, C, Rust and Go throw ArgumentException: Name cannot be null or whitespace.

In the editor, CoderEditorApp.Regenerate (Coder.Editor/CoderEditorApp.cs:637-655) runs from the preview pane every frame but catches only NotSupportedException. Its own remarks say an exception thrown in a frame takes the application down. Choosing one of those four preview languages with a half-filled assignment therefore crashes the editor.

Related but separate: #112 hits the same constructor through MemberInitialiser fallbacks. This one comes through Clone().

Suggested fix / acceptance criteria

  • Make Clone() use the parameterless constructor and copy Name, so cloning never validates.
  • Optionally, have Validate() flag an empty VariableReference, and/or have Regenerate also catch ArgumentException/InvalidOperationException and show the message in the preview.
  • Add a reflective test asserting that Clone() succeeds for every AST node type built with its parameterless constructor.

Activity

  1. matt-edmondson commented on Oct 5, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    • Category: Bug
    • Priority: High. Placing a new, unfilled assignment node in the editor and previewing it in C, C++, Rust or Go crashes the whole Coder.Editor application. Headless generation also throws for any class that has a property. The fix is small and local.
    • Area / suggested owner: The AST core (VariableReference.Clone), plus CoderEditorApp.Regenerate exception handling in the editor.
    • Duplicates / related: Related to Every generator throws ArgumentException on a braced-list MemberInitialiser with no value (new MemberInitialiser("x")) #112 (the same constructor validation reached through MemberInitialiser), but this one is a separate entry point.
    • In progress: No open PR covers this.
    • Next step: Make Clone() bypass validation by using the parameterless constructor and copying Name. Also have Regenerate catch ArgumentException/InvalidOperationException, so a half-built AST can't take the editor down. Add the reflective test that clones every node type.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions