Skip to content

A method or constructor whose BodyFactory writes only comments or #pragma lines gets no body, so the output fails with CS1002 #157

Closed

Description

@matt-edmondson

What happens

WriteBody (TemplateRendering.cs#L286-L306) picks the shape of a member body by counting non-blank lines. A line counts even when it holds no code, such as a // comment or a #pragma directive:

  • One such line is treated as an expression body and written on the declaration line after a space.
  • Two or more are spliced below the declaration with no braces around them.

In both cases the member has no body. #119 and #133 fixed this for bodies made of blank lines only. Bodies made of comments or directives only were not covered.

Repro

using var cb = CodeBlocker.Create();
cb.AddClass(new ClassTemplate { Name = "C", Members = {
    new MethodTemplate { Name = "M", Type = "void", BodyFactory = b => b.WriteLine("// nothing to reset") } } });

Output:

class C
{
	void M() // nothing to reset
}

Parsing that with Roslyn gives (3,10): error CS1002: ; expected. These inputs fail the same way:

BodyFactory writes Output
// a, // b void M() followed by the two bare comment lines
// no state (on a ConstructorTemplate) C() // no state
an empty PragmaScope (only the disable and restore lines) void M() followed by the two bare #pragma lines

Why it matters

Generators often write a placeholder comment in place of a loop over a collection that turned out to be empty, such as // no fields to reset. Today that produces a file that does not compile. Nothing reports the problem when the code is generated; it only shows up later as a build error in the consumer's project.

Suggested fix

When choosing the body's shape, count only lines that contain code:

  • Ignore lines whose code part is empty. FindCodeEnds already works out where a line comment starts, and WriteExpressionBody uses it for the same purpose.
  • Ignore lines whose trimmed text starts with #.

If no line has code, write a braced block around whatever was written ({, the comment or directive lines, }) rather than " " + line.

Acceptance criteria

  • The four inputs above render output that Roslyn parses with no errors, and the comments and directives are kept inside the body.
  • A one-line body that contains code, such as => x; or { }, still stays on the declaration line.
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