Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
225 commits
Select commit Hold shift + click to select a range
04ef6c2
Update BuildApiTest.cs
SimonCropp Jun 19, 2025
1967ea2
Update BuildApiTest.cs
SimonCropp Jun 20, 2025
e9d943c
Update BuildApiTest.cs
SimonCropp Jun 20, 2025
eb4dd0f
.
SimonCropp Jun 20, 2025
dc8079c
Update BuildApiTest.cs
SimonCropp Jun 20, 2025
bd28a54
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
8685db5
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
f72be2f
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
ad8c14f
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
2be4bcb
.
SimonCropp Jun 21, 2025
22a3a17
.
SimonCropp Jun 21, 2025
b4ee1ce
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
e69bc4d
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
4b408b7
.
SimonCropp Jun 21, 2025
5076b17
Update LinkReader.cs
SimonCropp Jun 21, 2025
11c1fe6
Update RoslynExtensions.cs
SimonCropp Jun 21, 2025
c2b507e
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
e4107ae
.
SimonCropp Jun 21, 2025
4f08a9d
Update BuildApiTest.cs
SimonCropp Jun 21, 2025
3182b38
.
SimonCropp Jun 21, 2025
3a6784c
Update DelegatePolyfill.cs
SimonCropp Jun 21, 2025
da9e1d2
Update DateTimePolyfill.cs
SimonCropp Jun 21, 2025
44494b4
Update DateTimePolyfill.cs
SimonCropp Jun 21, 2025
eec2c12
Update DelegatePolyfill.cs
SimonCropp Jun 21, 2025
db703c3
.
SimonCropp Jun 21, 2025
ebdf2c8
Merge branch 'main' into sdk10Version
SimonCropp Jun 21, 2025
2b43a07
.
SimonCropp Jun 21, 2025
4fead01
Update global.json
SimonCropp Jun 21, 2025
19679b4
.
SimonCropp Jun 21, 2025
9a107d5
Merge branch 'main' into sdk10Version
SimonCropp Jun 21, 2025
8acb22b
.
SimonCropp Jun 21, 2025
59138fa
.
SimonCropp Jun 21, 2025
f7c82e1
.
SimonCropp Jun 22, 2025
7080b99
Update StringPolyfill.cs
SimonCropp Jun 22, 2025
39a0600
Update StringPolyfill.cs
SimonCropp Jun 22, 2025
8274504
Update BuildApiTest.cs
SimonCropp Jun 22, 2025
90bebd3
.
SimonCropp Jun 22, 2025
e505ab7
Update RegexPolyfill.cs
SimonCropp Jun 22, 2025
5bb0bf2
.
SimonCropp Jun 22, 2025
1352c30
.
SimonCropp Jun 22, 2025
909af2a
.
SimonCropp Jun 22, 2025
79df7fb
.
SimonCropp Jun 22, 2025
6c8cf16
Update ULongPolyfill.cs
SimonCropp Jun 22, 2025
9831355
.
SimonCropp Jun 22, 2025
4cbadc5
.
SimonCropp Jun 22, 2025
36c65b7
Update DelegatePolyfill.cs
SimonCropp Jun 22, 2025
b810c95
.
SimonCropp Jun 22, 2025
a4c55f3
Update OperatingSystemPolyfill.cs
SimonCropp Jun 22, 2025
3f27230
.
SimonCropp Jun 22, 2025
9641780
.
SimonCropp Jun 22, 2025
8235058
.
SimonCropp Jun 22, 2025
d5c7efa
.
SimonCropp Jun 22, 2025
59bd03a
.
SimonCropp Jun 22, 2025
bfb7053
.
SimonCropp Jun 22, 2025
5dda7ce
.
SimonCropp Jun 22, 2025
7ad69f3
Update SHA256Polyfill.cs
SimonCropp Jun 22, 2025
55006d2
Update RandomPolyfill.cs
SimonCropp Jun 22, 2025
38770df
Update PathPolyfill.cs
SimonCropp Jun 22, 2025
b5f5353
Update MathPolyfill.cs
SimonCropp Jun 22, 2025
9f6cbc2
Update GuidPolyfill.cs
SimonCropp Jun 22, 2025
5bcff65
Update FilePolyfill.cs
SimonCropp Jun 22, 2025
fa33737
Update EnumPolyfill.cs
SimonCropp Jun 22, 2025
62f6793
Update DelegatePolyfill.cs
SimonCropp Jun 22, 2025
6a25f8b
Update DateTimePolyfill.cs
SimonCropp Jun 22, 2025
df27369
Update DateTimeOffsetPolyfill.cs
SimonCropp Jun 22, 2025
6b15cf4
.
SimonCropp Jun 22, 2025
1a9eb64
.
SimonCropp Jun 22, 2025
cb7a494
Update RegexPolyfill.cs
SimonCropp Jun 22, 2025
6710bde
.
SimonCropp Jun 22, 2025
3e29264
.
SimonCropp Jun 22, 2025
68bc278
.
SimonCropp Jun 22, 2025
57cb419
.
SimonCropp Jun 22, 2025
e664b2a
.
SimonCropp Jun 22, 2025
248424d
Merge branch 'main' into sdk10Version
SimonCropp Jun 25, 2025
3946f98
.
SimonCropp Jun 25, 2025
f4c45d0
Merge branch 'main' into sdk10Version
SimonCropp Jun 28, 2025
4da4004
.
SimonCropp Jun 28, 2025
f490ce9
Add EnvironmentPolyfill ProcessId (#367)
SimonCropp Jun 29, 2025
1970605
Update Directory.Build.props
SimonCropp Jun 29, 2025
33720ca
Merge branch 'main' into sdk10Version
SimonCropp Jun 30, 2025
77ea5f9
Merge branch 'main' into sdk10Version
SimonCropp Jun 30, 2025
9a65a30
cleanup
SimonCropp Jun 30, 2025
8c39391
Merge branch 'main' into sdk10Version
SimonCropp Jun 30, 2025
d4035f8
Merge branch 'main' into sdk10Version
SimonCropp Jun 30, 2025
3e33a24
Update GlobalUsings.cs
SimonCropp Jun 30, 2025
aa58b92
Update StringPolyfillTests.cs
SimonCropp Jun 30, 2025
99db355
Update StringPolyfill.cs
SimonCropp Jun 30, 2025
d82d93d
Update Directory.Build.props
SimonCropp Jun 30, 2025
8379356
Merge branch 'main' into sdk10Version
SimonCropp Jun 30, 2025
a5b5845
Merge branch 'main' into sdk10Version
SimonCropp Jul 1, 2025
8fe9a39
Merge branch 'main' into sdk10Version
SimonCropp Jul 1, 2025
e621583
docs
SimonCropp Jul 1, 2025
93ce284
Merge branch 'main' into sdk10Version
SimonCropp Jul 1, 2025
ce6f83d
Merge branch 'main' into sdk10Version
SimonCropp Jul 7, 2025
3d56c0c
.
SimonCropp Jul 7, 2025
7e9c20c
Add string.GetHashCode(ReadOnlySpan) (#370)
SimonCropp Jul 7, 2025
f25f1a6
Merge branch 'main' into sdk10Version
SimonCropp Jul 8, 2025
89d3e21
.
SimonCropp Jul 8, 2025
95ff8b9
.
SimonCropp Jul 8, 2025
1940c64
Update readme.md
SimonCropp Jul 8, 2025
1ee4d2c
Update Directory.Build.props
SimonCropp Jul 8, 2025
cc0dad2
Merge branch 'main' into sdk10Version
SimonCropp Jul 8, 2025
309a630
9.0.0-beta.9
SimonCropp Jul 8, 2025
8c07086
Merge branch 'main' into sdk10Version
SimonCropp Jul 8, 2025
7045f07
Update Directory.Build.props
SimonCropp Jul 8, 2025
3f89f48
Merge branch 'main' into sdk10Version
SimonCropp Jul 9, 2025
d342149
cleanup
SimonCropp Jul 9, 2025
5e78b33
Update Consume.cs
SimonCropp Jul 9, 2025
43b3b3e
Add XElement.LoadAsync (#375)
SimonCropp Jul 9, 2025
c6fa7fc
Add XDocument.LoadAsync (#376)
SimonCropp Jul 9, 2025
8c39832
Merge branch 'main' into sdk10Version
SimonCropp Jul 9, 2025
5254b87
Update Consume.cs
SimonCropp Jul 9, 2025
3837eae
docs
SimonCropp Jul 9, 2025
505fb5e
more tests
SimonCropp Jul 9, 2025
1dc2fe0
Use Sequential and detect encoding in FilePolyfill.Read* (#378)
SimonCropp Jul 9, 2025
b3ac2ce
Update FilePolyfill.cs
SimonCropp Jul 9, 2025
724aa98
Update FilePolyfill.cs
SimonCropp Jul 10, 2025
f0780d1
refs or cleanup
SimonCropp Jul 10, 2025
ef2d32b
Merge branch 'main' into sdk10Version
SimonCropp Jul 13, 2025
8f362d8
Merge branch 'main' into sdk10Version
SimonCropp Jul 14, 2025
0bf3adc
Update Directory.Build.props
SimonCropp Jul 14, 2025
0872000
Merge branch 'main' into sdk10Version
SimonCropp Jul 15, 2025
81750e1
fix SHA256.HashData bytes being filtered by memory (#382)
SimonCropp Jul 15, 2025
cbdbcbc
Merge branch 'main' into sdk10Version
SimonCropp Jul 16, 2025
93a1e87
Create GuidPolyfillTests.cs
SimonCropp Jul 16, 2025
3123c65
Update Consume.cs
SimonCropp Jul 16, 2025
83f3e88
Update Consume.cs
SimonCropp Jul 16, 2025
8b0b7d0
Update Consume.cs
SimonCropp Jul 16, 2025
220763f
Update global.json
SimonCropp Jul 16, 2025
5e1c1df
Add Guid Parse and TryParse for ReadOnlySpan bytes (#383)
SimonCropp Jul 16, 2025
382189b
Update BytePolyfill.cs
SimonCropp Jul 16, 2025
16c7276
Update BytePolyfill.cs
SimonCropp Jul 16, 2025
b218b5a
Update Directory.Build.props
SimonCropp Jul 17, 2025
b99e78c
Fix param names (#384)
SimonCropp Jul 17, 2025
11d5f19
Merge branch 'sdk10Version' of https://github.com/SimonCropp/Polyfill…
SimonCropp Jul 17, 2025
a3ac502
cleanup
SimonCropp Jul 17, 2025
d15c4b7
Update PolyfillTests_IEnumerable.cs
SimonCropp Jul 17, 2025
2733e95
add Enumerable Sequence and InfiniteSequence (#385)
SimonCropp Jul 17, 2025
78b47de
better-polyfill-filtering (#387)
SimonCropp Jul 18, 2025
adbda16
Merge branch 'main' into sdk10Version
SimonCropp Jul 18, 2025
db82538
Update OperatingSystemPolyfill.cs
SimonCropp Jul 18, 2025
ad8f5b7
Update StringPolyfill.cs
SimonCropp Jul 18, 2025
d81e9b8
Update readme.md
SimonCropp Jul 23, 2025
b702b84
Merge branch 'main' into sdk10Version
SimonCropp Jul 23, 2025
10fd74f
Merge branch 'main' into sdk10Version
SimonCropp Jul 23, 2025
391c4b5
Merge branch 'main' into sdk10Version
SimonCropp Aug 2, 2025
69dad2b
Merge branch 'main' into sdk10Version
SimonCropp Aug 2, 2025
1cc811a
Update StringPolyfill.cs
SimonCropp Aug 2, 2025
df5a214
Merge branch 'main' into sdk10Version
SimonCropp Aug 3, 2025
2fe9af1
fix TryParse
SimonCropp Aug 3, 2025
a9c3012
Single type (#393)
SimonCropp Aug 3, 2025
0315fc0
Update Directory.Build.props
SimonCropp Aug 3, 2025
977d58e
Update RegexPolyfill.cs
SimonCropp Aug 4, 2025
6b19388
Update Directory.Build.props
SimonCropp Aug 4, 2025
5211e21
Update appveyor.yml
SimonCropp Aug 4, 2025
16e6844
Merge branch 'main' into sdk10Version
SimonCropp Aug 4, 2025
186567c
Merge branch 'main' into sdk10Version
SimonCropp Aug 4, 2025
b944f79
Update appveyor.yml
SimonCropp Aug 4, 2025
0022963
Merge branch 'main' into sdk10Version
SimonCropp Aug 13, 2025
d5b751f
refs and cleanup
SimonCropp Aug 14, 2025
2a7f615
Revert "refs and cleanup"
SimonCropp Aug 14, 2025
7a0f478
Merge branch 'main' into sdk10Version
SimonCropp Aug 15, 2025
49366ce
Update PolyfillTests_IEnumerable.cs
SimonCropp Aug 15, 2025
59df925
Merge branch 'main' into sdk10Version
SimonCropp Aug 15, 2025
277b163
docs
SimonCropp Aug 15, 2025
52b395c
Update readme.md
SimonCropp Aug 28, 2025
8650048
Update PolyfillTests_XElement.cs
SimonCropp Aug 28, 2025
36f2a21
Update StringPolyfillTests.cs
SimonCropp Aug 28, 2025
4dd88d6
Merge branch 'main' into sdk10Version
SimonCropp Sep 19, 2025
12e56a5
.
SimonCropp Sep 19, 2025
e4b83c0
Merge branch 'main' into sdk10Version
SimonCropp Sep 19, 2025
ba72992
Merge branch 'main' into sdk10Version
SimonCropp Oct 1, 2025
af3f490
refs and cleanup
SimonCropp Oct 7, 2025
c685380
add ExcludeStatics to RequiresDynamicCode and RequiresUnreferencedCod…
SimonCropp Oct 7, 2025
d83eff7
Add option to generate EmbeddedAttribute (#388)
Youssef1313 Oct 7, 2025
a896229
Update Directory.Build.props
SimonCropp Oct 7, 2025
af9dea2
slnx
SimonCropp Oct 7, 2025
1d88abd
Update appveyor.yml
SimonCropp Oct 7, 2025
814e127
Update appveyor.yml
SimonCropp Oct 14, 2025
dd66c41
refs and cleanup
SimonCropp Oct 14, 2025
0de883b
Merge branch 'main' into sdk10Version
SimonCropp Oct 15, 2025
e854c9b
Update Directory.Packages.props
SimonCropp Oct 15, 2025
3fcfeeb
Update Directory.Packages.props
SimonCropp Oct 15, 2025
5928323
Revert "Update Directory.Packages.props"
SimonCropp Oct 15, 2025
f69b0d7
also check for valuetuple ref (#403)
SimonCropp Oct 15, 2025
1a9356b
Update Directory.Build.props
SimonCropp Oct 15, 2025
9bd2781
Merge branch 'sdk10Version' of https://github.com/SimonCropp/Polyfill…
SimonCropp Oct 15, 2025
e84bb69
remove redundant Message
SimonCropp Oct 15, 2025
0e52f49
docs
SimonCropp Oct 15, 2025
3a4a505
workaround rc2 pruning issue (#404)
SimonCropp Oct 15, 2025
8954d86
Update Directory.Build.props
SimonCropp Oct 15, 2025
91efbde
Add Guard.NotEqual (#405)
SimonCropp Oct 17, 2025
58392f8
more NotNullIfNotNull
SimonCropp Oct 17, 2025
258b323
docs
SimonCropp Oct 17, 2025
93db1be
Update GuardTests.cs
SimonCropp Oct 17, 2025
86a071f
Update GuardTests.cs
SimonCropp Oct 17, 2025
ad4bee0
Update GuardTests.cs
SimonCropp Oct 17, 2025
7d15b21
Update GuardTests.cs
SimonCropp Oct 17, 2025
ec0a18b
Add Number guards (#406)
SimonCropp Oct 17, 2025
4bee42c
cleanup
SimonCropp Oct 17, 2025
339af8e
Update Directory.Build.props
SimonCropp Oct 17, 2025
e1c4975
refs and cleanup
SimonCropp Oct 21, 2025
1235f58
Update TestIncludes.targets
SimonCropp Oct 25, 2025
e1b1d3c
Update Polyfill.slnx
SimonCropp Oct 25, 2025
b1a142d
refs or cleanup
SimonCropp Oct 29, 2025
a5aab5f
Update appveyor.yml
SimonCropp Nov 2, 2025
a8c1dda
Update appveyor.yml
SimonCropp Nov 2, 2025
03c3486
Update XDocumentPolyfill.cs
SimonCropp Nov 2, 2025
066b74f
Update BuildApiTest.cs
SimonCropp Nov 2, 2025
103d981
Add ZipArchiveEntryPolyfill (#409)
SimonCropp Nov 2, 2025
971d449
Update Directory.Build.props
SimonCropp Nov 2, 2025
c82b4cf
Merge branch 'sdk10Version' of https://github.com/SimonCropp/Polyfill…
SimonCropp Nov 2, 2025
deb48f7
Update Polyfill.slnx
SimonCropp Nov 2, 2025
94da858
Update PolyfillTests_TryFormatToByteSpan.cs
SimonCropp Nov 4, 2025
d8b98b4
Update PolyfillTests_TryFormatToByteSpan.cs
SimonCropp Nov 4, 2025
54c5f49
Update Directory.Packages.props
SimonCropp Nov 5, 2025
ecfb0be
Merge branch 'main' into sdk10Version
SimonCropp Nov 6, 2025
0bd7903
Update Polyfill.slnx
SimonCropp Nov 6, 2025
e18c39e
Update ConstantExpectedTests.cs
SimonCropp Nov 6, 2025
be81103
Update XElementPolyfillTests.cs
SimonCropp Nov 6, 2025
39909aa
Update XElementPolyfillTests.cs
SimonCropp Nov 6, 2025
bbcf016
Update PolyfillTests_TaskCompletionSource.cs
SimonCropp Nov 6, 2025
aee5f2a
Update PolyfillTrimmed.slnf
SimonCropp Nov 6, 2025
526b749
Update PolyfillTests_StringBuilder.cs
SimonCropp Nov 6, 2025
3938565
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
SimonCropp Nov 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apiCount.include.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
**API count: 594**
**API count: 617**
688 changes: 328 additions & 360 deletions api_list.include.md

Large diffs are not rendered by default.

6 changes: 5 additions & 1 deletion consuming.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

The default type visibility for all polyfills is `internal`. This means it can be consumed in multiple projects and types will not conflict.

## Recommended consuming pattern

The recommended general way to consume polyfill is to use the source package (`Polyfill`, not `PolyfillLib`), with all types being `internal` (default). As many projects use `InternalsVisibleTo`, this can result in conflicts. To resolve this, specify `<PolyUseEmbeddedAttribute>true</PolyUseEmbeddedAttribute>` under a `PropertyGroup`. That way, every project will have its "embedded" version of the types of Polyfill. Simply put, "embedded" means that even if `InternalsVisibleTo` is used, the "embedded" types are still not visible to the other assemblies.

Alternatively, and depending on your specific scenario, below states other ways to consume Polyfill.

## Consuming in an app

Expand All @@ -27,4 +32,3 @@ If, however, `InternalsVisibleTo` is being used to expose APIs (for example to t

* [PolyfillLib](polyfill-lib.md)
* [Polyfill and TargetFrameworks](target-frameworks.md)

5 changes: 4 additions & 1 deletion contributing.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ using System.Diagnostics.CodeAnalysis;
[AttributeUsage(
validOn: AttributeTargets.Method,
Inherited = false)]
#if PolyUseEmbeddedAttribute
[global::Microsoft.CodeAnalysis.EmbeddedAttribute]
#endif
#if PolyPublic
public
#endif
Expand All @@ -159,7 +162,7 @@ using System.Runtime.CompilerServices;
[assembly: TypeForwardedTo(typeof(ModuleInitializerAttribute))]
#endif
```
<sup><a href='/src/Polyfill/ModuleInitializerAttribute.cs#L1-L29' title='Snippet source file'>snippet source</a> | <a href='#snippet-ModuleInitializerAttribute.cs' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Polyfill/ModuleInitializerAttribute.cs#L1-L32' title='Snippet source file'>snippet source</a> | <a href='#snippet-ModuleInitializerAttribute.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down
710 changes: 339 additions & 371 deletions readme.md

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion src/.gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
*.verified.json text eol=lf working-tree-encoding=UTF-8

.editorconfig text eol=lf working-tree-encoding=UTF-8
Shared.sln.DotSettings text eol=lf working-tree-encoding=UTF-8
*.sln.DotSettings text eol=lf working-tree-encoding=UTF-8
*.slnx.DotSettings text eol=lf working-tree-encoding=UTF-8
225 changes: 164 additions & 61 deletions src/ApiBuilderTests/BuildApiTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,40 +13,19 @@ static BuildApiTest()
[Test]
public void RunWithRoslyn()
{
var types = ReadFiles();

var md = Path.Combine(solutionDirectory, "..", "api_list.include.md");
File.Delete(md);
using var writer = File.CreateText(md);
var count = 0;
count = WriteExtensions(writer, count);

var extensions = types["Polyfill"];
writer.WriteLine("### Extension methods");
writer.WriteLine();
foreach (var grouping in PublicMethods(extensions)
.GroupBy(_ => _.ParameterList.Parameters[0].Type!.ToString())
.OrderBy(_ => _.Key))
{
WriteTypeMethods(grouping.Key, writer, ref count, grouping);
}

writer.WriteLine("### Static helpers");
writer.WriteLine();
foreach (var (key, value) in types
.OrderBy(_ => _.Key)
.Where(_ => _.Key.EndsWith("Polyfill") &&
_.Key != "Polyfill"))
{
WriteTypeMethods(key, writer, ref count, value);
}

WriteHelper(types, "Guard", writer, ref count);
WriteHelper(types, "Lock", writer, ref count);
WriteHelper(types, nameof(KeyValuePair), writer, ref count);
WriteHelper("Ensure*", writer, ref count);
WriteHelper("Lock", writer, ref count);
WriteHelper(nameof(KeyValuePair), writer, ref count);
WriteType(nameof(TaskCompletionSource), writer, ref count);
WriteType(nameof(UnreachableException), writer, ref count);

count += types.Count(_ => _.Key.EndsWith("Attribute"));
count += Directory.EnumerateFiles(polyfillDir, "*Attribute.cs", SearchOption.AllDirectories).Count();
// Index and Range
count++;
//Nullability*
Expand All @@ -57,37 +36,152 @@ public void RunWithRoslyn()
File.WriteAllText(countMd, $"**API count: {count}**");
}

static IEnumerable<Method> PublicMethods(HashSet<Method> type) =>
type.Where(_ => _.IsPublic() &&
!_.IsConstructor())
.OrderBy(_ => _.Identifier.ToString());

static Dictionary<string, HashSet<Method>> ReadFiles()
static int WriteExtensions(StreamWriter writer, int count)
{
var types = new Dictionary<string, HashSet<Method>>();
var methodComparer = EqualityComparer<Method>
.Create(
(x, y) => Key(x!) == Key(y!),
_ => Key(_).GetHashCode());
foreach (var file in Directory.EnumerateFiles(polyfillDir, "*.cs", SearchOption.AllDirectories))
var files = Directory.EnumerateFiles(polyfillDir, "*Polyfill*.cs", SearchOption.AllDirectories).ToList();

var instanceFiles = files
.Where(_ => Path.GetFileNameWithoutExtension(_).StartsWith("Polyfill_"))
.ToList();

var staticFiles = files
.Where(_ =>
{
var name = Path.GetFileNameWithoutExtension(_);
return name.EndsWith("Polyfill") &&
name != "Polyfill";
})
.ToList();

var instanceMethods = ReadMethodsForFiles(instanceFiles);

var instanceTypeNames = instanceMethods
.Select(FirstParameterType);

var staticTypeNames = staticFiles
.Select(Path.GetFileNameWithoutExtension)
.Select(_ => _![..^8].ToString());

var typeNames = instanceTypeNames.Concat(staticTypeNames)
.Distinct()
.ToList();

writer.WriteLine("### Extension methods");
writer.WriteLine();

foreach (var name in typeNames.Order())
{
foreach (var type in Identifiers.ReadTypesForFile(file))
var instanceMethodsForType = instanceMethods
.Where(_ => FirstParameterType(_) == name)
.ToList();
writer.WriteLine($"#### {name}");
writer.WriteLine();
if (instanceMethodsForType.Count != 0)
{
foreach (var method in instanceMethodsForType.OrderBy(Key))
{
count++;
WriteSignature(method, writer);
}
}

var staticExtension = staticFiles
.SingleOrDefault(_ => Path.GetFileNameWithoutExtension(_)[..^8].ToString() == name);
if (staticExtension != null)
{
var identifier = type.Identifier.Text;
if (!types.TryGetValue(identifier, out var methods))
foreach (var method in ReadMethodsForFiles([staticExtension]).OrderBy(Key))
{
methods = new(methodComparer);
types.Add(identifier, methods);
count++;
WriteSignature(method, writer);
}

foreach (var method in type.PublicMethods())
foreach (var property in ReadPropertiesForFiles([staticExtension]))
{
methods.Add(method);
count++;
WriteSignature(property, writer);
}
}

writer.WriteLine();
writer.WriteLine();
}

return count;
}

static Dictionary<string, string> langwordToType = new()
{
["bool"] = "Boolean",
["byte"] = "Byte",
["sbyte"] = "SByte",
["char"] = "Char",
["decimal"] = "Decimal",
["double"] = "Double",
["float"] = "Single",
["int"] = "Int32",
["uint"] = "UInt32",
["long"] = "Int64",
["ulong"] = "UInt64",
["object"] = "Object",
["short"] = "Int16",
["ushort"] = "UInt16",
["string"] = "String"
};

static string FirstParameterType(Method method)
{
var type = method.ParameterList.Parameters[0].Type!.ToString();
return langwordToType.GetValueOrDefault(type, type);
}

static List<Method> ReadMethodsForFiles(string pattern)
{
var files = Directory.EnumerateFiles(polyfillDir, $"{pattern}.cs", SearchOption.AllDirectories);
return ReadMethodsForFiles(files);
}

private static List<Method> ReadMethodsForFiles(IEnumerable<string> files)
{
var types = files
.SelectMany(Identifiers.ReadTypesForFile)
.ToList();

var distinctTypes = types.Select(_ => _.Identifier.Text).Distinct().ToList();
if (distinctTypes.Count > 1)
{
throw new(string.Join(", ", distinctTypes));
}

return types
.SelectMany(_ => _.PublicMethods())
.DistinctBy(Key)
.OrderBy(Key)
.ToList();
}

static List<Property> ReadPropertiesForFiles(string pattern)
{
var files = Directory.EnumerateFiles(polyfillDir, $"{pattern}.cs", SearchOption.AllDirectories);
return ReadPropertiesForFiles(files);
}

static List<Property> ReadPropertiesForFiles(IEnumerable<string> files)
{
var types = files
.SelectMany(Identifiers.ReadTypesForFile)
.ToList();

var distinctTypes = types.DistinctBy(_ => _.Identifier.Text).ToList();
if (distinctTypes.Count > 1)
{
throw new(string.Join(", ", distinctTypes));
}

return types;
return types
.SelectMany(_ => _.PublicProperties())
.DistinctBy(_ => _.Identifier.Text)
.OrderBy(_ => _.Identifier.Text)
.ToList();
}

static void WriteType(string name, StreamWriter writer, ref int count)
Expand All @@ -100,12 +194,8 @@ static void WriteType(string name, StreamWriter writer, ref int count)
count++;
}

static void WriteHelper(Dictionary<string, HashSet<Method>> types, string name, StreamWriter writer, ref int count)
{
var methods = types[name];

WriteTypeMethods(name, writer, ref count, methods.OrderBy(Key));
}
static void WriteHelper(string name, StreamWriter writer, ref int count) =>
WriteTypeMethods(name.Trim('*'), writer, ref count, ReadMethodsForFiles(name));

static void WriteTypeMethods(string name, StreamWriter writer, ref int count, IEnumerable<Method> methods)
{
Expand Down Expand Up @@ -144,6 +234,20 @@ static void WriteSignature(Method method, StreamWriter writer)
}
}

static void WriteSignature(Property method, StreamWriter writer)
{
var signature = new StringBuilder(method.Identifier.Text);

if (method.TryGetReference(out var reference))
{
writer.WriteLine($" * `{signature}` [reference]({reference})");
}
else
{
writer.WriteLine($" * `{signature}`");
}
}

static string Key(Method method) =>
$"{method.Identifier.Text}{BuildTypeArgs(method)}({BuildParameters(method, false)})";

Expand All @@ -160,17 +264,16 @@ static string BuildTypeArgs(Method method)

static string BuildParameters(Method method, bool skipThisModified)
{
List<Parameter> parameters;
var parameters = method
.ParameterList
.Parameters
.ToList();

if (skipThisModified)
{
parameters = method.ParameterList
.Parameters
.Where(_ => !_.IsThis()).ToList();
}
else
{
parameters = method.ParameterList
.Parameters.ToList();
parameters = parameters
.Where(_ => !_.IsThis())
.ToList();
}

if (parameters.Count > 0)
Expand Down
2 changes: 1 addition & 1 deletion src/ApiBuilderTests/Identifiers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static IEnumerable<Type> ReadTypesForFile(string file)
[
"FeatureMemory",
"FeatureRuntimeInformation",
"PolyGuard",
"PolyEnsure",
"PolyPublic",
"FeatureHttp",
"PolyNullability",
Expand Down
4 changes: 2 additions & 2 deletions src/ApiBuilderTests/LinkReader.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
public static class LinkReader
{
public static bool TryGetReference(this Method method, [NotNullWhen(true)] out string? reference)
public static bool TryGetReference(this Member member, [NotNullWhen(true)] out string? reference)
{
var syntaxTrivia = method.GetLeadingTrivia();
var syntaxTrivia = member.GetLeadingTrivia();
foreach (var trivia in syntaxTrivia)
{
if (!trivia.IsKind(SyntaxKind.SingleLineCommentTrivia))
Expand Down
7 changes: 7 additions & 0 deletions src/ApiBuilderTests/RoslynExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@ public static IEnumerable<Method> PublicMethods(this Type type) =>
_.IsPublic() &&
!_.IsConstructor());

public static IEnumerable<Property> PublicProperties(this Type type) =>
type
.DescendantNodes()
.OfType<Property>()
.Where(_ => _.Parent == type &&
_.IsPublic());

public static bool IsConstructor(this Method method)
{
if (method.Parent is Type type)
Expand Down
Loading