Skip to content

Add MSBuildTask0012: require concrete MSBuild tasks to declare multithreading support - #14789

Open
ViktorHofer with Copilot wants to merge 6 commits into
mainfrom
copilot/add-opt-in-rule-multithreading-support
Open

Add MSBuildTask0012: require concrete MSBuild tasks to declare multithreading support#14789
ViktorHofer with Copilot wants to merge 6 commits into
mainfrom
copilot/add-opt-in-rule-multithreading-support

Conversation

Copilot AI commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Context

Once a repo finishes migrating its tasks to [MSBuildMultiThreadableTask], nothing keeps it migrated. TaskRouter.NeedsTaskHostInMultiThreadedMode routes any task lacking the attribute to an out-of-proc TaskHost — no error, no warning, just a slower build. All 11 existing rules either skip unannotated types (scope = multithreadable_only) or only flag unsafe API usage (scope = all), so a new task that happens to touch no banned API is never told to opt in.

MSBuildTask0012 turns that silent regression into a diagnostic.

Changes Made

New rule (RequireMultiThreadableTaskAnalyzer.cs) — reports non-abstract classes implementing ITask without a directly applied Microsoft.Build.Framework.MSBuildMultiThreadableTaskAttribute. Attribute detection mirrors the engine: matched by namespace + name via GetAttributes() (direct only), honoring Inherited = false. Consequently:

  • abstract bases and interfaces are never flagged;
  • a concrete leaf deriving from an annotated base is flagged — the silent mistake seen repeatedly in the Arcade migration;
  • generated code is excluded; test tasks are left to path-based .editorconfig severity.

Opting in — silent otherwise:

  • msbuild_task_analyzer.scope = require_multithreadable, a third value alongside all and multithreadable_only, meaning "analyze all task types and require the attribute";
  • or configuring dotnet_diagnostic.MSBuildTask0012.severity (.editorconfig per-file, .globalconfig, ruleset, <WarningsAsErrors>).

Code fix — "Declare multithreading support" adds the attribute, IMultiThreadableTask, and the TaskEnvironment property, falling back to attribute-only when the type already has a conflicting TaskEnvironment member. The other rules then take over on the newly annotated task.

Docs — the rule, and the scope option's three values, in src/TaskAnalyzer/README.md (scope was previously undocumented); a "Keeping a Migrated Repository Migrated" section in the multithreading spec; the AnalyzerReleases.Unshipped.md entry.

# one line in a shared .globalconfig protects every consuming repo
msbuild_task_analyzer.scope = require_multithreadable

Testing

23 tests across RequireMultiThreadableTaskAnalyzerTests and RequireMultiThreadableTaskCodeFixProviderTests cover the scope values, each severity-configuration path, the inheritance and abstract-type scoping rules, and the code fix including the conflicting-member fallback. Also verified end to end against a real dotnet build, which is how the severity bug in the notes below surfaced.

Notes

Two implementation constraints worth flagging for review:

  • The descriptor is isEnabledByDefault: true, with the opt-in enforced in analyzer code. Roslyn filters disabled-by-default descriptors before an analyzer can consult its options, so isEnabledByDefault: false cannot be re-enabled by the scope setting. To keep the cost of this at zero for unmigrated repos, no symbol action is registered at compilation start when nothing opts in.
  • dotnet_diagnostic.*.severity never reaches AnalyzerConfigOptions — Roslyn strips it into TreeOptions. The severity opt-in initially looked correct but did nothing in a real build; it now reads Compilation.Options.SyntaxTreeOptionsProvider (plus SpecificDiagnosticOptions for rulesets).

The doc nit in the issue does not apply here: MSBuildTask0006/0007/0008 are already Warning in both this repo's source and AnalyzerReleases.Unshipped.md; the Info severities came from the shipped 18.11.0-1.26420.118 package. Nothing changed.

