public static AssemblyUsagesResult[]    CheckCompatibilities(IEnumerable <string> assembliesPath, FilterText[] filterNamespaces, string[] targetNamespaces, IEnumerable <string> unityVersions)
        {
            if (targetNamespaces.Length == 0)
            {
                Debug.LogWarning("You must target at least one namespace.");
                return(null);
            }

            int hash = 0;

            hash += assembliesPath.GetHashCode();

            for (int i = 0, max = filterNamespaces.Length; i < max; ++i)
            {
                FilterText filter = filterNamespaces[i];

                if (filter.active == true)
                {
                    hash += filter.text.GetHashCode() + filter.active.GetHashCode();
                }
            }

            for (int i = 0, max = targetNamespaces.Length; i < max; ++i)
            {
                hash += targetNamespaces[i].GetHashCode();
            }

            if (AssemblyUsages.usages == null || AssemblyUsages.lastUsagesHash != hash)
            {
                AssemblyUsages.lastUsagesHash = hash;

                using ((AssemblyUsages.debug & DebugItems.WatchTime) == 0 ? null : WatchTime.Get("Extracted usages from target assemblies"))
                {
                    AssemblyUsages.usages = AssemblyUsages.InspectAssembly(assembliesPath, filterNamespaces, targetNamespaces);
                }
            }

            List <AssemblyUsagesResult> results = new List <AssemblyUsagesResult>();
            int          processorCount         = Environment.ProcessorCount;
            Exception    threadException        = null;
            DatabaseMeta database = DatabaseMeta.GetDatabase();

            using ((AssemblyUsages.debug & DebugItems.WatchTime) == 0 ? null : WatchTime.Get("Resolving all"))
            {
                foreach (string unityVersion in unityVersions)
                {
                    try
                    {
                        UnityMeta unityMeta = database.Get(unityVersion);

                        if (unityMeta != null)
                        {
                            AssemblyUsagesResult result = new AssemblyUsagesResult()
                            {
                                assemblyUsages = usages, unityMeta = unityMeta
                            };

                            using ((AssemblyUsages.debug & DebugItems.WatchTime) == 0 ? null : WatchTime.Get("Resolved against " + unityMeta.Version))
                            {
                                result.ResolveReferences(AssemblyUsages.usages.visibleTypes, AssemblyUsages.usages.visibleFields, AssemblyUsages.usages.visibleMethods);
                            }

                            lock (results)
                            {
                                results.Add(result);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.LogException(ex);
                        threadException = ex;
                    }
                }
            }

            if (threadException != null)
            {
                throw threadException;
            }

            results.Sort(Utility.CompareVersion);

            return(results.ToArray());
        }
        /// <summary>Creates a UnityMeta from a Unity installation path and automatically adds it to DatabaseMeta.</summary>
        /// <param name="unityInstallPath"></param>
        /// <returns></returns>
        public static UnityMeta Create(string unityInstallPath)
        {
            UnityMeta unityMeta;

            try
            {
                // Gather all assemblies referencing UnityEditor.
                string unityEditor = Path.Combine(unityInstallPath, @"Editor\Data\Managed\UnityEditor.dll");

                if (File.Exists(unityEditor) == false)
                {
                    Debug.LogError("Assembly at \"" + unityEditor + "\" was not found.");
                    return(null);
                }

                string[] editorAssemblies = Directory.GetFiles(Path.Combine(unityInstallPath, @"Editor\Data\Managed"), "*.dll");

                for (int i = 0, max = editorAssemblies.Length; i < max; ++i)
                {
                    using (AssemblyDefinition assemblyDef = AssemblyDefinition.ReadAssembly(editorAssemblies[i]))
                    {
                        int j    = 0;
                        int max2 = assemblyDef.Modules.Count;

                        for (; j < max2; ++j)
                        {
                            ModuleDefinition moduleDef = assemblyDef.Modules[j];

                            if (moduleDef.HasAssemblyReferences == true)
                            {
                                int k    = 0;
                                int max3 = moduleDef.AssemblyReferences.Count;

                                for (; k < max3; ++k)
                                {
                                    if (moduleDef.AssemblyReferences[k].Name == "UnityEditor")
                                    {
                                        break;
                                    }
                                }

                                if (k < max3)
                                {
                                    break;
                                }
                            }
                        }

                        if (j == max2)
                        {
                            editorAssemblies[i] = null;
                        }
                    }
                }

                string   runtimeAssembliesPath = Path.Combine(unityInstallPath, @"Editor\Data\Managed\UnityEngine");
                string[] runtimeAssemblies;

                if (Directory.Exists(runtimeAssembliesPath) == true)
                {
                    runtimeAssemblies = Directory.GetFiles(runtimeAssembliesPath, "*.dll");
                }
                else
                {
                    // Switch to Unity <=2017.1.
                    runtimeAssembliesPath = Path.Combine(unityInstallPath, @"Editor\Data\Managed\UnityEngine.dll");

                    if (File.Exists(runtimeAssembliesPath) == false)
                    {
                        Debug.LogError("Runtime assembly at \"" + runtimeAssembliesPath + "\" was not found.");
                        return(null);
                    }

                    runtimeAssemblies = new string[] { runtimeAssembliesPath };
                }

                string   extensionAssembliesPath = Path.Combine(unityInstallPath, @"Editor\Data\UnityExtensions\Unity");
                string[] extensionAssemblies;

                if (Directory.Exists(extensionAssembliesPath) == false)                 // Does not exist in Unity 4.5.
                {
                    extensionAssemblies = new string[0];
                }
                else
                {
                    extensionAssemblies = Directory.GetFiles(extensionAssembliesPath, "*.dll", SearchOption.AllDirectories);
                }

                List <AssemblyMeta> meta = new List <AssemblyMeta>();

                try
                {
                    meta.Add(new AssemblyMeta(unityEditor.Substring(unityInstallPath.Length + 1), unityEditor));
                }
                catch (Exception)
                {
                    Debug.LogError("Main editor assembly \"" + unityEditor + "\" failed extraction.");
                    throw;
                }

                for (int i = 0, max = runtimeAssemblies.Length; i < max; ++i)
                {
                    try
                    {
                        meta.Add(new AssemblyMeta(runtimeAssemblies[i].Substring(unityInstallPath.Length + 1), runtimeAssemblies[i]));
                    }
                    catch (Exception)
                    {
                        Debug.LogError("Runtime assembly \"" + runtimeAssemblies[i] + "\" failed extraction.");
                        throw;
                    }
                }

                for (int i = 0, max = editorAssemblies.Length; i < max; ++i)
                {
                    try
                    {
                        if (editorAssemblies[i] != null)
                        {
                            meta.Add(new AssemblyMeta(editorAssemblies[i].Substring(unityInstallPath.Length + 1), editorAssemblies[i]));
                        }
                    }
                    catch (Exception)
                    {
                        Debug.LogError("Editor assembly \"" + editorAssemblies[i] + "\" failed extraction.");
                        throw;
                    }
                }

                for (int i = 0, max = extensionAssemblies.Length; i < max; ++i)
                {
                    try
                    {
                        meta.Add(new AssemblyMeta(extensionAssemblies[i].Substring(unityInstallPath.Length + 1), extensionAssemblies[i]));
                    }
                    catch (Exception)
                    {
                        Debug.LogWarning("Extension assembly \"" + extensionAssemblies[i] + "\" failed extraction and has been discarded.");
                    }
                }

                unityMeta = new UnityMeta(Utility.GetUnityVersion(unityInstallPath), meta.ToArray());
            }
            catch (Exception ex)
            {
                Debug.LogException(ex);
                throw;
            }

            DatabaseMeta.GetDatabase().Add(unityMeta);

            return(unityMeta);
        }