From ccf0be2856c7673ffbc737e8ef7b3d8974532dda Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Sat, 12 Jul 2025 00:01:10 -0400 Subject: [PATCH] Ensure IsExternalInit is type forwarded on NET builds It's included as internal on netstandard/net472, and the C# compiler may bake a reference to that into a consumer. If that consumer is then used with a net8.0+ build, the IsExternalInit needs to be there and forwarded to the real one. This switches our polyfill files to always be included but the actual contents ifdef'd out on TFMs that already have the contents. That then makes it easier to do specialized ifdef'ing in the future, as this does for IsExternalInit. --- .../System/Collections/Generic/CollectionExtensions.cs | 4 +++- .../CodeAnalysis/DynamicallyAccessedMemberTypes.cs | 2 ++ .../CodeAnalysis/DynamicallyAccessedMembersAttribute.cs | 2 ++ .../System/Diagnostics/CodeAnalysis/NullableAttributes.cs | 2 ++ .../CodeAnalysis/RequiresDynamicCodeAttribute.cs | 2 ++ .../Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs | 2 ++ .../CodeAnalysis/SetsRequiredMembersAttribute.cs | 2 ++ .../Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs | 4 +++- .../CodeAnalysis/UnconditionalSuppressMessageAttribute.cs | 4 +++- src/Common/Polyfills/System/IO/StreamExtensions.cs | 4 +++- src/Common/Polyfills/System/IO/TextWriterExtensions.cs | 4 +++- .../Polyfills/System/Net/Http/HttpClientExtensions.cs | 4 +++- src/Common/Polyfills/System/PasteArguments.cs | 4 +++- .../CompilerServices/CallerArgumentExpressionAttribute.cs | 2 ++ .../CompilerServices/CompilerFeatureRequiredAttribute.cs | 2 ++ .../CompilerServices/DefaultInterpolatedStringHandler.cs | 4 +++- .../System/Runtime/CompilerServices/IsExternalInit.cs | 6 ++++++ .../Runtime/CompilerServices/RequiredMemberAttribute.cs | 2 ++ .../System/Threading/CancellationTokenSourceExtensions.cs | 4 +++- .../System/Threading/Channels/ChannelExtensions.cs | 4 +++- src/Common/Polyfills/System/Threading/ForceYielding.cs | 4 +++- .../Polyfills/System/Threading/Tasks/TaskExtensions.cs | 4 +++- src/Directory.Build.props | 4 ++++ .../ModelContextProtocol.Core.csproj | 1 - src/ModelContextProtocol/ModelContextProtocol.csproj | 4 ---- 25 files changed, 64 insertions(+), 17 deletions(-) diff --git a/src/Common/Polyfills/System/Collections/Generic/CollectionExtensions.cs b/src/Common/Polyfills/System/Collections/Generic/CollectionExtensions.cs index ae4f697bc..fe5e09931 100644 --- a/src/Common/Polyfills/System/Collections/Generic/CollectionExtensions.cs +++ b/src/Common/Polyfills/System/Collections/Generic/CollectionExtensions.cs @@ -1,3 +1,4 @@ +#if !NET using ModelContextProtocol; namespace System.Collections.Generic; @@ -18,4 +19,5 @@ public static TValue GetValueOrDefault(this IReadOnlyDictionary ToDictionary(this IEnumerable> source) => source.ToDictionary(kv => kv.Key, kv => kv.Value); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs index ee6fa51a3..fcb09e4ff 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMemberTypes.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis; /// @@ -162,3 +163,4 @@ internal enum DynamicallyAccessedMemberTypes /// All = ~None } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs index 2d0140477..c99bb8e0a 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis; /// @@ -48,3 +49,4 @@ public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes member /// public DynamicallyAccessedMemberTypes MemberTypes { get; } } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/NullableAttributes.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/NullableAttributes.cs index ef577a9ca..0e7425e01 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/NullableAttributes.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/NullableAttributes.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis { /// Specifies that null is allowed as an input even if the corresponding type disallows it. @@ -137,3 +138,4 @@ public MemberNotNullWhenAttribute(bool returnValue, params string[] members) public string[] Members { get; } } } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs index 817ec6eaa..554a699a4 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis; /// @@ -36,3 +37,4 @@ public RequiresDynamicCodeAttribute(string message) /// public string? Url { get; set; } } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs index 3e845a534..eb91908ec 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCode.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis; /// @@ -37,3 +38,4 @@ public RequiresUnreferencedCodeAttribute(string message) /// public string? Url { get; set; } } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs index 83d6793b3..b778c95fc 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/SetsRequiredMembersAttribute.cs @@ -1,5 +1,7 @@ +#if !NET namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)] internal sealed class SetsRequiredMembersAttribute : Attribute; } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs index a8ab9bd28..1b884fa14 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/StringSyntaxAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis; /// Specifies the syntax used in a string. @@ -65,4 +66,5 @@ public StringSyntaxAttribute(string syntax, params object?[] arguments) /// The syntax identifier for strings containing XML. public const string Xml = nameof(Xml); -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs index b06d9ed1a..db80655a7 100644 --- a/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs +++ b/src/Common/Polyfills/System/Diagnostics/CodeAnalysis/UnconditionalSuppressMessageAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Diagnostics.CodeAnalysis; /// @@ -81,4 +82,5 @@ public UnconditionalSuppressMessageAttribute(string category, string checkId) /// Gets or sets the justification for suppressing the code analysis message. /// public string? Justification { get; set; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/IO/StreamExtensions.cs b/src/Common/Polyfills/System/IO/StreamExtensions.cs index 4dc8e2a5a..452b80321 100644 --- a/src/Common/Polyfills/System/IO/StreamExtensions.cs +++ b/src/Common/Polyfills/System/IO/StreamExtensions.cs @@ -3,6 +3,7 @@ using System.Runtime.InteropServices; using System.Text; +#if !NET namespace System.IO; internal static class StreamExtensions @@ -61,4 +62,5 @@ static async ValueTask ReadAsyncCore(Stream stream, Memory buffer, Ca } } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/IO/TextWriterExtensions.cs b/src/Common/Polyfills/System/IO/TextWriterExtensions.cs index 637cc09b0..a8dabd1fc 100644 --- a/src/Common/Polyfills/System/IO/TextWriterExtensions.cs +++ b/src/Common/Polyfills/System/IO/TextWriterExtensions.cs @@ -1,3 +1,4 @@ +#if !NET namespace System.IO; internal static class TextWriterExtensions @@ -7,4 +8,5 @@ public static async Task FlushAsync(this TextWriter writer, CancellationToken ca cancellationToken.ThrowIfCancellationRequested(); await writer.FlushAsync(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Net/Http/HttpClientExtensions.cs b/src/Common/Polyfills/System/Net/Http/HttpClientExtensions.cs index 85612b1d5..96a2948fb 100644 --- a/src/Common/Polyfills/System/Net/Http/HttpClientExtensions.cs +++ b/src/Common/Polyfills/System/Net/Http/HttpClientExtensions.cs @@ -1,3 +1,4 @@ +#if !NET using ModelContextProtocol; namespace System.Net.Http; @@ -19,4 +20,5 @@ public static async Task ReadAsStringAsync(this HttpContent content, Can cancellationToken.ThrowIfCancellationRequested(); return await content.ReadAsStringAsync(); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/PasteArguments.cs b/src/Common/Polyfills/System/PasteArguments.cs index 32eb4c69f..d838ec023 100644 --- a/src/Common/Polyfills/System/PasteArguments.cs +++ b/src/Common/Polyfills/System/PasteArguments.cs @@ -5,6 +5,7 @@ // https://github.com/dotnet/runtime/blob/d2650b6ae7023a2d9d2c74c56116f1f18472ab04/src/libraries/System.Private.CoreLib/src/System/PasteArguments.cs // and changed from using ValueStringBuilder to StringBuilder. +#if !NET using System.Text; namespace System; @@ -98,4 +99,5 @@ private static bool ContainsNoWhitespaceOrQuotes(string s) private const char Quote = '\"'; private const char Backslash = '\\'; -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs b/src/Common/Polyfills/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs index 968c31e8a..553afbea1 100644 --- a/src/Common/Polyfills/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs +++ b/src/Common/Polyfills/System/Runtime/CompilerServices/CallerArgumentExpressionAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Runtime.CompilerServices; [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] @@ -13,3 +14,4 @@ public CallerArgumentExpressionAttribute(string parameterName) public string ParameterName { get; } } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs b/src/Common/Polyfills/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs index 12f3e5d2d..1df9c1c21 100644 --- a/src/Common/Polyfills/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs +++ b/src/Common/Polyfills/System/Runtime/CompilerServices/CompilerFeatureRequiredAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET namespace System.Runtime.CompilerServices { /// @@ -30,3 +31,4 @@ public CompilerFeatureRequiredAttribute(string featureName) public const string RequiredMembers = nameof(RequiredMembers); } } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs b/src/Common/Polyfills/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs index 244f0875e..24622096f 100644 --- a/src/Common/Polyfills/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs +++ b/src/Common/Polyfills/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs @@ -5,6 +5,7 @@ // https://github.com/dotnet/runtime/blob/dd75c45c123055baacd7aa4418f425f412797a29/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/DefaultInterpolatedStringHandler.cs // and then modified to build on netstandard2.0. +#if !NET using System.Buffers; using System.Diagnostics; using System.Globalization; @@ -614,4 +615,5 @@ private static uint Clamp(uint value, uint min, uint max) return value; } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Runtime/CompilerServices/IsExternalInit.cs b/src/Common/Polyfills/System/Runtime/CompilerServices/IsExternalInit.cs index 70443090c..9ae535381 100644 --- a/src/Common/Polyfills/System/Runtime/CompilerServices/IsExternalInit.cs +++ b/src/Common/Polyfills/System/Runtime/CompilerServices/IsExternalInit.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET using System.ComponentModel; namespace System.Runtime.CompilerServices @@ -12,3 +13,8 @@ namespace System.Runtime.CompilerServices [EditorBrowsable(EditorBrowsableState.Never)] internal static class IsExternalInit; } +#else +// The compiler emits a reference to the internal copy of this type in the non-.NET builds, +// so we must include a forward to be compatible. +[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))] +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Runtime/CompilerServices/RequiredMemberAttribute.cs b/src/Common/Polyfills/System/Runtime/CompilerServices/RequiredMemberAttribute.cs index 6930dc4f1..35b6948a7 100644 --- a/src/Common/Polyfills/System/Runtime/CompilerServices/RequiredMemberAttribute.cs +++ b/src/Common/Polyfills/System/Runtime/CompilerServices/RequiredMemberAttribute.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if !NET using System.ComponentModel; namespace System.Runtime.CompilerServices @@ -10,3 +11,4 @@ namespace System.Runtime.CompilerServices [EditorBrowsable(EditorBrowsableState.Never)] internal sealed class RequiredMemberAttribute : Attribute; } +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Threading/CancellationTokenSourceExtensions.cs b/src/Common/Polyfills/System/Threading/CancellationTokenSourceExtensions.cs index 95acac96c..d5508153f 100644 --- a/src/Common/Polyfills/System/Threading/CancellationTokenSourceExtensions.cs +++ b/src/Common/Polyfills/System/Threading/CancellationTokenSourceExtensions.cs @@ -1,3 +1,4 @@ +#if !NET using ModelContextProtocol; namespace System.Threading.Tasks; @@ -11,4 +12,5 @@ public static Task CancelAsync(this CancellationTokenSource cancellationTokenSou cancellationTokenSource.Cancel(); return Task.CompletedTask; } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Threading/Channels/ChannelExtensions.cs b/src/Common/Polyfills/System/Threading/Channels/ChannelExtensions.cs index 89822eff1..6cda43e94 100644 --- a/src/Common/Polyfills/System/Threading/Channels/ChannelExtensions.cs +++ b/src/Common/Polyfills/System/Threading/Channels/ChannelExtensions.cs @@ -1,3 +1,4 @@ +#if !NET using System.Runtime.CompilerServices; namespace System.Threading.Channels; @@ -14,4 +15,5 @@ public static async IAsyncEnumerable ReadAllAsync(this ChannelReader re } } } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Threading/ForceYielding.cs b/src/Common/Polyfills/System/Threading/ForceYielding.cs index a25baa977..4ce99c87c 100644 --- a/src/Common/Polyfills/System/Threading/ForceYielding.cs +++ b/src/Common/Polyfills/System/Threading/ForceYielding.cs @@ -1,3 +1,4 @@ +#if !NET using System.Runtime.CompilerServices; namespace System.Threading; @@ -14,4 +15,5 @@ namespace System.Threading; public void OnCompleted(Action continuation) => ThreadPool.QueueUserWorkItem(a => ((Action)a!)(), continuation); public void UnsafeOnCompleted(Action continuation) => ThreadPool.UnsafeQueueUserWorkItem(a => ((Action)a!)(), continuation); public void GetResult() { } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Common/Polyfills/System/Threading/Tasks/TaskExtensions.cs b/src/Common/Polyfills/System/Threading/Tasks/TaskExtensions.cs index bee89a25d..68eb073d7 100644 --- a/src/Common/Polyfills/System/Threading/Tasks/TaskExtensions.cs +++ b/src/Common/Polyfills/System/Threading/Tasks/TaskExtensions.cs @@ -1,3 +1,4 @@ +#if !NET using ModelContextProtocol; namespace System.Threading.Tasks; @@ -49,4 +50,5 @@ public static async Task WaitAsync(this Task task, TimeSpan timeout, Cancellatio await task.ConfigureAwait(false); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b8408bacd..7859ba39a 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -23,6 +23,10 @@ + + + + diff --git a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj index f3ab71819..07a5ec1b0 100644 --- a/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj +++ b/src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj @@ -20,7 +20,6 @@ - diff --git a/src/ModelContextProtocol/ModelContextProtocol.csproj b/src/ModelContextProtocol/ModelContextProtocol.csproj index 994f3dcc5..963ba0fed 100644 --- a/src/ModelContextProtocol/ModelContextProtocol.csproj +++ b/src/ModelContextProtocol/ModelContextProtocol.csproj @@ -17,10 +17,6 @@ - - - -