diff --git a/AGENTS.md b/AGENTS.md
index 06e33c132..4af0e6205 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -55,7 +55,7 @@ The analyzer must use `IOperation` or `ISymbol` to analyze the content. Only fal
### Generated code
-The analyzers analyze generated code, so they must call `context.ConfigureAnalysisOfGeneratedCode(...)` in `Initialize` instead of `ConfigureGeneratedCodeAnalysis`, which `BannedSymbols.txt` makes a compilation error: the flags passed to it are the minimum, and `Analyze | ReportDiagnostics` is added to them unless the `MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable opts out, as analyzing generated code has a cost. Pass `GeneratedCodeAnalysisFlags.None` unless the rule needs generated code to be correct even when a user opts out (`Analyze`), or reports in generated code by default (`Analyze | ReportDiagnostics`). The diagnostics located in generated code are filtered when they are reported. The filtering is done by `GeneratedCodeReporting`, which sets the `DiagnosticReporter.CanReportDiagnostic` filter of `Meziantou.Framework.Roslyn` from a module initializer, so the rules must report their diagnostics with the `ReportDiagnostic` extension methods of the analysis contexts or with a `DiagnosticReporter`; `BannedSymbols.txt` makes reporting directly on a Roslyn context a compilation error, as it would bypass the filter. Add `customTags: [GeneratedCodeReporting.ReportInGeneratedCodeTag]` to the descriptor of the rules that must report in generated code by default, such as the rules whose subject is the generated file itself, use `GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics` in their analyzer, and run `dotnet run --project src/DocumentationGenerator` to update the list in [`docs/generated-code.md`](/docs/generated-code.md).
+The analyzers skip generated code, so they must call `context.ConfigureAnalysisOfGeneratedCode(...)` in `Initialize` instead of `ConfigureGeneratedCodeAnalysis`, which `BannedSymbols.txt` makes a compilation error: the flags passed to it are the minimum, and `Analyze | ReportDiagnostics` is added to them only when the `MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable opts in, as analyzing generated code has a cost. Pass `GeneratedCodeAnalysisFlags.None` unless the rule needs generated code to be correct even when nobody opts in (`Analyze`), or reports in generated code by default (`Analyze | ReportDiagnostics`). The diagnostics located in generated code are filtered when they are reported. The filtering is done by `GeneratedCodeReporting`, which sets the `DiagnosticReporter.CanReportDiagnostic` filter of `Meziantou.Framework.Roslyn` from a module initializer, so the rules must report their diagnostics with the `ReportDiagnostic` extension methods of the analysis contexts or with a `DiagnosticReporter`; `BannedSymbols.txt` makes reporting directly on a Roslyn context a compilation error, as it would bypass the filter. Add `customTags: [GeneratedCodeReporting.ReportInGeneratedCodeTag]` to the descriptor of the rules that must report in generated code by default, such as the rules whose subject is the generated file itself, use `GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics` in their analyzer, and run `dotnet run --project src/DocumentationGenerator` to update the list in [`docs/generated-code.md`](/docs/generated-code.md).
Code snippets in tests must use raw string literals (`"""`) and must be minimized to only include the necessary code to reproduce the issue. Avoid including unnecessary code that does not contribute to the test case.
When reporting a diagnostic, the snippet must use the `[|code|]` syntax or `{|id:code|}` syntax. Do not explicitly indicates lines or columns.
diff --git a/README.md b/README.md
index bb35c6e35..04d1d4db9 100755
--- a/README.md
+++ b/README.md
@@ -298,8 +298,19 @@ Supported values are:
## Analyzing generated code
-The rules analyze generated code, but most of them do not report the diagnostics located in generated code. Set
-`report_generated_code` in the `.editorconfig` file to change it, for a single rule or for all of them at once:
+The rules skip generated code, as analyzing it costs build time and you cannot fix code you do not own. Set the
+`MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable to `true` (or `1`) to opt in, which makes the rules analyze
+generated code:
+
+```bash
+MEZIANTOU_ANALYZER_GENERATED_CODE=true
+```
+
+Note that the analyzers run in a long-lived process. After changing the variable, run `dotnet build-server shutdown`
+and rebuild, or restart your IDE.
+
+Opting in does not report anything by itself: `report_generated_code` decides whether a rule reports the diagnostics
+located in the generated code it analyzes, for a single rule or for all of them at once:
```ini
[*.cs]
@@ -310,18 +321,8 @@ MA.report_generated_code = true
MA0051.report_generated_code = false
```
-A few rules report in generated code by default, such as the Blazor rules that work on the code generated from the
-`.razor` files.
-
-Analyzing generated code costs build time. Set the `MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable to
-`false` (or `0`) to opt out, which makes the rules skip generated code entirely, except the few that need it:
-
-```bash
-MEZIANTOU_ANALYZER_GENERATED_CODE=false
-```
-
-Note that the analyzers run in a long-lived process. After changing the variable, run `dotnet build-server shutdown`
-and rebuild, or restart your IDE.
+A few rules analyze generated code without the variable, and report in it by default, such as the Blazor rules that
+work on the code generated from the `.razor` files.
See [Analyzing generated code](https://github.com/meziantou/Meziantou.Analyzer/blob/main/docs/generated-code.md)
for the list of those rules and for the detection of the generated files.
diff --git a/docs/generated-code.md b/docs/generated-code.md
index 048759cf6..ba79e018d 100644
--- a/docs/generated-code.md
+++ b/docs/generated-code.md
@@ -1,14 +1,15 @@
# Analyzing generated code
-The rules analyze generated code, so they see the whole compilation, but most of them do not report the diagnostics
-located in generated code, which is the expected behavior for the vast majority of projects: you cannot fix code you
-do not own. Some rules are the exception and report in generated code by default, as the generated file is the
-subject of the rule, such as the Blazor rules that work on the code generated from the `.razor` files.
+The rules skip generated code, which is the expected behavior for the vast majority of projects: you cannot fix code
+you do not own, and analyzing code nobody looks at costs build time. Some rules are the exception and analyze it
+anyway: the ones whose subject is the generated file itself, such as the Blazor rules that work on the code generated
+from the `.razor` files, and the ones that need to see the whole compilation to be correct. Set the
+`MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable to opt in to analyzing generated code with every rule.
## Configuration
-The `report_generated_code` option indicates whether a rule reports the diagnostics located in generated code. It can
-be set for a single rule, or for all of them at once with the `MA` prefix:
+The `report_generated_code` option indicates whether a rule reports the diagnostics located in the generated code it
+analyzes. It can be set for a single rule, or for all of them at once with the `MA` prefix:
```ini
[*.cs]
@@ -35,24 +36,23 @@ MA0051.report_generated_code = true
When neither is set, each rule uses its own default, which is to not report in generated code, except for the rules
below. To turn off a rule entirely, set its severity to `none` instead.
-## Opting out with the environment variable
+This option only decides what a rule reports, not what it analyzes, so `report_generated_code = true` has no effect on
+a rule that does not analyze generated code: it needs the environment variable below. Setting it to `false` always
+works, as a rule can only report what it is allowed to report.
-Analyzing generated code costs build time, and a project where nothing reports in generated code pays it for nothing.
-Set the `MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable to skip generated code entirely:
+## Opting in with the environment variable
+
+Set the `MEZIANTOU_ANALYZER_GENERATED_CODE` environment variable to analyze generated code with every rule:
| Value | Behavior |
|-------|----------|
-| not set, empty, or any other value | The rules analyze generated code, and `report_generated_code` decides what they report |
-| `false` (case-insensitive) or `0` | The rules skip generated code, except the ones that need it |
-
-The variable can only remove analysis from the rules that do not need it. Two kinds of rules are unaffected: the ones
-that report in generated code by default, listed below, and the ones that need to see the whole compilation to be
-correct, such as MA0053, which reports a class that no other class inherits from and would report a false positive if
-the deriving class were declared in a generated file.
+| `true` (case-insensitive) or `1` | The rules analyze generated code, and `report_generated_code` decides what they report |
+| not set, empty, or any other value | The rules skip generated code, except the ones that need it |
-The option above only decides what the rules report, not what they analyze, so `report_generated_code = true` has no
-effect on a rule that skips generated code because of the variable. Setting it to `false` always works, as a rule can
-only report what it is allowed to report.
+Two kinds of rules analyze generated code without the variable: the ones that report in generated code by default,
+listed below, and the ones that need to see the whole compilation to be correct, such as MA0053, which reports a class
+that no other class inherits from and would report a false positive if the deriving class were declared in a generated
+file. `report_generated_code` works on those rules whether the variable is set or not.
## Rules reporting in generated code by default
@@ -99,8 +99,9 @@ written file does not make the code generated, and a partial type declared in a
one reports only in the hand written file. Use the `generated_code` option below for the files the detection does not
recognize.
-The rules that skip generated code because of the environment variable never see it, so they follow the detection of
-Roslyn instead, which also considers the symbols marked with `[GeneratedCode]` or `[DebuggerNonUserCode]` generated.
+The rules that do not analyze generated code never see it, so they follow the detection of Roslyn instead, which also
+considers the symbols marked with `[GeneratedCode]` or `[DebuggerNonUserCode]` generated. The two detections only
+differ for a rule the variable opted in.
## Using the `generated_code` option
@@ -121,7 +122,7 @@ generated, and `generated_code` when you want all the analyzers to treat a speci
An analyzer must declare how it handles generated code from `Initialize(AnalysisContext)`, and the options of the
`.editorconfig` files are not available at that point: they can only be read from the analysis callbacks, which run
later. An environment variable is the only configuration that can be read early enough, which is why the global
-opt-out is not an `.editorconfig` option.
+opt-in is not an `.editorconfig` option.
This has consequences that are worth knowing:
diff --git a/src/Meziantou.Analyzer/BannedSymbols.txt b/src/Meziantou.Analyzer/BannedSymbols.txt
index 3ba2cee74..d3e53c5c7 100644
--- a/src/Meziantou.Analyzer/BannedSymbols.txt
+++ b/src/Meziantou.Analyzer/BannedSymbols.txt
@@ -1,5 +1,5 @@
M:Microsoft.CodeAnalysis.Compilation.GetTypeByMetadataName(System.String); Use GetBestTypeByMetadataName instead
-M:Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.ConfigureGeneratedCodeAnalysis(Microsoft.CodeAnalysis.Diagnostics.GeneratedCodeAnalysisFlags); Use ConfigureAnalysisOfGeneratedCode instead, so users can opt out of analyzing generated code
+M:Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.ConfigureGeneratedCodeAnalysis(Microsoft.CodeAnalysis.Diagnostics.GeneratedCodeAnalysisFlags); Use ConfigureAnalysisOfGeneratedCode instead, so users can opt in to analyzing generated code
M:Microsoft.CodeAnalysis.Diagnostics.SymbolAnalysisContext.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic); Use the ReportDiagnostic methods of ContextExtensions instead, so the diagnostics located in generated code are filtered by GeneratedCodeReporting
M:Microsoft.CodeAnalysis.Diagnostics.OperationAnalysisContext.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic); Use the ReportDiagnostic methods of ContextExtensions instead, so the diagnostics located in generated code are filtered by GeneratedCodeReporting
M:Microsoft.CodeAnalysis.Diagnostics.OperationBlockAnalysisContext.ReportDiagnostic(Microsoft.CodeAnalysis.Diagnostic); Use the ReportDiagnostic methods of ContextExtensions instead, so the diagnostics located in generated code are filtered by GeneratedCodeReporting
diff --git a/src/Meziantou.Analyzer/Internals/AnalysisContextExtensions.cs b/src/Meziantou.Analyzer/Internals/AnalysisContextExtensions.cs
index c0ac95169..b31e72228 100644
--- a/src/Meziantou.Analyzer/Internals/AnalysisContextExtensions.cs
+++ b/src/Meziantou.Analyzer/Internals/AnalysisContextExtensions.cs
@@ -14,11 +14,11 @@ internal static class AnalysisContextExtensions
private static readonly GeneratedCodeAnalysisFlags AdditionalFlags = GetAdditionalFlags(ReadEnvironmentVariable());
///
- /// Configures how the analyzer handles generated code. The rules analyze generated code and report the
- /// diagnostics located in it, which then filters, unless the
- /// MEZIANTOU_ANALYZER_GENERATED_CODE environment variable opts out, as analyzing generated code has a
- /// cost. is the minimum, which opting out cannot remove: it is what the rule
- /// needs to be correct, or to report in generated code by default.
+ /// Configures how the analyzer handles generated code. The rules skip generated code, as analyzing it has a
+ /// cost, unless the MEZIANTOU_ANALYZER_GENERATED_CODE environment variable opts in, in which case they
+ /// analyze it and report the diagnostics located in it, which then
+ /// filters. is the minimum, which not opting in cannot remove: it is what the
+ /// rule needs to be correct, or to report in generated code by default.
///
public static void ConfigureAnalysisOfGeneratedCode(this AnalysisContext context, GeneratedCodeAnalysisFlags defaultFlags)
{
@@ -29,9 +29,9 @@ public static void ConfigureAnalysisOfGeneratedCode(this AnalysisContext context
internal static GeneratedCodeAnalysisFlags GetAdditionalFlags(string? value) => value?.Trim() switch
{
- "0" => GeneratedCodeAnalysisFlags.None,
- var trimmed when string.Equals(trimmed, "false", StringComparison.OrdinalIgnoreCase) => GeneratedCodeAnalysisFlags.None,
- _ => GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics,
+ "1" => GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics,
+ var trimmed when string.Equals(trimmed, "true", StringComparison.OrdinalIgnoreCase) => GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics,
+ _ => GeneratedCodeAnalysisFlags.None,
};
private static string? ReadEnvironmentVariable()
diff --git a/src/Meziantou.Analyzer/Internals/GeneratedCodeReporting.cs b/src/Meziantou.Analyzer/Internals/GeneratedCodeReporting.cs
index b9984bf41..74d2f6875 100644
--- a/src/Meziantou.Analyzer/Internals/GeneratedCodeReporting.cs
+++ b/src/Meziantou.Analyzer/Internals/GeneratedCodeReporting.cs
@@ -4,12 +4,12 @@
namespace Meziantou.Analyzer.Internals;
///
-/// Decides whether a rule reports the diagnostics located in generated code. The analyzers configure Roslyn to
-/// analyze generated code and to report the diagnostics located in it, as ConfigureGeneratedCodeAnalysis
+/// Decides whether a rule reports the diagnostics located in generated code. The analyzers that analyze generated
+/// code also configure Roslyn to report the diagnostics located in it, as ConfigureGeneratedCodeAnalysis
/// cannot read the .editorconfig options, so the decision is taken when a diagnostic is reported. The
-/// options below only apply to what the analyzers actually analyze: a rule stops reporting in generated code when
-/// the MEZIANTOU_ANALYZER_GENERATED_CODE environment variable opts out of analyzing it, unless the rule
-/// needs it (see ).
+/// options below only apply to what the analyzers actually analyze: a rule only reports in generated code when the
+/// MEZIANTOU_ANALYZER_GENERATED_CODE environment variable opts in to analyzing it, unless the rule analyzes
+/// it anyway (see ).
///
internal static class GeneratedCodeReporting
{
diff --git a/tests/Meziantou.Analyzer.Test/Internals/AnalysisContextExtensionsTests.cs b/tests/Meziantou.Analyzer.Test/Internals/AnalysisContextExtensionsTests.cs
index 906847ea9..e56a6d3d3 100644
--- a/tests/Meziantou.Analyzer.Test/Internals/AnalysisContextExtensionsTests.cs
+++ b/tests/Meziantou.Analyzer.Test/Internals/AnalysisContextExtensionsTests.cs
@@ -6,28 +6,28 @@ namespace Meziantou.Analyzer.Test.Internals;
public sealed class AnalysisContextExtensionsTests
{
[Theory]
- [InlineData("0")]
- [InlineData(" 0 ")]
- [InlineData("false")]
- [InlineData("False")]
- [InlineData("FALSE")]
- [InlineData(" false ")]
- public void GetAdditionalFlags_OptedOut(string value)
+ [InlineData("1")]
+ [InlineData(" 1 ")]
+ [InlineData("true")]
+ [InlineData("True")]
+ [InlineData("TRUE")]
+ [InlineData(" true ")]
+ public void GetAdditionalFlags_OptedIn(string value)
{
- Assert.Equal(GeneratedCodeAnalysisFlags.None, AnalysisContextExtensions.GetAdditionalFlags(value));
+ Assert.Equal(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics, AnalysisContextExtensions.GetAdditionalFlags(value));
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData(" ")]
- [InlineData("1")]
- [InlineData("true")]
- [InlineData("True")]
+ [InlineData("0")]
+ [InlineData("false")]
+ [InlineData("False")]
[InlineData("dummy")]
- [InlineData("falsy")]
- public void GetAdditionalFlags_NotOptedOut(string? value)
+ [InlineData("truthy")]
+ public void GetAdditionalFlags_NotOptedIn(string? value)
{
- Assert.Equal(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics, AnalysisContextExtensions.GetAdditionalFlags(value));
+ Assert.Equal(GeneratedCodeAnalysisFlags.None, AnalysisContextExtensions.GetAdditionalFlags(value));
}
}
diff --git a/tests/Meziantou.Analyzer.Test/Rules/GeneratedCodeAnalysisTests.cs b/tests/Meziantou.Analyzer.Test/Rules/GeneratedCodeAnalysisTests.cs
index 52a70d9fc..af4247e63 100644
--- a/tests/Meziantou.Analyzer.Test/Rules/GeneratedCodeAnalysisTests.cs
+++ b/tests/Meziantou.Analyzer.Test/Rules/GeneratedCodeAnalysisTests.cs
@@ -14,14 +14,15 @@
namespace Meziantou.Analyzer.Test.Rules;
///
-/// The analyzers analyze generated code, but only the rules configured with report_generated_code, or
-/// whose default is to report in generated code such as MA0070, report the diagnostics located in it. The
-/// MEZIANTOU_ANALYZER_GENERATED_CODE environment variable opts out of analyzing generated code, which the
-/// tests simulate by setting GeneratedCodeAnalysisFlags to the flags of the rule, as the rules read the
-/// variable once per process.
+/// The analyzers skip generated code, except the rules that need it to be correct and the rules that report in it
+/// by default such as MA0070. The MEZIANTOU_ANALYZER_GENERATED_CODE environment variable opts in to
+/// analyzing it, and report_generated_code then decides what the rules report, which the tests simulate by
+/// setting GeneratedCodeAnalysisFlags, as the rules read the variable once per process.
///
public sealed class GeneratedCodeAnalysisTests
{
+ private const GeneratedCodeAnalysisFlags OptedIn = GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics;
+
private const string GeneratedCodeWithDiagnostic = """
//
abstract class Test
@@ -47,10 +48,33 @@ public Task AutoGeneratedHeader_NoDiagnosticByDefault()
return test.RunAsync();
}
+ [Fact]
+ public Task AutoGeneratedHeader_NoDiagnosticWhenTheRuleIsConfiguredButNotOptedIn()
+ {
+ // MA0017 does not analyze generated code, so configuring it to report in generated code is not enough
+ var test = new AbstractTypesTest();
+ test.TestState.SetConfiguration("MA0017.report_generated_code", "true");
+ test.TestCode = GeneratedCodeWithDiagnostic;
+
+ return test.RunAsync();
+ }
+
+ [Fact]
+ public Task AutoGeneratedHeader_NoDiagnosticWhenOptedInWithoutConfiguration()
+ {
+ // Opting in makes the rule analyze generated code, but its default is still to not report in it
+ var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
+ test.TestCode = GeneratedCodeWithDiagnostic;
+
+ return test.RunAsync();
+ }
+
[Fact]
public Task AutoGeneratedHeader_DiagnosticWhenTheRuleIsConfigured()
{
var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.SetConfiguration("MA0017.report_generated_code", "true");
test.TestCode = GeneratedCodeWithDiagnosticReported;
@@ -61,6 +85,7 @@ public Task AutoGeneratedHeader_DiagnosticWhenTheRuleIsConfigured()
public Task AutoGeneratedHeader_DiagnosticWhenAllTheRulesAreConfigured()
{
var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.SetConfiguration("MA.report_generated_code", "true");
test.TestCode = GeneratedCodeWithDiagnosticReported;
@@ -71,6 +96,7 @@ public Task AutoGeneratedHeader_DiagnosticWhenAllTheRulesAreConfigured()
public Task AutoGeneratedHeader_RuleConfigurationWinsOverTheGlobalOne()
{
var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.SetConfiguration(("MA.report_generated_code", "true"), ("MA0017.report_generated_code", "false"));
test.TestCode = GeneratedCodeWithDiagnostic;
@@ -81,24 +107,13 @@ public Task AutoGeneratedHeader_RuleConfigurationWinsOverTheGlobalOne()
public Task AutoGeneratedHeader_GlobalConfigurationDoesNotApplyToAnotherRule()
{
var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.SetConfiguration(("MA.report_generated_code", "false"), ("MA0053.report_generated_code", "true"));
test.TestCode = GeneratedCodeWithDiagnostic;
return test.RunAsync();
}
- [Fact]
- public Task AutoGeneratedHeader_NoDiagnosticWhenTheRuleIsConfiguredButOptedOut()
- {
- // MA0017 does not need generated code, so opting out prevents it from reporting in it
- var test = new AbstractTypesTest();
- test.GeneratedCodeAnalysisFlags = GeneratedCodeAnalysisFlags.None;
- test.TestState.SetConfiguration("MA0017.report_generated_code", "true");
- test.TestCode = GeneratedCodeWithDiagnostic;
-
- return test.RunAsync();
- }
-
[Fact]
public Task GeneratedFileName_NoDiagnosticByDefault()
{
@@ -117,6 +132,7 @@ public Test() { }
public Task GeneratedFileName_DiagnosticWhenTheRuleIsConfigured()
{
var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.SetConfiguration("MA0017.report_generated_code", "true");
test.TestState.Sources.Add(("/0/Test.g.cs", """
abstract class Test
@@ -129,10 +145,12 @@ abstract class Test
}
[Fact]
- public Task GeneratedCodeAttribute_TheFileIsWhatMatters()
+ public Task GeneratedCodeAttribute_TheFileIsWhatMattersWhenOptedIn()
{
// Only the file of the diagnostic is considered, so the attribute does not hide the code of a hand written file
var test = new AbstractTypesTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
+ test.TestState.SetConfiguration("MA0017.report_generated_code", "true");
test.TestCode = """
[System.CodeDom.Compiler.GeneratedCode("tool", "1.0")]
abstract class Test
@@ -144,6 +162,23 @@ abstract class Test
return test.RunAsync();
}
+ [Fact]
+ public Task GeneratedCodeAttribute_NoDiagnosticWhenNotOptedIn()
+ {
+ // A rule that does not analyze generated code follows the detection of Roslyn, which also considers the
+ // symbols marked with [GeneratedCode] generated
+ var test = new AbstractTypesTest();
+ test.TestCode = """
+ [System.CodeDom.Compiler.GeneratedCode("tool", "1.0")]
+ abstract class Test
+ {
+ public Test() { }
+ }
+ """;
+
+ return test.RunAsync();
+ }
+
[Fact]
public Task GeneratedCodeOption_TheFileIsNotGeneratedCode()
{
@@ -223,6 +258,7 @@ public Task SyntaxTreeRule_NoDiagnosticByDefault()
public Task SyntaxTreeRule_DiagnosticWhenTheRuleIsConfigured()
{
var test = new FixToDoTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.SetConfiguration("MA0026.report_generated_code", "true");
test.TestCode = """
//
@@ -234,11 +270,10 @@ public Task SyntaxTreeRule_DiagnosticWhenTheRuleIsConfigured()
}
[Fact]
- public Task GeneratedCodeIsAnalyzedWhenOptedOut()
+ public Task GeneratedCodeIsAnalyzedWhenNotOptedIn()
{
- // MA0053 needs generated code to be correct, so opting out cannot stop it from analyzing it
+ // MA0053 needs generated code to be correct, so it analyzes it even when nobody opts in
var test = new ClassMustBeSealedTest();
- test.GeneratedCodeAnalysisFlags = GeneratedCodeAnalysisFlags.Analyze;
test.TestState.Sources.Add(("/0/Test.cs", """
class Test
{
@@ -254,10 +289,11 @@ class Test2 : Test
}
[Fact]
- public Task GeneratedCodeIsAnalyzed()
+ public Task GeneratedCodeIsAnalyzedWhenOptedIn()
{
// The class declared in the generated file inherits from the other one, which cannot be sealed
var test = new ClassMustBeSealedTest();
+ test.GeneratedCodeAnalysisFlags = OptedIn;
test.TestState.Sources.Add(("/0/Test.cs", """
class Test
{