Skip to content

Commit ec638ca

Browse files
committed
refactor: analyzers, config, and interpolated handler
- Update .editorconfig and .csharpierignore for analyzer and formatting rules, including generated code and migrations. - Add Roslynator and Meziantou analyzers; remove GitVersion.MsBuild. - Move CSharpInterpolatedStringHandler to its own file with NET6_0_OR_GREATER guard. - Suppress unused parameter and missing IFormatProvider warnings in tests. - Update test assertions to use .ConfigureAwait(false). - Update .gitattributes and .gitignore for clarity and new tool files. - Minor formatting and namespace header adjustments.
1 parent 9dc294d commit ec638ca

13 files changed

Lines changed: 241 additions & 145 deletions

.csharpierignore

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
**/nuget.config
2-
**/_snapshots/
3-
**/_snapshot/
1+
**/[Nn]u[Gg]et.config
2+
**/*.verified.*
3+
**/*.received.*

.editorconfig

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,22 @@ generated_code = true
4444
# XML project files
4545
[*.{slnx,csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj,nativeproj,locproj}]
4646
indent_size = 2
47-
max_line_length = 160
47+
max_line_length = 200
4848

4949
# Xml build files
5050
[*.builds]
5151
indent_size = 2
52+
max_line_length = 200
5253

5354
# Xml files
5455
[*.{xml,stylecop,resx,ruleset}]
5556
indent_size = 2
57+
max_line_length = 200
5658

5759
# XML config files
5860
[*.{props,targets,ruleset,config,nuspec,vsixmanifest,vsct}]
5961
indent_size = 2
62+
max_line_length = 200
6063

6164
# JSON files
6265
[*.json]
@@ -128,7 +131,7 @@ dotnet_naming_style.all_const.capitalization = pascal
128131
dotnet_naming_symbols.all_const.applicable_kinds = field
129132
dotnet_naming_symbols.all_const.required_modifiers = const
130133
dotnet_naming_rule.all_const.severity = error
131-
dotnet_naming_rule.all_const.style = all_const
134+
dotnet_naming_rule.all_const.style = all_elements
132135
dotnet_naming_rule.all_const.symbols = all_const
133136

134137
dotnet_naming_style.all_static_readonly.capitalization = pascal_case
@@ -267,10 +270,26 @@ dotnet_diagnostic.IDE0046.severity = sugges
267270
csharp_style_prefer_primary_constructors = false
268271
dotnet_diagnostic.IDE0290.severity = suggestion
269272

273+
# IDE0060: Remove unused parameter
274+
dotnet_diagnostic.IDE0060.severity = warning
275+
dotnet_diagnostic.RCS1163.severity = none
276+
dotnet_code_quality_unused_parameters = all
277+
270278
# [CSharpier] Incompatible rules deactivated
271279
# https://csharpier.com/docs/IntegratingWithLinters#code-analysis-rules
272280
dotnet_diagnostic.IDE0055.severity = none
273281

