Skip to content

Commit

Permalink
Merge pull request #257 from stakx/init-only-setters
Browse files Browse the repository at this point in the history
Add support for C# 9 init-only setters
  • Loading branch information
stakx committed Dec 30, 2022
2 parents c2ee28c + 8b2b749 commit b2df393
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
5 changes: 5 additions & 0 deletions src/PublicApiGenerator/ApiGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,11 @@ static void AddPropertyToTypeDeclaration(CodeTypeDeclaration typeDeclaration, IM
// TODO: CodeDOM has no support for different access modifiers for getters and setters
// TODO: CodeDOM has no support for attributes on setters or getters - promote to property?

if (hasSet && member.SetMethod?.ReturnType is RequiredModifierType reqmod && reqmod.ModifierType.FullName == "System.Runtime.CompilerServices.IsExternalInit")
{
property.Name = string.Format(CodeNormalizer.PropertyInitOnlySetterTemplate, property.Name);
}

typeDeclaration.Members.Add(property);
}

Expand Down
9 changes: 9 additions & 0 deletions src/PublicApiGenerator/CodeNormalizer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ internal static class CodeNormalizer
internal const string EventRemovePublicMarker = "removepublic";
internal const string MethodModifierMarkerTemplate = "_{0}_3C0D97CD952D40AA8B6E1ECB98FFC79F_";
internal const string PropertyModifierMarkerTemplate = "_{0}_5DB9F56043FF464997155541DA321AD4_";
internal const string PropertyInitOnlySetterTemplate = "_{0}_156783F107B3427090B5486DC33EE6A9_";

public static string NormalizeMethodName(string methodName)
{
Expand Down Expand Up @@ -61,6 +62,7 @@ public static string NormalizeGeneratedCode(StringWriter writer)

gennedClass = Regex.Replace(gennedClass, @"(public|protected) (.*) _(.*)_292C96C3C42E4C07BEED73F5DAA0A6DF_(.*)", EventModifierMatcher);
gennedClass = Regex.Replace(gennedClass, @"(public|protected)( abstract | static | new static | virtual | override | new | unsafe | )(.*) _(.*)_5DB9F56043FF464997155541DA321AD4_(.*)", PropertyModifierMatcher);
gennedClass = Regex.Replace(gennedClass, @"_(.*)_156783F107B3427090B5486DC33EE6A9_(.*)", PropertyInitOnlySetterMatcher);
gennedClass = Regex.Replace(gennedClass, @"(public|protected)( abstract | static | new static | virtual | override | new | unsafe | )(.*) _(.*)_3C0D97CD952D40AA8B6E1ECB98FFC79F_(.*)", MethodModifierMatcher);
gennedClass = gennedClass.Replace("class " + StaticMarker, "static class ");
gennedClass = gennedClass.Replace("struct " + ReadonlyMarker, "readonly struct ");
Expand Down Expand Up @@ -101,6 +103,13 @@ static string PropertyModifierMatcher(Match match)
return string.IsNullOrWhiteSpace(oldModifier) ? s.Insert(s.IndexOf(oldModifier, StringComparison.Ordinal), modifier.Substring(0, modifier.Length - 1)) : s.Replace(oldModifier, modifier);
}

static string PropertyInitOnlySetterMatcher(Match match)
{
var name = match.Groups[1].Value;
var tail = match.Groups[2].Value;
return name + tail.Replace("set;", "init;");
}

static string MethodModifierMatcher(Match match)
{
var oldModifier = match.Groups[2].Value;
Expand Down
42 changes: 40 additions & 2 deletions src/PublicApiGeneratorTests/Property_methods.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using PublicApiGeneratorTests.Examples;
using PublicApiGeneratorTests.Examples;
using Xunit;

namespace PublicApiGeneratorTests
Expand Down Expand Up @@ -47,6 +47,34 @@ public class PropertyWriteOnly
}");
}

[Fact]
public void Should_output_getter_and_init_only_setter()
{
AssertPublicApi<PropertyReadInit>(
@"namespace PublicApiGeneratorTests.Examples
{
public class PropertyReadInit
{
public PropertyReadInit() { }
public string Value { get; init; }
}
}");
}

[Fact]
public void Should_output_init_only_setter_only()
{
AssertPublicApi<PropertyInitOnly>(
@"namespace PublicApiGeneratorTests.Examples
{
public class PropertyInitOnly
{
public PropertyInitOnly() { }
public string Value { init; }
}
}");
}

[Fact]
public void Should_output_indexer_read_write()
{
Expand Down Expand Up @@ -125,6 +153,16 @@ public class PropertyWriteOnly
public string Value { set { } }
}

public class PropertyReadInit
{
public string Value { get; init; }
}

public class PropertyInitOnly
{
public string Value { init { } }
}

public class PropertyIndexer
{
public string this[int index]
Expand Down Expand Up @@ -163,4 +201,4 @@ public class PropertyIndexerMultipleParameters
// ReSharper restore UnusedMember.Global
// ReSharper restore ClassNeverInstantiated.Global
// ReSharper restore ValueParameterNotUsed
}
}
4 changes: 2 additions & 2 deletions src/PublicApiGeneratorTests/Record.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public void Should_output_simple_record()
public class User : System.IEquatable<PublicApiGeneratorTests.Examples.User>
{
public User(string login, string password) { }
public string login { get; set; }
public string password { get; set; }
public string login { get; init; }
public string password { get; init; }
}
}");
}
Expand Down

0 comments on commit b2df393

Please sign in to comment.