com.wallstop-studios.dxmessaging 1.0.6 → 2.0.0-rc02

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.
Files changed (45) hide show
  1. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
  2. package/Editor/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +33 -0
  3. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
  4. package/Editor/Analyzers/Microsoft.CodeAnalysis.dll.meta +33 -0
  5. package/Editor/Analyzers/System.Reflection.Metadata.dll +0 -0
  6. package/Editor/Analyzers/System.Reflection.Metadata.dll.meta +33 -0
  7. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
  8. package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +71 -0
  9. package/Editor/Analyzers.meta +8 -0
  10. package/Editor/SetupCscRsp.cs +146 -0
  11. package/Editor/SetupCscRsp.cs.meta +3 -0
  12. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef +18 -0
  13. package/Editor/WallstopStudios.DxMessaging.Editor.asmdef.meta +7 -0
  14. package/README.md +43 -6
  15. package/Runtime/Core/Attributes/DxAutoMessageTypeAttribute.cs +9 -0
  16. package/Runtime/Core/Attributes/DxAutoMessageTypeAttribute.cs.meta +3 -0
  17. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs +10 -0
  18. package/Runtime/Core/Attributes/DxBroadcastMessageAttribute.cs.meta +3 -0
  19. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs +10 -0
  20. package/Runtime/Core/Attributes/DxTargetedMessageAttribute.cs.meta +3 -0
  21. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs +10 -0
  22. package/Runtime/Core/Attributes/DxUntargetedMessageAttribute.cs.meta +3 -0
  23. package/Runtime/Core/Attributes.meta +3 -0
  24. package/Runtime/WallstopStudios.DxMessaging.asmdef +15 -17
  25. package/Runtime/WallstopStudios.DxMessaging.asmdef.meta +7 -7
  26. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoMessageTypeGenerator.cs +75 -0
  27. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoMessageTypeGenerator.cs.meta +11 -0
  28. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxBroadcastMessageGenerator.cs +77 -0
  29. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxBroadcastMessageGenerator.cs.meta +3 -0
  30. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxTargetedMessageGenerator.cs +77 -0
  31. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxTargetedMessageGenerator.cs.meta +3 -0
  32. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxUntargetedMessageGenerator.cs +78 -0
  33. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxUntargetedMessageGenerator.cs.meta +3 -0
  34. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj +21 -0
  35. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.csproj.meta +7 -0
  36. package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators.meta +8 -0
  37. package/SourceGenerators.meta +8 -0
  38. package/Tests/Runtime/Core/NominalTests.cs +127 -77
  39. package/Tests/Runtime/Core/RegistrationTests.cs +56 -106
  40. package/Tests/Runtime/Scripts/Messages/ComplexTargetedMessage.cs +4 -2
  41. package/Tests/Runtime/Scripts/Messages/SimpleBroadcastMessage.cs +3 -3
  42. package/Tests/Runtime/Scripts/Messages/SimpleTargetedMessage.cs +4 -4
  43. package/Tests/Runtime/Scripts/Messages/SimpleUntargetedMessage.cs +3 -3
  44. package/Tests/Runtime/WallstopStudios.DxMessaging.Tests.Runtime.asmdef +1 -1
  45. package/package.json +3 -3