Copilot AI and others added 4 commits August 23, 2026 16:06
Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>
Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>
Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>
Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>
Copilot AI changed the title [WIP] Add opt-in rule for declaring multithreading support in MSBuild tasks Add MSBuildTask0012: require concrete MSBuild tasks to declare multithreading support Aug 23, 2026
Copilot AI requested a review from ViktorHofer August 23, 2026 16:23
@ViktorHofer
ViktorHofer marked this pull request as ready for review August 23, 2026 17:49
Copilot AI lite review requested due to automatic review settings August 23, 2026 17:49

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

Adds a new opt-in TaskAuthoring analyzer rule to prevent “silent” multithreading regression by requiring concrete MSBuild tasks to explicitly opt into multithreaded execution via [MSBuildMultiThreadableTask], plus a code fix and accompanying documentation/tests.

Changes:

  • Introduces MSBuildTask0012 analyzer (RequireMultiThreadableTaskAnalyzer) with opt-in via msbuild_task_analyzer.scope = require_multithreadable or explicit severity configuration.
  • Adds a code fix to apply [MSBuildMultiThreadableTask] and, when safe, implement IMultiThreadableTask and add the TaskEnvironment property.
  • Updates docs, release notes, and unit test infrastructure + adds new analyzer/codefix test suites.
Show a summary per file
File Description
src/TaskAnalyzer/WellKnownTypeNames.cs Adds constants to support attribute detection by namespace + name.
src/TaskAnalyzer/SharedAnalyzerHelpers.cs Adds new require_multithreadable scope value and helper option readers.
src/TaskAnalyzer/RequireMultiThreadableTaskAnalyzer.cs New MSBuildTask0012 analyzer with opt-in gating and per-tree severity support.
src/TaskAnalyzer/RequireMultiThreadableTaskCodeFixProvider.cs New code fix to declare multithreading support (attribute + optional interface/property).
src/TaskAnalyzer/DiagnosticIds.cs Adds MSBuildTask0012 ID constant.
src/TaskAnalyzer/DiagnosticDescriptors.cs Adds MSBuildTask0012 descriptor and includes it in the global descriptor list.
src/TaskAnalyzer/README.md Documents MSBuildTask0012 and the expanded scope option behavior.
src/TaskAnalyzer/AnalyzerReleases.Unshipped.md Adds unshipped release entry for MSBuildTask0012.
src/TaskAnalyzer.Tests/TestHelpers.cs Extends test helpers to run arbitrary analyzers with supplied global options.
src/TaskAnalyzer.Tests/RequireMultiThreadableTaskAnalyzerTests.cs New analyzer tests covering scope/severity opt-in and inheritance/abstract behavior.
src/TaskAnalyzer.Tests/RequireMultiThreadableTaskCodeFixProviderTests.cs New code fix tests for the various “safe to implement interface/property” cases.
documentation/specs/multithreading/thread-safe-tasks.md Documents MSBuildTask0012 as a way to keep migrated repos from regressing.

Review details

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

  • Files reviewed: 12/12 changed files
  • Comments generated: 2
  • Review effort level: Lite

Comment thread src/TaskAnalyzer/RequireMultiThreadableTaskAnalyzer.cs Outdated
Comment thread src/TaskAnalyzer/RequireMultiThreadableTaskCodeFixProvider.cs
… opt-in comment

Co-authored-by: ViktorHofer <7412651+ViktorHofer@users.noreply.github.com>
Comment on lines +105 to +106
string.Equals(attributeClass.Name, WellKnownTypeNames.MultiThreadableTaskAttributeName, StringComparison.Ordinal) &&
string.Equals(attributeClass.ContainingNamespace?.ToDisplayString(), WellKnownTypeNames.FrameworkNamespace, StringComparison.Ordinal))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why doesn't this use the same machinery as the analysis that is triggered when explicitly opted in, in MultiThreadableTaskAnalyzer.OnCompilationStart?

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.

TaskAnalyzer: add an opt-in rule requiring concrete MSBuild tasks to declare multithreading support

4 participants