From a1788f128db69da28e536a1b80ceac08ca0bcf91 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 18 Jan 2024 16:51:58 +0900 Subject: [PATCH 01/11] Support for nuget package with multiple Roslyn version analyzers --- .../Editor/NugetAssetPostprocessor.cs | 54 ++++++++++++++++++- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index 897c91a9..494b73db 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -36,6 +36,9 @@ public class NugetAssetPostprocessor : AssetPostprocessor /// private const string AnalyzersFolderName = "analyzers"; + private static readonly string AnalyzersRoslynVersionsFolderName = Path.Join("analyzers", "dotnet"); + private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Join("analyzers", "dotnet", "roslyn"); + /// /// Used to mark an asset as already processed by this class. /// @@ -142,7 +145,7 @@ internal static void OnPostprocessAllAssets( if (assetPathComponents.Length > 1 && assetPathComponents[1].Equals(AnalyzersFolderName, StringComparison.OrdinalIgnoreCase)) { - ModifyImportSettingsOfRoslynAnalyzer(plugin, reimport); + ModifyImportSettingsOfRoslynAnalyzer(plugin, assetPathComponents, reimport); yield return ("RoslynAnalyzer", projectRelativeAssetPath, ResultStatus.Success); yield break; @@ -180,7 +183,21 @@ private static string GetNuGetRepositoryPath() return ConfigurationManager.NugetConfigFile.RepositoryPath + Path.DirectorySeparatorChar; } - private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporter plugin, bool reimport) + [CanBeNull] + private static string GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath) + { + var versionPrefixIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal); + if (versionPrefixIndex < 0) + { + return null; + } + + return analyzerAssetPath.Substring(versionPrefixIndex + AnalyzersRoslynVersionSubFolderPrefix.Length) + .Split(Path.DirectorySeparatorChar) + .First(); + } + + private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporter plugin, string[] relativeRepositoryPathComponents, bool reimport) { plugin.SetCompatibleWithAnyPlatform(false); plugin.SetCompatibleWithEditor(false); @@ -191,6 +208,39 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte AssetDatabase.SetLabels(plugin, new[] { RoslynAnalyzerLabel, ProcessedLabel }); + // The nuget package can contain analyzers for multiple Roslyn versions. + // In that case, for the same package, the most recent version must be chosen out of those available for the current Unity version. + var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(plugin.assetPath); + if (assetRoslynVersion != null) + { + var versionPrefixIndex = plugin.assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); + var analyzersVersionsRoot = Path.Join(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); + var analyzersFolders = AssetDatabase.GetSubFolders(analyzersVersionsRoot); + + var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) + .Where(ver => + { +#if UNITY_2022_3_OR_NEWER // Up to Roslyn 4.3.0 + return string.CompareOrdinal(ver, "4.3.0") <= 0; +#elif UNITY_2022_2_OR_NEWER // Up to Roslyn 4.1.0 + return string.CompareOrdinal(ver, "4.1.0") <= 0; +#elif UNITY_2021_2_OR_NEWER // Up to Roslyn 4.1.0 + return string.CompareOrdinal(ver, "3.8.0") <= 0; +#else + return false; +#endif + }) + .ToArray(); + + // If most recent valid analyzers exist elsewhere, remove label `RoslynAnalyzer` + if (!enabledRoslynVersions.Contains(assetRoslynVersion) || + string.CompareOrdinal(assetRoslynVersion, enabledRoslynVersions.Max()) < 0) + { + AssetDatabase.SetLabels(plugin, new[] { ProcessedLabel }); + } + } + + if (reimport) { // Persist and reload the change to the meta file From 94c91b912e0a69bbc3f791258cf1f286892ec4d8 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 18 Jan 2024 17:37:38 +0900 Subject: [PATCH 02/11] Fix Roslyn 4.3.0 support for Unity versions .12f and later --- src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index 494b73db..b043076a 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -217,14 +217,15 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte var analyzersVersionsRoot = Path.Join(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); var analyzersFolders = AssetDatabase.GetSubFolders(analyzersVersionsRoot); - var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) + var enabledRoslynVersions = analyzersFolders + .Select(GetRoslynVersionNumberFromAnalyzerPath) .Where(ver => { -#if UNITY_2022_3_OR_NEWER // Up to Roslyn 4.3.0 +#if UNITY_2022_3_OR_NEWER && !UNITY_2022_3_1 && !UNITY_2022_3_2 && !UNITY_2022_3_3 && !UNITY_2022_3_3 && !UNITY_2022_3_4 && !UNITY_2022_3_5 && !UNITY_2022_3_6 && !UNITY_2022_3_7 && !UNITY_2022_3_8 && !UNITY_2022_3_9 && !UNITY_2022_3_10 && !UNITY_2022_3_11 return string.CompareOrdinal(ver, "4.3.0") <= 0; -#elif UNITY_2022_2_OR_NEWER // Up to Roslyn 4.1.0 +#elif UNITY_2022_2_OR_NEWER return string.CompareOrdinal(ver, "4.1.0") <= 0; -#elif UNITY_2021_2_OR_NEWER // Up to Roslyn 4.1.0 +#elif UNITY_2021_2_OR_NEWER return string.CompareOrdinal(ver, "3.8.0") <= 0; #else return false; From eb85acaeb85bb608404ec1944605632a7f59bfc0 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 18 Jan 2024 17:55:50 +0900 Subject: [PATCH 03/11] Add comments --- src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index b043076a..852379d2 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -36,8 +36,15 @@ public class NugetAssetPostprocessor : AssetPostprocessor /// private const string AnalyzersFolderName = "analyzers"; - private static readonly string AnalyzersRoslynVersionsFolderName = Path.Join("analyzers", "dotnet"); - private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Join("analyzers", "dotnet", "roslyn"); + /// + /// Folder of root before the version of analyzers was split. + /// + private static readonly string AnalyzersRoslynVersionsFolderName = Path.Join(AnalyzersFolderName, "dotnet"); + + /// + /// Prefix for roslyn versioning of dll asset path. + /// + private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Join(AnalyzersRoslynVersionsFolderName, "roslyn"); /// /// Used to mark an asset as already processed by this class. From 719a2965781305804937b76824c1545767cb43ea Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 18 Jan 2024 18:26:56 +0900 Subject: [PATCH 04/11] Fix compilation errors in netstandard2.0 --- src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index 852379d2..e71b3aa6 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -39,12 +39,12 @@ public class NugetAssetPostprocessor : AssetPostprocessor /// /// Folder of root before the version of analyzers was split. /// - private static readonly string AnalyzersRoslynVersionsFolderName = Path.Join(AnalyzersFolderName, "dotnet"); + private static readonly string AnalyzersRoslynVersionsFolderName = JoinPathComponents(AnalyzersFolderName, "dotnet"); /// /// Prefix for roslyn versioning of dll asset path. /// - private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Join(AnalyzersRoslynVersionsFolderName, "roslyn"); + private static readonly string AnalyzersRoslynVersionSubFolderPrefix = JoinPathComponents(AnalyzersRoslynVersionsFolderName, "roslyn"); /// /// Used to mark an asset as already processed by this class. @@ -173,6 +173,12 @@ private static string[] GetPathComponents([NotNull] string path) return path.Split(Path.DirectorySeparatorChar); } + [NotNull] + private static string JoinPathComponents([NotNull] params string[] pathComponents) + { + return string.Join(Path.DirectorySeparatorChar.ToString(), pathComponents); + } + private static bool AssetIsDllInsideNuGetRepository([NotNull] string absoluteAssetPath, [NotNull] string absoluteRepositoryPath) { return absoluteAssetPath.StartsWith(absoluteRepositoryPath, PathHelper.PathComparisonType) && @@ -221,7 +227,7 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte if (assetRoslynVersion != null) { var versionPrefixIndex = plugin.assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); - var analyzersVersionsRoot = Path.Join(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); + var analyzersVersionsRoot = JoinPathComponents(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); var analyzersFolders = AssetDatabase.GetSubFolders(analyzersVersionsRoot); var enabledRoslynVersions = analyzersFolders From 13333a348eef890e1459b5dcbe99697b41313e9a Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 18 Jan 2024 18:35:43 +0900 Subject: [PATCH 05/11] Add a check for null --- .../Editor/NugetAssetPostprocessor.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index e71b3aa6..48aec9d1 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -234,16 +234,20 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte .Select(GetRoslynVersionNumberFromAnalyzerPath) .Where(ver => { + if (ver == null) + { + return false; + } #if UNITY_2022_3_OR_NEWER && !UNITY_2022_3_1 && !UNITY_2022_3_2 && !UNITY_2022_3_3 && !UNITY_2022_3_3 && !UNITY_2022_3_4 && !UNITY_2022_3_5 && !UNITY_2022_3_6 && !UNITY_2022_3_7 && !UNITY_2022_3_8 && !UNITY_2022_3_9 && !UNITY_2022_3_10 && !UNITY_2022_3_11 - return string.CompareOrdinal(ver, "4.3.0") <= 0; + return string.CompareOrdinal(ver, "4.3.0") <= 0; #elif UNITY_2022_2_OR_NEWER - return string.CompareOrdinal(ver, "4.1.0") <= 0; + return string.CompareOrdinal(ver, "4.1.0") <= 0; #elif UNITY_2021_2_OR_NEWER - return string.CompareOrdinal(ver, "3.8.0") <= 0; + return string.CompareOrdinal(ver, "3.8.0") <= 0; #else - return false; + return false; #endif - }) + }) .ToArray(); // If most recent valid analyzers exist elsewhere, remove label `RoslynAnalyzer` From 7a75e128b30fa89db51bb01be3f622effffa3436 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Mon, 22 Jan 2024 19:48:49 +0900 Subject: [PATCH 06/11] Tweaks. reduced costly process and commonized code more --- .../Editor/NugetAssetPostprocessor.cs | 62 ++++++++----------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index 48aec9d1..ca3b092c 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -31,6 +31,17 @@ namespace NugetForUnity /// public class NugetAssetPostprocessor : AssetPostprocessor { + private const string MaxSupportedRoslynVersion = +#if UNITY_2022_3_OR_NEWER && !UNITY_2022_3_1 && !UNITY_2022_3_2 && !UNITY_2022_3_3 && !UNITY_2022_3_3 && !UNITY_2022_3_4 && !UNITY_2022_3_5 && !UNITY_2022_3_6 && !UNITY_2022_3_7 && !UNITY_2022_3_8 && !UNITY_2022_3_9 && !UNITY_2022_3_10 && !UNITY_2022_3_11 + "4.3.0"; +#elif UNITY_2022_2_OR_NEWER + "4.1.0"; +#elif UNITY_2021_2_OR_NEWER + "3.8.0"; +#else + ""; +#endif + /// /// Folder used to store Roslyn-Analyzers inside NuGet packages. /// @@ -39,12 +50,12 @@ public class NugetAssetPostprocessor : AssetPostprocessor /// /// Folder of root before the version of analyzers was split. /// - private static readonly string AnalyzersRoslynVersionsFolderName = JoinPathComponents(AnalyzersFolderName, "dotnet"); + private static readonly string AnalyzersRoslynVersionsFolderName = Path.Combine(AnalyzersFolderName, "dotnet"); /// /// Prefix for roslyn versioning of dll asset path. /// - private static readonly string AnalyzersRoslynVersionSubFolderPrefix = JoinPathComponents(AnalyzersRoslynVersionsFolderName, "roslyn"); + private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Combine(AnalyzersRoslynVersionsFolderName, "roslyn"); /// /// Used to mark an asset as already processed by this class. @@ -152,7 +163,7 @@ internal static void OnPostprocessAllAssets( if (assetPathComponents.Length > 1 && assetPathComponents[1].Equals(AnalyzersFolderName, StringComparison.OrdinalIgnoreCase)) { - ModifyImportSettingsOfRoslynAnalyzer(plugin, assetPathComponents, reimport); + ModifyImportSettingsOfRoslynAnalyzer(plugin, reimport); yield return ("RoslynAnalyzer", projectRelativeAssetPath, ResultStatus.Success); yield break; @@ -173,12 +184,6 @@ private static string[] GetPathComponents([NotNull] string path) return path.Split(Path.DirectorySeparatorChar); } - [NotNull] - private static string JoinPathComponents([NotNull] params string[] pathComponents) - { - return string.Join(Path.DirectorySeparatorChar.ToString(), pathComponents); - } - private static bool AssetIsDllInsideNuGetRepository([NotNull] string absoluteAssetPath, [NotNull] string absoluteRepositoryPath) { return absoluteAssetPath.StartsWith(absoluteRepositoryPath, PathHelper.PathComparisonType) && @@ -205,12 +210,13 @@ private static string GetRoslynVersionNumberFromAnalyzerPath(string analyzerAsse return null; } - return analyzerAssetPath.Substring(versionPrefixIndex + AnalyzersRoslynVersionSubFolderPrefix.Length) - .Split(Path.DirectorySeparatorChar) - .First(); + var startIndex = versionPrefixIndex + AnalyzersRoslynVersionSubFolderPrefix.Length; + var separatorIndex = analyzerAssetPath.IndexOf(Path.DirectorySeparatorChar, startIndex); + var length = separatorIndex >= 0 ? separatorIndex - startIndex : analyzerAssetPath.Length - startIndex; + return analyzerAssetPath.Substring(startIndex, length); } - private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporter plugin, string[] relativeRepositoryPathComponents, bool reimport) + private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporter plugin, bool reimport) { plugin.SetCompatibleWithAnyPlatform(false); plugin.SetCompatibleWithEditor(false); @@ -219,7 +225,7 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte plugin.SetExcludeFromAnyPlatform(platform, false); } - AssetDatabase.SetLabels(plugin, new[] { RoslynAnalyzerLabel, ProcessedLabel }); + var enableRoslynAnalyzer = true; // The nuget package can contain analyzers for multiple Roslyn versions. // In that case, for the same package, the most recent version must be chosen out of those available for the current Unity version. @@ -227,37 +233,21 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte if (assetRoslynVersion != null) { var versionPrefixIndex = plugin.assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); - var analyzersVersionsRoot = JoinPathComponents(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); + var analyzersVersionsRoot = Path.Combine(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); var analyzersFolders = AssetDatabase.GetSubFolders(analyzersVersionsRoot); - var enabledRoslynVersions = analyzersFolders - .Select(GetRoslynVersionNumberFromAnalyzerPath) - .Where(ver => - { - if (ver == null) - { - return false; - } -#if UNITY_2022_3_OR_NEWER && !UNITY_2022_3_1 && !UNITY_2022_3_2 && !UNITY_2022_3_3 && !UNITY_2022_3_3 && !UNITY_2022_3_4 && !UNITY_2022_3_5 && !UNITY_2022_3_6 && !UNITY_2022_3_7 && !UNITY_2022_3_8 && !UNITY_2022_3_9 && !UNITY_2022_3_10 && !UNITY_2022_3_11 - return string.CompareOrdinal(ver, "4.3.0") <= 0; -#elif UNITY_2022_2_OR_NEWER - return string.CompareOrdinal(ver, "4.1.0") <= 0; -#elif UNITY_2021_2_OR_NEWER - return string.CompareOrdinal(ver, "3.8.0") <= 0; -#else - return false; -#endif - }) + var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) + .Where(version => version != null && string.CompareOrdinal(version, MaxSupportedRoslynVersion) <= 0) .ToArray(); // If most recent valid analyzers exist elsewhere, remove label `RoslynAnalyzer` - if (!enabledRoslynVersions.Contains(assetRoslynVersion) || - string.CompareOrdinal(assetRoslynVersion, enabledRoslynVersions.Max()) < 0) + if (!enabledRoslynVersions.Contains(assetRoslynVersion) || string.CompareOrdinal(assetRoslynVersion, enabledRoslynVersions.Max()) < 0) { - AssetDatabase.SetLabels(plugin, new[] { ProcessedLabel }); + enableRoslynAnalyzer = false; } } + AssetDatabase.SetLabels(plugin, enableRoslynAnalyzer ? new[] { RoslynAnalyzerLabel, ProcessedLabel } : new[] { ProcessedLabel }); if (reimport) { From 4c66ceb130d0bc4dc371bb360b4fab09b34baebd Mon Sep 17 00:00:00 2001 From: hadashiA Date: Tue, 23 Jan 2024 09:29:43 +0900 Subject: [PATCH 07/11] Make sure asset path normalize to the system format --- src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index ca3b092c..e21249b3 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -229,10 +229,11 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte // The nuget package can contain analyzers for multiple Roslyn versions. // In that case, for the same package, the most recent version must be chosen out of those available for the current Unity version. - var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(plugin.assetPath); + var assetPath = Path.GetFullPath(plugin.assetPath); + var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(assetPath); if (assetRoslynVersion != null) { - var versionPrefixIndex = plugin.assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); + var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); var analyzersVersionsRoot = Path.Combine(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); var analyzersFolders = AssetDatabase.GetSubFolders(analyzersVersionsRoot); From 638c10a49e5bd8fc76849c1b272d25d0500caf98 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Mon, 29 Jan 2024 22:33:27 +0900 Subject: [PATCH 08/11] Fix problem with RoslynAnalyzer not coming when restarting Unity --- src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index e21249b3..e2f6de00 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -234,9 +234,8 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte if (assetRoslynVersion != null) { var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); - var analyzersVersionsRoot = Path.Combine(plugin.assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); - var analyzersFolders = AssetDatabase.GetSubFolders(analyzersVersionsRoot); - + var analyzersVersionsRoot = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); + var analyzersFolders = Directory.GetDirectories(analyzersVersionsRoot); var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) .Where(version => version != null && string.CompareOrdinal(version, MaxSupportedRoslynVersion) <= 0) .ToArray(); From 0adabedb7ff3105bc64561b676b97366afd4811a Mon Sep 17 00:00:00 2001 From: hadashiA Date: Wed, 14 Feb 2024 15:42:09 +0900 Subject: [PATCH 09/11] Use UnityVersion, NuGetPackageVersion --- .../Editor/Models/UnityVersion.cs | 148 ++++++++++++++++++ .../Editor/Models/UnityVersion.cs.meta | 3 + .../Editor/NugetAssetPostprocessor.cs | 44 ++++-- .../Editor/TargetFrameworkResolver.cs | 121 -------------- 4 files changed, 180 insertions(+), 136 deletions(-) create mode 100644 src/NuGetForUnity/Editor/Models/UnityVersion.cs create mode 100644 src/NuGetForUnity/Editor/Models/UnityVersion.cs.meta diff --git a/src/NuGetForUnity/Editor/Models/UnityVersion.cs b/src/NuGetForUnity/Editor/Models/UnityVersion.cs new file mode 100644 index 00000000..e743286c --- /dev/null +++ b/src/NuGetForUnity/Editor/Models/UnityVersion.cs @@ -0,0 +1,148 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.Globalization; +using System.Text.RegularExpressions; +using UnityEngine; + +namespace NugetForUnity.Models +{ + /// + /// Represents a unity version. + /// + internal readonly struct UnityVersion : IComparable + { + private readonly int build; + + private readonly int major; + + private readonly int minor; + + private readonly char release; + + private readonly int revision; + + /// + /// Initializes a new instance of the struct. + /// + /// Major version number. + /// Minor version number. + /// Revision number. + /// Release flag. If 'f', official release. If 'p' patch release. + /// Build number. + public UnityVersion(int major, int minor, int revision, char release, int build) + { + this.major = major; + this.minor = minor; + this.revision = revision; + this.release = release; + this.build = build; + } + + /// + /// Initializes a new instance of the struct. + /// + /// A string representation of Unity version. + /// Cannot parse version. + [SuppressMessage("ReSharper", "MemberCanBePrivate.Local", Justification = "Called by Unit Test.")] + public UnityVersion(string version) + { + var match = Regex.Match(version, @"(\d+)\.(\d+)\.(\d+)([fpba])(\d+)"); + if (!match.Success) + { + throw new ArgumentException("Invalid unity version"); + } + + major = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); + minor = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture); + revision = int.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture); + release = match.Groups[4].Value[0]; + build = int.Parse(match.Groups[5].Value, CultureInfo.InvariantCulture); + } + + /// + /// Gets current version from Application.unityVersion. + /// + [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Local", Justification = "Property setter needed for unit test")] + public static UnityVersion Current { get; private set; } = new UnityVersion(Application.unityVersion); + + public static bool operator <(UnityVersion left, UnityVersion right) + { + return left.CompareTo(right) < 0; + } + + public static bool operator <=(UnityVersion left, UnityVersion right) + { + return left.CompareTo(right) <= 0; + } + + public static bool operator >(UnityVersion left, UnityVersion right) + { + return left.CompareTo(right) > 0; + } + + public static bool operator >=(UnityVersion left, UnityVersion right) + { + return left.CompareTo(right) >= 0; + } + + public int CompareTo(UnityVersion other) + { + return Compare(this, other); + } + + private static int Compare(UnityVersion a, UnityVersion b) + { + if (a.major < b.major) + { + return -1; + } + + if (a.major > b.major) + { + return 1; + } + + if (a.minor < b.minor) + { + return -1; + } + + if (a.minor > b.minor) + { + return 1; + } + + if (a.revision < b.revision) + { + return -1; + } + + if (a.revision > b.revision) + { + return 1; + } + + if (a.release < b.release) + { + return -1; + } + + if (a.release > b.release) + { + return 1; + } + + if (a.build < b.build) + { + return -1; + } + + if (a.build > b.build) + { + return 1; + } + + return 0; + } + } +} diff --git a/src/NuGetForUnity/Editor/Models/UnityVersion.cs.meta b/src/NuGetForUnity/Editor/Models/UnityVersion.cs.meta new file mode 100644 index 00000000..49394ef0 --- /dev/null +++ b/src/NuGetForUnity/Editor/Models/UnityVersion.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 294ab99fe7354275bb1500695b816801 +timeCreated: 1707812879 \ No newline at end of file diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index e2f6de00..fa7d7b12 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -8,6 +8,7 @@ using JetBrains.Annotations; using NugetForUnity.Configuration; using NugetForUnity.Helper; +using NugetForUnity.Models; using UnityEditor; using UnityEngine; using Object = UnityEngine.Object; @@ -31,17 +32,6 @@ namespace NugetForUnity /// public class NugetAssetPostprocessor : AssetPostprocessor { - private const string MaxSupportedRoslynVersion = -#if UNITY_2022_3_OR_NEWER && !UNITY_2022_3_1 && !UNITY_2022_3_2 && !UNITY_2022_3_3 && !UNITY_2022_3_3 && !UNITY_2022_3_4 && !UNITY_2022_3_5 && !UNITY_2022_3_6 && !UNITY_2022_3_7 && !UNITY_2022_3_8 && !UNITY_2022_3_9 && !UNITY_2022_3_10 && !UNITY_2022_3_11 - "4.3.0"; -#elif UNITY_2022_2_OR_NEWER - "4.1.0"; -#elif UNITY_2021_2_OR_NEWER - "3.8.0"; -#else - ""; -#endif - /// /// Folder used to store Roslyn-Analyzers inside NuGet packages. /// @@ -202,7 +192,29 @@ private static string GetNuGetRepositoryPath() } [CanBeNull] - private static string GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath) + private static NugetPackageVersion GetMaxSupportedRoslynVersion() + { + var unityVersion = UnityVersion.Current; + if (unityVersion >= new UnityVersion(2022, 3, 12, 'f', 1)) + { + return new NugetPackageVersion("4.3.0"); + } + + if (unityVersion >= new UnityVersion(2022, 2, 1, 'f', 1)) + { + return new NugetPackageVersion("4.1.0"); + } + + if (unityVersion >= new UnityVersion(2021, 2, 1, 'f', 1)) + { + return new NugetPackageVersion("3.8.0"); + } + + return null; + } + + [CanBeNull] + private static NugetPackageVersion GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath) { var versionPrefixIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal); if (versionPrefixIndex < 0) @@ -213,7 +225,8 @@ private static string GetRoslynVersionNumberFromAnalyzerPath(string analyzerAsse var startIndex = versionPrefixIndex + AnalyzersRoslynVersionSubFolderPrefix.Length; var separatorIndex = analyzerAssetPath.IndexOf(Path.DirectorySeparatorChar, startIndex); var length = separatorIndex >= 0 ? separatorIndex - startIndex : analyzerAssetPath.Length - startIndex; - return analyzerAssetPath.Substring(startIndex, length); + var versionString = analyzerAssetPath.Substring(startIndex, length); + return string.IsNullOrEmpty(versionString) ? null : new NugetPackageVersion(versionString); } private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporter plugin, bool reimport) @@ -233,15 +246,16 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(assetPath); if (assetRoslynVersion != null) { + var maxSupportedRoslynVersion = GetMaxSupportedRoslynVersion(); var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); var analyzersVersionsRoot = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); var analyzersFolders = Directory.GetDirectories(analyzersVersionsRoot); var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) - .Where(version => version != null && string.CompareOrdinal(version, MaxSupportedRoslynVersion) <= 0) + .Where(version => version != null && version.CompareTo(maxSupportedRoslynVersion) <= 0) .ToArray(); // If most recent valid analyzers exist elsewhere, remove label `RoslynAnalyzer` - if (!enabledRoslynVersions.Contains(assetRoslynVersion) || string.CompareOrdinal(assetRoslynVersion, enabledRoslynVersions.Max()) < 0) + if (!enabledRoslynVersions.Contains(assetRoslynVersion) || assetRoslynVersion < enabledRoslynVersions.Max()) { enableRoslynAnalyzer = false; } diff --git a/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs b/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs index 6e734423..0ecbdd34 100644 --- a/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs +++ b/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs @@ -289,126 +289,5 @@ public TargetFrameworkSupport( public DotnetVersionCompatibilityLevel[] SupportedDotnetVersions { get; } } - - private readonly struct UnityVersion : IComparable - { - private readonly int build; - - private readonly int major; - - private readonly int minor; - - private readonly char release; - - private readonly int revision; - - public UnityVersion(int major, int minor, int revision, char release, int build) - { - this.major = major; - this.minor = minor; - this.revision = revision; - this.release = release; - this.build = build; - } - - [SuppressMessage("ReSharper", "MemberCanBePrivate.Local", Justification = "Called by Unit Test.")] - public UnityVersion(string version) - { - var match = Regex.Match(version, @"(\d+)\.(\d+)\.(\d+)([fpba])(\d+)"); - if (!match.Success) - { - throw new ArgumentException("Invalid unity version"); - } - - major = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture); - minor = int.Parse(match.Groups[2].Value, CultureInfo.InvariantCulture); - revision = int.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture); - release = match.Groups[4].Value[0]; - build = int.Parse(match.Groups[5].Value, CultureInfo.InvariantCulture); - } - - [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Local", Justification = "Property setter needed for unit test")] - public static UnityVersion Current { get; private set; } = new UnityVersion(Application.unityVersion); - - public static bool operator <(UnityVersion left, UnityVersion right) - { - return left.CompareTo(right) < 0; - } - - public static bool operator <=(UnityVersion left, UnityVersion right) - { - return left.CompareTo(right) <= 0; - } - - public static bool operator >(UnityVersion left, UnityVersion right) - { - return left.CompareTo(right) > 0; - } - - public static bool operator >=(UnityVersion left, UnityVersion right) - { - return left.CompareTo(right) >= 0; - } - - public int CompareTo(UnityVersion other) - { - return Compare(this, other); - } - - private static int Compare(UnityVersion a, UnityVersion b) - { - if (a.major < b.major) - { - return -1; - } - - if (a.major > b.major) - { - return 1; - } - - if (a.minor < b.minor) - { - return -1; - } - - if (a.minor > b.minor) - { - return 1; - } - - if (a.revision < b.revision) - { - return -1; - } - - if (a.revision > b.revision) - { - return 1; - } - - if (a.release < b.release) - { - return -1; - } - - if (a.release > b.release) - { - return 1; - } - - if (a.build < b.build) - { - return -1; - } - - if (a.build > b.build) - { - return 1; - } - - return 0; - } - } } } From 05e86fc5579f0f0613f36ff489b226894db40df2 Mon Sep 17 00:00:00 2001 From: JoC0de <53140583+JoC0de@users.noreply.github.com> Date: Sun, 3 Mar 2024 13:32:31 +0100 Subject: [PATCH 10/11] fix warnings + add missind documentation + format code --- .../Assets/Tests/Editor/NuGetTests.cs | 4 +- .../Editor/Models/UnityVersion.cs | 41 +++++++++++++++---- .../Editor/NugetAssetPostprocessor.cs | 34 +++++++-------- .../Editor/TargetFrameworkResolver.cs | 3 -- src/NuGetForUnity/Editor/Ui/NugetWindow.cs | 4 +- 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs b/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs index e05cf0dc..c259e65a 100644 --- a/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs +++ b/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs @@ -615,10 +615,10 @@ public void TryGetBestTargetFrameworkForCurrentSettingsTest( bool supportsNetStandard21, bool supportsNet48) { - var unityVersionType = typeof(TargetFrameworkResolver).GetNestedType("UnityVersion", BindingFlags.NonPublic); + var unityVersionType = typeof(UnityVersion); Assume.That(unityVersionType, Is.Not.Null); - var currentUnityVersionProperty = unityVersionType.GetProperty("Current", BindingFlags.Public | BindingFlags.Static); + var currentUnityVersionProperty = unityVersionType.GetProperty(nameof(UnityVersion.Current), BindingFlags.Public | BindingFlags.Static); Assume.That(currentUnityVersionProperty, Is.Not.Null); Assume.That(currentUnityVersionProperty.CanRead, Is.True); Assume.That(currentUnityVersionProperty.CanWrite, Is.True); diff --git a/src/NuGetForUnity/Editor/Models/UnityVersion.cs b/src/NuGetForUnity/Editor/Models/UnityVersion.cs index e743286c..1ec45e0b 100644 --- a/src/NuGetForUnity/Editor/Models/UnityVersion.cs +++ b/src/NuGetForUnity/Editor/Models/UnityVersion.cs @@ -7,7 +7,7 @@ namespace NugetForUnity.Models { /// - /// Represents a unity version. + /// Represents a unity version. /// internal readonly struct UnityVersion : IComparable { @@ -22,7 +22,7 @@ namespace NugetForUnity.Models private readonly int revision; /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// Major version number. /// Minor version number. @@ -39,7 +39,7 @@ public UnityVersion(int major, int minor, int revision, char release, int build) } /// - /// Initializes a new instance of the struct. + /// Initializes a new instance of the struct. /// /// A string representation of Unity version. /// Cannot parse version. @@ -65,32 +65,57 @@ public UnityVersion(string version) [SuppressMessage("ReSharper", "AutoPropertyCanBeMadeGetOnly.Local", Justification = "Property setter needed for unit test")] public static UnityVersion Current { get; private set; } = new UnityVersion(Application.unityVersion); - public static bool operator <(UnityVersion left, UnityVersion right) + /// + /// Checks to see if the left is less than the right. + /// + /// The first value to compare. + /// The second value to compare. + /// True if left is less than the right. + public static bool operator <(in UnityVersion left, in UnityVersion right) { return left.CompareTo(right) < 0; } - public static bool operator <=(UnityVersion left, UnityVersion right) + /// + /// Checks to see if the left is less than or equal to the right. + /// + /// The first value to compare. + /// The second value to compare. + /// True if left is less than or equal to the right. + public static bool operator <=(in UnityVersion left, in UnityVersion right) { return left.CompareTo(right) <= 0; } - public static bool operator >(UnityVersion left, UnityVersion right) + /// + /// Checks to see if the left is greater than the right. + /// + /// The first value to compare. + /// The second value to compare. + /// True if left is greater than the right. + public static bool operator >(in UnityVersion left, in UnityVersion right) { return left.CompareTo(right) > 0; } - public static bool operator >=(UnityVersion left, UnityVersion right) + /// + /// Checks to see if the left is greater than or equal to the right. + /// + /// The first value to compare. + /// The second value to compare. + /// True if left is greater than or equal to the right. + public static bool operator >=(in UnityVersion left, in UnityVersion right) { return left.CompareTo(right) >= 0; } + /// public int CompareTo(UnityVersion other) { return Compare(this, other); } - private static int Compare(UnityVersion a, UnityVersion b) + private static int Compare(in UnityVersion a, in UnityVersion b) { if (a.major < b.major) { diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index fa7d7b12..67312643 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -38,24 +38,24 @@ public class NugetAssetPostprocessor : AssetPostprocessor private const string AnalyzersFolderName = "analyzers"; /// - /// Folder of root before the version of analyzers was split. + /// Used to mark an asset as already processed by this class. /// - private static readonly string AnalyzersRoslynVersionsFolderName = Path.Combine(AnalyzersFolderName, "dotnet"); + private const string ProcessedLabel = "NuGetForUnity"; /// - /// Prefix for roslyn versioning of dll asset path. + /// Used to let unity know an asset is a Roslyn-Analyzer. /// - private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Combine(AnalyzersRoslynVersionsFolderName, "roslyn"); + private const string RoslynAnalyzerLabel = "RoslynAnalyzer"; /// - /// Used to mark an asset as already processed by this class. + /// Name of the root folder containing dotnet analyzers. /// - private const string ProcessedLabel = "NuGetForUnity"; + private static readonly string AnalyzersRoslynVersionsFolderName = Path.Combine(AnalyzersFolderName, "dotnet"); /// - /// Used to let unity know an asset is a Roslyn-Analyzer. + /// Prefix for the path of dll's of roslyn analyzers. /// - private const string RoslynAnalyzerLabel = "RoslynAnalyzer"; + private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Combine(AnalyzersRoslynVersionsFolderName, "roslyn"); private static readonly List NonObsoleteBuildTargets = typeof(BuildTarget).GetFields(BindingFlags.Public | BindingFlags.Static) .Where(fieldInfo => fieldInfo.GetCustomAttribute(typeof(ObsoleteAttribute)) == null) @@ -216,16 +216,16 @@ private static NugetPackageVersion GetMaxSupportedRoslynVersion() [CanBeNull] private static NugetPackageVersion GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath) { - var versionPrefixIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal); - if (versionPrefixIndex < 0) + var versionPrefixStartIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal); + if (versionPrefixStartIndex < 0) { return null; } - var startIndex = versionPrefixIndex + AnalyzersRoslynVersionSubFolderPrefix.Length; - var separatorIndex = analyzerAssetPath.IndexOf(Path.DirectorySeparatorChar, startIndex); - var length = separatorIndex >= 0 ? separatorIndex - startIndex : analyzerAssetPath.Length - startIndex; - var versionString = analyzerAssetPath.Substring(startIndex, length); + var versionStartIndex = versionPrefixStartIndex + AnalyzersRoslynVersionSubFolderPrefix.Length; + var separatorIndex = analyzerAssetPath.IndexOf(Path.DirectorySeparatorChar, versionStartIndex); + var versionLength = separatorIndex >= 0 ? separatorIndex - versionStartIndex : analyzerAssetPath.Length - versionStartIndex; + var versionString = analyzerAssetPath.Substring(versionStartIndex, versionLength); return string.IsNullOrEmpty(versionString) ? null : new NugetPackageVersion(versionString); } @@ -248,13 +248,13 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte { var maxSupportedRoslynVersion = GetMaxSupportedRoslynVersion(); var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); - var analyzersVersionsRoot = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); - var analyzersFolders = Directory.GetDirectories(analyzersVersionsRoot); + var analyzerVersionsRootDirectoryPath = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); + var analyzersFolders = Directory.EnumerateDirectories(analyzerVersionsRootDirectoryPath); var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) .Where(version => version != null && version.CompareTo(maxSupportedRoslynVersion) <= 0) .ToArray(); - // If most recent valid analyzers exist elsewhere, remove label `RoslynAnalyzer` + // If most recent valid analyzers exist elsewhere, don't add label `RoslynAnalyzer` if (!enabledRoslynVersions.Contains(assetRoslynVersion) || assetRoslynVersion < enabledRoslynVersions.Max()) { enableRoslynAnalyzer = false; diff --git a/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs b/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs index 0ecbdd34..70fa8102 100644 --- a/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs +++ b/src/NuGetForUnity/Editor/TargetFrameworkResolver.cs @@ -6,13 +6,10 @@ using System; using System.Collections.Generic; -using System.Globalization; using System.Linq; -using System.Text.RegularExpressions; using JetBrains.Annotations; using NugetForUnity.Models; using UnityEditor; -using UnityEngine; #region No ReShaper diff --git a/src/NuGetForUnity/Editor/Ui/NugetWindow.cs b/src/NuGetForUnity/Editor/Ui/NugetWindow.cs index d0db9011..4c99cd48 100644 --- a/src/NuGetForUnity/Editor/Ui/NugetWindow.cs +++ b/src/NuGetForUnity/Editor/Ui/NugetWindow.cs @@ -1182,9 +1182,7 @@ private void DrawPackage(INugetPackage package, GUIStyle packageStyle, GUIStyle // Show the version selection dropdown only on Updates tab OR on Online tab if the package is not installed and not already in Unity if (currentTab == NugetWindowTab.UpdatesTab || - (currentTab == NugetWindowTab.OnlineTab && - installed == null && - !isAlreadyImportedInEngine)) + (currentTab == NugetWindowTab.OnlineTab && installed == null && !isAlreadyImportedInEngine)) { if (package.Versions.Count <= 1) { From dd3bc8cef41e1f6cc4e27819c0e4afdeb37bca70 Mon Sep 17 00:00:00 2001 From: JoC0de <53140583+JoC0de@users.noreply.github.com> Date: Sun, 3 Mar 2024 15:42:56 +0100 Subject: [PATCH 11/11] fix handeling of unity version that doesn't support roslyn analyzer + add unit test for package with multiple roslyn analyzers --- .../Assets/Tests/Editor/NuGetTests.cs | 79 +++++++++++++++++-- .../Editor/NugetAssetPostprocessor.cs | 27 ++++--- .../Editor/UnityPreImportedLibraryResolver.cs | 2 +- 3 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs b/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs index c259e65a..0e509fab 100644 --- a/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs +++ b/src/NuGetForUnity.Tests/Assets/Tests/Editor/NuGetTests.cs @@ -95,6 +95,13 @@ public void InstallRoslynAnalyzerTest([Values] InstallMode installMode) AssetDatabase.Refresh(); var path = $"Assets/Packages/{analyzer.Id}.{analyzer.Version}/analyzers/dotnet/cs/ErrorProne.NET.Core.dll"; var meta = (PluginImporter)AssetImporter.GetAtPath(path); + +#if UNITY_2022_3_OR_NEWER + // somehow unity doesn't import the .dll on newer unity version + var postprocessor = new NugetAssetPostprocessor() { assetPath = path }; + postprocessor.GetType().GetMethod("OnPreprocessAsset", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(postprocessor, null); +#endif + meta.SaveAndReimport(); AssetDatabase.Refresh(); @@ -107,8 +114,8 @@ public void InstallRoslynAnalyzerTest([Values] InstallMode installMode) // Verify analyzer dll import settings meta = AssetImporter.GetAtPath(path) as PluginImporter; Assert.IsNotNull(meta, "Get meta file"); - Assert.IsFalse(meta.GetCompatibleWithAnyPlatform(), "Not compatible any platform"); - Assert.IsFalse(meta.GetCompatibleWithEditor(), "Not compatible editor"); + Assert.IsFalse(meta.GetCompatibleWithAnyPlatform(), "Expected to have set compatible with any platform to false"); + Assert.IsFalse(meta.GetCompatibleWithEditor(), "Expected to have set compatible with editor to false"); foreach (var platform in Enum.GetValues(typeof(BuildTarget))) { Assert.IsFalse( @@ -130,6 +137,70 @@ public void InstallRoslynAnalyzerTest([Values] InstallMode installMode) } } + [Test] + [TestCase("2020.2.1f1", "")] + [TestCase("2021.2.1f1", "")] // no version selected because it only supports <= 3.8 + [TestCase("2022.2.1f1", "4.0")] + [TestCase("2022.3.12f1", "4.0")] + public void InstallRoslynAnalyzerWithMultipleVersionsTest(string unityVersion, string expectedEnabledRoslynAnalyzerVersion) + { + var jsonPackageId = new NugetPackageIdentifier("System.Text.Json", "7.0.1"); + var roslynAnalyzerVersions = new[] { "3.11", "4.0", "4.4" }; + + var unityVersionType = typeof(UnityVersion); + var currentUnityVersionProperty = unityVersionType.GetProperty(nameof(UnityVersion.Current), BindingFlags.Public | BindingFlags.Static); + Assume.That(currentUnityVersionProperty, Is.Not.Null); + Assume.That(currentUnityVersionProperty.CanRead, Is.True); + Assume.That(currentUnityVersionProperty.CanWrite, Is.True); + + var oldUnityVersion = currentUnityVersionProperty.GetValue(null); + try + { + currentUnityVersionProperty.SetValue(null, new UnityVersion(unityVersion)); + NugetPackageInstaller.InstallIdentifier(jsonPackageId); + AssetDatabase.Refresh(); + + foreach (var roslynAnalyzerVersion in roslynAnalyzerVersions) + { + var path = $"Assets/Packages/{jsonPackageId.Id}.{jsonPackageId.Version}/analyzers/dotnet/roslyn{roslynAnalyzerVersion}/cs/System.Text.Json.SourceGeneration.dll"; + Assert.That(path, Does.Exist.IgnoreDirectories); + var meta = (PluginImporter)AssetImporter.GetAtPath(path); + meta.SaveAndReimport(); + +#if UNITY_2022_3_OR_NEWER + // somehow unity doesn't import the .dll on newer unity version + var postprocessor = new NugetAssetPostprocessor() { assetPath = path }; + postprocessor.GetType().GetMethod("OnPreprocessAsset", BindingFlags.NonPublic | BindingFlags.Instance).Invoke(postprocessor, null); +#endif + } + + AssetDatabase.Refresh(); + + foreach (var roslynAnalyzerVersion in roslynAnalyzerVersions) + { + var path = $"Assets/Packages/{jsonPackageId.Id}.{jsonPackageId.Version}/analyzers/dotnet/roslyn{roslynAnalyzerVersion}/cs/System.Text.Json.SourceGeneration.dll"; + Assert.That(path, Does.Exist.IgnoreDirectories); + var meta = (PluginImporter)AssetImporter.GetAtPath(path); + Assert.IsNotNull(meta, "Get meta file"); + Assert.That(AssetDatabase.GetLabels(meta), Does.Contain("NuGetForUnity")); + Assert.IsFalse(meta.GetCompatibleWithAnyPlatform(), "Expected to have set compatible with any platform to false"); + Assert.IsFalse(meta.GetCompatibleWithEditor(), "Expected to have set compatible with editor to false"); + if (roslynAnalyzerVersion == expectedEnabledRoslynAnalyzerVersion) + { + Assert.That(AssetDatabase.GetLabels(meta), Does.Contain("RoslynAnalyzer"), $"DLL of Roslyn analyzer version '{roslynAnalyzerVersion}' should have 'RoslynAnalyzer' label"); + } + else + { + Assert.That(AssetDatabase.GetLabels(meta), Does.Not.Contain("RoslynAnalyzer"), $"DLL of Roslyn analyzer version '{roslynAnalyzerVersion}' should not have 'RoslynAnalyzer' label"); + } + } + } + finally + { + currentUnityVersionProperty.SetValue(null, oldUnityVersion); + } + } + [Test] public void InstallProtobufTest([Values] InstallMode installMode) { @@ -616,8 +687,6 @@ public void TryGetBestTargetFrameworkForCurrentSettingsTest( bool supportsNet48) { var unityVersionType = typeof(UnityVersion); - Assume.That(unityVersionType, Is.Not.Null); - var currentUnityVersionProperty = unityVersionType.GetProperty(nameof(UnityVersion.Current), BindingFlags.Public | BindingFlags.Static); Assume.That(currentUnityVersionProperty, Is.Not.Null); Assume.That(currentUnityVersionProperty.CanRead, Is.True); @@ -635,7 +704,7 @@ public void TryGetBestTargetFrameworkForCurrentSettingsTest( try { - currentUnityVersionProperty.SetValue(null, Activator.CreateInstance(unityVersionType, unityVersion)); + currentUnityVersionProperty.SetValue(null, new UnityVersion(unityVersion)); var expectedCompatibilityLevel = useNetStandard ? ApiCompatibilityLevel.NET_Standard_2_0 : ApiCompatibilityLevel.NET_4_6; currentBuildTargetApiCompatibilityLevelProperty.SetValue(null, new Lazy(() => expectedCompatibilityLevel)); diff --git a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs index 67312643..7e9d546a 100644 --- a/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs +++ b/src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs @@ -247,18 +247,27 @@ private static void ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporte if (assetRoslynVersion != null) { var maxSupportedRoslynVersion = GetMaxSupportedRoslynVersion(); - var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); - var analyzerVersionsRootDirectoryPath = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); - var analyzersFolders = Directory.EnumerateDirectories(analyzerVersionsRootDirectoryPath); - var enabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) - .Where(version => version != null && version.CompareTo(maxSupportedRoslynVersion) <= 0) - .ToArray(); - - // If most recent valid analyzers exist elsewhere, don't add label `RoslynAnalyzer` - if (!enabledRoslynVersions.Contains(assetRoslynVersion) || assetRoslynVersion < enabledRoslynVersions.Max()) + if (maxSupportedRoslynVersion == null) { + // the current unity version doesn't support roslyn analyzers enableRoslynAnalyzer = false; } + else + { + var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal); + var analyzerVersionsRootDirectoryPath = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName); + var analyzersFolders = Directory.EnumerateDirectories(analyzerVersionsRootDirectoryPath); + var allEnabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath) + .Where(version => version != null && version.CompareTo(maxSupportedRoslynVersion) <= 0) + .ToArray(); + + // If most recent valid analyzers exist elsewhere, don't add label `RoslynAnalyzer` + var maxMatchingVersion = allEnabledRoslynVersions.Max(); + if (!allEnabledRoslynVersions.Contains(assetRoslynVersion) || assetRoslynVersion < maxMatchingVersion) + { + enableRoslynAnalyzer = false; + } + } } AssetDatabase.SetLabels(plugin, enableRoslynAnalyzer ? new[] { RoslynAnalyzerLabel, ProcessedLabel } : new[] { ProcessedLabel }); diff --git a/src/NuGetForUnity/Editor/UnityPreImportedLibraryResolver.cs b/src/NuGetForUnity/Editor/UnityPreImportedLibraryResolver.cs index f67a082c..378668c7 100644 --- a/src/NuGetForUnity/Editor/UnityPreImportedLibraryResolver.cs +++ b/src/NuGetForUnity/Editor/UnityPreImportedLibraryResolver.cs @@ -39,7 +39,7 @@ internal static HashSet GetAlreadyImportedEditorOnlyLibraries() /// /// Check if a package is already imported in the Unity project e.g. is a part of Unity. /// - /// The package of witch the identifier is checked. + /// The package identifier witch is checked. /// Whether to log a message with the result of the check. /// If it is included in Unity. internal static bool IsAlreadyImportedInEngine([NotNull] string packageId, bool log = true)