Skip to content

[TaskAnalyzer] Align diagnostic severities and ignore open generic ITaskItem<T> - #14811

Merged
VolPlita merged 3 commits into
dotnet:mainfrom
VolPlita:vplita-scope-policy-independent
Aug 26, 2026
Merged

[TaskAnalyzer] Align diagnostic severities and ignore open generic ITaskItem<T>#14811
VolPlita merged 3 commits into
dotnet:mainfrom
VolPlita:vplita-scope-policy-independent

Conversation

@VolPlita

@VolPlita VolPlita commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Part of #14078.

Summary

Aligns TaskAnalyzer descriptor severities with the documented intent and prevents an unsupported-type false positive when a task uses an open generic ITaskItem<T> property.

This PR intentionally does not change msbuild_task_analyzer.scope. The scope-policy implementation and tests belong to #14775 and are excluded from this PR.

Changes

  • Changes MSBuildTask0006, MSBuildTask0007, and MSBuildTask0008 from Warning to Info. These rules provide modernization suggestions with code fixes; they do not report invalid task definitions.
  • Changes MSBuildTask0010 from Error to Warning. Convert.ChangeType binding succeeds, but its invariant-culture behavior may not match the task's intended parsing semantics.
  • Keeps MSBuildTask0009 as Warning, avoiding a new unconditional build break for existing analyzer consumers.
  • Skips MSBuildTask0009 for open generic ITaskItem<T> properties because an unresolved type parameter does not provide enough information to determine whether the closed task parameter will be supported.
  • Updates DiagnosticDescriptors.cs, AnalyzerReleases.Unshipped.md, the README, and analyzer tests so all severity declarations agree.
  • Adds coverage showing typed task-item diagnostics apply to regular tasks independently of MT opt-in and that open generic task-item properties do not produce a diagnostic.

Compatibility

The severity changes only reduce diagnostics from Warning/Error to Info/Warning. No new warning or error is introduced, and analyzer scope behavior is unchanged.

Testing

  • .dotnet\dotnet.exe test src\TaskAnalyzer.Tests\TaskAnalyzer.Tests.csproj -c Release: 250 passed, 0 failed, 0 skipped.
  • .\build.cmd -v quiet: succeeded with 0 warnings and 0 errors.

Related

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@VolPlita
VolPlita marked this pull request as ready for review August 24, 2026 12:13
Copilot AI lite review requested due to automatic review settings August 24, 2026 12:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR finalizes TaskAnalyzer’s initial shipping behavior by gating MT-focused diagnostics behind an explicit MT opt-in (with a migration scope=all override) while refining the severities and documentation for typed task-property binding diagnostics. It also expands the test suite to cover default scope behavior, migration mode, .globalconfig configuration, invalid scope handling, and warnings-as-errors behavior.

Changes:

  • Updated analyzer scope handling so MSBuildTask0001–MSBuildTask0005 are MT-only by default, with msbuild_task_analyzer.scope=all enabling analysis for regular tasks.
  • Adjusted typed ITaskItem<T> diagnostics: MSBuildTask0009 to Error (unsupported types cannot bind) and MSBuildTask0010 to Warning (binding succeeds but may be culture-sensitive).
  • Added/updated tests and docs for scope behavior, .globalconfig configuration, and generic ITaskItem<T> cases.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/TaskAnalyzer/UnsupportedTaskItemTypeAnalyzer.cs Suppresses MSBuildTask0009/0010 for open generic ITaskItem<T> type parameters to avoid unactionable diagnostics.
