Skip to content

Commit 9b61368

Browse files
authored
multi-partials (#444)
1 parent 2dd8d8d commit 9b61368

File tree

10 files changed

+75
-57
lines changed

10 files changed

+75
-57
lines changed

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jobs:
2323
- name: Setup .NET 5.0
2424
uses: actions/setup-dotnet@v1
2525
with:
26-
dotnet-version: 5.0.100
26+
dotnet-version: 5.0.201
2727
- name: Setup .NET Core 3.1
2828
uses: actions/setup-dotnet@v1
2929
with:

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
- name: Setup .NET Core
1616
uses: actions/setup-dotnet@v1
1717
with:
18-
dotnet-version: 5.0.100
18+
dotnet-version: 5.0.201
1919
- name: Setup NUKE
2020
run: dotnet tool install Nuke.GlobalTool --global
2121
- name: Push to NuGet

global.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "5.0.100",
4-
"rollForward": "latestFeature"
3+
"version": "5.0.201",
4+
"rollForward": "major"
55
}
66
}

src/Core/Silk.NET.SilkTouch/NativeApiGenerator.cs

Lines changed: 36 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,14 @@ public void Initialize(GeneratorInitializationContext context)
2929

3030
public void Execute(GeneratorExecutionContext context)
3131
{
32-
MarshalBuilder marshalBuilder;
33-
3432
if (!context.Compilation.ReferencedAssemblyNames.Any
3533
(ai => ai.Name.Equals("Silk.NET.Core", StringComparison.OrdinalIgnoreCase)))
3634
{
3735
context.ReportDiagnostic(Diagnostic.Create(Diagnostics.SilkNetCoreMissing, Location.None));
3836
return;
3937
}
4038

41-
if (!(context.SyntaxReceiver is SyntaxReceiver receiver))
39+
if (context.SyntaxContextReceiver is not SyntaxReceiver receiver)
4240
return;
4341

4442
var nativeApiAttribute = context.Compilation.GetTypeByMetadataName
@@ -62,7 +60,7 @@ public void Execute(GeneratorExecutionContext context)
6260
(string) array[1].Value! /* first return is just the lib target */, new PInvokeNativeContextOverride());
6361

6462

65-
marshalBuilder = new MarshalBuilder();
63+
var marshalBuilder = new MarshalBuilder();
6664

6765
// begin | end
6866
marshalBuilder.Use(Middlewares.InjectMiddleware);
@@ -79,22 +77,23 @@ public void Execute(GeneratorExecutionContext context)
7977
// pre load | post load
8078

8179
List<ITypeSymbol> processedSymbols = new List<ITypeSymbol>();
82-
8380

84-
foreach (var receiverClassDeclaration in receiver.ClassDeclarations)
81+
82+
foreach (var group in receiver.ClassDeclarations.Select(x => (x.Item1, x.Item2, x.Item2.GetDeclaredSymbol(x.Item1)))
83+
.GroupBy(x => x.Item3, SymbolEqualityComparer.Default))
8584
{
8685
try
8786
{
8887
var s = ProcessClassDeclaration
8988
(
90-
receiverClassDeclaration, context, nativeApiAttribute, marshalBuilder, ref processedSymbols,
91-
excludeFromOverrideAttribute
89+
group.Select(x => (x.Item1, x.Item2)), context, nativeApiAttribute, marshalBuilder, ref processedSymbols,
90+
excludeFromOverrideAttribute, (INamedTypeSymbol)group.Key
9291
);
9392

9493
if (s is null) continue;
9594

9695
var name =
97-
$"{receiverClassDeclaration.Identifier.Text}.{receiverClassDeclaration.GetHashCode()}.gen";
96+
$"{group.Key.Name}.{Guid.NewGuid()}.gen";
9897
context.AddSource(name, SourceText.From(s, Encoding.UTF8));
9998
// File.WriteAllText(@"C:\SILK.NET\src\Lab\" + name, s);
10099
}
@@ -103,48 +102,47 @@ public void Execute(GeneratorExecutionContext context)
103102
context.ReportDiagnostic
104103
(
105104
Diagnostic.Create
106-
(Diagnostics.ProcessClassFailure, receiverClassDeclaration.GetLocation(), ex.ToString())
105+
(Diagnostics.ProcessClassFailure, group.First().Item1.GetLocation(), ex.ToString())
107106
);
108107
}
109108
}
110109
}
111110

