forked from GlitchEnzo/NuGetForUnity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request GlitchEnzo#393 from nowsprinting/roslyn_analyzer_s…
…upport Add Roslyn analyzer package support Allow System.Text.Json to be imported correctly Change back NuGetForUnity.dll name to NugetForUnity.dll (need to be same as namespace)
- Loading branch information
Showing
49 changed files
with
1,252 additions
and
849 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
{ | ||
"name": "NuGetForUnity", | ||
"references": [], | ||
"optionalUnityReferences": [], | ||
"includePlatforms": [ | ||
"Editor" | ||
], | ||
"excludePlatforms": [], | ||
"allowUnsafeCode": false, | ||
"overrideReferences": false, | ||
"precompiledReferences": [], | ||
"autoReferenced": true, | ||
"defineConstraints": [] | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Reflection; | ||
using UnityEditor; | ||
using UnityEngine; | ||
|
||
namespace NugetForUnity | ||
{ | ||
/// <summary> | ||
/// Hook into the import pipeline to change NuGet package related assets after / before they are imported. | ||
/// </summary> | ||
public class NugetPackageAssetPostprocessor : AssetPostprocessor | ||
{ | ||
/// <summary> | ||
/// Folder used to store Roslyn-Analyzers inside NuGet packages. | ||
/// </summary> | ||
private const string AnalyzersFolderName = "analyzers"; | ||
|
||
/// <summary> | ||
/// Used to mark an asset as already processed by this class. | ||
/// </summary> | ||
private const string ProcessedLabel = "NuGetForUnity"; | ||
|
||
/// <summary> | ||
/// Used to let unity know an asset is a Roslyn-Analyzer. | ||
/// </summary> | ||
private const string RoslynAnalyzerLabel = "RoslynAnalyzer"; | ||
|
||
/// <summary> | ||
/// Get informed about a new asset that is added. | ||
/// This is called before unity tried to import a asset but the <see cref="AssetImporter"/> is already created | ||
/// so we can change the import settings before unity throws errors about incompatibility etc.. | ||
/// Currently we change the import settings of: | ||
/// Roslyn-Analyzers: are marked so unity knows that the *.dll's are analyzers and treats them accordingly. | ||
/// </summary> | ||
private void OnPreprocessAsset() | ||
{ | ||
var absoluteRepositoryPath = GetNuGetRepositoryPath(); | ||
var result = HandleAsset(assetPath, absoluteRepositoryPath, false); | ||
if (result.HasValue) | ||
{ | ||
LogResults(new[] { result.Value }); | ||
} | ||
} | ||
|
||
private static readonly List<BuildTarget> NonObsoleteBuildTargets = typeof(BuildTarget) | ||
.GetFields(BindingFlags.Public | BindingFlags.Static) | ||
.Where(fieldInfo => fieldInfo.GetCustomAttribute(typeof(ObsoleteAttribute)) == null) | ||
.Select(fieldInfo => (BuildTarget)fieldInfo.GetValue(null)) | ||
.ToList(); | ||
|
||
private enum ResultStatus | ||
{ | ||
Success, | ||
Failure, | ||
AlreadyProcessed | ||
} | ||
|
||
private static (string AssetType, string AssetPath, ResultStatus Status)? HandleAsset(string projectRelativeAssetPath, string absoluteRepositoryPath, bool reimport) | ||
{ | ||
var absoluteAssetPath = Path.GetFullPath(Path.Combine(NugetHelper.AbsoluteProjectPath, projectRelativeAssetPath)); | ||
if (!AssetIsDllInsideNuGetRepository(absoluteAssetPath, absoluteRepositoryPath)) | ||
{ | ||
return null; | ||
} | ||
|
||
var assetPathRelativeToRepository = absoluteAssetPath.Substring(absoluteRepositoryPath.Length); | ||
// the first component is the package name | ||
var assetPathComponents = GetPathComponents(assetPathRelativeToRepository); | ||
if (assetPathComponents.Length > 1 && assetPathComponents[1].Equals(AnalyzersFolderName, StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
var result = ModifyImportSettingsOfRoslynAnalyzer(projectRelativeAssetPath, reimport); | ||
return ("RoslynAnalyzer", projectRelativeAssetPath, result); | ||
} | ||
|
||
return null; | ||
} | ||
|
||
private static string[] GetPathComponents(string path) | ||
{ | ||
return path.Split(Path.DirectorySeparatorChar); | ||
} | ||
|
||
private static bool AssetIsDllInsideNuGetRepository(string absoluteAssetPath, string absoluteRepositoryPath) | ||
{ | ||
return absoluteAssetPath.StartsWith(absoluteRepositoryPath, StringComparison.OrdinalIgnoreCase) | ||
&& absoluteAssetPath.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) | ||
&& File.Exists(absoluteAssetPath); | ||
} | ||
|
||
/// <summary> | ||
/// Gets the absolute path where NuGetForUnity restores NuGet packages, with trailing directory separator. | ||
/// </summary> | ||
/// <returns>The absolute path where NuGetForUnity restores NuGet packages, with trailing directory separator.</returns> | ||
private static string GetNuGetRepositoryPath() | ||
{ | ||
if (NugetHelper.NugetConfigFile == null) | ||
{ | ||
NugetHelper.LoadNugetConfigFile(); | ||
} | ||
|
||
return NugetHelper.NugetConfigFile.RepositoryPath + Path.DirectorySeparatorChar; | ||
} | ||
|
||
private static ResultStatus ModifyImportSettingsOfRoslynAnalyzer(string analyzerAssetPath, bool reimport) | ||
{ | ||
if (!GetPluginImporter(analyzerAssetPath, out var plugin)) | ||
{ | ||
return ResultStatus.Failure; | ||
} | ||
|
||
if (AlreadyProcessed(plugin)) | ||
{ | ||
return ResultStatus.AlreadyProcessed; | ||
} | ||
|
||
plugin.SetCompatibleWithAnyPlatform(false); | ||
plugin.SetCompatibleWithEditor(false); | ||
foreach (var platform in NonObsoleteBuildTargets) | ||
{ | ||
plugin.SetExcludeFromAnyPlatform(platform, false); | ||
} | ||
|
||
AssetDatabase.SetLabels(plugin, new[] { RoslynAnalyzerLabel, ProcessedLabel }); | ||
|
||
if (reimport) | ||
{ | ||
// Persist and reload the change to the meta file | ||
plugin.SaveAndReimport(); | ||
} | ||
|
||
NugetHelper.LogVerbose("Configured asset '{0}' as a Roslyn-Analyzer.", analyzerAssetPath); | ||
return ResultStatus.Success; | ||
} | ||
|
||
/// <summary> | ||
/// Logs the aggregated result of the processing of the assets. | ||
/// </summary> | ||
/// <param name="results">The aggregated result status.</param> | ||
private static void LogResults(IEnumerable<(string AssetType, string AssetPath, ResultStatus Status)> results) | ||
{ | ||
var grouped = results.GroupBy(result => result.Status); | ||
foreach (var groupEntry in grouped) | ||
{ | ||
if (groupEntry.Key == ResultStatus.Success && NugetHelper.NugetConfigFile.Verbose) | ||
{ | ||
NugetHelper.LogVerbose("NuGetForUnity: successfully processed: {0}", string.Join(",", groupEntry.Select(asset => $"'{asset.AssetPath}' ({asset.AssetType})"))); | ||
} | ||
|
||
if (groupEntry.Key == ResultStatus.Failure) | ||
{ | ||
Debug.LogError($"NuGetForUnity: failed to process: {string.Join(",", groupEntry.Select(asset => $"'{asset.AssetPath}' ({asset.AssetType})"))}"); | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Given the <paramref name="assetFilePath" /> load the <see cref="PluginImporter" /> for the asset it's associated | ||
/// with. | ||
/// </summary> | ||
/// <param name="assetFilePath">Path to the assets.</param> | ||
/// <param name="plugin">The loaded PluginImporter.</param> | ||
/// <returns>True if the plug-in importer for the asset could be loaded.</returns> | ||
private static bool GetPluginImporter(string assetFilePath, out PluginImporter plugin) | ||
{ | ||
var assetPath = assetFilePath; | ||
plugin = AssetImporter.GetAtPath(assetPath) as PluginImporter; | ||
|
||
if (plugin == null) | ||
{ | ||
Debug.LogWarning($"Failed to import plug-in at {assetPath}"); | ||
return false; | ||
} | ||
|
||
NugetHelper.LogVerbose("Plug-in loaded for file: {0}", assetPath); | ||
|
||
return true; | ||
} | ||
|
||
/// <summary> | ||
/// Check the labels on the asset to determine if we've already processed it. Calls to | ||
/// <see cref="AssetImporter.SaveAndReimport"/> trigger call backs to this class to occur so not checking | ||
/// if an asset has already been processed triggers an infinite loop that Unity detects and logs as an error. | ||
/// </summary> | ||
/// <param name="asset">Asset to check.</param> | ||
/// <returns>True if already processed.</returns> | ||
private static bool AlreadyProcessed(UnityEngine.Object asset) | ||
{ | ||
return AssetDatabase.GetLabels(asset).Contains(ProcessedLabel); | ||
} | ||
} | ||
} |
11 changes: 11 additions & 0 deletions
11
Assets/NuGet/Editor/NugetPackageAssetPostprocessor.cs.meta
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"name": "NuGetForUnity.Editor.Tests", | ||
"references": [ | ||
"NuGetForUnity" | ||
], | ||
"optionalUnityReferences": [ | ||
"TestAssemblies" | ||
], | ||
"includePlatforms": [ | ||
"Editor" | ||
], | ||
"excludePlatforms": [], | ||
"allowUnsafeCode": false, | ||
"overrideReferences": false, | ||
"precompiledReferences": [], | ||
"autoReferenced": true, | ||
"defineConstraints": [] | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.