src/TaskAnalyzer/TransitiveCallChainAnalyzer.cs Updates scope comment and ensures scope option is read consistently for transitive analysis gating.
src/TaskAnalyzer/SharedAnalyzerHelpers.cs Changes scope parsing to default to MT-only unless scope=all is explicitly set.
src/TaskAnalyzer/README.md Updates scope/severity documentation and adds .globalconfig guidance for migration mode.
src/TaskAnalyzer/MultiThreadableTaskAnalyzer.cs Applies scope gating consistently to MSBuildTask0001–0004 and updates documentation/comments to match new defaults.
src/TaskAnalyzer/DiagnosticDescriptors.cs Changes default severities for MSBuildTask0009 (Error) and MSBuildTask0010 (Warning).
src/TaskAnalyzer/AnalyzerReleases.Unshipped.md Updates the unshipped release table to reflect intended severities after the policy change.
src/TaskAnalyzer.Tests/UnsupportedTaskItemTypeAnalyzerTests.cs Updates severity expectations and adds coverage for MT-scope independence + generic task cases.
src/TaskAnalyzer.Tests/TransitiveCallChainAnalyzerTests.cs Adds default-scope vs scope=all test coverage for transitive diagnostics.
src/TaskAnalyzer.Tests/TestHelpers.cs Refactors helpers to support running analyzers with default scope and explicit scope values.
src/TaskAnalyzer.Tests/MultiThreadableTaskAnalyzerTests.cs Adds tests for default scope, scope=all, .globalconfig, invalid scope values, and warnings-as-errors promotion.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/TaskAnalyzer/AnalyzerReleases.Unshipped.md
@VolPlita VolPlita changed the title Finalize TaskAnalyzer scope and diagnostic severities Make MSBuildTask0001-0005 MT-only by default; swap MSBuildTask0009/0010 severities Aug 25, 2026
Comment thread src/TaskAnalyzer/README.md Outdated
Comment thread src/TaskAnalyzer/MultiThreadableTaskAnalyzer.cs Outdated
Comment thread src/TaskAnalyzer/SharedAnalyzerHelpers.cs Outdated
Comment thread src/TaskAnalyzer/UnsupportedTaskItemTypeAnalyzer.cs
Comment thread src/TaskAnalyzer.Tests/TestHelpers.cs Outdated
@VolPlita

Copy link
Copy Markdown
Contributor Author

