Skip to content

Commit d64d052

Browse files
authored
Merge pull request #295 from distantcam/feature/more-readable-gen
More readable generated code
2 parents 2fe251b + 26fe5d5 commit d64d052

27 files changed

+379
-171
lines changed

.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ csharp_preserve_single_line_statements = true
227227
##########################################
228228

229229
# Always have accessibility keyword
230-
dotnet_style_require_accessibility_modifiers = always:warning
230+
dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
231231

232232
# Use file scoped namespaces
233233
csharp_style_namespace_declarations = file_scoped:warning

src/AutoCtor.Shared/AttributeSourceGenerator/Emitter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ public static SourceText GenerateSource()
3131
using (source.StartBlock())
3232
{
3333
source.AppendLine("public AutoConstructAttribute(GuardSetting guard = GuardSetting.Default)");
34-
source.OpenBlock().CloseBlock();
34+
source.StartBlock().Dispose();
3535
}
3636

3737
source.AddCompilerGeneratedAttribute().AddGeneratedCodeAttribute();
3838
source.AppendLine("[global::System.AttributeUsage(global::System.AttributeTargets.Method, AllowMultiple = false, Inherited = false)]");
3939
source.AppendLine("internal sealed class AutoPostConstructAttribute : global::System.Attribute");
40-
source.OpenBlock().CloseBlock();
40+
source.StartBlock().Dispose();
4141

4242
source.AddCompilerGeneratedAttribute().AddGeneratedCodeAttribute();
4343
source.AppendLine("[global::System.AttributeUsage(global::System.AttributeTargets.Field | global::System.AttributeTargets.Property, AllowMultiple = false, Inherited = false)]");
4444
source.AppendLine("internal sealed class AutoConstructIgnoreAttribute : global::System.Attribute");
45-
source.OpenBlock().CloseBlock();
45+
source.StartBlock().Dispose();
4646
}
4747
source.AppendLine("#endif");
4848

src/AutoCtor.Shared/AutoConstructSourceGenerator/Emitter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ private static (SourceText?, ParameterList?) GenerateSource(
114114
.AddDebuggerNonUserCodeAttribute();
115115

116116
source.AppendIndent()
117-
.Append($"public {type.Name}({parameters})")
118-
.Append(parameters.HasBaseParameters, $" : base({parameters:B})")
117+
.Append($"public {type.Name}({parameters.ParameterDeclarations:commaindent})")
118+
.Append(parameters.HasBaseParameters, $" : base({parameters.BaseParameters:commaindent})")
119119
.AppendLine();
120120

121121
using (source.StartBlock())
@@ -138,7 +138,7 @@ private static (SourceText?, ParameterList?) GenerateSource(
138138
}
139139
if (postCtorMethod.HasValue)
140140
{
141-
source.AppendLine($"{postCtorMethod.Value.Name}({parameters:P});");
141+
source.AppendLine($"{postCtorMethod.Value.Name}({parameters.Parameters:commaindent});");
142142
}
143143
}
144144
}