112111
private string ProcessClassDeclaration
113112
(
114-
ClassDeclarationSyntax classDeclaration,
113+
IEnumerable<(ClassDeclarationSyntax, SemanticModel)> classDeclarations,
115114
GeneratorExecutionContext sourceContext,
116115
INamedTypeSymbol nativeApiAttributeSymbol,
117116
MarshalBuilder rootMarshalBuilder,
118117
ref List<ITypeSymbol> processedSymbols,
119-
INamedTypeSymbol excludeFromOverrideAttribute
118+
INamedTypeSymbol excludeFromOverrideAttribute,
119+
INamedTypeSymbol sharedClassSymbol
120120
)
121121
{
122122
var stopwatch = Stopwatch.StartNew();
123123
var compilation = sourceContext.Compilation;
124-
if (!classDeclaration.Modifiers.Any(x => x.IsKind(SyntaxKind.PartialKeyword)))
124+
if (!classDeclarations.First().Item1.Modifiers.Any(x => x.IsKind(SyntaxKind.PartialKeyword)))
125125
return null;
126126

127-
if (!classDeclaration.Parent.IsKind(SyntaxKind.NamespaceDeclaration))
127+
if (!classDeclarations.All(x => x.Item1.Parent.IsKind(SyntaxKind.NamespaceDeclaration)))
128128
return null;
129-
var namespaceDeclaration = (NamespaceDeclarationSyntax) classDeclaration.Parent;
129+
130+
var namespaceDeclaration = (NamespaceDeclarationSyntax) classDeclarations.First().Item1.Parent;
130131

131132
if (!namespaceDeclaration.Parent.IsKind(SyntaxKind.CompilationUnit))
132133
return null;
133134

134135
var compilationUnit = (CompilationUnitSyntax) namespaceDeclaration.Parent;
135136

136-
var classSymbol = ModelExtensions.GetDeclaredSymbol
137-
(compilation.GetSemanticModel(classDeclaration.SyntaxTree), classDeclaration) as ITypeSymbol;
138-
139137
if (!compilation.HasImplicitConversion
140-
(classSymbol, compilation.GetTypeByMetadataName("Silk.NET.Core.Native.NativeApiContainer")))
138+
(sharedClassSymbol, compilation.GetTypeByMetadataName("Silk.NET.Core.Native.NativeApiContainer")))
141139
return null;
142140

143-
var classIsSealed = classDeclaration.Modifiers.Any(x => x.Text == "sealed");
141+
var classIsSealed = classDeclarations.First().Item1.Modifiers.Any(x => x.Text == "sealed");
144142
var generateSeal = false;
145143

