public async Task Scan(string whitelistCacheFileName)
        {
            await Task.Run(() =>
            {
                var whitelist      = Whitelist.Load(whitelistCacheFileName);
                var spaceEngineers = new SpaceEngineers();
                var installPath    = Path.Combine(spaceEngineers.GetInstallPath(), "bin64");
                MDKUtilityFramework.Load(installPath);
                var dllFiles = Directory.EnumerateFiles(installPath, "*.dll", SearchOption.TopDirectoryOnly)
                               .ToList();

                foreach (var dllFile in dllFiles)
                {
                    Visit(whitelist, dllFile);
                }

                foreach (var assemblyGroup in _members.GroupBy(m => m.DeclaringType.Assembly))
                {
                    var assemblyPath = new Uri(assemblyGroup.Key.CodeBase).LocalPath;
                    var xmlFileName  = Path.ChangeExtension(assemblyPath, "xml");
                    XDocument documentation;
                    if (File.Exists(xmlFileName))
                    {
                        documentation = XDocument.Load(xmlFileName);
                    }
                    else
                    {
                        documentation = null;
                    }
                    foreach (var typeGroup in assemblyGroup.GroupBy(m => m.DeclaringType))
                    {
                        var typeEntry = ApiEntry.Create(typeGroup.Key, documentation);
                        _entries.Add(typeEntry);
                        foreach (var member in typeGroup)
                        {
                            var entry = ApiEntry.Create(member, documentation);
                            _entries.Add(entry);
                        }
                    }
                }

                foreach (var entry in _entries)
                {
                    entry.ResolveLinks(_entries);
                }
            });
        }
        public static async Task <ProgrammableBlockApi> LoadAsync(string whitelistCacheFileName)
        {
            var api = new ProgrammableBlockApi();
            await Task.Run(() =>
            {
                var members        = new List <MemberInfo>();
                var spaceEngineers = new SpaceEngineers();
                var installPath    = Path.Combine(spaceEngineers.GetInstallPath(), "bin64");
                MDKUtilityFramework.Load(installPath);
                var dllFiles = Directory.EnumerateFiles(installPath, "*.dll", SearchOption.TopDirectoryOnly)
                               .ToList();
                foreach (var file in dllFiles)
                {
                    LoadAssembly(file);
                }
                //var assemblies = dllFiles.Select(LoadAssembly).Where(a => a != null).ToList();
                var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
                var whitelist  = Whitelist.Load(whitelistCacheFileName);
                api._whitelist = whitelist;

                foreach (var assembly in assemblies)
                {
                    Visit(whitelist, assembly, members);
                }

                // Hack. I'm getting duplicated entries and atm I cannot be bothered to do a proper check
                // for why...
                HashSet <MemberInfo> visitedMembers = new HashSet <MemberInfo>();

                foreach (var assemblyGroup in members.GroupBy(m => m.GetAssembly()))
                {
                    foreach (var typeGroup in assemblyGroup.GroupBy(m => m.DeclaringType))
                    {
                        var typeEntry = api.GetEntry(typeGroup.Key);
                        if (typeEntry != null)
                        {
                            if (!visitedMembers.Add(typeEntry.Member))
                            {
                                continue;
                            }
                            api._entries.Add(typeEntry);
                            foreach (var member in typeGroup)
                            {
                                var entry = api.GetEntry(member);
                                if (entry != null)
                                {
                                    if (!visitedMembers.Add(member))
                                    {
                                        continue;
                                    }
                                    api._entries.Add(entry);
                                }
                            }
                        }
                    }
                }

                foreach (var entry in api.Entries)
                {
                    entry.ResolveLinks();
                }
            });

            return(api);
        }