Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Convert AOT/trim pragma suppressions to attributes so they propagate to consumers by Evangelink · Pull Request #8686 · microsoft/testfx · GitHub
Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers - #8686

Merged
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
May 31, 2026
Merged

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Amaury Levé (Evangelink) merged 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink

@EvangelinkAmaury Levé (Evangelink) commented May 29, 2026

Copy link
Copy Markdown
Member

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

FileChange
TestFramework/Internal/ReflectionTestMethodInfo.csAdd [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs[UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csSame on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csSame on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.csPer-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csLambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csPer-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csPer-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers
#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.
This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.
Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 17:28

CopilotAI 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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
FileDescription
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.csAdds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.csReplaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.csAdds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.csAdds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.csAdds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.csReplaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.csAdds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.csAdds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.csAdds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.csAdds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources
DotnetCli.RunAsync defaults warnAsError to true, which auto-injects
-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish
command. The acceptance test for this PR was written assuming TreatWarningsAsErrors
is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and
App Insights stay as warnings, and the test can grep the publish output for
the absence of suppressed source file names).
Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size
failed) due to dozens of trim warnings that are explicitly out of scope for this PR.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 29, 2026 20:13

CopilotAI 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.

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

@Evangelink
Amaury Levé (Evangelink) merged commit f76c12b into microsoft:mainMay 31, 2026
23 checks passed
@Evangelink
Amaury Levé (Evangelink) deleted the dev/amauryleve/aot-pragma-to-suppress-attribute branch May 31, 2026 06:38
Amaury Levé (Evangelink) added a commit that referenced this pull request Jun 1, 2026
…flection
- ReflectionMetadataEmitter: emit [DynamicDependency(All, typeof(T))] per test
class on the [ModuleInitializer], so the trimmer keeps constructors and other
reflected members alive (otherwise discovery fails with 'Cannot find a valid
constructor for test class').
- ReflectionMetadataEmitter: annotate ResolveMethod's Type parameter with
[DynamicallyAccessedMembers(PublicMethods | NonPublicMethods)] to satisfy
IL2070 in the generated module initializer.
- SourceGeneratedReflectionOperations: stop routing fallback through
_fallback.GetCustomAttributesCached. ReflectionOperations.NotCachedReflectionAccessor
reads PlatformServiceProvider.Instance.ReflectionOperations, which after
SetMetadata is the source-gen wrapper itself -- causing infinite mutual recursion
and a StackOverflowException at runtime. Use _fallback.GetCustomAttributes
(direct reflection) instead.
- MSTest.Sdk NativeAOT.targets: add MSTest.TestAdapter package reference and set
EnableMSTestRunner/IsTestingPlatformApplication = true (mirroring ClassicEngine.targets)
so MSTestAdapter.PlatformServices.dll (the source-generator runtime hook host) is
available to NAOT-published apps.
- NativeAotTests / SdkTests / TrimTests: tolerate upstream IL warnings from
Microsoft.TestPlatform.ObjectModel and System.Private.DataContractSerialization
(warnAsError: false) and assert via shared TrimAndAotAssertions.MSTestOwnedSourceFiles
that MSTest-owned source files do not appear in publish output, mirroring the
pattern established in PR #8686. Rename Publish_ShouldNotProduceTrimWarnings to
Publish_WithSourceGeneration_DoesNotSurfaceMSTestOwnedTrimWarnings.
- NativeAotTests: use AssertOutputContainsSummary helper (current MTP output format).
- samples/NativeAotRunner/TestProject1: convert to MSTest.Sdk shape and drop the
pinned MSTest.SourceGeneration 2.0.0-alpha.26228.3 reference (which emitted now-
removed Microsoft.Testing.Framework.TestNode types and broke the WindowsSamples
CI legs).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for freeto 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

@Evangelink