diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 0b46b329029e..48adec2c9a9a 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -84,6 +84,7 @@ Major source areas under [`src/`](../src/): | [`Containers/`](../src/Containers/) | `dotnet publish` container image support. | | [`Dotnet.Watch/`](../src/Dotnet.Watch/), [`Dotnet.Format/`](../src/Dotnet.Format/) | `dotnet watch` and `dotnet format` tools. | | [`Compatibility/`](../src/Compatibility/) | ApiCompat, GenAPI, API diff, and package validation tooling. | +| [`Microsoft.CodeAnalysis.NetAnalyzers/`](../src/Microsoft.CodeAnalysis.NetAnalyzers/) | The .NET code analyzers (`CA####` rules and their fixers), migrated from the retired `dotnet/roslyn-analyzers`. | | [`TemplateEngine/`](../src/TemplateEngine/) | Template engine libraries and authoring/discovery tools; see the [Template Engine overview](../documentation/TemplateEngine/README.md). | | [`Workloads/`](../src/Workloads/), [`Microsoft.DotNet.TemplateLocator/`](../src/Microsoft.DotNet.TemplateLocator/) | Workload manifests and installation, plus workload-provided template pack location. | | [`Layout/`](../src/Layout/) | Composes the final `dotnet` layout through [`redist.csproj`](../src/Layout/redist/redist.csproj). | diff --git a/.github/skills/add-net-analyzer/SKILL.md b/.github/skills/add-net-analyzer/SKILL.md new file mode 100644 index 000000000000..1ca6b5d1ff64 --- /dev/null +++ b/.github/skills/add-net-analyzer/SKILL.md @@ -0,0 +1,189 @@ +--- +name: add-net-analyzer +description: > + Add, port, or change a .NET code analysis rule (CA####) under + src/Microsoft.CodeAnalysis.NetAnalyzers. USE FOR: implementing a new CA analyzer and + its code fixer, porting a rule or PR from the retired dotnet/roslyn-analyzers repo, + allocating a diagnostic ID from DiagnosticCategoryAndIdRanges.txt, choosing + RuleLevel/severity/category, wiring resx + xlf strings, recording the rule in + AnalyzerReleases.Unshipped.md, regenerating the analyzer documentation/sarif files, and + writing MSTest analyzer/code-fix tests with the VerifyCS/VerifyVB harness. DO NOT USE + FOR: NETSDK#### MSBuild diagnostics (src/Tasks), CS####/BC#### compiler diagnostics or + IDE#### analyzers (dotnet/roslyn), or CONTAINER#### diagnostics (src/Containers). +license: MIT +--- + +# Add or port a .NET code analysis (CA) rule + +[`AGENTS.md`](../../../src/Microsoft.CodeAnalysis.NetAnalyzers/AGENTS.md) maps the tree and +carries the build/test commands and environment gotchas. Paths below are relative to `$NA` += `src/Microsoft.CodeAnalysis.NetAnalyzers`. + +| File | Load when | +|---|---| +| [`references/authoring-patterns.md`](references/authoring-patterns.md) | Writing the analyzer, the fixer, or the tests. | +| [`references/porting-from-roslyn-analyzers.md`](references/porting-from-roslyn-analyzers.md) | Porting a rule or PR from the archived `dotnet/roslyn-analyzers`. | + +## 1. Confirm the rule is wanted + +New CA rules are proposed and triaged before implementation — .NET API-related ones in +`dotnet/runtime` under the `code-analyzer` label. If an API review already decided the +category, severity, and whether a fixer is wanted, **follow that decision** and cite it in +the PR rather than re-deriving one. Ask before diverging from it. + +## 2. Allocate the diagnostic ID + +`DiagnosticCategoryAndIdRanges.txt` records only *merged* work, so the "next" ID is +routinely already claimed by an open PR or a concurrent branch. Run: + +```powershell +./.dotnet/dotnet .github/skills/add-net-analyzer/scripts/NextDiagnosticId.cs Performance +``` + +It scans forward from the end of the category's range until it finds an ID unclaimed in the +working tree, on any local branch, and in any open `dotnet/sdk` PR, prints the exact range +edit to apply, and reports anything it skipped. Exit `0` means every check ran, `1` means +the ID is proposed but open PRs went unchecked, and `2` is a hard failure — including "every +candidate in the scan window is already taken". The PR check matches titles and bodies +rather than diffs, so treat it as a strong heuristic, not proof. + +## 3. Implement the analyzer and fixer + +Read [`references/authoring-patterns.md`](references/authoring-patterns.md) first. + +The language-agnostic analyzer goes in +`$NA/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft..Analyzers//.cs`, +the fixer in `.Fixer.cs` beside it. Derive C#/VB types only where you genuinely need +syntax; those go at the same relative path inside +`$NA/src/Microsoft.CodeAnalysis.CSharp.NetAnalyzers/` or `…VisualBasic.NetAnalyzers/`. The +folder is the *rule group's* category — the `category:` you report can differ, and comes +from the `DiagnosticCategory` constants, never a raw string. Decisions that are yours +rather than pattern-matching an existing rule: + +- **`RuleLevel`** — `IdeSuggestion` unless you have a reason. `IdeHidden_BulkConfigurable` + is the first level that tolerates any false positives, and `BuildWarning` additionally + breaks builds under `TreatWarningsAsErrors`. +- **Whether the fix preserves semantics** — preserve them where doing so is trivial; where + it is not, the fix may still change them but must say so (`(may change semantics)`). + +## 4. Add the strings + +Append to the resx for the rule group — e.g. +`$NA/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/MicrosoftNetCoreAnalyzersResources.resx` +— one entry each for +`Title`, `Message`, `Description`, plus `CodeFixTitle` if there is +a fixer. Reference them via `CreateLocalizableResourceString(nameof(Title))` with +`using static ;` at the top of the namespace. + +`CodeFixTitle` names the *action* the fix performs ("Extract to static readonly +field"), not the problem the analyzer reports. Terms that must not be translated get +`{Locked="static readonly"}`; multiple terms are adjacent braces with no +separator. + +Then regenerate the 13 `.xlf` files in the `xlf/` subfolder beside it. Run the target +against the project that owns the resx — passing `/t:UpdateXlf` to `build.cmd` fails with +`MSB4057`, because Arcade applies the target to its own `Build.proj` rather than to the +projects being built: + +```powershell +./.dotnet/dotnet msbuild src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.csproj /t:UpdateXlf +``` + +## 5. Record the rule in release tracking + +Each of the three analyzer projects has its own `AnalyzerReleases.Unshipped.md` at its +root; the row goes in the project that *declares the descriptor*, which for a +language-agnostic rule is `Microsoft.CodeAnalysis.NetAnalyzers`. The `RS2000`/`RS2001` +meta-analyzers fail the build if you skip this, and they ship a code fix that writes the +row for you. + +``` +Rule ID | Category | Severity | Notes +--------|----------|----------|------- +CA#### | Performance | Info | Analyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca####) +``` + +`Severity` is the release-tracking severity for your `RuleLevel`, which is **not** always +the descriptor's `DiagnosticSeverity` — a disabled rule carries `Warning` on the descriptor +but tracks as `Disabled`: + +| `RuleLevel` | `Severity` column | +|---|---| +| `BuildError` | `Error` | +| `BuildWarning` | `Warning` | +| `IdeSuggestion`, `BuildWarningCandidate` | `Info` | +| `IdeHidden_BulkConfigurable` | `Hidden` | +| `Disabled`, `CandidateForRemoval` | `Disabled` | + +The `Documentation` link must carry the same rule ID as the row it sits on, lowercased to +match the help link `DiagnosticDescriptorHelper` derives for the descriptor. Nothing +validates this, and a row copy-pasted from the one above keeps *that* rule's ID, quietly +pointing readers at a different rule — check it by eye. The page itself 404s until your +docs PR lands, which is expected; don't paper over it by linking an existing rule's page. + +Rows move to `AnalyzerReleases.Shipped.md` at release time — don't move them yourself. + +## 6. Write the tests + +Tests go in +`$NA/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft..Analyzers//Tests.cs`, +mirroring the analyzer's folder. Full conventions are in +[`references/authoring-patterns.md`](references/authoring-patterns.md); the coverage bar: + +- C# fully; VB at least mainline positive and negative, fully if any VB-specific code + exists. Split by both behavior and language — a separate test method per language. +- When a fixer exists, write *every* test as a code-fix test, and include a trivia case. + If the diagnostic can nest, add a nested case — that is what catches a broken fix-all. +- The negative cases you reasoned about while designing. Reviewers will ask for them. + +## 7. Build and test + +```powershell +# ~10s incremental once .dotnet is provisioned; the first run provisions it. +./build.cmd -projects src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.slnx -c Debug + +./.dotnet/dotnet test src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests.csproj --filter "FullyQualifiedName~Tests" +``` + +Then `git status` and commit the regenerated files along with your change. `./build.sh` on +Linux/macOS; never pass `-restore`/`-build` alongside `-projects`. + +## 8. Validate the rule against real code + +Unit tests prove the rule fires; they say nothing about how often it is wrong, and that is +the gate on `RuleLevel`. Every level from `IdeSuggestion` up requires **no false +positives**, so before proposing one, run the built analyzer over a large real codebase +(`dotnet/runtime`, `dotnet/roslyn`) and triage every hit. Report the result in the PR. +[`docs/netcore-getting-started.md`](../../../src/Microsoft.CodeAnalysis.NetAnalyzers/docs/netcore-getting-started.md) +has the mechanics and the full definition of done. + +## 9. Documentation + +Each `CA####` is auto-assigned the help link +`https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca####`, +backed by `ca####.md` in +[`dotnet/docs`](https://github.com/dotnet/docs/tree/main/docs/fundamentals/code-analysis/quality-rules). +A docs PR is required **within one week** of the rule merging, or the implementation may be +reverted — a condition of the rule landing, not an optional follow-up. Raise it with the +user as outstanding work and leave the opening to them. Nothing in the build checks +that the page exists — `RulesMissingDocumentation.md` is generated with the link check +disabled and stays empty — so the docs PR is the only thing standing between the rule and a +dead help link in every user's IDE. + +## Checklist + +- [ ] Rule proposal reviewed and accepted, and the decision cited in the PR. +- [ ] ID unclaimed by any local branch or open PR, and the category's range extended to + cover it. +- [ ] `AnalyzerReleases.Unshipped.md` row added, its `Documentation` link matching the row's + own ID in lowercase. +- [ ] `.resx` edited and `.xlf` regenerated via `/t:UpdateXlf` — neither hand-edited. +- [ ] Regenerated `.md` / `.sarif.template` committed. +- [ ] Targeted test run passes, covering VB and the negative cases. +- [ ] Analyzer not narrowed to what the fixer handles, and no fix registered that leaves the + document unchanged. +- [ ] Fix-all handles nesting (not the batch fixer), if the diagnostic can overlap or nest. +- [ ] Every shape the fix offers itself on produces compiling code. +- [ ] Rule run against a real codebase and hits triaged, at `IdeSuggestion` or stronger. +- [ ] `dotnet/docs` PR raised with the user as a condition of merging. + diff --git a/.github/skills/add-net-analyzer/references/authoring-patterns.md b/.github/skills/add-net-analyzer/references/authoring-patterns.md new file mode 100644 index 000000000000..49f86be64214 --- /dev/null +++ b/.github/skills/add-net-analyzer/references/authoring-patterns.md @@ -0,0 +1,429 @@ +# Writing an analyzer and code fixer + +Public `Microsoft.CodeAnalysis` APIs throughout, so the shapes transfer to any analyzer +repo. **[In this repo](#in-this-repo) replaces several of them** — in the skeleton below +alone, `new DiagnosticDescriptor(...)` by `DiagnosticDescriptorHelper.Create(...)`, +`defaultSeverity` + `isEnabledByDefault` by `RuleLevel`, and +`compilation.GetTypeByMetadataName(...)` by `WellKnownTypeProvider`. Read that section +before copying from here. + +## Analyzer skeleton + +```csharp +[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] +public sealed class ExampleAnalyzer : DiagnosticAnalyzer +{ + internal static readonly DiagnosticDescriptor Rule = new( + id: "EXAMPLE0001", + title: ..., + messageFormat: ..., + category: ..., + defaultSeverity: DiagnosticSeverity.Info, + isEnabledByDefault: true); + + public override ImmutableArray SupportedDiagnostics { get; } = ImmutableArray.Create(Rule); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.RegisterCompilationStartAction(OnCompilationStart); + } + + private static void OnCompilationStart(CompilationStartAnalysisContext context) + { + if (context.Compilation.GetTypeByMetadataName("System.Span`1") is not { } spanType) + { + return; + } + + context.RegisterOperationAction(ctx => Analyze(ctx, spanType), OperationKind.Invocation); + } +} +``` + +Non-negotiable bits: + +- **No state in analyzer fields.** One analyzer instance is reused across many + compilations, so a field written during analysis is a correctness bug, not just a leak — + and immutability is not sufficient. A field must hold nothing derived from a compiler + API: an `ImmutableArray` is immutable and still roots the compilation + it came from. Compiler data that is itself constant is fine, such as the + `ImmutableArray` of kinds you register for. Everything per-compilation is + computed in the compilation-start action and reaches the nested callbacks by closure or + by a per-compilation state object. +- **All symbol lookup happens once, in the compilation-start action**, and the analyzer + returns *without registering* the inner action when a required type is absent. That is + what keeps the analyzer free on compilations that can't possibly match. Never look a type + up per-node, and never register the inner action before the bail-out checks. +- Prefer `IOperation` (`RegisterOperationAction`, `RegisterOperationBlockStartAction`) over + syntax actions: it is language-agnostic, so one analyzer covers C# and VB. The fixer does + not come along for free — it edits syntax, so expect per-language work there even when + the analyzer is shared. +- **Match with a pattern, not a check-then-extract pair.** + `if (operation is IInvocationOperation { TargetMethod: { Name: "Slice" } method })` keeps + the matched shape and the data you need as one expression; a `Kind` test followed by a + cast and a property read is two things that have to stay in sync. Where the shape isn't + obvious, one comment giving the source it matches (`// span.Slice(0, n)`) beats a prose + description of it. +- **`RegisterSymbolStartAction` when the rule needs per-symbol state and a decision at + symbol end**, in preference to a compilation-end action. Symbol-end diagnostics surface + live in the IDE; compilation-end ones never do — they appear only in a complete build. + Reach for `RegisterCompilationEndAction` only when the decision genuinely has to + aggregate across multiple symbol definitions, and put + `WellKnownDiagnosticTags.CompilationEnd` on the descriptor when you do. + +## Choosing a severity + +Severity is a claim about the code, not about how much you care. `Error` says *this is not +valid — its meaning is undefined and it cannot be what you wanted*. `Warning` says *this is +legal, but you almost certainly did not intend it, and you need to think about it either +way*. Both put the burden of acting on the user, so both require that the rule is right +essentially every time. Unit tests prove the rule fires; they say nothing about how often +it is wrong, so measure that against a large real codebase before proposing anything above +`Hidden`. + +| Default severity | Enabled | Use when | +|---|---|---| +| `Error` | yes | The code is broken, not merely suspicious. Reserved — effectively source-generator-only; needs owner sign-off. | +| `Warning` | yes | Legal code the user almost certainly did not mean, and will nearly always change. **No false positives** — it breaks builds under `TreatWarningsAsErrors`. | +| `Info` | yes | **The default for a new rule.** Still no false positives, but leaving it alone is a defensible choice. Worth surfacing in the IDE, not worth enforcing in CI. | +| `Hidden` | yes | The judgement is genuinely arguable, or the rule has some false positives. Effectively off, but still reachable through bulk configuration. | +| any | no | Opt-in only, by an explicit rule-ID severity entry. | + +## Code fixers + +- Export it: `[ExportCodeFixProvider(LanguageNames.CSharp), Shared]` with + `using System.Composition;`. It is a real MEF v2 export attribute and non-shared is the MEF + default, so `[Shared]` is load-bearing wherever the fixer is composed. It has no effect on + the analyzer-package path — there the host finds the type by reflection and constructs one + cached instance per reference — but write it anyway, as nearly every fixer here does. +- `equivalenceKey` must be a `nameof`, not a literal — it identifies the action for + fix-all and for the test harness. +- **The fix title describes the action**, not the problem: *"Extract to a static readonly + field"*, not a restatement of the analyzer title. It is its own localizable string. +- Build edits with `DocumentEditor` + `SyntaxGenerator` rather than raw `SyntaxFactory` — + it keeps a fixer language-agnostic and gives you a single changed document at the end. + It does **not** move trivia for you: when you replace a node, carry the original's trivia + across explicitly (`WithTriviaFrom`), or the user loses their comments. +- **Parenthesize any expression you substitute into an arbitrary context.** Replacing + `And(y, z)` with `y & z` inside `x * …` silently changes the meaning. Add + `Simplifier.Annotation` to the parentheses you introduce: the code-fix pipeline runs the + simplifier over annotated nodes and drops the ones that turn out to be redundant, so you + can parenthesize unconditionally rather than reasoning about precedence at each site. + Check [In this repo](#in-this-repo) before hand-rolling this — there is a helper that + applies the annotation for you. +- **Preserve semantics where doing so is trivial.** Precedence (see the bullet above), operand + and evaluation order, overflow, rounding — if the fix can keep the original meaning without + meaningful extra work, it should. Arithmetic deserves the most care, because a rewrite there + changes results silently instead of failing to compile. Where preserving it is not trivial + the fix may still change semantics, but it must say so — suffix the action with + `(may change semantics)`, and offer the semantics-preserving fix alongside it when both + readings are reasonable. The failure mode is a title that reads as pure cleanup. +- **Make a reasonable effort to produce valid output.** If the fix can reach a correct form with + the information it has, it should; most rewrites have one clear target and should generate + valid code for the shapes they handle. That does not mean the fixed document must always + compile — the original code may already be broken, or further user edits may still be + required, and neither is a reason to decline. A fixer that never produces correct code in any + shape is probably not worth offering; one that falls short in some edge cases is still + valuable. The failure mode is withholding a useful fix because it cannot guarantee + compilation. +- Where the fixer *is* language-agnostic, VB is cheap — export it for both languages and add + mainline VB tests. If it needs language-specific syntax APIs, the VB fixer is optional. + +### Report the diagnostic; decide separately whether you can fix it + +Whether the code is worth reporting and whether you can rewrite it are different questions. +A shape you cannot fix is still worth a diagnostic — never narrow the analyzer to what the +fixer happens to handle. What the fixer must not do is register an action it cannot carry +out. Registering nothing is the correct outcome for an unfixable shape: the user sees the +diagnostic with no fix offered. Registering and then returning the document unchanged is +the bug — that is the lightbulb that does nothing. + +So the eligibility check runs *before* `RegisterCodeFix`, and where it needs semantics the +analyzer and the fixer share one helper rather than each growing their own: + +```csharp +// core: the semantics, shared by every language +protected virtual bool IsCandidate(IInvocationOperation invocation) => ...; + +// C#: the syntax it needs, then defer +protected override bool IsCandidate(IInvocationOperation invocation) +{ + if (invocation.Syntax is not InvocationExpressionSyntax) + { + return false; + } + + return base.IsCandidate(invocation); +} +``` + +Binding is not a shape guarantee — error recovery will happily bind an invocation with too +few or too many arguments, so `symbol is not null` does not mean +`invocation.Arguments.Length == 2`. Expose the check as a shared helper and call it from +both the analyzer and the fixer. `Debug.Assert` is not that validation: everything that +consumes a shipped analyzer runs release builds, so an assert catches nothing outside your +own tests. + +This is not a licence to drop the fixer's own defensive checks. A fixer re-finds its nodes +in the *current* document, which may have changed since the diagnostic was computed, so +pattern-match what you find and `return` when it doesn't match. The distinction is that +those guards handle a stale span, not an eligibility question you should have answered +before registering. + +### Flowing data from the analyzer to the fixer + +Use `Diagnostic.Properties` (`ImmutableDictionary`), or additional +`Location`s. **Not `CustomTags`** — tags describe the *rule*, not an individual report. + +```csharp +// analyzer +var properties = ImmutableDictionary.Empty.Add(ReplacementKey, replacement); +context.ReportDiagnostic(Diagnostic.Create(Rule, location, properties, messageArgs)); + +// fixer +if (!diagnostic.Properties.TryGetValue(ReplacementKey, out string? replacement)) +{ + return; +} +``` + +Keep it small. The more the analyzer stores for the fixer, the more it holds alive; the +fixer can usually recompute from the span the diagnostic already carries. + +### Fix-all + +`WellKnownFixAllProviders.BatchFixer` is the cheap default, and most fixers use it, but it +is the *simplest* implementation rather than a good one. It runs every fix independently +against the original document and merges the resulting edits. That means: + +- N independent forks, each running the code-action cleanup pass — slow. +- Real **incorrectness**, but not everywhere. Merging happens at the *text* level, through + an interval tree of `TextChange`s, so the question is whether the edits conflict as spans + — not whether the diagnostics share a parent node. What conflicts: + - **Nested or overlapping rewrites.** For `Add(x, Add(y, z))` one fix wants + `x + Add(y, z)` and the other `Add(x, y + z)`; the spans overlap. + - **The same node rewritten into two different shapes** — one overload added per pass. + - **Two insertions at the same position.** An empty span cannot overlap anything, so + these are easy to miss, but the merger rejects them as ambiguous: it cannot know which + order you meant. This is the usual reason a fixer that *adds* a member, overload, or + argument fixes only one diagnostic per pass. + + And the loss is per-fix, not per-edit: one conflicting hunk discards **every** change + that fix made to the document. + + What the merger sees is the *diff* between the original and fixed documents, not the edit + you made. Those are not the same span: the code-action cleanup pass can reflow a region + wider than the edit, so two rewrites that look disjoint still collide. Measured example — + a fixer whose fix is a single `RemoveNode` merges 33 diagnostics cleanly when they are all + field initializers, and fails at 18 once two property initializers are in the mix. The + shape of the fix does not tell you the width of the diff, so treat the list above as + *where to look first*, never as a substitute for the test below. + +If your diagnostics can conflict this way, use `FixAllProvider.Create` and implement the +pattern yourself: + +1. Fix all diagnostics in a document in a single callback. +2. Order them by `Location.SourceSpan.Start` **descending**, so inner nodes are handled + before the outer nodes containing them. If two diagnostics can share a start — a chained + call reported at two different lengths — add a shorter-span-first tie-break, since a sort + on start alone leaves those in enumeration order. +3. Apply each through `editor.ReplaceNode(node, (currentNode, generator) => ...)` — the + lambda overload, so outer rewrites observe the inner ones. + +The caveat inherited from `FixAllProvider.Create` is that the fix must stay within the +document the diagnostic is in; anything cross-file needs a hand-written `FixAllProvider`. + +A shared base class that packages this is worth reaching for, but check how it registers +before you derive from one. If its `RegisterCodeFixesAsync` is sealed and offers the action +for every diagnostic in `context.Diagnostics`, it is only suitable when *every* diagnostic +the rule reports is fixable. A rule whose single ID also covers shapes the fixer cannot +handle needs conditional registration, so it has to register the fix itself and use +`FixAllProvider.Create` directly — otherwise it surfaces a lightbulb that does nothing. + +The `Microsoft.CodeAnalysis.Testing` harness exercises fix-all-in-document/project/solution +separately from the iterative case, so a batch-fixer correctness bug shows up as +`Expected '1' iterations but found '2' iterations` — that is a real bug, not a test +artifact. Likewise a `CodeActionValidationMode` failure means your fix produced a tree that +differs from what the compiler would parse from the same text; fix the fix, don't lower the +mode. + +A multi-diagnostic test that *passes* proves nothing on its own, because "fix-all converged +in one pass" and "fix-all never ran" look identical from the outside. Before concluding a +fixer is fine, run the positive control: set `NumberOfFixAllIterations = 2` against the +unchanged fixer and confirm it fails with `Expected '2' iterations but found '1'`. + +A test that *fails* needs reading for the same reason. Confirm the message is an iteration +count and not a content mismatch: a verbatim string literal written with `\n` into a repo +whose `.cs` files are CRLF produces a diff that reads exactly like a fix-all bug. + +If you have a correct `FixAllProvider` and *still* see that iteration failure, suspect the +rewrite itself. Removing several nodes from one `SeparatedSyntaxList` by chaining +`.Remove(node)` silently no-ops after the first call: `Remove` returns a new list whose +surviving nodes are re-created, so a later `Remove` passed an original node reference no +longer finds it. Collect the indices and `RemoveAt` in descending order instead. The same +hazard applies to any rewrite that holds node references across an edit — re-find or +re-index rather than reusing them. + +## Tests + +The `Microsoft.CodeAnalysis.Testing` harness is the standard way to test both. Give each +test file a per-language verifier alias rather than naming the harness types at every call +site — that is the general recommendation, not a local convention: + +```csharp +using VerifyCS = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier< + ExampleAnalyzer, + ExampleFixer, + Microsoft.CodeAnalysis.Testing.DefaultVerifier>; +``` + +It is test-framework agnostic; the snippet below omits the parameterized-test attribute +your framework supplies. + +```csharp +public async Task Match_ReportsDiagnostic(string typeName) +{ + // lang=C#-test + string code = $$""" + public class C + { + public void M() => [|Target<{{typeName}}>()|]; + } + """; + + await VerifyCS.VerifyAnalyzerAsync(code); +} +``` + +- **Use raw string literals for embedded sources.** Not for the escaping — for the + indentation. A `@"..."` source has to start at column 0, so it collides with the test + method's own indentation and becomes hard to scan. The `// lang=C#-test` comment gives + the IDE syntax colorization inside the literal. +- Markup: `[|...|]` when the rule has a single ID; `{|EXAMPLE0001:...|}` when the file + exercises more than one ID or you need to be explicit. With a single rule, keep the ID + out of test *names* too. Use `Diagnostic(Rule).WithLocation(...).WithArguments(...)` only + when asserting message arguments. +- **Collapse mechanical permutations into data rows.** When the scaffolding is identical + from test to test and only a type or method name varies, N near-identical test methods + are noise; the rows *are* the signal, lining the cases up where you can see at a glance + which are covered and which are missing. The limit: no logic in the test body driven by + the data — only when input and expected output are mechanically transformable. +- **Split by both behavior and language.** One scenario per test method, and a separate + method per language, so a failure says immediately whether the bug is language-specific. + Split a large rule across partial-class files by scenario rather than one enormous file. +- **Use realistic scenarios** — call APIs that would actually accept the input you're + passing. A contrived call that couldn't compile in real code is a weak test. +- **`LanguageVersion` and `ReferenceAssemblies` have defaults you will outgrow.** The + harness pins an older C# version than you probably expect, so a test source using newer + syntax must set it explicitly. The reference set likewise only carries the framework — + add the packages your scenario needs. +- Cover both languages. C# gets full coverage; VB needs at least mainline positive and + negative cases, and full coverage if any syntax-specific code exists. +- **When a fixer exists, write every test as a code-fix test.** A fix test with identical + input and expected output asserts "diagnostic but no fix offered" or "no diagnostic"; a + differing pair asserts both the diagnostic and the fix output. Don't split analyzer-only + and fixer-only test classes. +- **Enumerate the contexts where the rewrite is *invalid*, and pin each with a no-fix + test.** The harness compiles the fixed output, but that only proves the shapes you thought + to write down compile — its strictness is not coverage. Work out what the new form cannot + do that the old one could: a conversion the old type had, a ref struct in an expression + tree or held across an `await`, an overload that only binds the original type. If every + fix test happens to use `var` or discard the result, that is the eligibility gap showing + rather than a coincidence. +- **Add trivia tests** — a source with comments and blank lines around the fixed node. +- Negative tests are not optional — the false-positive cases you thought about during + design are the ones a reviewer will ask for. +- **Shapes that earn a test of their own for any invocation-shaped rule**, positive or + negative depending on what your rule does with them: + - **Nested occurrences** (`Add(x, Add(y, z))`) — the case that catches a broken fix-all. + - **Named and reordered arguments** (`Divide(right: y, left: x)`). `IOperation` exposes + arguments in *evaluation* order — syntactic order in C#, parameter order in VB — so a + fixer that indexes `Arguments[0]` positionally reads the wrong argument in C# while the + same code stays correct in VB. + - **The match nested inside another expression** (`Console.WriteLine(X.Add(a, b))`) — so + you find the invocation node, not the enclosing argument node, and so you notice a + missing parenthesization. + +## Performance + +Analyzers run on every keystroke in the IDE and on every build, so small savings — +allocations especially — add up. Beyond the usual (no LINQ or allocating closures on +per-node paths, cheapest predicate first, don't re-query the semantic model for something +the `IOperation` already carries): + +- **Scope every cache to the compilation.** The closure of the + `RegisterCompilationStartAction` lambda is the right holder: when the IDE drops a + compilation it drops the registered actions with it, and the caches go too. A cache in a + `static` or in an analyzer field outlives the compilation and keeps it alive. +- **Cache negative results too.** If you look up whether a symbol carries an attribute, + cache the "no" as well, or every subsequent hit repeats the lookup. +- **When the rule is trying to match an invocation to a set of library methods, build the + lookup once.** If the rule is trying to find all invocations of a specific set of library + methods (or generally all references to a library member), where each member will have a + slightly different set of applied rules, build the mapping of member->kind up front. The + per-node action is then one dictionary probe rather than N `Contains` calls on every + invocation in the compilation. +- Don't compare symbols by `ToDisplayString()` or `Name`. It allocates, and it's wrong for + identity — use `SymbolEqualityComparer.Default`. Compare `OriginalDefinition` only when + you mean to ignore construction; it equates `List.Add` with `List.Add`. + +## In this repo + +`src/Microsoft.CodeAnalysis.NetAnalyzers` wraps several of the calls above; paths below are +relative to it. Use the wrapper, not the raw API: + +| General API above | Use here instead | +|---|---| +| `new DiagnosticDescriptor(...)` | `DiagnosticDescriptorHelper.Create(...)` — derives the `learn.microsoft.com` help link from the lowercased ID and applies the telemetry/FxCop custom tags. | +| `defaultSeverity` + `isEnabledByDefault` | `RuleLevel` (`src/Utilities/Compiler/RuleLevel.cs`). Its XML doc is the rubric reviewers apply; `IdeSuggestion` is the default for a new rule. | +| `compilation.GetTypeByMetadataName(...)` | `WellKnownTypeProvider.GetOrCreate(compilation).GetOrCreateTypeByMetadataName(...)`, with the metadata name added to `src/Utilities/Compiler/WellKnownTypeNames.cs`. | +| `arguments[i]` to reach parameter `i` | `arguments.GetArgumentForParameterAtIndex(i)` (`src/Utilities/Compiler/Extensions/IOperationExtensions.cs`) — matches on `Parameter.Ordinal`, so it survives named and reordered arguments. Use the `Try` overload where the parameter may not be matched. | +| hand-rolled `FixAllProvider.Create` | Derive from [`OrderedCodeFixProvider`](../../../../src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/OrderedCodeFixProvider.cs) — it seals `RegisterCodeFixesAsync` and sorts descending by span start; you supply `FixableDiagnosticIds`, `CodeActionTitle`, `CodeActionEquivalenceKey`, and `FixAllCoreAsync`. It has no same-start tie-break, so apply that yourself in `FixAllCoreAsync` if your diagnostics can share a start. Its sealed registration is unconditional, so it does not fit a rule that also reports shapes the fixer cannot handle. | +| manual parenthesizing | `Analyzer.Utilities.Extensions.SyntaxGeneratorExtensions.Parenthesize` — applies `Simplifier.Annotation` for you. C#-only (`src/Utilities/Compiler.CSharp/`); a VB fixer parenthesizes by hand. | +| `HashSet` / `Dictionary` on hot paths | `src/Utilities/Compiler/PooledObjects/`. Must be freed on every path — prefer `using var x = PooledHashSet.GetInstance();`. | +| reading `AnalyzerConfigOptions` directly | `src/Utilities/Compiler/Options/` (`AnalyzerOptionsExtensions`, `EditorConfigOptionNames`), e.g. `context.Options.MatchesConfiguredVisibility(Rule, symbol, compilation)`. Reuse an existing option name before adding one, and document new ones in `docs/analyzer-configuration.md`. | + +`DiagnosticDescriptorHelper.Create` also requires `isPortedFxCopRule` and `isDataflowRule`; +a new rule passes `false` for both. `isDataflowRule: true` is for rules built on the +flow-analysis framework in `src/Utilities/FlowAnalysis/` — they ship `Disabled` because +flow analysis costs far more than an `IOperation` walk, and writing one is a separate +undertaking covered by +[`docs/writing-dataflow-analysis-based-analyzers.md`](../../../../src/Microsoft.CodeAnalysis.NetAnalyzers/docs/writing-dataflow-analysis-based-analyzers.md). +The helper also takes `isReportedAtCompilationEnd`, which applies the compilation-end tag +for you. + +**Tests are MSTest**, not xUnit (`[TestMethod]`, `[DataRow]`, `[DynamicData]`), and the +verifier alias points at the `Test.Utilities` wrapper, which bakes in `DefaultVerifier` so +the alias takes two type arguments rather than three: + +```csharp +using VerifyCS = Test.Utilities.CSharpCodeFixVerifier< + Microsoft.NetCore.Analyzers..Analyzer, + Microsoft.NetCore.CSharp.Analyzers..CSharpFixer>; +``` + +which is what supplies `VerifyCS.VerifyAnalyzerAsync` / `VerifyCodeFixAsync`. +`ReferenceAssemblies` defaults to `AdditionalMetadataReferences.Default`; pick the member +carrying the packages your scenario needs. `LanguageVersion` defaults to `CSharp7_3` in +`CSharpCodeFixVerifier.Test` — raw string literals in the *test file* are fine, that's the +test project's own language version. + +**Validating against a real codebase**: the analyzers ship inside the SDK layout now, so +point the target repo at a locally built SDK or overwrite +`/sdk//Sdks/Microsoft.NET.Sdk/analyzers/` — not the NuGet cache. + +## Further reading + +In-repo docs under `src/Microsoft.CodeAnalysis.NetAnalyzers/docs/`, each worth reading only +when it applies: +[`netcore-getting-started.md`](../../../../src/Microsoft.CodeAnalysis.NetAnalyzers/docs/netcore-getting-started.md) +(definition of done, validating against a real codebase, debugging in VS), +[`guidelines-for-new-rules.md`](../../../../src/Microsoft.CodeAnalysis.NetAnalyzers/docs/guidelines-for-new-rules.md) +(proposal and documentation requirements), +[`analyzer-configuration.md`](../../../../src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-configuration.md) +(long; the `.editorconfig` option catalog — grep it for a specific option rather than +reading it through), and +[`writing-dataflow-analysis-based-analyzers.md`](../../../../src/Microsoft.CodeAnalysis.NetAnalyzers/docs/writing-dataflow-analysis-based-analyzers.md) +(only if your rule needs the dataflow framework). diff --git a/.github/skills/add-net-analyzer/references/porting-from-roslyn-analyzers.md b/.github/skills/add-net-analyzer/references/porting-from-roslyn-analyzers.md new file mode 100644 index 000000000000..0446cb46d52e --- /dev/null +++ b/.github/skills/add-net-analyzer/references/porting-from-roslyn-analyzers.md @@ -0,0 +1,61 @@ +# Porting from dotnet/roslyn-analyzers + +`dotnet/roslyn-analyzers` is retired: its default branch is now `archive`, which carries no +source tree, so an upstream PR's paths can no longer be corrected at the source. + +## Reaching the archived source + +`main` still exists and still carries `src/`, so `?ref=main` works. Pin the PR's merge SHA +instead when you want the tree as the PR saw it: + +```powershell +gh api "repos/dotnet/roslyn-analyzers/contents/?ref=" --jq .download_url +# or, for a whole PR: +gh pr view --repo dotnet/roslyn-analyzers --json commits,files +git fetch https://github.com/dotnet/roslyn-analyzers +``` + +Only the **NetAnalyzers** package migrated. `Microsoft.CodeAnalysis.Analyzers`, +`PublicApiAnalyzers`, `BannedApiAnalyzers`, `Roslyn.Diagnostics.Analyzers`, +`Text.Analyzers`, and `PerformanceSensitiveAnalyzers` are not in `dotnet/sdk`. + +## Path translation + +`$NA` is `src/Microsoft.CodeAnalysis.NetAnalyzers`. + +| roslyn-analyzers | dotnet/sdk | +|---|---| +| `src/NetAnalyzers/Core/` | `$NA/src/Microsoft.CodeAnalysis.NetAnalyzers/` | +| `src/NetAnalyzers/CSharp/` | `$NA/src/Microsoft.CodeAnalysis.CSharp.NetAnalyzers/` | +| `src/NetAnalyzers/VisualBasic/` | `$NA/src/Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers/` | +| `src/NetAnalyzers/UnitTests/` | `$NA/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/` | +| `src/Utilities/` | `$NA/src/Utilities/` | +| `src/Test.Utilities/` | `$NA/tests/Test.Utilities/` | +| `src/NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.sarif` | `$NA/src/Microsoft.CodeAnalysis.NetAnalyzers.sarif.template` | +| `RoslynAnalyzers.sln` | `$NA/Microsoft.CodeAnalysis.NetAnalyzers.slnx` | + +Below the project root the folder layout is unchanged, so +`src/NetAnalyzers/Core/Microsoft.NetCore.Analyzers/Runtime/Foo.cs` maps to +`$NA/src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/Foo.cs`. + +`src/Utilities.UnitTests/` did not migrate — a ported change to `src/Utilities/` has no +test project to land in. + +## What reliably breaks on a straight copy + +- **Tests are MSTest here, xUnit upstream.** The + [`migrate-xunit-to-mstest`](../../migrate-xunit-to-mstest/SKILL.md) skill carries the + attribute, assertion, and lifecycle mapping — load it rather than re-deriving one. Two + things it cannot know about this repo: `xunit.TheoryData<...>` maps to the + `Test.Utilities.TheoryData<...>` shim (up to 4 type args, already an + `IEnumerable` for `[DynamicData]`) rather than to a hand-written sequence, and + a skipped test cites an issue — `[TestMethod]` + `[Ignore("https://github.com/dotnet/sdk/issues/N")]`. + +- **Rule IDs drift.** The ID the upstream PR used is very likely taken now. Re-allocate + with `scripts/NextDiagnosticId.cs` and rename every occurrence — analyzer, + `AnalyzerReleases.Unshipped.md`, test markup (`{|CA####:...|}`), and doc comments. +- **Nullable reference warnings are errors.** Upstream code predating a nullable + annotation change will not compile. +- **`RS0030` (banned `new DiagnosticDescriptor(...)`) did not migrate.** It is a + convention here rather than an enforced rule; still use + `DiagnosticDescriptorHelper.Create`. diff --git a/.github/skills/add-net-analyzer/scripts/NextDiagnosticId.cs b/.github/skills/add-net-analyzer/scripts/NextDiagnosticId.cs new file mode 100644 index 000000000000..796678127318 --- /dev/null +++ b/.github/skills/add-net-analyzer/scripts/NextDiagnosticId.cs @@ -0,0 +1,270 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Proposes the next free CA diagnostic ID for a category and reports in-flight collisions. +// +// dotnet NextDiagnosticId.cs +// +// DiagnosticCategoryAndIdRanges.txt records only *merged* work, so the "next" ID is +// frequently already claimed by an open PR or a concurrent branch. This scans forward from +// the end of the category's range until it finds one unclaimed in the working tree, on any +// local branch, and in any open dotnet/sdk PR, then prints the range edit that covers it. +// +// The open-PR check searches PR titles and bodies, not diffs, so an ID used only in changed +// source can slip through. It is a strong heuristic, not a guarantee. +// +// Exit codes: +// 0 all checks ran +// 1 ID proposed, but the open-PR check did not run or did not complete +// 2 usage error, unknown category, git failure, or no free ID in the scan window + +using System.ComponentModel; +using System.Diagnostics; +using System.Globalization; +using System.Text.Json; +using System.Text.RegularExpressions; + +const string AnalyzerRoot = "src/Microsoft.CodeAnalysis.NetAnalyzers"; +const int ScanLimit = 25; + +if (args.Length != 1) +{ + Console.Error.WriteLine("usage: dotnet NextDiagnosticId.cs "); + return 2; +} + +string category = args[0]; + +(int gitExit, string repoRootOutput) = Exec("git", "rev-parse", "--show-toplevel"); + +if (gitExit != 0) +{ + Console.Error.WriteLine("error: not inside a git repository."); + return 2; +} + +string repoRoot = repoRootOutput.Trim(); +string rangesFile = Path.Combine(repoRoot, AnalyzerRoot, "src", "Utilities", "Compiler", "DiagnosticCategoryAndIdRanges.txt"); +string[] lines = File.ReadAllLines(rangesFile); +string? line = Array.Find(lines, l => Regex.IsMatch(l, $@"^\s*{Regex.Escape(category)}\s*:")); + +if (line is null) +{ + // Only categories with a CA range can be allocated from; the rest carry RS ranges. + string known = string.Join(", ", lines + .Where(l => Regex.IsMatch(l, @"^\w+\s*:.*\bCA\d+")) + .Select(l => l.Split(':')[0])); + + Console.Error.WriteLine($"error: category '{category}' not found. Allocatable categories: {known}"); + return 2; +} + +// The range to extend is the last CA segment on the line; earlier segments are legacy or +// prefix entries (e.g. 'Performance: HA, CA1800-CA1877'). +string? lastRange = line.Split(':', 2)[1] + .Split(',') + .Select(segment => segment.Trim()) + .LastOrDefault(segment => Regex.IsMatch(segment, @"^CA\d+(-CA\d+)?$")); + +if (lastRange is null) +{ + Console.Error.WriteLine($"error: no CA range found on line: {line}"); + return 2; +} + +string[] bounds = lastRange.Split('-'); +string rangeStart = bounds[0]; +int rangeEnd = int.Parse(bounds[^1]["CA".Length..], CultureInfo.InvariantCulture); + +bool ghAvailable = Exec("gh", "--version").ExitCode == 0; +bool prCheckComplete = ghAvailable; +string? gitFailure = null; + +// Concurrent branches, including those checked out in other worktrees. +string[] branches = Exec("git", "-C", repoRoot, "for-each-ref", "--format=%(refname)", "refs/heads") + .Output + .Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + +List<(string Id, string Reason)> skipped = []; +string? proposed = null; + +for (int candidate = rangeEnd + 1; candidate <= rangeEnd + ScanLimit; candidate++) +{ + string id = $"CA{candidate}"; + string? reason = ClaimedBy(id); + + if (gitFailure is not null) + { + Console.Error.WriteLine($"error: {gitFailure}"); + return 2; + } + + if (reason is null) + { + proposed = id; + break; + } + + skipped.Add((id, reason)); +} + +if (proposed is null) +{ + Console.Error.WriteLine($"error: no free ID in CA{rangeEnd + 1}..CA{rangeEnd + ScanLimit} for '{category}'; every candidate is claimed."); + return 2; +} + +int rangeAt = line.LastIndexOf(lastRange, StringComparison.Ordinal); +string updatedLine = $"{line[..rangeAt]}{rangeStart}-{proposed}{line[(rangeAt + lastRange.Length)..]}"; + +Console.WriteLine($"Category : {category}"); +Console.WriteLine($"Current range : {lastRange}"); +Console.WriteLine($"Proposed ID : {proposed}"); + +if (skipped.Count > 0) +{ + Console.WriteLine(); + Console.WriteLine("Skipped (already claimed):"); + + foreach ((string id, string reason) in skipped) + { + Console.WriteLine($" {id} - {reason}"); + } +} + +Console.WriteLine(); +Console.WriteLine("Apply to DiagnosticCategoryAndIdRanges.txt:"); +Console.WriteLine($" - {line}"); +Console.WriteLine($" + {updatedLine}"); +Console.WriteLine(); + +if (ghAvailable && prCheckComplete) +{ + Console.WriteLine($"{proposed} is unclaimed in the working tree, on local branches, and in open dotnet/sdk PR titles and bodies."); + return 0; +} + +Console.WriteLine($"{proposed} is unclaimed in the working tree and on local branches."); +Console.Error.WriteLine(ghAvailable + ? "warning: a dotnet/sdk PR query failed; open PRs were not fully checked." + : "warning: gh is not on PATH; open PRs were not checked."); + +return 1; + +string? ClaimedBy(string id) +{ + // No revision, so this searches the working tree: the current branch plus uncommitted + // work. --untracked also covers files created but not yet staged. + if (GitGrep(["-C", repoRoot, "grep", "-l", "--untracked", "--fixed-strings", id, "--", AnalyzerRoot]) is string inTree) + { + return $"working tree ({inTree})"; + } + + if (branches.Length > 0 && + GitGrep(["-C", repoRoot, "grep", "-l", "--fixed-strings", id, .. branches, "--", AnalyzerRoot]) is string onBranch) + { + return $"branch ({onBranch})"; + } + + if (gitFailure is not null || !ghAvailable) + { + return null; + } + + (int exitCode, string output) = Exec("gh", "pr", "list", "--repo", "dotnet/sdk", "--state", "open", "--search", id, "--json", "number,title"); + + if (exitCode != 0) + { + prCheckComplete = false; + return null; + } + + return FirstOpenPr(output) is string pr ? $"open PR ({pr})" : null; +} + +string? GitGrep(string[] arguments) +{ + if (gitFailure is not null) + { + return null; + } + + (int exitCode, string output) = Exec("git", arguments); + + // git grep exits 0 on a match and 1 on none; anything else is a real failure, and + // silently reading it as "no match" would hand back an ID that is already taken. + if (exitCode is not (0 or 1)) + { + gitFailure = $"git grep exited with {exitCode}. Arguments: {string.Join(' ', arguments)}"; + return null; + } + + return exitCode == 0 ? FirstLine(output) : null; +} + +string? FirstOpenPr(string json) +{ + if (string.IsNullOrWhiteSpace(json)) + { + prCheckComplete = false; + return null; + } + + try + { + using JsonDocument document = JsonDocument.Parse(json); + + if (document.RootElement.ValueKind != JsonValueKind.Array) + { + prCheckComplete = false; + return null; + } + + if (document.RootElement.GetArrayLength() == 0) + { + return null; + } + + JsonElement pr = document.RootElement[0]; + return $"#{pr.GetProperty("number")} {pr.GetProperty("title").GetString()}"; + } + catch (JsonException) + { + prCheckComplete = false; + return null; + } +} + +static string FirstLine(string text) => text.Split('\n', StringSplitOptions.RemoveEmptyEntries)[0].Trim(); + +static (int ExitCode, string Output) Exec(string fileName, params string[] arguments) +{ + ProcessStartInfo startInfo = new() + { + FileName = fileName, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + + foreach (string argument in arguments) + { + startInfo.ArgumentList.Add(argument); + } + + try + { + using Process process = Process.Start(startInfo)!; + + // Drain stderr concurrently so a chatty child can't fill its pipe and deadlock. + Task stderr = process.StandardError.ReadToEndAsync(); + string output = process.StandardOutput.ReadToEnd(); + process.WaitForExit(); + stderr.Wait(); + + return (process.ExitCode, output); + } + catch (Win32Exception) + { + return (-1, ""); + } +} diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/AGENTS.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/AGENTS.md index e818a7543df1..b3bfcaa2b3eb 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/AGENTS.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/AGENTS.md @@ -1,25 +1,78 @@ # NetAnalyzers Agent Instructions Guidance for changes under `src/Microsoft.CodeAnalysis.NetAnalyzers` — the .NET code -analyzers (the `CA####` rules). +analyzers (the `CA####` rules), migrated here from the retired `dotnet/roslyn-analyzers`. + +For the end-to-end workflow of adding or porting a rule, use the +[`add-net-analyzer`](../../.github/skills/add-net-analyzer/SKILL.md) skill. ## Where things live +Paths are relative to `src/Microsoft.CodeAnalysis.NetAnalyzers`. + | Path | Role | |------|------| -| `src/Microsoft.CodeAnalysis.NetAnalyzers` (+ `CSharp`, `VisualBasic`) | The analyzer assemblies. Rules live under here grouped into `Microsoft.CodeQuality.Analyzers`, `Microsoft.NetCore.Analyzers`, `Microsoft.NetFramework.Analyzers`. | -| `src/Utilities/`| Shared analyzer/flow-analysis helpers linked into the analyzers. | -| `tests/` | Tests and the verifier harness. | -| `tools/GenerateDocumentationAndConfigFiles` | Generates rule docs, rulesets, editorconfig, and SARIF. | +| `src/Microsoft.CodeAnalysis.NetAnalyzers/` (+ `…CSharp.NetAnalyzers/`, `…VisualBasic.NetAnalyzers/`) | The analyzer assemblies. Rules are grouped into `Microsoft.CodeQuality.Analyzers`, `Microsoft.NetCore.Analyzers`, `Microsoft.NetFramework.Analyzers`, then into a category folder. | +| `src/Utilities/{Compiler,Compiler.CSharp,FlowAnalysis,Workspaces}` | Shared analyzer/flow-analysis helpers, linked in as shared projects (`.shproj`) rather than referenced as assemblies. | +| `src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj` | Packaging **and** the generated-file regeneration target. | +| `tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/` | Tests, mirroring the analyzer folder structure. | +| `tests/Test.Utilities/` | The `VerifyCS`/`VerifyVB` verifier harness. | +| `tools/GenerateDocumentationAndConfigFiles/` | Generates rule docs, rulesets, editorconfig, and SARIF. | +| `docs/` | Rule-design guidance, the `.editorconfig` option reference, and the dataflow-analysis framework walkthrough. | + +## Build & test + +```powershell +./build.cmd -projects src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.slnx -c Debug + +./.dotnet/dotnet test src/Microsoft.CodeAnalysis.NetAnalyzers/tests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests/Microsoft.CodeAnalysis.NetAnalyzers.UnitTests.csproj --filter "FullyQualifiedName~Tests" +``` + +`./build.sh` on Linux/macOS. Do **not** pass `-restore`/`-build` alongside `-projects` — +the driver already implies them and the combination fails. To regenerate `.xlf` after a +`.resx` change, run `/t:UpdateXlf` against the project that owns the resx; passing it to +`build.cmd` fails with `MSB4057`, as Arcade routes the target to its own `Build.proj`. ## Conventions & gotchas -- **Release tracking is mandatory (not `PublicAPI.txt`).** Any new/changed/removed - diagnostic ID **must** be recorded in the project's `AnalyzerReleases.Unshipped.md` - (it moves to `AnalyzerReleases.Shipped.md` at release). The `RS2000`/`RS2001` - analyzers fail the build if you skip this. -- **Analyzer file pattern**: `XxxAnalyzer.cs` + a **co-located** `Xxx.Fixer.cs` - + a test under `tests/…` mirroring the analyzer's folder. - **Diagnostic IDs are allocated centrally** in - `src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt` — take the next free - `CA####` in the category's range and update that file. + `src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt` — take the ID after the + category's range end and extend the range. That file only reflects *merged* work, so + concurrent branches routinely collide; + `.github/skills/add-net-analyzer/scripts/NextDiagnosticId.cs` checks the working + tree, local branches, and open PR titles and bodies for you. +- **Release tracking is mandatory (not `PublicAPI.txt`).** Any new, changed, or removed + diagnostic ID must be recorded in the declaring project's `AnalyzerReleases.Unshipped.md` + or `RS2000`/`RS2001` fails the build. +- **Analyzer file pattern**: `.cs` (declaring `Analyzer`) and its + `.Fixer.cs` sit together under `//`, with a test at the mirrored + path under `tests/…`. A fixer that needs language-specific syntax APIs instead goes to + the same relative path inside `…CSharp.NetAnalyzers/` or `…VisualBasic.NetAnalyzers/`. +- **Descriptors come from `DiagnosticDescriptorHelper.Create`**, never + `new DiagnosticDescriptor(...)` — the helper derives the `learn.microsoft.com` help + link from the ID and applies the telemetry/FxCop-compat tags. `RuleLevel` + (`src/Utilities/Compiler/RuleLevel.cs`) is the severity knob; its XML doc is the + rubric reviewers apply. +- **Building rewrites committed files.** `GenerateAnalyzerConfigAndDocumentationFiles` in + the Package project regenerates `src/Microsoft.CodeAnalysis.NetAnalyzers.md` and + `src/Microsoft.CodeAnalysis.NetAnalyzers.sarif.template`. CI runs the same generator in + validate-only mode and fails when they're stale — commit whatever the local build + produces. It also owns `src/RulesMissingDocumentation.md`, but that file stays empty in + practice: the help-link check is skipped whenever the generator runs offline, and the + product build forces offline on. Nothing verifies that a rule's help page exists. +- **Nullable reference warnings are errors** in the analyzer source projects. The unit-test + project sets `disable`. +- Pooled collections from `src/Utilities/Compiler/PooledObjects/` must be returned on every + path; prefer `using var x = PooledHashSet.GetInstance();`. + +## Tests + +- **MSTest** (`[TestClass]`/`[TestMethod]`/`[DataRow]`/`[DynamicData]`), *not* xUnit — + upstream `dotnet/roslyn-analyzers` tests use xUnit and must be translated when ported. + `tests/Test.Utilities/TheoryData.cs` is an MSTest-friendly shim for xUnit's `TheoryData`, + consumable from `[DynamicData]`. +- Embedded C# test sources default to `LanguageVersion.CSharp7_3`; set `LanguageVersion` + explicitly when the source uses newer syntax. +- `test/ConditionalTests.props` registers a `NetAnalyzers` scope, so PR validation can skip + these tests when nothing under this directory changed. Shared-infrastructure paths listed + as global triggers force every scope active, and non-PR CI always runs them. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/porting-fxcop-rules-to-roslyn.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/porting-fxcop-rules-to-roslyn.md deleted file mode 100644 index 2c5932c8a13e..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/porting-fxcop-rules-to-roslyn.md +++ /dev/null @@ -1,75 +0,0 @@ -# Porting Managed Code Analysis Rules to Roslyn - -Visual Studio 2015 shipped with over 300 Code Analysis rules for managed code. These rules were written using an MSIL-based analysis engine. Historically, this was valuable because it enabled the rules to apply to assemblies built from any managed language, including C#, VB, and managed C++. We are now engaged in an effort to rewrite some of these rules as Roslyn analyzers. Roslyn covers only C# and VB, but it has the following benefits: - -* You get live analysis as you type in VS. - -* Roslyn analyzers can be accompanied by fixers. - -However, we do not envision the new Roslyn-based managed analysis rules as a strict port of the FxCop rules, for various reasons: - -* FxCop includes rules related to a variety of quality concerns (standardization of public API conventions, correct usage of core BCL classes, internationalization, performance, security, etc.). This suggests that we can profitably unbundle the FxCop rules into a collection of packages, each serving a clearly defined purpose, and allow developers to select the packages that meet their needs. - -* To many people, the name "FxCop" means _nothing_. VS's customers just see a mass of Code Analysis rules, and there's no mention of FxCop anywhere in VS. (The only place the name appears is in the name of the command line tool FxCopCmd.exe.) Customers care mostly about getting some guidance from static analysis. But they can't figure out which of the 300+ rules matter to them, because the rules are not arranged in useful groups (other than the category, which is rather generic). - -* Most of the rules in VS today were written about 10 years ago. Platforms and guidelines have evolved since then. Many of the rules either don't make sense or aren't that valuable any more. For example, the introduction of generics has rendered many of the rules obsolete, as has the deprecation of CAS (Code Access Security) Policy and Security-Transparent Code. Experience has shown that other rules provide limited value and/or are a source of noise (false positives). - -For these reasons, we stopped thinking about these rules as "FxCop analyzers". Instead, we looked at the inventory of all the rules that exist today, and factored them according to the APIs they relate to and the purposes they serve. As part of this exercise, we identified the rules that provided the highest value. We chose to implement only those rules as analyzers, and not to re-implement low-value rules. In addition, we are adding new rules to fill the gaps that have appeared in the last 10 years, for example, rules related to `async` or `ImmutableCollections`. - -In the remainder of this document, we explain the principles we used to decide how to factor the new Roslyn-based analyzers, enumerate the specific NuGet packages into which the analyzers will be factored, and describe in a little more detail how we decided which FxCop rules to port. - -## Factoring principles - -* In the spirit of [Code-Aware libraries](https://channel9.msdn.com/Events/Build/2015/3-725), if a rule is about the usage of a specific API, and the rule doesn't make sense if that API is not referenced, then that rule should ship with that API. For example, rules about `ImmutableArray` (which resides in System.Collections.Immutable.dll) should reside in an analyzer assembly System.Collections.Immutable.Analyzers.dll, which would be included in the System.Collections.Immutable NuGet package. - -* Some types reside in different .NET assemblies, depending on which flavor of .NET you use. For example, in the .NET Framework, `IDisposable` resides in mscorlib.dll, whereas in [.NET Core](http://blogs.msdn.com/b/dotnet/archive/2014/11/12/net-core-is-open-source.aspx), it resides in System.Runtime.dll. Where should we place analyzers that examine uses of `IDisposable`: in mscorlib.Analyzers.dll or in System.Runtime.Analyzers.dll? We should choose the .NET Core version of the types; that is, we should place the `IDisposable` analyzers in System.Runtime.Analyzers.dll. - - The rationale for this choice is that developers using .NET Core, which is delivered as a set of NuGet packages, will automatically get exactly the API-specific analyzers they need. Developers using .NET Framework will still need to manually download the API-specific analyzers. For those developers, we might consider creating a consolidated NuGet package containing the analyzers for all types in the .NET framework. By doing these two things, we minimize the number of times developers have to search for and download API-specific analyzer packages. - -* Rules that do not relate to the usage of specific APIs, but relate instead to more general coding guidelines, should be organized according to the intended purpose of those guidelines. For example, some rules might help API authors produce consistent public APIs, but those rules might not make sense for test assemblies. (We will package those analyzers in Microsoft.ApiDesignGuidelines.Analyzers.dll.) As another example, there might be some rules that restrict the expressiveness of the language (by discouraging the use of certain language features) in order to gain a performance advantage. Such rules would only apply in a specific context where that tradeoff is acceptable, and hence it would be useful to place them in a separate NuGet package. - -## Analyzer packages - -The list of all the rules that ship in VS, along with certain other FxCop/Roslyn rules that we know of, is captured in the file [rules-inventory.csv](rules-inventory.csv) file (which, thanks to GitHub, is searchable). That file also contains our proposed factoring of the analyzers (in the "Proposed Analyzer" column, which perhaps might have been better named "Proposed Analyzer Package"). - -### API analyzer packages - -There are rules about types in the following contract assemblies: - -* **System.Runtime.Analyzers** - This package already exists - -* **System.Runtime.InteropServices.Analyzers** - Contains analyzers related to interop and marshalling. This package already exists. - -* **System.Security.Cryptography.Algorithms.Analyzers** - Contains analyzers with guidelines for crypto algorithm usage. This is a new package. - -* **System.Xml.Analyzers** - Contains analyzers for types dealing with XML across the System.Xml.* contracts. This is a new package. - -* **Desktop.Analyzers** - Contains analyzers for APIs that are present in the desktop .NET Framework but not in the new .NET Core API set. Since the .NET framework isn't available in a piecemeal fashion, there's not much value in breaking this down further. - -* **Microsoft.CodeAnalysis.Analyzers** - Contains analyzers related to using the Roslyn APIs correctly. Analyzer authors would use these rules; we refer to them informally as "analyzer analyzers." This package already exists. - -### Theme-based analyzer packages - -* **Microsoft.ApiDesignGuidelines.Analyzers** - Contains guidelines for authoring libraries which contain public APIs. The advantage of factoring it out this way is that one could simply install this analyzer for projects that expose real public APIs, and not for executables and test projects, reducing noise significantly. - -* **Microsoft.Maintainability.Analyzers** - Contains rules that contains metrics-based and heuristics-based rules to assess complexity, maintainability, and readability. - -* **Microsoft.QualityGuidelines.Analyzers** - Contains miscellaneous rules related to code quality, which do not fall into any of the other packages. - -* **Text.Analyzers** - Contains rules that analyze code as text. The existing rules check spelling errors in programming elements such as resource string names and identifiers. Future rules could do things such as flagging comments for inappropriate or deprecated terms. - -* **Roslyn.Internal.Analyzers** - Contains rules about some internal types in the Roslyn code base, meant as guidelines for Roslyn contributors as opposed to Roslyn consumers. - -## What to port? - -In addition to specifying the name of the analyzer package into which each former FxCop rule will be placed, the .csv file also contains some information from telemetry that has been reported through VS about the number of violations and suppressions for many of the rules. We used that as one consideration in deciding whether a rule was high value. Of course some of those numbers might have been reported long ago, so a subjective evaluation of the usefulness of a rule was needed. - -We were critical of rules at both ends of the "fire frequency" spectrum, throwing out some checks that never or rarely fire (some of these related to compiler fixes that actually prevent older, bad MSIL patterns from occurring) and deprioritizing some checks that are extremely noisy (which argues for an improved analysis spec, which was out of scope for this exercise). - -We tended to favor rules that were not frequently suppressed. We did not automatically throw out rules that fired infrequently; there are several useful checks which don't fire often but always indicate a real issue. - -We have populated the "Port?" column of the spreadsheet with our decisions. (NOTE: To see that column, you'll need to scroll to the bottom of the page and scroll horizontally.) - -## Feedback - -Although we are currently actively executing on this plan, please do provide feedback about the plan, the factoring, individual rules, rules that should be rewritten, rules that should be cut, and/or anything else. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/proposed-fxcop-rule-changes-in-roslyn.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/proposed-fxcop-rule-changes-in-roslyn.md deleted file mode 100644 index fdd159c1b551..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/proposed-fxcop-rule-changes-in-roslyn.md +++ /dev/null @@ -1,78 +0,0 @@ -# Proposed FxCop rule changes in Roslyn - -As we reimplement a subset of the existing FxCop rules as Roslyn analyzers, we follow the existing FxCop implementations as closely as possible. This has two benefits: - -* It minimizes the friction experienced by developers who are considering changing their process to run the new Roslyn analyzers instead of FxCop. It would hinder their adoption if the Roslyn implementation of a rule they relied on started producing new warnings. - -* It facilitates testing the new Roslyn analyzers by making it possible to simply compare the diagnostics produced by the analyzers with the diagnostics produced by FxCop. - -Nonetheless, the porting effort raises questions about certain implementation choices in the FxCop rules. We will capture those questions here and review them with the framework API designers to decide whether to allow Roslyn analyzers to behave differently from their FxCop counterparts. - -To be clear: In the first release of the FxCop analyzer equivalents, their behavior will be identical to FxCop as far as possible. -We would make changes only in subsequent releases. - -In addition to implementation details of the analyzers we have decided to port, there will be some feedback from the community regarding the rules we have decided _not_ to port. We will track that here as well, and consider this feedback as we revisit our decisions about rules to cut. - -## CA1034: Nested types should not be visible - -The .NET Framework Design Guidelines for [nested types](https://learn.microsoft.com/dotnet/standard/design-guidelines/nested-types) specifically mentions enumerations: - -> For example, an enum passed to a method defined on a class should not be defined as a nested type in the class. - -But the [documentation](https://learn.microsoft.com/visualstudio/code-quality/ca1034-nested-types-should-not-be-visible) for this rule says: - -> Nested enumerations ... are exempt from this rule - -... and the FxCop implementation conforms to the documentation by allowing nested enums. - -@michaelcfanning explains that this exemption was made for the sake of the `Environment.SpecialFolders` enumeration. - -At present, the Roslyn analyzer for CA1034 follows the FxCop implementation. Do we want to change it (and the documentation) to prohibit nested public enums? - -### Conclusion - -Yes, this is a good change. The .NET team would mark `Environment.SpecialFolders` to suppress this warning. -That has the advantage of making it clear that this wasn't a good design choice, -and will discourage others from emulating it. - -## CA1716: Identifiers should not match keywords - -* @sharwell made the following suggestions: - -> 1. The rule is defined according to "reserved identifiers". I believe it makes sense to expand this to include context-sensitive keywords where the identifier is visible in that context. For example, this rule should report a field named value as a violation because fields are visible in property setters, but it should not report a violation for a parameter or local variable named value because they can never be visible in the same scope where value is a keyword. -> -> 2. The set of languages and keywords are not defined. This makes expanding the rule in the future difficult. For example, some users may want new languages (e.g. Boo) for interoperability reasons while other users will not. I encourage this rule to be split into one rule for each programming language. -> -> 3. It makes sense to check publicly-exposed identifiers against multiple programming languages, but identifiers which are only internally visible only need to be checked against the current programming language. This separation should apply whether or not the advice from the second item is taken. - -These are good suggestions. - -With regard to item #2, the [documentation](https://learn.microsoft.com/visualstudio/code-quality/ca1716-identifiers-should-not-match-keywords) for the rule actually does define the set of languages to which it applies: - -> This rule checks against keywords in the following languages: -> -> * Visual Basic -> * C# -> * C++/CLI - -... and of course the Roslyn replacements would only apply to the Roslyn languages C# and VB. - -* @nguerrera: Consider adding `stackalloc` to the list of C# keywords we check. - -* @nguerrera, @lgolding, @srivatsn: Why did FxCop CA1716 limit itself to virtual/interface members? The error message says -that it will be hard to implement a virtual method if you name it with a keyword. But it's just as hard to _invoke_ it. -Why shouldn't all publicly visible methods follow this rule? - -## CA1812: Avoid uninstantiated internal classes - -* @mavasani suggests: - -> ... you probably want to ignore types with the MEF export attributes - they wouldn't have an explicit instantiation. And Roslyn code is full of such types. - -## CA2213: Disposable fields should be disposed - -We decided not to port this because of a high false positive rate, and our opinion that it was not of high value. We have had the following pushback on this decision: - -> @stilgarSCA: :-1: on this decision. Despite the fact that this causes a lot of false positives, I think it's worth keeping the rule for the correctly identified issues. End users always have the option of disabling rules for which they find no value. -> -> Several others have also argued for reversing this decision, as can be seen in the comments of [issue #695](https://github.com/dotnet/roslyn-analyzers/issues/695) and [issue #291](https://github.com/dotnet/roslyn-analyzers/issues/291). diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/rules-inventory.csv b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/rules-inventory.csv deleted file mode 100644 index 999c971d0260..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/FxCopPort/rules-inventory.csv +++ /dev/null @@ -1,318 +0,0 @@ -Id,Name,Proposed Analyzer,Existing Analyzer,Title,Description,VS Built-In,Triggered,Suppressed,% Suppressed,Rank,Category,Revised Priority,Original Priority,Port?,Default state,Notes,Dependency -CA2229,ImplementSerializationConstructors,Desktop,Microsoft.AnalyzerPowerPack,Implement serialization constructors,"To fix a violation of this rule, implement the serialization constructor. For a sealed class, make the constructor private; otherwise, make it protected.",Yes,58070,100,0.00172206,2766.426825,Usage,,Low,Ported,,,None -CA2235,MarkAllNonSerializableFields,Desktop,Microsoft.AnalyzerPowerPack,Mark all non-serializable fields,An instance field of a type that is not serializable is declared in a type that is serializable.,Yes,136128,564,0.004143159,1239.138299,Usage,,Low,Ported,,,None -CA2237,MarkISerializableTypesWithSerializable,Desktop,Microsoft.AnalyzerPowerPack,Mark ISerializable types with serializable,"To be recognized by the common language runtime as serializable, types must be marked by using the SerializableAttribute attribute even when the type uses a custom serialization routine through implementation of the ISerializable interface.",Yes,517360,1135,0.00219383,2604.482703,Usage,,Low,Ported,,,None -Async001,#N/A,Microsoft.ApiDesignGuidelines,AsyncPackage,Avoid Async Void,#N/A,,,,,,Usage,,,Ported,,, -Async002,#N/A,Microsoft.ApiDesignGuidelines,AsyncPackage,Async Method Names Should End in Async,#N/A,,,,,,Naming,,,Ported,,, -Async003,#N/A,Microsoft.ApiDesignGuidelines,AsyncPackage,Don't Pass Async Lambdas as Void Returning Delegate Types,#N/A,,,,,,Usage,,,Ported,,, -CA1000,DoNotDeclareStaticMembersOnGenericTypes,Microsoft.ApiDesignGuidelines,#N/A,Do not declare static members on generic types,"When a static member of a generic type is called, the type argument must be specified for the type. When a generic instance member that does not support inference is called, the type argument must be specified for the member. In these two cases, the syntax for specifying the type argument is different and easily confused.",Yes,177899,853,0.004794856,1094.959691,Design,,High,Yes,On,,None -Async004,#N/A,Microsoft.ApiDesignGuidelines,AsyncPackage,Don't Store Async Lambdas as Void Returning Delegate Types,#N/A,,,,,,Usage,,,Ported,,, -CA1002,DoNotExposeGenericLists,Microsoft.ApiDesignGuidelines,#N/A,Do not expose generic lists,"System.Collections.Generic.List<(Of <(T>)>) is a generic collection that is designed for performance, not inheritance. Therefore, List does not contain any virtual members. The generic collections that are designed for inheritance should be exposed instead.",Yes,1720656,18601,0.010810412,576.8229873,Design,,Low,Yes,On,,None -Async005,#N/A,Microsoft.ApiDesignGuidelines,AsyncPackage,Propagate CancellationTokens When Possible,#N/A,,,,,,Library,,,Ported,,, -CA1004,GenericMethodsShouldProvideTypeParameter,Microsoft.ApiDesignGuidelines,#N/A,Generic methods should provide type parameter,"Inference is how the type argument of a generic method is determined by the type of argument that is passed to the method, instead of by the explicit specification of the type argument. To enable inference, the parameter signature of a generic method must include a parameter that is of the same type as the type parameter for the method. In this case, the type argument does not have to be specified. When using inference for all type parameters, the syntax for calling generic and non-generic instance methods is identical; this simplifies the usability of generic methods.",Yes,360357,4493,0.012468191,445.6727399,Design,,Low,Yes,On,,None -CA1005,AvoidExcessiveParametersOnGenericTypes,Microsoft.ApiDesignGuidelines,#N/A,Avoid excessive parameters on generic types,"The more type parameters a generic type contains, the more difficult it is to know and remember what each type parameter represents. It is usually obvious with one type parameter, as in List<T>, and in certain cases that have two type parameters, as in Dictionary<TKey, TValue>. However, if more than two type parameters exist, the difficulty becomes too great for most users.",Yes,67481,367,0.005438568,887.9509468,Design,,Low,Yes,On,, -CA1006,DoNotNestGenericTypesInMemberSignatures,Microsoft.ApiDesignGuidelines,#N/A,Do not nest generic types in member signatures,"A nested type argument is a type argument that is also a generic type. To call a member whose signature contains a nested type argument, the user must instantiate one generic type and pass this type to the constructor of a second generic type. The required procedure and syntax are complex and should be avoided.",Yes,668354,10022,0.014995048,388.4620264,Design,,Low,Yes,On,,None -CA1007,UseGenericsWhereAppropriate,Microsoft.ApiDesignGuidelines,#N/A,Use generics where appropriate,"An externally visible method contains a reference parameter of type System.Object. Use of a generic method enables all types, subject to constraints, to be passed to the method without first casting the type to the reference parameter type.",Yes,78406,297,0.003787975,1292.075256,Design,,Low,Yes,On,, -Async006,#N/A,Microsoft.ApiDesignGuidelines,AsyncPackage,Don't Mix Blocking and Async,#N/A,,,,,,Usage,,,Ported,,, -CA1009,DeclareEventHandlersCorrectly,Microsoft.ApiDesignGuidelines,#N/A,Declare event handlers correctly,"Event handler methods take two parameters. The first is of type System.Object and is named """"sender"""". This is the object that raised the event. The second parameter is of type System.EventArgs and is named """"e"""". This is the data that is associated with the event. Event handler methods should not return a value; in the C# programming language, this is indicated by the return type void.",Yes,358275,1202,0.003354965,1655.521563,Design,,High,No,,CA1003 already does this.,None -CA1010,CollectionsShouldImplementGenericInterface,Microsoft.ApiDesignGuidelines,#N/A,Collections should implement generic interface,"To broaden the usability of a collection, implement one of the generic collection interfaces. Then the collection can be used to populate generic collection types.",Yes,218335,1570,0.007190785,742.4952222,Design,,High,Yes,On,,None -CA1011,ConsiderPassingBaseTypesAsParameters,Microsoft.ApiDesignGuidelines,#N/A,Consider passing base types as parameters,"When a base type is specified as a parameter in a method declaration, any type that is derived from the base type can be passed as the corresponding argument to the method. If the additional functionality that is provided by the derived parameter type is not required, use of the base type enables wider use of the method.",Yes,770430,4590,0.005957712,988.0862414,Design,,High,yes,On,,None -CA1001,TypesThatOwnDisposableFieldsShouldBeDisposable,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Types that own disposable fields should be disposable,"A class declares and implements an instance field that is a System.IDisposable type, and the class does not implement IDisposable. A class that declares an IDisposable field indirectly owns an unmanaged resource and should implement the IDisposable interface.",Yes,1133673,2747,0.002423097,2498.65648,Design,,High,Ported,,,Dataflow -CA1013,OverloadOperatorEqualsOnOverloadingAddAndSubtract,Microsoft.ApiDesignGuidelines,#N/A,Overload operator equals on overloading add and subtract,A public or protected type implements the addition or subtraction operators without implementing the equality operator.,Yes,14271,53,0.003713825,1118.645638,Design,,Low,yes,On,, -CA1003,UseGenericEventHandlerInstances,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Use generic event handler instances,"A type contains a delegate that returns void, whose signature contains two parameters (the first an object and the second a type that is assignable to EventArgs), and the containing assembly targets Microsoft .NET Framework?2.0.",Yes,198562,724,0.003646216,1452.984604,Design,,High,Ported,,, -CA1008,EnumsShouldHaveZeroValue,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Enums should have zero value,"The default value of an uninitialized enumeration, just as other value types, is zero. A nonflags-attributed enumeration should define a member by using the value of zero so that the default value is a valid value of the enumeration. If an enumeration that has the FlagsAttribute attribute applied defines a zero-valued member, its name should be """"None"""" to indicate that no values have been set in the enumeration.",Yes,569246,1776,0.003119917,1844.696789,Design,,High,Ported,,, -CA1012,AbstractTypesShouldNotHaveConstructors,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Abstract types should not have constructors,"Constructors on abstract types can be called only by derived types. Because public constructors create instances of a type, and you cannot create instances of an abstract type, an abstract type that has a public constructor is incorrectly designed.",Yes,379125,425,0.001121002,4976.602085,Design,,High,Ported,,, -CA1014,MarkAssembliesWithClsCompliant,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Mark assemblies with CLSCompliant,"The Common Language Specification (CLS) defines naming restrictions, data types, and rules to which assemblies must conform if they will be used across programming languages. Good design dictates that all assemblies explicitly indicate CLS compliance by using CLSCompliantAttribute . If this attribute is not present on an assembly, the assembly is not compliant.",Yes,2586566,4600,0.00177842,3605.854943,Design,,High,Ported,,, -CA1016,MarkAssembliesWithAssemblyVersion,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Mark assemblies with assembly version,"The .NET Framework uses the version number to uniquely identify an assembly, and to bind to types in strongly named assemblies. The version number is used together with version and publisher policy. By default, applications run only with the assembly version with which they were built.",Yes,320791,821,0.002559299,2151.457391,Design,,High,Ported,,, -CA1020,AvoidNamespacesWithFewTypes,Microsoft.ApiDesignGuidelines,#N/A,Avoid namespaces with few types,"Make sure that each of your namespaces has a logical organization, and that a valid reason exists for putting types in a sparsely populated namespace.",Yes,1946199,15579,0.008004834,785.6736586,Design,,High,No,,assembly factoring makes this noisy,None -CA1021,AvoidOutParameters,Microsoft.ApiDesignGuidelines,#N/A,Avoid out parameters,"Passing types by reference (using out or ref) requires experience with pointers, understanding how value types and reference types differ, and handling methods with multiple return values. Also, the difference between out and ref parameters is not widely understood.",Yes,673184,9276,0.013779294,422.9631753,Design,,Low,Yes,On,,None -CA1023,IndexersShouldNotBeMultidimensional,Microsoft.ApiDesignGuidelines,#N/A,Indexers should not be multidimensional,"Indexers (that is, indexed properties) should use a single index. Multidimensional indexers can significantly reduce the usability of the library.",Yes,33232,70,0.002106403,2146.576642,Design,,Low,Yes,On,, -CA1017,MarkAssembliesWithComVisible,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Mark assemblies with ComVisible,"ComVisibleAttribute determines how COM clients access managed code. Good design dictates that assemblies explicitly indicate COM visibility. COM visibility can be set for the whole assembly and then overridden for individual types and type members. If this attribute is not present, the contents of the assembly are visible to COM clients.",Yes,342998,836,0.002437332,2271.045388,Design,,High,Ported,,, -CA1025,ReplaceRepetitiveArgumentsWithParamsArray,Microsoft.ApiDesignGuidelines,#N/A,Replace repetitive arguments with params array,Use a parameter array instead of repeated arguments when the exact number of arguments is unknown and when the variable arguments are the same type or can be passed as the same type.,Yes,11210,87,0.007760928,521.7940105,Design,,Low,No,,Only catches case when somebody doesn't know about params, -CA1026,DefaultParametersShouldNotBeUsed,Microsoft.ApiDesignGuidelines,#N/A,Default parameters should not be used,"Methods that use default parameters are allowed under the CLS; however, the CLS lets compilers ignore the values that are assigned to these parameters. To maintain the behavior that you want across programming languages, methods that use default parameters should be replaced by method overloads that provide the default parameters.",Yes,451901,2791,0.006176131,915.6287078,Design,,High,No,,"Replace with a ""breaking change"" analyzer", -CA1018,MarkAttributesWithAttributeUsage,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Mark attributes with AttributeUsageAttribute,"When you define a custom attribute, mark it by using AttributeUsageAttribute to indicate where in the source code the custom attribute can be applied. The meaning and intended usage of an attribute will determine its valid locations in code.",Yes,114431,178,0.001555523,3251.989963,Design,,High,Ported,,, -CA1028,EnumStorageShouldBeInt32,Microsoft.ApiDesignGuidelines,#N/A,Enum Storage should be Int32,"An enumeration is a value type that defines a set of related named constants. By default, the System.Int32 data type is used to store the constant value. Although you can change this underlying type, it is not required or recommended for most scenarios.",Yes,140302,1177,0.008389046,613.5457553,Design,,High,Yes,,,None -CA1030,UseEventsWhereAppropriate,Microsoft.ApiDesignGuidelines,#N/A,Use events where appropriate,"This rule detects methods that have names that ordinarily would be used for events. If a method is called in response to a clearly defined state change, the method should be invoked by an event handler. Objects that call the method should raise events instead of calling the method directly.",Yes,191586,926,0.004833339,1092.901669,Design,,High,Yes,,We should check if it has a delegate arg?. FxCop doesn't do that.,WordParser -CA1031,DoNotCatchGeneralExceptionTypes,Microsoft.ApiDesignGuidelines,#N/A,Do not catch general exception types,"General exceptions should not be caught. Catch a more specific exception, or rethrow the general exception as the last statement in the catch block.",Yes,2802219,35947,0.012828048,502.6097536,Design,,Low,Yes,On,Don't fire if it rethrows (FxCop does this). Don't fire if there's an exception filter. Look for overlap with CA2153.,None (similar CA2153 already ported) -CA1032,ImplementStandardExceptionConstructors,Microsoft.ApiDesignGuidelines,#N/A,Implement standard exception constructors,Failure to provide the full set of constructors can make it difficult to correctly handle exceptions.,Yes,469099,2028,0.004323181,1311.826681,Design,,High,Yes,,Only implement checks for the three public ctors. Existing desktop-only rule catches the Iserializable case.,None -CA1019,DefineAccessorsForAttributeArguments,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Define accessors for attribute arguments,"Attributes can define mandatory arguments that must be specified when you apply the attribute to a target. These are also known as positional arguments because they are supplied to attribute constructors as positional parameters. For every mandatory argument, the attribute should also provide a corresponding read-only property so that the value of the argument can be retrieved at execution time. Attributes can also define optional arguments, which are also known as named arguments. These arguments are supplied to attribute constructors by name and should have a corresponding read/write property.",Yes,134071,354,0.002640392,1941.883928,Design,,High,Ported,,, -CA1034,NestedTypesShouldNotBeVisible,Microsoft.ApiDesignGuidelines,#N/A,Nested types should not be visible,"A nested type is a type that is declared in the scope of another type. Nested types are useful to encapsulate private implementation details of the containing type. Used for this purpose, nested types should not be externally visible.",Yes,1211946,9506,0.007843584,775.5999595,Design,,High,Yes,,,None -CA1035,ICollectionImplementationsHaveStronglyTypedMembers,Microsoft.ApiDesignGuidelines,#N/A,ICollection implementations have strongly typed members,This rule requires ICollection implementations to provide strongly typed members so that users are not required to cast arguments to the Object type when they use the functionality that is provided by the interface. This rule assumes that the type that implements ICollection does so to manage a collection of instances of a type that is stronger than Object.,Yes,84344,611,0.007244143,680.005098,Design,,Low,No,,"CA1010 takes care of it because it requires you to implement Icollection, which has CopyTo", -CA1024,UsePropertiesWhereAppropriate,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Use properties where appropriate,"A public or protected method has a name that starts with """"Get"""", takes no parameters, and returns a value that is not an array. The method might be a good candidate to become a property.",Yes,1626915,11430,0.007025567,884.1087197,Design,,High,Ported,,, -CA1038,EnumeratorsShouldBeStronglyTyped,Microsoft.ApiDesignGuidelines,#N/A,Enumerators should be strongly typed,This rule requires IEnumerator implementations to also provide a strongly typed version of the Current property so that users are not required to cast the return value to the strong type when they use the functionality that is provided by the interface.,Yes,18244,91,0.004987941,854.2843345,Design,,Low,No,,"CA1010 takes care of it because it requires you to implement a generic collection, whose GetEnumerator method will return Ienumerator.", -CA1039,ListsAreStronglyTyped,Microsoft.ApiDesignGuidelines,#N/A,Lists are strongly typed,This rule requires IList implementations to provide strongly typed members so that users are not required to cast arguments to the System.Object type when they use the functionality that is provided by the interface.,Yes,48572,197,0.004055835,1155.467716,Design,,Low,No,,CA1010 covers this as well., -CA1040,AvoidEmptyInterfaces,Microsoft.ApiDesignGuidelines,#N/A,Avoid empty interfaces,"Interfaces define members that provide a behavior or usage contract. The functionality that is described by the interface can be adopted by any type, regardless of where the type appears in the inheritance hierarchy. A type implements an interface by providing implementations for the members of the interface. An empty interface does not define any members; therefore, it does not define a contract that can be implemented.",Yes,189655,1043,0.00549946,959.724179,Design,,High,Yes,,,None -CA1041,ProvideObsoleteAttributeMessage,Microsoft.ApiDesignGuidelines,#N/A,Provide ObsoleteAttribute message,"A type or member is marked by using a System.ObsoleteAttribute attribute that does not have its ObsoleteAttribute.Message property specified. When a type or member that is marked by using ObsoleteAttribute is compiled, the Message property of the attribute is displayed. This gives the user information about the obsolete type or member.",Yes,51888,74,0.001426149,3306.153959,Design,,High,Yes,,, -CA1043,UseIntegralOrStringArgumentForIndexers,Microsoft.ApiDesignGuidelines,#N/A,Use integral or string argument for indexers,"Indexers (that is, indexed properties) should use integral or string types for the index. These types are typically used for indexing data structures and they increase the usability of the library. Use of the Object type should be restricted to those cases where the specific integral or string type cannot be specified at design time.",Yes,39552,251,0.006346076,724.4111813,Design,,Low,Yes,,, -CA1044,PropertiesShouldNotBeWriteOnly,Microsoft.ApiDesignGuidelines,#N/A,Properties should not be write only,"Although it is acceptable and often necessary to have a read-only property, the design guidelines prohibit the use of write-only properties. This is because letting a user set a value, and then preventing the user from viewing that value, does not provide any security. Also, without read access, the state of shared objects cannot be viewed, which limits their usefulness.",Yes,282895,935,0.003305113,1649.451905,Design,,High,Yes,,,None -CA1045,DoNotPassTypesByReference,Microsoft.ApiDesignGuidelines,#N/A,Do not pass types by reference,"Passing types by reference (using out or ref) requires experience with pointers, understanding how value types and reference types differ, and handling methods that have multiple return values. Library architects who design for a general audience should not expect users to master working with out or ref parameters.",Yes,523037,4636,0.008863618,645.1691193,Design,,Low,Yes,,, -CA1046,DoNotOverloadOperatorEqualsOnReferenceTypes,Microsoft.ApiDesignGuidelines,#N/A,Do not overload operator equals on reference types,"For reference types, the default implementation of the equality operator is almost always correct. By default, two references are equal only if they point to the same object.",Yes,4107,9,0.002191381,1648.971773,Design,,Low,Yes,,, -CA1047,DoNotDeclareProtectedMembersInSealedTypes,Microsoft.ApiDesignGuidelines,#N/A,Do not declare protected members in sealed types,"Types declare protected members so that inheriting types can access or override the member. By definition, sealed types cannot be inherited, which means that protected methods on sealed types cannot be called.",Yes,19563,96,0.004907223,874.5140813,Design,,Low,Yes,,"1. If VB compiler doesn't warn, implement VB analyzer. 2. In any case, implement fixer.", -CA1048,DoNotDeclareVirtualMembersInSealedTypes,Microsoft.ApiDesignGuidelines,#N/A,Do not declare virtual members in sealed types,"Types declare methods as virtual so that inheriting types can override the implementation of the virtual method. By definition, a sealed type cannot be inherited. This makes a virtual method on a sealed type meaningless.",Yes,5014,6,0.001196649,3092.120705,Design,,Low,Yes,,Error in both C# and VB. Implement fixer., -CA1049,TypesThatOwnNativeResourcesShouldBeDisposable,Microsoft.ApiDesignGuidelines,#N/A,Types that own native resources should be disposable,Types that allocate unmanaged resources should implement IDisposable to enable callers to release those resources on demand and to shorten the lifetimes of the objects that hold the resources.,Yes,32518,146,0.004489821,1004.967415,Design,,Low,Yes,,, -CA1050,DeclareTypesInNamespaces,Microsoft.ApiDesignGuidelines,#N/A,Declare types in namespaces,Types are declared in namespaces to prevent name collisions and as a way to organize related types in an object hierarchy.,Yes,112547,682,0.006059691,833.5960103,Design,,High,Yes,,Fixes wraps type in namespace and puts you in rename session for the namespace name.,None -CA1051,DoNotDeclareVisibleInstanceFields,Microsoft.ApiDesignGuidelines,#N/A,Do not declare visible instance fields,The primary use of a field should be as an implementation detail. Fields should be private or internal and should be exposed by using properties.,Yes,1291311,22729,0.017601492,347.1882335,Design,High,Low,Yes,,,None -CA1027,MarkEnumsWithFlags,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Mark enums with FlagsAttribute,An enumeration is a value type that defines a set of related named constants. Apply FlagsAttribute to an enumeration when its named constants can be meaningfully combined.,Yes,160610,392,0.002440695,2132.905955,Design,,High,Ported,,, -CA1033,InterfaceMethodsShouldBeCallableByChildTypes,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Interface methods should be callable by child types,An unsealed externally visible type provides an explicit method implementation of a public interface and does not provide an alternative externally visible method that has the same name.,Yes,485847,3981,0.008193938,693.9886297,Design,,High,Ported,,, -CA1054,UriParametersShouldNotBeStrings,Microsoft.ApiDesignGuidelines,#N/A,Uri parameters should not be strings,"If a method takes a string representation of a URI, a corresponding overload should be provided that takes an instance of the URI class, which provides these services in a safe and secure manner.",Yes,558646,3283,0.005876709,977.9515459,Design,,High,Yes,,,WordParser -CA1055,UriReturnValuesShouldNotBeStrings,Microsoft.ApiDesignGuidelines,#N/A,Uri return values should not be strings,"This rule assumes that the method returns a URI. A string representation of a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. The System.Uri class provides these services in a safe and secure manner.",Yes,270886,1742,0.006430749,844.8139037,Design,,High,Yes,,,WordParser -CA1056,UriPropertiesShouldNotBeStrings,Microsoft.ApiDesignGuidelines,#N/A,Uri properties should not be strings,"This rule assumes that the property represents a Uniform Resource Identifier (URI). A string representation of a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. The System.Uri class provides these services in a safe and secure manner.",Yes,676100,4114,0.006084899,958.1114229,Design,,High,Yes,,,WordParser -CA1057,StringUriOverloadsCallSystemUriOverloads,Microsoft.ApiDesignGuidelines,#N/A,String uri overloads call system uri overloads,"Because the overloads differ only by the string/Uri parameter, the string is assumed to represent a uniform resource identifier (URI). A string representation of a URI is prone to parsing and encoding errors, and can lead to security vulnerabilities. The Uri class provides these services in a safe and secure manner. To reap the benefits of the Uri class, the string overload should call the Uri overload using the string argument.",Yes,24713,131,0.005300854,828.7203597,Design,,Low,Yes,,, -CA1036,OverrideMethodsOnComparableTypes,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Override methods on comparable types,"A public or protected type implements the System.IComparable interface. It does not override Object.Equals nor does it overload the language-specific operator for equality, inequality, less than, or greater than.",Yes,131526,411,0.003124857,1638.158446,Design,,High,Ported,,, -CA1059,MembersShouldNotExposeCertainConcreteTypes,Microsoft.ApiDesignGuidelines,#N/A,Members should not expose certain concrete types,"A concrete type is a type that has a complete implementation and therefore can be instantiated. To enable widespread use of the member, replace the concrete type by using the suggested interface.",Yes,264897,2427,0.009162052,591.9064024,Design,,High,No,,,None -CA1052,StaticHolderTypesShouldBeSealed,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Static holder types should be sealed,A public or protected type contains only static members and is not declared by using the sealed (C# Reference) (NotInheritable) modifier. A type that is not meant to be inherited should be marked by using the sealed modifier to prevent its use as a base type.,Yes,161447,235,0.001455586,3577.96092,Design,,High,Ported,,Needs VB fixer., -CA1061,DoNotHideBaseClassMethods,Microsoft.ApiDesignGuidelines,#N/A,Do not hide base class methods,"A method in a base type is hidden by an identically named method in a derived type, when the parameter signature of the derived method differs only by types that are more weakly derived than the corresponding types in the parameter signature of the base method.",Yes,47204,99,0.00209728,2228.590862,Design,,Low,Yes,,, -CA1062,ValidateArgumentsOfPublicMethods,Microsoft.ApiDesignGuidelines,#N/A,Validate arguments of public methods,All reference arguments that are passed to externally visible methods should be checked against null.,Yes,2267308,29134,0.0128496,494.6076696,Design,,Low,Yes,,,"Dataflow, use IOperation" -CA1063,ImplementIDisposableCorrectly,Microsoft.ApiDesignGuidelines,#N/A,Implement IDisposable Correctly,All IDisposable types should implement the Dispose pattern correctly.,Yes,638117,2035,0.00318907,1820.248439,Design,,High,Yes,,,None -CA1064,ExceptionsShouldBePublic,Microsoft.ApiDesignGuidelines,#N/A,Exceptions should be public,"An internal exception is visible only inside its own internal scope. After the exception falls outside the internal scope, only the base exception can be used to catch the exception. If the internal exception is inherited from T:System.Exception, T:System.SystemException, or T:System.ApplicationException, the external code will not have sufficient information to know what to do with the exception.",Yes,74650,172,0.002304086,2114.951602,Design,High,Low,Yes,,, -CA1065,DoNotRaiseExceptionsInUnexpectedLocations,Microsoft.ApiDesignGuidelines,#N/A,Do not raise exceptions in unexpected locations,A method that is not expected to throw exceptions throws an exception.,Yes,437640,2017,0.004608811,1223.985349,Design,,High,Yes,,,None -CA1300,SpecifyMessageBoxOptions,Desktop,#N/A,Specify MessageBoxOptions,"To correctly display a message box for cultures that use a right-to-left reading order, the RightAlign and RtlReading members of the MessageBoxOptions enumeration must be passed to the Show method.",Yes,283590,2427,0.00855813,637.1358121,Globalization,,Low,Yes,,,None -CA1301,AvoidDuplicateAccelerators,Desktop,#N/A,Avoid duplicate accelerators,"An access key, also known as an accelerator, enables keyboard access to a control by using the ALT key. When multiple controls have duplicate access keys, the behavior of the access key is not well defined.",Yes,2707,16,0.005910602,580.7341068,Globalization,,Low,Yes,,, -CA1302,DoNotHardcodeLocaleSpecificStrings,Desktop,#N/A,Do not hardcode locale specific strings,"The System.Environment.SpecialFolder enumeration contains members that refer to special system folders. The locations of these folders can have different values on different operating systems; the user can change some of the locations; and the locations are localized. The Environment.GetFolderPath method returns the locations that are associated with the Environment.SpecialFolder enumeration, localized and appropriate for the currently running computer.",Yes,13519,71,0.005251868,786.5667551,Globalization,,Low,No,,, -CA1303,DoNotPassLiteralsAsLocalizedParameters,Microsoft.QualityGuidelines,#N/A,Do not pass literals as localized parameters,"An externally visible method passes a string literal as a parameter to a constructor or method in the .NET Framework class library, and that string should be localizable.",Yes,1370581,20484,0.014945487,410.6192633,Globalization,,Low,Yes,,,Dataflow -CA1304,SpecifyCultureInfo,System.Runtime,#N/A,Specify CultureInfo,"A method or constructor calls a member that has an overload that accepts a System.Globalization.CultureInfo parameter, and the method or constructor does not call the overload that takes the CultureInfo parameter. When a CultureInfo or System.IFormatProvider object is not supplied, the default value that is supplied by the overloaded member might not have the effect that you want in all locales.",Yes,1301330,3995,0.003069936,1991.698576,Globalization,,High,Yes,,,None -CA1305,SpecifyIFormatProvider,System.Runtime,#N/A,Specify IFormatProvider,"A method or constructor calls one or more members that have overloads that accept a System.IFormatProvider parameter, and the method or constructor does not call the overload that takes the IFormatProvider parameter. When a System.Globalization.CultureInfo or IFormatProvider object is not supplied, the default value that is supplied by the overloaded member might not have the effect that you want in all locales.",Yes,3114669,26486,0.008503632,763.6044986,Globalization,,High,Yes,,,None -CA1306,SetLocaleForDataTypes,Desktop,#N/A,Set locale for data types,"The locale determines culture-specific presentation elements for data, such as formatting that is used for numeric values, currency symbols, and sort order. When you create a DataTable or DataSet, you should explicitly set the locale.",Yes,486816,1204,0.002473214,2299.584887,Globalization,,Low,Yes,,,Dataflow -CA1307,SpecifyStringComparison,System.Runtime,#N/A,Specify StringComparison,A string comparison operation uses a method overload that does not set a StringComparison parameter.,Yes,1556401,3723,0.002392057,2588.617807,Globalization,,High,Yes,,,None -CA1308,NormalizeStringsToUppercase,System.Runtime,#N/A,Normalize strings to uppercase,Strings should be normalized to uppercase. A small group of characters cannot make a round trip when they are converted to lowercase.,Yes,465112,3117,0.006701612,845.7006816,Naming,,High,Yes,,"High noise, because it's perfectly valid to call ToLower; it's not always used for comparison.",None -CA1053,StaticHolderTypesShouldNotHaveConstructors,Microsoft.ApiDesignGuidelines,#N/A,Static holder types should not have constructors,A public or nested public type declares only static members and has a public or protected default constructor. The constructor is unnecessary because calling static members does not require an instance of the type. The string overload should call the uniform resource identifier (URI) overload by using the string argument for safety and security.,Yes,1300683,3250,0.002498687,2446.953502,Design,,High,Ported,,, -CA1400,PInvokeEntryPointsShouldExist,System.Runtime.InteropServices,#N/A,PInvoke entry points should exist,"No compile-time check is available to make sure that methods that are marked with DllImportAttribute are located in the referenced unmanaged DLL. If no function that has the specified name is in the library, or the arguments to the method do not match the function arguments, the common language runtime throws an exception.",Yes,19083,257,0.013467484,317.8505059,Interoperability,,Low,No,,Belongs in BinSkim? Easier to do in binary analysis., -CA1058,TypesShouldNotExtendCertainBaseTypes,Desktop,#N/A,Types should not extend certain base types,An externally visible type extends certain base types. Use one of the alternatives.,Yes,134607,292,0.002169278,2364.412358,Design,Low,High,Yes,,,None -CA1402,AvoidOverloadsInComVisibleInterfaces,System.Runtime.InteropServices,#N/A,Avoid overloads in ComVisible interfaces,"When overloaded methods are exposed to COM clients, only the first method overload retains its name. Subsequent overloads are uniquely renamed by appending to the name an underscore character '_' and an integer that corresponds to the order of declaration of the overload.",Yes,36284,88,0.002425311,1880.053464,Interoperability,,Low,Yes,,, -CA1403,AutoLayoutTypesShouldNotBeComVisible,System.Runtime.InteropServices,#N/A,Auto layout types should not be ComVisible,"Auto layout types are managed by the common language runtime. The layout of these types can change between versions of the .NET Framework, which will break COM clients that expect a specific layout. Note that if the StructLayoutAttribute attribute is not specified, the C#, Visual Basic, and C++ compilers specify the Sequential layout for value types.",Yes,46,0,0,,Interoperability,,Low,Yes,,, -CA1404,CallGetLastErrorImmediatelyAfterPInvoke,System.Runtime.InteropServices,#N/A,Call GetLastError immediately after PInvoke,"A platform invoke method accesses unmanaged code and is defined by using the Declare keyword in Visual Basic or the System.Runtime.InteropServices.DllImportAttribute attribute. Generally, upon failure, unmanaged functions call the Win32 SetLastError function to set an error code that is associated with the failure. The caller of the failed function calls the Win32 GetLastError function to retrieve the error code and determine the cause of the failure. The error code is maintained on a per-thread basis and is overwritten by the next call to SetLastError. After a call to a failed platform invoke method, managed code can retrieve the error code by calling the GetLastWin32Error method. Because the error code can be overwritten by internal calls from other managed class library methods, the GetLastError or GetLastWin32Error method should be called immediately after the platform invoke method call.",Yes,32639,62,0.001899568,2376.19124,Interoperability,,Low,Yes,,,Control flow -CA1405,ComVisibleTypeBaseTypesShouldBeComVisible,System.Runtime.InteropServices,#N/A,COM visible type base types should be ComVisible,"When a COM visible type adds members in a new version, it must abide by strict guidelines to avoid breaking COM clients that bind to the current version. A type that is invisible to COM presumes it does not need to adhere to these COM versioning rules when it adds new members. However, if a COM visible type derives from the COM invisible type and exposes a class interface of ClassInterfaceType.AutoDual or AutoDispatch (the default), all public members of the base type (unless they are specifically marked as COM invisible, which would be redundant) are exposed to COM. If the base type adds new members in a subsequent version, any COM clients that bind to the class interface of the derived type might break. COM visible types should derive only from COM visible types to reduce the possibility of breaking COM clients.",Yes,246688,4954,0.020082047,268.5058966,Interoperability,,Low,Yes,,,None -CA1406,AvoidInt64ArgumentsForVB6Clients,System.Runtime.InteropServices,#N/A,Avoid Int64 arguments for VB6 clients,Visual Basic 6 COM clients cannot access 64-bit integers.,Yes,2271,15,0.00660502,508.1312741,Interoperability,,Low,No,,, -CA1407,AvoidStaticMembersInComVisibleTypes,System.Runtime.InteropServices,#N/A,Avoid static members in ComVisible types,COM does not support static methods.,Yes,2603,38,0.01459854,233.9599805,Interoperability,,Low,Yes,,, -CA1408,DoNotUseAutoDualClassInterfaceType,System.Runtime.InteropServices,#N/A,Do not use AutoDual ClassInterfaceType,"Types that use a dual interface enable clients to bind to a specific interface layout. Any changes in a future version to the layout of the type or any base types will break COM clients that bind to the interface. By default, if the ClassInterfaceAttribute attribute is not specified, a dispatch-only interface is used.",Yes,4648,12,0.002581756,1420.45441,Interoperability,,Low,Yes,,, -CA1409,ComVisibleTypesShouldBeCreatable,System.Runtime.InteropServices,#N/A,COM visible types should be creatable,A reference type that is specifically marked as visible to COM contains a public parameterized constructor but does not contain a public default (parameterless) constructor. A type without a public default constructor is not creatable by COM clients.,Yes,9738,198,0.020332717,196.1601951,Interoperability,,Low,Yes,,, -CA1410,ComRegistrationMethodsShouldBeMatched,System.Runtime.InteropServices,#N/A,COM registration methods should be matched,"A type declares a method that is marked by using the System.Runtime.InteropServices.ComRegisterFunctionAttribute attribute but does not declare a method marked by using the System.Runtime.InteropServices.ComUnregisterFunctionAttribute attribute, or vice versa.",Yes,129,0,0,,Interoperability,,Low,Yes,,, -CA1411,ComRegistrationMethodsShouldNotBeVisible,System.Runtime.InteropServices,#N/A,COM registration methods should not be visible,A method marked by using the System.Runtime.InteropServices.ComRegisterFunctionAttribute attribute or the System.Runtime.InteropServices.ComUnregisterFunctionAttribute attribute is externally visible.,Yes,1758,16,0.009101251,356.5464484,Interoperability,,Low,Yes,,, -CA1412,MarkComSourceInterfacesAsIDispatch,System.Runtime.InteropServices,#N/A,Mark ComSource interfaces as IDispatch,"A type is marked by using the System.Runtime.InteropServices.ComSourceInterfacesAttribute attribute, and at least one of the specified interfaces is not marked by using the System.Runtime.InteropServices.InterfaceTypeAttribute attribute set to ComInterfaceType.InterfaceIsIDispatch.",Yes,558,1,0.001792115,1532.621883,Interoperability,,Low,Yes,,, -CA1413,AvoidNonpublicFieldsInComVisibleValueTypes,System.Runtime.InteropServices,#N/A,Avoid non-public fields in ComVisible value types,"Non-public instance fields of COM visible value types are visible to COM clients. Review the content of the field for information that should not be exposed, or will have unintended design or security impact. By default, all public value types are visible to COM. However, to reduce false positives, this rule requires the COM visibility of the type to be explicitly stated; the containing assembly must be marked with the System.Runtime.InteropServices.ComVisibleAttribute set to false and the type must be marked with the ComVisibleAttribute set to true.",Yes,563,10,0.017761989,154.8536226,Interoperability,,Low,Yes,,, -CA1414,MarkBooleanPInvokeArgumentsWithMarshalAs,System.Runtime.InteropServices,#N/A,Mark boolean PInvoke arguments with MarshalAs,The Boolean data type has multiple representations in unmanaged code.,Yes,171199,883,0.00515774,1014.688761,Interoperability,Low,High,Yes,,,None -CA1415,DeclarePInvokesCorrectly,System.Runtime.InteropServices,#N/A,Declare PInvokes correctly,"A platform invoke method accesses unmanaged code and is defined by using the Declare keyword in Visual Basic or the System.Runtime.InteropServices.DllImportAttribute. Currently, this rule looks for platform invoke method declarations that target Win32 functions that have a pointer to an OVERLAPPED structure parameter and the corresponding managed parameter is not a pointer to a System.Threading.NativeOverlapped structure.",Yes,7117,17,0.002388647,1612.752794,Interoperability,,Low,Yes,,, -CA1500,VariableNamesShouldNotMatchFieldNames,Microsoft.Maintainability,#N/A,Variable names should not match field names,"An instance method declares a parameter or a local variable whose name matches an instance field of the declaring type, leading to errors.",Yes,926277,4086,0.004411207,1352.63212,Maintainability,Low,High,Yes,,,None -CA1501,AvoidExcessiveInheritance,Microsoft.Maintainability,#N/A,Avoid excessive inheritance,"A type is more than four levels deep in its inheritance hierarchy. Deeply nested type hierarchies can be difficult to follow, understand, and maintain.",Yes,20270,926,0.045683276,94.27637741,Maintainability,,Low,Yes,,, -CA1502,AvoidExcessiveComplexity,Microsoft.Maintainability,#N/A,Avoid excessive complexity,"This rule measures the number of linearly independent paths through the method, which is determined by the number and complexity of conditional branches.",Yes,1681578,7375,0.004385761,1419.529325,Maintainability,,High,No,,"VS is the better place to experience this. You don't want to add one more ""if"" to a method, ""fall off the cliff"", and have your RI blocked.",MetricsPackage -CA1504,ReviewMisleadingFieldNames,Microsoft.Maintainability,#N/A,Review misleading field names,"The name of an instance field starts with """"s_"""", or the name of a static (Shared in Visual?Basic) field starts with """"m_"""".",Yes,175139,817,0.004664866,1124.015706,Maintainability,Low,High,No,,"This is a StyleCop rule, not an FxFop rule",None -CA1505,AvoidUnmaintainableCode,Microsoft.Maintainability,#N/A,Avoid unmaintainable code,A type or method has a low maintainability index value. A low maintainability index indicates that a type or method is probably difficult to maintain and would be a good candidate for redesign.,Yes,433586,1040,0.002398601,2350.150875,Maintainability,,High,No,,"VS is the better place to experience this. You don't want to add one more operand to an expression, ""fall off the cliff"", and have your RI blocked.",MetricsPackage -CA1506,AvoidExcessiveClassCoupling,Microsoft.Maintainability,#N/A,Avoid excessive class coupling,This rule measures class coupling by counting the number of unique type references that a type or method contains.,Yes,880097,3730,0.004238169,1402.617559,Maintainability,,High,No,,"VS is the better place to experience this. You don't want to add one more class-valued field to a class, ""fall off the cliff"", and have your RI blocked.",MetricsPackage -CA1600,DoNotUseIdleProcessPriority,System.Diagnostics,#N/A,Do not use idle process priority,"Do not set process priority to Idle. Processes that have System.Diagnostics.ProcessPriorityClass.Idle will occupy the CPU when it would otherwise be idle, and will therefore block standby.",Yes,310,1,0.003225806,772.3221251,Mobility,,Low,Yes,,, -CA1601,DoNotUseTimersThatPreventPowerStateChanges,System.Runtime,#N/A,Do not use timers that prevent power state changes,Higher-frequency periodic activity will keep the CPU busy and interfere with power-saving idle timers that turn off the display and hard disks.,Yes,61232,189,0.003086621,1550.879704,Mobility,,Low,Yes,,, -CA1700,DoNotNameEnumValuesReserved,Microsoft.ApiDesignGuidelines,#N/A,Do not name enum values 'Reserved',"This rule assumes that an enumeration member that has a name that contains """"reserved"""" is not currently used but is a placeholder to be renamed or removed in a future version. Renaming or removing a member is a breaking change.",Yes,17591,143,0.008129157,522.2301097,Naming,,Low,Yes,,, -CA1701,ResourceStringCompoundWordsShouldBeCasedCorrectly,Microsoft.ApiDesignGuidelines,#N/A,Resource string compound words should be cased correctly,"Each word in the resource string is split into tokens based on the casing. Each contiguous two-token combination is checked by the Microsoft spelling checker library. If recognized, the word produces a violation of the rule.",Yes,2530287,18776,0.007420502,862.9024959,Naming,,High,No,,Belongs in BinSkim. The resx is not part of the compilation.,NamingService -CA1702,CompoundWordsShouldBeCasedCorrectly,Microsoft.ApiDesignGuidelines,#N/A,Compound words should be cased correctly,Avoid creating compound words from terms which exist in the dictionary as discrete terms. Do not create a compound word such as 'StopWatch' or 'PopUp'. These terms are recognized in the dictionary and should be cased as 'Stopwatch' and 'Popup'.,Yes,,,,,,,#N/A,No,,Deprecated rule (replaced by 1709), -CA1703,ResourceStringsShouldBeSpelledCorrectly,Text,#N/A,Resource strings should be spelled correctly,A resource string contains one or more words that are not recognized by the Microsoft spelling checker library.,Yes,247983,8213,0.033119206,162.8789636,Naming,,Low,No,,Belongs in BinSkim. The resx is not part of the compilation.,WordParser -CA1704,IdentifiersShouldBeSpelledCorrectly,Text,#N/A,Identifiers should be spelled correctly,The name of an externally visible identifier contains one or more words that are not recognized by the Microsoft spelling checker library.,Yes,4050045,134475,0.033203335,198.9998864,Naming,High,Low,Yes,,See if StyleCop has implemented it,NamingService -CA1705,LongAcronymnsShouldBePascalBased,Microsoft.ApiDesignGuidelines,#N/A,Long acronyms should be pascal-cased,"This rule assumes it has found an acronym when the name contains four uppercase letters in a row, or at the end of the name, three uppercase letters in a row. By convention, two-letter acronyms use all uppercase letters, and acronyms of three or more characters use Pascal casing. The following examples conform to this naming convention: 'DB', 'CR', 'Cpa', and 'Ecma'. The following examples violate the convention: 'Io', 'XML', and 'DoD', and for non-parameter names, 'xp' and 'cpl'. Naming conventions provide a common look for libraries that target the common language runtime. This reduces the learning curve required for new software libraries, and increases customer confidence that the library was developed by someone with expertise in developing managed code.",,2574,90,0.034965035,97.54340432,Naming,,Low,No,,Deprecated rule (replaced by 1709), -CA1706,ShortAcronymsShouldBeUpperCase,Microsoft.ApiDesignGuidelines,#N/A,Short acronyms should be uppercase,"This rule splits the name into words based on the casing and checks any two-letter words against a list of common two-letter words, such as ""In"" or ""My"". If a match is not found, the word is assumed to be an acronym. For parameters, the first word is ignored due to the camel casing convention used for parameter names. By convention, two-letter acronyms use all uppercase letters, and acronyms of three or more characters use Pascal casing. The following examples conform to this naming convention: 'DB', 'CR', 'Cpa', and 'Ecma'. The following examples violate the convention: 'Io', 'XML', and 'DoD', and for non-parameter names, 'xp' and 'cpl'. 'ID' is special-cased to cause a violation of this rule. 'Id' is not an acronym but is an abbreviation for 'identification'. Naming conventions provide a common look for libraries that target the common language runtime. This reduces the learning curve required for new software libraries, and increases customer confidence that the library was developed by someone with expertise in developing managed code.",,470,2,0.004255319,627.9429966,Naming,,Low,No,,Deprecated rule (replaced by 1709), -CA1707,IdentifiersShouldNotContainUnderscores,Microsoft.ApiDesignGuidelines,#N/A,Identifiers should not contain underscores,"By convention, identifier names do not contain the underscore (_) character. This rule checks namespaces, types, members, and parameters.",Yes,1216136,42995,0.035353776,172.1168937,Naming,High,Low,Yes,,See if StyleCop has implemented it,None -CA1060,MovePInvokesToNativeMethodsClass,Microsoft.ApiDesignGuidelines,System.Runtime.InteropServices.Analyzers,Move pinvokes to native methods class,"Platform Invocation methods, such as those that are marked by using the System.Runtime.InteropServices.DllImportAttribute attribute, or methods that are defined by using the Declare keyword in Visual Basic, access unmanaged code. These methods should be of the NativeMethods, SafeNativeMethods, or UnsafeNativeMethods class.",Yes,377447,2739,0.007256648,768.5168157,Design,,High,Ported,,, -CA1709,IdentifiersShouldBeCasedCorrectly,Microsoft.ApiDesignGuidelines,#N/A,Identifiers should be cased correctly,"By convention, parameter names use camel casing and namespace, type, and member names use Pascal casing.",Yes,3261791,137633,0.04219553,154.3636525,Naming,,Low,Yes,,See if StyleCop has implemented it,NamingService -CA1710,IdentifiersShouldHaveCorrectSuffix,Microsoft.ApiDesignGuidelines,#N/A,Identifiers should have correct suffix,"By convention, the names of types that extend certain base types or that implement certain interfaces, or types that are derived from these types, have a suffix that is associated with the base type or interface.",Yes,597568,3205,0.005363406,1076.999758,Naming,,High,Yes,,See if StyleCop has implemented it,None -CA1711,IdentifiersShouldNotHaveIncorrectSuffix,Microsoft.ApiDesignGuidelines,#N/A,Identifiers should not have incorrect suffix,"By convention, only the names of types that extend certain base types or that implement certain interfaces, or types that are derived from these types, should end with specific reserved suffixes. Other type names should not use these reserved suffixes.",Yes,684645,2065,0.003016162,1934.732318,Naming,,High,Yes,,See if StyleCop has implemented it,None -CA1712,DoNotPrefixEnumValuesWithTypeName,Microsoft.ApiDesignGuidelines,#N/A,Do not prefix enum values with type name,Names of enumeration members are not prefixed by using the type name because development tools are expected to provide type information.,Yes,15010,57,0.003797468,1099.780249,Naming,,Low,Yes,,See if StyleCop has implemented it, -CA1713,EventsShouldNotHaveBeforeOrAfterPrefix,Microsoft.ApiDesignGuidelines,#N/A,Events should not have before or after prefix,"The name of an event starts with """"Before"""" or """"After"""". To name related events that are raised in a specific sequence, use the present or past tense to indicate the relative position in the sequence of actions.",Yes,42823,58,0.001354412,3419.694965,Naming,,Low,Yes,,See if StyleCop has implemented it, -CA1714,FlagsEnumsShouldHavePluralNames,Microsoft.ApiDesignGuidelines,#N/A,Flags enums should have plural names,"A public enumeration has the System.FlagsAttribute attribute, and its name does not end in """"s"""". Types that are marked by using FlagsAttribute have names that are plural because the attribute indicates that more than one value can be specified.",Yes,149797,409,0.002730362,1895.537507,Naming,,High,Yes,,See if StyleCop has implemented it,None -CA1708,IdentifiersShouldDifferByMoreThanCase,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Identifiers should differ by more than case,"Identifiers for namespaces, types, members, and parameters cannot differ only by case because languages that target the common language runtime are not required to be case-sensitive.",Yes,240275,455,0.001893664,2841.428034,Naming,,High,Ported,,, -CA1716,IdentifiersShouldNotMatchKeywords,Microsoft.ApiDesignGuidelines,#N/A,Identifiers should not match keywords,A namespace name or a type name matches a reserved keyword in a programming language. Identifiers for namespaces and types should not match keywords that are defined by languages that target the common language runtime.,Yes,563948,2635,0.004672417,1230.891752,Naming,,High,Yes,,See if StyleCop has implemented it,Valid rule? -CA1717,OnlyFlagsEnumsShouldHavePluralNames,Microsoft.ApiDesignGuidelines,#N/A,Only FlagsAttribute enums should have plural names,Naming conventions dictate that a plural name for an enumeration indicates that more than one value of the enumeration can be specified at the same time.,Yes,389307,875,0.002247584,2487.245589,Naming,,High,Yes,,See if StyleCop has implemented it,None -CA1718,#N/A,Microsoft.ApiDesignGuidelines,#N/A,Avoid language specific type names in parameters,"Each concatenated word in the parameter name is checked against language-specific type names, in a case-insensitive manner",,4,0,0,,Naming,,Low,Yes,,See if StyleCop has implemented it, -CA1719,ParameterNamesShouldNotMatchMemberNames,Microsoft.ApiDesignGuidelines,#N/A,Parameter names should not match member names,A parameter name should communicate the meaning of a parameter and a member name should communicate the meaning of a member. It would be a rare design where these were the same. Naming a parameter the same as its member name is unintuitive and makes the library difficult to use.,Yes,96386,394,0.004087731,1219.261851,Naming,,Low,Yes,,See if StyleCop has implemented it,None -CA1715,IdentifiersShouldHaveCorrectPrefix,Microsoft.ApiDesignGuidelines,Microsoft.AnalyzerPowerPack,Identifiers should have correct prefix,"The name of an externally visible interface does not start with an uppercase """"I"""". The name of a generic type parameter on an externally visible type or method does not start with an uppercase """"T"""".",Yes,163866,1290,0.007872286,662.3856049,Naming,,High,Ported,,, -CA1721,PropertyNamesShouldNotMatchGetMethods,Microsoft.ApiDesignGuidelines,#N/A,Property names should not match get methods,"The name of a public or protected member starts with """"Get"""" and otherwise matches the name of a public or protected property. """"Get"""" methods and properties should have names that clearly distinguish their function.",Yes,622332,1854,0.002979117,1944.878847,Naming,,High,Yes,,See if StyleCop has implemented it,None -CA1722,IdentifiersShouldNotHaveIncorrectPrefix,Microsoft.ApiDesignGuidelines,#N/A,Identifiers should not have incorrect prefix,"By convention, only certain programming elements have names that begin with a specific prefix.",Yes,28805,234,0.00812359,548.952873,Naming,,Low,Yes,,See if StyleCop has implemented it, -CA1724,TypeNamesShouldNotMatchNamespaces,Microsoft.ApiDesignGuidelines,#N/A,Type names should not match namespaces,Type names should not match the names of namespaces that are defined in the .NET Framework class library. Violating this rule can reduce the usability of the library.,Yes,633745,1999,0.003154266,1839.38686,Naming,,High,Yes,,See if StyleCop has implemented it,Hardcoded table -CA1725,ParameterNamesShouldMatchBaseDeclaration,Microsoft.ApiDesignGuidelines,#N/A,Parameter names should match base declaration,Consistent naming of parameters in an override hierarchy increases the usability of the method overrides. A parameter name in a derived method that differs from the name in the base declaration can cause confusion about whether the method is an override of the base method or a new overload of the method.,Yes,829781,4723,0.005691863,1039.899098,Naming,,High,Yes,,See if StyleCop has implemented it,None -CA1726,UsePreferredTerms,Microsoft.ApiDesignGuidelines,#N/A,Use preferred terms,"The name of an externally visible identifier includes a term for which an alternative, preferred term exists. Alternatively, the name includes the term """"Flag"""" or """"Flags"""".",Yes,1027505,7215,0.007021864,856.1521914,Naming,,High,Yes,,See if StyleCop has implemented it,NamingService -CA1800,DoNotCastUnnecessarily,System.Runtime,#N/A,Do not cast unnecessarily,"Duplicate casts decrease performance, especially when the casts are performed in compact iteration statements.",Yes,1161244,5060,0.004357396,1391.868776,Performance,,High,No,,,RemoveUnnecessaryCast IDE CodeFix -CA1801,ReviewUnusedParameters,Microsoft.Maintainability,#N/A,Review unused parameters,A method signature includes a parameter that is not used in the method body.,Yes,2443403,26581,0.01087868,587.20313,Performance,High,Low,Yes,,Don't fire if the parameter comes from an interface you're implementing or a virtual method you're overriding.,"None, can be based on: https://github.com/dotnet/roslyn/blob/main/src/Samples/CSharp/Analyzers/CSharpAnalyzers/CSharpAnalyzers/StatefulAnalyzers/CodeBlockStartedAnalyzer.cs" -CA1802,UseLiteralsWhereAppropriate,Microsoft.QualityGuidelines,#N/A,Use literals where appropriate,"A field is declared static and read-only (Shared and ReadOnly in Visual Basic), and is initialized by using a value that is computable at compile time. Because the value that is assigned to the targeted field is computable at compile time, change the declaration to a const (Const in Visual Basic) field so that the value is computed at compile time instead of at run?time.",Yes,156024,573,0.003672512,1414.070674,Performance,,High,Yes,,Does it fire on publics? That has versioning implications. Consider only firing on symbols not visible outside assembly.,None -CA1804,RemoveUnusedLocals,Microsoft.Maintainability,#N/A,Remove unused locals,Unused local variables and unnecessary assignments increase the size of an assembly and decrease performance.,Yes,2660659,16292,0.006123295,1049.269911,Performance,,High,Yes,,"See if the compiler warns of this. At the least, it should have a fixer.",None -CA1805,DoNotInitializeUnnecessarily,Microsoft.QualityGuidelines,#N/A,Do not initialize unnecessarily,"The common language runtime initializes all fields to their default values before running the constructor. In most cases, initializing a field to its default value in a constructor is redundant, which degrades performance and adds to maintenance costs. One case where it is not redundant occurs when the constructor calls another constructor of the same class or a base class constructor and that constructor initializes the field to a non-default value. In this case, changing the value of the field back to its default value can be appropriate.",,900111,3408,0.0037862,1572.631276,Performance,,High,No,,"The JITter now takes care of removing the redundant initializations for reference types, primitive value types, and some but not all user-defined value types, so we feel this rule is of low value.", -CA1806,DoNotIgnoreMethodResults,Microsoft.Maintainability,#N/A,Do not ignore method results,A new object is created but never used; or a method that creates and returns a new string is called and the new string is never used; or a COM or P/Invoke method returns an HRESULT or error code that is never used.,Yes,845078,3707,0.004386577,1351.143806,Performance,,High,Yes,,"Consider having a whitelist, like immutable types (including string), and also look for the Pure attribute",None -CA1809,AvoidExcessiveLocals,Microsoft.Maintainability,#N/A,Avoid excessive locals,"A common performance optimization is to store a value in a processor register instead of memory, which is referred to as """"enregistering the value"""". To increase the chance that all local variables are enregistered, limit the number of local variables to?64.",Yes,136521,362,0.002651607,1936.636922,Performance,,High,No,,"This was created at a time when after a certain number of locals, the JITTer would stop trying to allocate them to registers. This is hard to do in source analysis because it's hard to know how many locals the compiler allocates.",None -CA1720,IdentifiersShouldNotContainTypeNames,Microsoft.ApiDesignGuidelines,#N/A,Avoid type names in parameters,"The name of a parameter in an externally visible member contains a data type name, or the name of an externally visible member contains a language-specific data type name.",Yes,904982,5153,0.005694036,1046.11914,Naming,,High,Ported,,,None -CA1811,AvoidUncalledPrivateCode,Microsoft.Maintainability,#N/A,Avoid uncalled private code,A private or internal (assembly-level) member does not have callers in the assembly; it is not invoked by the common language runtime; and it is not invoked by a delegate.,Yes,2515500,32368,0.012867422,497.4286481,Performance,,Low,Yes,,Implementation: Create a dictionary at compilation start; add to it each time you see a function call.,IOperation -CA1812,AvoidUninstantiatedInternalClasses,Microsoft.Maintainability,#N/A,Avoid uninstantiated internal classes,An instance of an assembly-level type is not created by code in the assembly.,Yes,830636,3549,0.00427263,1385.42566,Performance,,High,Yes,,"Do we need additional APIs to make this efficient, for example, a RegisterSymbolReferenceAction API?",FxCopSDKUtilities -CA2217,DoNotMarkEnumsWithFlags,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Do not mark enums with FlagsAttribute,"An externally visible enumeration is marked by using FlagsAttribute, and it has one or more values that are not powers of two or a combination of the other defined values on the enumeration.",Yes,33479,117,0.003494728,1294.742374,Usage,,High,Ported,,,None -CA1814,PreferJaggedArraysOverMultidimensional,Microsoft.QualityGuidelines,#N/A,Prefer jagged arrays over multidimensional,"A jagged array is an array whose elements are arrays. The arrays that make up the elements can be of different sizes, leading to less wasted space for some sets of data.",Yes,163220,1424,0.008724421,597.492184,Performance,,High,Yes,,,None -CA1815,OverrideEqualsAndOperatorEqualsOnValueTypes,Microsoft.ApiDesignGuidelines,#N/A,Override equals and operator equals on value types,"For value types, the inherited implementation of Equals uses the Reflection library and compares the contents of all fields. Reflection is computationally expensive, and comparing every field for equality might be unnecessary. If you expect users to compare or sort instances, or to use instances as hash table keys, your value type should implement Equals.",Yes,399294,1633,0.004089718,1369.603552,Performance,,High,Yes,,,None -CA1816,CallGCSuppressFinalizeCorrectly,System.Runtime,#N/A,Dispose methods should call SuppressFinalize,A method that is an implementation of Dispose does not call GC.SuppressFinalize; or a method that is not an implementation of Dispose calls GC.SuppressFinalize; or a method calls GC.SuppressFinalize and passes something other than this (Me in Visual?Basic).,Yes,443318,1136,0.002562495,2203.600847,Performance,,High,Yes,,,None -CA1819,PropertiesShouldNotReturnArrays,Microsoft.ApiDesignGuidelines,#N/A,Properties should not return arrays,"Arrays that are returned by properties are not write-protected, even when the property is read-only. To keep the array tamper-proof, the property must return a copy of the array. Typically, users will not understand the adverse performance implications of calling such a property.",Yes,866343,7145,0.008247311,719.9546614,Performance,,High,Yes,,,None -CA2227,CollectionPropertiesShouldBeReadOnly,Microsoft.ApiDesignGuidelines,#N/A,Collection properties should be read only,A writable collection property allows a user to replace the collection with a different collection. A read-only property stops the collection from being replaced but still allows the individual members to be set.,Yes,1479039,18904,0.012781272,482.7359551,Usage,,High,Ported,,,None -CA1821,RemoveEmptyFinalizers,Microsoft.QualityGuidelines,Microsoft.AnalyzerPowerPack,Remove empty finalizers,"Whenever you can, avoid finalizers because of the additional performance overhead that is involved in tracking object lifetime. An empty finalizer incurs added overhead and delivers no benefit.",Yes,39675,3102,0.078185255,58.81565423,Performance,,Low,Yes,,Sri thinks we've already implemented this., -CA1822,MarkMembersAsStatic,Microsoft.QualityGuidelines,#N/A,Mark members as static,"Members that do not access instance data or call instance methods can be marked as static (Shared in Visual Basic). After you mark the methods as static, the compiler will emit nonvirtual call sites to these members. This can give you a measurable performance gain for performance-sensitive code.",Yes,3382541,37372,0.011048499,590.9620138,Performance,High,Low,Yes,,"Doesn't depend on IOperation, but would be language-agnostic if it did use IOperation.",IOperation -CA1823,AvoidUnusedPrivateFields,Microsoft.Maintainability,#N/A,Avoid unused private fields,Private fields were detected that do not appear to be accessed in the assembly.,Yes,2037563,18054,0.008860585,712.0422748,Performance,,High,Yes,,,None -CA1824,MarkAssembliesWithNeutralResourcesLanguage,System.Resources,#N/A,Mark assemblies with NeutralResourcesLanguageAttribute,The NeutralResourcesLanguage attribute informs the ResourceManager of the language that was used to display the resources of a neutral culture for an assembly. This improves lookup performance for the first resource that you load and can reduce your working set.,Yes,807994,798,0.000987631,5981.39139,Performance,,High,Yes,,,None -CA1900,ValueTypeFieldsShouldBePortable,Microsoft.QualityGuidelines,#N/A,Value type fields should be portable,This rule checks that structures that are declared by using explicit layout will align correctly when marshaled to unmanaged code on 64-bit operating systems.,Yes,21717,139,0.006400516,677.5703737,Portability,,Low,Yes,,, -RS0008,#N/A,Microsoft.ApiDesignGuidelines,Roslyn.Diagnostics.Analyzers,Implement IEquatable when overriding Object.Equals,#N/A,,,,,,Performance,,,Ported,,, -CA1903,UseOnlyApiFromTargetedFramework,System.Runtime,#N/A,Use only api from targeted framework,A member or type is using a member or type that was introduced in a service pack that was not included together with the targeted framework of the project.,Yes,114762,732,0.006378418,793.2685116,Portability,,High,No,,This was invented before we learned to ship new reference assemblies with each service pack.,FrameworkCompatibilityService -CA2000,DisposeObjectsBeforeLosingScope,Microsoft.QualityGuidelines,#N/A,Dispose Objects Before Losing Scope,"Because an exceptional event might occur that will prevent the finalizer of an object from running, the object should be explicitly disposed before all references to it are out of scope.",Yes,2950496,21737,0.007367236,878.1984362,Reliability,,High,Yes,,,Dataflow -CA2001,AvoidCallingProblematicMethods,ApiReview,#N/A,Avoid calling problematic methods,A member calls a potentially dangerous or problematic method.,Yes,279199,1198,0.004290846,1269.193408,Reliability,,Low,Yes,,,None -RS0011,#N/A,Microsoft.ApiDesignGuidelines,Roslyn.Diagnostics.Analyzers,CancellationToken parameters must come last,#N/A,,,,,,ApiDesign,,,Ported,,, -CA2003,DoNotTreatFibersAsThreads,System.Runtime.InteropServices,#N/A,Do not treat fibers as threads,A managed thread is being treated as a Win32 thread.,Yes,34,0,0,,Reliability,,Low,No,,, -CA2004,RemoveCallsToGCKeepAlive,System.Runtime.InteropServices,#N/A,Remove calls to GC.KeepAlive,"If you convert to SafeHandle usage, remove all calls to GC.KeepAlive (object). In this case, classes should not have to call GC.KeepAlive. This assumes they do not have a finalizer but rely on SafeHandle to finalize the OS handle for them.",Yes,16938,72,0.004250797,994.8398157,Reliability,,Low,Yes,,, -CA2006,UseSafeHandleToEncapsulateNativeResources,System.Runtime.InteropServices,#N/A,Use SafeHandle to encapsulate native resources,"Use of IntPtr in managed code might indicate a potential security and reliability problem. All uses of IntPtr must be reviewed to determine whether use of a SafeHandle, or similar technology, is required in its place.",Yes,63814,334,0.005233961,918.0266694,Reliability,,Low,Yes,,, -CA2100,ReviewSqlQueriesForSecurityVulnerabilities,Desktop,#N/A,Review SQL queries for security vulnerabilities,A method sets the System.Data.IDbCommand.CommandText property by using a string that is built from a string argument to the method. This rule assumes that the string argument contains user input. A SQL command string that is built from user input is vulnerable to SQL injection attacks.,Yes,418391,3364,0.008040326,699.1734406,Security,,Low,No,,,Dataflow -RS0022,#N/A,Microsoft.ApiDesignGuidelines,Roslyn.Diagnostics.Analyzers,Constructor make noninheritable base class inheritable,"When a base class is noninheritable because its constructor is internal, a derived class should not make it inheritable by having a public or protected constructor.",,,,,,ApiDesign,,,Ported,,, -CA2102,CatchNonClsCompliantExceptionsInGeneralHandlers,System.Runtime,#N/A,Catch non-CLSCompliant exceptions in general handlers,A member in an assembly that is not marked by using the RuntimeCompatibilityAttribute or is marked RuntimeCompatibility(WrapNonExceptionThrows = false) contains a catch block that handles System.Exception and does not contain an immediately following general catch block.,Yes,2400,11,0.004583333,737.5006346,Security,,Low,No,,Not relevant any more because the CLR wraps non-Exception-derived throws, -CA2103,ReviewImperativeSecurity,Desktop,#N/A,Review imperative security,A method uses imperative security and might be constructing the permission by using state information or return values that can change as long as the demand is active. Use declarative security whenever possible.,Yes,11291,80,0.007085289,571.9925201,Security,,Low,No,,CAS is deprecated, -CA2104,DoNotDeclareReadOnlyMutableReferenceTypes,System.Runtime,#N/A,Do not declare read only mutable reference types,An externally visible type contains an externally visible read-only field that is a mutable reference type. A mutable type is a type whose instance data can be modified.,Yes,292444,8727,0.029841611,183.1684881,Security,,Low,No,,,Hardcoded list of immutable types -CA2105,ArrayFieldsShouldNotBeReadOnly,System.Runtime,#N/A,Array fields should not be read only,"When you apply the read-only (ReadOnly in Visual Basic) modifier to a field that contains an array, the field cannot be changed to reference a different array. However, the elements of the array that are stored in a read-only field can be changed.",Yes,58839,177,0.003008209,1585.549919,Security,,Low,No,,Some other rule about not having visible fields would have to be suppressed before this would be the only indication of a problem., -CA2106,SecureAsserts,Desktop,#N/A,Secure asserts,A method asserts a permission and no security checks are performed on the caller. Asserting a security permission without performing any security checks can leave an exploitable security weakness in your code.,Yes,13428,138,0.010277033,401.6734505,Security,,Low,No,,CAS is deprecated, -CA2107,ReviewDenyAndPermitOnlyUsage,Desktop,#N/A,Review deny and permit only usage,The PermitOnly method and CodeAccessPermission.Deny security actions should be used only by those who have an advanced knowledge of .NET Framework security. Code that uses these security actions should undergo a security review.,Yes,938,16,0.017057569,174.2453914,Security,,Low,No,,CAS is deprecated, -CA2108,ReviewDeclarativeSecurityOnValueTypes,Desktop,#N/A,Review declarative security on value types,A public or protected value type is secured by Data Access or Link Demands.,Yes,136,0,0,,Security,,Low,No,,CAS is deprecated, -CA2109,ReviewVisibleEventHandlers,Microsoft.QualityGuidelines,#N/A,Review visible event handlers,A public or protected event-handling method was detected. Event-handling methods should not be exposed unless absolutely necessary.,Yes,249217,1465,0.005878411,918.0333759,Security,Low,High,Yes,,@michaelcfanning: Validate this decision,None -CA2111,PointersShouldNotBeVisible,Microsoft.QualityGuidelines,#N/A,Pointers should not be visible,"A pointer is not private, internal, or read-only. Malicious code can change the value of the pointer, which potentially gives access to arbitrary locations in memory or causes application or system failures.",Yes,49556,248,0.005004439,938.1862479,Security,Low,Low,No,,@nguerrera has validated this decision, -CA2112,SecuredTypesShouldNotExposeFields,Desktop,#N/A,Secured types should not expose fields,"A public or protected type contains public fields and is secured by Link Demands. If code has access to an instance of a type that is secured by a link demand, the code does not have to satisfy the link demand to access the fields of the type.",Yes,9409,0,0,,Security,,Low,No,,, -CA2114,MethodSecurityShouldBeASupersetOfType,Desktop,#N/A,Method security should be a superset of type,A method should not have both method-level and type-level declarative security for the same action.,Yes,7,0,0,,Security,,Low,No,,CAS is deprecated, -CA2115,CallGCKeepAliveWhenUsingNativeResources,System.Runtime.InteropServices,#N/A,Call GC.KeepAlive when using native resources,This rule detects errors that might occur because an unmanaged resource is being finalized while it is still being used in unmanaged code.,Yes,21,153,7.285714286,0.18148108,Security,,Low,No,,SafeHandle is available on all platforms; this is only relevant when SafeHandle is not available, -CA2116,AptcaMethodsShouldOnlyCallAptcaMethods,System.Runtime,#N/A,Aptca methods should only call aptca methods,"When the APTCA (AllowPartiallyTrustedCallersAttribute) is present on a fully trusted assembly, and the assembly executes code in another assembly that does not allow for partially trusted callers, a security exploit is possible.",Yes,20253,864,0.042660347,100.9482975,Security,,Low,No,,CAS/Transparency are de-emphasized, -CA2117,AptcaTypesShouldOnlyExtendAptcaBaseTypes,System.Runtime,#N/A,Aptca types should only extend aptca base types,"When the APTCA is present on a fully trusted assembly, and a type in the assembly inherits from a type that does not allow for partially trusted callers, a security exploit is possible.",Yes,6740,43,0.006379822,600.1201791,Security,,Low,No,,CAS/Transparency are de-emphasized, -CA2118,ReviewSuppressUnmanagedCodeSecurityUsage,System.Runtime.InteropServices,#N/A,Review suppress unmanaged code security usage,"This attribute is primarily used to increase performance; however, the performance gains come with significant security risks. If you place the attribute on public members that call native methods, the callers in the call stack (other than the immediate caller) do not need unmanaged code permission to execute unmanaged code. Depending on the public member's actions and input handling, it might allow untrustworthy callers to access functionality normally restricted to trustworthy code.",Yes,13584,539,0.039679034,104.1614989,Security,,Low,No,,CAS is deprecated, -CA2119,SealMethodsThatSatisfyPrivateInterfaces,Microsoft.QualityGuidelines,#N/A,Seal methods that satisfy private interfaces,"An inheritable public type provides an overridable method implementation of an internal (Friend in Visual Basic) interface. To fix a violation of this rule, prevent the method from being overridden outside the assembly.",Yes,16649,76,0.004564839,924.7617285,Security,High,Low,Yes,,, -CA2120,SecureSerializationConstructors,Desktop,#N/A,Secure serialization constructors,"This type has a constructor that takes a System.Runtime.Serialization.SerializationInfo object and a System.Runtime.Serialization.StreamingContext object (the signature of the serialization constructor). This constructor is not secured by a security check, but one or more of the regular constructors in the type are secured.",Yes,33,26,0.787878788,1.927344616,Security,,Low,No,,, -CA2121,StaticConstructorsShouldBePrivate,System.Runtime,#N/A,Static constructors should be private,"The system calls the static constructor before the first instance of the type is created or any static members are referenced. If a static constructor is not private, it can be called by code other than the system. Depending on the operations that are performed in the constructor, this can cause unexpected behavior.",Yes,44,0,0,,Security,,Low,No,,This was a VB compiler bug that was fixed years ago, -CA2122,DoNotIndirectlyExposeMethodsWithLinkDemands,Desktop,#N/A,Do not indirectly expose methods with link demands,A public or protected member has Link Demands and is called by a member that does not perform any security checks. A link demand checks the permissions of the immediate caller only.,Yes,733224,7044,0.009606887,610.5241757,Security,,High,No,,CAS is deprecated,FxCopSDKUtilities -CA2123,OverrideLinkDemandsShouldBeIdenticalToBase,System.Runtime,#N/A,Override link demands should be identical to base,"This rule matches a method to its base method, which is either an interface or a virtual method in another type, and then compares the link demands on each. If this rule is violated, a malicious caller can bypass the link demand just by calling the unsecured method.",No,138994,437,0.003144021,1635.802273,Security,,High,No,,CAS is deprecated,FxCopSDKUtilties -CA2124,WrapVulnerableFinallyClausesInOuterTry,Desktop,#N/A,Wrap vulnerable finally clauses in outer try,A public or protected method contains a try/finally block. The finally block appears to reset the security state and is not itself enclosed in a finally block.,Yes,2527,5,0.001978631,1719.676689,Security,,Low,No,,@michaelcfanning to review, -CA2126,TypeLinkDemandsRequireInheritanceDemands,Desktop,#N/A,Type link demands require inheritance demands,A public unsealed type is protected by using a link demand and has an overridable method. Neither the type nor the method is protected by using an inheritance demand.,Yes,3318,7,0.002109705,1668.895405,Security,,Low,No,,CAS is deprecated, -CA2130,ConstantsShouldBeTransparent,System.Runtime,#N/A,Security critical constants should be transparent,Transparency enforcement is not enforced for constant values because compilers inline constant values so that no lookup is required at run time. Constant fields should be security transparent so that code reviewers do not assume that transparent code cannot access the constant.,No,7,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2131,CriticalTypesMustNotParticipateInTypeEquivalence,System.Runtime,#N/A,Security critical types may not participate in type equivalence,"A type participates in type equivalence and either the type itself, or a member or field of the type, is marked by using the SecurityCriticalAttribute attribute. This rule occurs on any critical types or types that contain critical methods or fields that are participating in type equivalence. When the CLR detects such a type, it does not load it with a TypeLoadException at run time. Typically, this rule is raised only when users implement type equivalence manually instead of in by relying on tlbimp and the compilers to do the type equivalence.",No,7,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2132,DefaultConstructorsMustHaveConsistentTransparency,System.Runtime,#N/A,Default constructors must be at least as critical as base type default constructors,"Types and members that have the SecurityCriticalAttribute cannot be used by Silverlight application code. Security-critical types and members can be used only by trusted code in the .NET Framework for Silverlight class library. Because a public or protected construction in a derived class must have the same or greater transparency than its base class, a class in an application cannot be derived from a class marked as SecurityCritical.",No,467,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2133,DelegatesMustBindWithConsistentTransparency,System.Runtime,#N/A,Delegates must bind to methods with consistent transparency,This warning is raised on a method that binds a delegate that is marked by using the SecurityCriticalAttribute to a method that is transparent or that is marked by using the SecuritySafeCriticalAttribute. The warning also is raised on a method that binds a delegate that is transparent or safe-critical to a critical method.,No,69,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2134,MethodsMustOverrideWithConsistentTransparency,System.Runtime,#N/A,Methods must keep consistent transparency when overriding base methods,This rule is raised when a method marked by using the SecurityCriticalAttribute overrides a method that is transparent or marked by using the SecuritySafeCriticalAttribute. The rule also is raised when a method that is transparent or marked by using the SecuritySafeCriticalAttribute overrides a method that is marked by using a SecurityCriticalAttribute. The rule is applied when overriding a virtual method or implementing an interface.,No,3916,5,0.001276813,2813.914389,Security,,Low,No,,Transparency is de-emphasized, -CA2135,SecurityRuleSetLevel2MethodsShouldNotBeProtectedWithLinkDemands,System.Runtime,#N/A,Level2 methods should not be protected with link demands,"LinkDemands are deprecated in the level 2 security rule set. Instead of using LinkDemands to enforce security at just-in-time (JIT) compilation time, mark the methods, types, and fields with the SecurityCriticalAttribute attribute.",No,72950,390,0.005346127,909.6351163,Security,,Low,No,,CAS/Transparency are de-emphasized, -CA2136,TransparencyAnnotationsShouldNotConflict,System.Runtime,#N/A,Members should not have conflicting transparency annotations,"Critical code cannot occur in a 100 percent?transparent assembly. This rule analyzes 100 percent?transparent assemblies for any SecurityCritical annotations at the type, field, and method levels.",No,6481,114,0.017589878,216.6951925,Security,,Low,No,,Transparency is de-emphasized, -CA2137,TransparentMethodsMustBeVerifiable,System.Runtime,#N/A,Transparent methods must contain only verifiable IL,"A method contains unverifiable code or returns a type by reference. This rule is raised on attempts by security transparent code to execute unverifiable microsoft intermediate language (MISL). However, the rule does not contain a full IL verifier, and instead uses heuristics to catch most violations of MSIL verification.",No,124,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2138,TransparentMethodsMustNotCallSuppressUnmanagedCodeSecurityMethods,System.Runtime,#N/A,Transparent methods must not call methods with the SuppressUnmanagedCodeSecurity attribute,A security transparent method calls a method that is marked by using the SuppressUnmanagedCodeSecurityAttribute attribute.,No,230,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2139,TransparentMethodsMustNotHandleProcessCorruptingExceptions,System.Runtime,#N/A,Transparent methods may not use the HandleProcessCorruptingExceptions attribute,"This rule is raised by any method that is transparent and attempts to handle a process corrupting exception by using the HandleProcessCorruptedStateExceptionsAttribute attribute. A process corrupting exception is a CLR version 4.0 exception classification of exceptions such as AccessViolationException. The HandleProcessCorruptedStateExceptionsAttribute attribute may be used only by security critical methods, and will be ignored if it is applied to a transparent method.",No,35,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2140,TransparentMethodsMustNotReferenceCriticalCode,System.Runtime,#N/A,Transparent code must not reference security critical items,"Methods that are marked by SecurityTransparentAttribute call nonpublic members that are marked as SecurityCritical. This rule analyzes all methods and types in an assembly that is mixed transparent/critical, and flags any calls from transparent code to nonpublic critical code that are not marked as SecurityTreatAsSafe.",No,13305,64,0.004810222,857.3440307,Security,,Low,No,,Transparency is de-emphasized, -CA2141,TransparentMethodsMustNotSatisfyLinkDemands,System.Runtime,#N/A,Transparent methods must not satisfy LinkDemands,"A security transparent method calls a method in an assembly that is not marked by using the APTCA, or a security transparent method satisfies a LinkDemand for a type or a method.",No,16361,245,0.014974635,281.3965015,Security,,Low,No,,Transparency is de-emphasized, -CA2142,TransparentMethodsShouldNotBeProtectedWithLinkDemands,System.Runtime,#N/A,Transparent code should not be protected with LinkDemands,"This rule is raised on transparent methods that require LinkDemands to access them. Security transparent code should not be responsible for verifying the security of an operation, and therefore should not demand permissions.",No,3330,18,0.005405405,651.6521832,Security,,Low,No,,Transparency is de-emphasized, -CA2143,TransparentMethodsShouldNotDemand,System.Runtime,#N/A,Transparent methods should not use security demands,"Security transparent code should not be responsible for verifying the security of an operation, and therefore should not demand permissions. Security transparent code should use full demands to make security decisions and safe-critical code should not rely on transparent code to have made the full demand.",No,13049,22,0.001685953,2441.098513,Security,,Low,No,,Transparency is de-emphasized, -CA2144,TransparentMethodsShouldNotLoadAssembliesFromByteArrays,System.Runtime,#N/A,Transparent code should not load assemblies from byte arrays,"The security review for transparent code is not as complete as the security review for critical code because transparent code cannot perform security sensitive actions. Assemblies that are loaded from a byte array might not be noticed in transparent code, and that byte array might contain critical, or more important safe-critical code, that does have to be audited.",No,72,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2145,TransparentMethodsShouldNotUseSuppressUnmanagedCodeSecurity,System.Runtime,#N/A,Transparent methods should not be decorated with the SuppressUnmanagedCodeSecurityAttribute,Methods that are decorated by the SuppressUnmanagedCodeSecurityAttribute attribute have an implicit LinkDemand put upon any method that calls it. This LinkDemand requires that the calling code be security critical. Marking the method that uses SuppressUnmanagedCodeSecurity by using the SecurityCriticalAttribute attribute makes this requirement more obvious for callers of the method.,No,155,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2146,TypesMustBeAtLeastAsCriticalAsBaseTypes,System.Runtime,#N/A,Types must be at least as critical as their base types and interfaces,"This rule is raised when a derived type has a security transparency attribute that is not as critical as its base type or implemented interface. Only critical types can derive from critical base types or implement critical interfaces, and only critical or safe-critical types can derive from safe-critical base types or implement safe-critical interfaces.",No,2865,2,0.00069808,4952.331027,Security,,Low,No,,Transparency is de-emphasized, -CA2147,TransparentMethodsMustNotUseSecurityAsserts,System.Runtime,#N/A,Transparent methods may not use security asserts,"This rule analyzes all methods and types in an assembly that is either 100 percent?transparent or mixed transparent/critical, and flags any declarative or imperative use of Assert.",No,91,0,0,,Security,,Low,No,,Transparency is de-emphasized, -CA2149,TransparentMethodsMustNotCallNativeCode,System.Runtime,#N/A,Transparent methods must not call into native code,"This rule is raised on any transparent method that calls directly into native code (for example, through a P/Invoke). Violations of this rule lead to a MethodAccessException in the level 2 transparency model and a full demand for UnmanagedCode in the level 1 transparency model.",No,4351,61,0.014019766,259.5328049,Security,,Low,No,,Transparency is de-emphasized, -CA2150,TransparentCodeMustNotUseCriticalAttributes,System.Runtime,#N/A,#N/A,#N/A,No,,,,,,,Low,No,,Transparency is de-emphasized, -CA2151,FieldsWithCriticalTypesShouldBeCritical,System.Runtime,#N/A,#N/A,#N/A,No,,,,,,,Low,No,,Transparency is de-emphasized, -RS0006,#N/A,Microsoft.Composition,Roslyn.Diagnostics.Analyzers,Do not mix attributes from different versions of MEF,#N/A,,,,,,Reliability,,,Ported,,, -RS0023,#N/A,Microsoft.Composition,Roslyn.Diagnostics.Analyzers,Parts exported with MEFv2 must be marked as Shared,#N/A,,,,,,Reliability,,,Ported,,, -RS0001,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Use SpecializedCollections.EmptyEnumerable(),#N/A,,,,,,Performance,,,Ported,,, -CA2202,DoNotDisposeObjectsMultipleTimes,System.Runtime,#N/A,Do not dispose objects multiple times,A method implementation contains code paths that could cause multiple calls to System.IDisposable.Dispose or a Dispose equivalent (such as a Close() method on some types) on the same object.,Yes,1034185,2477,0.002395123,2511.18582,Usage,,High,No,,,Dataflow -CA2204,LiteralsShouldBeSpelledCorrectly,Text,#N/A,Literals should be spelled correctly,A literal string in a method body contains one or more words that are not recognized by the Microsoft spelling checker library.,Yes,1364858,19401,0.014214666,431.6026604,Naming,,Low,Yes,,,Dataflow -CA2205,UseManagedEquivalentsOfWin32Api,System.Runtime.InteropServices,#N/A,Use managed equivalents of win32 api,An operating system invoke method is defined and a method that has the equivalent functionality is located in the .NET Framework class library.,Yes,28980,117,0.004037267,1105.227445,Usage,,Low,Yes,,,None -RS0002,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Use SpecializedCollections.SingletonEnumerable(),#N/A,,,,,,Performance,,,Ported,,, -CA2208,InstantiateArgumentExceptionsCorrectly,System.Runtime,#N/A,Instantiate argument exceptions correctly,"A call is made to the default (parameterless) constructor of an exception type that is or derives from ArgumentException, or an incorrect string argument is passed to a parameterized constructor of an exception type that is or derives from ArgumentException.",Yes,774590,2637,0.003404382,1729.850661,Usage,,High,Yes,,The fixer should introduce nameof,IOperation -CA2209,AssembliesShouldDeclareMinimumSecurity,Desktop,#N/A,Assemblies should declare minimum security,"Assemblies specify security permission requests to communicate to administrators the minimum permissions that are required to execute the assembly, and to limit security vulnerabilities caused by mistakenly omitting demands at the type and member level. ",,7023,203,0.028905026,133.0745256,Security,,Low,No,,Deprecated rule, -CA2210,AssembliesShouldHaveValidStrongNames,Microsoft.ApiDesignGuidelines,#N/A,Assemblies should have valid strong names,"The strong name protects clients from unknowingly loading an assembly that has been tampered with. Assemblies without strong names should not be deployed outside very limited scenarios. If you share or distribute assemblies that are not correctly signed, the assembly can be tampered with, the common language runtime might not load the assembly, or the user might have to disable verification on his or her computer.",Yes,2955771,8737,0.002955912,2189.060439,Design,,High,Yes,,Implement the check to just see if it has a public key.,None -CA2211,NonConstantFieldsShouldNotBeVisible,Microsoft.ApiDesignGuidelines,#N/A,Non-constant fields should not be visible,Static fields that are neither constants nor read-only are not thread-safe. Access to such a field must be carefully controlled and requires advanced programming techniques to synchronize access to the class object.,Yes,752431,8608,0.011440252,513.6658574,Usage,,High,Yes,,,None -CA2212,DoNotMarkServicedComponentsWithWebMethod,Desktop,#N/A,Do not mark serviced components with WebMethod,"A method in a type that inherits from System.EnterpriseServices.ServicedComponent is marked by using System.Web.Services.WebMethodAttribute. Because WebMethodAttribute and a ServicedComponent method have conflicting behavior and requirements for context and transaction flow, the behavior of the method will be incorrect in some scenarios.",Yes,26,0,0,,Usage,,Low,Yes,,,None -RS0004,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Invoke the correct property to ensure correct use site diagnostics.,#N/A,,,,,,Usage,,,Ported,,, -RS0005,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Do not use generic CodeAction.Create to create CodeAction,#N/A,,,,,,Performance,,,Ported,,, -CA2215,DisposeMethodsShouldCallBaseClassDispose,System.Runtime,#N/A,Dispose Methods Should Call Base Class Dispose,"If a type inherits from a disposable type, it must call the Dispose method of the base type from its own Dispose method.",Yes,37586,119,0.003166072,1445.01623,Usage,,Low,Yes,,,Dataflow -CA2216,DisposableTypesShouldDeclareFinalizer,System.Runtime,#N/A,Disposable types should declare finalizer,"A type that implements System.IDisposable and has fields that suggest the use of unmanaged resources does not implement a finalizer, as described by Object.Finalize.",Yes,8011,13,0.001622769,2405.571878,Usage,,High,Yes,,,InternalUtilities -RS0009,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Override Object.Equals(object) when implementing Iequatable,#N/A,,,,,,Reliability,,,Ported,,, -CA2218,OverrideGetHashCodeOnOverridingEquals,Microsoft.ApiDesignGuidelines,#N/A,Override GetHashCode on overriding Equals,"GetHashCode returns a value, based on the current instance, that is suited for hashing algorithms and data structures such as a hash table. Two objects that are the same type and are equal must return the same hash code.",Yes,34660,25,0.000721293,6294.018313,Usage,,High,Yes,,Fixer should create method that throws NotImplementedException. Implementer should check if the compiler gives this warning.,None -CA2219,DoNotRaiseExceptionsInExceptionClauses,System.Runtime,#N/A,Do not raise exceptions in exception clauses,"When an exception is raised in a finally or fault clause, the new exception hides the active exception. When an exception is raised in a filter clause, the run time silently catches the exception. This makes the original error difficult to detect and debug.",Yes,14661,36,0.002455494,1696.670124,Usage,,High,Yes,,,None -CA2220,FinalizersShouldCallBaseClassFinalizer,System.Runtime,#N/A,Finalizers should call base class finalizer,"Finalization must be propagated through the inheritance hierarchy. To guarantee this, types must call their base class Finalize method in their own Finalize method.",Yes,47,0,0,,Usage,,Low,No,,The compiler automatically chains to the base class. @nguerrera: Does the VB compiler do that?>,None -CA2221,FinalizersShouldBeProtected,System.Runtime,#N/A,Finalizers should be protected,Finalizers must use the family access modifier.,Yes,10,0,0,,Usage,,Low,No,,,N/A -CA2222,DoNotDecreaseInheritedMemberVisibility,Microsoft.ApiDesignGuidelines,#N/A,Do not decrease inherited member visibility,You should not change the access modifier for inherited members. Changing an inherited member to private does not prevent callers from accessing the base class implementation of the method.,Yes,64588,185,0.002864309,1679.34101,Usage,,High,Yes,,,None -CA2223,MembersShouldDifferByMoreThanReturnType,Microsoft.ApiDesignGuidelines,#N/A,Members should differ by more than return type,"Although the common language runtime allows the use of return types to differentiate between otherwise identical members, this feature is not in the Common Language Specification, nor is it a common feature of .NET programming languages.",Yes,12,1,0.083333333,12.95017495,Usage,,High,No,,"Hardly ever fires, can't violate it in C# and VB, and Roslyn can't examine anything else.",None -CA2224,OverrideEqualsOnOverloadingOperatorEquals,Microsoft.ApiDesignGuidelines,#N/A,Override Equals on overloading operator equals,A public type implements the equality operator but does not override Object.Equals.,Yes,7619,11,0.001443759,2688.743696,Usage,,High,Yes,,Fixer should create method that throws NotImplementedException. Implementer should check if the compiler gives this warning.,None -CA2225,OperatorOverloadsHaveNamedAlternates,Microsoft.ApiDesignGuidelines,#N/A,Operator overloads have named alternates,"An operator overload was detected, and the expected named alternative method was not found. The named alternative member provides access to the same functionality as the operator and is provided for developers who program in languages that do not support overloaded operators.",Yes,71083,1385,0.019484265,249.009433,Usage,,High,Yes,,,HardCoded list of alternates -CA2226,OperatorsShouldHaveSymmetricalOverloads,Microsoft.ApiDesignGuidelines,#N/A,Operators should have symmetrical overloads,A type implements the equality or inequality operator and does not implement the opposite operator.,Yes,47,0,0,,Usage,,High,Yes,,,None -RS0013,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Do not invoke Diagnostic.Descriptor,"Accessing the Descriptor property of Diagnostic in compiler layer leads to unnecessary string allocations for fields of the descriptor that are not utilized in command line compilation. Hence, you should avoid accessing the Descriptor of the compiler diagnostics here. Instead you should directly access these properties off the Diagnostic type.",,,,,,Performance,,,Ported,,, -CA2228,DoNotShipUnreleasedResourceFormats,System.Runtime,#N/A,Do not ship unreleased resource formats,Resource files that were built by using prerelease versions of the .NET Framework might not be usable by supported versions of the .NET Framework.,Yes,2033,45,0.022134776,149.4542954,Usage,,High,No,,,N/A -RS0016,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Add public types and members to the declared API,"All public types and members should be declared in PublicAPI.txt. This draws attention to API changes in the code reviews and source control history, and helps prevent breaking changes.",,,,,,ApiDesign,,,Ported,,, -CA2230,UseParamsForVariableArguments,Microsoft.ApiDesignGuidelines,#N/A,Use params for variable arguments,A public or protected type contains a public or protected method that uses the VarArgs calling convention instead of the params keyword.,Yes,126,8,0.063492063,33.08083609,Usage,,High,No,,"This is about __arglist, rarely used.",None -CA2231,OverloadOperatorEqualsOnOverridingValueTypeEquals,Microsoft.ApiDesignGuidelines,System.Runtime.Analyzers,Overload operator equals on overriding value type Equals,"In most programming languages there is no default implementation of the equality operator (==) for value types. If your programming language supports operator overloads, you should consider implementing the equality operator. Its behavior should be identical to that of Equals",Yes,15312,25,0.001632706,2563.248351,Usage,,High,Yes,,,None -CA2232,MarkWindowsFormsEntryPointsWithStaThread,Desktop,#N/A,Mark Windows Forms entry points with STAThread,"STAThreadAttribute indicates that the COM threading model for the application is a single-threaded apartment. This attribute must be present on the entry point of any application that uses Windows Forms; if it is omitted, the Windows components might not work correctly.",Yes,17032,43,0.002524659,1675.974803,Usage,,Low,Yes,,,None -CA2233,OperationsShouldNotOverflow,System.Runtime,#N/A,Operations should not overflow,You should not perform arithmetic operations without first validating the operands. This makes sure that the result of the operation is not outside the range of possible values for the data types that are involved.,Yes,177875,717,0.004030921,1302.460516,Usage,,High,No,,Very noisy,IOperation -CA2234,PassSystemUriObjectsInsteadOfStrings,Microsoft.ApiDesignGuidelines,#N/A,Pass system uri objects instead of strings,"A call is made to a method that has a string parameter whose name contains ""uri"", ""URI"", ""urn"", ""URN"", ""url"", or ""URL"". The declaring type of the method contains a corresponding method overload that has a System.Uri parameter.",Yes,197362,824,0.004175069,1268.305585,Usage,,High,Yes,,,WordParser -RS0017,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Remove deleted types and members from the declared API,"When removing a public type or member the corresponding entry in PublicAPI.txt should also be removed. This draws attention to API changes in the code reviews and source control history, and helps prevent breaking changes.",,,,,,ApiDesign,,,Ported,,, -CA2236,CallBaseClassMethodsOnISerializableTypes,Desktop,#N/A,Call base class methods on ISerializable types,"To fix a violation of this rule, call the base type GetObjectData method or serialization constructor from the corresponding derived type method or constructor.",Yes,23555,57,0.002419868,1806.744169,Usage,,Low,Yes,,,IOperation -RS0019,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,SymbolDeclaredEvent must be generated for source symbols,"Compilation event queue is required to generate symbol declared events for all declared source symbols. Hence, every source symbol type or one of it's base types must generate a symbol declared event.",,,,,,Reliability,,,Ported,,, -CA2238,ImplementSerializationMethodsCorrectly,Desktop,#N/A,Implement serialization methods correctly,"A method that handles a serialization event does not have the correct signature, return type, or visibility.",Yes,38890,1402,0.036050399,127.3172594,Usage,,Low,Yes,,,None -CA2239,ProvideDeserializationMethodsForOptionalFields,Desktop,#N/A,Provide deserialization methods for optional fields,"A type has a field that is marked by using the System.Runtime.Serialization.OptionalFieldAttribute attribute, and the type does not provide deserialization event handling methods.",Yes,13047,393,0.030121867,136.6286708,Usage,,Low,Yes,,,None -CA2240,ImplementISerializableCorrectly,Desktop,#N/A,Implement ISerializable correctly,"To fix a violation of this rule, make the GetObjectData method visible and overridable, and make sure that all instance fields are included in the serialization process or explicitly marked by using the NonSerializedAttribute attribute.",Yes,254727,2301,0.0090332,598.4673019,Usage,,Low,Yes,,,None -CA2241,ProvideCorrectArgumentsToFormattingMethods,System.Runtime,#N/A,Provide correct arguments to formatting methods,"The format argument that is passed to System.String.Format does not contain a format item that corresponds to each object argument, or vice versa.",Yes,275305,236,0.000857231,6345.796697,Usage,,High,Yes,,,Dataflow -CA2242,TestForNaNCorrectly,System.Runtime,#N/A,Test for NaN correctly,This expression tests a value against Single.Nan or Double.Nan. Use Single.IsNan(Single) or Double.IsNan(Double) to test the value.,Yes,15800,4,0.000253165,16584.69549,Usage,,High,Yes,,,IOperation -CA2243,AttributeStringLiteralsShouldParseCorrectly,System.Runtime,#N/A,Attribute string literals should parse correctly,"The string literal parameter of an attribute does not parse correctly for a URL, a GUID, or a version.",Yes,63488,553,0.008710307,551.3802662,Usage,,High,Yes,,,WordParser -CA3050,DoNotUseXslTransform,System.Xml,#N/A,Do not use XslTransform,"Do not use obsolete and unsafe System.Xml.Xsl.XslTransform API. This API allows processing script within XSL, which, on untrusted XSL input, may lead to malicious code execution.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3053,UseXmlSecureResolver,System.Xml,#N/A,Use XmlSecureResolver,"Review code to ensure that external resource resolution is explicitly disabled or a XmlSecureResolver is used when processing untrusted input (the resolver used internally on some overloaded methods is not safe to use on untrusted input). Using default resolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3054,DoNotAllowDtdOnXmlTextReader,System.Xml,#N/A,Do not allow Dtd on XmlTextReader,"Prohibit DTD processing when using XmlTextReader on untrusted sources. Enabling DTD processing on the XML reader and using UrlResolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3055,DoNotAllowDtdOnXmlReader,System.Xml,#N/A,Do not allow Dtd on XmlReader,"Prohibit DTD processing when using XmlReader on untrusted sources. Enabling DTD processing on the XML reader and using UrlResolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3056,UseXmlReaderForLoad,System.Xml,#N/A,Use XmlReader for Load,"Do not use unsafe overloads of System.Xml.XmlDocument/XmlDataDocument Load. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3057,DoNotUseLoadXml,System.Xml,#N/A,Do not use LoadXml,"Do not use unsafe overloads of System.Xml.XmlDocument/XmlDataDocument LoadXml API. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3058,DoNotUseSetInnerXml,System.Xml,#N/A,Do not use SetInnerXml,"Do not use the unsafe setter of InnerXml property of System.Xml.XmlDocument/XmlDataDocument. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3059,UseXmlReaderForXPathDocument,System.Xml,#N/A,Use XmlReader for XPathDocument,"Do not use unsafe overloads of the constructor for System.Xml.XPath.Xpath.XPathDocument. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3060,UseXmlReaderForSchemaRead,System.Xml,#N/A,Use XmlReader for Schema Read,"Do not use unsafe overloads of System.Xml.Schema.XmlSchema.Read. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3061,DoNotAddStringsToXmlSchema,System.Xml,#N/A,Do not add strings to Xml schema,"Do not use unsafe overloads of System.Xml.Schema.XmlSchemaCollection.Add. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3062,UseXmlReaderForValidatingReader,System.Xml,#N/A,Use XmlReader for ValidatingReader,"Configure System.Xml.XmlValidatingReader to validate the parsed XML. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3063,UseXmlReaderForDataSetReadXml,Desktop,#N/A,Use XmlReader for DataSet ReadXml,"Do not use unsafe overloads of System.Data.DataSet.ReadXml. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,High,Yes,,, -CA3064,UseXmlReaderForDataSetReadXmlSchema,Desktop,#N/A,Use XmlReader for DataSet ReadXmlSchema,"Do not use unsafe overloads of System.Data.DataSet.ReadXmlSchema. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,High,Yes,,, -CA3065,ReviewDataViewCollectionString,Desktop,#N/A,Review DataView CollectionString,"Review code to insure that usage of System.Data.DataViewManager.DataViewSettingCollectionString input is sanitized to not contain DTD. Enabling DTD processing on the XML reader and using UrlResolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,High,Yes,,, -CA3066,ReviewWebControlForSet_Data,System.Web,#N/A,Review WebControl for set_Data,"Review code to insure that System.Web.UI.WebControls.XmlDataSource::Data is set from a trusted source. This pattern internally enables DTD processing in XML and uses UrlResolver for resolving external XML entities, which, on untrusted input, may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,@michaelcfanning to review, -CA3067,ReviewWebControlForSet_DocumentContent,System.Web,#N/A,Review WebControl for set_DocumentContent,"Review code to insure that System.Web.UI.WebControls.Xml::DocumentContent is set from a trusted source. This pattern internally enables DTD processing in XML and uses UrlResolver for resolving external XML entities, which, on untrusted input, may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,@michaelcfanning to review, -CA3068,TextReaderImplNeedsSettingsAndResolver,System.Xml,#N/A,TextReaderImpl needs settings and resolver,"Do not use unsafe overloads of the constructor for the System.Xml.XmlTextReaderImpl. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3069,ReviewDtdProcessingAssignment,System.Xml,#N/A,Review DtdProcessing assignment,"Review all code that enables DtdProcessing to insure that it is necessary and properly documented. Enabling DTD processing on the XML reader and using UrlResolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3070,UseXmlReaderForDeserialize,System.Xml,#N/A,Use XmlReader for Deserialize,"Do not use unsafe overloads of System.Xml.Serialization.XmlSerializer.Deserialize. This API internally enables DTD processing on the XML reader instance used but doesn't allow external entity resolution, enabling the attacker to DoS the machine processing the XML with a single especially crafted XML input.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3071,UseXmlReaderForDataTableReadXml,Desktop,#N/A,Use XmlReader for DataTable ReadXml,"Do not use unsafe overloads of System.Data.DataTable.ReadXml. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,High,Yes,,, -CA3072,UseXmlReaderForDataTableReadXmlSchema,Desktop,#N/A,Use XmlReader for DataTable ReadXmlSchema,"Checks for usage of an unsafe overload of System.Data.DataTable.ReadXmlSchema. This API internally enables DTD processing on the XML reader instance used, and uses UrlResolver for resolving external XML entities. The outcome is information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,High,Yes,,, -CA3073,ReviewTrustedXsltUse,System.Xml,#N/A,Review Trusted Xslt use,"Review code to insure that System.Xml.Xsl.XsltSettings::TrustedXslt is set from a trusted source. This pattern allows processing script within XSL, which, on untrusted XSL input, may lead to malicious code execution.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA3074,ReviewClassesDerivedFromXmlTextReader,System.Xml,#N/A,Review classes derived from XmlTextReader,"Review code to insure that DTD prosessing is disabled on all instances of classes derived from System.Xml.XmlTextReader. Enabling DTD processing on the XML reader and using UrlResolver for resolving external XML entities may lead to information disclosure. Content from file system or network shares for the machine processing the XML can be exposed to attacker. In addition, an attacker can use this as a DoS vector.",No,,,,,,,,No,,These will be consolidated into two or three new rules, -CA5122,PInvokesShouldNotBeSafeCriticalFxCopRule,System.Runtime,#N/A,#N/A,#N/A,No,,,,,,,Low,No,,, -CA5350,DoNotUseWeakCryptographicAlgorithms,System.Security.Cryptography.Algorithms,#N/A,Do Not Use Weak Cryptographic Algorithms,"Cryptographic algorithms degrade over time as attacks become for advances to attacker get access to more computation. Depending on the type and application of this cryptographic algorithm, further degradation of the cryptographic strength of it may allow attackers to read enciphered messages, tamper with enciphered? messages, forge digital signatures, tamper with hashed content, or otherwise compromise any cryptosystem based on this algorithm. Replace encryption uses with the AES algorithm (AES-256, AES-192 and AES-128 are acceptable) with a key length greater than or equal to 128 bits. Replace hashing uses with a hashing function in the SHA-2 family, such as SHA-2 512, SHA-2 384, or SHA-2 256.",No,,,,,,,,Ported,,, -CA5351,DoNotUseBrokenCryptographicAlgorithms,System.Security.Cryptography.Algorithms,#N/A,Do Not Use Broken Cryptographic Algorithms,"An attack making it computationally feasible to break this algorithm exists. This allows attackers to break the cryptographic guarantees it is designed to provide. Depending on the type and application of this cryptographic algorithm, this may allow attackers to read enciphered messages, tamper with enciphered? messages, forge digital signatures, tamper with hashed content, or otherwise compromise any cryptosystem based on this algorithm. Replace encryption uses with the AES algorithm (AES-256, AES-192 and AES-128 are acceptable) with a key length greater than or equal to 128 bits. Replace hashing uses with a hashing function in the SHA-2 family, such as SHA512, SHA384, or SHA256. Replace digital signature uses with RSA with a key length greater than or equal to 2048-bits, or ECDSA with a key length greater than or equal to 256 bits.",No,,,,,,,,Ported,,, -CA5352,RC2CannotBeUsed,System.Security.Cryptography.Algorithms,#N/A,Do not use RC2,RC2 is banned by SDL,No,,,,,,,,No,,merged into CA5351, -CA5353,TripleDESCannotBeUsed,System.Security.Cryptography.Algorithms,#N/A,Do not use TripleDES,TripleDES is not recommended by SDL,No,,,,,,,,No,,merged into CA5350, -CA5354,SHA1CannotBeUsed,System.Security.Cryptography.Algorithms,#N/A,Do not use SHA1,SHA-1 is banned by SDL,No,,,,,,,,No,,merged into CA5350, -CA5355,RIPEMD160IsNotRecommended,System.Security.Cryptography.Algorithms,#N/A,Do not use RIPEMD160,RIPEMD-160 is banned by SDL,No,,,,,,,,No,,merged into CA5350, -CA5356,DSACannotBeUsed,System.Security.Cryptography.Algorithms,#N/A,Do not use DSA,DSA is banned by SDL,No,,,,,,,,No,,merged into CA5351, -CA5357,RijndaelCannotBeUsed,System.Security.Cryptography.Algorithms,#N/A,Do not use Rijndael,Rijndael is not recommended by SDL,No,,,,,,,,No,,deleted form SDL, -CA900,AptcaAssembliesShouldBeReviewed,System.Runtime,#N/A,Aptca assemblies should be reviewed,Microsoft only allows certain assemblies to have the AllowPartiallyTrustedCallers attribute. This rule can be ignored if the assembly is not for distribution outside of Microsoft.,No,,,,,,,,No,,, -CA901,AptcaTypesShouldBeReviewed,System.Runtime,#N/A,Aptca types should be reviewed,"Types not on the list must either have both a LinkDemand and an InheritanceDemand, or have a LinkDemand and be sealed. This is a requirement of RTM security signoff.",No,,,,,,,,No,,, -CA908,AvoidTypesThatRequireJitCompilationInPrecompiledAssemblies,System.Runtime,#N/A,Avoid types that require JIT compilation in precompiled assemblies,"Assemblies that are precompiled (using ngen.exe) should only instantiate generic types that will not cause JIT compilation at runtime. Generic types with value type type parameters (outside of a special set of supported runtime generic types) will always cause JIT compilation, even if the encapsulating assembly has been precompiled. If this is not an precompiled assembly this message should be suppressed or this rule should be disabled.",No,,,,,,,,No,,, -CA909,UseFrameworksThatSatisfySecurityRequirements,System.Runtime,#N/A,#N/A,#N/A,No,,,,,,,,No,,Deprecated rule checking for insecure/beta framework use, -RS0024,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,The contents of the public API files are invalid,#N/A,,,,,,ApiDesign,,,Ported,,, -RS0012,#N/A,System.Collections.Immutable,Roslyn.Diagnostics.Analyzers,Do not call ToImmutableArray on an ImmutableArray value,#N/A,,,,,,Reliability,,,Ported,,, -CA1309,UseOrdinalStringComparison,System.Runtime,System.Runtime.Analyzers,Use ordinal stringcomparison,"A string comparison operation that is nonlinguistic does not set the StringComparison parameter to either Ordinal or OrdinalIgnoreCase. By explicitly setting the parameter to either StringComparison.Ordinal or StringComparison.OrdinalIgnoreCase, your code often gains speed, becomes more correct, and becomes more reliable.",Yes,450803,879,0.001949854,2899.697623,Globalization,,High,Ported,,, -CA1810,InitializeReferenceTypeStaticFieldsInline,Microsoft.QualityGuidelines,#N/A,Initialize reference type static fields inline,"When a type declares an explicit static constructor, the just-in-time (JIT) compiler adds a check to each static method and instance constructor of the type to make sure that the static constructor was previously called. Static constructor checks can decrease performance.",Yes,755408,2731,0.003615265,1625.933867,Performance,,High,Ported,,,None -CA1813,AvoidUnsealedAttributes,System.Runtime,System.Runtime.Analyzers,Avoid unsealed attributes,"The .NET Framework class library provides methods for retrieving custom attributes. By default, these methods search the attribute inheritance hierarchy. Sealing the attribute eliminates the search through the inheritance hierarchy and can improve performance.",Yes,219135,401,0.001829922,2918.545808,Performance,,High,Ported,,, -CA1820,TestForEmptyStringsUsingStringLength,System.Runtime,System.Runtime.Analyzers,Test for empty strings using string length,Comparing strings by using the String.Length property or the String.IsNullOrEmpty method is significantly faster than using Equals.,Yes,1121246,2134,0.00190324,3178.633057,Performance,,High,Ported,,, -CA2002,DoNotLockOnObjectsWithWeakIdentity,System.Runtime,System.Runtime.Analyzers,Do not lock on objects with weak identity,An object is said to have a weak identity when it can be directly accessed across application domain boundaries. A thread that tries to acquire a lock on an object that has a weak identity can be blocked by a second thread in a different application domain that has a lock on the same object.,Yes,123953,440,0.003549733,1434.828387,Reliability,,High,Ported,,, -CA2153,DoNotCatchCorruptedStateExceptionsInGeneralHandlers,System.Runtime,Desktop.Analyzers,Do not catch corrupted state exceptions in general handlers.,Do not author general catch handlers in code that receives corrupted state exceptions.,No,,,,,Security,,,Ported,,, -CA2200,RethrowToPreserveStackDetails,Microsoft.QualityGuidelines,Microsoft.AnalyzerPowerPack,Rethrow to preserve stack details,"An exception is rethrown and the exception is explicitly specified in the throw statement. If an exception is rethrown by specifying the exception in the throw statement, the list of method calls between the original method that threw the exception and the current method is lost.",Yes,713166,2048,0.002871702,2038.230737,Usage,,High,Ported,,,None -CA2201,DoNotRaiseReservedExceptionTypes,System.Runtime,#N/A,Do not raise reserved exception types,This makes the original error difficult to detect and debug.,Yes,1439723,9215,0.006400537,962.150389,Usage,,High,Ported,,,None -CA2207,InitializeValueTypeStaticFieldsInline,Microsoft.QualityGuidelines,#N/A,Initialize value type static fields inline,"A value type declares an explicit static constructor. To fix a violation of this rule, initialize all static data when it is declared and remove the static constructor.",Yes,13270,20,0.001507159,2735.524857,Usage,,High,Ported,,,None -CA2213,DisposableFieldsShouldBeDisposed,System.Runtime,System.Runtime.Analyzers,Disposable fields should be disposed,A type that implements System.IDisposable declares fields that are of types that also implement IDisposable. The Dispose method of the field is not called by the Dispose method of the declaring type.,Yes,347843,920,0.002644871,2095.142804,Usage,,High,Ported,,,Dataflow -CA2214,DoNotCallOverridableMethodsInConstructors,Microsoft.QualityGuidelines,Microsoft.AnalyzerPowerPack,Do not call overridable methods in constructors,"When a constructor calls a virtual method, the constructor for the instance that invokes the method may not have executed.",Yes,681532,2824,0.004143606,1407.828453,Usage,,High,Ported,,,None -RS0007,#N/A,System.Runtime,Roslyn.Diagnostics.Analyzers,Avoid zero-length array allocations.,#N/A,,,,,,Performance,,,Ported,,, -RS0014,#N/A,System.Runtime,Roslyn.Diagnostics.Analyzers,Do not use Enumerable methods on indexable collections. Instead use the collection directly,This collection is directly indexable. Going through LINQ here causes unnecessary allocations and CPU work.,,,,,,Performance,,,Ported,,, -CA1401,PInvokesShouldNotBeVisible,System.Runtime.InteropServices,System.Runtime.InteropServices.Analyzers,PInvokes should not be visible,A public or protected method in a public type has the System.Runtime.InteropServices.DllImportAttribute attribute (also implemented by the Declare keyword in Visual Basic). Such methods should not be exposed.,Yes,128953,940,0.007289478,701.0696455,Interoperability,,High,Ported,,, -CA1901,PInvokeDeclarationsShouldBePortable,System.Runtime.InteropServices,#N/A,PInvoke declarations should be portable,"This rule evaluates the size of each parameter and the return value of a P/Invoke, and verifies that the size of the parameter is correct when marshaled to unmanaged code on 32-bit and 64-bit operating systems.",Yes,114993,367,0.003191499,1585.672444,Portability,,High,Yes,,,See CA2101 -CA2101,SpecifyMarshalingForPInvokeStringArguments,System.Runtime.InteropServices,System.Runtime.InteropServices.Analyzers,Specify marshaling for PInvoke string arguments,"A platform invoke member allows partially trusted callers, has a string parameter, and does not explicitly marshal the string. This can cause a potential security vulnerability.",Yes,230439,998,0.004330864,1238.218475,Globalization,,High,Ported,,, -RS0015,#N/A,System.Runtime.InteropServices,Roslyn.Diagnostics.Analyzers,Always consume the value returned by methods marked with PreserveSigAttribute,"PreserveSigAttribute indicates that a method will return an HRESULT, rather than throwing an exception. Therefore, it is important to consume the HRESULT returned by the method, so that errors can be detected. Generally, this is done by calling Marshal.ThrowExceptionForHR.",,,,,,Reliability,,,Ported,,, -RS0020,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,unused code,#N/A,,,,,,Maintainability,,,,,, -RS0021,#N/A,Roslyn.Diagnostics,Roslyn.Diagnostics.Analyzers,Hidden (used by CodeFix),#N/A,,,,,,#N/A,,,,,, -RS0003,#N/A,System.Threading.Tasks,Roslyn.Diagnostics.Analyzers,Do not directly await a Task,#N/A,,,,,,Reliability,,,Ported,,, -RS0018,#N/A,System.Threading.Tasks,Roslyn.Diagnostics.Analyzers,Do not create tasks without passing a TaskScheduler,"Do not create tasks unless you are using one of the overloads that takes a TaskScheduler. The default is to schedule on TaskScheduler.Current, which would lead to deadlocks. Either use TaskScheduler.Default to schedule on the thread pool, or explicitly pass TaskScheduler.Current to make your intentions clear.",,,,,,Reliability,,,Ported,,, -RS0010,#N/A,XmlDocumentationComments,Roslyn.Diagnostics.Analyzers,Avoid using cref tags with a prefix,"Use of cref tags with prefixes should be avoided, since it prevents the compiler from verifying references and the IDE from updating references during refactorings. It is permissible to suppress this error at a single documentation site if the cref must use a prefix because the type being mentioned is not findable by the compiler. For example, if a cref is mentioning a special attribute in the full framework but you're in a file that compiles against the portable framework, or if you want to reference a type at higher layer of Roslyn, you should suppress the error. You should not suppress the error just because you want to take a shortcut and avoid using the full syntax.",,,,,,Documentation,,,Ported,,, -RS1001,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Missing diagnostic analyzer attribute,"Non-abstract sub-types of DiagnosticAnalyzer should be marked with DiagnosticAnalyzerAttribute(s). The argument to this attribute(s), if any, determine the supported languages for the analyzer. Analyzer types without this attribute will be ignored by the analysis engine.",,,,,,AnalyzerCorrectness,,,Ported,,, -RS1002,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Missing kind argument while registering an analyzer action,"You must specify at least one syntax/symbol kinds of interest while registering a syntax/symbol analyzer action. Otherwise, the registered action will be dead code and will never be invoked during analysis.",,,,,,AnalyzerCorrectness,,,Ported,,, -RS1003,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Unsupported SymbolKind argument while registering a symbol analyzer action,#N/A,,,,,,AnalyzerCorrectness,,,Ported,,, -RS1004,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Recommend adding language support to diagnostic analyzer,"Diagnostic analyzer is marked as supporting only one language, but the analyzer assembly doesn't seem to refer to any language specific CodeAnalysis assemblies, and so is likely to work for more than one language. Consider adding an additional language argument to DiagnosticAnalyzerAttribute.",,,,,,AnalyzerCorrectness,,,Ported,,, -RS1005,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,ReportDiagnostic invoked with an unsupported DiagnosticDescriptor,"ReportDiagnostic should only be invoked with supported DiagnosticDescriptors that are returned from DiagnosticAnalyzer.SupportedDiagnostics property. Otherwise, the reported diagnostic will be filtered out by the analysis engine.",,,,,,AnalyzerCorrectness,,,Ported,,, -RS1006,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Invalid type argument for DiagnosticAnalyzer's Register method,"DiagnosticAnalyzer's language-specific Register methods, such as RegisterSyntaxNodeAction, RegisterCodeBlockStartAction and RegisterCodeBlockEndAction, expect a language-specific 'SyntaxKind' type argument for it's 'TLanguageKindEnumName' type parameter. Otherwise, the registered analyzer action can never be invoked during analysis.",,,,,,AnalyzerCorrectness,,,Ported,,, -RS1007,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Provide localizable arguments to diagnostic descriptor constructor,"If your diagnostic analyzer and it's reported diagnostics need to be localizable, then the supported DiagnosticDescriptors used for constructing the diagnostics must also be localizable. If so, then localizable argument(s) must be provided for parameter 'title' (and optionally 'description') to the diagnostic descriptor constructor to ensure that the descriptor is localizable.",,,,,,AnalyzerLocalization,,,Ported,,, -RS1008,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Avoid storing per-compilation data into the fields of a diagnostic analyzer,"Instance of a diagnostic analyzer might outlive the lifetime of compilation. Hence, storing per-compilation data, such as symbols, into the fields of a diagnostic analyzer might cause stale compilations to stay alive and cause memory leaks. Instead, you should store this data on a separate type instantiated in a compilation start action, registered using 'AnalysisContext.RegisterCompilationStartAction' API. An instance of this type will be created per-compilation and it won't outlive compilation's lifetime, hence avoiding memory leaks.",,,,,,AnalyzerPerformance,,,Ported,,, -RS1009,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Only internal implementations of this interface are allowed,The author of this interface did not intend to have third party implementations of this interface and reserves the right to change it. Implementing this interface could therefore result in a source or binary compatibility issue with a future version of this interface.,,,,,,Compatibility,,,Ported,,, -RS1010,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Create code actions should have a unique EquivalenceKey for FixAll occurrences support,"A CodeFixProvider that intends to support fix all occurrences must classify the registered code actions into equivalence classes by assigning it an explicit, non-null equivalence key which is unique across all registered code actions by this fixer. This enables the FixAllProvider to fix all diagnostics in the required scope by applying code actions from this fixer that are in the equivalence class of the trigger code action.",,,,,,Correctness,,,Ported,,, -RS1011,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Use code actions that have a unique EquivalenceKey for FixAll occurrences support,"A CodeFixProvider that intends to support fix all occurrences must classify the registered code actions into equivalence classes by assigning it an explicit, non-null equivalence key which is unique across all registered code actions by this fixer. This enables the FixAllProvider to fix all diagnostics in the required scope by applying code actions from this fixer that are in the equivalence class of the trigger code action.",,,,,,Correctness,,,Ported,,, -RS1012,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Start action has no registered actions,"An analyzer start action enables performing stateful analysis over a given code unit, such as a code block, compilation, etc. Careful design is necessary to achieve efficient analyzer execution without memory leaks. Use the following guidelines for writing such analyzers: 1. Define a new scope for the registered start action, possibly with a private nested type for analyzing each code unit. 2. If required, define and initialize state in the start action. 3. Register at least one non-end action that refers to this state in the start action. If no such action is necessary, consider replacing the start action with a non-start action. For example, a CodeBlockStartAction with no registered actions or only a registered CodeBlockEndAction should be replaced with a CodeBlockAction. 4. If required, register an end action to report diagnostics based on the final state.",,,,,,AnalyzerPerformance,,,Ported,,, -RS1013,#N/A,Microsoft.CodeAnalysis,Microsoft.CodeAnalysis.Analyzers,Start action has no registered non-end actions,"An analyzer start action enables performing stateful analysis over a given code unit, such as a code block, compilation, etc. Careful design is necessary to achieve efficient analyzer execution without memory leaks. Use the following guidelines for writing such analyzers: 1. Define a new scope for the registered start action, possibly with a private nested type for analyzing each code unit. 2. If required, define and initialize state in the start action. 3. Register at least one non-end action that refers to this state in the start action. If no such action is necessary, consider replacing the start action with a non-start action. For example, a CodeBlockStartAction with no registered actions or only a registered CodeBlockEndAction should be replaced with a CodeBlockAction. 4. If required, register an end action to report diagnostics based on the final state.",,,,,,AnalyzerPerformance,,,Ported,,, diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-configuration.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-configuration.md index 0f8a73f4fd59..fd195e9fda5c 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-configuration.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-configuration.md @@ -2,7 +2,7 @@ # Analyzer Configuration -All the analyzer NuGet packages produced in this repo support _.editorconfig based analyzer configuration_. End users can configure the behavior of specific CA rule(s) OR all configurable CA rules by specifying supported key-value pair options in an `.editorconfig` file. You can read more about `.editorconfig` format [here](https://editorconfig.org/). +The `Microsoft.CodeAnalysis.NetAnalyzers` analyzers support _.editorconfig based analyzer configuration_. End users can configure the behavior of specific CA rule(s) OR all configurable CA rules by specifying supported key-value pair options in an `.editorconfig` file. You can read more about `.editorconfig` format [here](https://editorconfig.org/). ## .editorconfig format @@ -26,27 +26,9 @@ For example, end users can configure the analyzed API surface for analyzers usin ## Enabling .editorconfig based configuration -### VS2019 16.3 and later + Analyzer package version 3.3.x and later +Create an `.editorconfig` file containing the options in the directory covering the scope you want — a document, folder, project, solution, or the whole repository. The same file can also carry `.editorconfig` based diagnostic severity entries; see [Configuration files for code analysis rules](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/configuration-files) and [rule severity](https://learn.microsoft.com/visualstudio/code-quality/use-roslyn-analyzers#rule-severity). -End users can enable `.editorconfig` based configuration for individual documents, folders, projects, solution or entire repo by creating an `.editorconfig` file with the options in the corresponding directory. This file can also contain `.editorconfig` based diagnostic severity configuration entries. See [here](https://learn.microsoft.com/visualstudio/code-quality/use-roslyn-analyzers#rule-severity) for more details. - -### Prior to VS2019 16.3 or using an analyzer package version prior to 3.3.x - -1. Per-project `.editorconfig` file: End users can enable `.editorconfig` based configuration for individual projects by just copying the `.editorconfig` file with the options to the project root directory. -2. Shared `.editorconfig` file: If you would like to share a common `.editorconfig` file between projects, say `<%PathToSharedEditorConfig%>\.editorconfig`, then you should add the following MSBuild property group and item group to a shared props file that is imported _before_ the FxCop analyzer props files (that come from the FxCop analyzer NuGet package reference): - -```xml - - true - - - - -``` - -Note that this additional file based approach is also supported on VS2019 16.3 and later releases for backwards compatibility. - -**The additional file based approach is no longer supported starting in Microsoft.CodeAnalysis.NetAnalyzers v5.0.4. It will be implicitly discovered (if the file is in the project's directory or any ancestor directory), or it should be converted into a 'globalconfig'. See [Configuration files for code analysis rules](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/configuration-files).** +Configuration is discovered implicitly from the project directory and its ancestors. The older `AdditionalFiles` based approach was removed in `Microsoft.CodeAnalysis.NetAnalyzers` v5.0.4; convert any remaining usage to an `.editorconfig` or a `.globalconfig`. ## Supported .editorconfig options @@ -92,14 +74,11 @@ Configurable Rules: [CA1708](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1708), [CA1710](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1710), [CA1711](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1711), -[CA1714](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1714), [CA1715](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1715), [CA1716](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1716), -[CA1717](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1717), [CA1720](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1720), [CA1721](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1721), [CA1725](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1725), -[CA1801](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1801), [CA1802](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1802), [CA1815](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1815), [CA1819](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1819), @@ -714,7 +693,7 @@ Option Name: `analyzed_symbol_kinds` Configurable Rules: [CA1716](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1716) -Option Values: One or more fields of enum [Microsoft.CodeAnalysis.SymbolKind](https://roslynsourceindex.azurewebsites.net/#Microsoft.CodeAnalysis/Symbols/SymbolKind.cs,30fd9c0834bef6ff) as a comma separated list. +Option Values: One or more fields of enum [Microsoft.CodeAnalysis.SymbolKind](https://learn.microsoft.com/dotnet/api/microsoft.codeanalysis.symbolkind) as a comma separated list. Default Value: `Namespace, NamedType, Method, Property, Event, Parameter` diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-reference-page-template.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-reference-page-template.md deleted file mode 100644 index b2b39050479f..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/analyzer-reference-page-template.md +++ /dev/null @@ -1,31 +0,0 @@ -# RULEID: Friendly rule name - -## Cause - -## Rule description - -## How to fix violations - -## When to suppress warnings - -## Example of a violation - -### Description - -### Code - -``` -``` - -## Example of how to fix - -### Description - -### Code - -``` -``` - -## Related rules - -[RULEID: Friendly related rule name](https://stable-uris-r-us.com/MyRuleId_MyFriendlyRuleName.md) diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/documenting-your-analyzers.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/documenting-your-analyzers.md deleted file mode 100644 index 6670f4c80948..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/documenting-your-analyzers.md +++ /dev/null @@ -1,45 +0,0 @@ -# Documenting your analyzers - -We recommend that you provide reference documentation for each of your analyzers, as follows: - -1. Create a directory `docs` at the root of your analyzers project. - -2. Create a subdirectory `docs\reference`. - - The rationale for this suggestion is that you might have other documents you want to put in your `docs` directory. Keeping the reference pages together in their own subdirectory makes them easier to distinguish from your other documentation. The more analyzer project authors that follow this convention, the easier it will be for analyzer users to find the documentation they need. It will also make it easier for tools that want to search, aggregate, or otherwise process the documentation pages from multiple analyzer projects. - -3. Make a copy of the [Rule reference page template](https://github.com/Microsoft/sarif-sdk/blob/main/docs/Rule%20reference%20page%20template.md) in your `docs/reference` directory, and name it according to the following convention: - - `_.md` - - For example, if your analyzer package Great Analyzers prefixes its rule ids with "`GA`", and you have a rule "code should not be evil", then your reference page file would be named - - `GA0001_CodeShouldNotBeEvil.md` - - The template is based on the format of the MSDN reference pages for the Code Analysis rules. - -4. Fill in the template with information about your analyzer. - -5. **Recommended**: Provide a stable URI for each reference page. -If you use a URI that points directly into your GitHub repo, then the URI will -change whenever you rearrange your source tree, or rename your repo. -Remember that this URI will be baked into your analyzer (see Step 6 below). - - Use the stable URI everywhere, both in your analyzer (Step 6) and in any -cross-references you create in the **Related rules** sections of your reference pages. - - Commercial providers of stable URIs include bit.ly and tinyurl.com, -but you can use any source for the stable URI, including (for example) -any facility your company might provide for registering URIs. - -6. In your analyzers, set the value of the `HelpLinkUri` property of -your `DiagnosticDescriptor` to the (preferably stable) URI you provided. - -**Note** Some analyzers produce diagnostics with more than one rule id. -For example, the [`EquatableAnalyzer`](https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.ApiDesignGuidelines.Analyzers/Core/EquatableAnalyzer.cs) in [`Microsoft.ApiDesignGuidelines.Analyzers`](https://github.com/dotnet/roslyn-analyzers/tree/main/src/Microsoft.ApiDesignGuidelines.Analyzers) -produces diagnostics with two rule ids: -`CA1066` ("Implement IEquatable\ when overriding Object.Equals") -and `CA1067` ("Override Object.Equals when implementing IEquatable\"). -In such a case, create a separate reference page for each rule id. -In this case, we would have `CA1066_ImplementIEquatableOfTWhenOverridingObjectEquals.md` -and `CA1067_OverrideObjectEqualsWhenImplementingIEquatableOfT.md`. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/guidelines-for-new-rules.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/guidelines-for-new-rules.md index 43d1bbbd2f02..9e00c9d0f3b0 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/guidelines-for-new-rules.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/guidelines-for-new-rules.md @@ -4,17 +4,19 @@ 1. File an issue describing your proposed rule prior to working on a PR. This will ensure that the rule gets triaged and there is no duplicate work involved from an existing rule OR another contributor working on a similar rule. 1. For .NET API related analyzer suggestions, please open an issue at [dotnet/runtime/issues](https://github.com/dotnet/runtime/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) with [code-analyzer](https://github.com/dotnet/runtime/issues?q=is%3Aopen+is%3Aissue+label%3Acode-analyzer+sort%3Aupdated-desc) label. - 2. For non-API related analyzer suggestions, please open an issue in this repo over [here](https://github.com/dotnet/roslyn-analyzers/issues/new?template=suggest-a-new-rule.md). + 2. For non-API related analyzer suggestions, please open an issue in [dotnet/sdk](https://github.com/dotnet/sdk/issues/new/choose) describing the rule, the scenarios it catches, and the scenarios it must not flag. -2. Newly proposed rule would be tagged with [Needs-Review](https://github.com/dotnet/roslyn-analyzers/labels/Needs-Review) label. An [Approved-Rule](https://github.com/dotnet/roslyn-analyzers/labels/Approved-Rule) label indicates that the proposal has been reviewed and a PR to implement the rule would be accepted. +2. A rule proposal is implemented only once it has been reviewed and accepted. Rule implementation PRs are labelled [Area-Microsoft.CodeAnalysis.NetAnalyzers](https://github.com/dotnet/sdk/labels/Area-Microsoft.CodeAnalysis.NetAnalyzers). 3. Follow the below steps to choose the appropriate **rule ID** for the new rule: - 1. Choose the **applicable 'category'** for the new rule. See [DiagnosticCategoryAndIdRanges.txt](.//src//Utilities//Compiler//DiagnosticCategoryAndIdRanges.txt) for current diagnostic categories, and the CA IDs currently in use for each category. - 2. Choose the **next available CA ID** for the chosen 'category' from [DiagnosticCategoryAndIdRanges.txt](.//src//Utilities//Compiler//DiagnosticCategoryAndIdRanges.txt). + 1. Choose the **applicable 'category'** for the new rule. See [DiagnosticCategoryAndIdRanges.txt](../src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt) for current diagnostic categories, and the CA IDs currently in use for each category. + 2. Choose the **next available CA ID** for the chosen 'category' from [DiagnosticCategoryAndIdRanges.txt](../src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt). For example, while adding a new rule in the `Performance` category, if `CA1800-CA1829` represents the current CA ID range in `DiagnosticCategoryAndIdRanges.txt`, then: 1. Choose `CA1830` as the rule ID for your rule. - 2. Update the range for `Performance` in [DiagnosticCategoryAndIdRanges.txt](.//src//Utilities//Compiler//DiagnosticCategoryAndIdRanges.txt) to `CA1800-CA1830` + 2. Update the range for `Performance` in [DiagnosticCategoryAndIdRanges.txt](../src/Utilities/Compiler/DiagnosticCategoryAndIdRanges.txt) to `CA1800-CA1830` + + That file records only *merged* work, so the next ID is routinely already claimed by an open PR or an in-flight branch. [`NextDiagnosticId.cs`](../../../.github/skills/add-net-analyzer/scripts/NextDiagnosticId.cs) scans forward past anything claimed in the working tree, on a local branch, or in an open PR's title or body. You can refer to the [official documentation](https://learn.microsoft.com/visualstudio/code-quality/code-analysis-for-managed-code-warnings) for all released CA rules by rule category. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/make-static.png b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/make-static.png deleted file mode 100644 index 0e9961faccfc..000000000000 Binary files a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/make-static.png and /dev/null differ diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/netcore-getting-started.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/netcore-getting-started.md index f66232e121bd..23fc93329d39 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/netcore-getting-started.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/netcore-getting-started.md @@ -1,22 +1,32 @@ -# Getting started with .NetCore/.NetStandard Analyzers - -1. Read through the [.NET Compiler Platform SDK](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/) for understanding the different Roslyn elements `(Syntax Nodes, Tokens, Trivia)`. The factory methods and APIs are super useful. -2. Learning this [tutorial](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix) for custom analyzers and trying it is quite useful to get started. It is an easy, step-by-step tutorial, and it also has a template for generating an analyzer, fixer and unit test, which saves time. The tutorial has a good explanation and would give you a good understanding of how Roslyn analyzers work. -3. Clone the `dotnet/roslyn-analyzers` repo, install all required dependencies and build the repo by the [instructions](https://github.com/dotnet/roslyn-analyzers#getting-started). -4. Follow the coding style of the `dotnet/roslyn-analyzers` repo. [Guidelines about new rule id and doc](guidelines-for-new-rules.md). -5. Open `RoslynAnalyzers.sln` and open the package where you are creating your analyzer. In our case, it is mostly `Microsoft.CodeAnalysis.NetAnalyzers`->`Microsoft.NetCore.Analyzers`. Create your analyzer and/or fixer class in the corresponding folder. -6. Add a message, title and description for your analyzer into `MicrosoftNetCoreAnalyzersResources.resx` and build the repo before using the analyzer. The language-specific resources will be generated. -7. Make sure you have done everything from the [Definition of done list](#definition-of-done) below. - -## Branch Definitions - -|Branch| SDK | Description| -|--------|--------|--------| -|[2.9.x](https://github.com/dotnet/roslyn-analyzers/tree/2.9.x)| Does not ship in the .NET SDK | A special branch compatible with Visual Studio 2017 where security analyzers are shipped from. -|[main](https://github.com/dotnet/roslyn-analyzers/tree/main)| .NET SDK 8.0.0xx | Currently active branch. All work should target this branch unless it is a bugfix for a previous release -|[release/5.0.3xx](https://github.com/dotnet/roslyn-analyzers/tree/release/5.0.3xx)| .NET SDK 5.0.3xx | Servicing branch for the .NET 5 SDK. -|[release/6.0.1xx](https://github.com/dotnet/roslyn-analyzers/tree/release/6.0.1xx)| .NET SDK 6.0.0xx | Servicing branch for the .NET 6 SDK. -|[release/7.0.1xx](https://github.com/dotnet/roslyn-analyzers/tree/release/7.0.1xx)| .NET SDK 7.0.1xx | Servicing branch for the .NET 7 SDK. +# Getting started with .NET analyzers + +The `CA####` analyzers live in `src/Microsoft.CodeAnalysis.NetAnalyzers`, migrated into +`dotnet/sdk` from the retired `dotnet/roslyn-analyzers` repo. PRs target `dotnet/sdk`; +servicing fixes target the relevant `release/..xx` branch. + +For the step-by-step authoring workflow — ID allocation, resource strings, release +tracking, tests — use the +[`add-net-analyzer`](../../../.github/skills/add-net-analyzer/SKILL.md) skill and +[`AGENTS.md`](../AGENTS.md). This document covers the parts that skill doesn't: the +definition of done, and validating a rule against real code. + +## Background reading + +1. The [.NET Compiler Platform SDK](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/) + overview, for the Roslyn concepts (syntax nodes, tokens, trivia) and the factory APIs. +2. The [analyzer/code-fix tutorial](https://learn.microsoft.com/dotnet/csharp/roslyn-sdk/tutorials/how-to-write-csharp-analyzer-code-fix), + which walks an analyzer, a fixer, and unit tests end to end. +3. [Guidelines about new rule ids and docs](guidelines-for-new-rules.md). + +## Building + +```powershell +./build.cmd -projects src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.slnx -c Debug +``` + +Use `./build.sh` on Linux/macOS. Do **not** pass `-restore`/`-build` alongside `-projects`; +the driver already implies them and the combination fails. Output lands in +`artifacts/bin/Microsoft.CodeAnalysis.{,CSharp.,VisualBasic.}NetAnalyzers//netstandard2.0/`. ## Definition of done @@ -35,61 +45,128 @@ - Do not separate analyzer tests from code fix tests. If the analyzer has a code fix, then write all your tests as code fix tests. - Calling `VerifyCodeFixAsync(source, source)` verifies that the analyzer either does not produce diagnostics, or produces diagnostics where no code fix is offered. - Calling `VerifyCodeFixAsync(source, fixedSource)` verifies the diagnostics (analyzer testing) and verifies that the code fix on source produces the expected output. -- Run the analyzer locally against `dotnet/runtime` and `dotnet/roslyn-analyzers` [(instructions)](#testing-against-the-runtime-and-roslyn-analyzers-repo). + - Fix-all is part of the fixer. `WellKnownFixAllProviders.BatchFixer` applies every fix + against the original document and merges the results, which produces a wrong tree when + diagnostics overlap or nest. Derive from + [`OrderedCodeFixProvider`](../src/Microsoft.CodeAnalysis.NetAnalyzers/OrderedCodeFixProvider.cs) + instead, and cover the nested case in tests. +- Run the analyzer locally against `dotnet/runtime` and `dotnet/roslyn` ([instructions](#validating-against-a-real-codebase)). - Review each of the failures in those repositories and determine the course of action for each. - Use the failures to discover nuance and guide the implementation details. - - Run the analyzer against `dotnet/roslyn` [(instructions)](#testing-against-the-roslyn-repo), and if feasible with `dotnet/aspnetcore` repos. - Document for review: matching and non-matching scenarios, including any discovered nuance. - - All warnings and errors in these repos are addressed (to prevent build failures) - - `Info` level diagnostics do not need to be fully resolved or suppressed as they do not cause build failures + - All warnings and errors in these repos are addressed (to prevent build failures). + - `Info` level diagnostics do not need to be fully resolved or suppressed as they do not cause build failures. - Document for review: severity, default, categorization, numbering, titles, messages, and descriptions. - Create the appropriate documentation for [learn.microsoft.com](https://github.com/dotnet/docs/tree/main/docs/fundamentals/code-analysis/quality-rules) within **ONE WEEK**, instructions available on [Contribute docs for .NET code analysis rules to the .NET docs repository](https://learn.microsoft.com/contribute/dotnet/dotnet-contribute-code-analysis). -- PR merged into `dotnet/roslyn-analyzers`. +- PR merged into `dotnet/sdk`. - Validate the analyzer's behavior with end-to-end testing using the command-line and Visual Studio: - - Use `dotnet new console` and `dotnet build` from the command-line, updating the code to introduce diagnostics and ensuring warnings/errors are reported at the command-line - - Use Visual Studio to create a new project, introduce diagnostics, and observe the warnings/errors/info messages without invoking a build - -## Testing against the Runtime and Roslyn Analyzers repo - -1. Navigate to the root of the Roslyn-analyzers repo and run these commands: - - `cd roslyn-analyzers` - - Set `RUNTIMEPACKAGEVERSION` variable with a version value whose major part is equal to the major part of the version the [runtime](https://github.com/dotnet/runtime/blob/main/eng/Versions.props#L53)/[roslyn-analyzers](https://github.com/dotnet/roslyn-analyzers/blob/main/eng/Versions.props#L50) repo is using. Example: `set RUNTIMEPACKAGEVERSION=8.0.0` - - `build.cmd -ci /p:AssemblyVersion=%RUNTIMEPACKAGEVERSION% /p:AutoGenerateAssemblyVersion=false /p:OfficialBuild=true -c Release` - - `cd artifacts\bin\Microsoft.CodeAnalysis.CSharp.NetAnalyzers\Release\netstandard2.0` -2. Copy the two DLLs and replace the NuGet cache entries used by `dotnet/runtime` and `dotnet/roslyn-analyzers`. They might be in `"roslyn-analyzers/.packages/..."` (roslyn-analyzers) or `"%USERPROFILE%/.nuget/packages/... "` (runtime). You can check the exact path by building something in runtime with `/bl` and checking the binlog file (instructions for reading MSBuild binary logs are [here](https://github.com/dotnet/msbuild/blob/main/documentation/wiki/Binary-Log.md#replaying-a-binary-log)). - - Example: `copy /y *.dll %USERPROFILE%\.nuget\packages\Microsoft.CodeAnalysis.NetAnalyzers\%RUNTIMEPACKAGEVERSION%\analyzers\dotnet\cs` - - Note that the `RUNTIMEPACKAGEVERSION` value is different for the runtime and roslyn-analyzers repos -3. Build the roslyn-analyzers with `build.cmd`. Now new analyzers will be used from updated NuGet packages and you would see the warnings if diagnostics found. -4. If failures found, review each of the failures and determine the course of action for each. - - Improve analyzer to reduce false positives. Fix valid warnings, and in very rare edge cases, suppress them, when you finish handling all diagnostics found, could raise a PR with those fixes. -5. Make sure all failures addressed and corresponding PR(s) merged. -6. Switch to the runtime repo. -7. Add a row for your new analyzer ID with a value of `warning` to make sure it would warn for findings in the [CodeAnalysis.src.globalconfig](https://github.com/dotnet/runtime/blob/main/eng/CodeAnalysis.src.globalconfig) file. For example if you are authored a new analyzer with id `CA1234`, add a row: `dotnet_diagnostic.CA1234.severity = warning` -8. Build the runtime repo. Either do a complete build or build each repo separately (coreclr, libraries, mono). -9. In the case of no failure, introduce an error somewhere to prove that the rule ran. - - Be careful about in which project you are producing an error. Choose an API not having references from other APIs, or else its dependent API's will fail. -10. If failures found, repeat step 4-5 to evaluate and address all warnings. - - In case you want to [debug some failures](#debugging-analyzer-with-runtime-repo-projects). - -## Testing against the Roslyn repo - -1. Clone `dotnet/roslyn` and build it with this command: - - `Build.cmd -restore -Configuration Release` -2. Build `dotnet/roslyn-analyzers` in debug mode: - - `Build.cmd -Configuration Debug` -3. Run AnalyzerRunner from the Roslyn root directory to get the diagnostics. - - `.\artifacts\bin\AnalyzerRunner\Release\netcoreapp3.1\AnalyzerRunner.exe ..\roslyn-analyzers\artifacts\bin\Microsoft.NetCore.Analyzers.Package\Debug\netstandard2.0 .\Roslyn.sln /stats /concurrent /a AnalyzerNameToTest /log Output.txt` - - Do not forget to change the value after the `/a` option with your testing analyzer name. -The diagnostics reported by the analyzer will be listed in Output.txt. - -## Debugging analyzer with runtime repo projects - -1. Copy over the debug build of analyzer assemblies on top of the NetAnalyzers NuGet package in your packages folder. (Instructions are the same as the step 1 and 2 of [Testing against the Runtime repo](#testing-against-the-runtime-and-roslyn-analyzers-repo)) -2. Start VS and open a project you want to debug -3. Note the process ID for `ServiceHub.RoslynCodeAnalysisService.exe` corresponding to that VS instance - - If you are using a `Visual Studio` version older than version `16.8 Preview2`, then analyzers run in `devenv.exe`, and you will need to attach that process instead. - - Code fixes and analyzers run in different processes. If you want to debug the CodeFixProvider corresponding to the analyzer, attach `devenv.exe` instead. -4. Open another VS instance for `RoslynAnalyzers.sln` and set breakpoints in the analyzer solution where you want to debug -5. Attach to the above process ID with the RoslynAnalyzers debugger: `Debug -> Attach to Process...` -6. Start typing in the other project and the breakpoints should hit - - If breakpoints are not hitting then the RoslynAnalyzers.sln build might not be the same as the build you copied in step 1. Repeat the step again or check if you copied into the correct path. + - Use `dotnet new console` and `dotnet build` from the command-line, updating the code to introduce diagnostics and ensuring warnings/errors are reported at the command-line. + - Use Visual Studio to create a new project, introduce diagnostics, and observe the warnings/errors/info messages without invoking a build. + +## Validating against a real codebase + +Unit tests prove the rule fires. They say nothing about the false-positive rate, which is +what actually decides the `RuleLevel` and what reviewers will ask about. + +Since the analyzers migrated into `dotnet/sdk` they ship *inside* the SDK, at +`/sdk//Sdks/Microsoft.NET.Sdk/analyzers/`, laid down by +`PublishNETAnalyzers` in +[`GenerateLayout.targets`](../../Layout/redist/targets/GenerateLayout.targets). A repo that +only sets `` consumes that copy, so overwriting the NuGet cache does nothing +for it. A repo that `PackageReference`s `Microsoft.CodeAnalysis.NetAnalyzers` is the +reverse: the package carries a props file setting `EnableNETAnalyzers=false`, which switches +the SDK copy off in its favour. `dotnet/runtime` does the latter, in +[`eng/Analyzers.targets`](https://github.com/dotnet/runtime/blob/main/eng/Analyzers.targets). +Work out which of the two applies before copying anything. + +Either route below changes only what the **command line** uses. At design time Visual Studio +redirects `Microsoft.CodeAnalysis.NetAnalyzers.dll` out of the SDK to its own deployed copy +whenever the major and minor versions match, so VS keeps running the shipped analyzers and +your change appears to do nothing. Set `DOTNET_ANALYZER_REDIRECTING=0` before launching VS +to suppress it; +[`analyzer-redirecting.md`](../../../documentation/general/analyzer-redirecting.md) has the +matching rules. + +### Point the target repo at a locally built SDK + +The cleanest route. A full `build.cmd` produces a complete SDK containing your analyzers: + +```powershell +./build.cmd -c Release +# -> artifacts/bin/redist/Release/dotnet +``` + +Then run the target repo's build against it, either by setting `DOTNET_ROOT` and putting +that `dotnet` first on `PATH`, or by pointing the target repo's `global.json` at the +version it contains. + +### Overwrite the analyzers in an existing SDK + +Faster inner loop, and it avoids a full redist build. Build only the analyzer solution, +then copy the three assemblies over the SDK the target repo actually uses — often that +repo's own `.dotnet`. The copy below is PowerShell; use `cp` on Linux/macOS. + +```powershell +./build.cmd -projects src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.CodeAnalysis.NetAnalyzers.slnx -c Release + +$dest = "/.dotnet/sdk//Sdks/Microsoft.NET.Sdk/analyzers" +Copy-Item artifacts/bin/Microsoft.CodeAnalysis.CSharp.NetAnalyzers/Release/netstandard2.0/*.dll $dest -Force +Copy-Item artifacts/bin/Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers/Release/netstandard2.0/Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers.dll $dest -Force +``` + +If the target repo *does* pin the `Microsoft.CodeAnalysis.NetAnalyzers` package, copy into +`~/.nuget/packages/microsoft.codeanalysis.netanalyzers//analyzers/dotnet/` instead +— into **both** `cs` and `vb`, since the language-agnostic assembly is duplicated into each +— and build with `/p:AssemblyVersion= /p:AutoGenerateAssemblyVersion=false +/p:OfficialBuild=true` so the assembly version matches what the package declares. Build the +target repo with `/bl` and +[read the binlog](https://github.com/dotnet/msbuild/blob/main/documentation/wiki/Binary-Log.md#replaying-a-binary-log) +if you are unsure which copy is in play. + +### dotnet/runtime + +Set your rule to `warning` in +[`eng/CodeAnalysis.src.globalconfig`](https://github.com/dotnet/runtime/blob/main/eng/CodeAnalysis.src.globalconfig) +— e.g. `dotnet_diagnostic.CA1234.severity = warning` — then build. If nothing fires, +introduce a violation to prove the rule actually ran; pick a project nothing else depends +on, so a deliberate error doesn't cascade. + +Triage every hit. Reduce false positives in the analyzer, fix the genuine violations, and +suppress only in rare edge cases. + +### dotnet/roslyn + +`dotnet/roslyn` builds `AnalyzerRunner`, which reports diagnostics over a solution without +requiring an analyzer-enabled build of the whole repo. + +1. Build `dotnet/roslyn`: `./Build.cmd -restore -Configuration Release` (their `build.sh` on + Linux/macOS — see roslyn's own docs for its flags). +2. Build the analyzers here in `Debug`. +3. From the roslyn root, point `AnalyzerRunner` at the analyzer output directory. It + multi-targets .NET and .NET Framework, so pick the .NET build rather than taking the + first folder under `artifacts/bin/AnalyzerRunner/Release/`, and launch it through + `dotnet exec` so the path is the same on every platform: + + ```powershell + $runner = Get-ChildItem artifacts/bin/AnalyzerRunner/Release/*/AnalyzerRunner.dll | + Where-Object { $_.Directory.Name -notlike 'net4*' } | Select-Object -First 1 + dotnet exec $runner /artifacts/bin/Microsoft.CodeAnalysis.CSharp.NetAnalyzers/Debug/netstandard2.0 ` + ./Roslyn.slnx /stats /concurrent /a /log Output.txt + ``` + + The `/a` value is the analyzer type name. Results land in `Output.txt`. + +## Debugging an analyzer inside Visual Studio + +1. Build the analyzers in `Debug` and copy them into the SDK the target project uses, as + above. +2. Open the project you want to analyze in Visual Studio. +3. Analyzers run in `ServiceHub.RoslynCodeAnalysisService.exe`; note its process ID. + **Code fixes run in `devenv.exe` instead** — attach to that one to debug a + `CodeFixProvider`. +4. In a second Visual Studio instance, open + `src\Microsoft.CodeAnalysis.NetAnalyzers\Microsoft.CodeAnalysis.NetAnalyzers.slnx`, set + your breakpoints, and *Debug -> Attach to Process...* onto the ID from step 3. +5. Type in the first instance; the breakpoints should hit. If they don't, either the build + you copied and the solution you attached from are out of sync, or VS redirected the + analyzer — check `DOTNET_ANALYZER_REDIRECTING=0` is set. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/performance.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/performance.md deleted file mode 100644 index 996986fe0fa7..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/performance.md +++ /dev/null @@ -1,73 +0,0 @@ -# Measuring Analyzer Performance - -Now that analyzers are part of the build we need a mechanism to track their performance across releases as well as build confidence regarding their use in the SDK. - -## Goals - -- Developers can quickly get feedback on how their change affects performance -- We can track and detect performance regressions in builds before release. - -## What we do today - -- Roslyn - - Can be run on CI: **No** - - Can be run locally with a single script: **No** - - [Compiler Performance](https://github.com/dotnet/roslyn/blob/main/docs/wiki/Measuring-Compiler-Performance.md) - - compiler team has written scenarios in the dotnet/performance repo. The directions for these call for developers to clone the dotnet/performance repo and manually run the tests - - dotnet/performance benchmarks for roslyn are [here]((https://github.com/dotnet/performance/tree/main/src/benchmarks/real-world/Roslyn)) - - [Analyzer Performance](https://github.com/dotnet/roslyn/blob/main/docs/wiki/Analyzer-Runner.md) - - There is an AnalyzerRunner commandline tool checked into dotnet/roslyn that can be used to run analyzers and validate their performance. It needs to be run in a manual fashion. -- [ASP.NET](https://github.com/aspnet/Benchmarks/blob/main/scenarios/README.md) - - Can be run on CI: **Yes** - - Can be run locally with a single script: **No** - - The ASP.NET team has written a tool (crank) that allows them to run benchmarks on either their local machines or remote machines using a client/server model. This does not require the user to download the dotnet/performance repository manually to run scenarios from there. Users will need to manually setup/patch runtimes with their changes but can then run them against the real benchmarks from there. - - [Crank](https://github.com/dotnet/crank) - - [TechEmpower Benchmarks Power BI](https://msit.powerbi.com/view?r=eyJrIjoiYTZjMTk3YjEtMzQ3Yi00NTI5LTg5ZDItNmUyMGRlOTkwMGRlIiwidCI6IjcyZjk4OGJmLTg2ZjEtNDFhZi05MWFiLTJkN2NkMDExZGI0NyIsImMiOjV9) -- Runtime - - Can be run on CI: **Yes** CI runs require you to submit a PR against dotnet/performance - - Can be run locally with a single script: **No** - - The runtime team has a set of benchmarking guides that detail how to run the tests in dotnet/performance against local changes. - - [Benchmarking](https://github.com/dotnet/performance/blob/main/docs/benchmarking-workflow-dotnet-runtime.md) - - [Profiling](https://github.com/dotnet/performance/blob/main/docs/profiling-workflow-dotnet-runtime.md) - -## Proposed Workflow - -### Tests - -We will have two types of tests: - -#### Micro-Benchmarks - -A set of micro-benchmarks (written in BenchmarkDotnet) testing how much time analyzers spend computing result. Each new analyzer that ships in the SDK is expected to have a micro-benchmark that tests - -- code files that cause the analyzer to execute but not issue a diagnostic. -- code files that cause the analyzer to issue a diagnostic. - -These tests are expected to live in the dotnet/roslyn-analyzers repo to make local development simpler. - -#### End-to-End Tests - -An end-to-end compilation test that measures how long the build takes on a large real-world project (based off existing scenarios [here](https://github.com/dotnet/performance/blob/main/docs/sdk-scenarios.md#sdk-build-throughput-scenario)). This test will be run twice, once with all multi-core build features disabled (no `/m` is passed to msbuild, and `/parallel-` is passed to the compiler) and once with the SDK defaults enabled. The reason we will want a test with no parallelism is to make it easier to see the source of regressions. These test will not just measure how long it takes analyzers to execute but the entire SDK-based build process. It will need to collect an ETL file for investigation as well as the following metrics in a binlog file - -- How much time was spend in analysis (`/p:reportanalyzer=true`) -- How long each build task took (recorded by default in the binlog file) -- Total Build Time (recorded by default in the binlog file) - -This test will be added to the dotnet/performance repo to augment the build throughput scenarios that are already there. - -### Local Developer Machine - -There will be a simple script that a developer can run locally on their machine that will compare their current changes to what is in `main`. The tests that will be run will be local to the dotnet/roslyn-analyzers repo. It will then produce a commandline result telling the developer if there is a regression (in typical benchmarkdotnet fashion) as well as an ETL file for both before and after that can be examined. - -### For Pull Requests - -The same script that the user ran locally will be executed on CI using the [results comparer](https://github.com/dotnet/performance/blob/main/src/tools/ResultsComparer/README.md) tool for BenchMarkDotNet to decide if the tests have passed. There are concerns about noise here. ResultsComparer has a noise threshold that can be set which we will adjust to the correct values over time. In addition, we can run these tests on a queue with "dedicated" hardware with the "Host" dnceng pool. We will need to evaluate carefully how noisy these results are, but the hope is that we can strike a good balance of giving developers feedback on the performance of their PRs (as well as traceability in the case of a regression) while also not kill code flow. - -### Weekly Cadence - -Our end-to-end performance tests are run and reported on the performance dashboard automatically. Once a week someone checks in on this performance board and verifies there are no negative trends. If a regression in build times appears to be trending a high priority bug is filed and acted on. - -### For Releases - -We run out end-to-end build performance tests and compare with the previous release -Example: We release .NET 6 Preview 7. CTI runs the performance tests on the this new release and compares to the results that were recorded for .NET 6 Preview 6 as well as the latest .NET 5 RTM. ***NOTE:*** The goal at this stage is to look at performance from a customer perspective. If there is not experiential change then we consider this change a pass. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1022.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1022.md deleted file mode 100644 index ecdb021e08d2..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1022.md +++ /dev/null @@ -1,22 +0,0 @@ -## RS1022: Do not use types from Workspaces assembly in an analyzer - -Diagnostic analyzer types should not use types from Workspaces assemblies. Workspaces assemblies are only available when the analyzer executes in Visual Studio IDE live analysis, but are not available during command line build. Referencing types from Workspaces assemblies will lead to runtime exception during analyzer execution in command line build. - -|Item|Value| -|-|-| -|Category|MicrosoftCodeAnalysisCorrectness| -|Enabled|True| -|Severity|Warning| -|CodeFix|False| ---- - -> **Warning** -> -> The analysis performed by RS1022 is slow and relies on implementation details of the JIT compiler for correctness. -> Authors of compiler extensions are encouraged to use the stricter (and faster) analyzer RS1038 instead of this rule. -> -> RS1038 is enabled by default. To enable RS1022 instead, the following configuration may be added to **.globalconfig**: -> -> ```ini -> roslyn_correctness.assembly_reference_validation = relaxed -> ``` diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1038.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1038.md deleted file mode 100644 index e0d73e8db2d4..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1038.md +++ /dev/null @@ -1,46 +0,0 @@ -## RS1038: Compiler extensions should be implemented in assemblies with compiler-provided references - -Types which implement compiler extension points should not be declared in assemblies that contain references to assemblies which are not provided by all compilation scenarios. Doing so may cause the feature to behave unpredictably. - -|Item|Value| -|-|-| -|Category|MicrosoftCodeAnalysisCorrectness| -|Enabled|True| -|Severity|Warning| -|CodeFix|False| ---- - -This rule helps ensure compiler extensions (e.g. analyzers and source generators) will load correctly in all compilation -scenarios. Depending on the manner in which the compiler is invoked, some assemblies may not be present during a build, -and attempting to reference them will result in exceptions that prevent the compiler extension from loading. RS1038 is -the most strict and best performing validation for this scenario. - -RS1038 is enabled by default unless relaxed validation has been manually enabled in **.globalconfig** as described in -[RS1022](RS1022.md). - -### Rules for compiler feature references - -* Compiler features supporting C# code should only reference the NuGet packages **Microsoft.CodeAnalysis.Common** and/or **Microsoft.CodeAnalysis.CSharp** -* Compiler features supporting Visual Basic code should only reference **Microsoft.CodeAnalysis.Common** and/or **Microsoft.CodeAnalysis.VisualBasic** -* Compiler features supporting both C# and Visual Basic should only reference **Microsoft.CodeAnalysis.Common** -* Compiler features should not be implemented in assemblies containing a reference to **Microsoft.CodeAnalysis.Workspaces.Common** - -> **Note** -> -> This analyzer only checks references to the core Roslyn assemblies. Compiler extensions with other dependencies may -> face restrictions and/or packaging requirements outside the scope of this analyzer. - -### Compiler extension points - -The following compiler extension points are examined by this analyzer: - -* `DiagnosticAnalyzer` -* `DiagnosticSuppressor` -* `ISourceGenerator` -* `IIncrementalGenerator` - -### Other extension points - -Some extension points provided by Roslyn are IDE extensions (e.g. code fixes and completion providers). These features -may ship in the same package as compiler features, but should be implemented in their own assembly since they require a -reference to non-compiler package **Microsoft.CodeAnalysis.Workspaces.Common**. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1041.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1041.md deleted file mode 100644 index 4d60ec77358b..000000000000 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/rules/RS1041.md +++ /dev/null @@ -1,25 +0,0 @@ -## RS1041: Compiler extensions should be implemented in assemblies targeting netstandard2.0 - -Types which implement compiler extension points should only be declared in assemblies targeting netstandard2.0. More specific target frameworks are only available in a subset of supported compilation scenarios, so targeting them may cause the feature to behave unpredictably. - -|Item|Value| -|-|-| -|Category|MicrosoftCodeAnalysisCorrectness| -|Enabled|True| -|Severity|Warning| -|CodeFix|False| ---- - -This rule helps ensure compiler extensions (e.g. analyzers and source generators) will load correctly in all compilation -scenarios. Depending on the manner in which the compiler is invoked, the compiler may execute under .NET Framework or -.NET, and compiler extensions are expected to work consistently in both cases. By targeting netstandard2.0, compiler -extensions are known to be compatible with both execution environments. - -### Compiler extension points - -The following compiler extension points are examined by this analyzer: - -* `DiagnosticAnalyzer` -* `DiagnosticSuppressor` -* `ISourceGenerator` -* `IIncrementalGenerator` diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/suppress-error-list.png b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/suppress-error-list.png deleted file mode 100644 index 448f2010d8de..000000000000 Binary files a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/suppress-error-list.png and /dev/null differ diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/writing-dataflow-analysis-based-analyzers.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/writing-dataflow-analysis-based-analyzers.md index 329e67957d1f..7cb7769f2d1c 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/writing-dataflow-analysis-based-analyzers.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/docs/writing-dataflow-analysis-based-analyzers.md @@ -16,7 +16,7 @@ Please read [this introductory article](https://wikipedia.org/wiki/Data-flow_ana ## Dataflow analysis framework -We have built a dataflow analysis [framework](https://github.com/dotnet/roslyn-analyzers/tree/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow) based on the above CFG API in this repo. Additionally, we have implemented certain [well-known dataflow analyses](https://github.com/dotnet/roslyn-analyzers/tree/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis) on top of this framework. This enables you to implement either or both of the following: +We have built a dataflow analysis [framework](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow) based on the above CFG API in this repo. Additionally, we have implemented certain [well-known dataflow analyses](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis) on top of this framework. This enables you to implement either or both of the following: 1. Write dataflow based analyzers which consume the analysis result from these well-known analyses. 2. Write your own custom dataflow analyses, which can optionally consume analysis results from these well-known analyses. @@ -25,30 +25,30 @@ Let us start by listing out the most important concepts and datatypes in our fra ### Important concepts and datatypes -1. [DataflowAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/89f1193364ef535a508f63e89d7c0e701b52c45c/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs): Base type for all dataflow analyses on a control flow graph. It performs a worklist based approach to flow abstract data values across the basic blocks until a fix point is reached. +1. [DataflowAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs): Base type for all dataflow analyses on a control flow graph. It performs a worklist based approach to flow abstract data values across the basic blocks until a fix point is reached. -2. [AbstractDataFlowAnalysisContext](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs): Base type for analysis contexts for execution of DataFlowAnalysis on a control flow graph. It is the primary input to the core dataflow analysis computation routine [DataFlowAnalysis.Run](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs#L52), and includes things such as input CFG, owning symbol, etc. +2. [AbstractDataFlowAnalysisContext](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDataFlowAnalysisContext.cs): Base type for analysis contexts for execution of DataFlowAnalysis on a control flow graph. It is the primary input to the core dataflow analysis computation routine [DataFlowAnalysis.Run](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysis.cs#L52), and includes things such as input CFG, owning symbol, etc. -3. [DataFlowAnalysisResult](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResult.cs): Result from execution of DataFlowAnalysis on a control flow graph. It stores: +3. [DataFlowAnalysisResult](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowAnalysisResult.cs): Result from execution of DataFlowAnalysis on a control flow graph. It stores: 1. Analysis values for all operations in the graph and 2. `AbstractBlockAnalysisResult` for every basic block in the graph and 3. Merged analysis state for all the unhandled throw operations in the graph. -4. [AbstractBlockAnalysisResult](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractBlockAnalysisResult.cs): Common base type for result from execution of DataFlowAnalysis on a basic block. +4. [AbstractBlockAnalysisResult](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractBlockAnalysisResult.cs): Common base type for result from execution of DataFlowAnalysis on a basic block. -5. [AbstractDomain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDomain.cs): Abstract domain for DataFlowAnalysis to merge and compare values across different control flow paths. The primary abstract domains of interest are: - 1. [AbstractValueDomain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractValueDomain.cs): Abstract value domain for a DataFlowAnalysis to merge and compare individual dataflow analysis values. - 2. [AbstractAnalysisDomain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractAnalysisDomain.cs): Abstract analysis domain for a DataFlowAnalysis to merge and compare entire analysis data sets or dictionary of analysis values. +5. [AbstractDomain](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractDomain.cs): Abstract domain for DataFlowAnalysis to merge and compare values across different control flow paths. The primary abstract domains of interest are: + 1. [AbstractValueDomain](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractValueDomain.cs): Abstract value domain for a DataFlowAnalysis to merge and compare individual dataflow analysis values. + 2. [AbstractAnalysisDomain](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractAnalysisDomain.cs): Abstract analysis domain for a DataFlowAnalysis to merge and compare entire analysis data sets or dictionary of analysis values. Each dataflow analysis must define its own value domain and analysis domain. These domains are used by DataFlowAnalysis to perform following primary operations: 1. _Merge_ individual analysis values and analysis sets at various program points in the graph and also at start of basic blocks which have more then one incoming control flow branches. 2. _Compare_ analysis values at same program point/basic blocks across different flow analysis iterations to determine if the algorithm has reached a fix point and can be terminated. -6. [DataFlowOperationVisitor](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs): Operation visitor to flow the abstract dataflow analysis values across a given statement (IOperation) in a basic block or a given control flow branch. Operation visitor basically defines the _transfer functions_ for analysis values. +6. [DataFlowOperationVisitor](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs): Operation visitor to flow the abstract dataflow analysis values across a given statement (IOperation) in a basic block or a given control flow branch. Operation visitor basically defines the _transfer functions_ for analysis values. -7. [AnalysisEntity](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntity.cs): Primary entity for which analysis data is tracked by majority of dataflow analyses. The entity is based on one or more of the following: +7. [AnalysisEntity](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntity.cs): Primary entity for which analysis data is tracked by majority of dataflow analyses. The entity is based on one or more of the following: 1. An [ISymbol](https://github.com/dotnet/roslyn/blob/version-3.0.0/src/Compilers/Core/Portable/Symbols/ISymbol.cs) - 2. One or more [AbstractIndex](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.cs) indices to index into the parent entity. For example, an index into an array or collection. + 2. One or more [AbstractIndex](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractIndex.cs) indices to index into the parent entity. For example, an index into an array or collection. 3. "this" or "Me" instance. 4. An allocation or an object creation. @@ -57,40 +57,40 @@ Let us start by listing out the most important concepts and datatypes in our fra 2. A non-null "InstanceLocation" indicating the abstract location at which the entity is located and 3. An optional parent entity if this entity has the same "InstanceLocation" as the parent (i.e. parent is a value type allocated on stack). -8. [AbstractLocation](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs): Represents an abstract analysis location. This may be used to represent a location where an AnalysisEntity resides, i.e. `AnalysisEntity.InstanceLocation` or a location that is pointed to by a reference type variable, and tracked with [PointsToAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs). An analysis location can be created for one of the following cases: +8. [AbstractLocation](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocation.cs): Represents an abstract analysis location. This may be used to represent a location where an AnalysisEntity resides, i.e. `AnalysisEntity.InstanceLocation` or a location that is pointed to by a reference type variable, and tracked with [PointsToAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs). An analysis location can be created for one of the following cases: 1. An allocation or an object creation operation. 2. Location for the implicit 'this' or 'Me' instance being analyzed. 3. Location created for certain symbols which do not have a declaration in executable code, i.e. no IOperation for declaration (such as parameter symbols, member symbols, etc.). - 4. Location created for flow capture entities, i.e. for [InterproceduralCaptureId](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralCaptureId.cs) created for [IFlowCaptureOperation](https://github.com/dotnet/roslyn/blob/version-3.0.0/src/Compilers/Core/Portable/Operations/IFlowCaptureOperation.cs) or [IFlowCaptureReferenceOperation](https://github.com/dotnet/roslyn/blob/version-3.0.0/src/Compilers/Core/Portable/Operations/IFlowCaptureReferenceOperation.cs). + 4. Location created for flow capture entities, i.e. for [InterproceduralCaptureId](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralCaptureId.cs) created for [IFlowCaptureOperation](https://github.com/dotnet/roslyn/blob/version-3.0.0/src/Compilers/Core/Portable/Operations/IFlowCaptureOperation.cs) or [IFlowCaptureReferenceOperation](https://github.com/dotnet/roslyn/blob/version-3.0.0/src/Compilers/Core/Portable/Operations/IFlowCaptureReferenceOperation.cs). -9. [PointsToAbstractValue](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAbstractValue.cs): Abstract PointsTo value for an AnalysisEntity/IOperation tracked by PointsToAnalysis. It contains the set of possible AbstractLocations that the entity or the operation can point to and the "Kind" of the location(s). +9. [PointsToAbstractValue](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAbstractValue.cs): Abstract PointsTo value for an AnalysisEntity/IOperation tracked by PointsToAnalysis. It contains the set of possible AbstractLocations that the entity or the operation can point to and the "Kind" of the location(s). ## Implementing a custom dataflow analysis -Now that we are familiar with the basic concepts and data types for flow analysis, let us walk through an existing flow analysis implementation and a step by step guide to creating your own flow analysis implementation, say `MyCustomAnalysis`. We will use [ValueContentAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis) as the sample flow analysis implementation. +Now that we are familiar with the basic concepts and data types for flow analysis, let us walk through an existing flow analysis implementation and a step by step guide to creating your own flow analysis implementation, say `MyCustomAnalysis`. We will use [ValueContentAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis) as the sample flow analysis implementation. -1. Start by creating a new folder, say `MyCustomAnalysis` within [this folder](https://github.com/dotnet/roslyn-analyzers/tree/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis) in the repo. +1. Start by creating a new folder, say `MyCustomAnalysis` within [this folder](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis) in the repo. -2. Add **MyCustomAnalysis.cs** that defines **MyCustomAnalysis**: Sub-type of `DataFlowAnalysis` that provides the public entry points `TryGetOrComputeResult` into your analysis. It takes a bunch of input parameters, packages them into your analysis specific analysis context, and invokes `DataFlowAnalysis.TryGetOrComputeResultForAnalysisContext` to compute the analysis result. The implementation of this type should be almost identical for all analyses. Note that the type arguments for this type will be defined in subsequent steps. See [ValueContentAnalysis.cs](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs) for reference. +2. Add **MyCustomAnalysis.cs** that defines **MyCustomAnalysis**: Sub-type of `DataFlowAnalysis` that provides the public entry points `TryGetOrComputeResult` into your analysis. It takes a bunch of input parameters, packages them into your analysis specific analysis context, and invokes `DataFlowAnalysis.TryGetOrComputeResultForAnalysisContext` to compute the analysis result. The implementation of this type should be almost identical for all analyses. Note that the type arguments for this type will be defined in subsequent steps. See [ValueContentAnalysis.cs](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs) for reference. -3. Add **MyCustomAbstractValue.cs** that defines **MyCustomAbstractValue**: This type defines the core analysis _value_ that needs to be tracked by your analysis. For example, ValueContentAnalysis defines [ValueContentAbstractValue](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs), such that each instance of `ValueContentAbstractValue` contains a set of potential constant literal values and a [ValueContainsNonLiteralState](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContainsNonLiteralState.cs) for the non-literal state of the abstract value. It also defines a bunch of static instances of common value content values, see [here](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs#L23-L32). +3. Add **MyCustomAbstractValue.cs** that defines **MyCustomAbstractValue**: This type defines the core analysis _value_ that needs to be tracked by your analysis. For example, ValueContentAnalysis defines [ValueContentAbstractValue](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs), such that each instance of `ValueContentAbstractValue` contains a set of potential constant literal values and a [ValueContainsNonLiteralState](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContainsNonLiteralState.cs) for the non-literal state of the abstract value. It also defines a bunch of static instances of common value content values, see [here](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAbstractValue.cs#L23-L32). -4. Add **MyCustomAnalysis.MyCustomAbstractValueDomain.cs** that defines **MyCustomAbstractValueDomain**: Sub-type of `AbstractValueDomain` that defines how to compare and merge different `MyCustomAbstractValue` across different control flow paths or flow analysis iterations. For example, see [ValueContentAbstractValueDomain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAbstractDomain.cs) +4. Add **MyCustomAnalysis.MyCustomAbstractValueDomain.cs** that defines **MyCustomAbstractValueDomain**: Sub-type of `AbstractValueDomain` that defines how to compare and merge different `MyCustomAbstractValue` across different control flow paths or flow analysis iterations. For example, see [ValueContentAbstractValueDomain](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentAbstractDomain.cs) -5. Define the core data structure for the global CFG wide and/or per-block _analysis data_ that will tracked by your analysis, i.e. **MyCustomAnalysisData**. For most analyses, you likely won't need to define a separate type or source file for `MyCustomAnalysisData`. A likely definition would be just a using such as `using MyCustomAnalysisData = DictionaryAnalysisData;`. See [here](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs#L13) for such an example for `DisposeAnalysisData`. However, for complex cases, you may need to define your own `MyCustomAnalysisData` user defined type. For example, see [ValueContentAnalysisData](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisData.cs) that has an aggregated analysis data, which contains core analysis data dictionary from AnalysisEntity to ValueContentAbstractValue per-basic block and additional predicated analysis data. +5. Define the core data structure for the global CFG wide and/or per-block _analysis data_ that will tracked by your analysis, i.e. **MyCustomAnalysisData**. For most analyses, you likely won't need to define a separate type or source file for `MyCustomAnalysisData`. A likely definition would be just a using such as `using MyCustomAnalysisData = DictionaryAnalysisData;`. See [here](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs#L13) for such an example for `DisposeAnalysisData`. However, for complex cases, you may need to define your own `MyCustomAnalysisData` user defined type. For example, see [ValueContentAnalysisData](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisData.cs) that has an aggregated analysis data, which contains core analysis data dictionary from AnalysisEntity to ValueContentAbstractValue per-basic block and additional predicated analysis data. -6. Define **MyCustomAnalysisDomain**: Sub-type of `AbstractAnalysisDomain` that defines how to compare and merge different `MyCustomAnalysisData` data sets across different control flow paths or flow analysis iterations. For most analyses, where `MyCustomAnalysisData` is defined as a simple dictionary, this domain will be defined with a simple using such as `using MyCustomAnalysisDomain = MapAbstractDomain;`. See [here](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs#L14) for such an example for `DisposeAnalysisDomain`. However, for complex cases, you may need to define your own `MyCustomAnalysisDomain` user defined type, such as [ValueContentAnalysis.CoreAnalysisDataDomain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs). +6. Define **MyCustomAnalysisDomain**: Sub-type of `AbstractAnalysisDomain` that defines how to compare and merge different `MyCustomAnalysisData` data sets across different control flow paths or flow analysis iterations. For most analyses, where `MyCustomAnalysisData` is defined as a simple dictionary, this domain will be defined with a simple using such as `using MyCustomAnalysisDomain = MapAbstractDomain;`. See [here](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.cs#L14) for such an example for `DisposeAnalysisDomain`. However, for complex cases, you may need to define your own `MyCustomAnalysisDomain` user defined type, such as [ValueContentAnalysis.CoreAnalysisDataDomain](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.CoreAnalysisDataDomain.cs). -7. Add **MyCustomAnalysis.MyCustomBlockAnalysisResult.cs** that defines **MyCustomBlockAnalysisResult**: Sub-type of `AbstractBlockAnalysisResult` that is the immutable per-basic block result from dataflow analysis. It is immutable equivalent of the mutable `MyCustomAnalysisData` that was used during flow analysis execution. For reference, see [ValueContentBlockAnalysisResult](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentBlockAnalysisResult.cs), the core immutable data exposed being `ImmutableDictionary`. +7. Add **MyCustomAnalysis.MyCustomBlockAnalysisResult.cs** that defines **MyCustomBlockAnalysisResult**: Sub-type of `AbstractBlockAnalysisResult` that is the immutable per-basic block result from dataflow analysis. It is immutable equivalent of the mutable `MyCustomAnalysisData` that was used during flow analysis execution. For reference, see [ValueContentBlockAnalysisResult](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentBlockAnalysisResult.cs), the core immutable data exposed being `ImmutableDictionary`. -8. Define **MyCustomAnalysisResult**: Parameterized version of `DataFlowAnalysisResult` with `MyCustomBlockAnalysisResult` and `MyCustomAbstractValue` as type arguments. For most cases, this will be just a simple using directive such as `using MyCustomAnalysisResult = DataFlowAnalysisResult;`. For example, see [ValueContentAnalysisResult](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs#L12). +8. Define **MyCustomAnalysisResult**: Parameterized version of `DataFlowAnalysisResult` with `MyCustomBlockAnalysisResult` and `MyCustomAbstractValue` as type arguments. For most cases, this will be just a simple using directive such as `using MyCustomAnalysisResult = DataFlowAnalysisResult;`. For example, see [ValueContentAnalysisResult](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs#L12). -9. Add **MyCustomAnalysisContext.cs** that defines **MyCustomAnalysisContext**: Sub-type of `AbstractDataFlowAnalysisContext` that packages the core input parameters to dataflow analysis. Most of the code in this type is common boiler plate code that is identical for all analyses. You should be able to just clone an existing file, for example [ValueContentAnalysisContext.cs](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs), and just do a simple find and replace of "ValueContent" with "MyCustom" in the file. +9. Add **MyCustomAnalysisContext.cs** that defines **MyCustomAnalysisContext**: Sub-type of `AbstractDataFlowAnalysisContext` that packages the core input parameters to dataflow analysis. Most of the code in this type is common boiler plate code that is identical for all analyses. You should be able to just clone an existing file, for example [ValueContentAnalysisContext.cs](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysisContext.cs), and just do a simple find and replace of "ValueContent" with "MyCustom" in the file. 10. Add **MyCustomAnalysis.MyCustomDataFlowOperationVisitor.cs** that defines **MyCustomDataFlowOperationVisitor**: Sub-type of `DataFlowOperationVisitor` that contains the core operation visitor, which tracks the `CurrentAnalysisData` and overrides the required `VisitXXXOperation` to define the transfer functions for how the current analysis data changes with operations and also computes the analysis values for the overridden operation (program points in CFG). You have three potential options for implementing this operation visitor: - 1. Derive from [AnalysisEntityDataFlowOperationVisitor](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs): If your core `MyCustomAnalysisData` is a dictionary keyed on `AnalysisEntity`, then you should most likely be deriving from this type. This operation visitor is intended for all analyses which track some data pertaining to symbols, which are represented by analysis entities. For example, [ValueContentDataFlowOperationVisitor](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentDataFlowOperationVisitor.cs#L18) derives from this visitor. - 2. Derive from [AbstractLocationDataFlowOperationVisitor](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs): If your core `MyCustomAnalysisData` is a dictionary keyed on `AbstractLocation`, then you should most likely be deriving from this type. This operation visitor is intended for all analyses which track some data pertaining to locations/allocations, which are represented by abstract locations. For example, [DisposeDataFlowOperationVisitor](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeDataFlowOperationVisitor.cs#L22) derives from this visitor. - 3. Derive from [DataFlowOperationVisitor](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs): If none of the above two special visitor sub-types are suitable for your analysis, you can directly sub-type the core `DataFlowOperationVisitor`, although you will likely have a more complicated implementation with many more overrides. Hopefully, this will not be required often. + 1. Derive from [AnalysisEntityDataFlowOperationVisitor](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AnalysisEntityDataFlowOperationVisitor.cs): If your core `MyCustomAnalysisData` is a dictionary keyed on `AnalysisEntity`, then you should most likely be deriving from this type. This operation visitor is intended for all analyses which track some data pertaining to symbols, which are represented by analysis entities. For example, [ValueContentDataFlowOperationVisitor](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.ValueContentDataFlowOperationVisitor.cs#L18) derives from this visitor. + 2. Derive from [AbstractLocationDataFlowOperationVisitor](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/AbstractLocationDataFlowOperationVisitor.cs): If your core `MyCustomAnalysisData` is a dictionary keyed on `AbstractLocation`, then you should most likely be deriving from this type. This operation visitor is intended for all analyses which track some data pertaining to locations/allocations, which are represented by abstract locations. For example, [DisposeDataFlowOperationVisitor](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/DisposeAnalysis/DisposeAnalysis.DisposeDataFlowOperationVisitor.cs#L22) derives from this visitor. + 3. Derive from [DataFlowOperationVisitor](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/DataFlowOperationVisitor.cs): If none of the above two special visitor sub-types are suitable for your analysis, you can directly sub-type the core `DataFlowOperationVisitor`, although you will likely have a more complicated implementation with many more overrides. Hopefully, this will not be required often. Once you have implemented the above custom analysis pieces, your dataflow analyzers can invoke `MyCustomAnalysis.TryGetOrComputeResult` API to get the analysis result. Your analyzer can then consume any of the below components of the analysis result: @@ -104,7 +104,7 @@ Once you have implemented the above custom analysis pieces, your dataflow analyz We have some common analyses that you may likely want to consume for your custom dataflow analysis implementation or use directly in dataflow analyzers: -1. [PointsToAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs): Dataflow analysis to track locations pointed to by AnalysisEntity and IOperation instances. This is the most commonly used dataflow analysis in all our flow based analyzers/analyses. Consider the following example: +1. [PointsToAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PointsToAnalysis/PointsToAnalysis.cs): Dataflow analysis to track locations pointed to by AnalysisEntity and IOperation instances. This is the most commonly used dataflow analysis in all our flow based analyzers/analyses. Consider the following example: ```csharp var x = new MyClass(); @@ -114,7 +114,7 @@ We have some common analyses that you may likely want to consume for your custom PointsToAnalysis will compute that variables `x` and `y` have identical non-null `PointsToAbstractValue`, which contains a single `AbstractLocation` corresponding to the first `IObjectCreationOperation` for `new MyClass()`. Variable `z` has a different `PointsToAbstractValue`, which is guaranteed to be non-null, but has two potential `AbstractLocation`, one for each `IObjectCreationOperation` in the above code. -2. [CopyAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs): Dataflow analysis to track AnalysisEntity instances that share the same value type or reference type value, determined based on [CopyAbstractValueKind](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAbstractValueKind.cs#L8). Consider the following example: +2. [CopyAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAnalysis.cs): Dataflow analysis to track AnalysisEntity instances that share the same value type or reference type value, determined based on [CopyAbstractValueKind](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/CopyAnalysis/CopyAbstractValueKind.cs#L8). Consider the following example: ```csharp var x = new MyClass(); @@ -123,9 +123,9 @@ We have some common analyses that you may likely want to consume for your custom int c2 = 0; ``` - CopyAnalysis will compute that variables `x` and `y` have identical `CopyAbstractValue` with `CopyAbstractValueKind.KnownReferenceCopy` with two `AnalysisEntity` instances, one for `x` and one for `y`. Similarly, it will compute that `c1` and `c2` have identical `CopyAbstractValue` with `CopyAbstractValueKind.KnownValueCopy` with two `AnalysisEntity` instances, one for `c1` and one for `c2`. CopyAnalysis is currently off by default for all analyzers as it has known performance issues and needs performance tuning. It can be enabled by end users with editorconfig option [copy_analysis](https://github.com/dotnet/roslyn-analyzers/blob/main/docs/analyzer-configuration.md#configure-execution-of-copy-analysis-tracks-value-and-reference-copies). + CopyAnalysis will compute that variables `x` and `y` have identical `CopyAbstractValue` with `CopyAbstractValueKind.KnownReferenceCopy` with two `AnalysisEntity` instances, one for `x` and one for `y`. Similarly, it will compute that `c1` and `c2` have identical `CopyAbstractValue` with `CopyAbstractValueKind.KnownValueCopy` with two `AnalysisEntity` instances, one for `c1` and one for `c2`. CopyAnalysis is currently off by default for all analyzers as it has known performance issues and needs performance tuning. It can be enabled by end users with editorconfig option [copy_analysis](analyzer-configuration.md#configure-execution-of-copy-analysis-tracks-value-and-reference-copies). -3. [ValueContentAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs): Dataflow analysis to track possible constant values that might be stored in an AnalysisEntity and IOperation instances. This is identical to constant propagation for constant values stored in non-constant symbols. Consider the following example: +3. [ValueContentAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/ValueContentAnalysis/ValueContentAnalysis.cs): Dataflow analysis to track possible constant values that might be stored in an AnalysisEntity and IOperation instances. This is identical to constant propagation for constant values stored in non-constant symbols. Consider the following example: ```csharp int c1 = 0; @@ -136,18 +136,18 @@ We have some common analyses that you may likely want to consume for your custom ValueContentAnalysis will compute that variables `c1`, `c2` and `c3` have identical `ValueContentAbstractValue` with a single literal value `0` and `ValueContainsNonLiteralState.No` to indicate it cannot contain a non-literal value. It will compute that `c4` has a different `ValueContentAbstractValue` with a single literal value `0` and `ValueContainsNonLiteralState.Maybe` to indicate that it may contain some non-literal value(s) in some code path(s). -4. [TaintedDataAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs): Dataflow analysis to track tainted state of AnalysisEntity and IOperation instances. +4. [TaintedDataAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/TaintedDataAnalysis/TaintedDataAnalysis.cs): Dataflow analysis to track tainted state of AnalysisEntity and IOperation instances. -5. [PropertySetAnalysis](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.cs): Dataflow analysis to track values assigned to one or more properties of an object to identify and flag incorrect/insecure object state. See its [PropertySetAnalysisTests.cs](https://github.com/dotnet/roslyn-analyzers/blob/0b21b2163220669981f682e58a8ddcdc9a839774/src/Utilities.UnitTests/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysisTests.cs) for examples. +5. [PropertySetAnalysis](../src/Utilities/FlowAnalysis/FlowAnalysis/Analysis/PropertySetAnalysis/PropertySetAnalysis.cs): Dataflow analysis to track values assigned to one or more properties of an object to identify and flag incorrect/insecure object state. The upstream `Utilities.UnitTests` project, which held its worked examples, did not migrate into `dotnet/sdk`; the security rules under `Microsoft.NetCore.Analyzers/Security` are the live consumers to read instead. ## Interprocedural dataflow analysis -We also support a complete context sensitive interprocedural flow analysis for invocations of methods within the same compilation. See [InterproceduralAnalysisKind](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisKind.cs) for more details. +We also support a complete context sensitive interprocedural flow analysis for invocations of methods within the same compilation. See [InterproceduralAnalysisKind](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisKind.cs) for more details. -Interprocedural analysis support is baked into the core `DataFlowOperationVisitor` and each custom dataflow analysis implementation gets all this support for free, without requiring to add any code specific to interprocedural analysis. Each dataflow analysis defines the default `InterproceduralAnalysisKind` in its `TryGetOrComputeResult` entry point, and the analyzer is free to override the interprocedural analysis kind. Interprocedural analysis almost always leads to more precise analysis results at the expense of more computation resources, i.e. it likely takes more memory and time to complete. So, an analyzer should be extremely fine tuned for performance if it defaults to enabling context sensitive interprocedural analysis by default. Note that the end user can override the interprocedural analysis kind for specific rule ID or all dataflow rules with the editorconfig option [interprocedural-analysis-kind](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/docs/analyzer-configuration.md#interprocedural-analysis-kind). This option takes precedence over the defaults in the `TryGetOrComputeResult` entry points to analysis and also any overrides from individual analyzers invoking this API. +Interprocedural analysis support is baked into the core `DataFlowOperationVisitor` and each custom dataflow analysis implementation gets all this support for free, without requiring to add any code specific to interprocedural analysis. Each dataflow analysis defines the default `InterproceduralAnalysisKind` in its `TryGetOrComputeResult` entry point, and the analyzer is free to override the interprocedural analysis kind. Interprocedural analysis almost always leads to more precise analysis results at the expense of more computation resources, i.e. it likely takes more memory and time to complete. So, an analyzer should be extremely fine tuned for performance if it defaults to enabling context sensitive interprocedural analysis by default. Note that the end user can override the interprocedural analysis kind for specific rule ID or all dataflow rules with the editorconfig option [interprocedural-analysis-kind](analyzer-configuration.md#interprocedural-analysis-kind). This option takes precedence over the defaults in the `TryGetOrComputeResult` entry points to analysis and also any overrides from individual analyzers invoking this API. We also have couple of additional configuration/customization points for interprocedural analysis: -1. [InterproceduralAnalysisConfiguration](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisConfiguration.cs): Defines interprocedural analysis configuration parameters. For example, `MaxInterproceduralMethodCallChain` and `MaxInterproceduralLambdaOrLocalFunctionCallChain` control the size of the maximum height of the interprocedural call tree. Each analyzer can override the defaults for these chain lengths (3 as of current implementation), and end users can override it with editorconfig options [max_interprocedural_method_call_chain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/docs/analyzer-configuration.md#maximum-method-call-chain-length-to-analyze-for-interprocedural-dataflow-analysis) and [max_interprocedural_lambda_or_local_function_call_chain](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/docs/analyzer-configuration.md#maximum-lambda-or-local-function-call-chain-length-to-analyze-for-interprocedural-dataflow-analysis). +1. [InterproceduralAnalysisConfiguration](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisConfiguration.cs): Defines interprocedural analysis configuration parameters. For example, `MaxInterproceduralMethodCallChain` and `MaxInterproceduralLambdaOrLocalFunctionCallChain` control the size of the maximum height of the interprocedural call tree. Each analyzer can override the defaults for these chain lengths (3 as of current implementation), and end users can override it with editorconfig options [max_interprocedural_method_call_chain](analyzer-configuration.md#maximum-method-call-chain-length-to-analyze-for-interprocedural-dataflow-analysis) and [max_interprocedural_lambda_or_local_function_call_chain](analyzer-configuration.md#maximum-lambda-or-local-function-call-chain-length-to-analyze-for-interprocedural-dataflow-analysis). -2. [InterproceduralAnalysisPredicate](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisPredicate.cs): Optional predicates that can be provided by each analyzer to determine if interprocedural analysis should be invoked or not for specific callsites. For example, [this predicate](https://github.com/dotnet/roslyn-analyzers/blob/v2.9.7/src/Microsoft.NetCore.Analyzers/Core/Runtime/DisposeObjectsBeforeLosingScope.cs#L175) used by dispose analysis significantly trims down the size of interprocedural call trees and provides huge performance improvements for interprocedural analysis. +2. [InterproceduralAnalysisPredicate](../src/Utilities/FlowAnalysis/FlowAnalysis/Framework/DataFlow/InterproceduralAnalysisPredicate.cs): Optional predicates that can be provided by each analyzer to determine if interprocedural analysis should be invoked or not for specific callsites. For example, [this predicate](../src/Microsoft.CodeAnalysis.NetAnalyzers/Microsoft.NetCore.Analyzers/Runtime/DisposeObjectsBeforeLosingScope.cs#L175) used by dispose analysis significantly trims down the size of interprocedural call trees and provides huge performance improvements for interprocedural analysis. diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj index e1f5e3d1e335..696ffe916517 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers.Package.csproj @@ -73,7 +73,6 @@ $(NetAnalyzersRootDir)src $(NetAnalyzersRootDir)src - $(NetAnalyzersRootDir)docs $(PackageId).props $(PackageId).targets @@ -81,7 +80,6 @@ $(PackageId).md $(PackageId).sarif.template AnalyzerVersion=$(VersionPrefix) - analyzer-configuration.md false diff --git a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md index 01932c4bfa29..4054f549ae6b 100644 --- a/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md +++ b/src/Microsoft.CodeAnalysis.NetAnalyzers/src/Microsoft.CodeAnalysis.NetAnalyzers/AnalyzerReleases.Unshipped.md @@ -4,9 +4,9 @@ Rule ID | Category | Severity | Notes --------|----------|----------|------- -CA1517 | Maintainability | Info | PreferReadOnlySpanOverSpanAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/CA1516) +CA1517 | Maintainability | Info | PreferReadOnlySpanOverSpanAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1517) CA1876 | Performance | Info | DoNotUseAsParallelInForEachLoopAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1876) -CA1877 | Performance | Info | CollapseMultiplePathOperationsAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/cA1877) +CA1877 | Performance | Info | CollapseMultiplePathOperationsAnalyzer, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1877) CA2026 | Reliability | Info | PreferJsonElementParse, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2026) CA2027 | Reliability | Info | DoNotUseNonCancelableTaskDelayWithWhenAny, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2027) CA2028 | Reliability | Info | AvoidRedundantRegexIsMatchBeforeMatch, [Documentation](https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca2028)