@@ -0,0 +1,33 @@
1
+ fileFormatVersion: 2
2
+ guid: f3159f12192b58547a5f8576eeca5fcf
3
+ PluginImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ iconMap: {}
7
+ executionOrder: {}
8
+ defineConstraints: []
9
+ isPreloaded: 0
10
+ isOverridable: 1
11
+ isExplicitlyReferenced: 0
12
+ validateReferences: 1
13
+ platformData:
14
+ - first:
15
+ Any:
16
+ second:
17
+ enabled: 0
18
+ settings: {}
19
+ - first:
20
+ Editor: Editor
21
+ second:
22
+ enabled: 1
23
+ settings:
24
+ DefaultValueInitialized: true
25
+ - first:
26
+ Windows Store Apps: WindowsStoreApps
27
+ second:
28
+ enabled: 0
29
+ settings:
30
+ CPU: AnyCPU
31
+ userData:
32
+ assetBundleName:
33
+ assetBundleVariant:
@@ -0,0 +1,33 @@
1
+ fileFormatVersion: 2
2
+ guid: 8292b8f0b3241d94db97183f9ebc34bd
3
+ PluginImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ iconMap: {}
7
+ executionOrder: {}
8
+ defineConstraints: []
9
+ isPreloaded: 0
10
+ isOverridable: 1
11
+ isExplicitlyReferenced: 0
12
+ validateReferences: 1
13
+ platformData:
14
+ - first:
15
+ Any:
16
+ second:
17
+ enabled: 1
18
+ settings: {}
19
+ - first:
20
+ Editor: Editor
21
+ second:
22
+ enabled: 0
23
+ settings:
24
+ DefaultValueInitialized: true
25
+ - first:
26
+ Windows Store Apps: WindowsStoreApps
27
+ second:
28
+ enabled: 0
29
+ settings:
30
+ CPU: AnyCPU
31
+ userData:
32
+ assetBundleName:
33
+ assetBundleVariant:
@@ -0,0 +1,33 @@
1
+ fileFormatVersion: 2
2
+ guid: b8c642df60408714396e9c4b38f80233
3
+ PluginImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ iconMap: {}
7
+ executionOrder: {}
8
+ defineConstraints: []
9
+ isPreloaded: 0
10
+ isOverridable: 1
11
+ isExplicitlyReferenced: 0
12
+ validateReferences: 1
13
+ platformData:
14
+ - first:
15
+ Any:
16
+ second:
17
+ enabled: 1
18
+ settings: {}
19
+ - first:
20
+ Editor: Editor
21
+ second:
22
+ enabled: 0
23
+ settings:
24
+ DefaultValueInitialized: true
25
+ - first:
26
+ Windows Store Apps: WindowsStoreApps
27
+ second:
28
+ enabled: 0
29
+ settings:
30
+ CPU: AnyCPU
31
+ userData:
32
+ assetBundleName:
33
+ assetBundleVariant:
@@ -0,0 +1,71 @@
1
+ fileFormatVersion: 2
2
+ guid: 6276058efb4d05248b64a4295f60baf6
3
+ labels:
4
+ - RoslynAnalyzer
5
+ PluginImporter:
6
+ externalObjects: {}
7
+ serializedVersion: 2
8
+ iconMap: {}
9
+ executionOrder: {}
10
+ defineConstraints: []
11
+ isPreloaded: 0
12
+ isOverridable: 1
13
+ isExplicitlyReferenced: 0
14
+ validateReferences: 1
15
+ platformData:
16
+ - first:
17
+ : Any
18
+ second:
19
+ enabled: 0
20
+ settings:
21
+ Exclude Editor: 1
22
+ Exclude Linux64: 1
23
+ Exclude OSXUniversal: 1
24
+ Exclude Win: 1
25
+ Exclude Win64: 1
26
+ - first:
27
+ Any:
28
+ second:
29
+ enabled: 0
30
+ settings: {}
31
+ - first:
32
+ Editor: Editor
33
+ second:
34
+ enabled: 0
35
+ settings:
36
+ CPU: AnyCPU
37
+ DefaultValueInitialized: true
38
+ OS: AnyOS
39
+ - first:
40
+ Standalone: Linux64
41
+ second:
42
+ enabled: 0
43
+ settings:
44
+ CPU: AnyCPU
45
+ - first:
46
+ Standalone: OSXUniversal
47
+ second:
48
+ enabled: 0
49
+ settings:
50
+ CPU: None
51
+ - first:
52
+ Standalone: Win
53
+ second:
54
+ enabled: 0
55
+ settings:
56
+ CPU: x86
57
+ - first:
58
+ Standalone: Win64
59
+ second:
60
+ enabled: 0
61
+ settings:
62
+ CPU: x86_64
63
+ - first:
64
+ Windows Store Apps: WindowsStoreApps
65
+ second:
66
+ enabled: 0
67
+ settings:
68
+ CPU: AnyCPU
69
+ userData:
70
+ assetBundleName:
71
+ assetBundleVariant:
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: 4272e6b69476a4b469ebd2f65090da2b
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,146 @@
1
+ #if UNITY_EDITOR
2
+
3
+ namespace DxMessaging.Editor
4
+ {
5
+ using System;
6
+ using System.Collections.Generic;
7
+ using System.IO;
8
+ using System.Linq;
9
+ using UnityEditor;
10
+ using UnityEngine;
11
+ using Object = UnityEngine.Object;
12
+
13
+ [InitializeOnLoad]
14
+ public static class SetupCscRsp
15
+ {
16
+ private static readonly string RspFilePath =
17
+ Path.Combine(Application.dataPath, "..", "csc.rsp").Replace("\\", "/");
18
+
19
+ private static readonly string AnalyzerPathRelative =
20
+ "Packages/com.wallstop-studios.dxmessaging/Editor/Analyzers/";
21
+
22
+ private static readonly string LibraryPathRelative =
23
+ "Library/PackageCache/com.wallstop-studios.dxmessaging/Editor/Analyzers/";
24
+
25
+ private static readonly string SourceGeneratorDllName = "WallstopStudios.DxMessaging.SourceGenerators.dll";
26
+
27
+ private static readonly string[] RequiredDllNames =
28
+ {
29
+ SourceGeneratorDllName,
30
+ "Microsoft.CodeAnalysis.dll",
31
+ "Microsoft.CodeAnalysis.CSharp.dll",
32
+ "System.Reflection.Metadata.dll"
33
+ };
34
+
35
+ private static readonly string LibraryArgument = $"-a:\"{LibraryPathRelative}\"";
36
+
37
+ static SetupCscRsp()
38
+ {
39
+ EditorApplication.delayCall += EnsureCscRsp;
40
+ EditorApplication.delayCall += EnsureDLLsExistInAssets;
41
+ }
42
+
43
+ private static void EnsureDLLsExistInAssets()
44
+ {
45
+ HashSet<string> dllNames = new();
46
+ foreach (string dllGuid in AssetDatabase.FindAssets("t:DefaultAsset", new[] { "Assets" }))
47
+ {
48
+ string dllPath = AssetDatabase.GUIDToAssetPath(dllGuid);
49
+ if (!dllPath.EndsWith(".dll"))
50
+ {
51
+ continue;
52
+ }
53
+
54
+ string dllName = Path.GetFileName(dllPath);
55
+ dllNames.Add(dllName);
56
+ }
57
+
58
+ string[] dllRelativeDirectories = { LibraryPathRelative, AnalyzerPathRelative };
59
+
60
+ bool anyFound = false;
61
+ foreach (string requiredDllName in RequiredDllNames.Where(dllName => !dllNames.Contains(dllName)))
62
+ {
63
+ bool found = false;
64
+ foreach (string relativeDirectory in dllRelativeDirectories)
65
+ {
66
+ try
67
+ {
68
+ string sourceFile = $"{relativeDirectory}{requiredDllName}";
69
+ if (!File.Exists(sourceFile))
70
+ {
71
+ continue;
72
+ }
73
+
74
+ const string pluginsDirectory = "Assets/Plugins/WallstopStudios.DxMessaging/";
75
+ string outputAsset = $"{pluginsDirectory}{requiredDllName}";
76
+ Directory.CreateDirectory(pluginsDirectory);
77
+ if (!File.Exists(outputAsset))
78
+ {
79
+ File.Copy($"{relativeDirectory}{requiredDllName}", outputAsset);
80
+ AssetDatabase.ImportAsset(outputAsset);
81
+ found = true;
82
+ }
83
+
84
+ if (requiredDllName == SourceGeneratorDllName)
85
+ {
86
+ Object loadedDll = AssetDatabase.LoadMainAssetAtPath(outputAsset);
87
+ AssetDatabase.SetLabels(loadedDll, new[] { "RoslynAnalyzer" });
88
+ }
89
+
90
+ PluginImporter importer = AssetImporter.GetAtPath(outputAsset) as PluginImporter;
91
+ if (importer != null)
92
+ {
93
+ importer.SetCompatibleWithAnyPlatform(false);
94
+ importer.SetExcludeFromAnyPlatform("Editor", false);
95
+ importer.SetExcludeFromAnyPlatform("Standalone", false);
96
+ importer.SaveAndReimport();
97
+ }
98
+
99
+ break;
100
+ }
101
+ catch (Exception e)
102
+ {
103
+ Debug.LogError($"Failed to copy {requiredDllName} to Assets, failed with {e}.");
104
+ }
105
+ }
106
+
107
+ anyFound |= found;
108
+ Debug.Log(
109
+ $"Missing required dll '{requiredDllName}', " +
110
+ $"{(found ? "creation successful." : "WARNING! Manual creation required.")}");
111
+ }
112
+
113
+ if (anyFound)
114
+ {
115
+ AssetDatabase.Refresh();
116
+ }
117
+ }
118
+
119
+ private static void EnsureCscRsp()
120
+ {
121
+ try
122
+ {
123
+ if (!File.Exists(RspFilePath))
124
+ {
125
+ File.WriteAllText(RspFilePath, string.Empty);
126
+ AssetDatabase.ImportAsset("csc.rsp");
127
+ }
128
+
129
+ string rspContent = File.ReadAllText(RspFilePath);
130
+ if (rspContent.Contains(LibraryArgument))
131
+ {
132
+ return;
133
+ }
134
+
135
+ File.AppendAllText(RspFilePath, $"{LibraryArgument}\n");
136
+ AssetDatabase.ImportAsset("csc.rsp");
137
+ Debug.Log("Updated csc.rsp.");
138
+ }
139
+ catch (IOException ex)
140
+ {
141
+ Debug.LogError($"Failed to modify csc.rsp: {ex}");
142
+ }
143
+ }
144
+ }
145
+ }
146
+ #endif
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 54bd01ff5fd34bbc9950a1c7230a15d8
3
+ timeCreated: 1730841461
@@ -0,0 +1,18 @@
1
+ {
2
+ "name": "WallstopStudios.DxMessaging.Editor",
3
+ "rootNamespace": "DxMessaging.Editor",
4
+ "references": [
5
+ "WallstopStudios.DxMessaging"
6
+ ],
7
+ "includePlatforms": [
8
+ "Editor"
9
+ ],
10
+ "excludePlatforms": [],
11
+ "allowUnsafeCode": false,
12
+ "overrideReferences": false,
13
+ "precompiledReferences": [],
14
+ "autoReferenced": true,
15
+ "defineConstraints": [],
16
+ "versionDefines": [],
17
+ "noEngineReferences": false
18
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 4be90ea11db262f43913b0e065a25c7f
3
+ AssemblyDefinitionImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
package/README.md CHANGED
@@ -17,12 +17,12 @@ This project has a dependency on my [`Unity Helpers`](https://github.com/wallsto
17
17
  DxMessaging is currently a bit slower (2-3x) than Unity's built in messaging solution (when running in Unity). [Source](./Tests/Runtime/Benchmarks/PerformanceTests.cs).
18
18
  | Message Tech | Operations / Second |
19
19
  | ------------ | ------------------- |
20
- | Unity | 1,908,539 |
21
- | DxMessaging (GameObject) - Normal | 729,221 |
22
- | DxMessaging (Component) - Normal | 740,140 |
23
- | DxMessaging (GameObject) - No-Copy | 720,678 |
24
- | DxMessaging (Component) - No-Copy | 754,243 |
25
- | DxMessaging (Untargeted) - No-Copy | 1,176,809 |
20
+ | Unity | 2,101,721 |
21
+ | DxMessaging (GameObject) - Normal | 889,760 |
22
+ | DxMessaging (Component) - Normal | 869,437 |
23
+ | DxMessaging (GameObject) - No-Copy | 871,880 |
24
+ | DxMessaging (Component) - No-Copy | 899,361 |
25
+ | DxMessaging (Untargeted) - No-Copy | 1,239,673 |
26
26
 
27
27
  # Functionality
28
28
  While not as fast, DxMessaging offers *additional functionality* as compared to Unity's messaging solution.
@@ -69,6 +69,43 @@ Please note, if you want to receive messages and inherit off of the `MessageAwar
69
69
 
70
70
  If you wish to use any of these methods in components that inherit from `MessageAwareComponent`, please make sure to have the overrides call the base methods, otherwise messaging *may break* or not work as expected.
71
71
 
72
+ ## Integration - Source Generators (v2 and above)
73
+ I'm piloting some new tech in version 2 of this library. Currently, if implementing any of the message interfaces, there will be boxing performed on the messages, if they are structs. This is due to the nature of default interface methods, which I was not aware of.
74
+
75
+ To get around this, I have updated both the Unity Helpers dependent package, as well as this package, to take advantage of Roslyn Source Generators.
76
+
77
+ Requirements:
78
+ 1. Use one of `DxTargetedMessage, DxBroadcastMessage, DxUntargetedMessage` depending on message requirement.
79
+ 2. Ensure that the struct or class is marked as `partial`.
80
+
81
+ To use:
82
+ ```csharp
83
+ [DxTargetedMessage]
84
+ public partial struct SimpleTargetedMessage // No longer needed : ITargetedMessage<SimpleTargetedMessage>
85
+ {
86
+ }
87
+
88
+ [DxBroadcastMessage]
89
+ public partial struct SimpleBroadcastMessage // No longer needed : IBroadcastMessage<SimpleBroadcastMessage>
90
+ {
91
+ }
92
+
93
+ [DxUntargetedMessage]
94
+ public partial struct SimpleUntargetedMessage // No longer needed : IUntargetedMesssage<SimpleUntargetedMessage>
95
+ {
96
+ }
97
+ ```
98
+
99
+ Or, if you already have messages, you can leave the interface implementations as-is and get a no-boxing implementation with the `DxAutoMessageType` attribute. `partial` is still required.
100
+
101
+ To use:
102
+ ```csharp
103
+ [DxAutoMessageType]
104
+ public partial struct SimpleTargetedMessage : ITargetedMessage<SimpleTargetedMessage>
105
+ {
106
+ }
107
+ ```
108
+
72
109
  ## Integration
73
110
  See the [tests](./Tests/Runtime/Scripts/) directory for examples about how to integrate with the MessageAwareComponent. But, for some starters:
74
111
  ```csharp
@@ -0,0 +1,9 @@
1
+ namespace DxMessaging.Core.Attributes
2
+ {
3
+ using System;
4
+
5
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
6
+ public sealed class DxAutoMessageTypeAttribute : Attribute
7
+ {
8
+ }
9
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 01e2bf7a935a4389be6e63a79b36723e
3
+ timeCreated: 1730779085
@@ -0,0 +1,10 @@
1
+ namespace DxMessaging.Core.Attributes
2
+ {
3
+ using System;
4
+
5
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
6
+ public sealed class DxBroadcastMessageAttribute : Attribute
7
+ {
8
+
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 73fd653a34be4f36b5773dce342ae9fa
3
+ timeCreated: 1730779174
@@ -0,0 +1,10 @@
1
+ namespace DxMessaging.Core.Attributes
2
+ {
3
+ using System;
4
+
5
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
6
+ public sealed class DxTargetedMessageAttribute : Attribute
7
+ {
8
+
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: ab2509dd51f5467d95b4fca1cb794b29
3
+ timeCreated: 1730779159
@@ -0,0 +1,10 @@
1
+ namespace DxMessaging.Core.Attributes
2
+ {
3
+ using System;
4
+
5
+ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
6
+ public sealed class DxUntargetedMessageAttribute : Attribute
7
+ {
8
+
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: 418b461df3764ef6896dc86524a00132
3
+ timeCreated: 1730779131
@@ -0,0 +1,3 @@
1
+ fileFormatVersion: 2
2
+ guid: e2cb23a56cf1416ba06dccca58c8297f
3
+ timeCreated: 1730779055
@@ -1,18 +1,16 @@
1
- {
2
- "name": "WallstopStudios.DxMessaging",
3
- "rootNamespace": "DxMessaging",
4
- "references": [],
5
- "includePlatforms": [],
6
- "excludePlatforms": [],
7
- "allowUnsafeCode": false,
8
- "overrideReferences": true,
9
- "precompiledReferences": [
10
- "System.Runtime.CompilerServices.Unsafe.dll"
11
- ],
12
- "autoReferenced": true,
13
- "defineConstraints": [
14
- "UNITY_2017_1_OR_NEWER"
15
- ],
16
- "versionDefines": [],
17
- "noEngineReferences": false
1
+ {
2
+ "name": "WallstopStudios.DxMessaging",
3
+ "rootNamespace": "DxMessaging",
4
+ "references": [],
5
+ "includePlatforms": [],
6
+ "excludePlatforms": [],
7
+ "allowUnsafeCode": false,
8
+ "overrideReferences": false,
9
+ "precompiledReferences": [
10
+ "System.Runtime.CompilerServices.Unsafe.dll"
11
+ ],
12
+ "autoReferenced": true,
13
+ "defineConstraints": [],
14
+ "versionDefines": [],
15
+ "noEngineReferences": false
18
16
  }
@@ -1,7 +1,7 @@
1
- fileFormatVersion: 2
2
- guid: 184635fd03dde55408891bd932619c81
3
- AssemblyDefinitionImporter:
4
- externalObjects: {}
5
- userData:
6
- assetBundleName:
7
- assetBundleVariant:
1
+ fileFormatVersion: 2
2
+ guid: 184635fd03dde55408891bd932619c81
3
+ AssemblyDefinitionImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,75 @@
1
+ namespace WallstopStudios.DxMessaging.SourceGenerators;
2
+
3
+ using System.Collections.Generic;
4
+ using System.Linq;
5
+ using System.Text;
6
+ using Microsoft.CodeAnalysis;
7
+ using Microsoft.CodeAnalysis.CSharp;
8
+ using Microsoft.CodeAnalysis.CSharp.Syntax;
9
+ using Microsoft.CodeAnalysis.Text;
10
+
11
+ [Generator]
12
+ public sealed class DxAutoMessageTypeGenerator : ISourceGenerator
13
+ {
14
+ public void Initialize(GeneratorInitializationContext context)
15
+ {
16
+ context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
17
+ }
18
+
19
+ public void Execute(GeneratorExecutionContext context)
20
+ {
21
+ if (context.SyntaxReceiver is not SyntaxReceiver receiver)
22
+ {
23
+ return;
24
+ }
25
+
26
+ INamedTypeSymbol attributeSymbol = context.Compilation.GetTypeByMetadataName("DxMessaging.Core.Attributes.DxAutoMessageTypeAttribute");
27
+
28
+ foreach (TypeDeclarationSyntax classDeclaration in receiver.CandidateClasses)
29
+ {
30
+ SemanticModel model = context.Compilation.GetSemanticModel(classDeclaration.SyntaxTree);
31
+ ISymbol classSymbol = ModelExtensions.GetDeclaredSymbol(model, classDeclaration);
32
+
33
+ if (classSymbol.GetAttributes().Any(
34
+ attributeData => attributeData.AttributeClass.Equals(
35
+ attributeSymbol, SymbolEqualityComparer.Default)))
36
+ {
37
+ string namespaceName = classSymbol.ContainingNamespace.ToDisplayString();
38
+ string className = classSymbol.Name;
39
+ string typeKind = classDeclaration.Kind() == SyntaxKind.ClassDeclaration ? "class" : "struct";
40
+
41
+ string source = $$"""
42
+
43
+ namespace {{namespaceName}}
44
+ {
45
+ public partial {{typeKind}} {{className}}
46
+ {
47
+ public System.Type MessageType => typeof({{className}});
48
+ }
49
+ }
50
+
51
+ """;
52
+
53
+ context.AddSource($"{className}_DxAutoMessageType.g.cs", SourceText.From(source, Encoding.UTF8));
54
+ }
55
+ }
56
+ }
57
+
58
+ private sealed class SyntaxReceiver : ISyntaxReceiver
59
+ {
60
+ public List<TypeDeclarationSyntax> CandidateClasses { get; } = [];
61
+
62
+ public void OnVisitSyntaxNode(SyntaxNode syntaxNode)
63
+ {
64
+ if (syntaxNode is TypeDeclarationSyntax typeDeclarationSyntax)
65
+ {
66
+ if (typeDeclarationSyntax.AttributeLists.Count > 0 &&
67
+ (typeDeclarationSyntax.Kind() == SyntaxKind.ClassDeclaration ||
68
+ typeDeclarationSyntax.Kind() == SyntaxKind.StructDeclaration))
69
+ {
70
+ CandidateClasses.Add(typeDeclarationSyntax);
71
+ }
72
+ }
73
+ }
74
+ }
75
+ }
@@ -0,0 +1,11 @@
1
+ fileFormatVersion: 2
2
+ guid: f6d3fd5024b56ce48b255e4d9b802b3b
3
+ MonoImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 2
6
+ defaultReferences: []
7
+ executionOrder: 0
8
+ icon: {instanceID: 0}
9
+ userData:
10
+ assetBundleName:
11
+ assetBundleVariant: