Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
98bcfc5
fix: enforce generated analyzer config ordering
ANcpLua May 9, 2026
e16db33
fix: satisfy config generator lint
ANcpLua May 9, 2026
f7b6125
fix: normalize generated config file endings
ANcpLua May 9, 2026
ada2f47
chore: normalize generated analyzer configs
ANcpLua May 9, 2026
cf18da3
fix: address analyzer config review feedback
ANcpLua May 9, 2026
b6e83a8
fix: address analyzer config review comments
ANcpLua May 9, 2026
4cc070c
Merge branch 'main' into fix/refix-codestyle-policy-pass
ANcpLua May 10, 2026
da195e3
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] May 10, 2026
eb99db2
Potential fix for pull request finding
ANcpLua May 10, 2026
b719189
merge main and resolve config conflicts
Copilot May 10, 2026
642a434
fix: apply CodeRabbit auto-fixes
coderabbitai[bot] May 10, 2026
5b85e59
fix: resolve NetAnalyzersVersion from Version.props for generator pin…
Copilot May 10, 2026
23aa320
fix: harden config generator review feedback
ANcpLua May 10, 2026
6b504e0
fix: preserve pinned analyzer versions during package dedup
ANcpLua May 10, 2026
1d0f071
fix: resolve property-based package versions instead of dropping
ANcpLua May 10, 2026
e6d76a4
fix: give xunit.analyzers a reserved global_level slot
ANcpLua May 10, 2026
abfdd06
chore: regenerate analyzer editorconfigs for current package versions
ANcpLua May 10, 2026
7e47350
fix: append rule id to analyzer help links missing the slug
ANcpLua May 10, 2026
062473c
perf: skip duplicate top-level package IDs before NuGet work
ANcpLua May 10, 2026
da64682
fix: fail fast when a pinned analyzer can't be resolved on the feed
ANcpLua May 10, 2026
bd356d1
fix: honor Condition guards and delay seenIds add until after resolution
ANcpLua May 10, 2026
bf2269e
fix: correct pinned-package error message to reflect nuget.org
ANcpLua May 10, 2026
fde3187
fix: set ContinuousIntegrationBuild before warnings-as-errors guards
ANcpLua May 10, 2026
67a10f2
fix: rename const identifiers to PascalCase to satisfy IDE1006
ANcpLua May 10, 2026
f6ba794
fix: suppress CA2000 on test CreateProject builder factories
ANcpLua May 10, 2026
c3ae70b
fix: only set ContinuousIntegrationBuild when consumer hasn't already
ANcpLua May 10, 2026
d517b7e
fix: stable-hash global_level fallback and tuple-keyed pkg dedup
ANcpLua May 10, 2026
7034f77
fix: rename opt-out property to EnableEditorConfigDogfooding
ANcpLua May 10, 2026
cb4e6cb
fix: track visited packages in a typed PackageIdentity set
ANcpLua May 10, 2026
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
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ insert_final_newline = true
[*.cs]
indent_size = 4
insert_final_newline = true
charset = utf-8-bom
charset = utf-8

# C# naming conventions live in src/Config/NamingConvention.editorconfig
# (single source of truth, dotnet/runtime aligned, shipped with the SDK package).
Expand Down
35 changes: 26 additions & 9 deletions Directory.Build.props
Original file line number Diff line number Diff line change
@@ -1,14 +1,26 @@
<Project>
<!--
Set the CI marker FIRST so the warning-as-error properties below see it.
PropertyGroups evaluate in document order, so deferring this until after
those conditions would silently bypass CI warning enforcement on Debug
builds (e.g. `dotnet test` without `-c Release`).
-->
<PropertyGroup Condition="'$(CI)' == 'true'">
<ContinuousIntegrationBuild Condition="'$(ContinuousIntegrationBuild)' == ''">true</ContinuousIntegrationBuild>
</PropertyGroup>
Comment thread
coderabbitai[bot] marked this conversation as resolved.

<!-- SDK-owned properties - centralized here, NOT in individual csproj files -->
<PropertyGroup>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<Deterministic>true</Deterministic>
</PropertyGroup>
<ImplicitUsings Condition="'$(ImplicitUsings)' == ''">enable</ImplicitUsings>
<Deterministic Condition="'$(Deterministic)' == ''">true</Deterministic>
<EnableNETAnalyzers Condition="'$(EnableNETAnalyzers)' == ''">true</EnableNETAnalyzers>
<AnalysisLevel Condition="'$(AnalysisLevel)' == ''">latest-all</AnalysisLevel>

