Skip to content

Commit 9a67ca2

Browse files
committed
feat: add support for c# 14 syntax
1 parent 8052ced commit 9a67ca2

File tree

12 files changed

+192
-14
lines changed

12 files changed

+192
-14
lines changed

samples/csharp/docfx.json

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,39 @@
11
{
22
"metadata": [
3+
{
4+
"src": [
5+
"src/*.csproj"
6+
],
7+
"outputFormat": "mref",
8+
"memberLayout": "separatePages",
9+
"output": "obj/api"
10+
},
11+
{
12+
"src": [
13+
"src/*.csproj"
14+
],
15+
"outputFormat": "apiPage",
16+
"memberLayout": "separatePages",
17+
"output": "obj/apipage"
18+
},
319
{
420
"src": [
521
"src/*.csproj"
622
],
7-
"dest": "api"
8-
}
23+
"outputFormat": "markdown",
24+
"memberLayout": "separatePages",
25+
"output": "obj/md"
26+
},
927
],
1028
"build": {
1129
"content": [
12-
{
13-
"files": [
14-
"api/**/*.yml",
15-
"toc.yml"
16-
]
17-
}
30+
{ "files": [ "*.{md,yml}" ]},
31+
{ "files": [ "**/*.yml" ], "src": "obj/api", "dest": "api" },
32+
{ "files": [ "**/*.yml" ], "src": "obj/apipage", "dest": "apipage" },
33+
{ "files": [ "**/*.{md,yml}" ], "src": "obj/md", "dest": "md" },
1834
],
19-
"dest": "_site",
35+
"output": "_site",
36+
"template": ["default", "modern"],
2037
"exportViewModel": true
2138
}
22-
}
39+
}

samples/csharp/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
---
2+
_layout: landing
3+
---

samples/csharp/src/CSharp13.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
namespace CSharp13;
2+
3+
// https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#allows-ref-struct
4+
public class AllowRefStruct<T>
5+
where T : allows ref struct
6+
{
7+
// Use T as a ref struct:
8+
public void Method(scoped T p)
9+
{
10+
// The parameter p must follow ref safety rules
11+
}
12+
}

samples/csharp/src/CSharp14.cs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
namespace CSharp14;
2+
3+
// https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-14#the-field-keyword
4+
public class FieldBackedPropertySample
5+
{
6+
public int FieldBackedProperty
7+
{
8+
get;
9+
set => field = value;
10+
}
11+
}
12+
13+
public class SampleClass
14+
{
15+
public required string Value { get; init; }
16+
}
17+
18+
public static class SampleClassExtensions
19+
{
20+
// Extension block
21+
extension(SampleClass sample)
22+
{
23+
// Extension property:
24+
public string ExtensionProperty => sample.Value;
25+
26+
// Extension method:
27+
public void ExtensionMethod()
28+
{
29+
}
30+
}
31+
32+
// Extension block for static type
33+
extension(SampleClass)
34+
{
35+
// static extension method:
36+
public static void StaticExtensionMethod()
37+
{
38+
}
39+
40+
// static extension property:
41+
public static int StaticExtensionProperty => default;
42+
43+
// static user defined operator:
44+
public static SampleClass operator +(SampleClass value1, SampleClass value2)
45+
=> new() { Value = value1.Value + value2.Value };
46+
}
47+
}
48+
49+
public class UserDefinedCompoundAssignmentOperatorsSample
50+
{
51+
public int? Value { get; set; }
52+
53+
public override string? ToString() => Value?.ToString();
54+
55+
public void operator ++() { Value += 1; }
56+
57+
public void operator --() { Value -= 1; }
58+
59+
public void operator +=(UserDefinedCompoundAssignmentOperatorsSample c) { Value += c?.Value; }
60+
61+
public void operator -=(UserDefinedCompoundAssignmentOperatorsSample c) { Value -= c?.Value; }
62+
63+
public void operator *=(UserDefinedCompoundAssignmentOperatorsSample c) { Value *= c?.Value; }
64+
65+
public void operator /=(UserDefinedCompoundAssignmentOperatorsSample c) { Value /= c?.Value; }
66+
67+
public void operator %=(UserDefinedCompoundAssignmentOperatorsSample c) { Value %= c?.Value; }
68+
69+
public void operator &=(UserDefinedCompoundAssignmentOperatorsSample c) { Value &= c?.Value; }
70+
71+
public void operator |=(UserDefinedCompoundAssignmentOperatorsSample c) { Value |= c?.Value; }
72+
73+
public void operator ^=(UserDefinedCompoundAssignmentOperatorsSample c) { Value ^= c?.Value; }
74+
75+
public void operator <<=(int shift) { Value <<= shift; }
76+
77+
public void operator >>=(int shift) { Value >>= shift; }
78+
}

