diff --git a/.gitattributes b/.gitattributes index 24a8e87..00c0c36 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,3 @@ *.png filter=lfs diff=lfs merge=lfs -text +debugger/*.dylib filter=lfs diff=lfs merge=lfs -text +debugger/*.so filter=lfs diff=lfs merge=lfs -text 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..4569bac 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 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/debugger/emmyluadebugger-darwin-arm64.dylib b/debugger/emmyluadebugger-darwin-arm64.dylib new file mode 100755 index 0000000..3acdd02 --- /dev/null +++ b/debugger/emmyluadebugger-darwin-arm64.dylib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c5e7b3f8a837c65e4d127bfaf946f76a4643f12cf6e9c56a0ebd1a9656cfc325 +size 499856 diff --git a/debugger/emmyluadebugger-darwin-x64.dylib b/debugger/emmyluadebugger-darwin-x64.dylib new file mode 100755 index 0000000..4d10f80 --- /dev/null +++ b/debugger/emmyluadebugger-darwin-x64.dylib @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f4a99aa3bffb67d5501f24b433ffdc2cd0915bd7e933a976ce72ea226a688b52 +size 483288 diff --git a/debugger/emmyluadebugger-linux-arm64.so b/debugger/emmyluadebugger-linux-arm64.so new file mode 100644 index 0000000..3887547 --- /dev/null +++ b/debugger/emmyluadebugger-linux-arm64.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6b71974688b2bdfc7571b1025d194406efb9b647487209231a2c55145372bc6e +size 792432 diff --git a/debugger/emmyluadebugger-linux-x64.so b/debugger/emmyluadebugger-linux-x64.so new file mode 100644 index 0000000..3a110bf --- /dev/null +++ b/debugger/emmyluadebugger-linux-x64.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0366b8247f936afb9651820714b4052ffe72117f16dea91c19a3d866df0cf3b9 +size 778632 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..e29b8c9 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,4 +1,6 @@ import * as vscode from 'vscode'; +import * as fs from 'fs'; +import * as path from 'path'; export function fetchWsFolder(opts?: { showWarning?: boolean }): vscode.WorkspaceFolder | null { const file = vscode.window.activeTextEditor?.document.uri.fsPath; @@ -21,3 +23,67 @@ 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. +`; + +const supportedDebuggerPlatforms = ['darwin', 'linux']; +const supportedDebuggerArchs = ['x64', 'arm64']; + +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; + } + + const extensionPath = __dirname; + const hostPlatform = process.platform; + const platform = supportedDebuggerPlatforms.includes(hostPlatform) ? hostPlatform : (await vscode.window.showQuickPick(supportedDebuggerPlatforms)); + if (!platform) + {return;} + + const arch = await vscode.window.showQuickPick(supportedDebuggerArchs); + if (!arch) { + return; + } + + const extension = platform === 'darwin' ? 'dylib' : 'so'; + + const dllPath = path.join(extensionPath, `emmyluadebugger-${platform}-${arch}.${extension}`); + if (!fs.existsSync(dllPath)) { + vscode.window.showWarningMessage(`Unable to access the Tarantool debugger for ${platform} on ${arch}. Try reinstalling the extension. If it does not help consider manually modifying the "cpath" variable in the pasted debugger code`); + } + + const snippet = new vscode.SnippetString(); + snippet.appendText(debuggerCodeSnippet.replace(dllPathTemplate, dllPath.replace(/\\/g, '/'))); + activeEditor.insertSnippet(snippet); +} diff --git a/webpack.config.js b/webpack.config.js index 7ba1443..9d13722 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -25,7 +25,8 @@ const extensionConfig = { plugins: [ new CopyWebpackPlugin({ patterns: [ - { from: './tarantool-annotations', to: path.resolve(__dirname, 'dist') } + { from: './tarantool-annotations', to: path.resolve(__dirname, 'dist') }, + { from: './debugger', to: path.resolve(__dirname, 'dist') }, ] }) ],