<!-- CI-only: Enable SourceLink reproducibility -->
<PropertyGroup Condition="'$(CI)' == 'true'">
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
<MSBuildTreatWarningsAsErrors Condition="'$(MSBuildTreatWarningsAsErrors)' == '' AND ('$(ContinuousIntegrationBuild)' == 'true' OR '$(Configuration)' == 'Release')">true</MSBuildTreatWarningsAsErrors>
<TreatWarningsAsErrors Condition="'$(TreatWarningsAsErrors)' == '' AND ('$(ContinuousIntegrationBuild)' == 'true' OR '$(Configuration)' == 'Release')">true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild Condition="'$(EnforceCodeStyleInBuild)' == '' AND ('$(ContinuousIntegrationBuild)' == 'true' OR '$(Configuration)' == 'Release')">true</EnforceCodeStyleInBuild>
Comment on lines +21 to +23
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Set CI marker before applying warning-as-error conditions

These properties are conditioned on $(ContinuousIntegrationBuild), but this file sets ContinuousIntegrationBuild later (line 18), so in CI Debug builds the condition is false when evaluated and warnings are not promoted to errors. In this repo, .github/workflows/nuget-publish.yml runs dotnet test without -c Release, so the default Debug configuration can silently bypass the intended CI warning enforcement.

Useful? React with 👍 / 👎.

</PropertyGroup>

<!--
Expand All @@ -24,9 +36,14 @@
<!--
This repo's own projects use Microsoft.NET.Sdk directly, not ANcpLua.NET.Sdk,
so the SDK's Common.props EditorConfigFiles injection doesn't run. Pull in
the canonical naming convention file so this repo eats its own dog food.
the canonical SDK-shipped editorconfigs so this repo eats its own dog food.
-->
<ItemGroup>
<EditorConfigFiles Include="$(MSBuildThisFileDirectory)src\Config\NamingConvention.editorconfig" />
<PropertyGroup>
<EnableEditorConfigDogfooding Condition="'$(EnableEditorConfigDogfooding)' == ''">true</EnableEditorConfigDogfooding>
</PropertyGroup>

<ItemGroup Condition="'$(EnableEditorConfigDogfooding)' == 'true'">
<EditorConfigFiles Include="$(MSBuildThisFileDirectory)src\Config\*.editorconfig"
Exclude="$(MSBuildThisFileDirectory)src\Config\ANcpLua.NET.Sdk*.editorconfig" />
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
</ItemGroup>
</Project>
</Project>
1 change: 1 addition & 0 deletions src/Build/Common/Version.props
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@

<PropertyGroup Label="Analyzers">
<ANcpLuaAnalyzersVersion>1.29.1</ANcpLuaAnalyzersVersion>
<NetAnalyzersVersion Condition="'$(NetAnalyzersVersion)' == ''">$(DotNetSdkVersion)</NetAnalyzersVersion>
<SbomTargetsVersion>4.1.5</SbomTargetsVersion>
<BannedApiAnalyzersVersion>4.14.0</BannedApiAnalyzersVersion>
</PropertyGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/Config/ANcpLua.NET.Sdk.SingleFileApp.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# global_level must be higher than the base editorconfig files
# global_level must be higher than the base SDK-shipped globals
is_global = true
global_level = 101
global_level = 61

# MA0047: Declare types in namespaces
dotnet_diagnostic.MA0047.severity = none
Expand Down
4 changes: 2 additions & 2 deletions src/Config/ANcpLua.NET.Sdk.Web.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# global_level must be higher than the base editorconfig files
# global_level must be higher than the base SDK-shipped globals
is_global = true
global_level = 101
global_level = 60

# CA1002: Do not expose generic lists
dotnet_diagnostic.CA1002.severity = none
6 changes: 3 additions & 3 deletions src/Config/Analyzer.ANcpLua.Analyzers.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 13

# AL0001: Prohibit reassignment of primary constructor parameters
# Help link: https://ancplua.mintlify.app/analyzers/rules/AL0001
Expand Down Expand Up @@ -672,4 +673,3 @@ dotnet_diagnostic.AL0137.severity = warning
# Help link: https://ancplua.mintlify.app/analyzers/rules/AL0138
# Enabled: True, Severity: warning
dotnet_diagnostic.AL0138.severity = warning

6 changes: 3 additions & 3 deletions src/Config/Analyzer.AwesomeAssertions.Analyzers.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 14

# AwesomeAssertions0801: Code Smell
# Enabled: True, Severity: warning
Expand All @@ -21,4 +22,3 @@ dotnet_diagnostic.FAA0003.severity = suggestion
# FAA0004: Replace NUnit assertion with Fluent Assertions equivalent
# Enabled: True, Severity: suggestion
dotnet_diagnostic.FAA0004.severity = suggestion

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 10

# Microsoft.CodeAnalysis.Analyzers - no configurable rules

Expand Down Expand Up @@ -224,4 +225,3 @@ dotnet_diagnostic.RS2007.severity = warning
# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
# Enabled: True, Severity: warning
dotnet_diagnostic.RS2008.severity = warning

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 12