Design-level notes (not tied to a specific diff line)

  • Two open PRs are racing on the same default. Scope MT-specific TaskAnalyzer diagnostics to MT tasks by default #14775 (vplita-mt-only-default, open, +261/-38) flips the same msbuild_task_analyzer.scope default in the same files, but scopes only MSBuildTask0002/0003/0005 and deliberately keeps the (MSBuildTask0001 and MSBuildTask0004 always fire on all tasks regardless) carve-out. This PR supersedes it and removes that carve-out. Since they share no commits, whichever merges second will conflict, and the surviving policy depends on merge order rather than on a decision. Recommend closing Scope MT-specific TaskAnalyzer diagnostics to MT tasks by default #14775 (or rebasing this one on it) and recording the chosen policy explicitly.

  • RS2001 in NoWarn is the systemic root cause of the severity drift. TaskAnalyzer.csproj:14 carries the comment "our analyzer rules use custom severities", but RS2001 is precisely the rule that keeps AnalyzerReleases.*.md in sync with DiagnosticDescriptors.cs. With it suppressed, the release notes are unverified prose - which is how the 0006-0008 Info/Warning mismatch reached a green build. Worth a follow-up issue to drop RS2001 from NoWarn and let the release-tracking files be the enforced contract before the analyzer ships in Microsoft.Build.Framework.

  • The shipping severity/scope policy deserves a durable home. "MT rules are opt-in; typed task-property rules are unconditional" is now the analyzer's public contract, and consumers will hit it via a package update. Today it lives only in a PR description. Consider a short section in src/TaskAnalyzer/README.md (or documentation/specs/) stating the policy, the rule-to-scope mapping, and how it interacts with [MT] Ship multi-threaded task analyzer as a NuGet package #14078's goal of shipping through Microsoft.Build.Framework - so the next scope change has something to be measured against.

  • build_property.msbuild_task_analyzer.scope is unreachable for package consumers. SharedAnalyzerHelpers.ReadAnalyzeAllTasksOption probes build_property.{ScopeOptionKey} first, but the package produced by TaskAnalyzer.csproj contains only analyzers/dotnet/cs/*.dll - no build/*.props declaring <CompilerVisibleProperty Include="msbuild_task_analyzer.scope" />. So the MSBuild-property route only works for consumers who wire it up themselves, and .globalconfig (correctly, the only route the README now documents) is the sole supported switch. If the MSBuild-property route is meant to be supported, the package needs the props file; if not, the build_property. probe is dead weight and could be dropped.

@VolPlita VolPlita changed the title Make MSBuildTask0001-0005 MT-only by default; swap MSBuildTask0009/0010 severities [TaskAnalyzer] Scope MSBuildTask0001-0005 to MT tasks by default; swap MSBuildTask0009/0010 severities Aug 25, 2026

@VolPlita VolPlita left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Second review pass on head 51074bb, diffed against base 8610df47f3. Every finding below was reproduced by building the analyzer from this branch and running it against MSBuild's own task library; candidates that did not reproduce were dropped.

# Dimension Verdict
19 Build Infrastructure Care 🔴 1 MAJOR
1 Backwards Compatibility 🔴 1 MAJOR
4 Test Coverage & Completeness 🟡 1 MODERATE
12 Code Simplification 🟡 1 MODERATE
20 Scope & PR Discipline 🟡 1 MODERATE
18 Documentation Accuracy ⚪ 1 NIT

Combined with the first pass (dimensions 6, 10, 14, 18, 22), 14 of 24 dimensions are clean. No BLOCKING findings, so this is a COMMENT review.

  • Build Infrastructure - src/Tasks consumes this analyzer under BuildAnalyzer=true and the BootstrapMSBuildWithMTMode CI job runs it. Nothing in the repo sets msbuild_task_analyzer.scope, so MSBuildTask0005 findings on MSBuild's own tasks drop 288 -> 132 and unique warnings drop 280 -> 193.
  • Backwards Compatibility - MSBuildTask0009 Warning -> Error is un-gated and undocumented, so a non-MT consumer both loses MSBuildTask0001-0005 and gains a hard build break in the same update.
  • Test Coverage - TypedTaskItemDiagnostics_AreIndependentOfMtScope uses an MT task and sets no scope, so it cannot fail for the reason it names.
  • Code Simplification - the per-operation callback cannot report anything when reportScopedRules is false, yet is still registered; that is the common path under the new default.
  • Documentation - the @rainersigwald rationale block still says Console.* is "always wrong in tasks" while the same commit stops checking it for ordinary tasks.
  • Scope & PR Discipline - see the separate design-level comment: four independent concerns are bundled, one of them a self-declared unfixed defect.

Verified clean in this pass

Concurrency (13) - the scope flag is an immutable bool captured per CompilationStart; no new shared state under EnableConcurrentExecution. Performance (3) - the option is read once per compilation, and $"build_property.{ScopeOptionKey}" is a constant interpolated string over two const strings, so it is folded rather than allocated. String comparison (7) - OrdinalIgnoreCase throughout, null-safe. API surface (8) - no public API added, changed, or removed; the touched Scope* members are internal const. Dependency management (23) - no eng/Versions.props, Version.Details.xml, Directory.Packages.props or PackageReference edits. Security (24) - the Assembly.LoadFrom / Process.Start / Directory.SetCurrentDirectory banned-API entries are unchanged and still enforced for MT tasks and under scope = all; the narrowed default removes no security boundary. ChangeWave (2) - N/A: this runs in csc, not the MSBuild engine; opt-in is expressed by msbuild_task_analyzer.scope, and I confirmed a project-directory .globalconfig with is_global = true / msbuild_task_analyzer.scope = all really does re-enable MSBuildTask0001/0002/0004 on a plain ITask. Also clean: cross-platform (11), file I/O (17), idiomatic C# (16), target authoring (9), SDK boundary (15), evaluation model (21).

Correctness re-checks that came back clean: the new TypeKind.TypeParameter guard is correctly placed before IsConvertChangeTypeTaskItemType and is harmless for MSBuildTask0010, since a type parameter's SpecialType is always None. ITaskItem<T>[] unwraps to ITaskItem<T> and is skipped consistently. The README.md:299 row change from MSBuildTask0001-0005 to MSBuildTask0001-0004 for [MSBuildMultiThreadableTaskAnalyzed] helpers is correct - FindTaskTypes (TransitiveCallChainAnalyzer.cs:239) seeds only from ITask implementations, so a non-ITask helper is never an MSBuildTask0005 root. The stale rows at README.md:440/455/456 are pre-existing and outside every hunk. dotnet test src\TaskAnalyzer.Tests\TaskAnalyzer.Tests.csproj -> 262/262.

PR metadata

The title and description were rewritten against the diff. Corrections: the build.cmd -v quiet validation line was replaced, because build.cmd does not set BuildAnalyzer=true and therefore exercises nothing this PR changes; the MSBuildTask0006-0008 item no longer claims to be "being resolved in review", since it is still present at 51074bb; the documentation section now lists the "Severity Levels" rewrite and the [MSBuildMultiThreadableTaskAnalyzed] row correction; the MT opt-in list is now precise about MSBuildTask0005; and the src/Tasks / CI impact plus the missing MSBuildTask0009 downgrade path are stated explicitly.

Comment thread src/TaskAnalyzer/README.md Outdated
Comment thread src/TaskAnalyzer/DiagnosticDescriptors.cs Outdated
Comment thread src/TaskAnalyzer.Tests/UnsupportedTaskItemTypeAnalyzerTests.cs Outdated
Comment thread src/TaskAnalyzer/MultiThreadableTaskAnalyzer.cs Outdated
Comment thread src/TaskAnalyzer/MultiThreadableTaskAnalyzer.cs Outdated
@VolPlita

Copy link
Copy Markdown
Contributor Author

Design-level note from the second review pass (not tied to a diff line)

Four independent concerns are bundled, and one of them is a known unfixed defect.

The diff carries:

  1. the scope-default policy flip (SharedAnalyzerHelpers.cs:36-39, MultiThreadableTaskAnalyzer.cs:167/181/199) - contested, and racing open PR Scope MT-specific TaskAnalyzer diagnostics to MT tasks by default #14775;
  2. two severity swaps moving in opposite directions (DiagnosticDescriptors.cs:93,102);
  3. an open-generic false-positive fix (UnsupportedTaskItemTypeAnalyzer.cs:98-104) - one file, its own tests, no dependency on 1 or 2;
  4. a revert of Promote typed parameter diagnostics to warnings #14706's deliberate Info -> Warning promotion for MSBuildTask0006-0008 (README.md:22-24, AnalyzerReleases.Unshipped.md:10-12), which the description itself labels a defect.

Item 3 is uncontroversial and fully separable; today it cannot merge until items 1 and 2 are settled. Item 4 is unrelated to all of the others and is still present at 51074bb - carrying a self-declared regression through review means the first reviewer to approve also approves the regression, and RS2001 being in NoWarn means CI will never object.

Suggestion: land item 3 as its own PR so it ships immediately, and drop the MSBuildTask0006-0008 rows from this diff entirely rather than tracking them as a known issue. That leaves this PR to argue exactly one thing - the shipping scope and severity policy - which is the part that actually needs a decision.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@VolPlita VolPlita changed the title [TaskAnalyzer] Scope MSBuildTask0001-0005 to MT tasks by default; swap MSBuildTask0009/0010 severities [TaskAnalyzer] Align diagnostic severities and ignore open generic ITaskItem<T> Aug 25, 2026
@VolPlita
VolPlita merged commit 6283dd9 into dotnet:main Aug 26, 2026
10 checks passed
ViktorHofer added a commit that referenced this pull request Aug 26, 2026
The severity bullet list in the TaskAnalyzer README conflicted: main
reclassified MSBuildTask0006-0008 as Info and MSBuildTask0010 as
Warning in #14811, while this branch had appended bullets for
MSBuildTask0012-0015. Kept main's rewritten taxonomy for
MSBuildTask0001-0011 and re-added the four newer bullets after it.

Also removed a stray conflict marker that the previous merge left in the
MSBuildTask0014 section.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants