From 3dadb297b9dab72a3c32010a92a4c35a5a7f6040 Mon Sep 17 00:00:00 2001 From: Georgiy Belyanin Date: Sat, 14 Jun 2025 18:03:54 +0300 Subject: [PATCH] Add Tarantool debugging facilities This patch introduces basic Tarantool debugging facilities into the extension. Basically it is done using EmmyLuaDebugger [^1]. Set up the debugger using the following instructions. * Insert debugger code in Tarantool application by pressing `Ctrl+Shift+P` (or `Cmd+Shift+P` on MacOS) and running `Tarantool: Insert debugger code` command. * Start single Tarantool instance. * Press `F5` or run `Debug: Start debugging` command by pressing `Ctrl+Shift+P` (or `Cmd+Shift+P` on MacOS). * Choose `EmmyLua New Debugger` in the list. This debugging configuration would run automatically from now. * Set up breakpoints & access the Tarantool instance through `Debug console` in the bottom panel. These features are supported. * Breakpoints. * Step-by-step execution within the fiber. * Multiple files support. * Interacting with the local variables, console at the debug mode. Needs https://github.com/EmmyLua/EmmyLuaDebugger/pull/75 to be tested on MacOS on arm64. Closes #19 [^1] https://github.com/EmmyLua/EmmyLuaDebugger/pull/75 --- CHANGELOG.md | 5 ++++ README.md | 14 ++++++++-- package.json | 4 +++ src/extension.ts | 1 + src/utils.ts | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f59c64..80ccad2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Support for debugging Tarantool code using + [EmmyLuaDebugger](https://github.com/EmmyLua/EmmyLuaDebugger). + ## [0.2.0] - 28.05.2025 ### Added diff --git a/README.md b/README.md index 391a68b..7745d40 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ -Tarantool VS Code Extension helps you to develop Tarantool applications in VS Code. It enhances your text editor with completions, suggestions, and snippets. +Tarantool VS Code Extension helps you to develop Tarantool applications in VS Code. It enhances your text editor with completions, suggestions, snippets, and Lua debugger. --- @@ -22,6 +22,7 @@ This extension offers the following features. * Cluster configuration schema validation for Tarantool 3.0+. * [tt cluster management utility](https://github.com/tarantool/tt) inside the command palette. * Other auxiliary commands, e.g. install Tarantool of a specific version right from VS Code. +* Debugger for Tarantool apps, allowing breakpoints, step-by-step execution, viewing local variables and Lua code execution. --- @@ -31,7 +32,6 @@ That's how you use this extension. * Install the extension from the VS Code marketplace. * Open a Tarantool project in VS Code. -* Run `Tarantool: Initialize VS Code extension in existing app` command from the command palette (`Ctrl+Shift+P` or `Cmd+Shift+P` on macOS). You may statically type your Lua functions as follows. @@ -54,6 +54,16 @@ local unnamed_user = { name = 'Unnamed' } For more examples, refer to [the examples folder](examples/) with tutorials on how to type your Lua code. +## Using debugger + +Tarantool VS Code extension provides debugger facility for developing Tarantool applications. It is employs EmmyLuaDebugger that is a stop-the-world Lua debugger. + +* Insert debugger code in Tarantool application by pressing `Ctrl+Shift+P` (or `Cmd+Shift+P` on MacOS) and running `Tarantool: Insert debugger code` command. +* Start single Tarantool instance. +* Press `F5` or run `Debug: Start debugging` command by pressing `Ctrl+Shift+P` (or `Cmd+Shift+P` on MacOS). +* Choose `EmmyLua New Debugger` in the list. This debugging configuration would run automatically from now. +* Set up breakpoints & access the Tarantool instance through `Debug console` in the bottom panel. + ## Contributing Feel free to open issues on feature requests, wrong type annotations and bugs. If you're dealing with a problem related to LSP we'd appreciate addressing a direct issue to [the used external Lua Language server](https://github.com/CppCXY/emmylua-analyzer-rust). diff --git a/package.json b/package.json index 7e72b66..a9cdad6 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,10 @@ { "command": "tarantool.install-ce", "title": "Tarantool: Install Tarantool Community Edition (tt)" + }, + { + "command": "tarantool.debugger-code", + "title": "Tarantool: Insert debugger code" } ], "yamlValidation": [ diff --git a/src/extension.ts b/src/extension.ts index 40ee505..e907714 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -115,6 +115,7 @@ export function activate(context: vscode.ExtensionContext) { { name: 'stat', cb: tt.stat }, { name: 'restart', cb: tt.restart }, { name: 'install-ce', cb: tt.installCe }, + { name: 'debugger-code', cb: utils.insertDebuggerCode }, ]; commands.forEach((command) => { diff --git a/src/utils.ts b/src/utils.ts index c28dbaf..2beedb6 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,5 @@ import * as vscode from 'vscode'; +import * as path from 'path'; export function fetchWsFolder(opts?: { showWarning?: boolean }): vscode.WorkspaceFolder | null { const file = vscode.window.activeTextEditor?.document.uri.fsPath; @@ -21,3 +22,68 @@ export function fetchWsFolder(opts?: { showWarning?: boolean }): vscode.Workspac return wsFolder; } + +const dllPathTemplate = '{dllPath}'; +const debuggerCodeSnippet = `-- Start of Tarantool debugger block. Remove after debugging. +do + local old_cpath = package.cpath + package.cpath = package.cpath .. ";${dllPathTemplate}" + rawset(_G, 'tolua', false) + rawset(_G, 'xlua', false) + rawset(_G, 'emmyHelper', {}) + local dbg = require('emmy_core') + local log = require('log') + _G.emmyHelperInit() + function init_debugger() + dbg.tcpListen('localhost', 9966) + dbg.waitIDE() + end + local ok, err = pcall(init_debugger) + if ok then + log.info('Set up Tarantool for debugging') + else + log.warn('Unable to start debugger: %s', err) + end + package.cpath = old_cpath +end +-- End of Tarantool debugger block. Remove after debugging. +`; + +export async function insertDebuggerCode() { + const activeEditor = vscode.window.activeTextEditor; + if (!activeEditor) { + vscode.window.showWarningMessage(`You should have an active text editor window to insert Tarantool debugger code. Consider opening a file`); + return; + } + const document = activeEditor.document; + if (document.languageId !== 'lua') { + vscode.window.showWarningMessage(`Tarantool Debugger code is supposed to be used within .lua files`); + return; + } + + let dllPath = ''; + const extensionPath = __dirname; + const isWindows = process.platform === 'win32'; + const isMac = process.platform === 'darwin'; + const isLinux = process.platform === 'linux'; + if (isWindows) { + const arch = await vscode.window.showQuickPick(['x64', 'x86']); + if (!arch) { + return; + } + dllPath = path.join(extensionPath, `debugger/emmy/windows/${arch}/?.dll`); + } else if (isMac) { + const arch = await vscode.window.showQuickPick(['x64', 'arm64']); + if (!arch) { + return; + } + dllPath = path.join(extensionPath, `debugger/emmy/mac/${arch}/emmy_core.dylib`); + } + else if (isLinux) { + dllPath = path.join(extensionPath, `debugger/emmy/linux/emmy_core.so`); + } + + const snippet = new vscode.SnippetString(); + snippet.appendText(debuggerCodeSnippet.replace(dllPathTemplate, dllPath.replace(/\\/g, '/'))); + activeEditor.insertSnippet(snippet); +}