274282
# Support for NetEvolve.Arguments Methods
275283
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1062#null-check-validation-methods
276284
dotnet_code_quality.CA1062.null_check_validation_methods = M:NetEvolve.Arguments.Argument.ThrowIfNull(System.Object,System.String)|M:NetEvolve.Arguments.Argument.ThrowIfNull(System.Void*,System.String)|M:NetEvolve.Arguments.Argument.ThrowIfNullOrEmpty(System.String,System.String)|M:NetEvolve.Arguments.Argument.ThrowIfNullOrEmpty``1(System.Collections.Generic.IEnumerable{``0},System.String)|M:NetEvolve.Arguments.Argument.ThrowIfNullOrWhiteSpace(System.String,System.String)
285+
286+
# Disable all style rules for generated code
287+
[*.{received,verified}.*]
288+
generated_code = true
289+
# Disable all style rules for migrations
290+
dotnet_analyzer_diagnostic.severity = none
291+
292+
[**/Migrations/*.{cs,csx,vb,vbx}]
293+
generated_code = true
294+
# Disable all style rules for migrations
295+
dotnet_analyzer_diagnostic.severity = none

.gitattributes

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
* text=auto eol=lf
2-
* text eol=lf
32

43
# (binary is a macro for -text -diff)
54
*.png binary

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,3 +364,13 @@ MigrationBackup/
364364
# Prevent nested .editorconfig files - only root .editorconfig should be used
365365
**/.editorconfig
366366
!/.editorconfig
367+
368+
# MemPalace per-project files
369+
.mempalace/
370+
mempalace.yaml
371+
entities.json
372+
373+
# Beads / Dolt files (added by bd init)
374+
.dolt/
375+
*.db
376+
.beads-credential-key

Directory.Packages.props

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,17 @@
55
</PropertyGroup>
66
<ItemGroup>
77
<GlobalPackageReference Include="CSharpier.MSBuild" Version="1.2.6" />
8-
<GlobalPackageReference Include="GitVersion.MsBuild" Version="6.7.0" />
8+
<GlobalPackageReference Include="Meziantou.Analyzer" Version="3.0.77" />
99
<GlobalPackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" />
1010
<GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.203" />
1111
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.203" />
1212
<GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" />
1313
<GlobalPackageReference Include="NetEvolve.Defaults" Version="2.6.19" />
14+
<GlobalPackageReference Include="Roslynator.Analyzers" Version="4.15.0" />
15+
<GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.15.0" />
16+
<GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.15.0" />
17+
<GlobalPackageReference Include="Roslynator.CodeFixes" Version="4.15.0" />
18+
<GlobalPackageReference Include="Roslynator.Refactorings" Version="4.15.0" />
1419
<GlobalPackageReference Include="SonarAnalyzer.CSharp" Version="10.25.0.139117" />
1520
</ItemGroup>
1621
<ItemGroup>

src/NetEvolve.CodeBuilder/CSharpCodeBuilder.AppendInterpolated.cs

Lines changed: 4 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ public partial class CSharpCodeBuilder
1717
/// </code>
1818
/// </example>
1919
public CSharpCodeBuilder AppendInterpolated(
20+
#pragma warning disable IDE0060 // Remove unused parameter
2021
[InterpolatedStringHandlerArgument("")] ref CSharpInterpolatedStringHandler handler
22+
#pragma warning restore IDE0060 // Remove unused parameter
2123
) => this;
2224

2325
/// <summary>
@@ -31,7 +33,9 @@ public CSharpCodeBuilder AppendInterpolated(
3133
/// </code>
3234
/// </example>
3335
public CSharpCodeBuilder AppendLineInterpolated(
36+
#pragma warning disable IDE0060 // Remove unused parameter
3437
[InterpolatedStringHandlerArgument("")] ref CSharpInterpolatedStringHandler handler
38+
#pragma warning restore IDE0060 // Remove unused parameter
3539
) => AppendLine();
3640

3741
internal void HandlerEnsureIndented() => EnsureIndented();
@@ -52,130 +56,4 @@ internal void HandlerRawAppend(ReadOnlySpan<char> value)
5256
}
5357
}
5458
}
55-
56-
/// <summary>
57-
/// Custom interpolated string handler for <see cref="CSharpCodeBuilder"/>.
58-
/// </summary>
59-
/// <remarks>
60-
/// This handler is instantiated by the compiler when an interpolated string is passed to
61-
/// <see cref="CSharpCodeBuilder.AppendInterpolated"/> or <see cref="CSharpCodeBuilder.AppendLineInterpolated"/>.
62-
/// It appends each literal and formatted part directly to the builder, applying indentation before
63-
/// the first non-empty part on a new line.
64-
/// </remarks>
65-
[InterpolatedStringHandler]
66-
public ref struct CSharpInterpolatedStringHandler
67-
{
68-
private readonly CSharpCodeBuilder _owner;
69-
private bool _indentEnsured;
70-
71-
/// <summary>
72-
/// Initializes a new instance of the <see cref="CSharpInterpolatedStringHandler"/> struct.
73-
/// </summary>
74-
/// <param name="literalLength">The total length of all literal parts (hint for capacity).</param>
75-
/// <param name="formattedCount">The number of formatted holes in the interpolated string.</param>
76-
/// <param name="builder">The <see cref="CSharpCodeBuilder"/> to append to.</param>
77-
public CSharpInterpolatedStringHandler(int literalLength, int formattedCount, CSharpCodeBuilder builder)
78-
{
79-
_owner = builder;
80-
_indentEnsured = false;
81-
}
82-
83-
private void EnsureIndented()
84-
{
85-
if (!_indentEnsured)
86-
{
87-
_owner.HandlerEnsureIndented();
88-
_indentEnsured = true;
89-
}
90-
}
91-
92-
/// <summary>Appends a literal string part of the interpolated string.</summary>
93-
/// <param name="value">The literal string to append.</param>
94-
public void AppendLiteral(string? value)
95-
{
96-
if (string.IsNullOrEmpty(value))
97-
{
98-
return;
99-
}
100-
101-
EnsureIndented();
102-
_owner.HandlerRawAppend(value);
103-
}
104-
105-
/// <summary>Appends a formatted value from the interpolated string.</summary>
106-
/// <typeparam name="T">The type of the value to format.</typeparam>
107-
/// <param name="value">The value to append.</param>
108-
public void AppendFormatted<T>(T value)
109-
{
110-
var str = value?.ToString();
111-
if (string.IsNullOrEmpty(str))
112-
{
113-
return;
114-
}
115-
116-
EnsureIndented();
117-
_owner.HandlerRawAppend(str);
118-
}
119-
120-
/// <summary>Appends a formatted value with a format string from the interpolated string.</summary>
121-
/// <typeparam name="T">The type of the value to format. Must implement <see cref="System.IFormattable"/>.</typeparam>
122-
/// <param name="value">The value to append.</param>
123-
/// <param name="format">The format string.</param>
124-
public void AppendFormatted<T>(T value, string? format)
125-
where T : System.IFormattable
126-
{
127-
var str = value?.ToString(format, CultureInfo.InvariantCulture);
128-
if (string.IsNullOrEmpty(str))
129-
{
130-
return;
131-
}
132-
133-
EnsureIndented();
134-
_owner.HandlerRawAppend(str);
135-
}
136-
137-
/// <summary>Appends a formatted value with alignment from the interpolated string.</summary>
138-
/// <typeparam name="T">The type of the value to format.</typeparam>
139-
/// <param name="value">The value to append.</param>
140-
/// <param name="alignment">Minimum width; negative values left-align.</param>
141-
public void AppendFormatted<T>(T value, int alignment)
142-
{
143-
var str = value?.ToString();
144-
if (str is null)
145-
{
146-
return;
147-
}
148-
149-
str = alignment >= 0 ? str.PadLeft(alignment) : str.PadRight(-alignment);
150-
EnsureIndented();
151-
_owner.HandlerRawAppend(str);
152-
}
153-
154-
/// <summary>Appends a formatted value with alignment and format string from the interpolated string.</summary>
155-
/// <typeparam name="T">The type of the value to format. Must implement <see cref="System.IFormattable"/>.</typeparam>
156-
/// <param name="value">The value to append.</param>
157-
/// <param name="alignment">Minimum width; negative values left-align.</param>
158-
/// <param name="format">The format string.</param>
159-
public void AppendFormatted<T>(T value, int alignment, string? format)
160-
where T : System.IFormattable
161-
{
162-
var str = value?.ToString(format, CultureInfo.InvariantCulture) ?? string.Empty;
163-
str = alignment >= 0 ? str.PadLeft(alignment) : str.PadRight(-alignment);
164-
EnsureIndented();
165-
_owner.HandlerRawAppend(str);
166-
}
167-
168-
/// <summary>Appends a <see cref="ReadOnlySpan{T}"/> value from the interpolated string.</summary>
169-
/// <param name="value">The span to append.</param>
170-
public void AppendFormatted(ReadOnlySpan<char> value)
171-
{
172-
if (value.IsEmpty)
173-
{
174-
return;
175-
}
176-
177-
EnsureIndented();
178-
_owner.HandlerRawAppend(value);
179-
}
180-
}
18159
#endif
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#if NET6_0_OR_GREATER
2+
namespace NetEvolve.CodeBuilder;
3+
4+
using System.Globalization;
5+
using System.Runtime.CompilerServices;
6+
7+
/// <summary>
8+
/// Custom interpolated string handler for <see cref="CSharpCodeBuilder"/>.
9+
/// </summary>
10+
/// <remarks>
11+
/// This handler is instantiated by the compiler when an interpolated string is passed to
12+
/// <see cref="CSharpCodeBuilder.AppendInterpolated"/> or <see cref="CSharpCodeBuilder.AppendLineInterpolated"/>.
13+
/// It appends each literal and formatted part directly to the builder, applying indentation before
14+
/// the first non-empty part on a new line.
15+
/// </remarks>
16+
[InterpolatedStringHandler]
17+
public ref struct CSharpInterpolatedStringHandler
18+
{
19+
private readonly CSharpCodeBuilder _owner;
20+
private bool _indentEnsured;
21+
22+
/// <summary>
23+
/// Initializes a new instance of the <see cref="CSharpInterpolatedStringHandler"/> struct.
24+
/// </summary>
25+
/// <param name="literalLength">The total length of all literal parts (hint for capacity).</param>
26+
/// <param name="formattedCount">The number of formatted holes in the interpolated string.</param>
27+
/// <param name="builder">The <see cref="CSharpCodeBuilder"/> to append to.</param>
28+
public CSharpInterpolatedStringHandler(int literalLength, int formattedCount, CSharpCodeBuilder builder)
29+
{
30+
_owner = builder;
31+
_indentEnsured = false;
32+
}
33+
34+
private void EnsureIndented()
35+
{
36+
if (!_indentEnsured)
37+
{
38+
_owner.HandlerEnsureIndented();
39+
_indentEnsured = true;
40+
}
41+
}
42+
43+
/// <summary>Appends a literal string part of the interpolated string.</summary>
44+
/// <param name="value">The literal string to append.</param>
45+
public void AppendLiteral(string? value)
46+
{
47+
if (string.IsNullOrEmpty(value))
48+
{
49+
return;
50+
}
51+
52+
EnsureIndented();
53+
_owner.HandlerRawAppend(value);
54+
}
55+
56+
/// <summary>Appends a formatted value from the interpolated string.</summary>
57+
/// <typeparam name="T">The type of the value to format.</typeparam>
58+
/// <param name="value">The value to append.</param>
59+
public void AppendFormatted<T>(T value)
60+
{
61+
var str = value?.ToString();
62+
if (string.IsNullOrEmpty(str))
63+
{
64+
return;
65+
}
66+
67+
EnsureIndented();
68+
_owner.HandlerRawAppend(str);
69+
}
70+
71+
/// <summary>Appends a formatted value with a format string from the interpolated string.</summary>
72+
/// <typeparam name="T">The type of the value to format. Must implement <see cref="System.IFormattable"/>.</typeparam>
73+
/// <param name="value">The value to append.</param>
74+
/// <param name="format">The format string.</param>
75+
public void AppendFormatted<T>(T value, string? format)
76+
where T : System.IFormattable
77+
{
78+
var str = value?.ToString(format, CultureInfo.InvariantCulture);
79+
if (string.IsNullOrEmpty(str))
80+
{
81+
return;
82+
}
83+
84+
EnsureIndented();
85+
_owner.HandlerRawAppend(str);
86+
}
87+
88+
/// <summary>Appends a formatted value with alignment from the interpolated string.</summary>
89+
/// <typeparam name="T">The type of the value to format.</typeparam>
90+
/// <param name="value">The value to append.</param>
91+
/// <param name="alignment">Minimum width; negative values left-align.</param>
92+
public void AppendFormatted<T>(T value, int alignment)
93+
{
94+
var str = value?.ToString();
95+
if (str is null)
96+
{
97+
return;
98+
}
99+
100+
str = alignment >= 0 ? str.PadLeft(alignment) : str.PadRight(-alignment);
101+
EnsureIndented();
102+
_owner.HandlerRawAppend(str);
103+
}
104+
105+
/// <summary>Appends a formatted value with alignment and format string from the interpolated string.</summary>
106+
/// <typeparam name="T">The type of the value to format. Must implement <see cref="System.IFormattable"/>.</typeparam>
107+
/// <param name="value">The value to append.</param>
108+
/// <param name="alignment">Minimum width; negative values left-align.</param>
109+
/// <param name="format">The format string.</param>
110+
public void AppendFormatted<T>(T value, int alignment, string? format)
111+
where T : System.IFormattable
112+
{
113+
var str = value?.ToString(format, CultureInfo.InvariantCulture) ?? string.Empty;
114+
str = alignment >= 0 ? str.PadLeft(alignment) : str.PadRight(-alignment);
115+
EnsureIndented();
116+
_owner.HandlerRawAppend(str);
117+
}
118+
119+
/// <summary>Appends a <see cref="ReadOnlySpan{T}"/> value from the interpolated string.</summary>
120+
/// <param name="value">The span to append.</param>
121+
public void AppendFormatted(ReadOnlySpan<char> value)
122+
{
123+
if (value.IsEmpty)
124+
{
125+
return;
126+
}
127+
128+
EnsureIndented();
129+
_owner.HandlerRawAppend(value);
130+
}
131+
}
132+
#endif

0 commit comments

Comments
 (0)