Skip to content

Commit 618cbac

Browse files
committed
.
1 parent e2c8ded commit 618cbac

File tree

208 files changed

+383
-2341
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

208 files changed

+383
-2341
lines changed

src/ApiBuilderTests/FrameworkSplitterTest.cs

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,19 @@ void ProcessFile(string sourceFile, FrameworkIdentifier framework, string framew
5353
var code = File.ReadAllText(sourceFile);
5454

5555
var frameworkSymbols = framework.Directives;
56-
var sharedSymbols = GetSharedSymbols();
56+
var featureSymbols = GetFeatureSymbols();
57+
var parseSymbols = GetParseSymbols();
5758

58-
// Parse with ALL symbols (framework + shared)
59-
// This makes all code active (both framework and feature code)
60-
var allSymbols = frameworkSymbols.Concat(sharedSymbols).ToList();
59+
// Parse with framework + parse symbols
60+
// This makes code active where those symbols are used
61+
var allSymbols = frameworkSymbols.Concat(parseSymbols).ToList();
6162
var parseOptions = CSharpParseOptions.Default.WithPreprocessorSymbols(allSymbols);
6263
var syntaxTree = CSharpSyntaxTree.ParseText(code, parseOptions);
6364

6465
// Get the root and remove only framework-related directives
6566
// Feature directives will be kept
6667
var root = syntaxTree.GetRoot();
67-
var processedRoot = RemoveFrameworkDirectives(root, sharedSymbols);
68+
var processedRoot = RemoveFrameworkDirectives(root, featureSymbols);
6869

6970
// Check if the file has any meaningful code
7071
if (!HasMeaningfulCode(processedRoot))
@@ -148,14 +149,16 @@ or ConversionOperatorDeclarationSyntax
148149
return hasNonPolyfillTypes;
149150
}
150151

151-
static SyntaxNode RemoveFrameworkDirectives(SyntaxNode root, List<string> sharedSymbols)
152+
static SyntaxNode RemoveFrameworkDirectives(SyntaxNode root, List<string> featureSymbols)
152153
{
153154
// Remove only framework-related preprocessor directives while keeping feature directives
154-
var rewriter = new DirectiveRemovalRewriter(sharedSymbols);
155+
var rewriter = new DirectiveRemovalRewriter(featureSymbols);
155156
return rewriter.Visit(root);
156157
}
157158

158-
List<string> GetSharedSymbols() =>
159+
// Symbols to define during parsing (makes code active)
160+
// Excludes symbols that typically appear negated (like !RefsBclMemory)
161+
List<string> GetParseSymbols() =>
159162
[
160163
"FeatureMemory",
161164
"FeatureRuntimeInformation",
@@ -167,7 +170,27 @@ List<string> GetSharedSymbols() =>
167170
"AllowUnsafeBlocks",
168171
"FeatureValueTask",
169172
"FeatureValueTuple",
170-
"FeatureCompression"
173+
"FeatureCompression",
174+
"PolyUseEmbeddedAttribute"
175+
];
176+
177+
// All feature symbols (for IsFrameworkRelated check)
178+
// Includes symbols that appear negated - we still want to recognize them as feature flags
179+
List<string> GetFeatureSymbols() =>
180+
[
181+
"FeatureMemory",
182+
"FeatureRuntimeInformation",
183+
"PolyEnsure",
184+
"PolyArgumentExceptions",
185+
"PolyPublic",
186+
"FeatureHttp",
187+
"PolyNullability",
188+
"AllowUnsafeBlocks",
189+
"FeatureValueTask",
190+
"FeatureValueTuple",
191+
"FeatureCompression",
192+
"PolyUseEmbeddedAttribute",
193+
"RefsBclMemory"
171194
];
172195

