.NET: Add ReferenceTrimmer and remove unused references#4487
.NET: Add ReferenceTrimmer and remove unused references#4487dfederm wants to merge 1 commit intomicrosoft:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds ReferenceTrimmer to the .NET build so unnecessary project/package/assembly references can be detected and removed, and then applies the tool’s findings across tests, samples, and a few libraries to reduce/normalize dependency declarations.
Changes:
- Introduce
ReferenceTrimmeras a repo-wide dependency and adjust analyzer references to be applied globally. - Remove unused
ProjectReference/PackageReferenceitems and add explicit references where transitive dependencies were previously masking missing direct dependencies. - Normalize test dependencies by removing
Moqfromdotnet/tests/Directory.Build.propsand adding it only to the test projects that actually use it.
Reviewed changes
Copilot reviewed 51 out of 51 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| dotnet/Directory.Packages.props | Adds global analyzer references and ReferenceTrimmer to apply across all projects. |
| dotnet/tests/Directory.Build.props | Stops referencing Moq for all tests; keeps only common test infra packages. |
| dotnet/tests/OpenAIResponse.IntegrationTests/OpenAIResponse.IntegrationTests.csproj | Removes an unused OpenAI project reference; relies on MEAI OpenAI package instead. |
| dotnet/tests/Microsoft.Agents.AI.Workflows.UnitTests/Microsoft.Agents.AI.Workflows.UnitTests.csproj | Marks analyzer project reference as used; adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests.csproj | Adds Moq; removes unused FluentAssertions. |
| dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.IntegrationTests/Microsoft.Agents.AI.Workflows.Declarative.IntegrationTests.csproj | Removes unused FluentAssertions. |
| dotnet/tests/Microsoft.Agents.AI.UnitTests/Microsoft.Agents.AI.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Purview.UnitTests/Microsoft.Agents.AI.Purview.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.OpenAI.UnitTests/Microsoft.Agents.AI.OpenAI.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Mem0.UnitTests/Microsoft.Agents.AI.Mem0.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Mem0.IntegrationTests/Microsoft.Agents.AI.Mem0.IntegrationTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.UnitTests/Microsoft.Agents.AI.Hosting.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests/Microsoft.Agents.AI.Hosting.OpenAI.UnitTests.csproj | Removes now-unnecessary conditional package references. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.AzureFunctions.IntegrationTests/Microsoft.Agents.AI.Hosting.AzureFunctions.IntegrationTests.csproj | Removes unused project reference; adds explicit configuration packages. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.UnitTests.csproj | Replaces unused FluentAssertions reference with Moq. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.IntegrationTests.csproj | Adds framework-compatibility conditions for some package references; swaps in Workflows project reference. |
| dotnet/tests/Microsoft.Agents.AI.Hosting.A2A.UnitTests/Microsoft.Agents.AI.Hosting.A2A.UnitTests.csproj | Adds Moq; removes no-longer-needed conditional packages. |
| dotnet/tests/Microsoft.Agents.AI.DevUI.UnitTests/Microsoft.Agents.AI.DevUI.UnitTests.csproj | Replaces unused OpenAI package reference with Moq. |
| dotnet/tests/Microsoft.Agents.AI.Declarative.UnitTests/Microsoft.Agents.AI.Declarative.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.CosmosNoSql.UnitTests/Microsoft.Agents.AI.CosmosNoSql.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.AzureAI.UnitTests/Microsoft.Agents.AI.AzureAI.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.AzureAI.Persistent.UnitTests/Microsoft.Agents.AI.AzureAI.Persistent.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Anthropic.UnitTests/Microsoft.Agents.AI.Anthropic.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/Microsoft.Agents.AI.Abstractions.UnitTests.csproj | Adds Moq explicitly. |
| dotnet/tests/Microsoft.Agents.AI.AGUI.UnitTests/Microsoft.Agents.AI.AGUI.UnitTests.csproj | Replaces unused FluentAssertions reference with Moq. |
| dotnet/src/Microsoft.Agents.AI.Workflows.Declarative/Microsoft.Agents.AI.Workflows.Declarative.csproj | Makes System.CodeDom conditional to avoid redundant net472 package reference. |
| dotnet/src/Microsoft.Agents.AI.Mem0/Microsoft.Agents.AI.Mem0.csproj | Adds explicit logging abstractions dependency. |
| dotnet/src/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore/Microsoft.Agents.AI.Hosting.AGUI.AspNetCore.csproj | Replaces unused hosting project reference with required package/project references. |
| dotnet/src/Microsoft.Agents.AI.Abstractions/Microsoft.Agents.AI.Abstractions.csproj | Removes unused logging abstractions package reference. |
| dotnet/src/Microsoft.Agents.AI.AGUI/Microsoft.Agents.AI.AGUI.csproj | Removes unused abstractions project reference. |
| dotnet/samples/05-end-to-end/M365Agent/M365Agent.csproj | Switches from OpenAI project reference to core AI project and MEAI OpenAI package usage. |
| dotnet/samples/05-end-to-end/HostedAgents/AgentsInWorkflows/AgentsInWorkflows.csproj | Removes analyzer reference removal block (no longer needed with global refs). |
| dotnet/samples/05-end-to-end/HostedAgents/AgentWithTools/AgentWithTools.csproj | Removes analyzer reference removal block. |
| dotnet/samples/05-end-to-end/HostedAgents/AgentWithTextSearchRag/AgentWithTextSearchRag.csproj | Removes analyzer reference removal block. |
| dotnet/samples/05-end-to-end/HostedAgents/AgentWithLocalTools/AgentWithLocalTools.csproj | Removes analyzer reference removal block. |
| dotnet/samples/05-end-to-end/HostedAgents/AgentWithHostedMCP/AgentWithHostedMCP.csproj | Removes analyzer reference removal block. |
| dotnet/samples/05-end-to-end/HostedAgents/AgentThreadAndHITL/AgentThreadAndHITL.csproj | Removes analyzer reference removal block. |
| dotnet/samples/05-end-to-end/AspNetAgentAuthorization/Service/Service.csproj | Switches from OpenAI project reference to core AI project and MEAI OpenAI package usage. |
| dotnet/samples/05-end-to-end/AgentWithPurview/AgentWithPurview.csproj | Removes OpenAI project reference; adds MEAI OpenAI package reference. |
| dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj | Removes hosting OpenAI project reference; adds MEAI OpenAI package reference. |
| dotnet/samples/05-end-to-end/AGUIClientServer/AGUIServer/AGUIServer.csproj | Adjusts AGUI-related project references and adds net10 compatibility conditions. |
| dotnet/samples/05-end-to-end/AGUIClientServer/AGUIDojoServer/AGUIDojoServer.csproj | Removes unused project references; adds MEAI OpenAI package reference. |
| dotnet/samples/04-hosting/A2A/A2AAgent_PollingForTaskCompletion/A2AAgent_PollingForTaskCompletion.csproj | Removes unused references (OpenAI project + async interfaces package). |
| dotnet/samples/03-workflows/_StartHere/05_SubWorkflows/05_SubWorkflows.csproj | Adds net10 compatibility condition to avoid redundant direct reference. |
| dotnet/samples/02-agents/DeclarativeAgents/ChatClient/DeclarativeChatClientAgents.csproj | Makes OpenAI project reference conditional; relies on packages for net10 path. |
| dotnet/samples/02-agents/Agents/Agent_Step17_AdditionalAIContext/Agent_Step17_AdditionalAIContext.csproj | Adds net10 compatibility conditions around object model refs. |
| dotnet/samples/02-agents/Agents/Agent_Step16_Declarative/Agent_Step16_Declarative.csproj | Makes OpenAI project reference conditional for net10. |
| dotnet/samples/02-agents/Agents/Agent_Step11_Middleware/Agent_Step11_Middleware.csproj | Replaces OpenAI project reference with MEAI OpenAI package reference. |
| dotnet/samples/02-agents/AgentWithOpenAI/Agent_OpenAI_Step02_Reasoning/Agent_OpenAI_Step02_Reasoning.csproj | Replaces OpenAI project reference with core AI + MEAI OpenAI package references. |
| dotnet/samples/02-agents/AgentProviders/Agent_With_CustomImplementation/Agent_With_CustomImplementation.csproj | Replaces direct AI project reference with explicit AI abstractions + MEAI package dependency. |
| dotnet/samples/02-agents/AgentOpenTelemetry/AgentOpenTelemetry.csproj | Makes OpenAI project reference conditional for net10. |
Comments suppressed due to low confidence (1)
dotnet/samples/05-end-to-end/AgentWebChat/AgentWebChat.Web/AgentWebChat.Web.csproj:19
- This project’s code uses OpenAI SDK types directly (e.g.,
OpenAIClientOptions,ChatClient,ResponsesClientunderAgentWebChat.Web/*) but the project file only referencesMicrosoft.Extensions.AI.OpenAI. Consider adding an explicitPackageReferencetoOpenAIso the build doesn’t depend onMicrosoft.Extensions.AI.OpenAIcontinuing to bring the OpenAI SDK transitively.
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Hosting.A2A\Microsoft.Agents.AI.Hosting.A2A.csproj" />
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Hosting\Microsoft.Agents.AI.Hosting.csproj" />
<ProjectReference Include="..\AgentWebChat.ServiceDefaults\AgentWebChat.ServiceDefaults.csproj" />
<ProjectReference Include="..\..\..\..\src\Microsoft.Agents.AI.Abstractions\Microsoft.Agents.AI.Abstractions.csproj" />
</ItemGroup>
| <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100" /> | ||
| <GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" /> | ||
| <GlobalPackageReference Include="xunit.analyzers" Version="1.23.0" /> | ||
| <GlobalPackageReference Include="Moq.Analyzers" Version="0.3.1" /> | ||
| <GlobalPackageReference Include="Roslynator.Analyzers" Version="4.14.1" /> | ||
| <GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" /> | ||
| <GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1" /> | ||
| <GlobalPackageReference Include="ReferenceTrimmer" Version="3.4.5" /> |
There was a problem hiding this comment.
These analyzer/tool packages were previously referenced with PrivateAssets=all and restricted IncludeAssets so they don’t flow to downstream consumers. With GlobalPackageReference and no metadata, they may become transitive dependencies and/or bring runtime/build assets into projects unexpectedly. Consider adding PrivateAssets="all" and the equivalent IncludeAssets (e.g., analyzers/build/buildTransitive only) for these global references, and keep versions in PackageVersion items if you want consistent central management.
| <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100" /> | |
| <GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" /> | |
| <GlobalPackageReference Include="xunit.analyzers" Version="1.23.0" /> | |
| <GlobalPackageReference Include="Moq.Analyzers" Version="0.3.1" /> | |
| <GlobalPackageReference Include="Roslynator.Analyzers" Version="4.14.1" /> | |
| <GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" /> | |
| <GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1" /> | |
| <GlobalPackageReference Include="ReferenceTrimmer" Version="3.4.5" /> | |
| <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="xunit.analyzers" Version="1.23.0" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="Moq.Analyzers" Version="0.3.1" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="Roslynator.Analyzers" Version="4.14.1" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> | |
| <GlobalPackageReference Include="ReferenceTrimmer" Version="3.4.5" PrivateAssets="all" IncludeAssets="analyzers;build;buildTransitive" /> |
| <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100" /> | ||
| <GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" /> | ||
| <GlobalPackageReference Include="xunit.analyzers" Version="1.23.0" /> | ||
| <GlobalPackageReference Include="Moq.Analyzers" Version="0.3.1" /> | ||
| <GlobalPackageReference Include="Roslynator.Analyzers" Version="4.14.1" /> | ||
| <GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" /> | ||
| <GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1" /> | ||
| <GlobalPackageReference Include="ReferenceTrimmer" Version="3.4.5" /> |
There was a problem hiding this comment.
ReferenceTrimmer (and the remaining analyzer global references in this ItemGroup) should likely be marked as build-time only (e.g., PrivateAssets=all plus appropriate IncludeAssets) so it doesn’t become a transitive NuGet dependency of produced packages. Right now the GlobalPackageReference entries have no such metadata, which can change dependency graphs compared to the previous PackageReference approach.
| <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100" /> | |
| <GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" /> | |
| <GlobalPackageReference Include="xunit.analyzers" Version="1.23.0" /> | |
| <GlobalPackageReference Include="Moq.Analyzers" Version="0.3.1" /> | |
| <GlobalPackageReference Include="Roslynator.Analyzers" Version="4.14.1" /> | |
| <GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" /> | |
| <GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1" /> | |
| <GlobalPackageReference Include="ReferenceTrimmer" Version="3.4.5" /> | |
| <GlobalPackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.100" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="Microsoft.VisualStudio.Threading.Analyzers" Version="17.14.15" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="xunit.analyzers" Version="1.23.0" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="Moq.Analyzers" Version="0.3.1" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="Roslynator.Analyzers" Version="4.14.1" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="Roslynator.CodeAnalysis.Analyzers" Version="4.14.1" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="Roslynator.Formatting.Analyzers" Version="4.14.1" PrivateAssets="all" IncludeAssets="analyzers" /> | |
| <GlobalPackageReference Include="ReferenceTrimmer" Version="3.4.5" PrivateAssets="all" IncludeAssets="analyzers" /> |
| <PackageReference Include="Microsoft.Extensions.AI.OpenAI" /> | ||
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" /> | ||
| <ProjectReference Include="..\AgentConformance.IntegrationTests\AgentConformance.IntegrationTests.csproj" /> |
There was a problem hiding this comment.
This project uses the OpenAI SDK types (e.g., OpenAIClient / OpenAI.Responses) in OpenAIResponseFixture.cs but only references Microsoft.Extensions.AI.OpenAI. To avoid relying on transitive package dependencies, add a direct PackageReference to the OpenAI package (or ensure it’s referenced in a way that won’t change if Microsoft.Extensions.AI.OpenAI updates its dependency graph).
dotnet/samples/05-end-to-end/AspNetAgentAuthorization/Service/Service.csproj
Show resolved
Hide resolved
|
|
||
| <ItemGroup> | ||
| <ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" /> | ||
| <ProjectReference Include="..\..\..\src\Microsoft.Agents.AI.OpenAI\Microsoft.Agents.AI.OpenAI.csproj" Condition="!$([MSBuild]::IsTargetFrameworkCompatible($(TargetFramework), 'net10.0'))" /> |
There was a problem hiding this comment.
Since this project is only targeting net 10.0, this condition will never be true, and therefore this reference can be removed in its entirety.
There was a problem hiding this comment.
Same for a few other sample projects below as well.
| <ItemGroup> | ||
| <PackageReference Include="coverlet.collector" /> | ||
| <PackageReference Include="Microsoft.NET.Test.Sdk" /> | ||
| <PackageReference Include="Moq" /> |
There was a problem hiding this comment.
Can we keep this here, to avoid adding it to many test projects individually? While it may not be used in each test project, it's used in most of them, and having the extra dependency is OK for test projects.
Add ReferenceTrimmer to enable detection of unnecessary project, package, and assembly references during build. Remove all unused references identified by ReferenceTrimmer.
Note: Because both ProjectReferences and PackageReferences are transitive, sometimes removing an unused dependency will cause build errors due to missing a dependency that was previously pull in transitively. In these cases, the reference is explicitly added. So despite this change having many added references, it's actually reducing references as those added references were previously underdefined but existing dependencies (due to transitivity).
Disclosure: I own ReferenceTrimmer, but I do think it will be helpful to this repo, as evidenced by the many unused references it was able to identify. Adding it to your repo will help keep the references clean.