/// <summary>
        /// Collate type data from assemblies into an AvailableTypeData object.
        /// </summary>
        /// <param name="assemblies">the assemblies to collate data from.</param>
        /// <param name="typeAccelerators">lookup table of PowerShell type accelerators.</param>
        /// <returns>an object describing all the available types from the given assemblies.</returns>
        public static AvailableTypeData AssembleAvailableTypes(
            IEnumerable <Assembly> assemblies,
            IDictionary <string, Type> typeAccelerators,
            out IEnumerable <CompatibilityAnalysisException> errors)
        {
            var errAcc = new List <CompatibilityAnalysisException>();
            var typeAcceleratorDict = new JsonCaseInsensitiveStringDictionary <TypeAcceleratorData>(typeAccelerators.Count);

            foreach (KeyValuePair <string, Type> typeAccelerator in typeAccelerators)
            {
                var ta = new TypeAcceleratorData()
                {
                    Assembly = typeAccelerator.Value.Assembly.GetName().Name,
                    Type     = typeAccelerator.Value.FullName
                };

                typeAcceleratorDict.Add(typeAccelerator.Key, ta);
            }

            var asms = new JsonCaseInsensitiveStringDictionary <AssemblyData>();

            foreach (Assembly asm in assemblies)
            {
                // Don't want to include this module or assembly in the output
                if (Assembly.GetCallingAssembly() == asm)
                {
                    continue;
                }

                try
                {
                    KeyValuePair <string, AssemblyData> asmData = AssembleAssembly(asm);
                    asms.Add(asmData.Key, asmData.Value);
                }
                catch (ReflectionTypeLoadException e)
                {
                    errAcc.Add(new CompatibilityAnalysisException($"Failed to load assembly '{asm.GetName().FullName}'", e));
                }
            }

            errors = errAcc;
            return(new AvailableTypeData()
            {
                TypeAccelerators = typeAcceleratorDict,
                Assemblies = asms
            });
        }
        /// <summary>
        /// Collate type data from assemblies into an AvailableTypeData object.
        /// </summary>
        /// <param name="assemblies">the assemblies to collate data from.</param>
        /// <param name="typeAccelerators">lookup table of PowerShell type accelerators.</param>
        /// <returns>an object describing all the available types from the given assemblies.</returns>
        public AvailableTypeData AssembleAvailableTypes(
            IEnumerable <Assembly> assemblies,
            IReadOnlyDictionary <string, Type> typeAccelerators,
            out IEnumerable <CompatibilityAnalysisException> errors)
        {
            var errAcc = new List <CompatibilityAnalysisException>();
            var typeAcceleratorDict = new JsonCaseInsensitiveStringDictionary <TypeAcceleratorData>(typeAccelerators.Count);

            foreach (KeyValuePair <string, Type> typeAccelerator in typeAccelerators)
            {
                var ta = new TypeAcceleratorData()
                {
                    Assembly = typeAccelerator.Value.Assembly.GetName().Name,
                    Type     = typeAccelerator.Value.FullName
                };

                typeAcceleratorDict.Add(typeAccelerator.Key, ta);
            }

            var asms = new JsonDictionary <string, AssemblyData>();

            foreach (Assembly asm in assemblies)
            {
                // Skip over this
                if (asm == s_executingAssembly ||
                    asm.IsDynamic ||
                    string.IsNullOrEmpty(asm.Location))
                {
                    continue;
                }

                if (_excludedAssemblyPathPrefixes != null &&
                    IsAssemblyPathExcluded(asm.Location))
                {
                    continue;
                }

                try
                {
                    // First check whether an assembly with this name already exists
                    // Only replace it if the current one is newer
                    AssemblyName asmName = asm.GetName();
                    if (asms.TryGetValue(asmName.Name, out AssemblyData currentAssemblyData) &&
                        asmName.Version < currentAssemblyData.AssemblyName.Version)
                    {
                        continue;
                    }

                    KeyValuePair <string, AssemblyData> asmData = AssembleAssembly(asm);
                    try
                    {
                        asms.Add(asmData.Key, asmData.Value);
                    }
                    catch (ArgumentException e)
                    {
                        // We don't have a way in the schema for two assemblies with the same name, so we just keep the first
                        // This is not really valid and we should update the schema to subkey the version
                        errAcc.Add(new CompatibilityAnalysisException($"Found duplicate assemblies with name {asmData.Key}. Kept the first one.", e));
                    }
                }
                catch (Exception e) when(e is ReflectionTypeLoadException || e is FileNotFoundException)
                {
                    errAcc.Add(new CompatibilityAnalysisException($"Failed to load assembly '{asm.GetName().FullName}'", e));
                }
            }

            errors = errAcc;
            return(new AvailableTypeData()
            {
                TypeAccelerators = typeAcceleratorDict,
                Assemblies = asms
            });
        }