173196
List<FrameworkIdentifier> GetAllTargetFrameworks() =>
@@ -480,6 +503,7 @@ partial class DirectiveRemovalRewriter(List<string> sharedSymbols) : CSharpSynta
480503
{
481504
readonly HashSet<string> sharedSymbols = sharedSymbols.ToHashSet();
482505
readonly Stack<bool> directiveStack = new();
506+
bool removeNextDisabledText; // Set when we remove a non-taken #else/#elif
483507

484508
readonly HashSet<string> frameworkRelatedKeywords =
485509
[
@@ -541,9 +565,10 @@ SyntaxTriviaList ProcessTrivia(SyntaxTriviaList triviaList)
541565
// Check if this disabled text is part of a framework conditional
542566
// Only check the INNERMOST directive (Peek), not any outer ones
543567
var insideFrameworkBlock = directiveStack.Count > 0 && directiveStack.Peek();
544-
if (insideFrameworkBlock)
568+
if (insideFrameworkBlock || removeNextDisabledText)
545569
{
546-
continue; // Remove disabled text from framework blocks
570+
removeNextDisabledText = false; // Reset the flag
571+
continue; // Remove disabled text
547572
}
548573
// Keep disabled text from feature blocks (though there shouldn't be any since we parse with all symbols)
549574
}
@@ -576,41 +601,63 @@ bool ShouldRemoveDirective(SyntaxTrivia trivia)
576601
{
577602
var isFrameworkRelated = IsFrameworkRelated(ifDirective.Condition.ToString());
578603

579-
// If the directive is inactive, always remove it (regardless of whether it's framework-related)
580-
// Inactive directives mean the code will never be compiled for this target framework
581-
if (!ifDirective.IsActive)
604+
// If this branch wasn't taken (condition was false), remove it entirely
605+
// BranchTaken indicates whether the condition evaluated to true
606+
if (!ifDirective.BranchTaken)
582607
{
583608
directiveStack.Push(true); // Mark for removal so matching endif is also removed
584609
return true;
585610
}
586611

587-
// For active directives, only remove if framework-related
612+
// For taken branches, only remove if framework-related
588613
directiveStack.Push(isFrameworkRelated);
589614
return isFrameworkRelated;
590615
}
591616

592617
// Check if it's an #elif directive
593618
if (structure is ElifDirectiveTriviaSyntax elifDirective)
594619
{
595-
// #elif is part of the current directive block
620+
// If we're already removing this directive block, continue removing
596621
if (directiveStack.Count > 0 && directiveStack.Peek())
597622
{
623+
// Keep stack as-is so matching #endif is also removed
624+
// Content after #elif (if taken) is active syntax tree, not disabled text
598625
return true;
599626
}
600627

601-
return false;
628+
// If #if branch was taken, this elif is inactive - remove it
629+
if (!elifDirective.BranchTaken)
630+
{
631+
removeNextDisabledText = true; // Remove the disabled text that follows
632+
return true;
633+
}
634+
635+
// This elif branch was taken and #if wasn't being removed
636+
// Check if it's framework-related
637+
var elifFrameworkRelated = IsFrameworkRelated(elifDirective.Condition.ToString());
638+
return elifFrameworkRelated;
602639
}
603640

604641
// Check if it's an #else directive
605-
if (structure is ElseDirectiveTriviaSyntax)
642+
if (structure is ElseDirectiveTriviaSyntax elseDirective)
606643
{
607-
// #else is part of the current directive block
644+
// If we're already removing this directive block, continue removing
608645
if (directiveStack.Count > 0 && directiveStack.Peek())
609646
{
647+
// Keep stack as-is so matching #endif is also removed
648+
// Content after #else (if taken) is active syntax tree, not disabled text
610649
return true;
611650
}
612651

613-
return false;
652+
// If previous branch was taken, this else is inactive - remove directive and content
653+
if (!elseDirective.BranchTaken)
654+
{
655+
removeNextDisabledText = true; // Remove the disabled text that follows
656+
return true;
657+
}
658+
659+
// This else branch was taken - remove the directive but keep content
660+
return true;
614661
}
615662

616663
// Check if it's an #endif directive

src/Consume/Consume.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
using System.Threading.Tasks;
3737
using System.Xml;
3838
using System.Xml.Linq;
39+
using Polyfills;
3940
using MemoryStream = System.IO.MemoryStream;
4041
// ReSharper disable MethodHasAsyncOverload
4142
// ReSharper disable RedundantCast

src/Split/net10.0/ArgumentExceptions/ArgumentNullExceptionPolyfill.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,5 @@ static partial class Polyfill
1111
extension(ArgumentNullException)
1212
{
1313

14-
#if AllowUnsafeBlocks && !NET9_0_OR_GREATER
15-
public static unsafe void ThrowIfNull(void* argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null)
16-
{
17-
if (argument is null)
18-
{
19-
throw new ArgumentNullException(paramName);
20-
}
21-
}
22-
#endif
2314
}
2415
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// <auto-generated />
2+
#pragma warning disable
3+
#if PolyUseEmbeddedAttribute
4+
5+
#if PolyPublic
6+
#error PolyPublic should not be used with PolyUseEmbeddedAttribute.
7+
#endif
8+
9+
namespace Microsoft.CodeAnalysis
10+
{
11+
internal sealed partial class EmbeddedAttribute : global::System.Attribute
12+
{
13+
}
14+
}
15+
#endif

src/Split/net10.0/Regex/RegexPolyfill.cs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,5 @@ static partial class Polyfill
1818
#if FeatureMemory
1919
#endif
2020

21-
#if !NET9_0_OR_GREATER && FeatureMemory && FeatureValueTuple
22-
23-
public static ValueSplitEnumerator EnumerateSplits(ReadOnlySpan<char> input, string pattern)
24-
{
25-
var regex = new Regex(pattern);
26-
return new ValueSplitEnumerator(input, regex, 0, 0);
27-
}
28-
29-
public static ValueSplitEnumerator EnumerateSplits(ReadOnlySpan<char> input, string pattern, RegexOptions options)
30-
{
31-
var regex = new Regex(pattern, options);
32-
return new ValueSplitEnumerator(input, regex, 0, 0);
33-
}
34-
35-
public static ValueSplitEnumerator EnumerateSplits(ReadOnlySpan<char> input, string pattern, RegexOptions options, TimeSpan matchTimeout)
36-
{
37-
var regex = new Regex(pattern, options, matchTimeout);
38-
return new ValueSplitEnumerator(input, regex, 0, 0);
39-
}
40-
41-
#endif
4221
}
4322
}

