using System.Collections.Generic; using System.IO; using System.Linq; using JetBrains.Annotations; using NugetForUnity.Configuration; using UnityEditor; using UnityEditor.Compilation; using UnityEngine; namespace NugetForUnity { /// /// Helper to resolve what libraries are already known / imported by unity. /// internal static class UnityPreImportedLibraryResolver { [CanBeNull] private static HashSet alreadyImportedLibs; [CanBeNull] private static HashSet alreadyImportedEditorOnlyLibraries; /// /// Gets all libraries that are already imported by Unity Editor so we shouldn't / don't need to install them as NuGet packages. /// /// The list of packages. [NotNull] internal static HashSet GetAlreadyImportedEditorOnlyLibraries() { if (alreadyImportedEditorOnlyLibraries == null) { GetAlreadyImportedLibs(); } Debug.Assert(alreadyImportedEditorOnlyLibraries != null, nameof(alreadyImportedEditorOnlyLibraries) + " != null"); return alreadyImportedEditorOnlyLibraries; } /// /// Check if a package is already imported in the Unity project e.g. is a part of Unity. /// /// 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) { var alreadyImported = GetAlreadyImportedLibs(); var isAlreadyImported = alreadyImported.Contains(packageId); if (log) { NugetLogger.LogVerbose("Is package '{0}' already imported? {1}", packageId, isAlreadyImported); } return isAlreadyImported; } /// /// Gets all libraries that are already imported by unity so we shouldn't / don't need to install them as NuGet packages. /// /// A set of all names of libraries that are already imported by unity. [NotNull] private static HashSet GetAlreadyImportedLibs() { if (alreadyImportedLibs != null) { return alreadyImportedLibs; } // Find all the assemblies already installed by NuGetForUnity var alreadyInstalledDllFileNames = new HashSet(); var repositoryPath = ConfigurationManager.NugetConfigFile.RepositoryPath; if (Directory.Exists(repositoryPath)) { alreadyInstalledDllFileNames = new HashSet( Directory.EnumerateFiles(repositoryPath, "*.dll", SearchOption.AllDirectories).Select(Path.GetFileNameWithoutExtension)); } // Search the all project assemblies that are not editor only. // We only use player assemblies as we don't need to collect UnityEditor assemblies, we don't support installing NuGet packages with reference to UnityEditor. #if UNITY_2019_3_OR_NEWER const AssembliesType assemblyType = AssembliesType.PlayerWithoutTestAssemblies; #else const AssembliesType assemblyType = AssembliesType.Player; #endif var projectAssemblies = CompilationPipeline.GetAssemblies(assemblyType) .Where(playerAssembly => playerAssembly.flags != AssemblyFlags.EditorAssembly); // Collect all referenced assemblies but exclude all assemblies installed by NuGetForUnity. var projectReferences = projectAssemblies.SelectMany(playerAssembly => playerAssembly.allReferences); alreadyImportedLibs = new HashSet( projectReferences.Select(Path.GetFileNameWithoutExtension) .Where(assemblyName => !alreadyInstalledDllFileNames.Contains(assemblyName))); if (TargetFrameworkResolver.CurrentBuildTargetApiCompatibilityLevel.Value == ApiCompatibilityLevel.NET_Standard_2_0) { // mark NuGet packages that contain the .net standard references as already imported alreadyImportedLibs.Add("NETStandard.Library"); alreadyImportedLibs.Add("Microsoft.NETCore.Platforms"); } // the compiler / language is available by default alreadyImportedLibs.Add("Microsoft.CSharp"); var editorOnlyAssemblies = CompilationPipeline.GetAssemblies(AssembliesType.Editor) .Where(assembly => assembly.flags == AssemblyFlags.EditorAssembly) .ToList(); alreadyImportedEditorOnlyLibraries = new HashSet(); // com.unity.visualscripting uses .net 4.8 so it implicitly has System.CodeDom if (!alreadyImportedLibs.Contains("System.CodeDom") && editorOnlyAssemblies.Any(editorOnlyAssembly => editorOnlyAssembly.name == "Unity.VisualScripting.Shared.Editor")) { alreadyImportedEditorOnlyLibraries.Add("System.CodeDom"); } NugetLogger.LogVerbose("Already imported libs: {0}", string.Join(", ", alreadyImportedLibs)); NugetLogger.LogVerbose("Already imported editor only libraries: {0}", string.Join(", ", alreadyImportedEditorOnlyLibraries)); return alreadyImportedLibs; } } }