128 lines · typescript
1import * as vscode from "vscode";2import { DebugProtocol } from "@vscode/debugprotocol";3 4import { DebugSessionTracker } from "../debug-session-tracker";5import { DisposableContext } from "../disposable-context";6 7import { SymbolType } from "..";8import { getSymbolsTableHTMLContent } from "./symbols-webview-html";9import { getDefaultConfigKey } from "../debug-configuration-provider";10 11export class SymbolsProvider extends DisposableContext {12 constructor(13 private readonly tracker: DebugSessionTracker,14 private readonly extensionContext: vscode.ExtensionContext,15 ) {16 super();17 18 this.pushSubscription(vscode.commands.registerCommand(19 "lldb-dap.debug.showSymbols",20 () => {21 const session = vscode.debug.activeDebugSession;22 if (!session) return;23 24 this.SelectModuleAndShowSymbols(session);25 },26 ));27 28 this.pushSubscription(vscode.commands.registerCommand(29 "lldb-dap.modules.showSymbols",30 (moduleItem: DebugProtocol.Module) => {31 const session = vscode.debug.activeDebugSession;32 if (!session) return;33 34 this.showSymbolsForModule(session, moduleItem);35 },36 ));37 38 this.tracker.onDidReceiveSessionCapabilities(([ _session, capabilities ]) => {39 if (capabilities.supportsModuleSymbolsRequest) {40 vscode.commands.executeCommand(41 "setContext", "lldb-dap.supportsModuleSymbolsRequest", true);42 }43 });44 45 this.tracker.onDidExitSession((_session) => {46 vscode.commands.executeCommand("setContext", "lldb-dap.supportsModuleSymbolsRequest", false);47 });48 }49 50 private async SelectModuleAndShowSymbols(session: vscode.DebugSession) {51 const modules = this.tracker.debugSessionModules(session);52 if (!modules || modules.length === 0) {53 return;54 }55 56 // Let the user select a module to show symbols for57 const selectedModule = await vscode.window.showQuickPick(modules.map(m => new ModuleQuickPickItem(m)), {58 placeHolder: "Select a module to show symbols for"59 });60 if (!selectedModule) {61 return;62 }63 64 await this.showSymbolsForModule(session, selectedModule.module);65 }66 67 private async showSymbolsForModule(session: vscode.DebugSession, module: DebugProtocol.Module) {68 try {69 const symbols = await this.getSymbolsForModule(session, module.id.toString());70 await this.showSymbolsInNewTab(module.name.toString(), symbols);71 } catch (error) {72 if (error instanceof Error) {73 await vscode.window.showErrorMessage("Failed to retrieve symbols: " + error.message);74 } else {75 await vscode.window.showErrorMessage("Failed to retrieve symbols due to an unknown error.");76 }77 78 return;79 }80 }81 82 private async getSymbolsForModule(session: vscode.DebugSession, moduleId: string): Promise<SymbolType[]> {83 const symbols_response: { symbols: Array<SymbolType> } = await session.customRequest("__lldb_moduleSymbols", { moduleId, moduleName: '' });84 return symbols_response?.symbols || [];85 }86 87 private async showSymbolsInNewTab(moduleName: string, symbols: SymbolType[]) {88 const panel = vscode.window.createWebviewPanel(89 "lldb-dap.symbols",90 `Symbols for ${moduleName}`,91 vscode.ViewColumn.Active,92 {93 enableScripts: true,94 localResourceRoots: [95 this.getExtensionResourcePath()96 ]97 }98 );99 100 let tabulatorJsFilename = "tabulator_simple.min.css";101 if (vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.Dark || vscode.window.activeColorTheme.kind === vscode.ColorThemeKind.HighContrast) {102 tabulatorJsFilename = "tabulator_midnight.min.css";103 }104 const tabulatorCssPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), tabulatorJsFilename));105 const tabulatorJsPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "tabulator.min.js"));106 const symbolsTableScriptPath = panel.webview.asWebviewUri(vscode.Uri.joinPath(this.getExtensionResourcePath(), "symbols-table-view.js"));107 108 panel.webview.html = getSymbolsTableHTMLContent(tabulatorJsPath, tabulatorCssPath, symbolsTableScriptPath);109 await panel.webview.postMessage({ command: "updateSymbols", symbols: symbols });110 }111 112 private getExtensionResourcePath(): vscode.Uri {113 return vscode.Uri.joinPath(this.extensionContext.extensionUri, "out", "webview");114 }115}116 117class ModuleQuickPickItem implements vscode.QuickPickItem {118 constructor(public readonly module: DebugProtocol.Module) {}119 120 get label(): string {121 return this.module.name;122 }123 124 get description(): string {125 return this.module.id.toString();126 }127}128