public DecompileResult Execute()
        {
            var result = new DecompileResult();

            try
            {
                using (var database = new Database(this.Context.DecompilePath, OpenDatabase.ReadOnly))
                {
                    // Delete the directory and its files to prevent cab extraction failure due to an existing file.
                    if (Directory.Exists(this.Context.ExtractFolder))
                    {
                        Directory.Delete(this.Context.ExtractFolder, true);
                    }

                    var unbindCommand      = new UnbindDatabaseCommand(this.Messaging, database, this.Context.DecompilePath, this.Context.DecompileType, this.Context.ExtractFolder, this.Context.IntermediateFolder, this.Context.IsAdminImage, false, skipSummaryInfo: false);
                    var output             = unbindCommand.Execute();
                    var extractedFilePaths = new List <string>(unbindCommand.ExportedFiles);

                    var decompiler = new Decompiler(this.Messaging, this.Extensions, this.Context.BaseSourcePath, this.Context.SuppressCustomTables, this.Context.SuppressDroppingEmptyTables, this.Context.SuppressUI, this.Context.TreatProductAsModule);
                    result.Document = decompiler.Decompile(output);

                    // extract the files from the cabinets
                    if (!String.IsNullOrEmpty(this.Context.ExtractFolder) && !this.Context.SuppressExtractCabinets)
                    {
                        var fileDirectory = String.IsNullOrEmpty(this.Context.CabinetExtractFolder) ? Path.Combine(this.Context.ExtractFolder, "File") : this.Context.CabinetExtractFolder;

                        var extractCommand = new ExtractCabinetsCommand(output, database, this.Context.DecompilePath, fileDirectory, this.Context.IntermediateFolder, this.Context.TreatProductAsModule);
                        extractCommand.Execute();

                        extractedFilePaths.AddRange(extractCommand.ExtractedFiles);
                        result.ExtractedFilePaths = extractedFilePaths;
                    }
                    else
                    {
                        result.ExtractedFilePaths = new string[0];
                    }
                }
            }
            catch (Win32Exception e)
            {
                if (0x6E == e.NativeErrorCode) // ERROR_OPEN_FAILED
                {
                    throw new WixException(ErrorMessages.OpenDatabaseFailed(this.Context.DecompilePath));
                }

                throw;
            }

            return(result);
        }
        private LanguageServerOptions AddRequests(LanguageServerOptions options)
        {
            // Pathmap creation is seperated into 2 requests, 'pathmapFromClipboard' and 'pathmapApply'.
            // Pathmap generation request.
            options.OnRequest <object, string>("pathmapFromClipboard", _ => Task <string> .Run(() =>
            {
                // Create the error handler for pathmap parser.
                ServerPathmapHandler error = new ServerPathmapHandler();

                // Get the pathmap. 'map' will be null if there is an error.
                try
                {
                    Pathmap map = Pathmap.ImportFromCSV(Clipboard.GetText(), error);

                    if (map == null)
                    {
                        return(error.Message);
                    }
                    else
                    {
                        lastMap = map;
                        return("success");
                    }
                }
                catch (Exception ex)
                {
                    return(ex.Message);
                }
            }));

            // Pathmap save request.
            options.OnRequest <Newtonsoft.Json.Linq.JToken>("pathmapApply", uriToken => Task.Run(() =>
            {
                // Save 'lastMap' to a file.
                string result = lastMap.ExportAsJSON();
                string output = uriToken["path"].ToObject <string>().Trim('/');
                using (var stream = new StreamWriter(output))
                    stream.Write(result);
            }));

            // Pathmap editor request.
            options.OnRequest <PathmapDocument, bool>("pathmapEditor", (editFileToken) => Task <bool> .Run(() =>
            {
                DeltinScript compile;
                if (editFileToken.Text == null)
                {
                    string editor = Extras.CombinePathWithDotNotation(null, "!PathfindEditor.del");
                    compile       = new DeltinScript(new TranslateSettings(editor)
                    {
                        OutputLanguage = ConfigurationHandler.OutputLanguage
                    });
                }
                else
                {
                    compile = Editor.Generate(editFileToken.File, Pathmap.ImportFromText(editFileToken.Text), ConfigurationHandler.OutputLanguage);
                }

                Clipboard.SetText(compile.WorkshopCode);

                return(true);
            }));

            // semantic tokens
            options.OnRequest <Newtonsoft.Json.Linq.JToken, SemanticToken[]>("semanticTokens", (uriToken) => Task <SemanticToken[]> .Run(async() =>
            {
                await DocumentHandler.WaitForParse();
                SemanticToken[] tokens = LastParse?.ScriptFromUri(new Uri(uriToken["fsPath"].ToObject <string>()))?.GetSemanticTokens();
                return(tokens ?? new SemanticToken[0]);
            }));

            // debugger start
            options.OnRequest <object>("debugger.start", args => Task.Run(() =>
            {
                _debugger.Start();
                return(new object());
            }));

            // debugger stop
            options.OnRequest <object>("debugger.stop", args => Task.Run(() =>
            {
                _debugger.Stop();
                return(new object());
            }));

            // debugger scopes
            options.OnRequest <ScopesArgs, DBPScope[]>("debugger.scopes", args => Task <DBPScope[]> .Run(() =>
            {
                try
                {
                    if (_debugger.VariableCollection != null)
                    {
                        return(_debugger.VariableCollection.GetScopes(args));
                    }
                }
                catch (Exception ex)
                {
                    DebuggerException(ex);
                }
                return(new DBPScope[0]);
            }));

            // debugger variables
            options.OnRequest <VariablesArgs, DBPVariable[]>("debugger.variables", args => Task <DBPVariable[]> .Run(() =>
            {
                try
                {
                    if (_debugger.VariableCollection != null)
                    {
                        return(_debugger.VariableCollection.GetVariables(args));
                    }
                }
                catch (Exception ex)
                {
                    DebuggerException(ex);
                }
                return(new DBPVariable[0]);
            }));

            // debugger evaluate
            options.OnRequest <EvaluateArgs, EvaluateResponse>("debugger.evaluate", args => Task <EvaluateResponse> .Run(() =>
            {
                try
                {
                    return(_debugger.VariableCollection?.Evaluate(args));
                }
                catch (Exception ex)
                {
                    DebuggerException(ex);
                    return(EvaluateResponse.Empty);
                }
            }));

            // Decompile insert
            options.OnRequest <DecompileResult>("decompile.insert", () => Task <DecompileResult> .Run(() =>
            {
                try
                {
                    var tte      = new ConvertTextToElement(Clipboard.GetText());
                    var workshop = tte.Get();
                    var code     = new WorkshopDecompiler(workshop, new OmitLobbySettingsResolver(), new CodeFormattingOptions()).Decompile();
                    return(new DecompileResult(tte, code));
                }
                catch (Exception ex)
                {
                    return(new DecompileResult(ex));
                }
            }));

            // Decompile file
            options.OnRequest <DecompileFileArgs, DecompileResult>("decompile.file", args => Task.Run <DecompileResult>(() =>
            {
                try
                {
                    // Parse the workshop code.
                    var tte      = new ConvertTextToElement(Clipboard.GetText());
                    var workshop = tte.Get();

                    // Decompile the parsed workshop code.
                    var workshopToCode = new WorkshopDecompiler(workshop, new FileLobbySettingsResolver(args.File, workshop.LobbySettings), new CodeFormattingOptions());
                    var code           = workshopToCode.Decompile();

                    var result = new DecompileResult(tte, code);

                    // Only create the decompile was successful.
                    if (result.Success)
                    {
                        // Create the file.
                        using (var writer = File.CreateText(args.File))
                            // Write the code to the file.
                            writer.Write(code);
                    }

                    return(result);
                }
                catch (Exception ex)
                {
                    return(new DecompileResult(ex));
                }
            }));

            return(options);
        }