src/AutoCtor.Shared/AutoCtor.Shared.projitems

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@
1313
<Compile Include="$(MSBuildThisFileDirectory)AutoConstructSourceGenerator\Tracking.cs" />
1414
<Compile Include="$(MSBuildThisFileDirectory)AutoConstructSourceGenerator\Diagnostics.cs" />
1515
<Compile Include="$(MSBuildThisFileDirectory)AutoConstructSourceGenerator\Emitter.cs" />
16+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\CodeBuilder.Block.cs" />
1617
<Compile Include="$(MSBuildThisFileDirectory)Helpers\CodeBuilder.cs" />
18+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\CodeBuilder.InterpolatedStringHandler.cs" />
19+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\CodeBuilder.PartialType.cs" />
20+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\CodeBuilder.Templates.cs" />
1721
<Compile Include="$(MSBuildThisFileDirectory)Helpers\EquatableList.cs" />
1822
<Compile Include="$(MSBuildThisFileDirectory)Helpers\EquatableTypeSymbol.cs" />
1923
<Compile Include="$(MSBuildThisFileDirectory)Helpers\Extensions.cs" />
2024
<Compile Include="$(MSBuildThisFileDirectory)Helpers\GeneratorUtilities.cs" />
21-
<Compile Include="$(MSBuildThisFileDirectory)Helpers\IsExternalInit.cs" />
25+
<Compile Include="$(MSBuildThisFileDirectory)Helpers\Polyfill.cs" />
2226
<Compile Include="$(MSBuildThisFileDirectory)Models\AttributeNames.cs" />
27+
<Compile Include="$(MSBuildThisFileDirectory)Models\IPartialTypeModel.cs" />
2328
<Compile Include="$(MSBuildThisFileDirectory)Models\MemberModel.cs" />
2429
<Compile Include="$(MSBuildThisFileDirectory)Models\ParameterModel.cs" />
2530
<Compile Include="$(MSBuildThisFileDirectory)Models\ParameterList.cs" />
@@ -30,4 +35,4 @@
3035
<AdditionalFiles Include="$(MSBuildThisFileDirectory)AnalyzerReleases.Shipped.md" />
3136
<AdditionalFiles Include="$(MSBuildThisFileDirectory)AnalyzerReleases.Unshipped.md" />
3237
</ItemGroup>
33-
</Project>
38+
</Project>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
internal partial class CodeBuilder
2+
{
3+
public IDisposable StartBlock() => StartIndent("{", "}");
4+
public IDisposable StartBlock(string line)
5+
{
6+
AppendLine(line);
7+
return StartIndent("{", "}");
8+
}
9+
10+
public IDisposable StartIndent(string? startLine = null, string? endLine = null)
11+
{
12+
if (!string.IsNullOrEmpty(startLine))
13+
AppendLine(startLine!);
14+
IncreaseIndent();
15+
return new DetentDisposable(this, endLine);
16+
}
17+
18+
private readonly struct DetentDisposable(CodeBuilder codeBuilder, string? endLine) : IDisposable
19+
{
20+
public void Dispose()
21+
{
22+
codeBuilder.DecreaseIndent();
23+
if (!string.IsNullOrEmpty(endLine))
24+
codeBuilder.AppendLine(endLine!);
25+
}
26+
}
27+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
using System.Runtime.CompilerServices;
2+
3+
#pragma warning disable CS9113 // Parameter is unread.
4+
#pragma warning disable IDE0060 // Remove unused parameter
5+
6+
internal partial class CodeBuilder
7+
{
8+
public CodeBuilder Append(
9+
[InterpolatedStringHandlerArgument("")]
10+
ref CodeBuilderInterpolatedStringHandler builder) => this;
11+
12+
public CodeBuilder Append(bool enabled,
13+
[InterpolatedStringHandlerArgument("", nameof(enabled))]
14+
ref ConditionalCodeBuilderInterpolatedStringHandler builder) => this;
15+
16+
public CodeBuilder AppendLineRaw(
17+
[InterpolatedStringHandlerArgument("")]
18+
ref CodeBuilderInterpolatedStringHandler builder) => AppendLine();
19+
20+
public CodeBuilder AppendLineRaw(bool enabled,
21+
[InterpolatedStringHandlerArgument("", nameof(enabled))]
22+
ref ConditionalCodeBuilderInterpolatedStringHandler builder) => enabled ? AppendLine() : this;
23+
24+
public CodeBuilder AppendLine(
25+
[InterpolatedStringHandlerArgument("")]
26+
IndentedCodeBuilderInterpolatedStringHandler builder) => AppendLine();
27+
28+
public CodeBuilder AppendLine(bool enabled,
29+
[InterpolatedStringHandlerArgument("", nameof(enabled))]
30+
ConditionalIndentedCodeBuilderInterpolatedStringHandler builder) => enabled ? AppendLine() : this;
31+
32+
private void AppendFormatted(IEnumerable<string> items, string? format)
33+
{
34+
if (format == "comma")
35+
AppendCommaSeparated(items);
36+
37+
if (format == "commaindent")
38+
AppendCommaIndented(items);
39+
}
40+
41+
private void AppendCommaSeparated(IEnumerable<string> items)
42+
{
43+
var comma = false;
44+
foreach (var item in items)
45+
{
46+
if (comma)
47+
Append(", ");
48+
comma = true;
49+
Append(item);
50+
}
51+
}
52+
53+
private void AppendCommaIndented(IEnumerable<string> items)
54+
{
55+
var count = items.Count();
56+
57+
if (count < 3)
58+
{
59+
AppendCommaSeparated(items);
60+
return;
61+
}
62+
63+
AppendLine();
64+
IncreaseIndent();
65+
var comma = false;
66+
foreach (var item in items)
67+
{
68+
if (comma)
69+
Append(",").AppendLine();
70+
comma = true;
71+
AppendIndent().Append(item);
72+
}
73+
AppendLine();
74+
DecreaseIndent();
75+
AppendIndent();
76+
}
77+
78+
[InterpolatedStringHandler]
79+
internal readonly struct CodeBuilderInterpolatedStringHandler(
80+
int literalLength, int formattedCount, CodeBuilder codeBuilder)
81+
{
82+
public readonly void AppendLiteral(string s) => codeBuilder.Append(s);
83+
public readonly void AppendFormatted(string s) => codeBuilder.Append(s);
84+
public readonly void AppendFormatted(IEnumerable<string> items, string? format)
85+
=> codeBuilder.AppendFormatted(items, format);
86+
}
87+
88+
[InterpolatedStringHandler]
89+
internal readonly struct ConditionalCodeBuilderInterpolatedStringHandler(
90+
int literalLength, int formattedCount, CodeBuilder codeBuilder, bool enabled)
91+
{
92+
public readonly bool AppendLiteral(string s) { if (enabled) codeBuilder.Append(s); return enabled; }
93+
public readonly bool AppendFormatted(string s) { if (enabled) codeBuilder.Append(s); return enabled; }
94+
public readonly bool AppendFormatted(IEnumerable<string> items, string? format)
95+
{ if (enabled) codeBuilder.AppendFormatted(items, format); return enabled; }
96+
}
97+
98+
[InterpolatedStringHandler]
99+
internal class IndentedCodeBuilderInterpolatedStringHandler(
100+
int literalLength, int formattedCount, CodeBuilder codeBuilder)
101+
{
102+
private bool _hasIndented;
103+
104+
private void EnsureIndent()
105+
{
106+
if (_hasIndented) return;
107+
codeBuilder.AppendIndent();
108+
_hasIndented = true;
109+
}
110+
111+
public void AppendLiteral(string s) { EnsureIndent(); codeBuilder.Append(s); }
112+
public void AppendFormatted(string s) { EnsureIndent(); codeBuilder.Append(s); }
113+
public void AppendFormatted(IEnumerable<string> items, string? format)
114+
{ EnsureIndent(); codeBuilder.AppendFormatted(items, format); }
115+
}
116+
117+
[InterpolatedStringHandler]
118+
internal class ConditionalIndentedCodeBuilderInterpolatedStringHandler(
119+
int literalLength, int formattedCount, CodeBuilder codeBuilder, bool enabled)
120+
: IndentedCodeBuilderInterpolatedStringHandler(literalLength, formattedCount, codeBuilder)
121+
{
122+
public new bool AppendLiteral(string s) { if (enabled) base.AppendLiteral(s); return enabled; }
123+
public new bool AppendFormatted(string s) { if (enabled) base.AppendFormatted(s); return enabled; }
124+
public new bool AppendFormatted(IEnumerable<string> items, string? format)
125+
{ if (enabled) base.AppendFormatted(items, format); return enabled; }
126+
}
127+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
internal partial class CodeBuilder
2+
{
3+
public IDisposable StartPartialType(IPartialTypeModel typeModel)
4+
{
5+
if (!string.IsNullOrEmpty(typeModel.Namespace))
6+
{
7+
AppendLine($"namespace {typeModel.Namespace!}");
8+
AppendLine("{");
9+
IncreaseIndent();
10+
}
11+
12+
for (var i = 0; i < typeModel.TypeDeclarations.Count; i++)
13+
{
14+
AppendLine(typeModel.TypeDeclarations[i]);
15+
AppendLine("{");
16+
IncreaseIndent();
17+
}
18+
19+
return new CloseBlockDisposable(this, typeModel.TypeDeclarations.Count + (typeModel.Namespace != null ? 1 : 0));
20+
}
21+
22+
private readonly struct CloseBlockDisposable(CodeBuilder codeBuilder, int count) : IDisposable
23+
{
24+
public void Dispose()
25+
{
26+
for (var i = 0; i < count; i++)
27+
{
28+
codeBuilder.DecreaseIndent();
29+
codeBuilder.AppendLine("}");
30+
}
31+
}
32+
}
33+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using System.Reflection;
2+
3+
internal partial class CodeBuilder
4+
{
5+
private static readonly string s_assemblyName;
6+
private static readonly string s_version;
7+
private static readonly string? s_packageProjectUrl;
8+
private static readonly string? s_gitSha;
9+
10+
static CodeBuilder()
11+
{
12+
var assembly = Assembly.GetAssembly(typeof(CodeBuilder));
13+
s_assemblyName = assembly?.GetCustomAttribute<AssemblyTitleAttribute>()?.Title ?? "Untitled";
14+
s_version = assembly?.GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version ?? "0.0.0.0";
15+
var metadata = assembly?.GetCustomAttributes<AssemblyMetadataAttribute>()?.ToDictionary(m => m.Key, m => m.Value);
16+
if (metadata != null)
17+
{
18+
metadata.TryGetValue("PackageProjectUrl", out s_packageProjectUrl);
19+
metadata.TryGetValue("GitSha", out s_gitSha);
20+
}
21+
}
22+
23+
public CodeBuilder AddCompilerGeneratedAttribute()
24+
=> AppendLine("[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute]");
25+
26+
public CodeBuilder AddDebuggerNonUserCodeAttribute()
27+
=> AppendLine("[global::System.Diagnostics.DebuggerNonUserCodeAttribute]");
28+
29+
public CodeBuilder AddGeneratedCodeAttribute()
30+
=> AppendLine($"[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{s_assemblyName}\", \"{s_version}\")]");
31+
32+
public CodeBuilder AppendHeader() =>
33+
AppendLine($"//------------------------------------------------------------------------------")
34+
.AppendLine($"// <auto-generated>")
35+
.AppendLine(!string.IsNullOrEmpty(s_packageProjectUrl), $"// This code was generated by {s_packageProjectUrl!}")
36+
.AppendLine($"// Version: {s_version}")
37+
.AppendLine(!string.IsNullOrEmpty(s_gitSha), $"// SHA: {s_gitSha!}")
38+
.AppendLine($"// </auto-generated>")
39+
.AppendLine($"//------------------------------------------------------------------------------");
40+
}

0 commit comments

Comments
 (0)