com.wallstop-studios.dxmessaging 3.0.1 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +211 -2
- package/Editor/Analyzers/DxMessagingConsoleHarvester.cs +69 -62
- package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +3 -3
- package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +3 -3
- package/Editor/Analyzers/System.Collections.Immutable.dll.meta +3 -3
- package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +3 -3
- package/Editor/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +3 -3
- package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll.meta +15 -2
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +2 -2
- package/Editor/AssemblyInfo.cs.meta +9 -1
- package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +24 -15
- package/Editor/CustomEditors/MessagingComponentEditor.cs.meta +9 -1
- package/Editor/DxMessagingEditorIdle.cs +62 -0
- package/{Runtime/Core/Internal/TypedDispatchLinkIndex.cs.meta → Editor/DxMessagingEditorIdle.cs.meta} +1 -1
- package/Editor/DxMessagingEditorInitializer.cs +112 -15
- package/Editor/DxMessagingEditorInitializer.cs.meta +9 -1
- package/Editor/DxMessagingEditorLog.cs +32 -0
- package/Editor/DxMessagingEditorLog.cs.meta +11 -0
- package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs +135 -12
- package/Editor/Settings/DxMessagingSettings.cs +92 -31
- package/Editor/Settings/DxMessagingSettings.cs.meta +9 -1
- package/Editor/Settings/DxMessagingSettingsProvider.cs.meta +9 -1
- package/Editor/SetupCscRsp.cs +339 -173
- package/Editor/SetupCscRsp.cs.meta +9 -1
- package/Editor/Testing/MessagingComponentEditorHarness.cs +1 -1
- package/Editor/Testing/MessagingComponentEditorHarness.cs.meta +9 -1
- package/README.md +17 -18
- package/Runtime/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Core/Attributes/DxAutoConstructorAttribute.cs.meta +9 -1
- package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +9 -1
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs +2 -4
- package/Runtime/Core/Attributes/DxOptionalParameterAttribute.cs.meta +9 -1
- package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +9 -1
- package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +9 -1
- package/Runtime/Core/Attributes/Il2CppSetOptionAttribute.cs +56 -0
- package/Runtime/Core/Attributes/Il2CppSetOptionAttribute.cs.meta +11 -0
- package/Runtime/Core/DataStructure/CyclicBuffer.cs +44 -26
- package/Runtime/Core/DataStructure/CyclicBuffer.cs.meta +9 -1
- package/Runtime/Core/Diagnostics/MessageEmissionData.cs.meta +9 -1
- package/Runtime/Core/Diagnostics/MessageRegistrationData.cs.meta +9 -1
- package/Runtime/Core/Diagnostics/MessageRegistrationType.cs.meta +9 -1
- package/Runtime/Core/Extensions/EnumExtensions.cs +6 -5
- package/Runtime/Core/Extensions/EnumExtensions.cs.meta +9 -1
- package/Runtime/Core/Extensions/IListExtensions.cs.meta +9 -1
- package/Runtime/Core/Extensions/MessageExtensions.cs +0 -60
- package/Runtime/Core/Helper/MessageCache.cs.meta +9 -1
- package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +9 -1
- package/Runtime/Core/InstanceId.cs +25 -1
- package/Runtime/Core/Internal/DxUnsafe.cs +60 -0
- package/Runtime/Core/Internal/DxUnsafe.cs.meta +11 -0
- package/Runtime/Core/Internal/FlatDispatch.cs +198 -0
- package/Runtime/Core/Internal/FlatDispatch.cs.meta +11 -0
- package/Runtime/Core/Internal/TypedSlots.cs +5 -21
- package/Runtime/Core/MessageBus/IMessageBus.cs +12 -12
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +1 -0
- package/Runtime/Core/MessageBus/Internal/BusSlots.cs +7 -6
- package/Runtime/Core/MessageBus/MessageBus.cs +2313 -2936
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +187 -14
- package/Runtime/Core/MessageHandler.cs +1023 -1143
- package/Runtime/Core/MessageRegistrationToken.cs +425 -47
- package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +9 -1
- package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +9 -1
- package/Runtime/Core/Messages/StringMessage.cs.meta +9 -1
- package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Unity/MessageAwareComponent.cs +46 -1
- package/Runtime/Unity/MessagingComponent.cs +43 -10
- package/Runtime/WallstopStudios.DxMessaging.asmdef +1 -1
- package/Samples~/DI/README.md +7 -7
- package/SourceGenerators/Directory.Build.props +50 -3
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +96 -63
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs +745 -87
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs.meta +9 -1
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +39 -46
- package/SourceGenerators/global.json +7 -0
- package/SourceGenerators/global.json.meta +7 -0
- package/package.json +27 -40
- package/Runtime/Core/Internal/TypedDispatchLinkIndex.cs +0 -51
package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxMessageIdGenerator.cs
CHANGED
|
@@ -11,8 +11,8 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
11
11
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
12
12
|
using Microsoft.CodeAnalysis.Text;
|
|
13
13
|
|
|
14
|
-
[Generator
|
|
15
|
-
public sealed class DxMessageIdGenerator :
|
|
14
|
+
[Generator]
|
|
15
|
+
public sealed class DxMessageIdGenerator : ISourceGenerator
|
|
16
16
|
{
|
|
17
17
|
private static readonly DiagnosticDescriptor NonPartialContainerDiagnostic = new(
|
|
18
18
|
id: "DXMSG003",
|
|
@@ -67,62 +67,137 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
67
67
|
INamedTypeSymbol TypeSymbol,
|
|
68
68
|
TypeDeclarationSyntax DeclarationSyntax,
|
|
69
69
|
string TargetInterfaceFullName,
|
|
70
|
+
bool RegistersUntargetedAotBridge,
|
|
71
|
+
bool RegistersTargetedAotBridge,
|
|
72
|
+
bool RegistersBroadcastAotBridge,
|
|
70
73
|
bool HasConflictingMessageAttributes
|
|
71
74
|
);
|
|
72
75
|
|
|
76
|
+
private record struct AotRegistrarInfo(
|
|
77
|
+
INamedTypeSymbol TypeSymbol,
|
|
78
|
+
bool RegistersUntargetedAotBridge,
|
|
79
|
+
bool RegistersTargetedAotBridge,
|
|
80
|
+
bool RegistersBroadcastAotBridge,
|
|
81
|
+
bool HasMessageAttribute
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
private record struct AotRegistrarSourceInfo(
|
|
85
|
+
AotRegistrarInfo Info,
|
|
86
|
+
string TypeName,
|
|
87
|
+
string Suffix
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
private readonly struct SemanticTargetInfo
|
|
91
|
+
{
|
|
92
|
+
public SemanticTargetInfo(
|
|
93
|
+
MessageToGenerateInfo? messageToGenerate,
|
|
94
|
+
AotRegistrarInfo? aotRegistrar
|
|
95
|
+
)
|
|
96
|
+
{
|
|
97
|
+
MessageToGenerate = messageToGenerate;
|
|
98
|
+
AotRegistrar = aotRegistrar;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
public MessageToGenerateInfo? MessageToGenerate { get; }
|
|
102
|
+
public AotRegistrarInfo? AotRegistrar { get; }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
private enum AotBridgeKind
|
|
106
|
+
{
|
|
107
|
+
Untargeted,
|
|
108
|
+
Targeted,
|
|
109
|
+
Broadcast,
|
|
110
|
+
}
|
|
111
|
+
|
|
73
112
|
/// <summary>
|
|
74
|
-
/// Configures
|
|
113
|
+
/// Configures syntax collection for deterministic message identifier generation.
|
|
75
114
|
/// </summary>
|
|
76
115
|
/// <param name="context">Initialization context provided by Roslyn.</param>
|
|
77
|
-
public void Initialize(
|
|
116
|
+
public void Initialize(GeneratorInitializationContext context)
|
|
117
|
+
{
|
|
118
|
+
context.RegisterForSyntaxNotifications(static () => new TypeSyntaxReceiver());
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public void Execute(GeneratorExecutionContext context)
|
|
78
122
|
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
123
|
+
if (context.SyntaxReceiver is not TypeSyntaxReceiver receiver)
|
|
124
|
+
{
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
List<MessageToGenerateInfo> typesToGenerate = new();
|
|
129
|
+
List<AotRegistrarInfo> aotTypes = new();
|
|
130
|
+
foreach (TypeDeclarationSyntax typeDeclarationSyntax in receiver.Candidates)
|
|
131
|
+
{
|
|
132
|
+
SemanticTargetInfo? targetInfo = GetSemanticTarget(
|
|
133
|
+
typeDeclarationSyntax,
|
|
134
|
+
context.Compilation,
|
|
135
|
+
context.CancellationToken
|
|
84
136
|
);
|
|
137
|
+
if (!targetInfo.HasValue)
|
|
138
|
+
{
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
85
141
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
142
|
+
if (targetInfo.Value.MessageToGenerate.HasValue)
|
|
143
|
+
{
|
|
144
|
+
typesToGenerate.Add(targetInfo.Value.MessageToGenerate.Value);
|
|
145
|
+
}
|
|
146
|
+
if (targetInfo.Value.AotRegistrar.HasValue)
|
|
147
|
+
{
|
|
148
|
+
aotTypes.Add(targetInfo.Value.AotRegistrar.Value);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
94
151
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
.Where(static target => target.HasValue)
|
|
98
|
-
.Select(static (target, _) => target!.Value);
|
|
152
|
+
Execute(typesToGenerate.ToImmutableArray(), aotTypes.ToImmutableArray(), context);
|
|
153
|
+
}
|
|
99
154
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
155
|
+
private static bool IsSyntaxTargetForGeneration(SyntaxNode node)
|
|
156
|
+
{
|
|
157
|
+
if (node is not TypeDeclarationSyntax typeDecl || !IsSupportedTypeDeclaration(typeDecl))
|
|
158
|
+
{
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
103
161
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
ImmutableArray<MessageToGenerateInfo>
|
|
107
|
-
)> compilationAndTypes = context.CompilationProvider.Combine(collectedTargets);
|
|
162
|
+
return typeDecl.AttributeLists.Count > 0 || HasRelevantMessageBaseType(typeDecl);
|
|
163
|
+
}
|
|
108
164
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
165
|
+
private static bool IsSupportedTypeDeclaration(TypeDeclarationSyntax typeDeclarationSyntax)
|
|
166
|
+
{
|
|
167
|
+
return typeDeclarationSyntax.IsKind(SyntaxKind.ClassDeclaration)
|
|
168
|
+
|| typeDeclarationSyntax.IsKind(SyntaxKind.StructDeclaration)
|
|
169
|
+
|| typeDeclarationSyntax.IsKind(SyntaxKind.RecordDeclaration)
|
|
170
|
+
|| string.Equals(
|
|
171
|
+
typeDeclarationSyntax.Kind().ToString(),
|
|
172
|
+
"RecordStructDeclaration",
|
|
173
|
+
StringComparison.Ordinal
|
|
174
|
+
);
|
|
114
175
|
}
|
|
115
176
|
|
|
116
|
-
private static bool
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
)
|
|
177
|
+
private static bool HasRelevantMessageBaseType(TypeDeclarationSyntax typeDeclarationSyntax)
|
|
178
|
+
{
|
|
179
|
+
if (typeDeclarationSyntax.BaseList is null)
|
|
180
|
+
{
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
foreach (BaseTypeSyntax baseType in typeDeclarationSyntax.BaseList.Types)
|
|
185
|
+
{
|
|
186
|
+
string baseTypeName = baseType.Type.ToString();
|
|
187
|
+
if (
|
|
188
|
+
baseTypeName.IndexOf("IUntargetedMessage", StringComparison.Ordinal) >= 0
|
|
189
|
+
|| baseTypeName.IndexOf("ITargetedMessage", StringComparison.Ordinal) >= 0
|
|
190
|
+
|| baseTypeName.IndexOf("IBroadcastMessage", StringComparison.Ordinal) >= 0
|
|
191
|
+
)
|
|
192
|
+
{
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
124
196
|
|
|
125
|
-
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private static SemanticTargetInfo? GetSemanticTarget(
|
|
126
201
|
TypeDeclarationSyntax typeDeclarationSyntax,
|
|
127
202
|
Compilation compilation,
|
|
128
203
|
CancellationToken cancellationToken
|
|
@@ -150,6 +225,9 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
150
225
|
|
|
151
226
|
string foundTargetInterface = null;
|
|
152
227
|
bool multipleAttributes = false;
|
|
228
|
+
bool hasUntargetedAttribute = false;
|
|
229
|
+
bool hasTargetedAttribute = false;
|
|
230
|
+
bool hasBroadcastAttribute = false;
|
|
153
231
|
|
|
154
232
|
// Check attributes to find the specific message type (Broadcast, Targeted, etc.)
|
|
155
233
|
foreach (AttributeData attributeData in typeSymbol.GetAttributes())
|
|
@@ -162,12 +240,15 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
162
240
|
{
|
|
163
241
|
case BroadcastAttrFullName:
|
|
164
242
|
targetInterfaceForThisAttribute = BroadcastInterfaceFullName;
|
|
243
|
+
hasBroadcastAttribute = true;
|
|
165
244
|
break;
|
|
166
245
|
case TargetedAttrFullName:
|
|
167
246
|
targetInterfaceForThisAttribute = TargetedInterfaceFullName;
|
|
247
|
+
hasTargetedAttribute = true;
|
|
168
248
|
break;
|
|
169
249
|
case UntargetedAttrFullName:
|
|
170
250
|
targetInterfaceForThisAttribute = UntargetedInterfaceFullName;
|
|
251
|
+
hasUntargetedAttribute = true;
|
|
171
252
|
break;
|
|
172
253
|
}
|
|
173
254
|
|
|
@@ -192,28 +273,92 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
192
273
|
|
|
193
274
|
if (foundTargetInterface == null && !multipleAttributes)
|
|
194
275
|
{
|
|
195
|
-
|
|
276
|
+
bool registersUntargeted = ImplementsInterface(
|
|
277
|
+
typeSymbol,
|
|
278
|
+
UntargetedInterfaceFullName
|
|
279
|
+
);
|
|
280
|
+
bool registersTargeted = ImplementsInterface(typeSymbol, TargetedInterfaceFullName);
|
|
281
|
+
bool registersBroadcast = ImplementsInterface(
|
|
282
|
+
typeSymbol,
|
|
283
|
+
BroadcastInterfaceFullName
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
if (!registersUntargeted && !registersTargeted && !registersBroadcast)
|
|
287
|
+
{
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
AotRegistrarInfo? manualRegistrar = ContainsTypeParameters(typeSymbol)
|
|
292
|
+
? null
|
|
293
|
+
: new AotRegistrarInfo(
|
|
294
|
+
typeSymbol,
|
|
295
|
+
registersUntargeted,
|
|
296
|
+
registersTargeted,
|
|
297
|
+
registersBroadcast,
|
|
298
|
+
HasMessageAttribute: false
|
|
299
|
+
);
|
|
300
|
+
return new SemanticTargetInfo(null, manualRegistrar);
|
|
196
301
|
}
|
|
197
302
|
|
|
198
|
-
|
|
303
|
+
bool implementsUntargeted = ImplementsInterface(
|
|
304
|
+
typeSymbol,
|
|
305
|
+
UntargetedInterfaceFullName
|
|
306
|
+
);
|
|
307
|
+
bool implementsTargeted = ImplementsInterface(typeSymbol, TargetedInterfaceFullName);
|
|
308
|
+
bool implementsBroadcast = ImplementsInterface(typeSymbol, BroadcastInterfaceFullName);
|
|
309
|
+
|
|
310
|
+
MessageToGenerateInfo messageToGenerate = new MessageToGenerateInfo(
|
|
199
311
|
typeSymbol,
|
|
200
312
|
typeDeclarationSyntax,
|
|
201
313
|
foundTargetInterface,
|
|
314
|
+
hasUntargetedAttribute || implementsUntargeted,
|
|
315
|
+
hasTargetedAttribute || implementsTargeted,
|
|
316
|
+
hasBroadcastAttribute || implementsBroadcast,
|
|
202
317
|
multipleAttributes
|
|
203
318
|
);
|
|
319
|
+
|
|
320
|
+
AotRegistrarInfo? attributedRegistrar =
|
|
321
|
+
multipleAttributes || ContainsTypeParameters(typeSymbol)
|
|
322
|
+
? null
|
|
323
|
+
: new AotRegistrarInfo(
|
|
324
|
+
typeSymbol,
|
|
325
|
+
hasUntargetedAttribute || implementsUntargeted,
|
|
326
|
+
hasTargetedAttribute || implementsTargeted,
|
|
327
|
+
hasBroadcastAttribute || implementsBroadcast,
|
|
328
|
+
HasMessageAttribute: true
|
|
329
|
+
);
|
|
330
|
+
|
|
331
|
+
return new SemanticTargetInfo(messageToGenerate, attributedRegistrar);
|
|
204
332
|
}
|
|
205
333
|
|
|
206
|
-
private static
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
SourceProductionContext context
|
|
334
|
+
private static bool ImplementsInterface(
|
|
335
|
+
INamedTypeSymbol typeSymbol,
|
|
336
|
+
string interfaceFullName
|
|
210
337
|
)
|
|
211
338
|
{
|
|
212
|
-
|
|
339
|
+
foreach (INamedTypeSymbol interfaceSymbol in typeSymbol.AllInterfaces)
|
|
213
340
|
{
|
|
214
|
-
|
|
341
|
+
if (
|
|
342
|
+
string.Equals(
|
|
343
|
+
interfaceSymbol.ToDisplayString(),
|
|
344
|
+
interfaceFullName,
|
|
345
|
+
StringComparison.Ordinal
|
|
346
|
+
)
|
|
347
|
+
)
|
|
348
|
+
{
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
215
351
|
}
|
|
216
352
|
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
private static void Execute(
|
|
357
|
+
ImmutableArray<MessageToGenerateInfo> typesToGenerate,
|
|
358
|
+
ImmutableArray<AotRegistrarInfo> aotTypes,
|
|
359
|
+
GeneratorExecutionContext context
|
|
360
|
+
)
|
|
361
|
+
{
|
|
217
362
|
// --- Step 1: Filter out types with multiple attributes applied ---
|
|
218
363
|
Dictionary<ISymbol, MessageToGenerateInfo> uniqueTypes = new Dictionary<
|
|
219
364
|
ISymbol,
|
|
@@ -282,11 +427,6 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
282
427
|
}
|
|
283
428
|
}
|
|
284
429
|
|
|
285
|
-
if (uniqueTypes.Count == 0)
|
|
286
|
-
{
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
430
|
List<MessageToGenerateInfo> validSingleAttrTypes = new List<MessageToGenerateInfo>();
|
|
291
431
|
foreach (KeyValuePair<ISymbol, MessageToGenerateInfo> entry in uniqueTypes)
|
|
292
432
|
{
|
|
@@ -298,12 +438,10 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
298
438
|
validSingleAttrTypes.Add(entry.Value);
|
|
299
439
|
}
|
|
300
440
|
|
|
301
|
-
if (validSingleAttrTypes.Count == 0)
|
|
302
|
-
{
|
|
303
|
-
return;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
441
|
// --- Step 2: Generate sources for each valid message type ---
|
|
442
|
+
HashSet<ISymbol> generatedAttributedTypes = new HashSet<ISymbol>(
|
|
443
|
+
SymbolEqualityComparer.Default
|
|
444
|
+
);
|
|
307
445
|
foreach (MessageToGenerateInfo messageInfo in validSingleAttrTypes)
|
|
308
446
|
{
|
|
309
447
|
context.CancellationToken.ThrowIfCancellationRequested();
|
|
@@ -363,10 +501,7 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
363
501
|
}
|
|
364
502
|
|
|
365
503
|
// Generate the partial IMessage implementation source
|
|
366
|
-
string implSource = GenerateImplementationSource(
|
|
367
|
-
targetInterfaceFullName,
|
|
368
|
-
messageInfo.TypeSymbol
|
|
369
|
-
);
|
|
504
|
+
string implSource = GenerateImplementationSource(messageInfo);
|
|
370
505
|
string implHintName =
|
|
371
506
|
$"{messageInfo.TypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)}.IMessage.g.cs"
|
|
372
507
|
.Replace("global::", "")
|
|
@@ -375,15 +510,31 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
375
510
|
.Replace(",", "_"); // Clean hint name
|
|
376
511
|
|
|
377
512
|
context.AddSource(implHintName, SourceText.From(implSource, Encoding.UTF8));
|
|
513
|
+
generatedAttributedTypes.Add(messageInfo.TypeSymbol);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
GenerateTopLevelAotRegistrar(aotTypes, generatedAttributedTypes, context);
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
private sealed class TypeSyntaxReceiver : ISyntaxReceiver
|
|
520
|
+
{
|
|
521
|
+
public List<TypeDeclarationSyntax> Candidates { get; } =
|
|
522
|
+
new List<TypeDeclarationSyntax>();
|
|
523
|
+
|
|
524
|
+
public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
|
|
525
|
+
{
|
|
526
|
+
if (IsSyntaxTargetForGeneration(syntaxNode))
|
|
527
|
+
{
|
|
528
|
+
Candidates.Add((TypeDeclarationSyntax)syntaxNode);
|
|
529
|
+
}
|
|
378
530
|
}
|
|
379
531
|
}
|
|
380
532
|
|
|
381
533
|
// Generates the partial class/struct implementing IMessage
|
|
382
|
-
private static string GenerateImplementationSource(
|
|
383
|
-
string targetInterfaceFullName, // e.g., IBroadcastMessage
|
|
384
|
-
INamedTypeSymbol typeSymbol
|
|
385
|
-
)
|
|
534
|
+
private static string GenerateImplementationSource(MessageToGenerateInfo messageInfo)
|
|
386
535
|
{
|
|
536
|
+
string targetInterfaceFullName = messageInfo.TargetInterfaceFullName;
|
|
537
|
+
INamedTypeSymbol typeSymbol = messageInfo.TypeSymbol;
|
|
387
538
|
string namespaceName = typeSymbol.ContainingNamespace.IsGlobalNamespace
|
|
388
539
|
? string.Empty
|
|
389
540
|
: typeSymbol.ContainingNamespace.ToDisplayString();
|
|
@@ -418,10 +569,11 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
418
569
|
_ => "internal",
|
|
419
570
|
};
|
|
420
571
|
|
|
572
|
+
bool containerIsRecord = IsRecordDeclaration(container);
|
|
421
573
|
string containerKind = container.TypeKind switch
|
|
422
574
|
{
|
|
423
|
-
TypeKind.Class =>
|
|
424
|
-
TypeKind.Struct =>
|
|
575
|
+
TypeKind.Class => containerIsRecord ? "record class" : "class",
|
|
576
|
+
TypeKind.Struct => containerIsRecord ? "record struct" : "struct",
|
|
425
577
|
_ => "class",
|
|
426
578
|
};
|
|
427
579
|
|
|
@@ -454,10 +606,11 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
454
606
|
SymbolDisplayFormat.FullyQualifiedFormat
|
|
455
607
|
);
|
|
456
608
|
|
|
609
|
+
bool typeIsRecord = IsRecordDeclaration(typeSymbol);
|
|
457
610
|
string typeKind = typeSymbol.TypeKind switch
|
|
458
611
|
{
|
|
459
|
-
TypeKind.Class =>
|
|
460
|
-
TypeKind.Struct =>
|
|
612
|
+
TypeKind.Class => typeIsRecord ? "record class" : "class",
|
|
613
|
+
TypeKind.Struct => typeIsRecord ? "record struct" : "struct",
|
|
461
614
|
_ => throw new InvalidOperationException("Unsupported type kind"),
|
|
462
615
|
};
|
|
463
616
|
|
|
@@ -473,6 +626,13 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
473
626
|
};
|
|
474
627
|
|
|
475
628
|
string interfaceDeclaration = $", global::{targetInterfaceFullName}";
|
|
629
|
+
string aotBridgeSource = ContainsTypeParameters(typeSymbol)
|
|
630
|
+
? string.Empty
|
|
631
|
+
: GenerateTypeScopedAotBridgeSource(
|
|
632
|
+
messageInfo,
|
|
633
|
+
fullyQualifiedName,
|
|
634
|
+
innerIndent + Indent
|
|
635
|
+
);
|
|
476
636
|
|
|
477
637
|
// Close containers string
|
|
478
638
|
for (int i = 0; i < containers.Count; i++)
|
|
@@ -484,21 +644,519 @@ namespace WallstopStudios.DxMessaging.SourceGenerators
|
|
|
484
644
|
containersClose.Append(currentIndent).AppendLine("}");
|
|
485
645
|
}
|
|
486
646
|
|
|
487
|
-
return
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
647
|
+
return string.Join(
|
|
648
|
+
"\r\n",
|
|
649
|
+
new[]
|
|
650
|
+
{
|
|
651
|
+
"// <auto-generated by DxMessageIdGenerator/>",
|
|
652
|
+
"#pragma warning disable",
|
|
653
|
+
"#nullable enable annotations",
|
|
654
|
+
string.Empty,
|
|
655
|
+
namespaceBlockOpen,
|
|
656
|
+
$"{containersOpen}{innerIndent}// Partial implementation for {typeNameWithGenerics} to implement {BaseInterfaceFullName}",
|
|
657
|
+
$"{innerIndent}{accessibility} partial {typeKind} {typeNameWithGenerics} : global::{BaseInterfaceFullName} {interfaceDeclaration}",
|
|
658
|
+
$"{innerIndent}{{",
|
|
659
|
+
$"{innerIndent} /// <inheritdoc/>",
|
|
660
|
+
$"{innerIndent} public global::System.Type MessageType => typeof({fullyQualifiedName});",
|
|
661
|
+
$"{aotBridgeSource}",
|
|
662
|
+
$"{innerIndent}}}",
|
|
663
|
+
$"{containersClose}",
|
|
664
|
+
namespaceBlockClose,
|
|
665
|
+
string.Empty,
|
|
666
|
+
}
|
|
667
|
+
);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
private static string GenerateTypeScopedAotBridgeSource(
|
|
671
|
+
MessageToGenerateInfo messageInfo,
|
|
672
|
+
string fullyQualifiedName,
|
|
673
|
+
string indent
|
|
674
|
+
)
|
|
675
|
+
{
|
|
676
|
+
var builder = new StringBuilder();
|
|
677
|
+
builder.AppendLine();
|
|
678
|
+
builder.Append(indent).AppendLine("#if ENABLE_IL2CPP && UNITY_2021_3_OR_NEWER");
|
|
679
|
+
builder.Append(indent).AppendLine("[global::UnityEngine.Scripting.Preserve]");
|
|
680
|
+
builder
|
|
681
|
+
.Append(indent)
|
|
682
|
+
.AppendLine(
|
|
683
|
+
"[global::UnityEngine.RuntimeInitializeOnLoadMethod(global::UnityEngine.RuntimeInitializeLoadType.AfterAssembliesLoaded)]"
|
|
684
|
+
);
|
|
685
|
+
builder
|
|
686
|
+
.Append(indent)
|
|
687
|
+
.AppendLine("private static void __DxMessagingRegisterAotBridges()");
|
|
688
|
+
builder.Append(indent).AppendLine("{");
|
|
689
|
+
if (messageInfo.RegistersUntargetedAotBridge)
|
|
690
|
+
{
|
|
691
|
+
AppendAotRegisterCall(
|
|
692
|
+
builder,
|
|
693
|
+
indent + " ",
|
|
694
|
+
"RegisterAotUntargetedBridge",
|
|
695
|
+
AotBridgeKind.Untargeted,
|
|
696
|
+
fullyQualifiedName,
|
|
697
|
+
"__DxMessagingAotUntargetedBridge"
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
if (messageInfo.RegistersTargetedAotBridge)
|
|
701
|
+
{
|
|
702
|
+
AppendAotRegisterCall(
|
|
703
|
+
builder,
|
|
704
|
+
indent + " ",
|
|
705
|
+
"RegisterAotTargetedBridge",
|
|
706
|
+
AotBridgeKind.Targeted,
|
|
707
|
+
fullyQualifiedName,
|
|
708
|
+
"__DxMessagingAotTargetedBridge"
|
|
709
|
+
);
|
|
710
|
+
}
|
|
711
|
+
if (messageInfo.RegistersBroadcastAotBridge)
|
|
712
|
+
{
|
|
713
|
+
AppendAotRegisterCall(
|
|
714
|
+
builder,
|
|
715
|
+
indent + " ",
|
|
716
|
+
"RegisterAotSourcedBridge",
|
|
717
|
+
AotBridgeKind.Broadcast,
|
|
718
|
+
fullyQualifiedName,
|
|
719
|
+
"__DxMessagingAotSourcedBridge"
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
builder.Append(indent).AppendLine("}");
|
|
723
|
+
|
|
724
|
+
AppendAotReflectionHelper(builder, indent);
|
|
725
|
+
if (messageInfo.RegistersUntargetedAotBridge)
|
|
726
|
+
{
|
|
727
|
+
AppendUntargetedBridgeMethod(
|
|
728
|
+
builder,
|
|
729
|
+
indent,
|
|
730
|
+
"__DxMessagingAotUntargetedBridge",
|
|
731
|
+
fullyQualifiedName
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
if (messageInfo.RegistersTargetedAotBridge)
|
|
735
|
+
{
|
|
736
|
+
AppendTargetedBridgeMethod(
|
|
737
|
+
builder,
|
|
738
|
+
indent,
|
|
739
|
+
"__DxMessagingAotTargetedBridge",
|
|
740
|
+
fullyQualifiedName
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
if (messageInfo.RegistersBroadcastAotBridge)
|
|
744
|
+
{
|
|
745
|
+
AppendBroadcastBridgeMethod(
|
|
746
|
+
builder,
|
|
747
|
+
indent,
|
|
748
|
+
"__DxMessagingAotSourcedBridge",
|
|
749
|
+
fullyQualifiedName
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
builder.Append(indent).Append("#endif");
|
|
754
|
+
return builder.ToString();
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
private static void GenerateTopLevelAotRegistrar(
|
|
758
|
+
ImmutableArray<AotRegistrarInfo> aotTypes,
|
|
759
|
+
HashSet<ISymbol> generatedAttributedTypes,
|
|
760
|
+
GeneratorExecutionContext context
|
|
761
|
+
)
|
|
762
|
+
{
|
|
763
|
+
if (aotTypes.IsDefaultOrEmpty)
|
|
764
|
+
{
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
List<AotRegistrarInfo> registrarTypes = aotTypes
|
|
769
|
+
.Where(info =>
|
|
770
|
+
!info.HasMessageAttribute
|
|
771
|
+
&& !generatedAttributedTypes.Contains(info.TypeSymbol)
|
|
772
|
+
&& IsAccessibleFromTopLevelRegistrar(info.TypeSymbol)
|
|
773
|
+
)
|
|
774
|
+
.GroupBy(info => info.TypeSymbol, SymbolEqualityComparer.Default)
|
|
775
|
+
.Select(group =>
|
|
776
|
+
{
|
|
777
|
+
AotRegistrarInfo merged = default;
|
|
778
|
+
bool hasValue = false;
|
|
779
|
+
foreach (AotRegistrarInfo info in group)
|
|
780
|
+
{
|
|
781
|
+
if (!hasValue)
|
|
782
|
+
{
|
|
783
|
+
merged = info;
|
|
784
|
+
hasValue = true;
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
merged = new AotRegistrarInfo(
|
|
789
|
+
info.TypeSymbol,
|
|
790
|
+
merged.RegistersUntargetedAotBridge
|
|
791
|
+
|| info.RegistersUntargetedAotBridge,
|
|
792
|
+
merged.RegistersTargetedAotBridge || info.RegistersTargetedAotBridge,
|
|
793
|
+
merged.RegistersBroadcastAotBridge || info.RegistersBroadcastAotBridge,
|
|
794
|
+
merged.HasMessageAttribute || info.HasMessageAttribute
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
return merged;
|
|
799
|
+
})
|
|
800
|
+
.OrderBy(
|
|
801
|
+
info =>
|
|
802
|
+
info.TypeSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat),
|
|
803
|
+
StringComparer.Ordinal
|
|
804
|
+
)
|
|
805
|
+
.ToList();
|
|
806
|
+
|
|
807
|
+
if (registrarTypes.Count == 0)
|
|
808
|
+
{
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
string source = GenerateTopLevelAotRegistrarSource(registrarTypes);
|
|
813
|
+
context.AddSource(
|
|
814
|
+
"DxMessaging.Il2CppMessageRegistrar.g.cs",
|
|
815
|
+
SourceText.From(source, Encoding.UTF8)
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
private static string GenerateTopLevelAotRegistrarSource(List<AotRegistrarInfo> types)
|
|
820
|
+
{
|
|
821
|
+
const string Indent = " ";
|
|
822
|
+
List<AotRegistrarSourceInfo> sourceTypes = types
|
|
823
|
+
.Select(
|
|
824
|
+
(info, index) =>
|
|
825
|
+
{
|
|
826
|
+
string typeName = info.TypeSymbol.ToDisplayString(
|
|
827
|
+
SymbolDisplayFormat.FullyQualifiedFormat
|
|
828
|
+
);
|
|
829
|
+
return new AotRegistrarSourceInfo(
|
|
830
|
+
info,
|
|
831
|
+
typeName,
|
|
832
|
+
index + "_" + SanitizeIdentifier(typeName)
|
|
833
|
+
);
|
|
834
|
+
}
|
|
835
|
+
)
|
|
836
|
+
.ToList();
|
|
837
|
+
|
|
838
|
+
var builder = new StringBuilder();
|
|
839
|
+
builder.AppendLine("// <auto-generated by DxMessageIdGenerator/>");
|
|
840
|
+
builder.AppendLine("#pragma warning disable");
|
|
841
|
+
builder.AppendLine("#nullable enable annotations");
|
|
842
|
+
builder.AppendLine("#if ENABLE_IL2CPP && UNITY_2021_3_OR_NEWER");
|
|
843
|
+
builder.AppendLine("namespace DxMessaging.Generated");
|
|
844
|
+
builder.AppendLine("{");
|
|
845
|
+
builder.AppendLine(" [global::UnityEngine.Scripting.Preserve]");
|
|
846
|
+
builder.AppendLine(" internal static class DxMessagingIl2CppMessageRegistrar");
|
|
847
|
+
builder.AppendLine(" {");
|
|
848
|
+
builder.AppendLine(
|
|
849
|
+
" [global::UnityEngine.RuntimeInitializeOnLoadMethod(global::UnityEngine.RuntimeInitializeLoadType.AfterAssembliesLoaded)]"
|
|
850
|
+
);
|
|
851
|
+
builder.AppendLine(" private static void Register()");
|
|
852
|
+
builder.AppendLine(" {");
|
|
853
|
+
foreach (AotRegistrarSourceInfo sourceInfo in sourceTypes)
|
|
854
|
+
{
|
|
855
|
+
AotRegistrarInfo info = sourceInfo.Info;
|
|
856
|
+
string typeName = sourceInfo.TypeName;
|
|
857
|
+
string suffix = sourceInfo.Suffix;
|
|
858
|
+
if (info.RegistersUntargetedAotBridge)
|
|
859
|
+
{
|
|
860
|
+
AppendAotRegisterCall(
|
|
861
|
+
builder,
|
|
862
|
+
Indent + " ",
|
|
863
|
+
"RegisterAotUntargetedBridge",
|
|
864
|
+
AotBridgeKind.Untargeted,
|
|
865
|
+
typeName,
|
|
866
|
+
"__DxMessagingAotUntargetedBridge_" + suffix
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
if (info.RegistersTargetedAotBridge)
|
|
870
|
+
{
|
|
871
|
+
AppendAotRegisterCall(
|
|
872
|
+
builder,
|
|
873
|
+
Indent + " ",
|
|
874
|
+
"RegisterAotTargetedBridge",
|
|
875
|
+
AotBridgeKind.Targeted,
|
|
876
|
+
typeName,
|
|
877
|
+
"__DxMessagingAotTargetedBridge_" + suffix
|
|
878
|
+
);
|
|
879
|
+
}
|
|
880
|
+
if (info.RegistersBroadcastAotBridge)
|
|
881
|
+
{
|
|
882
|
+
AppendAotRegisterCall(
|
|
883
|
+
builder,
|
|
884
|
+
Indent + " ",
|
|
885
|
+
"RegisterAotSourcedBridge",
|
|
886
|
+
AotBridgeKind.Broadcast,
|
|
887
|
+
typeName,
|
|
888
|
+
"__DxMessagingAotSourcedBridge_" + suffix
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
builder.AppendLine(" }");
|
|
893
|
+
|
|
894
|
+
AppendAotReflectionHelper(builder, Indent);
|
|
895
|
+
foreach (AotRegistrarSourceInfo sourceInfo in sourceTypes)
|
|
896
|
+
{
|
|
897
|
+
AotRegistrarInfo info = sourceInfo.Info;
|
|
898
|
+
string typeName = sourceInfo.TypeName;
|
|
899
|
+
string suffix = sourceInfo.Suffix;
|
|
900
|
+
if (info.RegistersUntargetedAotBridge)
|
|
901
|
+
{
|
|
902
|
+
AppendUntargetedBridgeMethod(
|
|
903
|
+
builder,
|
|
904
|
+
Indent,
|
|
905
|
+
"__DxMessagingAotUntargetedBridge_" + suffix,
|
|
906
|
+
typeName
|
|
907
|
+
);
|
|
908
|
+
}
|
|
909
|
+
if (info.RegistersTargetedAotBridge)
|
|
910
|
+
{
|
|
911
|
+
AppendTargetedBridgeMethod(
|
|
912
|
+
builder,
|
|
913
|
+
Indent,
|
|
914
|
+
"__DxMessagingAotTargetedBridge_" + suffix,
|
|
915
|
+
typeName
|
|
916
|
+
);
|
|
917
|
+
}
|
|
918
|
+
if (info.RegistersBroadcastAotBridge)
|
|
919
|
+
{
|
|
920
|
+
AppendBroadcastBridgeMethod(
|
|
921
|
+
builder,
|
|
922
|
+
Indent,
|
|
923
|
+
"__DxMessagingAotSourcedBridge_" + suffix,
|
|
924
|
+
typeName
|
|
925
|
+
);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
builder.AppendLine(" }");
|
|
930
|
+
builder.AppendLine("}");
|
|
931
|
+
builder.AppendLine("#endif");
|
|
932
|
+
return builder.ToString();
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
private static void AppendAotRegisterCall(
|
|
936
|
+
StringBuilder builder,
|
|
937
|
+
string indent,
|
|
938
|
+
string runtimeMethodName,
|
|
939
|
+
AotBridgeKind bridgeKind,
|
|
940
|
+
string fullyQualifiedName,
|
|
941
|
+
string bridgeMethodName
|
|
942
|
+
)
|
|
943
|
+
{
|
|
944
|
+
string delegateType = GetAotDelegateType(bridgeKind);
|
|
945
|
+
builder
|
|
946
|
+
.Append(indent)
|
|
947
|
+
.Append("__DxMessagingRegisterAotBridge(\"")
|
|
948
|
+
.Append(runtimeMethodName)
|
|
949
|
+
.Append("\", typeof(")
|
|
950
|
+
.Append(fullyQualifiedName)
|
|
951
|
+
.Append("), (")
|
|
952
|
+
.Append(delegateType)
|
|
953
|
+
.Append(")")
|
|
954
|
+
.Append(bridgeMethodName)
|
|
955
|
+
.AppendLine(");");
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
private static string GetAotDelegateType(AotBridgeKind bridgeKind)
|
|
959
|
+
{
|
|
960
|
+
return bridgeKind switch
|
|
961
|
+
{
|
|
962
|
+
AotBridgeKind.Untargeted =>
|
|
963
|
+
"global::System.Action<global::DxMessaging.Core.MessageBus.IMessageBus, global::DxMessaging.Core.Messages.IUntargetedMessage>",
|
|
964
|
+
AotBridgeKind.Targeted =>
|
|
965
|
+
"global::System.Action<global::DxMessaging.Core.MessageBus.IMessageBus, global::DxMessaging.Core.InstanceId, global::DxMessaging.Core.Messages.ITargetedMessage>",
|
|
966
|
+
AotBridgeKind.Broadcast =>
|
|
967
|
+
"global::System.Action<global::DxMessaging.Core.MessageBus.IMessageBus, global::DxMessaging.Core.InstanceId, global::DxMessaging.Core.Messages.IBroadcastMessage>",
|
|
968
|
+
_ => throw new ArgumentOutOfRangeException(nameof(bridgeKind)),
|
|
969
|
+
};
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
private static void AppendAotReflectionHelper(StringBuilder builder, string indent)
|
|
973
|
+
{
|
|
974
|
+
builder.AppendLine();
|
|
975
|
+
builder
|
|
976
|
+
.Append(indent)
|
|
977
|
+
.AppendLine(
|
|
978
|
+
"private static void __DxMessagingRegisterAotBridge(string methodName, global::System.Type messageType, global::System.Delegate bridge)"
|
|
979
|
+
);
|
|
980
|
+
builder.Append(indent).AppendLine("{");
|
|
981
|
+
builder
|
|
982
|
+
.Append(indent)
|
|
983
|
+
.AppendLine(
|
|
984
|
+
" global::System.Reflection.MethodInfo method = typeof(global::DxMessaging.Core.MessageBus.MessageBus).GetMethod(methodName, global::System.Reflection.BindingFlags.Static | global::System.Reflection.BindingFlags.NonPublic);"
|
|
985
|
+
);
|
|
986
|
+
builder.Append(indent).AppendLine(" if (method == null)");
|
|
987
|
+
builder.Append(indent).AppendLine(" {");
|
|
988
|
+
builder
|
|
989
|
+
.Append(indent)
|
|
990
|
+
.AppendLine(
|
|
991
|
+
" throw new global::System.MissingMethodException(\"DxMessaging AOT bridge registration hook was not found: \" + methodName);"
|
|
992
|
+
);
|
|
993
|
+
builder.Append(indent).AppendLine(" }");
|
|
994
|
+
builder
|
|
995
|
+
.Append(indent)
|
|
996
|
+
.AppendLine(" method.Invoke(null, new object[] { messageType, bridge });");
|
|
997
|
+
builder.Append(indent).AppendLine("}");
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
private static void AppendUntargetedBridgeMethod(
|
|
1001
|
+
StringBuilder builder,
|
|
1002
|
+
string indent,
|
|
1003
|
+
string methodName,
|
|
1004
|
+
string fullyQualifiedName
|
|
1005
|
+
)
|
|
1006
|
+
{
|
|
1007
|
+
builder.AppendLine();
|
|
1008
|
+
builder
|
|
1009
|
+
.Append(indent)
|
|
1010
|
+
.AppendLine(
|
|
1011
|
+
"private static void "
|
|
1012
|
+
+ methodName
|
|
1013
|
+
+ "(global::DxMessaging.Core.MessageBus.IMessageBus messageBus, global::DxMessaging.Core.Messages.IUntargetedMessage message)"
|
|
1014
|
+
);
|
|
1015
|
+
builder.Append(indent).AppendLine("{");
|
|
1016
|
+
builder
|
|
1017
|
+
.Append(indent)
|
|
1018
|
+
.Append(" ")
|
|
1019
|
+
.Append(fullyQualifiedName)
|
|
1020
|
+
.AppendLine(" typedMessage = (" + fullyQualifiedName + ")message;");
|
|
1021
|
+
builder
|
|
1022
|
+
.Append(indent)
|
|
1023
|
+
.AppendLine(" messageBus.UntargetedBroadcast(ref typedMessage);");
|
|
1024
|
+
builder.Append(indent).AppendLine("}");
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
private static void AppendTargetedBridgeMethod(
|
|
1028
|
+
StringBuilder builder,
|
|
1029
|
+
string indent,
|
|
1030
|
+
string methodName,
|
|
1031
|
+
string fullyQualifiedName
|
|
1032
|
+
)
|
|
1033
|
+
{
|
|
1034
|
+
builder.AppendLine();
|
|
1035
|
+
builder
|
|
1036
|
+
.Append(indent)
|
|
1037
|
+
.AppendLine(
|
|
1038
|
+
"private static void "
|
|
1039
|
+
+ methodName
|
|
1040
|
+
+ "(global::DxMessaging.Core.MessageBus.IMessageBus messageBus, global::DxMessaging.Core.InstanceId target, global::DxMessaging.Core.Messages.ITargetedMessage message)"
|
|
1041
|
+
);
|
|
1042
|
+
builder.Append(indent).AppendLine("{");
|
|
1043
|
+
builder
|
|
1044
|
+
.Append(indent)
|
|
1045
|
+
.Append(" ")
|
|
1046
|
+
.Append(fullyQualifiedName)
|
|
1047
|
+
.AppendLine(" typedMessage = (" + fullyQualifiedName + ")message;");
|
|
1048
|
+
builder
|
|
1049
|
+
.Append(indent)
|
|
1050
|
+
.AppendLine(" messageBus.TargetedBroadcast(ref target, ref typedMessage);");
|
|
1051
|
+
builder.Append(indent).AppendLine("}");
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
private static void AppendBroadcastBridgeMethod(
|
|
1055
|
+
StringBuilder builder,
|
|
1056
|
+
string indent,
|
|
1057
|
+
string methodName,
|
|
1058
|
+
string fullyQualifiedName
|
|
1059
|
+
)
|
|
1060
|
+
{
|
|
1061
|
+
builder.AppendLine();
|
|
1062
|
+
builder
|
|
1063
|
+
.Append(indent)
|
|
1064
|
+
.AppendLine(
|
|
1065
|
+
"private static void "
|
|
1066
|
+
+ methodName
|
|
1067
|
+
+ "(global::DxMessaging.Core.MessageBus.IMessageBus messageBus, global::DxMessaging.Core.InstanceId source, global::DxMessaging.Core.Messages.IBroadcastMessage message)"
|
|
1068
|
+
);
|
|
1069
|
+
builder.Append(indent).AppendLine("{");
|
|
1070
|
+
builder
|
|
1071
|
+
.Append(indent)
|
|
1072
|
+
.Append(" ")
|
|
1073
|
+
.Append(fullyQualifiedName)
|
|
1074
|
+
.AppendLine(" typedMessage = (" + fullyQualifiedName + ")message;");
|
|
1075
|
+
builder
|
|
1076
|
+
.Append(indent)
|
|
1077
|
+
.AppendLine(" messageBus.SourcedBroadcast(ref source, ref typedMessage);");
|
|
1078
|
+
builder.Append(indent).AppendLine("}");
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
private static bool IsAccessibleFromTopLevelRegistrar(INamedTypeSymbol typeSymbol)
|
|
1082
|
+
{
|
|
1083
|
+
if (ContainsTypeParameters(typeSymbol))
|
|
1084
|
+
{
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1088
|
+
for (
|
|
1089
|
+
INamedTypeSymbol current = typeSymbol;
|
|
1090
|
+
current != null;
|
|
1091
|
+
current = current.ContainingType
|
|
1092
|
+
)
|
|
1093
|
+
{
|
|
1094
|
+
if (!IsAccessibleFromSameAssemblyTopLevel(current.DeclaredAccessibility))
|
|
1095
|
+
{
|
|
1096
|
+
return false;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
return true;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
private static bool IsAccessibleFromSameAssemblyTopLevel(Accessibility accessibility)
|
|
1104
|
+
{
|
|
1105
|
+
return accessibility == Accessibility.Public
|
|
1106
|
+
|| accessibility == Accessibility.Internal
|
|
1107
|
+
|| accessibility == Accessibility.ProtectedOrInternal;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
private static bool ContainsTypeParameters(INamedTypeSymbol typeSymbol)
|
|
1111
|
+
{
|
|
1112
|
+
for (
|
|
1113
|
+
INamedTypeSymbol current = typeSymbol;
|
|
1114
|
+
current != null;
|
|
1115
|
+
current = current.ContainingType
|
|
1116
|
+
)
|
|
1117
|
+
{
|
|
1118
|
+
if (current.TypeParameters.Length > 0)
|
|
1119
|
+
{
|
|
1120
|
+
return true;
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
return false;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
private static string SanitizeIdentifier(string value)
|
|
1128
|
+
{
|
|
1129
|
+
var builder = new StringBuilder(value.Length);
|
|
1130
|
+
foreach (char c in value)
|
|
1131
|
+
{
|
|
1132
|
+
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
|
|
1133
|
+
{
|
|
1134
|
+
builder.Append(c);
|
|
1135
|
+
}
|
|
1136
|
+
else
|
|
1137
|
+
{
|
|
1138
|
+
builder.Append('_');
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
return builder.ToString();
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
private static bool IsRecordDeclaration(INamedTypeSymbol symbol)
|
|
1146
|
+
{
|
|
1147
|
+
foreach (SyntaxReference syntaxReference in symbol.DeclaringSyntaxReferences)
|
|
1148
|
+
{
|
|
1149
|
+
if (syntaxReference.GetSyntax() is TypeDeclarationSyntax declaration)
|
|
1150
|
+
{
|
|
1151
|
+
string kind = declaration.Kind().ToString();
|
|
1152
|
+
if (kind.IndexOf("Record", StringComparison.Ordinal) >= 0)
|
|
1153
|
+
{
|
|
1154
|
+
return true;
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
return false;
|
|
502
1160
|
}
|
|
503
1161
|
|
|
504
1162
|
private static List<INamedTypeSymbol> GetNonPartialContainers(INamedTypeSymbol typeSymbol)
|