# RS0030: Do not use banned APIs
# Help link: https://github.com/dotnet/roslyn/blob/main/src/RoslynAnalyzers/Microsoft.CodeAnalysis.BannedApiAnalyzers/BannedApiAnalyzers.Help.md
Expand All @@ -15,4 +16,3 @@ dotnet_diagnostic.RS0031.severity = warning
# RS0035: External access to internal symbols outside the restricted namespace(s) is prohibited
# Enabled: True, Severity: error
dotnet_diagnostic.RS0035.severity = error

Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 11

dotnet_diagnostic.CA2217.api_surface = all

Expand Down Expand Up @@ -1602,4 +1603,3 @@ dotnet_diagnostic.CA5404.severity = warning
# Help link: https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca5405
# Enabled: False, Severity: warning
dotnet_diagnostic.CA5405.severity = warning

6 changes: 3 additions & 3 deletions src/Config/Analyzer.xunit.analyzers.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 15

# xUnit1000: Test classes must be public
# Help link: https://xunit.net/xunit.analyzers/rules/xUnit1000
Expand Down Expand Up @@ -451,4 +452,3 @@ dotnet_diagnostic.xUnit3002.severity = warning
# Help link: https://xunit.net/xunit.analyzers/rules/xUnit3003
# Enabled: True, Severity: warning
dotnet_diagnostic.xUnit3003.severity = warning

23 changes: 8 additions & 15 deletions src/Config/CodingStyle.editorconfig
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
is_global = true
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
global_level = 100
global_level = 30

charset = utf-8-bom
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
# Note: global AnalyzerConfig files aren't intended for editor-only formatting
# settings (indent size, trimming whitespace, encoding, ...). Keep those in a
# regular repo-level `.editorconfig` instead.

# New line preferences
csharp_new_line_before_open_brace = all
Expand All @@ -26,25 +23,21 @@ csharp_indent_switch_labels = true
csharp_indent_labels = one_less_than_current

# Modifier preferences
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async

# avoid this. unless absolutely necessary
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_property = false
dotnet_style_qualification_for_method = false
dotnet_style_qualification_for_event = false

# Types: use keywords instead of BCL types, and permit var only when the type is clear
# Types: use keywords instead of BCL types; prefer `var` consistently
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere = true
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true

# Use language keywords instead of framework type names for type references
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true

# File style
csharp_using_directive_placement = outside_namespace
dotnet_sort_system_directives_first = true
Expand All @@ -53,6 +46,7 @@ csharp_style_namespace_declarations = file_scoped
# Expression-level preferences
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true
dotnet_style_prefer_collection_expression = when_types_exactly_match
dotnet_style_explicit_tuple_names = true
dotnet_style_null_propagation = true
dotnet_style_object_initializer = true
Expand All @@ -70,7 +64,7 @@ csharp_prefer_inferred_anonymous_type_member_names = true
csharp_prefer_inferred_tuple_names = true
csharp_prefer_simple_default_expression = true
csharp_style_deconstructed_variable_declaration = true
csharp_style_pattern_local_over_anonymous_function = true
csharp_style_prefer_local_over_anonymous_function = true
csharp_style_prefer_switch_expression = true

dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
Expand Down Expand Up @@ -99,7 +93,6 @@ csharp_style_throw_expression = true
# Other features
csharp_style_prefer_index_operator = true
csharp_style_prefer_range_operator = true
csharp_style_pattern_local_over_anonymous_function = true

# Code block preferences
csharp_prefer_braces = when_multiline
Expand Down
6 changes: 3 additions & 3 deletions src/Config/Compiler.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
# global_level controls precedence across multiple global AnalyzerConfig files.
# Keep distinct values to avoid equal-level conflicts (which are ignored).
is_global = true
global_level = 100
global_level = 40

# EnableGenerateDocumentationFile: Set MSBuild property 'GenerateDocumentationFile' to 'true'
# Help link: https://github.com/dotnet/roslyn/issues/41640
Expand Down Expand Up @@ -298,4 +299,3 @@ dotnet_diagnostic.IDE2006.severity = silent
# RemoveUnnecessaryImportsFixable:
# Enabled: True, Severity: silent
dotnet_diagnostic.RemoveUnnecessaryImportsFixable.severity = silent

8 changes: 5 additions & 3 deletions src/Config/Global.editorconfig
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Highest precedence among the base/non-flavor SDK globals.
# Per-flavor overlays (e.g. ANcpLua.NET.Sdk.Web=60, .SingleFileApp=61) sit above this.
# EditorConfig spec: comments must be on their own line, never trailing a value.
is_global = true
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
global_level = 100
global_level = 50

dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
dotnet_style_prefer_foreach_explicit_cast_in_source=when_strongly_typed

