Files
2026-09-21 12:15:57 +03:00

106 lines
4.5 KiB
C#

using System;
using System.IO;
using System.Linq;
using JetBrains.Annotations;
using NugetForUnity.Models;
namespace NugetForUnity.Helper
{
/// <summary>
/// Helper class for analyzers.
/// </summary>
internal static class AnalyzerHelper
{
/// <summary>
/// Folder used to store Roslyn-Analyzers inside NuGet packages.
/// </summary>
private const string AnalyzersFolderName = "analyzers";
/// <summary>
/// Name of the root folder containing dotnet analyzers.
/// </summary>
private static readonly string AnalyzersRoslynVersionsFolderName = Path.Combine(AnalyzersFolderName, "dotnet");
/// <summary>
/// Prefix for the path of dll's of roslyn analyzers.
/// </summary>
private static readonly string AnalyzersRoslynVersionSubFolderPrefix = Path.Combine(AnalyzersRoslynVersionsFolderName, "roslyn");
/// <summary>
/// Determine if "RoslynAnalyzer" label should be added to an analyzer
/// </summary>
/// <param name="path">The path to the analyzer</param>
/// <returns>True if the label should be added, false otherwise.</returns>
public static bool ShouldEnableRoslynAnalyzer(string path)
{
// 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 assetPath = Path.GetFullPath(path);
var assetRoslynVersion = GetRoslynVersionNumberFromAnalyzerPath(assetPath);
if (assetRoslynVersion != null)
{
var maxSupportedRoslynVersion = GetMaxSupportedRoslynVersion();
if (maxSupportedRoslynVersion == null)
{
// the current unity version doesn't support roslyn analyzers
return false;
}
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)
{
return false;
}
}
return true;
}
[CanBeNull]
private static NugetPackageVersion GetRoslynVersionNumberFromAnalyzerPath(string analyzerAssetPath)
{
var versionPrefixStartIndex = analyzerAssetPath.IndexOf(AnalyzersRoslynVersionSubFolderPrefix, StringComparison.Ordinal);
if (versionPrefixStartIndex < 0)
{
return null;
}
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);
}
[CanBeNull]
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;
}
}
}