146144
if (sourceContext.AnalyzerConfigOptions.GetOptions
147-
(classDeclaration.SyntaxTree)
145+
(classDeclarations.First().Item1.SyntaxTree)
148146
.TryGetValue("silk_touch_sealed_vtable_creation", out var generateSealstr))
149147
{
150148
if (bool.TryParse(generateSealstr, out var v))
@@ -155,7 +153,7 @@ INamedTypeSymbol excludeFromOverrideAttribute
155153
var generateVTable = false;
156154

157155
if (sourceContext.AnalyzerConfigOptions.GetOptions
158-
(classDeclaration.SyntaxTree)
156+
(classDeclarations.First().Item1.SyntaxTree)
159157
.TryGetValue("silk_touch_vtable_generate", out var genvtablestr))
160158
{
161159
if (bool.TryParse(genvtablestr, out var v))
@@ -165,7 +163,7 @@ INamedTypeSymbol excludeFromOverrideAttribute
165163
var preloadVTable = false;
166164

167165
if (sourceContext.AnalyzerConfigOptions.GetOptions
168-
(classDeclaration.SyntaxTree)
166+
(classDeclarations.First().Item1.SyntaxTree)
169167
.TryGetValue("silk_touch_vtable_preload", out var vtablepreloadstr))
170168
{
171169
if (bool.TryParse(vtablepreloadstr, out var v))
@@ -175,14 +173,14 @@ INamedTypeSymbol excludeFromOverrideAttribute
175173
var emitAssert = false;
176174

177175
if (sourceContext.AnalyzerConfigOptions.GetOptions
178-
(classDeclaration.SyntaxTree)
176+
(classDeclarations.First().Item1.SyntaxTree)
179177
.TryGetValue("silk_touch_vtable_tree_emit_assert", out var emitAssertStr))
180178
{
181179
if (bool.TryParse(emitAssertStr, out var v))
182180
emitAssert = v;
183181
}
184182

185-
var classAttribute = classSymbol.GetAttributes()
183+
var classAttribute = sharedClassSymbol.GetAttributes()
186184
.FirstOrDefault(x => SymbolEqualityComparer.Default.Equals(x.AttributeClass, nativeApiAttributeSymbol));
187185

188186
var classNativeApiAttribute = classAttribute == default
@@ -198,18 +196,18 @@ INamedTypeSymbol excludeFromOverrideAttribute
198196
Dictionary<int, string> entryPoints = new Dictionary<int, string>();
199197
var processedEntrypoints = new List<EntryPoint>();
200198
foreach (var (declaration, symbol, entryPoint, callingConvention) in from declaration in
201-
from member in classDeclaration.Members
202-
where member.IsKind(SyntaxKind.MethodDeclaration)
203-
select (MethodDeclarationSyntax) member
204-
let symbol = compilation.GetSemanticModel(declaration.SyntaxTree).GetDeclaredSymbol(declaration)
199+
from member in classDeclarations.SelectMany(x => x.Item1.Members.Select(x2 => (x2, x.Item2)))
200+
where member.x2.IsKind(SyntaxKind.MethodDeclaration)
201+
select ((MethodDeclarationSyntax) member.x2, member.Item2)
202+
let symbol = declaration.Item2.GetDeclaredSymbol(declaration.Item1)
205203
where symbol is not null
206204
let attribute = ToNativeApiAttribute
207205
(
208206
symbol.GetAttributes()
209207
.FirstOrDefault
210208
(att => SymbolEqualityComparer.Default.Equals(att.AttributeClass, nativeApiAttributeSymbol))
211209
)
212-
where declaration.Modifiers.Any
210+
where declaration.Item1.Modifiers.Any
213211
(modifier => modifier.IsKind(SyntaxKind.PartialKeyword)) && symbol.PartialImplementationPart is null
214212
let entryPoint = NativeApiAttribute.GetEntryPoint(attribute, classNativeApiAttribute, symbol.Name)
215213
let callingConvention = NativeApiAttribute.GetCallingConvention(attribute, classNativeApiAttribute)
@@ -220,14 +218,14 @@ where declaration.Modifiers.Any
220218
ProcessMethod
221219
(
222220
sourceContext, rootMarshalBuilder, callingConvention, entryPoints, entryPoint, classIsSealed,
223-
generateSeal, generateVTable, slot, compilation, symbol, declaration, newMembers,
221+
generateSeal, generateVTable, slot, compilation, symbol, declaration.Item1, newMembers,
224222
ref gcCount, processedEntrypoints, generatedVTableName
225223
);
226224
}
227225

228226
if (slotCount > 0)
229227
{
230-
if (!processedSymbols.Contains(classSymbol))
228+
if (!processedSymbols.Contains(sharedClassSymbol))
231229
{
232230
newMembers.Add
233231
(
@@ -283,7 +281,7 @@ where declaration.Modifiers.Any
283281
);
284282
}
285283

286-
processedSymbols.Add(classSymbol);
284+
processedSymbols.Add(sharedClassSymbol);
287285
}
288286

289287
if (newMembers.Count == 0)
@@ -330,21 +328,21 @@ where declaration.Modifiers.Any
330328
);
331329
}
332330

333-
ProcessNativeContextOverrides(processedEntrypoints.ToArray(), ref newMembers, classSymbol, classDeclaration, sourceContext.Compilation, excludeFromOverrideAttribute);
334-
331+
ProcessNativeContextOverrides(processedEntrypoints.ToArray(), ref newMembers, sharedClassSymbol, excludeFromOverrideAttribute);
332+
335333
var newNamespace = namespaceDeclaration.WithMembers
336334
(
337335
List
338336
(
339337
new MemberDeclarationSyntax[]
340338
{
341-
classDeclaration.WithMembers
339+
classDeclarations.First().Item1.WithMembers
342340
(List(newMembers))
343341
.WithAttributeLists(List<AttributeListSyntax>())
344342
}
345343
)
346344
)
347-
.WithUsings(compilationUnit.Usings);
345+
.WithUsings(compilationUnit.Usings.Add(UsingDirective(IdentifierName("Silk.NET.Core.Native"))).Add(UsingDirective(IdentifierName("Silk.NET.Core.Contexts"))));
348346

349347
var result = newNamespace.NormalizeWhitespace().ToFullString();
350348
stopwatch.Stop();
@@ -358,7 +356,7 @@ where declaration.Modifiers.Any
358356
(
359357
Diagnostic.Create
360358
(
361-
Diagnostics.BuildInfo, classDeclaration.GetLocation(), slotCount, gcCount,
359+
Diagnostics.BuildInfo, classDeclarations.First().Item1.GetLocation(), slotCount, gcCount,
362360
stopwatch.ElapsedMilliseconds + "ms"
363361
)
364362
);

src/Core/Silk.NET.SilkTouch/NativeContextOverrideGeneration.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,13 @@ public partial class NativeApiGenerator
1717
{
1818
private Dictionary<INamedTypeSymbol, Func<ImmutableArray<TypedConstant>, (int, string, INativeContextOverride)?>>
1919
_nativeContextAttributes =
20-
new Dictionary<INamedTypeSymbol, Func<ImmutableArray<TypedConstant>, (int, string, INativeContextOverride)?>>();
20+
new(SymbolEqualityComparer.Default);
2121

2222
private void ProcessNativeContextOverrides
2323
(
2424
EntryPoint[] entrypoints,
2525
ref List<MemberDeclarationSyntax> members,
2626
ITypeSymbol classSymbol,
27-
ClassDeclarationSyntax classDeclaration,
28-
Compilation compilation,
2927
INamedTypeSymbol excludeFromOverrideAttribute
3028
)
3129
{

src/Core/Silk.NET.SilkTouch/Silk.NET.SilkTouch.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
<Compile Include="..\Silk.NET.Core\Attributes\UnmanagedTypeAttribute.cs" />
1919
<Compile Include="..\Silk.NET.Core\Attributes\InjectAttribute.cs" />
2020

21-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.8.0-3.final" PrivateAssets="all" />
22-
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.0" PrivateAssets="all" />
21+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" PrivateAssets="all" />
22+
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.2" PrivateAssets="all" />
2323

2424
<!-- Package the generator in the analyzer directory of the nuget package -->
2525
<None Include="$(OutputPath)\$(AssemblyName).dll" Pack="true" PackagePath="analyzers/dotnet/cs" Visible="false" />

src/Core/Silk.NET.SilkTouch/SyntaxReceiver.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ namespace Silk.NET.SilkTouch
99
{
1010
public partial class NativeApiGenerator
1111
{
12-
public class SyntaxReceiver : ISyntaxReceiver
12+
public class SyntaxReceiver : ISyntaxContextReceiver
1313
{
14-
public List<ClassDeclarationSyntax> ClassDeclarations = new List<ClassDeclarationSyntax>();
15-
16-
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
14+
public List<(ClassDeclarationSyntax, SemanticModel)> ClassDeclarations = new();
15+
16+
public void OnVisitSyntaxNode(GeneratorSyntaxContext context)
1717
{
18-
if (syntaxNode is ClassDeclarationSyntax cds) ClassDeclarations.Add(cds);
18+
if (context.Node is ClassDeclarationSyntax cds)
19+
{
20+
ClassDeclarations.Add((cds, context.SemanticModel));
21+
}
1922
}
2023
}
2124
}

src/Lab/TestLib/Class1.cs renamed to src/Lab/TestLib/TestClass2-1.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using Silk.NET.Core.Attributes;
77
using Silk.NET.Core.Contexts;
88
using Silk.NET.Core.Native;
9-
using UnmanagedType = Silk.NET.Core.Native.UnmanagedType;
109

1110
namespace TestLib
1211
{
@@ -25,10 +24,6 @@ public partial class TestClass2 : NativeApiContainer
2524
[NativeApi(EntryPoint = "MessageBoxA")]
2625
public partial int MessageBox(nint hwnd, string text, string caption, uint buttons);
2726

28-
[NativeApi(EntryPoint = "MessageBoxA")]
29-
public partial int MessageBox(nint hwnd, string text, string caption,
30-
[UnmanagedType(UnmanagedType.U4)] bool buttons);
31-
3227
[NativeApi(EntryPoint = "MessageBoxA")]
3328
public partial int MessageBox(nint hwnd, string text, Span<char> caption, uint buttons);
3429

src/Lab/TestLib/TestClass2-2.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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 Silk.NET.Core.Attributes;
5+
using Silk.NET.Core.Native;
6+
7+
namespace TestLib
8+
{
9+
partial class TestClass2
10+
{
11+
[NativeApi(EntryPoint = "MessageBoxA")]
12+
public partial int MessageBox(nint hwnd, string text, string caption,
13+
[UnmanagedType(UnmanagedType.U4)] bool buttons);
14+
}
15+
}

src/Lab/TestLib/TestClass2-3.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
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+
namespace TestLib
5+
{
6+
partial class TestClass2
7+
{
8+
}
9+
}

0 commit comments

Comments
 (0)