com.wallstop-studios.dxmessaging 3.0.1 → 3.2.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 +497 -2
- package/Editor/Analyzers/BaseCallLogMessageParser.cs.meta +3 -3
- package/Editor/Analyzers/BaseCallReportAggregator.cs.meta +3 -3
- package/Editor/Analyzers/DxMessagingConsoleHarvester.cs +69 -62
- package/Editor/Analyzers/DxMessagingConsoleHarvester.cs.meta +3 -3
- package/Editor/AssemblyInfo.cs.meta +9 -1
- package/Editor/CustomEditors/MessageAwareComponentFallbackEditor.cs.meta +3 -3
- package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs +24 -15
- package/Editor/CustomEditors/MessageAwareComponentInspectorOverlay.cs.meta +3 -3
- 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/DxMessagingMenu.cs.meta +3 -3
- package/Editor/DxMessagingSceneBuildProcessor.cs.meta +3 -3
- package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs +137 -15
- package/Editor/Settings/DxMessagingBaseCallIgnoreSync.cs.meta +3 -3
- 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 +539 -304
- 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/{Editor → Runtime}/Analyzers/Microsoft.CodeAnalysis.CSharp.dll.meta +3 -3
- package/{Editor → Runtime}/Analyzers/Microsoft.CodeAnalysis.dll.meta +3 -3
- package/{Editor → Runtime}/Analyzers/System.Collections.Immutable.dll.meta +3 -3
- package/{Editor → Runtime}/Analyzers/System.Reflection.Metadata.dll.meta +3 -3
- package/{Editor → Runtime}/Analyzers/System.Runtime.CompilerServices.Unsafe.dll.meta +3 -3
- package/Runtime/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll +0 -0
- package/Runtime/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll.meta +46 -0
- package/Runtime/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/{Editor → Runtime}/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll.meta +2 -2
- package/Runtime/Analyzers.meta +8 -0
- 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/DxIgnoreMissingBaseCallAttribute.cs.meta +3 -3
- 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/DxMessagingStaticState.cs.meta +3 -3
- 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/MessageBusExtensions.cs.meta +3 -3
- package/Runtime/Core/Extensions/MessageExtensions.cs +0 -60
- package/Runtime/Core/Extensions/MessageExtensions.cs.meta +3 -3
- package/Runtime/Core/Helper/MessageCache.cs.meta +9 -1
- package/Runtime/Core/Helper/MessageHelperIndexer.cs.meta +9 -1
- package/Runtime/Core/IMessage.cs.meta +3 -3
- package/Runtime/Core/InstanceId.cs +25 -1
- package/Runtime/Core/InstanceId.cs.meta +3 -3
- 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 +47 -21
- package/Runtime/Core/MessageBus/DiagnosticsTarget.cs.meta +3 -3
- package/Runtime/Core/MessageBus/GlobalMessageBusProvider.cs.meta +3 -3
- package/Runtime/Core/MessageBus/IMessageBus.cs +75 -40
- package/Runtime/Core/MessageBus/IMessageBus.cs.meta +3 -3
- package/Runtime/Core/MessageBus/IMessageBusProvider.cs.meta +3 -3
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs +1 -0
- package/Runtime/Core/MessageBus/IMessageRegistrationBuilder.cs.meta +3 -3
- package/Runtime/Core/MessageBus/Internal/BusSlots.cs +7 -6
- package/Runtime/Core/MessageBus/MessageBus.cs +2864 -3413
- package/Runtime/Core/MessageBus/MessageBus.cs.meta +3 -3
- package/Runtime/Core/MessageBus/MessageBusRebindMode.cs.meta +3 -3
- package/Runtime/Core/MessageBus/MessageBusRegistration.cs +207 -0
- package/Runtime/Core/MessageBus/MessageBusRegistration.cs.meta +11 -0
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs +187 -14
- package/Runtime/Core/MessageBus/MessageRegistrationBuilder.cs.meta +3 -3
- package/Runtime/Core/MessageBus/MessagingRegistration.cs.meta +3 -3
- package/Runtime/Core/MessageBus/RegistrationLog.cs.meta +3 -3
- package/Runtime/Core/MessageHandler.cs +2206 -1510
- package/Runtime/Core/MessageHandler.cs.meta +3 -3
- package/Runtime/Core/MessageRegistrationHandle.cs.meta +3 -3
- package/Runtime/Core/MessageRegistrationToken.cs +1667 -812
- package/Runtime/Core/MessageRegistrationToken.cs.meta +3 -3
- package/Runtime/Core/Messages/GlobalStringMessage.cs.meta +9 -1
- package/Runtime/Core/Messages/IBroadcastMessage.cs.meta +3 -3
- package/Runtime/Core/Messages/ITargetedMessage.cs.meta +3 -3
- package/Runtime/Core/Messages/IUntargetedMessage.cs.meta +3 -3
- package/Runtime/Core/Messages/ReflexiveMessage.cs.meta +9 -1
- package/Runtime/Core/Messages/SourcedStringMessage.cs.meta +3 -3
- package/Runtime/Core/Messages/StringMessage.cs.meta +9 -1
- package/Runtime/Core/MessagingDebug.cs.meta +3 -3
- package/Runtime/Unity/CurrentGlobalMessageBusProvider.cs.meta +3 -3
- package/Runtime/Unity/DxMessagingRuntimeInitializer.cs.meta +3 -3
- package/Runtime/Unity/InitialGlobalMessageBusProvider.cs.meta +3 -3
- package/Runtime/Unity/Integrations/Reflex/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Unity/Integrations/Reflex/ReflexRegistrationInstaller.cs.meta +3 -3
- package/Runtime/Unity/Integrations/VContainer/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Unity/Integrations/VContainer/VContainerRegistrationExtensions.cs.meta +3 -3
- package/Runtime/Unity/Integrations/Zenject/AssemblyInfo.cs.meta +9 -1
- package/Runtime/Unity/Integrations/Zenject/ZenjectRegistrationInstaller.cs.meta +3 -3
- package/Runtime/Unity/MessageAwareComponent.cs +46 -1
- package/Runtime/Unity/MessageAwareComponent.cs.meta +3 -3
- package/Runtime/Unity/MessageBusProviderHandle.cs.meta +3 -3
- package/Runtime/Unity/MessagingComponent.cs +43 -10
- package/Runtime/Unity/MessagingComponent.cs.meta +3 -3
- package/Runtime/Unity/MessagingComponentInstaller.cs.meta +3 -3
- package/Runtime/Unity/ScriptableMessageBusProvider.cs.meta +3 -3
- package/Runtime/WallstopStudios.DxMessaging.asmdef +1 -1
- package/Samples~/DI/README.md +7 -7
- package/Samples~/DI/Reflex/SampleInstaller.cs.meta +3 -3
- package/Samples~/DI/VContainer/SampleLifetimeScope.cs.meta +3 -3
- package/Samples~/DI/Zenject/SampleInstaller.cs.meta +3 -3
- package/Samples~/Mini Combat/Boot.cs.meta +3 -3
- package/Samples~/Mini Combat/Enemy.cs.meta +3 -3
- package/Samples~/Mini Combat/Messages.cs.meta +3 -3
- package/Samples~/Mini Combat/Player.cs.meta +3 -3
- package/Samples~/Mini Combat/UIOverlay.cs.meta +3 -3
- package/Samples~/UI Buttons + Inspector/DiagnosticsEnabler.cs.meta +3 -3
- package/Samples~/UI Buttons + Inspector/Messages.cs.meta +3 -3
- package/Samples~/UI Buttons + Inspector/MessagingObserver.cs.meta +3 -3
- package/Samples~/UI Buttons + Inspector/UIButtonEmitter.cs.meta +3 -3
- package/SourceGenerators/Directory.Build.props +50 -3
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs +96 -63
- package/SourceGenerators/WallstopStudios.DxMessaging.SourceGenerators/DxAutoConstructorGenerator.cs.meta +3 -3
- 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 +40 -46
- package/SourceGenerators/global.json +7 -0
- package/SourceGenerators/global.json.meta +7 -0
- package/package.json +30 -40
- package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll +0 -0
- package/Editor/Analyzers/WallstopStudios.DxMessaging.Analyzer.dll.meta +0 -33
- package/Editor/Analyzers/WallstopStudios.DxMessaging.SourceGenerators.dll +0 -0
- package/Runtime/Core/Internal/TypedDispatchLinkIndex.cs +0 -51
- /package/{Editor → Runtime}/Analyzers/Microsoft.CodeAnalysis.CSharp.dll +0 -0
- /package/{Editor → Runtime}/Analyzers/Microsoft.CodeAnalysis.dll +0 -0
- /package/{Editor → Runtime}/Analyzers/System.Collections.Immutable.dll +0 -0
- /package/{Editor → Runtime}/Analyzers/System.Reflection.Metadata.dll +0 -0
- /package/{Editor → Runtime}/Analyzers/System.Runtime.CompilerServices.Unsafe.dll +0 -0
package/Editor/SetupCscRsp.cs
CHANGED
|
@@ -5,12 +5,9 @@ namespace DxMessaging.Editor
|
|
|
5
5
|
using System;
|
|
6
6
|
using System.Collections.Generic;
|
|
7
7
|
using System.IO;
|
|
8
|
-
using System.Linq;
|
|
9
|
-
using System.Security.Cryptography;
|
|
10
8
|
using DxMessaging.Editor.Settings;
|
|
11
9
|
using UnityEditor;
|
|
12
10
|
using UnityEngine;
|
|
13
|
-
using Object = UnityEngine.Object;
|
|
14
11
|
|
|
15
12
|
[InitializeOnLoad]
|
|
16
13
|
public static class SetupCscRsp
|
|
@@ -22,279 +19,297 @@ namespace DxMessaging.Editor
|
|
|
22
19
|
)
|
|
23
20
|
.Replace("\\", "/");
|
|
24
21
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
22
|
+
// Older package versions copied the analyzer + Roslyn runtime DLLs into the consumer
|
|
23
|
+
// project here so the source generator applied project-wide. The generator now ships
|
|
24
|
+
// under the package's Runtime/Analyzers folder (Unity scopes it natively to the runtime
|
|
25
|
+
// assembly and everything that references it, including the predefined Assembly-CSharp),
|
|
26
|
+
// so this in-project copy is redundant and is removed on upgrade.
|
|
27
|
+
internal const string LegacyAnalyzerCopyFolder =
|
|
28
|
+
"Assets/Plugins/Editor/WallstopStudios.DxMessaging";
|
|
30
29
|
|
|
31
|
-
private
|
|
30
|
+
private const string LegacySourceGeneratorDllName =
|
|
32
31
|
"WallstopStudios.DxMessaging.SourceGenerators.dll";
|
|
33
32
|
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
33
|
+
// Released 2.x legacy folders predate the companion analyzer DLL, so the source generator
|
|
34
|
+
// is the required package-owned marker. Unknown DLLs still make the folder unsafe.
|
|
35
|
+
private static readonly HashSet<string> RequiredLegacyAnalyzerCopyDlls = new(
|
|
36
|
+
StringComparer.OrdinalIgnoreCase
|
|
37
|
+
)
|
|
38
|
+
{
|
|
39
|
+
LegacySourceGeneratorDllName,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
private static readonly HashSet<string> KnownLegacyAnalyzerCopyDlls = new(
|
|
43
|
+
StringComparer.OrdinalIgnoreCase
|
|
44
|
+
)
|
|
45
45
|
{
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
LegacySourceGeneratorDllName,
|
|
47
|
+
"WallstopStudios.DxMessaging.Analyzer.dll",
|
|
48
48
|
"Microsoft.CodeAnalysis.dll",
|
|
49
49
|
"Microsoft.CodeAnalysis.CSharp.dll",
|
|
50
|
-
"System.
|
|
51
|
-
"System.Reflection.Metadata.dll",
|
|
52
|
-
"System.Runtime.CompilerServices.Unsafe.dll",
|
|
50
|
+
"System.Buffers.dll",
|
|
53
51
|
"System.Collections.Immutable.dll",
|
|
54
52
|
"System.Memory.dll",
|
|
55
|
-
"System.Buffers.dll",
|
|
56
|
-
"System.Threading.Tasks.Extensions.dll",
|
|
57
53
|
"System.Numerics.Vectors.dll",
|
|
54
|
+
"System.Reflection.Metadata.dll",
|
|
55
|
+
"System.Runtime.CompilerServices.Unsafe.dll",
|
|
58
56
|
"System.Text.Encoding.CodePages.dll",
|
|
57
|
+
"System.Text.Encodings.Web.dll",
|
|
58
|
+
"System.Threading.Tasks.Extensions.dll",
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
private static readonly HashSet<string> AnalyzerLabeledDllNames = new(
|
|
65
|
-
StringComparer.OrdinalIgnoreCase
|
|
66
|
-
)
|
|
61
|
+
private static bool loggedSkippedLegacyAnalyzerCopyCleanup;
|
|
62
|
+
|
|
63
|
+
static SetupCscRsp()
|
|
67
64
|
{
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
// Backstop only: the primary removal happens pre-compile in LegacyAnalyzerCopyCleanup.
|
|
66
|
+
// This catches projects whose legacy copy predates the upgrade and triggers no import.
|
|
67
|
+
ScheduleSetupStep(
|
|
68
|
+
() => TryRemoveLegacyAnalyzerCopy(),
|
|
69
|
+
"remove redundant in-project analyzer copy"
|
|
70
|
+
);
|
|
71
|
+
ScheduleSetupStep(EnsureCscRsp, "clean csc.rsp analyzer entries");
|
|
72
|
+
ScheduleAdditionalFileForIgnoreListSync();
|
|
73
|
+
}
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
internal static void ScheduleAdditionalFileForIgnoreListSync()
|
|
76
|
+
{
|
|
77
|
+
ScheduleSetupStep(
|
|
78
|
+
EnsureAdditionalFileForIgnoreList,
|
|
79
|
+
"sync csc.rsp base-call ignore additionalfile entry"
|
|
80
|
+
);
|
|
81
|
+
}
|
|
73
82
|
|
|
74
|
-
static
|
|
83
|
+
private static void ScheduleSetupStep(Action work, string description)
|
|
75
84
|
{
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
DxMessagingEditorIdle.ScheduleAssetDatabaseMutation(() =>
|
|
86
|
+
RunSetupStep(work, description)
|
|
87
|
+
);
|
|
79
88
|
}
|
|
80
89
|
|
|
81
|
-
private static void
|
|
90
|
+
private static void RunSetupStep(Action work, string description)
|
|
82
91
|
{
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
92
|
+
try
|
|
93
|
+
{
|
|
94
|
+
work();
|
|
95
|
+
}
|
|
96
|
+
catch (Exception ex)
|
|
97
|
+
{
|
|
98
|
+
DxMessagingEditorLog.LogError($"SetupCscRsp failed to {description}.", ex);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// <summary>
|
|
103
|
+
/// Deletes the redundant in-project analyzer copy that older package versions deployed to
|
|
104
|
+
/// <see cref="LegacyAnalyzerCopyFolder"/>. The source generator now ships under the
|
|
105
|
+
/// package's <c>Runtime/Analyzers</c> folder and applies automatically, so the copy is no
|
|
106
|
+
/// longer needed -- and, critically, leaving it in place makes BOTH copies generate into
|
|
107
|
+
/// every DxMessaging-referencing assembly, emitting each member twice (CS0102). Removing it
|
|
108
|
+
/// is therefore an upgrade requirement, not just cleanup.
|
|
109
|
+
/// </summary>
|
|
110
|
+
/// <remarks>
|
|
111
|
+
/// Called from <see cref="LegacyAnalyzerCopyCleanup"/> (an <c>AssetPostprocessor</c>) so the
|
|
112
|
+
/// removal lands during the asset import that PRECEDES script compilation -- before the two
|
|
113
|
+
/// copies can both feed the compiler -- and again from the <c>[InitializeOnLoad]</c> static
|
|
114
|
+
/// constructor as a post-compile backstop. Idempotent (a no-op once the folder is gone) and
|
|
115
|
+
/// conservative: it leaves the folder untouched if it holds anything other than the analyzer
|
|
116
|
+
/// DLLs this package deployed there. Returns <c>true</c> only when it actually deleted the
|
|
117
|
+
/// folder.
|
|
118
|
+
/// </remarks>
|
|
119
|
+
internal static bool TryRemoveLegacyAnalyzerCopy()
|
|
120
|
+
{
|
|
121
|
+
if (!AssetDatabase.IsValidFolder(LegacyAnalyzerCopyFolder))
|
|
122
|
+
{
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// The only shape this package ever created here is a flat set of analyzer / Roslyn
|
|
127
|
+
// DLLs plus their auto-generated .meta sidecars. Inspect the on-disk folder and bail
|
|
128
|
+
// out if a consumer repurposed it for anything else.
|
|
129
|
+
string absoluteFolder = Path.GetFullPath(
|
|
130
|
+
Path.Combine(Application.dataPath, "..", LegacyAnalyzerCopyFolder)
|
|
131
|
+
);
|
|
132
|
+
if (!Directory.Exists(absoluteFolder))
|
|
133
|
+
{
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// A real subdirectory means a consumer repurposed this folder for their own content;
|
|
138
|
+
// preserve it. The package only ever wrote a flat set of analyzer DLLs here, so the
|
|
139
|
+
// safe-to-remove check below sees only files (a subfolder named "x.dll" can never be
|
|
140
|
+
// mistaken for a DLL).
|
|
141
|
+
string[] files = Directory.GetFiles(absoluteFolder);
|
|
142
|
+
if (Directory.GetDirectories(absoluteFolder).Length > 0)
|
|
143
|
+
{
|
|
144
|
+
LogSkippedLegacyAnalyzerCopyCleanupIfNeeded(files);
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (!IsLegacyAnalyzerCopySafeToRemove(files))
|
|
149
|
+
{
|
|
150
|
+
LogSkippedLegacyAnalyzerCopyCleanupIfNeeded(files);
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (AssetDatabase.DeleteAsset(LegacyAnalyzerCopyFolder))
|
|
155
|
+
{
|
|
156
|
+
Debug.Log(
|
|
157
|
+
"DxMessaging: removed the redundant in-project analyzer copy at "
|
|
158
|
+
+ LegacyAnalyzerCopyFolder
|
|
159
|
+
+ ". The source generator now ships under the package's Runtime/Analyzers "
|
|
160
|
+
+ "folder and applies automatically; nothing needs to live under Assets."
|
|
161
|
+
);
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private static void LogSkippedLegacyAnalyzerCopyCleanupIfNeeded(IEnumerable<string> files)
|
|
169
|
+
{
|
|
170
|
+
if (
|
|
171
|
+
loggedSkippedLegacyAnalyzerCopyCleanup
|
|
172
|
+
|| !ContainsKnownLegacyAnalyzerCopyEntry(files)
|
|
86
173
|
)
|
|
87
174
|
{
|
|
88
|
-
|
|
89
|
-
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
loggedSkippedLegacyAnalyzerCopyCleanup = true;
|
|
179
|
+
Debug.LogWarning(
|
|
180
|
+
"DxMessaging: found a legacy in-project analyzer copy at "
|
|
181
|
+
+ LegacyAnalyzerCopyFolder
|
|
182
|
+
+ " but did not remove it because the folder contains content outside "
|
|
183
|
+
+ "the exact known package payload or is missing the required "
|
|
184
|
+
+ "DxMessaging source-generator DLL. Move consumer-owned files out of that folder, "
|
|
185
|
+
+ "then delete the stale DxMessaging analyzer DLLs manually to avoid "
|
|
186
|
+
+ "double-loading analyzers."
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/// <summary>
|
|
191
|
+
/// True when the legacy analyzer-copy folder contains the first-party source generator and
|
|
192
|
+
/// every entry is one of the exact analyzer/dependency DLLs this package deployed there or
|
|
193
|
+
/// a matching <c>.dll.meta</c> sidecar. A subfolder, a foreign DLL, or any other file makes
|
|
194
|
+
/// this false so the folder is preserved rather than deleted.
|
|
195
|
+
/// </summary>
|
|
196
|
+
internal static bool IsLegacyAnalyzerCopySafeToRemove(IEnumerable<string> folderEntries)
|
|
197
|
+
{
|
|
198
|
+
HashSet<string> presentRequiredDlls = new(StringComparer.OrdinalIgnoreCase);
|
|
199
|
+
HashSet<string> seenEntryNames = new(StringComparer.OrdinalIgnoreCase);
|
|
200
|
+
foreach (string entry in folderEntries ?? Array.Empty<string>())
|
|
201
|
+
{
|
|
202
|
+
if (string.IsNullOrEmpty(entry))
|
|
90
203
|
{
|
|
91
204
|
continue;
|
|
92
205
|
}
|
|
93
206
|
|
|
94
|
-
|
|
207
|
+
string name = GetLegacyAnalyzerCopyEntryName(entry);
|
|
208
|
+
if (string.IsNullOrEmpty(name) || !seenEntryNames.Add(name))
|
|
95
209
|
{
|
|
96
|
-
|
|
97
|
-
DllNames.Add(dllName);
|
|
210
|
+
return false;
|
|
98
211
|
}
|
|
99
|
-
}
|
|
100
212
|
|
|
101
|
-
|
|
102
|
-
{
|
|
103
|
-
if (DllNames.Contains(requiredDllName))
|
|
213
|
+
if (name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
|
104
214
|
{
|
|
215
|
+
if (!KnownLegacyAnalyzerCopyDlls.Contains(name))
|
|
216
|
+
{
|
|
217
|
+
return false;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
if (RequiredLegacyAnalyzerCopyDlls.Contains(name))
|
|
221
|
+
{
|
|
222
|
+
presentRequiredDlls.Add(name);
|
|
223
|
+
}
|
|
224
|
+
|
|
105
225
|
continue;
|
|
106
226
|
}
|
|
107
227
|
|
|
108
|
-
|
|
228
|
+
if (name.EndsWith(".dll.meta", StringComparison.OrdinalIgnoreCase))
|
|
109
229
|
{
|
|
110
|
-
|
|
230
|
+
string dllName = name.Substring(0, name.Length - ".meta".Length);
|
|
231
|
+
if (!KnownLegacyAnalyzerCopyDlls.Contains(dllName))
|
|
111
232
|
{
|
|
112
|
-
|
|
113
|
-
if (!File.Exists(sourceFile))
|
|
114
|
-
{
|
|
115
|
-
continue;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const string pluginsDirectory =
|
|
119
|
-
"Assets/Plugins/Editor/WallstopStudios.DxMessaging/";
|
|
120
|
-
string outputAsset = $"{pluginsDirectory}{requiredDllName}";
|
|
121
|
-
if (!Directory.Exists(pluginsDirectory))
|
|
122
|
-
{
|
|
123
|
-
Directory.CreateDirectory(pluginsDirectory);
|
|
124
|
-
AssetDatabase.Refresh();
|
|
125
|
-
}
|
|
126
|
-
bool needsCopy = FilesDiffer(sourceFile, outputAsset);
|
|
127
|
-
if (needsCopy)
|
|
128
|
-
{
|
|
129
|
-
File.Copy(sourceFile, outputAsset, true);
|
|
130
|
-
AssetDatabase.ImportAsset(outputAsset);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
if (AnalyzerLabeledDllNames.Contains(requiredDllName))
|
|
134
|
-
{
|
|
135
|
-
Object loadedDll = AssetDatabase.LoadMainAssetAtPath(outputAsset);
|
|
136
|
-
if (loadedDll != null)
|
|
137
|
-
{
|
|
138
|
-
string[] existingLabels = AssetDatabase.GetLabels(loadedDll);
|
|
139
|
-
if (!existingLabels.Contains("RoslynAnalyzer"))
|
|
140
|
-
{
|
|
141
|
-
List<string> newLabels = existingLabels.ToList();
|
|
142
|
-
newLabels.Add("RoslynAnalyzer");
|
|
143
|
-
AssetDatabase.SetLabels(loadedDll, newLabels.ToArray());
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
if (AssetImporter.GetAtPath(outputAsset) is PluginImporter importer)
|
|
149
|
-
{
|
|
150
|
-
bool importerDirty = false;
|
|
151
|
-
|
|
152
|
-
if (importer.GetCompatibleWithAnyPlatform())
|
|
153
|
-
{
|
|
154
|
-
importer.SetCompatibleWithAnyPlatform(false);
|
|
155
|
-
importerDirty = true;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (importer.GetExcludeFromAnyPlatform("Editor"))
|
|
159
|
-
{
|
|
160
|
-
importer.SetExcludeFromAnyPlatform("Editor", false);
|
|
161
|
-
importerDirty = true;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
if (!importer.GetExcludeFromAnyPlatform("Standalone"))
|
|
165
|
-
{
|
|
166
|
-
importer.SetExcludeFromAnyPlatform("Standalone", true);
|
|
167
|
-
importerDirty = true;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (importerDirty || needsCopy)
|
|
171
|
-
{
|
|
172
|
-
importer.SaveAndReimport();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
DllNames.Add(requiredDllName);
|
|
177
|
-
break;
|
|
178
|
-
}
|
|
179
|
-
catch (Exception e)
|
|
180
|
-
{
|
|
181
|
-
Debug.LogError(
|
|
182
|
-
$"Failed to copy {requiredDllName} to Assets, failed with {e}."
|
|
183
|
-
);
|
|
233
|
+
return false;
|
|
184
234
|
}
|
|
235
|
+
|
|
236
|
+
continue;
|
|
185
237
|
}
|
|
186
|
-
}
|
|
187
238
|
|
|
188
|
-
|
|
189
|
-
{
|
|
190
|
-
AssetDatabase.Refresh();
|
|
239
|
+
return false;
|
|
191
240
|
}
|
|
241
|
+
|
|
242
|
+
return presentRequiredDlls.Count == RequiredLegacyAnalyzerCopyDlls.Count;
|
|
192
243
|
}
|
|
193
244
|
|
|
194
|
-
private static
|
|
245
|
+
private static string GetLegacyAnalyzerCopyEntryName(string entry)
|
|
195
246
|
{
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
247
|
+
string normalizedEntry = entry.Replace("\\", "/");
|
|
248
|
+
int lastSeparator = normalizedEntry.LastIndexOf('/');
|
|
249
|
+
return lastSeparator >= 0
|
|
250
|
+
? normalizedEntry.Substring(lastSeparator + 1)
|
|
251
|
+
: normalizedEntry;
|
|
252
|
+
}
|
|
200
253
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
254
|
+
private static bool ContainsKnownLegacyAnalyzerCopyEntry(IEnumerable<string> folderEntries)
|
|
255
|
+
{
|
|
256
|
+
foreach (string entry in folderEntries ?? Array.Empty<string>())
|
|
204
257
|
{
|
|
205
|
-
|
|
258
|
+
if (string.IsNullOrEmpty(entry))
|
|
259
|
+
{
|
|
260
|
+
continue;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
string name = GetLegacyAnalyzerCopyEntryName(entry);
|
|
264
|
+
if (KnownLegacyAnalyzerCopyDlls.Contains(name))
|
|
265
|
+
{
|
|
266
|
+
return true;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (!name.EndsWith(".dll.meta", StringComparison.OrdinalIgnoreCase))
|
|
270
|
+
{
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
string dllName = name.Substring(0, name.Length - ".meta".Length);
|
|
275
|
+
if (KnownLegacyAnalyzerCopyDlls.Contains(dllName))
|
|
276
|
+
{
|
|
277
|
+
return true;
|
|
278
|
+
}
|
|
206
279
|
}
|
|
207
280
|
|
|
208
|
-
|
|
209
|
-
using FileStream destinationStream = File.OpenRead(destinationPath);
|
|
210
|
-
using SHA256 sha256 = SHA256.Create();
|
|
211
|
-
byte[] sourceHash = sha256.ComputeHash(sourceStream);
|
|
212
|
-
byte[] destinationHash = sha256.ComputeHash(destinationStream);
|
|
213
|
-
return !sourceHash.AsSpan().SequenceEqual(destinationHash);
|
|
281
|
+
return false;
|
|
214
282
|
}
|
|
215
283
|
|
|
216
284
|
/// <summary>
|
|
217
|
-
///
|
|
218
|
-
/// on-disk DLL roster.
|
|
285
|
+
/// Removes stale DxMessaging analyzer <c>-a:</c> entries from <c>csc.rsp</c>.
|
|
219
286
|
/// </summary>
|
|
287
|
+
/// <remarks>
|
|
288
|
+
/// DxMessaging analyzers are activated solely through the RoslynAnalyzer-labeled
|
|
289
|
+
/// DLLs shipped under the package's <c>Runtime/Analyzers</c> folder, which Unity
|
|
290
|
+
/// scopes to the runtime assembly and every assembly that references it (including
|
|
291
|
+
/// the predefined Assembly-CSharp). A stray <c>-a:</c> registration here (for
|
|
292
|
+
/// example, one left behind by an older package version that copied analyzers into
|
|
293
|
+
/// the project) double-loads the source generator, and registering dependency DLLs
|
|
294
|
+
/// as analyzers makes Unity's compiler path fragile, so this method strips them.
|
|
295
|
+
/// </remarks>
|
|
220
296
|
private static void EnsureCscRsp()
|
|
221
297
|
{
|
|
222
298
|
try
|
|
223
299
|
{
|
|
224
300
|
if (!File.Exists(RspFilePath))
|
|
225
301
|
{
|
|
226
|
-
|
|
227
|
-
AssetDatabase.ImportAsset("csc.rsp");
|
|
302
|
+
return;
|
|
228
303
|
}
|
|
229
304
|
|
|
230
305
|
string rspContent = File.ReadAllText(RspFilePath);
|
|
231
306
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
StringComparer.OrdinalIgnoreCase
|
|
307
|
+
string[] newLines = CleanDxMessagingAnalyzerLines(
|
|
308
|
+
rspContent.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries),
|
|
309
|
+
out bool foundStaleEntries
|
|
236
310
|
);
|
|
237
311
|
|
|
238
|
-
|
|
239
|
-
List<string> newLines = new();
|
|
240
|
-
bool foundStaleEntries = false;
|
|
241
|
-
|
|
242
|
-
foreach (
|
|
243
|
-
string line in rspContent.Split(
|
|
244
|
-
new[] { '\r', '\n' },
|
|
245
|
-
StringSplitOptions.RemoveEmptyEntries
|
|
246
|
-
)
|
|
247
|
-
)
|
|
248
|
-
{
|
|
249
|
-
string trimmedLine = line.Trim();
|
|
250
|
-
|
|
251
|
-
// Check if this is a DxMessaging analyzer line
|
|
252
|
-
bool isDxMessagingAnalyzer =
|
|
253
|
-
trimmedLine.StartsWith("-a:", StringComparison.OrdinalIgnoreCase)
|
|
254
|
-
&& (
|
|
255
|
-
trimmedLine.Contains(
|
|
256
|
-
"com.wallstop-studios.dxmessaging",
|
|
257
|
-
StringComparison.OrdinalIgnoreCase
|
|
258
|
-
)
|
|
259
|
-
|| trimmedLine.Contains(
|
|
260
|
-
"WallstopStudios.DxMessaging",
|
|
261
|
-
StringComparison.OrdinalIgnoreCase
|
|
262
|
-
)
|
|
263
|
-
);
|
|
264
|
-
|
|
265
|
-
if (isDxMessagingAnalyzer)
|
|
266
|
-
{
|
|
267
|
-
// Only keep if it's in the current valid set
|
|
268
|
-
if (currentAnalyzerArgs.Contains(trimmedLine))
|
|
269
|
-
{
|
|
270
|
-
newLines.Add(trimmedLine);
|
|
271
|
-
}
|
|
272
|
-
else
|
|
273
|
-
{
|
|
274
|
-
foundStaleEntries = true;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
else
|
|
278
|
-
{
|
|
279
|
-
// Keep all non-DxMessaging lines as-is
|
|
280
|
-
newLines.Add(trimmedLine);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Add any new analyzer arguments that aren't already present
|
|
285
|
-
bool foundNewEntries = false;
|
|
286
|
-
foreach (string analyzerArgument in currentAnalyzerArgs)
|
|
287
|
-
{
|
|
288
|
-
if (!newLines.Contains(analyzerArgument, StringComparer.OrdinalIgnoreCase))
|
|
289
|
-
{
|
|
290
|
-
newLines.Add(analyzerArgument);
|
|
291
|
-
foundNewEntries = true;
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
bool modified = foundStaleEntries || foundNewEntries;
|
|
296
|
-
|
|
297
|
-
if (modified)
|
|
312
|
+
if (foundStaleEntries)
|
|
298
313
|
{
|
|
299
314
|
// Write the cleaned up content
|
|
300
315
|
string newContent = string.Join(Environment.NewLine, newLines);
|
|
@@ -309,8 +324,77 @@ namespace DxMessaging.Editor
|
|
|
309
324
|
}
|
|
310
325
|
catch (IOException ex)
|
|
311
326
|
{
|
|
312
|
-
|
|
327
|
+
DxMessagingEditorLog.LogError("Failed to modify csc.rsp.", ex);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
internal static string[] CleanDxMessagingAnalyzerLines(
|
|
332
|
+
IEnumerable<string> lines,
|
|
333
|
+
out bool foundStaleEntries
|
|
334
|
+
)
|
|
335
|
+
{
|
|
336
|
+
List<string> newLines = new();
|
|
337
|
+
foundStaleEntries = false;
|
|
338
|
+
|
|
339
|
+
foreach (string line in lines ?? Array.Empty<string>())
|
|
340
|
+
{
|
|
341
|
+
string trimmedLine = line?.Trim();
|
|
342
|
+
if (string.IsNullOrEmpty(trimmedLine))
|
|
343
|
+
{
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (IsResponseFileComment(trimmedLine))
|
|
348
|
+
{
|
|
349
|
+
newLines.Add(trimmedLine);
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
List<string> retainedArguments = new();
|
|
354
|
+
bool removedFromLine = false;
|
|
355
|
+
foreach (string argument in SplitResponseFileArguments(trimmedLine))
|
|
356
|
+
{
|
|
357
|
+
if (IsDxMessagingAnalyzerArgument(argument))
|
|
358
|
+
{
|
|
359
|
+
foundStaleEntries = true;
|
|
360
|
+
removedFromLine = true;
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
retainedArguments.Add(argument);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (removedFromLine)
|
|
368
|
+
{
|
|
369
|
+
if (retainedArguments.Count > 0)
|
|
370
|
+
{
|
|
371
|
+
newLines.Add(string.Join(" ", retainedArguments));
|
|
372
|
+
}
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
newLines.Add(trimmedLine);
|
|
313
377
|
}
|
|
378
|
+
|
|
379
|
+
return newLines.ToArray();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
private static bool IsDxMessagingAnalyzerArgument(string trimmedLine)
|
|
383
|
+
{
|
|
384
|
+
return (
|
|
385
|
+
TryGetCompilerOptionValue(trimmedLine, "a", out string _)
|
|
386
|
+
|| TryGetCompilerOptionValue(trimmedLine, "analyzer", out string _)
|
|
387
|
+
)
|
|
388
|
+
&& (
|
|
389
|
+
trimmedLine.Contains(
|
|
390
|
+
"com.wallstop-studios.dxmessaging",
|
|
391
|
+
StringComparison.OrdinalIgnoreCase
|
|
392
|
+
)
|
|
393
|
+
|| trimmedLine.Contains(
|
|
394
|
+
"WallstopStudios.DxMessaging",
|
|
395
|
+
StringComparison.OrdinalIgnoreCase
|
|
396
|
+
)
|
|
397
|
+
);
|
|
314
398
|
}
|
|
315
399
|
|
|
316
400
|
/// <summary>
|
|
@@ -319,19 +403,14 @@ namespace DxMessaging.Editor
|
|
|
319
403
|
/// entries pointing at moved or deleted sidecar paths are removed.
|
|
320
404
|
/// </summary>
|
|
321
405
|
/// <remarks>
|
|
322
|
-
/// The sidecar is generated by <see cref="DxMessagingBaseCallIgnoreSync"
|
|
323
|
-
///
|
|
406
|
+
/// The sidecar is generated by <see cref="DxMessagingBaseCallIgnoreSync"/>. csc happily
|
|
407
|
+
/// runs without it, so this method does NOT auto-create; sidecar writes schedule this sync
|
|
408
|
+
/// again after deferred regeneration completes.
|
|
324
409
|
/// </remarks>
|
|
325
410
|
private static void EnsureAdditionalFileForIgnoreList()
|
|
326
411
|
{
|
|
327
412
|
try
|
|
328
413
|
{
|
|
329
|
-
if (!File.Exists(RspFilePath))
|
|
330
|
-
{
|
|
331
|
-
File.WriteAllText(RspFilePath, string.Empty);
|
|
332
|
-
AssetDatabase.ImportAsset("csc.rsp");
|
|
333
|
-
}
|
|
334
|
-
|
|
335
414
|
string sidecarRelativePath = DxMessagingBaseCallIgnoreSync.SidecarAssetPath;
|
|
336
415
|
string projectRoot = Path.GetFullPath(Path.Combine(Application.dataPath, ".."))
|
|
337
416
|
.Replace("\\", "/");
|
|
@@ -339,74 +418,28 @@ namespace DxMessaging.Editor
|
|
|
339
418
|
.Replace("\\", "/");
|
|
340
419
|
|
|
341
420
|
bool sidecarExists = File.Exists(sidecarAbsolutePath);
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
string rspContent = File.ReadAllText(RspFilePath);
|
|
345
|
-
List<string> newLines = new();
|
|
346
|
-
bool foundDesired = false;
|
|
347
|
-
bool foundStale = false;
|
|
348
|
-
|
|
349
|
-
foreach (
|
|
350
|
-
string line in rspContent.Split(
|
|
351
|
-
new[] { '\r', '\n' },
|
|
352
|
-
StringSplitOptions.RemoveEmptyEntries
|
|
353
|
-
)
|
|
354
|
-
)
|
|
421
|
+
if (!File.Exists(RspFilePath))
|
|
355
422
|
{
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
bool isDxMessagingAdditionalFile =
|
|
359
|
-
trimmedLine.StartsWith(
|
|
360
|
-
"-additionalfile:",
|
|
361
|
-
StringComparison.OrdinalIgnoreCase
|
|
362
|
-
)
|
|
363
|
-
&& trimmedLine.Contains("DxMessaging.", StringComparison.OrdinalIgnoreCase)
|
|
364
|
-
&& trimmedLine.Contains(
|
|
365
|
-
"BaseCallIgnore",
|
|
366
|
-
StringComparison.OrdinalIgnoreCase
|
|
367
|
-
);
|
|
368
|
-
|
|
369
|
-
if (isDxMessagingAdditionalFile)
|
|
423
|
+
if (!sidecarExists)
|
|
370
424
|
{
|
|
371
|
-
|
|
372
|
-
sidecarExists
|
|
373
|
-
&& string.Equals(
|
|
374
|
-
trimmedLine,
|
|
375
|
-
desiredLine,
|
|
376
|
-
StringComparison.OrdinalIgnoreCase
|
|
377
|
-
)
|
|
378
|
-
)
|
|
379
|
-
{
|
|
380
|
-
if (!foundDesired)
|
|
381
|
-
{
|
|
382
|
-
newLines.Add(trimmedLine);
|
|
383
|
-
foundDesired = true;
|
|
384
|
-
}
|
|
385
|
-
else
|
|
386
|
-
{
|
|
387
|
-
// Drop duplicate.
|
|
388
|
-
foundStale = true;
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
else
|
|
392
|
-
{
|
|
393
|
-
// Stale entry pointing at a moved/renamed/deleted sidecar; drop it.
|
|
394
|
-
foundStale = true;
|
|
395
|
-
}
|
|
425
|
+
return;
|
|
396
426
|
}
|
|
397
|
-
else
|
|
398
|
-
{
|
|
399
|
-
newLines.Add(trimmedLine);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
427
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
428
|
+
File.WriteAllText(
|
|
429
|
+
RspFilePath,
|
|
430
|
+
FormatAdditionalFileArgument(sidecarRelativePath) + Environment.NewLine
|
|
431
|
+
);
|
|
432
|
+
AssetDatabase.ImportAsset("csc.rsp");
|
|
433
|
+
Debug.Log("Updated csc.rsp additionalfile entries.");
|
|
434
|
+
return;
|
|
407
435
|
}
|
|
408
436
|
|
|
409
|
-
|
|
437
|
+
string[] newLines = SynchronizeAdditionalFileForIgnoreListLines(
|
|
438
|
+
File.ReadAllLines(RspFilePath),
|
|
439
|
+
sidecarRelativePath,
|
|
440
|
+
sidecarExists,
|
|
441
|
+
out bool modified
|
|
442
|
+
);
|
|
410
443
|
|
|
411
444
|
if (modified)
|
|
412
445
|
{
|
|
@@ -422,46 +455,248 @@ namespace DxMessaging.Editor
|
|
|
422
455
|
}
|
|
423
456
|
catch (IOException ex)
|
|
424
457
|
{
|
|
425
|
-
|
|
458
|
+
DxMessagingEditorLog.LogError("Failed to update csc.rsp additionalfile entry.", ex);
|
|
426
459
|
}
|
|
427
460
|
}
|
|
428
461
|
|
|
429
|
-
|
|
462
|
+
internal static string[] SynchronizeAdditionalFileForIgnoreListLines(
|
|
463
|
+
IEnumerable<string> lines,
|
|
464
|
+
string sidecarRelativePath,
|
|
465
|
+
bool sidecarExists,
|
|
466
|
+
out bool modified
|
|
467
|
+
)
|
|
430
468
|
{
|
|
431
|
-
|
|
432
|
-
string
|
|
469
|
+
string desiredLine = FormatAdditionalFileArgument(sidecarRelativePath);
|
|
470
|
+
List<string> newLines = new();
|
|
471
|
+
bool foundDesired = false;
|
|
472
|
+
bool foundStale = false;
|
|
433
473
|
|
|
434
|
-
foreach (string
|
|
474
|
+
foreach (string line in lines ?? Array.Empty<string>())
|
|
435
475
|
{
|
|
436
|
-
|
|
476
|
+
string trimmedLine = line?.Trim();
|
|
477
|
+
if (string.IsNullOrEmpty(trimmedLine))
|
|
437
478
|
{
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
479
|
+
continue;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
if (IsResponseFileComment(trimmedLine))
|
|
483
|
+
{
|
|
484
|
+
newLines.Add(trimmedLine);
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
441
487
|
|
|
442
|
-
|
|
443
|
-
|
|
488
|
+
List<string> retainedArguments = new();
|
|
489
|
+
bool removedFromLine = false;
|
|
490
|
+
foreach (string argument in SplitResponseFileArguments(trimmedLine))
|
|
491
|
+
{
|
|
492
|
+
if (!IsDxMessagingBaseCallIgnoreAdditionalFile(argument))
|
|
444
493
|
{
|
|
494
|
+
retainedArguments.Add(argument);
|
|
445
495
|
continue;
|
|
446
496
|
}
|
|
447
497
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
if (
|
|
498
|
+
bool isDesired =
|
|
499
|
+
sidecarExists
|
|
500
|
+
&& IsAdditionalFileArgumentForPath(argument, sidecarRelativePath);
|
|
501
|
+
if (!isDesired)
|
|
452
502
|
{
|
|
503
|
+
// Stale entry pointing at a moved/renamed/deleted sidecar; drop it.
|
|
504
|
+
foundStale = true;
|
|
505
|
+
removedFromLine = true;
|
|
453
506
|
continue;
|
|
454
507
|
}
|
|
455
508
|
|
|
456
|
-
|
|
457
|
-
if (!yielded.Add(normalizedRelativePath))
|
|
509
|
+
if (foundDesired)
|
|
458
510
|
{
|
|
511
|
+
// Drop duplicate.
|
|
512
|
+
foundStale = true;
|
|
513
|
+
removedFromLine = true;
|
|
459
514
|
continue;
|
|
460
515
|
}
|
|
461
516
|
|
|
462
|
-
|
|
517
|
+
retainedArguments.Add(desiredLine);
|
|
518
|
+
foundDesired = true;
|
|
519
|
+
if (!string.Equals(argument, desiredLine, StringComparison.Ordinal))
|
|
520
|
+
{
|
|
521
|
+
foundStale = true;
|
|
522
|
+
removedFromLine = true;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
if (retainedArguments.Count > 0)
|
|
527
|
+
{
|
|
528
|
+
newLines.Add(string.Join(" ", retainedArguments));
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (!removedFromLine)
|
|
533
|
+
{
|
|
534
|
+
newLines.Add(trimmedLine);
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
bool needsAppend = sidecarExists && !foundDesired;
|
|
539
|
+
if (needsAppend)
|
|
540
|
+
{
|
|
541
|
+
newLines.Add(desiredLine);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
modified = foundStale || needsAppend;
|
|
545
|
+
return newLines.ToArray();
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
private static string FormatAdditionalFileArgument(string sidecarRelativePath)
|
|
549
|
+
{
|
|
550
|
+
return $"-additionalfile:\"{sidecarRelativePath}\"";
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
private static bool IsResponseFileComment(string trimmedLine)
|
|
554
|
+
{
|
|
555
|
+
return trimmedLine.StartsWith("#", StringComparison.Ordinal);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
private static bool IsDxMessagingBaseCallIgnoreAdditionalFile(string trimmedLine)
|
|
559
|
+
{
|
|
560
|
+
return TryGetCompilerOptionValue(trimmedLine, "additionalfile", out string value)
|
|
561
|
+
&& value.Contains("DxMessaging.", StringComparison.OrdinalIgnoreCase)
|
|
562
|
+
&& value.Contains("BaseCallIgnore", StringComparison.OrdinalIgnoreCase);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
private static bool IsAdditionalFileArgumentForPath(
|
|
566
|
+
string argument,
|
|
567
|
+
string sidecarRelativePath
|
|
568
|
+
)
|
|
569
|
+
{
|
|
570
|
+
if (!TryGetCompilerOptionValue(argument, "additionalfile", out string value))
|
|
571
|
+
{
|
|
572
|
+
return false;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
string unquotedValue = UnquoteWholeArgument(value.Trim());
|
|
576
|
+
return string.Equals(
|
|
577
|
+
unquotedValue.Replace("\\", "/"),
|
|
578
|
+
sidecarRelativePath,
|
|
579
|
+
StringComparison.OrdinalIgnoreCase
|
|
580
|
+
);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
private static bool TryGetCompilerOptionValue(
|
|
584
|
+
string argument,
|
|
585
|
+
string optionName,
|
|
586
|
+
out string value
|
|
587
|
+
)
|
|
588
|
+
{
|
|
589
|
+
value = string.Empty;
|
|
590
|
+
if (string.IsNullOrEmpty(argument) || string.IsNullOrEmpty(optionName))
|
|
591
|
+
{
|
|
592
|
+
return false;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
string unquotedArgument = UnquoteWholeArgument(argument.Trim());
|
|
596
|
+
if (unquotedArgument.Length <= optionName.Length + 1)
|
|
597
|
+
{
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (unquotedArgument[0] != '-' && unquotedArgument[0] != '/')
|
|
602
|
+
{
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
if (unquotedArgument[optionName.Length + 1] != ':')
|
|
607
|
+
{
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
if (
|
|
612
|
+
string.Compare(
|
|
613
|
+
unquotedArgument,
|
|
614
|
+
1,
|
|
615
|
+
optionName,
|
|
616
|
+
0,
|
|
617
|
+
optionName.Length,
|
|
618
|
+
StringComparison.OrdinalIgnoreCase
|
|
619
|
+
) != 0
|
|
620
|
+
)
|
|
621
|
+
{
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
value = unquotedArgument.Substring(optionName.Length + 2);
|
|
626
|
+
return true;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
private static string UnquoteWholeArgument(string argument)
|
|
630
|
+
{
|
|
631
|
+
if (argument.Length >= 2 && argument[0] == '"' && argument[argument.Length - 1] == '"')
|
|
632
|
+
{
|
|
633
|
+
return argument.Substring(1, argument.Length - 2).Replace("\"\"", "\"");
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
return argument;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
private static List<string> SplitResponseFileArguments(string line)
|
|
640
|
+
{
|
|
641
|
+
List<string> arguments = new();
|
|
642
|
+
if (string.IsNullOrWhiteSpace(line))
|
|
643
|
+
{
|
|
644
|
+
return arguments;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
System.Text.StringBuilder current = new();
|
|
648
|
+
bool inQuotes = false;
|
|
649
|
+
foreach (char character in line)
|
|
650
|
+
{
|
|
651
|
+
if (character == '"')
|
|
652
|
+
{
|
|
653
|
+
inQuotes = !inQuotes;
|
|
654
|
+
current.Append(character);
|
|
655
|
+
continue;
|
|
463
656
|
}
|
|
657
|
+
|
|
658
|
+
if (char.IsWhiteSpace(character) && !inQuotes)
|
|
659
|
+
{
|
|
660
|
+
if (current.Length > 0)
|
|
661
|
+
{
|
|
662
|
+
arguments.Add(current.ToString());
|
|
663
|
+
current.Clear();
|
|
664
|
+
}
|
|
665
|
+
continue;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
current.Append(character);
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
if (current.Length > 0)
|
|
672
|
+
{
|
|
673
|
+
arguments.Add(current.ToString());
|
|
464
674
|
}
|
|
675
|
+
|
|
676
|
+
return arguments;
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/// <summary>
|
|
681
|
+
/// Removes the legacy in-project analyzer copy (via
|
|
682
|
+
/// <see cref="SetupCscRsp.TryRemoveLegacyAnalyzerCopy"/>) during the asset import that PRECEDES
|
|
683
|
+
/// script compilation. This is the primary upgrade path: deleting the redundant copy before the
|
|
684
|
+
/// compiler runs prevents it and the package's Runtime/Analyzers copy from both generating into
|
|
685
|
+
/// the same assembly (which would emit each member twice -- CS0102). It is a cheap no-op in the
|
|
686
|
+
/// steady state: once the folder is gone, <c>AssetDatabase.IsValidFolder</c> short-circuits on
|
|
687
|
+
/// every subsequent import.
|
|
688
|
+
/// </summary>
|
|
689
|
+
internal sealed class LegacyAnalyzerCopyCleanup : AssetPostprocessor
|
|
690
|
+
{
|
|
691
|
+
// Classic four-argument signature so this compiles on every supported Unity (2021.3+).
|
|
692
|
+
private static void OnPostprocessAllAssets(
|
|
693
|
+
string[] importedAssets,
|
|
694
|
+
string[] deletedAssets,
|
|
695
|
+
string[] movedAssets,
|
|
696
|
+
string[] movedFromAssetPaths
|
|
697
|
+
)
|
|
698
|
+
{
|
|
699
|
+
SetupCscRsp.TryRemoveLegacyAnalyzerCopy();
|
|
465
700
|
}
|
|
466
701
|
}
|
|
467
702
|
}
|