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
4 changes: 4 additions & 0 deletions docs/wiki/Code-Writer.md
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,10 @@ one. Set the defaults on `GenerationSettings` (to apply across a generation) or
(to override per writer). Each value is `null`-able, so setting a kind back to `null` omits the
modifier entirely.

Partial methods are the one exception to method defaulting: `PartialMethod(...)` and any method
declaration with `IsPartial = true` omit the accessibility modifier when none is provided, even if
`DefaultMethodAccessibility` is still `Public`.

| Setting | Default |
|---|---|
| `DefaultTypeAccessibility` | `Public` |
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "purview-sourcegenerator-framework",
"version": "1.0.0-prerelease.44",
"version": "1.0.0-prerelease.45",
"license": "MIT",
"author": {
"name": "Kieron Lanning",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ Action<CodeWriter> writeBody
/// </summary>
/// <param name="name">The method name.</param>
/// <param name="returnType">The return type, or <see langword="null"/> for <c>void</c>.</param>
/// <param name="accessibility">The optional accessibility.</param>
/// <param name="accessibility">
/// The optional accessibility. When omitted, the partial method is emitted without an accessibility
/// modifier.
/// </param>
/// <param name="configure">An optional callback that configures the declaration.</param>
/// <returns>The current writer.</returns>
/// <example><code>writer.PartialMethod("OnChanged");</code></example>
Expand Down
16 changes: 13 additions & 3 deletions src/src/SourceGeneratorShared/CodeWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -236,8 +236,10 @@ public CodeWriter(

/// <summary>
/// Gets or sets the default accessibility emitted for method declarations when a declaration does not
/// specify one. The default is <see cref="TypeDeclarationAccessibility.Public"/>. Set to
/// <see langword="null"/> to omit the modifier.
/// specify one. The default is <see cref="TypeDeclarationAccessibility.Public"/>. Partial methods are
/// the exception: when their declaration does not specify an accessibility, the modifier is omitted
/// instead of using this default. Set to <see langword="null"/> to omit the modifier for other method
/// declarations.
/// </summary>
public TypeDeclarationAccessibility? DefaultMethodAccessibility { get; set; } = TypeDeclarationAccessibility.Public;

Expand Down Expand Up @@ -727,6 +729,11 @@ BlockScope MethodScope(MethodDeclarationOptions declaration, Action<CodeWriter>?

void MethodHeader(MethodDeclarationOptions declaration)
{
var accessibility =
declaration.IsPartial && declaration.Accessibility is null
? null
: ResolveAccessibility(declaration.Accessibility, DefaultMethodAccessibility);

ValidateMethodDeclaration(declaration);
BeginWrittenItem(WrittenItemKind.Method);

Expand All @@ -737,7 +744,7 @@ void MethodHeader(MethodDeclarationOptions declaration)
Attributes(declaration.ReturnAttributes, defaultTarget: "return");

MemberModifiers(
ResolveAccessibility(declaration.Accessibility, DefaultMethodAccessibility),
accessibility,
declaration.IsStatic,
declaration.IsAbstract,
declaration.IsVirtual,
Expand All @@ -759,6 +766,9 @@ void MethodHeader(MethodDeclarationOptions declaration)

/// <summary>
/// Writes a structured partial method declaration.
/// When <see cref="MethodDeclarationOptions.Accessibility"/> is <see langword="null"/>, the
/// declaration omits any accessibility modifier instead of using
/// <see cref="DefaultMethodAccessibility"/>.
/// </summary>
/// <example><code>writer.PartialMethod(new MethodDeclarationOptions("OnChanged"));</code></example>
public CodeWriter PartialMethod(MethodDeclarationOptions declaration)
Expand Down
6 changes: 4 additions & 2 deletions src/src/SourceGeneratorShared/GenerationSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,10 @@ public GenerationSettings(

/// <summary>
/// Gets the default accessibility emitted for method declarations when a declaration does not specify
/// one. The default is <see cref="TypeDeclarationAccessibility.Public"/>. Set to
/// <see langword="null"/> to omit the modifier, matching the previous behaviour.
/// one. The default is <see cref="TypeDeclarationAccessibility.Public"/>. Partial methods are the
/// exception: when their declaration does not specify an accessibility, the modifier is omitted
/// instead of using this default. Set to <see langword="null"/> to omit the modifier for other
/// method declarations, matching the previous behaviour.
/// </summary>
public TypeDeclarationAccessibility? DefaultMethodAccessibility { get; init; } =
TypeDeclarationAccessibility.Public;
Expand Down
32 changes: 29 additions & 3 deletions src/tests/SourceGeneratorShared.UnitTests/CodeWriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3535,7 +3535,7 @@ await Assert
.That(writer.ToString())
.IsEqualTo(
GeneratedAttributes()
+ "public readonly partial void OnValidate(global::System.Guid id, string? displayName, bool isActive);\n"
+ "readonly partial void OnValidate(global::System.Guid id, string? displayName, bool isActive);\n"
);
}

Expand All @@ -3550,7 +3550,7 @@ public async Task PartialMethod_GivenIsReadOnlyFalse_OmitsReadonlyModifier()
writer.PartialMethod(declaration);

// Assert
await Assert.That(writer.ToString()).IsEqualTo(GeneratedAttributes() + "public partial void Apply();\n");
await Assert.That(writer.ToString()).IsEqualTo(GeneratedAttributes() + "partial void Apply();\n");
}

[Test]
Expand Down Expand Up @@ -4654,7 +4654,33 @@ public async Task PartialMethodOverload_GivenMinimalProperties_WritesPartialMeth
writer.PartialMethod("OnChanged", Type("void"));

// Assert
await Assert.That(writer.ToString()).IsEqualTo(GeneratedAttributes() + "public partial void OnChanged();\n");
await Assert.That(writer.ToString()).IsEqualTo(GeneratedAttributes() + "partial void OnChanged();\n");
}

[Test]
public async Task PartialMethod_WithoutAccessibility_OmitsDefaultMethodAccessibility()
{
// Arrange
var writer = CodeWriterFactory.ForTests();

// Act
writer.PartialMethod(new("OnChanged"));

// Assert
await Assert.That(writer.ToString()).IsEqualTo(GeneratedAttributes() + "partial void OnChanged();\n");
}

[Test]
public async Task PartialMethod_ExplicitAccessibility_OverridesOmittedDefault()
{
// Arrange
var writer = CodeWriterFactory.ForTests();

// Act
writer.PartialMethod(new("OnChanged", TypeDeclarationAccessibility.Internal));

// Assert
await Assert.That(writer.ToString()).IsEqualTo(GeneratedAttributes() + "internal partial void OnChanged();\n");
}

[Test]
Expand Down
Loading