Skip to content

Commit e8f98df

Browse files
StevenTCramerclaude
andcommitted
Fix TW0003 analyzer to properly handle editorconfig exclusions
- Changed from GlobalOptions to file-specific options for reading excluded_files - Merge configured exclusions with default exclusions instead of replacing - Added more default exclusions for generated files (*.GlobalUsings.g.cs, *.AssemblyAttributes.cs) - Fixed code style warnings (explicit types, simplified namespace) - Test project .editorconfig now only needs to specify additional exclusions 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent d6f846a commit e8f98df

File tree

2 files changed

+23
-15
lines changed

2 files changed

+23
-15
lines changed

source/timewarp-source-generators/file-name-rule-analyzer.cs

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,26 +30,29 @@ public class FileNameRuleAnalyzer : IIncrementalGenerator
3030
"Directory.Build.props",
3131
"Directory.Build.targets",
3232
"Directory.Packages.props",
33-
"AssemblyInfo.cs",
33+
"*AssemblyInfo.cs",
34+
"*.AssemblyInfo.cs",
35+
"*.AssemblyAttributes.cs",
36+
"*.GlobalUsings.g.cs",
3437
"AnalyzerReleases.Shipped.md",
3538
"AnalyzerReleases.Unshipped.md"
3639
];
3740

3841
public void Initialize(IncrementalGeneratorInitializationContext context)
3942
{
4043
// Create a value provider that provides all syntax trees with config options
41-
var syntaxTreesWithConfig = context.CompilationProvider
44+
IncrementalValuesProvider<(SyntaxTree tree, AnalyzerConfigOptionsProvider configOptions)> syntaxTreesWithConfig = context.CompilationProvider
4245
.Combine(context.AnalyzerConfigOptionsProvider)
4346
.SelectMany((source, _) =>
4447
{
45-
var (compilation, configOptions) = source;
48+
(Compilation compilation, AnalyzerConfigOptionsProvider configOptions) = source;
4649
return compilation.SyntaxTrees.Select(tree => (tree, configOptions));
4750
});
4851

4952
// Register diagnostics for each syntax tree
5053
context.RegisterSourceOutput(syntaxTreesWithConfig, (spc, source) =>
5154
{
52-
var (tree, configOptions) = source;
55+
(SyntaxTree tree, AnalyzerConfigOptionsProvider configOptions) = source;
5356
AnalyzeFileNaming(spc, tree, configOptions);
5457
});
5558
}
@@ -69,7 +72,7 @@ private void AnalyzeFileNaming(SourceProductionContext context, SyntaxTree tree,
6972
return;
7073

7174
// Get configured exceptions
72-
string[] exceptions = GetConfiguredExceptions(configOptions);
75+
string[] exceptions = GetConfiguredExceptions(configOptions, tree);
7376

7477
// Check if file matches any exception pattern
7578
if (IsFileExcepted(fileName, exceptions))
@@ -78,28 +81,33 @@ private void AnalyzeFileNaming(SourceProductionContext context, SyntaxTree tree,
7881
// Check if file name follows kebab-case pattern
7982
if (!KebabCasePattern.IsMatch(fileName))
8083
{
81-
Location location = Location.Create(
84+
var location = Location.Create(
8285
tree,
83-
Microsoft.CodeAnalysis.Text.TextSpan.FromBounds(0, 0)
86+
TextSpan.FromBounds(0, 0)
8487
);
8588

86-
Diagnostic diagnostic = Diagnostic.Create(Rule, location, fileName);
89+
var diagnostic = Diagnostic.Create(Rule, location, fileName);
8790
context.ReportDiagnostic(diagnostic);
8891
}
8992
}
9093

91-
private string[] GetConfiguredExceptions(AnalyzerConfigOptionsProvider configOptions)
94+
private string[] GetConfiguredExceptions(AnalyzerConfigOptionsProvider configOptions, SyntaxTree tree)
9295
{
96+
// Get file-specific options
97+
AnalyzerConfigOptions options = configOptions.GetOptions(tree);
98+
9399
// Try to get configured exceptions from .editorconfig
94-
if (configOptions.GlobalOptions.TryGetValue(
100+
if (options.TryGetValue(
95101
"dotnet_diagnostic.TW0003.excluded_files",
96102
out string? configuredExceptions) && !string.IsNullOrEmpty(configuredExceptions))
97103
{
98104
// Split by semicolon and trim whitespace
99-
return configuredExceptions
100-
.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
101-
.Select(s => s.Trim())
102-
.ToArray();
105+
IEnumerable<string> additionalExceptions = configuredExceptions
106+
.Split([';'], StringSplitOptions.RemoveEmptyEntries)
107+
.Select(s => s.Trim());
108+
109+
// Merge defaults with configured exceptions
110+
return [.. DefaultExceptions, .. additionalExceptions];
103111
}
104112

105113
// Return default exceptions if not configured

tests/timewarp-source-generators-test-console/.editorconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ root = true
55
[*.cs]
66

77
dotnet_diagnostic.TW0003.severity = error # Set to warning/error to enforce kebab-case file naming
8-
# dotnet_diagnostic.TW0003.excluded_files =
8+
dotnet_diagnostic.TW0003.excluded_files = PascalCaseTest.cs
99
# Enable TW0004 - XML documentation to markdown analyzer
1010
dotnet_diagnostic.TW0004.severity = suggestion

0 commit comments

Comments
 (0)