src/Split/net10.0/StringInterpolation/Polyfill_StringBuilder_Append.cs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,6 @@ namespace Polyfills;
88

99
static partial class Polyfill
1010
{
11-
#if FeatureMemory && !NET6_0_OR_GREATER
12-
/// <summary>Appends the specified interpolated string to this instance.</summary>
13-
public static StringBuilder Append(
14-
StringBuilder target,
15-
[InterpolatedStringHandlerArgument(nameof(target))]
16-
ref AppendInterpolatedStringHandler handler) => target;
17-
18-
/// <summary>Appends the specified interpolated string to this instance.</summary>
19-
public static StringBuilder Append(
20-
StringBuilder target,
21-
IFormatProvider? provider,
22-
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))]
23-
ref AppendInterpolatedStringHandler handler) => target;
24-
25-
#elif NET6_0_OR_GREATER
2611

2712
/// <summary>Appends the specified interpolated string to this instance.</summary>
2813

@@ -39,5 +24,4 @@ public static StringBuilder Append(
3924
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))] ref StringBuilder.AppendInterpolatedStringHandler handler) =>
4025
target.Append(provider, ref handler);
4126

42-
#endif
4327
}

src/Split/net10.0/StringInterpolation/Polyfill_StringBuilder_AppendLine.cs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,6 @@ namespace Polyfills;
88

99
static partial class Polyfill
1010
{
11-
#if FeatureMemory && !NET6_0_OR_GREATER
12-
13-
/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
14-
public static StringBuilder AppendLine(
15-
StringBuilder target,
16-
[InterpolatedStringHandlerArgument(nameof(target))]
17-
ref AppendInterpolatedStringHandler handler) =>
18-
target.AppendLine();
19-
20-
/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
21-
public static StringBuilder AppendLine(
22-
StringBuilder target,
23-
IFormatProvider? provider,
24-
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))]
25-
ref AppendInterpolatedStringHandler handler) =>
26-
target.AppendLine();
27-
28-
#elif NET6_0_OR_GREATER
2911

3012
/// <summary>Appends the specified interpolated string followed by the default line terminator to the end of the current StringBuilder object.</summary>
3113

@@ -43,6 +25,5 @@ public static StringBuilder AppendLine(
4325
[InterpolatedStringHandlerArgument(nameof(target), nameof(provider))]
4426
ref StringBuilder.AppendInterpolatedStringHandler handler) =>
4527
target.AppendLine(provider, ref handler);
46-
#endif
4728

4829
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// <auto-generated />
2+
#pragma warning disable
3+
#if PolyUseEmbeddedAttribute
4+
5+
#if PolyPublic
6+
#error PolyPublic should not be used with PolyUseEmbeddedAttribute.
7+
#endif
8+
9+
namespace Microsoft.CodeAnalysis
10+
{
11+
internal sealed partial class EmbeddedAttribute : global::System.Attribute
12+
{
13+
}
14+
}
15+
#endif

src/Split/net461/FilePolyfill.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -257,12 +257,8 @@ public static Task AppendAllTextAsync(string path, string? contents, Cancellatio
257257

258258
public static async Task<byte[]> ReadAllBytesAsync(string path, CancellationToken cancellationToken = default)
259259
{
260-
#if (NETCOREAPP2_0_OR_GREATER || NETSTANDARD) && FeatureRuntimeInformation
261-
var options = FileOptions.Asynchronous | (OperatingSystem.IsWindows() ? FileOptions.SequentialScan : FileOptions.None);
262-
#else
263-
var options = FileOptions.Asynchronous | FileOptions.SequentialScan;
264-
#endif
265-
using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, options);
260+
var options = FileOptions.Asynchronous | FileOptions.SequentialScan;
261+
using var stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, options);
266262
var length = (int) stream.Length;
267263
var bytes = new byte[length];
268264
var bytesRead = 0;

src/Split/net461/FileUnixModePolyfill.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,6 @@ public static UnixFileMode GetUnixFileMode(string path)
2626
{
2727
throw new PlatformNotSupportedException();
2828
}
29-
#else
30-
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
31-
{
32-
throw new PlatformNotSupportedException();
33-
}
3429
#endif
3530
if (string.IsNullOrEmpty(path))
3631
{
@@ -184,11 +179,6 @@ public static void SetUnixFileMode(string path, UnixFileMode mode)
184179
{
185180
throw new PlatformNotSupportedException();
186181
}
187-
#else
188-
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
189-
{
190-
throw new PlatformNotSupportedException();
191-
}
192182
#endif
193183
if (string.IsNullOrEmpty(path))
194184
{

0 commit comments

Comments
 (0)