Skip to content

Consolidate duplicate MSBuildUtilities copies (#51487)#54947

Open
mthalman wants to merge 1 commit into
dotnet:mainfrom
mthalman:mthalman-top-refactoring-candidate
Open

Consolidate duplicate MSBuildUtilities copies (#51487)#54947
mthalman wants to merge 1 commit into
dotnet:mainfrom
mthalman:mthalman-top-refactoring-candidate

Conversation

@mthalman

@mthalman mthalman commented Jun 23, 2026

Copy link
Copy Markdown
Member

Why

MSBuildUtilities existed as two copies whose class bodies were byte-for-byte identical, differing only by namespace:

  • src/Common/MSBuildUtilities.cs in Microsoft.DotNet.Cli, compiled into the SDK MSBuild build tasks.
  • src/Cli/Microsoft.DotNet.FileBasedPrograms/MSBuildUtilities.cs in Microsoft.DotNet.FileBasedPrograms, shipped in the source package and consumed by Roslyn, the dotnet CLI, and ProjectTools.

Keeping two copies in sync is exactly the duplication tracked by #51487.

What

Collapse the two copies into the single physical file src/Common/MSBuildUtilities.cs and switch the namespace at compile time with an MSBUILD_BUILD_TASKS symbol:

  • The default form (no symbol) is the one that originally shipped in the source package: namespace Microsoft.DotNet.FileBasedPrograms, with #nullable enable and using System;. External and uncontrolled consumers (Roslyn, the dotnet CLI) compile the shipped contentFiles with no symbols defined, so this default keeps their input unchanged.
  • The two build-tasks projects (Microsoft.NET.Build.Tasks and Microsoft.NET.Build.Extensions.Tasks) define MSBUILD_BUILD_TASKS, which selects the Microsoft.DotNet.Cli namespace and drops the nullable/using directives. Those projects enable nullable and provide System via ImplicitUsings, so emitting the directives there would otherwise trip IDE0240/IDE0005.

The class body is unchanged, so the emitted IL for ConvertStringToBool is identical to before. Net result is +27 / -72 with one shared file instead of two.

Validation

  • Built every consumer clean (0/0): both build-tasks projects (net11.0 + net472), Microsoft.DotNet.ProjectTools, the Microsoft.DotNet.FileBasedPrograms source package, and the dotnet CLI.
  • Inspected the compiled assemblies' metadata to confirm per-assembly namespaces: the two build-tasks DLLs expose Microsoft.DotNet.Cli.MSBuildUtilities; Microsoft.DotNet.ProjectTools.dll exposes Microsoft.DotNet.FileBasedPrograms.MSBuildUtilities.
  • Confirmed the shipped source package still packs MSBuildUtilities.cs into contentFiles/cs/{net9.0,netstandard2.0}/ defaulting to the Microsoft.DotNet.FileBasedPrograms namespace, matching the prior shipped contract.
  • Ran the build-tasks unit tests that exercise ConvertStringToBool (ProcessFrameworkReferences: 39/39 passing).

InternalAPI.Unshipped.txt is unchanged because the default namespace remains Microsoft.DotNet.FileBasedPrograms.

Contributes to #51487

The MSBuildUtilities helper existed as two byte-identical-bodied copies
differing only by namespace: one in src/Common (Microsoft.DotNet.Cli, used
by the SDK MSBuild build tasks) and one in
src/Cli/Microsoft.DotNet.FileBasedPrograms (Microsoft.DotNet.FileBasedPrograms,
shipped in the source package and consumed by Roslyn, the dotnet CLI, and
ProjectTools).

Keep a single physical file in src/Common and switch the namespace with an
MSBUILD_BUILD_TASKS compile symbol. The default (no symbol) form matches the
file as it originally shipped in the source package
(Microsoft.DotNet.FileBasedPrograms, #nullable enable, using System;) so
external consumers see no change. The two build-tasks projects define
MSBUILD_BUILD_TASKS to select the Microsoft.DotNet.Cli namespace and suppress
the redundant nullable/using directives (which would otherwise trip
IDE0240/IDE0005 there).

The class body is unchanged. Verified by building all consumers (build tasks,
ProjectTools, source package, dotnet CLI), inspecting the compiled assemblies'
metadata to confirm the per-assembly namespaces, and running the build-tasks
unit tests that exercise ConvertStringToBool.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 23, 2026 18:16

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 removes the duplicated MSBuildUtilities source by consolidating both byte-identical copies into src/Common/MSBuildUtilities.cs, using an MSBUILD_BUILD_TASKS compilation symbol to select the appropriate namespace for each consumer (build tasks vs. FileBasedPrograms source package).

Changes:

  • Added MSBUILD_BUILD_TASKS constant to the two MSBuild build-task projects so the shared file compiles into Microsoft.DotNet.Cli.
  • Updated src/Common/MSBuildUtilities.cs to switch namespaces (and file-level directives) via #if MSBUILD_BUILD_TASKS.
  • Removed the old FileBasedPrograms-local MSBuildUtilities.cs and linked the shared src/Common/MSBuildUtilities.cs into the FileBasedPrograms shared items.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj Defines MSBUILD_BUILD_TASKS so the shared utility compiles under the build-task namespace.
src/Tasks/Microsoft.NET.Build.Extensions.Tasks/Microsoft.NET.Build.Extensions.Tasks.csproj Adds MSBUILD_BUILD_TASKS alongside existing constants for consistent build-task compilation.
src/Common/MSBuildUtilities.cs Centralizes the implementation and conditionally selects namespace/directives per consumer.
src/Cli/Microsoft.DotNet.FileBasedPrograms/MSBuildUtilities.cs Deletes the redundant local copy now that the file is shared.
src/Cli/Microsoft.DotNet.FileBasedPrograms/Microsoft.DotNet.FileBasedPrograms.projitems Links the shared src/Common/MSBuildUtilities.cs into the FileBasedPrograms source package inputs.

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.

2 participants