Skip to content

Commit fe31ad0

Browse files
AlanLiu90JoC0de
andauthored
Support for nuget package with multiple Roslyn version analyzers in CLI (#706)
* Support for nuget package with multiple Roslyn version analyzers in CLI * only add label if asset is supported + reformat code --------- Co-authored-by: JoC0de <53140583+JoC0de@users.noreply.github.com>
1 parent 36d3260 commit fe31ad0

File tree

4 files changed

+130
-84
lines changed

4 files changed

+130
-84
lines changed

src/NuGetForUnity.Cli/Program.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Text;
88
using NugetForUnity;
99
using NugetForUnity.Configuration;
10+
using NugetForUnity.Helper;
1011
using UnityEngine;
1112

1213
namespace NuGetForUnity.Cli
@@ -97,14 +98,20 @@ private static void FixRoslynAnalyzerImportSettings()
9798
continue;
9899
}
99100

101+
var isSupportedRoslynAnalyzer = AnalyzerHelper.ShouldEnableRoslynAnalyzer(analyzerDllPath);
102+
var labelsForAsset = isSupportedRoslynAnalyzer ?
103+
"""
104+
labels:
105+
- RoslynAnalyzer
106+
""" :
107+
"labels: []";
100108
utf8NoBom ??= new UTF8Encoding(false);
101109
File.WriteAllText(
102110
analyzerDllMetaPath,
103111
$"""
104112
fileFormatVersion: 2
105113
guid: {Guid.NewGuid():N}
106-
labels:
107-
- RoslynAnalyzer
114+
{labelsForAsset}
108115
PluginImporter:
109116
platformData:
110117
- first:
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
using System;
2+
using System.IO;
3+
using System.Linq;
4+
using JetBrains.Annotations;
5+
using NugetForUnity.Models;
6+
7+
namespace NugetForUnity.Helper
8+
{
9+
/// <summary>
10+
/// Helper class for analyzers.
11+
/// </summary>
12+
internal static class AnalyzerHelper
13+
{
14+
/// <summary>
15+
/// Folder used to store Roslyn-Analyzers inside NuGet packages.
16+
/// </summary>
17+
private const string AnalyzersFolderName = "analyzers";
18+
19+
/// <summary>
20+
/// Name of the root folder containing dotnet analyzers.
21+
/// </summary>
22+
private static readonly string AnalyzersRoslynVersionsFolderName = Path.Combine(AnalyzersFolderName, "dotnet");
23+
24+
/// <summary>
25+
/// Prefix for the path of dll's of roslyn analyzers.
26+
/// </summary>
27+
private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Combine(AnalyzersRoslynVersionsFolderName, "roslyn");
28+
29+
/// <summary>
30+
/// Determine if "RoslynAnalyzer" label should be added to an analyzer
31+
/// </summary>
32+
/// <param name="path">The path to the analyzer</param>
33+
/// <returns>True if the label should be added, false otherwise.</returns>
34+
public static bool ShouldEnableRoslynAnalyzer(string path)
35+
{
36+
// The nuget package can contain analyzers for multiple Roslyn versions.
37+
// In that case, for the same package, the most recent version must be chosen out of those available for the current Unity version.
38+
var assetPath = Path.GetFullPath(path);
39+
var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(assetPath);
40+
if (assetRoslynVersion != null)
41+
{
42+
var maxSupportedRoslynVersion = GetMaxSupportedRoslynVersion();
43+
if (maxSupportedRoslynVersion == null)
44+
{
45+
// the current unity version doesn't support roslyn analyzers
46+
return false;
47+
}
48+
49+
var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal);
50+
var analyzerVersionsRootDirectoryPath = Path.Combine(assetPath.Substring(0, versionPrefixIndex), AnalyzersRoslynVersionsFolderName);
51+
var analyzersFolders = Directory.EnumerateDirectories(analyzerVersionsRootDirectoryPath);
52+
var allEnabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath)
53+
.Where(version => version != null && version.CompareTo(maxSupportedRoslynVersion) <= 0)
54+
.ToArray();
55+
56+
// If most recent valid analyzers exist elsewhere, don't add label `RoslynAnalyzer`
57+
var maxMatchingVersion = allEnabledRoslynVersions.Max();
58+
if (!allEnabledRoslynVersions.Contains(assetRoslynVersion) || assetRoslynVersion < maxMatchingVersion)
59+
{
60+
return false;
61+
}
62+
}
63+
64+
return true;
65+
}
66+
67+
[CanBeNull]
68+
private static NugetPackageVersion GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath)
69+
{
70+
var versionPrefixStartIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal);
71+
if (versionPrefixStartIndex < 0)
72+
{
73+
return null;
74+
}
75+
76+
var versionStartIndex = versionPrefixStartIndex + AnalyzersRoslynVersionSubFolderPrefix.Length;
77+
var separatorIndex = analyzerAssetPath.IndexOf(Path.DirectorySeparatorChar, versionStartIndex);
78+
var versionLength = separatorIndex >= 0 ? separatorIndex - versionStartIndex : analyzerAssetPath.Length - versionStartIndex;
79+
var versionString = analyzerAssetPath.Substring(versionStartIndex, versionLength);
80+
return string.IsNullOrEmpty(versionString) ? null : new NugetPackageVersion(versionString);
81+
}
82+
83+
[CanBeNull]
84+
private static NugetPackageVersion GetMaxSupportedRoslynVersion()
85+
{
86+
var unityVersion = UnityVersion.Current;
87+
if (unityVersion >= new UnityVersion(2022, 3, 12, 'f', 1))
88+
{
89+
return new NugetPackageVersion("4.3.0");
90+
}
91+
92+
if (unityVersion >= new UnityVersion(2022, 2, 1, 'f', 1))
93+
{
94+
return new NugetPackageVersion("4.1.0");
95+
}
96+
97+
if (unityVersion >= new UnityVersion(2021, 2, 1, 'f', 1))
98+
{
99+
return new NugetPackageVersion("3.8.0");
100+
}
101+
102+
return null;
103+
}
104+
}
105+
}

src/NuGetForUnity/Editor/Helper/AnalyzerHelper.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/NuGetForUnity/Editor/NugetAssetPostprocessor.cs

Lines changed: 5 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using JetBrains.Annotations;
99
using NugetForUnity.Configuration;
1010
using NugetForUnity.Helper;
11-
using NugetForUnity.Models;
1211
using UnityEditor;
1312
using UnityEngine;
1413
using Object = UnityEngine.Object;
@@ -51,16 +50,6 @@ public class NugetAssetPostprocessor : AssetPostprocessor
5150
/// </summary>
5251
private const string RoslynAnalyzerLabel = "RoslynAnalyzer";
5352

54-
/// <summary>
55-
/// Name of the root folder containing dotnet analyzers.
56-
/// </summary>
57-
private static readonly string AnalyzersRoslynVersionsFolderName = Path.Combine(AnalyzersFolderName, "dotnet");
58-
59-
/// <summary>
60-
/// Prefix for the path of dll's of roslyn analyzers.
61-
/// </summary>
62-
private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Combine(AnalyzersRoslynVersionsFolderName, "roslyn");
63-
6453
private static readonly List<BuildTarget> NonObsoleteBuildTargets = typeof(BuildTarget).GetFields(BindingFlags.Public | BindingFlags.Static)
6554
.Where(fieldInfo => fieldInfo.GetCustomAttribute(typeof(ObsoleteAttribute)) == null)
6655
.Select(fieldInfo => (BuildTarget)fieldInfo.GetValue(null))
@@ -280,44 +269,6 @@ private static string GetNuGetRepositoryPath()
280269
return ConfigurationManager.NugetConfigFile.RepositoryPath + Path.DirectorySeparatorChar;
281270
}
282271

283-
[CanBeNull]
284-
private static NugetPackageVersion GetMaxSupportedRoslynVersion()
285-
{
286-
var unityVersion = UnityVersion.Current;
287-
if (unityVersion >= new UnityVersion(2022, 3, 12, 'f', 1))
288-
{
289-
return new NugetPackageVersion("4.3.0");
290-
}
291-
292-
if (unityVersion >= new UnityVersion(2022, 2, 1, 'f', 1))
293-
{
294-
return new NugetPackageVersion("4.1.0");
295-
}
296-
297-
if (unityVersion >= new UnityVersion(2021, 2, 1, 'f', 1))
298-
{
299-
return new NugetPackageVersion("3.8.0");
300-
}
301-
302-
return null;
303-
}
304-
305-
[CanBeNull]
306-
private static NugetPackageVersion GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath)
307-
{
308-
var versionPrefixStartIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal);
309-
if (versionPrefixStartIndex < 0)
310-
{
311-
return null;
312-
}
313-
314-
var versionStartIndex = versionPrefixStartIndex + AnalyzersRoslynVersionSubFolderPrefix.Length;
315-
var separatorIndex = analyzerAssetPath.IndexOf(Path.DirectorySeparatorChar, versionStartIndex);
316-
var versionLength = separatorIndex >= 0 ? separatorIndex - versionStartIndex : analyzerAssetPath.Length - versionStartIndex;
317-
var versionString = analyzerAssetPath.Substring(versionStartIndex, versionLength);
318-
return string.IsNullOrEmpty(versionString) ? null : new NugetPackageVersion(versionString);
319-
}
320-
321272
private static string[] ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImporter plugin)
322273
{
323274
plugin.SetCompatibleWithAnyPlatform(false);
@@ -327,42 +278,14 @@ private static string[] ModifyImportSettingsOfRoslynAnalyzer([NotNull] PluginImp
327278
plugin.SetExcludeFromAnyPlatform(platform, false);
328279
}
329280

330-
var enableRoslynAnalyzer = true;
331-
332-
// The nuget package can contain analyzers for multiple Roslyn versions.
333-
// In that case, for the same package, the most recent version must be chosen out of those available for the current Unity version.
334-
var assetPath = Path.GetFullPath(plugin.assetPath);
335-
var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(assetPath);
336-
if (assetRoslynVersion != null)
281+
var enableRoslynAnalyzer = AnalyzerHelper.ShouldEnableRoslynAnalyzer(plugin.assetPath);
282+
if (enableRoslynAnalyzer)
337283
{
338-
var maxSupportedRoslynVersion = GetMaxSupportedRoslynVersion();
339-
if (maxSupportedRoslynVersion == null)
340-
{
341-
// the current unity version doesn't support roslyn analyzers
342-
enableRoslynAnalyzer = false;
343-
}
344-
else
345-
{
346-
var versionPrefixIndex = assetPath.IndexOf(AnalyzersRoslynVersionsFolderName, StringComparison.Ordinal);
347-
var analyzerVersionsRootDirectoryPath = Path.Combine(
348-
assetPath.Substring(0, versionPrefixIndex),
349-
AnalyzersRoslynVersionsFolderName);
350-
var analyzersFolders = Directory.EnumerateDirectories(analyzerVersionsRootDirectoryPath);
351-
var allEnabledRoslynVersions = analyzersFolders.Select(GetRoslynVersionNumberFromAnalyzerPath)
352-
.Where(version => version != null && version.CompareTo(maxSupportedRoslynVersion) <= 0)
353-
.ToArray();
354-
355-
// If most recent valid analyzers exist elsewhere, don't add label `RoslynAnalyzer`
356-
var maxMatchingVersion = allEnabledRoslynVersions.Max();
357-
if (!allEnabledRoslynVersions.Contains(assetRoslynVersion) || assetRoslynVersion < maxMatchingVersion)
358-
{
359-
enableRoslynAnalyzer = false;
360-
}
361-
}
284+
NugetLogger.LogVerbose("Configured asset '{0}' as a Roslyn-Analyzer.", plugin.assetPath);
285+
return new[] { RoslynAnalyzerLabel, ProcessedLabel };
362286
}
363287

364-
NugetLogger.LogVerbose("Configured asset '{0}' as a Roslyn-Analyzer.", plugin.assetPath);
365-
return enableRoslynAnalyzer ? new[] { RoslynAnalyzerLabel, ProcessedLabel } : new[] { ProcessedLabel };
288+
return new[] { ProcessedLabel };
366289
}
367290

368291
private static string[] ModifyImportSettingsOfGeneralPlugin([NotNull] PackageConfig packageConfig, [NotNull] PluginImporter plugin)

0 commit comments

Comments
 (0)