Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "purview-sourcegeneratorframework",
"version": "1.0.0-prerelease.31",
"version": "1.0.0-prerelease.32",
"private": true
}
12 changes: 9 additions & 3 deletions src/src/SourceGeneratorShared/CodeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ public CodeWriter WritePartialMethod(MethodDeclarationOptions declaration)
}

/// <summary>
/// Writes a structured partial method declaration.
/// Writes an expression-bodied method.
/// </summary>
/// <example><code>writer.WriteMethodExpression(new MethodDeclarationOptions("Count", "int") { ExpressionBody = "items.Count" });</code></example>
public CodeWriter WriteMethodExpression(MethodDeclarationOptions declaration)
Expand All @@ -645,8 +645,12 @@ public CodeWriter WriteMethodExpression(MethodDeclarationOptions declaration)
);
}

// The method is not abstract, so we can use the WriteMethod overload that takes a body callback.
return WriteMethod(declaration, _ => { });
using (WriteMethodScope(declaration))
{
//
}

return this;
}

/// <summary>
Expand Down Expand Up @@ -3606,6 +3610,8 @@ static void ValidateMethodDeclaration(MethodDeclarationOptions declaration)
throw new ArgumentException("A readonly method cannot also be static.", nameof(declaration));
if (declaration.IsAbstract && declaration.ExpressionBody is not null)
throw new ArgumentException("An abstract method cannot have an expression body.", nameof(declaration));
if (declaration.IsPartial && declaration.ExpressionBody is not null)
throw new ArgumentException("A partial method cannot have an expression body.", nameof(declaration));
}

static void ValidateOperatorDeclaration(OperatorDeclarationOptions declaration)
Expand Down
140 changes: 140 additions & 0 deletions src/tests/SourceGeneratorShared.UnitTests/CodeWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -980,6 +980,146 @@ await Assert
);
}

[Test]
public async Task WriteMethodExpression_GivenExpressionBody_WritesExpressionBodiedMethod()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int")) { ExpressionBody = "items.Count" };

// Act
writer.WriteMethodExpression(declaration);

// Assert
await Assert.That(writer).Generates(GeneratedAttributes() + "int Count() => items.Count;\n");
}

[Test]
[Arguments(null)]
[Arguments("")]
[Arguments(" ")]
public async Task WriteMethodExpression_GivenWhitespaceExpressionBody_ThrowsWithoutWriting(string? expressionBody)
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int")) { ExpressionBody = expressionBody };

// Act / Assert
await Assert.That(() => writer.WriteMethodExpression(declaration)).Throws<ArgumentException>();
await Assert.That(writer.ToString()).IsEmpty();
}

[Test]
public async Task WriteMethodExpression_GivenCallback_WritesExpressionBodiedMethod()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int"));

// Act
writer.WriteMethodExpression(declaration, expression => expression.Write("items.Count"));

// Assert
await Assert.That(writer).Generates(GeneratedAttributes() + "int Count() => items.Count;\n");
}

[Test]
public async Task WriteMethodExpression_GivenNullCallback_Throws()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int"));

// Act / Assert
await Assert.That(() => writer.WriteMethodExpression(declaration, null!)).Throws<ArgumentNullException>();
}

[Test]
public async Task WriteMethodExpression_GivenExpressionBodyAndCallback_ThrowsWithoutWriting()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int")) { ExpressionBody = "items.Count" };

// Act / Assert
await Assert
.That(() => writer.WriteMethodExpression(declaration, expression => expression.Write("items.Count")))
.Throws<ArgumentException>();
await Assert.That(writer.ToString()).IsEmpty();
}

[Test]
public async Task WriteMethodExpression_GivenPartialDeclaration_ThrowsWithoutWriting()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int"))
{
IsPartial = true,
ExpressionBody = "items.Count",
};

// Act / Assert
await Assert.That(() => writer.WriteMethodExpression(declaration)).Throws<ArgumentException>();
await Assert.That(writer.ToString()).IsEmpty();
}

[Test]
public async Task WriteMethodExpression_GivenPartialDeclarationAndCallback_ThrowsWithoutWriting()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int")) { IsPartial = true };

// Act / Assert
await Assert
.That(() => writer.WriteMethodExpression(declaration, expression => expression.Write("items.Count")))
.Throws<ArgumentException>();
await Assert.That(writer.ToString()).IsEmpty();
}

[Test]
public async Task WritePartialMethod_GivenExpressionBody_ThrowsWithoutWriting()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int")) { ExpressionBody = "items.Count" };

// Act / Assert
await Assert.That(() => writer.WritePartialMethod(declaration)).Throws<ArgumentException>();
await Assert.That(writer.ToString()).IsEmpty();
}

[Test]
public async Task WriteMethod_GivenExpressionBody_ThrowsWithoutWriting()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int")) { ExpressionBody = "items.Count" };

// Act / Assert
await Assert
.That(() => writer.WriteMethod(declaration, body => body.WriteLine("return items.Count;")))
.Throws<ArgumentException>();
await Assert.That(writer.ToString()).IsEmpty();
}

[Test]
public async Task WriteMethod_GivenBodyAndNoExpressionBody_WritesBlockBody()
{
// Arrange
var writer = CodeWriterFactory.ForTests();
var declaration = new MethodDeclarationOptions("Count", Type("int"));

// Act
writer.WriteMethod(declaration, body => body.WriteLine("return items.Count;"));

// Assert
await Assert
.That(writer)
.Generates(GeneratedAttributes() + "int Count()\n" + "{\n" + "\treturn items.Count;\n" + "}\n");
}

[Test]
public async Task WritePartialMethod_GivenPartialMethods_WritesDeclaration()
{
Expand Down