Skip to content

A class with an empty expression-bodied property is still written with its closing brace, minus that member and everything after it (#164 again, since #178) #183

Open

Description

@matt-edmondson

What happens

var cls = new ClassTemplate
{
    Name = "C",
    Members =
    {
        new FieldTemplate { Type = "int", Name = "f" },
        new PropertyTemplate { Type = "int", Name = "P", ExpressionBodyFactory = b => { } },
    },
};
cls.WriteTo(cb);

WriteTo throws InvalidOperationException ("…has an expression body whose callback wrote no expression…"). By then the buffer already holds:

class C
{
	int f;

}

That is a well-formed class that silently lacks P and every member and nested class after it. It is the situation #164 was about, which #169 fixed by validating every member before writing the class header.

Reproduced against main @ aa7ca53 on net10.0. The same thing happens one level up through SourceFileTemplate / AddClasses, and for accessor expressions (Getter = AccessorTemplate.Expression(b => { })).

Why

#178 added the empty-expression check in TemplateRendering.RenderExpression (CodeBlocker/Templates/TemplateRendering.cs:338-349). That runs from PropertyTemplate.WriteTo and from the accessor write path, not from Validate(). So ClassTemplate.Validate() (ClassTemplate.cs:105-118) passes. The member then throws inside WriteBodyTo's using Scope, and disposing that scope writes the closing }.

Why it matters

A generator that catches the exception and reports it gets a compilable file with members missing. One that writes the buffer anyway (for example, a source generator that adds whatever was produced) ships a type with a silently truncated API. #169 exists to prevent exactly this.

Suggested fix

Make the check part of validation. Either:

  • have PropertyTemplate.Validate() and AccessorTemplate.Validate() render the expression and throw when it is empty, or
  • render all member fragments before the class header is written.

Acceptance criteria

Related: #176 is the same "half-written then closed" shape when a user BodyFactory throws. This issue is about a check the library itself makes, which belongs in Validate().

Activity

  1. matt-edmondson commented on Nov 5, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    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