samples/csharp/toc.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
- name: API Documentation
2+
items:
3+
- name: .NET API
4+
href: obj/api/
5+
- name: .NET API (apipage)
6+
href: obj/apipage/
7+
- name: .NET API (markdown)
8+
href: obj/md/

src/Docfx.Dotnet/DotnetApiCatalog.Toc.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ enum TocNodeType
2626
Method,
2727
Event,
2828
Operator,
29+
Extension,
2930
}
3031

3132
class TocNode
@@ -135,6 +136,12 @@ IEnumerable<TocNode> CreateNamedTypeToc(INamedTypeSymbol type)
135136
{
136137
var idExists = true;
137138
var id = VisitorHelper.PathFriendlyId(VisitorHelper.GetId(symbol));
139+
140+
// TODO: Handle C# 14 Extension Members. It'll be shown on `static class` and target type of extension.
141+
// Currently Extension symbol is skipped.
142+
if (type.TypeKind == TypeKind.Extension)
143+
yield break;
144+
138145
if (!tocNodes.TryGetValue(id, out var node))
139146
{
140147
idExists = false;

src/Docfx.Dotnet/ManagedReference/Models/MemberType.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,6 @@ public enum MemberType
2222
Operator,
2323
Container,
2424
AttachedEvent,
25-
AttachedProperty
25+
AttachedProperty,
26+
Extension,
2627
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using Docfx.DataContracts.ManagedReference;
5+
6+
#nullable enable
7+
8+
namespace Docfx.Dotnet;
9+
10+
internal class ResolveExtensionMember : IResolverPipeline
11+
{
12+
public void Run(MetadataModel yaml, ResolverContext context)
13+
{
14+
// Remove extension from root members.
15+
yaml.Members.RemoveAll(x => x.Type == MemberType.Extension);
16+
17+
// Remove extension from TocYamlViewModel items.
18+
ProcessItem(yaml.TocYamlViewModel);
19+
}
20+
21+
private static void ProcessItem(MetadataItem metadataItem)
22+
{
23+
if (metadataItem.IsInvalid || metadataItem.Items == null)
24+
return;
25+
26+
metadataItem.Items.RemoveAll(x => x.Type == MemberType.Extension);
27+
28+
foreach (var item in metadataItem.Items)
29+
ProcessItem(item);
30+
}
31+
}

src/Docfx.Dotnet/ManagedReference/Resolvers/YamlMetadataResolver.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ internal static class YamlMetadataResolver
1616
new NormalizeSyntax(),
1717
new BuildMembers(),
1818
new SetDerivedClass(),
19+
new ResolveExtensionMember(),
1920
new BuildToc()
2021
];
2122

src/Docfx.Dotnet/ManagedReference/Visitors/SymbolVisitorAdapter.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,15 @@ s is not INamedTypeSymbol
197197
}
198198
}
199199

200-
AddReference(symbol);
200+
if (symbol.IsExtension)
201+
{
202+
// Currently extension symbol is skipped and reference is not added.
203+
// TODO: Handle C# 14 Extension Member definition.
204+
}
205+
else
206+
{
207+
AddReference(symbol);
208+
}
201209

202210
item.Attributes = GetAttributeInfo(symbol.GetAttributes());
203211

0 commit comments

Comments
 (0)