Analysis of commit 916e3a0
Assignee: @copilot
Summary
ObjectPool<T> is implemented independently in two separate projects — MSTest.Analyzers and Microsoft.Testing.Platform — with 160 duplicated lines across 6 clone pairs. Both implementations are internal copies of the same Roslyn object-pooling pattern with near-identical logic and comments.
Duplication Details
Pattern: Parallel ObjectPool(T) Implementations
- Severity: Medium
- Occurrences: 6 clone pairs, 160 duplicated lines
- Locations:
src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ObjectPool.cs (lines 44–276, 281 lines total)
src/Platform/Microsoft.Testing.Platform/Helpers/ObjectPool.cs (lines 52–289, 294 lines total)
The two files share:
- The
Element struct definition (lines 44–94 / 52–102, 51 lines)
- The
Allocate / Free loop pattern (lines 134–159 / 147–172, 26 lines)
- The
CreateInstance factory overloads (lines 161–178 / 174–191, 18 lines)
- The
ObjectPool<T>.Clear method (lines 197–213 / 210–226, 17 lines)
- The
ForgetTrackedObject / leak-detection block (lines 229–266 / 242–279, 38 lines)
- The
DebugViewOfPool helpers (lines 267–276 / 280–289, 10 lines)
Code Sample (shared Allocate logic):
// src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ObjectPool.cs lines 134-159
// src/Platform/Microsoft.Testing.Platform/Helpers/ObjectPool.cs lines 147-172
public T Allocate()
{
// PERF: Examine the first element. If that fails, AllocateSlow will look at the remaining elements.
// Note that the initial read is optimistically not synchronized. That is intentional.
// We will interlock only when we have a candidate. In a worst case we may miss some
// recently returned objects. Not a big deal.
T? inst = _firstItem;
if (inst == null || inst != Interlocked.CompareExchange(ref _firstItem, null, inst))
{
inst = AllocateSlow();
}
...
}
Impact Analysis
- Maintainability: Any bug fix or improvement to the pool implementation must be applied twice. The two copies have already diverged — e.g. the Platform copy adds
[ExcludeFromCodeCoverage], #pragma warning disable SA1201, and extra StyleCop suppressions not present in the Analyzer copy.
- Bug Risk: Fixes applied to one copy will silently miss the other, causing inconsistent behavior.
- Code Bloat: ~300 lines of duplicated infrastructure code.
Refactoring Recommendations
-
Move to a shared internal package or linked file
- Create
src/Platform/SharedExtensionHelpers/ObjectPool.cs (the SharedExtensionHelpers pattern already exists in the repo)
- Or use
<Compile Include="..." Link="..." /> MSBuild linking to share the file between the two projects
- Estimated effort: 2–3 hours
- Benefits: Single source of truth; fixes and improvements propagate to both consumers
-
Expose via InternalsVisibleTo from Platform
- If the Platform project is already a dependency of the Analyzers project (or a shared helpers project), expose the existing
ObjectPool<T> as internal-visible to Analyzers
- Estimated effort: 1 hour
Implementation Checklist
Analysis Metadata
- Analyzed Files: 1003 C# source files
- Detection Method: jscpd semantic code analysis (threshold: minLines=6, minTokens=50)
- Commit: 916e3a0
- Analysis Date: 2026-06-13
🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Duplicate Code Detector workflow. · 734 AIC · ⌖ 14.1 AIC · [◷]( · ◷)
Add this agentic workflows to your repo
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/duplicate-code-detector.md@main
Analysis of commit 916e3a0
Assignee:
@copilotSummary
ObjectPool<T>is implemented independently in two separate projects —MSTest.AnalyzersandMicrosoft.Testing.Platform— with 160 duplicated lines across 6 clone pairs. Both implementations are internal copies of the same Roslyn object-pooling pattern with near-identical logic and comments.Duplication Details
Pattern: Parallel ObjectPool(T) Implementations
src/Analyzers/MSTest.Analyzers/RoslynAnalyzerHelpers/ObjectPool.cs(lines 44–276, 281 lines total)src/Platform/Microsoft.Testing.Platform/Helpers/ObjectPool.cs(lines 52–289, 294 lines total)The two files share:
Elementstruct definition (lines 44–94 / 52–102, 51 lines)Allocate/ Free loop pattern (lines 134–159 / 147–172, 26 lines)CreateInstancefactory overloads (lines 161–178 / 174–191, 18 lines)ObjectPool<T>.Clearmethod (lines 197–213 / 210–226, 17 lines)ForgetTrackedObject/ leak-detection block (lines 229–266 / 242–279, 38 lines)DebugViewOfPoolhelpers (lines 267–276 / 280–289, 10 lines)Code Sample (shared
Allocatelogic):Impact Analysis
[ExcludeFromCodeCoverage],#pragma warning disable SA1201, and extra StyleCop suppressions not present in the Analyzer copy.Refactoring Recommendations
Move to a shared internal package or linked file
src/Platform/SharedExtensionHelpers/ObjectPool.cs(theSharedExtensionHelperspattern already exists in the repo)<Compile Include="..." Link="..." />MSBuild linking to share the file between the two projectsExpose via
InternalsVisibleTofrom PlatformObjectPool<T>as internal-visible to AnalyzersImplementation Checklist
MSTest.AnalyzerstoMicrosoft.Testing.Platformis feasible (analyzer packages typically can't reference runtime packages)InternalsVisibleTo)Analysis Metadata
Add this agentic workflows to your repo
To install this agentic workflow, run