# Remove this or Me qualification
dotnet_diagnostic.IDE0003.severity = suggestion
Expand Down
3 changes: 1 addition & 2 deletions src/Config/NamingConvention.editorconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
is_global = true
# global_level is set to 100 so SDK configuration overrides analyzer-provided defaults.
global_level = 100
global_level = 20

dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case

Expand Down
26 changes: 14 additions & 12 deletions tests/ANcpLua.Sdk.Tests/Helpers/SdkProjectBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,16 @@ public static SdkProjectBuilder Create(
public new SdkProjectBuilder WithDirectoryBuildProps(string content)
{
// Inject DisableVersionAnalyzer to prevent AL0017-AL0019 errors in test projects
var modifiedContent = content.Replace(
"<Project>",
"""
<Project>
<PropertyGroup>
<DisableVersionAnalyzer>true</DisableVersionAnalyzer>
</PropertyGroup>
""");
var doc = XDocument.Parse(content, LoadOptions.PreserveWhitespace);
if (doc.Root is null || doc.Root.Name.LocalName != "Project")
throw new InvalidOperationException("Directory.Build.props must have a <Project> root element.");

var ns = doc.Root.Name.Namespace;
doc.Root.AddFirst(
new XElement(ns + "PropertyGroup",
new XElement(ns + "DisableVersionAnalyzer", "true")));

var modifiedContent = doc.ToString(SaveOptions.DisableFormatting);
base.WithDirectoryBuildProps(modifiedContent);
return this;
}
Expand Down Expand Up @@ -579,14 +581,14 @@ public override async Task<BuildResult> ExecuteDotnetCommandAsync(
var result = await psi.RunAsTaskAsync();

// Retry on SDK resolution errors
const int maxRetries = 5;
for (var retry = 0; retry < maxRetries && result.ExitCode is not 0; retry++)
const int MaxRetries = 5;
for (var retry = 0; retry < MaxRetries && result.ExitCode is not 0; retry++)
if (result.Output.Any(static line => line.Text.Contains("error MSB4236", StringComparison.Ordinal) ||
line.Text.Contains(
"The project file may be invalid or missing targets required for restore",
StringComparison.Ordinal)))
{
Output?.WriteLine($"SDK resolution or restore error detected, retrying ({retry + 1}/{maxRetries})...");
Output?.WriteLine($"SDK resolution or restore error detected, retrying ({retry + 1}/{MaxRetries})...");
await Task.Delay(100 * (1 << retry));
result = await psi.RunAsTaskAsync();
}
Expand Down Expand Up @@ -643,7 +645,7 @@ public override async Task<BuildResult> ExecuteDotnetCommandAsync(
}

// Fail fast on SDK resolution errors
if (result.Output.Any(static line => line.Text.Contains("Could not resolve SDK")))
if (result.Output.Any(static line => line.Text.Contains("Could not resolve SDK", StringComparison.Ordinal)))
Assert.Fail("The SDK cannot be found, expected version: " + _fixture.Version);

return new BuildResult(result.ExitCode, result.Output, sarif, binlogContent)
Expand Down
11 changes: 7 additions & 4 deletions tests/ANcpLua.Sdk.Tests/MtpDetectionTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Diagnostics.CodeAnalysis;
using static ANcpLua.Sdk.Tests.Helpers.PackageFixture;

namespace ANcpLua.Sdk.Tests;
Expand Down Expand Up @@ -42,6 +43,8 @@ public abstract class MtpDetectionTests(
"TestingPlatformCommandLineArguments"
];

[SuppressMessage("Reliability", "CA2000:Dispose objects before losing scope",
Justification = "Builder factory transfers ownership; every caller disposes via 'await using var project = CreateProject(...);'.")]
private SdkProjectBuilder CreateProject(string? sdkName = null) =>
SdkProjectBuilder.Create(fixture, SdkImportStyle.ProjectElement, sdkName ?? SdkTestName)
.WithDotnetSdkVersion(dotnetSdkVersion)
Expand Down Expand Up @@ -121,10 +124,10 @@ public class SampleTests
.BuildAsync();

var cliArgs = result.GetRecordedProperty("TestingPlatformCommandLineArguments");
Assert.Contains("--report-xunit-trx", cliArgs);
Assert.DoesNotContain("--report-trx ", cliArgs);
Assert.DoesNotContain("--crashdump", cliArgs);
Assert.DoesNotContain("--hangdump", cliArgs);
Assert.Contains("--report-xunit-trx", cliArgs, StringComparison.Ordinal);
Assert.DoesNotContain("--report-trx", cliArgs, StringComparison.Ordinal);
Assert.DoesNotContain("--crashdump", cliArgs, StringComparison.Ordinal);
Assert.DoesNotContain("--hangdump", cliArgs, StringComparison.Ordinal);
}

[Fact]
Expand Down
Loading
Loading