diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 3607bd7f7..0f8354e37 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -18,7 +18,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: 'Insatll requirements' - run: pip3 install --user -r dev_requirements.txt + run: pip3 install --user -r dev_requirements.txt - name: 'Run flake8' run: '$HOME/.local/bin/flake8 python3/ *.py' VimscriptLint: @@ -27,7 +27,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: 'Install requirements' - run: pip3 install --user -r dev_requirements.txt + run: pip3 install --user -r dev_requirements.txt - name: 'Run vint' run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/ @@ -81,7 +81,7 @@ jobs: VIMSPECTOR_MIMODE: gdb - name: "Upload test logs" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: 'test-logs-${{ runner.os }}-${{ matrix.runtime }}' @@ -97,7 +97,7 @@ jobs: # SSH_PASS: ${{ secrets.SSH_PASS }} MacOS: - runs-on: 'macos-12' + runs-on: 'macos-13' strategy: fail-fast: false matrix: @@ -113,7 +113,7 @@ jobs: brew update-reset brew doctor || true brew cleanup || true - for p in vim go tcl-tk llvm lua luajit love neovim coreutils; do + for p in vim go tcl-tk@8 llvm lua luajit love neovim coreutils; do brew install $p || brew outdated $p || brew upgrade $p done brew reinstall icu4c @@ -122,11 +122,11 @@ jobs: brew link --overwrite go # latest neovim doesn't work on python 3.12 # https://github.com/neovim/pynvim/issues/538 - pip3 install --user 'pynvim @ git+https://github.com/neovim/pynvim' + pip3 install --break-system-packages --user 'pynvim @ git+https://github.com/neovim/pynvim' name: 'Install vim and deps' - name: 'Install requirements' - run: pip3 install --user -r dev_requirements.txt + run: pip3 install --break-system-packages --user -r dev_requirements.txt - run: go install github.com/go-delve/delve/cmd/dlv@latest name: 'Install Delve for Go' @@ -163,7 +163,7 @@ jobs: VIMSPECTOR_MIMODE: lldb - name: "Upload test logs" - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 if: always() with: name: 'test-logs-${{ runner.os }}-${{ matrix.runtime }}' diff --git a/.mergify.yml b/.mergify.yml index 10df2e73e..9fa098eda 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -1,5 +1,67 @@ # https://blog.mergify.com/strict-mode-deprecation/ queue_rules: + - name: duplicated default from Merge owner PR when all checks passed + queue_conditions: + - author=puremourning + - base=master + - status-success=code-review/reviewable + - "#changes-requested-reviews-by=0" + - status-success=PythonLint + - status-success=VimscriptLint + - status-success=Linux (vim) + - status-success=Linux (nvim) + - status-success=MacOS (vim) + merge_conditions: + # CI https://doc.mergify.io/conditions.html#github-actions + - status-success=PythonLint + - status-success=VimscriptLint + - status-success=Linux (vim) + - status-success=Linux (nvim) + - status-success=MacOS (vim) + #- status-success=MacOS (nvim) + + merge_method: merge + - name: duplicated default from Merge auto pr when approved + queue_conditions: + - author=VimspectorUpdateBot + - label=auto + - base=master + - status-success=code-review/reviewable + - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" + merge_conditions: + # CI https://doc.mergify.io/conditions.html#github-actions + - status-success=PythonLint + - status-success=VimscriptLint + - status-success=Linux (vim) + - status-success=Linux (nvim) + - status-success=MacOS (vim) + #- status-success=MacOS (nvim) + + merge_method: merge + - name: duplicated default from Merge PR when all checks passed + queue_conditions: + - author!=puremourning + - base=master + - status-success=code-review/reviewable + - "#approved-reviews-by>=1" + - "#changes-requested-reviews-by=0" + - approved-reviews-by=puremourning + - status-success=PythonLint + - status-success=VimscriptLint + - status-success=Linux (vim) + - status-success=Linux (nvim) + - status-success=MacOS (vim) + merge_conditions: + # CI https://doc.mergify.io/conditions.html#github-actions + - status-success=PythonLint + - status-success=VimscriptLint + - status-success=Linux (vim) + - status-success=Linux (nvim) + - status-success=MacOS (vim) + #- status-success=MacOS (nvim) + + merge_method: merge - name: default # These define the conditions to get out of the merge queue conditions: @@ -11,6 +73,7 @@ queue_rules: - status-success=MacOS (vim) #- status-success=MacOS (nvim) + pull_request_rules: - name: Merge owner PR when all checks passed # These define the conditions to get into the merge queue @@ -28,11 +91,7 @@ pull_request_rules: - status-success=MacOS (vim) #- status-success=MacOS (nvim) actions: &merge-actions - queue: - method: merge - name: default delete_head_branch: {} - - name: Merge auto pr when approved conditions: - author=VimspectorUpdateBot @@ -44,7 +103,6 @@ pull_request_rules: - "#changes-requested-reviews-by=0" actions: <<: *merge-actions - - name: Merge PR when all checks passed # These define the conditions to get into the merge queue conditions: @@ -66,3 +124,8 @@ pull_request_rules: <<: *merge-actions comment: message: Thanks for sending a PR! + - name: Merge PR when all checks passed + Merge auto pr when approved + Merge owner + PR when all checks passed + conditions: [] + actions: + queue: diff --git a/README.md b/README.md index 2df4d3239..11691553d 100644 --- a/README.md +++ b/README.md @@ -9,108 +9,110 @@ For detailed explanation of the `.vimspector.json` format, see the [![Build](https://github.com/puremourning/vimspector/actions/workflows/build.yaml/badge.svg?branch=master)](https://github.com/puremourning/vimspector/actions/workflows/build.yaml) [![Matrix](https://img.shields.io/matrix/vimspector:matrix.org?label=matrix)](https://matrix.to/#/#vimspector_Lobby:gitter.im) [![Gitter](https://badges.gitter.im/vimspector/Lobby.svg)](https://gitter.im/vimspector/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) - * [Features and Usage](#features-and-usage) - * [Supported debugging features](#supported-debugging-features) - * [Supported languages](#supported-languages) - * [Other languages](#other-languages) - * [Installation](#installation) - * [Quick Start](#quick-start) - * [Method 1: Using a repo clone, Vim packages and select gadgets to be installed](#method-2-using-a-repo-clone-vim-packages-and-select-gadgets-to-be-installed) - * [Method 2: Using a plugin manager](#method-3-using-a-plugin-manager) - * [Dependencies](#dependencies) - * [Neovim limitations](#neovim-limitations) - * [Windows differences](#windows-differences) - * [Trying it out](#trying-it-out) - * [Cloning the plugin](#cloning-the-plugin) - * [Install some gadgets](#install-some-gadgets) - * [VimspectorInstall and VimspectorUpdate commands](#vimspectorinstall-and-vimspectorupdate-commands) - * [install_gadget.py](#install_gadgetpy) - * [Manual gadget installation](#manual-gadget-installation) - * [The gadget directory](#the-gadget-directory) - * [Upgrade](#upgrade) - * [About](#about) - * [Background](#background) - * [What Vimspector is not](#what-vimspector-is-not) - * [Status](#status) - * [Experimental](#experimental) - * [Motivation](#motivation) - * [License](#license) - * [Sponsorship](#sponsorship) - * [Mappings](#mappings) - * [Visual Studio / VSCode](#visual-studio--vscode) - * [Human Mode](#human-mode) - * [Usage and API](#usage-and-api) - * [Launch and attach by PID:](#launch-and-attach-by-pid) - * [Picking a PID](#picking-a-pid) - * [Launch with options](#launch-with-options) - * [Debug configuration selection](#debug-configuration-selection) - * [Get configurations](#get-configurations) - * [Breakpoints](#breakpoints) - * [Breakpoints Window](#breakpoints-window) - * [Line breakpoints](#line-breakpoints) - * [Conditional breakpoints and logpoints](#conditional-breakpoints-and-logpoints) - * [Exception breakpoints](#exception-breakpoints) - * [API Summary](#api-summary) - * [Instruction breakpoints](#instruction-breakpoints) - * [Clear breakpoints](#clear-breakpoints) - * [Run to Cursor](#run-to-cursor) - * [Go to current line](#go-to-current-line) - * [Save and restore](#save-and-restore) - * [Stepping](#stepping) - * [Variables and scopes](#variables-and-scopes) - * [Variable or selection hover evaluation](#variable-or-selection-hover-evaluation) - * [Watches](#watches) - * [Watch autocompletion](#watch-autocompletion) - * [Disassembly](#disassembly) - * [Dump memory](#dump-memory) - * [Stack Traces](#stack-traces) - * [Child sessions](#child-sessions) - * [Program Output](#program-output) - * [Console](#console) - * [Console autocompletion](#console-autocompletion) - * [Log View](#log-view) - * [Closing debugger](#closing-debugger) - * [Terminate debuggee](#terminate-debuggee) - * [Multiple debugging sessions](#multiple-debugging-sessions) - * [Debug profile configuration](#debug-profile-configuration) - * [C, C , Rust, etc.](#c-c-rust-etc) - * [Data visualization / pretty printing](#data-visualization--pretty-printing) - * [C Remote debugging](#c-remote-debugging) - * [C Remote launch and attach](#c-remote-launch-and-attach) - * [Rust](#rust) - * [Jai](#jai) - * [Python](#python) - * [Python Remote Debugging](#python-remote-debugging) - * [Python Remote launch and attach](#python-remote-launch-and-attach) - * [Python 2](#python-2) - * [TCL](#tcl) - * [C♯](#c) - * [Go](#go) - * [PHP](#php) - * [Debug web application](#debug-web-application) - * [Debug cli application](#debug-cli-application) - * [JavaScript and TypeScript](#javascript-and-typescript) - * [Java](#java) - * [Hot code replace](#hot-code-replace) - * [Usage with YouCompleteMe](#usage-with-youcompleteme) - * [Other LSP clients](#other-lsp-clients) - * [Lua](#lua) - * [Other servers](#other-servers) - * [Customisation](#customisation) - * [Changing the default signs](#changing-the-default-signs) - * [Sign priority](#sign-priority) - * [Presentation Hints](#presentation-hints) - * [Changing the default window sizes](#changing-the-default-window-sizes) - * [Changing the terminal size](#changing-the-terminal-size) - * [Custom mappings while debugging](#custom-mappings-while-debugging) - * [Pre-launch building strategies](#pre-launch-building-strategies) - * [Disabling the WinBar](#disabling-the-winbar) - * [Advanced UI customisation](#advanced-ui-customisation) - * [Customising the WinBar](#customising-the-winbar) - * [Example](#example) - * [FAQ](#faq) - - +* [Features and Usage](#features-and-usage) + * [Supported debugging features](#supported-debugging-features) + * [Supported languages](#supported-languages) + * [Other languages](#other-languages) +* [Installation](#installation) + * [Quick Start](#quick-start) + * [Method 1: Using a repo clone, Vim packages and select gadgets to be installed](#method-1-using-a-repo-clone-vim-packages-and-select-gadgets-to-be-installed) + * [Method 2: Using a plugin manager](#method-2-using-a-plugin-manager) + * [Dependencies](#dependencies) + * [Neovim limitations](#neovim-limitations) + * [Windows differences](#windows-differences) + * [Trying it out](#trying-it-out) + * [Installing the plugin](#installing-the-plugin) + * [Install some gadgets](#install-some-gadgets) + * [VimspectorInstall and VimspectorUpdate commands](#vimspectorinstall-and-vimspectorupdate-commands) + * [install_gadget.py](#install_gadgetpy) + * [Manual gadget installation](#manual-gadget-installation) + * [The gadget directory](#the-gadget-directory) + * [Upgrade](#upgrade) +* [About](#about) + * [Background](#background) +* [What Vimspector is not](#what-vimspector-is-not) + * [Status](#status) + * [Experimental](#experimental) + * [Motivation](#motivation) + * [License](#license) + * [Sponsorship](#sponsorship) +* [Mappings](#mappings) + * [Visual Studio / VSCode](#visual-studio--vscode) + * [Human Mode](#human-mode) +* [Usage and API](#usage-and-api) + * [Launch and attach by PID:](#launch-and-attach-by-pid) + * [Picking a PID](#picking-a-pid) + * [Launch with options](#launch-with-options) + * [Debug configuration selection](#debug-configuration-selection) + * [Get configurations](#get-configurations) + * [Breakpoints](#breakpoints) + * [Breakpoints Window](#breakpoints-window) + * [Line breakpoints](#line-breakpoints) + * [Conditional breakpoints and logpoints](#conditional-breakpoints-and-logpoints) + * [Exception breakpoints](#exception-breakpoints) + * [Data breakpoints](#data-breakpoints) + * [API Summary](#api-summary) + * [Instruction breakpoints](#instruction-breakpoints) + * [Clear breakpoints](#clear-breakpoints) + * [Run to Cursor](#run-to-cursor) + * [Go to current line](#go-to-current-line) + * [Save and restore](#save-and-restore) + * [Stepping](#stepping) + * [Variables and scopes](#variables-and-scopes) + * [Variable or selection hover evaluation](#variable-or-selection-hover-evaluation) + * [Watches](#watches) + * [Watch autocompletion](#watch-autocompletion) + * [Disassembly](#disassembly) + * [Dump memory](#dump-memory) + * [Stack Traces](#stack-traces) + * [Child sessions](#child-sessions) + * [Program Output](#program-output) + * [Console](#console) + * [Console autocompletion](#console-autocompletion) + * [Log View](#log-view) + * [Closing debugger](#closing-debugger) + * [Terminate debuggee](#terminate-debuggee) +* [Multiple debugging sessions](#multiple-debugging-sessions) +* [Debug profile configuration](#debug-profile-configuration) + * [C, C++, Rust, etc.](#c-c-rust-etc) + * [Data visualization / pretty printing](#data-visualization--pretty-printing) + * [C++ Remote debugging](#c-remote-debugging) + * [C++ Remote launch and attach](#c-remote-launch-and-attach) + * [Rust](#rust) + * [Jai](#jai) + * [Python](#python) + * [Python Remote Debugging](#python-remote-debugging) + * [Python Remote launch and attach](#python-remote-launch-and-attach) + * [Python 2](#python-2) + * [TCL](#tcl) + * [C♯](#c) + * [Go](#go) + * [PHP](#php) + * [Debug web application](#debug-web-application) + * [Debug cli application](#debug-cli-application) + * [JavaScript and TypeScript](#javascript-and-typescript) + * [Java](#java) + * [Hot code replace](#hot-code-replace) + * [Usage with YouCompleteMe](#usage-with-youcompleteme) + * [Other LSP clients](#other-lsp-clients) + * [Lua](#lua) + * [Other servers](#other-servers) +* [Customisation](#customisation) + * [Changing the default signs](#changing-the-default-signs) + * [Sign priority](#sign-priority) + * [Presentation Hints](#presentation-hints) + * [Changing the default window sizes](#changing-the-default-window-sizes) + * [Changing the terminal size](#changing-the-terminal-size) + * [Custom mappings while debugging](#custom-mappings-while-debugging) + * [Pre-launch building strategies](#pre-launch-building-strategies) + * [Disabling the WinBar](#disabling-the-winbar) + * [Advanced UI customisation](#advanced-ui-customisation) + * [Customising the WinBar](#customising-the-winbar) + * [Example](#example) +* [FAQ](#faq) + + + @@ -137,6 +139,8 @@ And a couple of brief demos: - flexible configuration syntax that can be checked in to source control - breakpoints (function, line and exception breakpoints) +- instruction breakpoints +- data breakpoints - conditional breakpoints (function, line) - step in/out/over/up, stop, restart - run to cursor @@ -175,11 +179,10 @@ runtime dependencies). They are categorised by their level of support: | C, C++, Rust, Jai, etc. | Tested | `--enable-rust`, `--enable-c`, etc. | CodeLLDB | none | | Python | Tested | `--all` or `--enable-python` | debugpy | Python 3 | | Go | Tested | `--enable-go` | delve | Go 1.16+ | -| TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL 8.5 | +| TCL | Supported | `--all` or `--enable-tcl` | tclpro | TCL >= 8.5 < 9.0 | | Bourne Shell | Supported | `--all` or `--enable-bash` | vscode-bash-debug | Bash v?? | | Lua | Tested | `--all` or `--enable-lua` | local-lua-debugger-vscode | Node >=12.13.0, Npm, Lua interpreter | | Node.js | Supported | `--force-enable-node` | vscode-js-debug | Node >= 18 | -| Node.js (legacy) | Supported | `--force-enable-node_legacy` | vscode-node-debug2 | 6 < Node < 12, Npm | | Javascript | Supported | `--force-enable-chrome` | debugger-for-chrome | Chrome | | Javascript | Supported | `--force-enable-firefox` | vscode-firefox-debug | Firefox | | Java | Supported | `--force-enable-java ` | vscode-java-debug | Compatible LSP plugin (see [later](#java)) | @@ -475,7 +478,7 @@ Example: ```json { "adapters": { - "lldb-vscode": { + "lldb-dap": { "variables": { "LLVM": { "shell": "brew --prefix llvm" @@ -486,7 +489,7 @@ Example: "pidSelect": "ask" }, "command": [ - "${LLVM}/bin/lldb-vscode" + "lldb-dap" ], "env": { "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" @@ -1058,6 +1061,28 @@ then answer `Y` to that (for example). You can configure your choices in the `.vimspector.json`. See [the configuration guide][vimspector-ref-exception] for details on that. +### Data breakpoints + +Data breakpoints are not supported by all debug adapters. They are breakpoints +which trigger when some memory is read or written. They can be created: + +- For a given variable in the variables window (`` on variable) +- For a given child variable in the watches or variables windows + (`` on child variable) +- For an arbitrary expression which evaluates to an address (`` in watch + window, not on any variable) + +When specifying an expression, you can also specify a size. + +In general, if you hit `` (or whatever mapping you have) in the Variables or +Watch window, you'll be adding a Data Breakpoint. If the context looks like a +variable, then Vimspector will ask the debug adapter to create a data breakpoint +on that variable expression. Otherwise, you'll be asked to enter an expression, +or an address and a size, depending on the capabilities of the debugger. + +NOTE: Not all debug adapters support data breakpoints, and the ability to +actually create them often depends on the hardware of the target. + ### API Summary ***NOTE:*** Previously, ToggleBreakpoint would cycle between 3 states: @@ -1083,6 +1108,7 @@ deletes a breakpoint. If you wish to 'disable' breakpoints, use the * `call vimspector#ListBreakpoints()` - toggle breakpoints window * `call vimspector#BreakpointsAsQuickFix()` - return the current set of breakpoints in vim quickfix format +* `call vimspector#AddDataBreakpoint()` - add a data breakpoint Examples: @@ -1210,6 +1236,7 @@ autocmd SessionLoadPost * silent! VimspectorLoadSession * View the type of the variable via mouse hover. * When changing the stack frame the locals window updates. * While paused, hover to see values. +* Create a data breakpoint with ``. ![locals window](https://puremourning.github.io/vimspector-web/img/vimspector-locals-window.png) @@ -1260,6 +1287,7 @@ to add a new watch expression. * Set the value of the variable with `` (control + ``) or `` (if `modifyOtherKeys` doesn't work for you) * Delete with ``. +* Create a data breakpoint with ``. ![watch window](https://puremourning.github.io/vimspector-web/img/vimspector-watch-window.png) @@ -1572,14 +1600,16 @@ Currently tested with the following debug adapters. ## C, C++, Rust, etc. +* Recommended: [CodeLLDB](#rust) * [vscode-cpptools](https://github.com/Microsoft/vscode-cpptools) -* On macOS, I *strongly* recommend using [CodeLLDB](#rust) instead for C and C++ +* [lldb-dap](https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.lldb-dap) +* I *strongly* recommend using [CodeLLDB](#rust) over cpptools for almost all projects. It's really excellent, has fewer dependencies and doesn't open console apps in another Terminal window. -Example `.vimspector.json` (works with both `vscode-cpptools` and `lldb-vscode`. -For `lldb-vscode` replace the name of the adapter with `lldb-vscode`: +Example `.vimspector.json` (works with both `vscode-cpptools` and `lldb-dap`. +For `lldb-dap` replace the name of the adapter with `lldb-dap`: * vscode-cpptools Linux/MacOS: @@ -1635,6 +1665,31 @@ licensing. } ``` +* `lldb-dap` + +```json + + "lldb-dap": { + "adapter": { + "command": [ + // TODO: Replace this with the path to your installation of lldb + "/opt/homebrew/Cellar/llvm/bin/lldb-dap" + ], + "name": "lldb" + }, + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/${fileBasenameNoExtension}", + "args": [ + "*${args}" + ], + "stopOnEntry": true, + "runInTerminal": true, + "cwd": "${workspaceRoot}" + } + } +``` + ### Data visualization / pretty printing Depending on the backend you need to enable pretty printing of complex types @@ -1682,22 +1737,22 @@ an example of getting Vimspector to remotely launch and attach. * CodeLLDB (MacOS) -CodeLLDB is superior to vscode-cpptools in a number of ways on macOS at least. +CodeLLDB is superior to vscode-cpptools in a number of ways. See [Rust](#rust). -* lldb-vscode (MacOS) +* lldb-dap (MacOS) -An alternative is to to use `lldb-vscode`, which comes with llvm. Here's how: +An alternative is to to use `lldb-dap`, which comes with llvm. Here's how: * Install llvm (e.g. with HomeBrew: `brew install llvm`) * Create a file named - `/path/to/vimspector/gadgets/macos/.gadgets.d/lldb-vscode.json`: + `/path/to/vimspector/gadgets/macos/.gadgets.d/lldb-dap.json`: ```json { "adapters": { - "lldb-vscode": { + "lldb-dap": { "variables": { "LLVM": { "shell": "brew --prefix llvm" @@ -1708,7 +1763,7 @@ An alternative is to to use `lldb-vscode`, which comes with llvm. Here's how: "pidSelect": "ask" }, "command": [ - "${LLVM}/bin/lldb-vscode" + "${LLVM}/bin/lldb-dap" ], "env": { "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" @@ -1722,7 +1777,7 @@ An alternative is to to use `lldb-vscode`, which comes with llvm. Here's how: ## Rust Rust is supported with any gdb/lldb-based debugger. So it works fine with -`vscode-cpptools` and `lldb-vscode` above. However, support for rust is best in +`vscode-cpptools` and `lldb-dap` above. However, support for rust is best in [`CodeLLDB`](https://github.com/vadimcn/vscode-lldb#features). * `./install_gadget.py --enable-rust` or `:VimspectorInstall CodeLLDB` @@ -1736,7 +1791,8 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with "filetypes": [ "rust" ], "configuration": { "request": "launch", - "program": "${workspaceRoot}/target/debug/vimspector_test" + "program": "${workspaceRoot}/target/debug/vimspector_test", + "sourceLanguages": [ "rust" ] } }, "attach": { @@ -1745,7 +1801,8 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with "configuration": { "request": "attach", "program": "${workspaceRoot}/${fileBasenameNoExtension}", - "PID": "${PID}" + "PID": "${PID}", + "sourceLanguages": [ "rust" ] } } } @@ -1934,6 +1991,8 @@ for examk * TCL (TclProDebug) +Requires TCL 8.x. Does not work with TCL 9. + See [my fork of TclProDebug](https://github.com/puremourning/TclProDebug) for instructions. ## C♯ @@ -2172,41 +2231,6 @@ multiple debug sessions. For a user, that shouldn't change anything (other than perhaps a slightly confusing stack trace). But it does make things more complicated and so there may be subtle bugs. -* Node.js (legacy) - -**NOTE**: This configuration uses the *deprecated* legacy debug adapter and will -be removed in future. Please update your configurations to use the `js-debug` -adapter. You _may_ be able to just change the adapter name. - -Requires: - -* `install_gadget.py --force-enable-node` -* For installation, a Node.js environment that is < node 12. I believe this is an - incompatibility with gulp. Advice, use [nvm](https://github.com/nvm-sh/nvm) with `nvm install --lts 10; nvm - use --lts 10; ./install_gadget.py --force-enable-node ...` -* Options described here: - https://code.visualstudio.com/docs/nodejs/nodejs-debugging -* Example: `support/test/node/simple` - -```json -{ - "configurations": { - "run": { - "adapter": "vscode-node", - "filetypes": [ "javascript", "typescript" ], // optional - "configuration": { - "request": "launch", - "protocol": "auto", - "stopOnEntry": true, - "console": "integratedTerminal", - "program": "${workspaceRoot}/simple.js", - "cwd": "${workspaceRoot}" - } - } - } -} -``` - * Chrome/Firefox This uses the chrome/firefox debugger (they are very similar), see diff --git a/autoload/vimspector.vim b/autoload/vimspector.vim index 4785399e7..1e4ecc22d 100644 --- a/autoload/vimspector.vim +++ b/autoload/vimspector.vim @@ -439,6 +439,14 @@ function! vimspector#ShowDisassembly( ... ) abort py3 _vimspector_session.ShowDisassembly() endfunction +function! vimspector#AddDataBreakpoint( ... ) abort + if !s:Enabled() + return + endif + " TODO: how to set options? + py3 _vimspector_session.AddDataBreakpoint( {} ) +endfunction + function! vimspector#DeleteWatch() abort if !s:Enabled() return diff --git a/dev_requirements.txt b/dev_requirements.txt index f24ae6df5..12e336c20 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -1,6 +1,6 @@ -flake8 == 3.8.3 -flake8-comprehensions == 3.2.3 -flake8-ycm >= 0.1.0 +flake8 >= 3.0.0 +flake8-comprehensions +flake8-ycm >= 0.1.0 # asciinema is used to record the output in case of failure # asciinema >= 2.2.0 diff --git a/doc/vimspector.txt b/doc/vimspector.txt index eb5b058ef..353fc381a 100644 --- a/doc/vimspector.txt +++ b/doc/vimspector.txt @@ -45,12 +45,13 @@ Contents ~ 2. Line breakpoints |vimspector-line-breakpoints| 3. Conditional breakpoints and logpoints |vimspector-conditional-breakpoints-logpoints| 4. Exception breakpoints |vimspector-exception-breakpoints| - 5. API Summary |vimspector-api-summary| - 6. Instruction breakpoints |vimspector-instruction-breakpoints| - 7. Clear breakpoints |vimspector-clear-breakpoints| - 8. Run to Cursor |vimspector-run-to-cursor| - 9. Go to current line |vimspector-go-to-current-line| - 10. Save and restore |vimspector-save-restore| + 5. Data breakpoints |vimspector-data-breakpoints| + 6. API Summary |vimspector-api-summary| + 7. Instruction breakpoints |vimspector-instruction-breakpoints| + 8. Clear breakpoints |vimspector-clear-breakpoints| + 9. Run to Cursor |vimspector-run-to-cursor| + 10. Go to current line |vimspector-go-to-current-line| + 11. Save and restore |vimspector-save-restore| 3. Stepping |vimspector-stepping| 4. Variables and scopes |vimspector-variables-scopes| 5. Variable or selection hover evaluation |vimspector-variable-or-selection-hover-evaluation| @@ -118,121 +119,134 @@ guide [2]. Image: Build [3] Image: Matrix [5] Image: Gitter [7] - Features and Usage - - - Supported debugging features - - Supported languages - - Other languages - +- Supported debugging features +- Supported languages +- Other languages - Installation +- Quick Start - - Quick Start - Method 1: Using a repo clone, Vim packages and select gadgets to be installed - Method 2: Using a plugin manager - - Dependencies + +- Dependencies + - Neovim limitations - Windows differences - - Trying it out - - Cloning the plugin - - Install some gadgets + +- Trying it out +- Installing the plugin +- Install some gadgets + - VimspectorInstall and VimspectorUpdate commands - install_gadget.py - - Manual gadget installation - - The gadget directory - - Upgrade -- About +- Manual gadget installation - - Background + - The gadget directory +- Upgrade +- About +- Background - What Vimspector is not +- Status - - Status - Experimental - - Motivation - - License - - Sponsorship +- Motivation +- License +- Sponsorship - Mappings - - - Visual Studio / VSCode - - Human Mode - +- Visual Studio / VSCode +- Human Mode - Usage and API +- Launch and attach by PID: - - Launch and attach by PID: - Picking a PID - Launch with options - Debug configuration selection - Get configurations - - Breakpoints + +- Breakpoints + - Breakpoints Window - Line breakpoints - Conditional breakpoints and logpoints - Exception breakpoints + - Data breakpoints - API Summary - Instruction breakpoints - Clear breakpoints - Run to Cursor - Go to current line - Save and restore - - Stepping - - Variables and scopes - - Variable or selection hover evaluation - - Watches + +- Stepping +- Variables and scopes +- Variable or selection hover evaluation +- Watches + - Watch autocompletion - - Disassembly - - Dump memory - - Stack Traces + +- Disassembly +- Dump memory +- Stack Traces + - Child sessions - - Program Output + +- Program Output + - Console - Console autocompletion - Log View - - Closing debugger - - Terminate debuggee +- Closing debugger +- Terminate debuggee - Multiple debugging sessions - Debug profile configuration +- C, C++, Rust, etc. - - C, C , Rust, etc. - Data visualization / pretty printing - - C Remote debugging - - C Remote launch and attach - - Rust - - Jai - - Python + - C++ Remote debugging + - C++ Remote launch and attach + +- Rust +- Jai +- Python + - Python Remote Debugging - Python Remote launch and attach - Python 2 - - TCL - - C♯ - - Go - - PHP + +- TCL +- C♯ +- Go +- PHP + - Debug web application - Debug cli application - - JavaScript and TypeScript - - Java + +- JavaScript and TypeScript +- Java + - Hot code replace - Usage with YouCompleteMe - Other LSP clients - - Lua - - Other servers +- Lua +- Other servers - Customisation - - - Changing the default signs - - Sign priority - - Presentation Hints - - Changing the default window sizes - - Changing the terminal size - - Custom mappings while debugging - - Pre-launch building strategies - - Disabling the WinBar - - Advanced UI customisation - - Customising the WinBar - - Example - +- Changing the default signs +- Sign priority +- Presentation Hints +- Changing the default window sizes +- Changing the terminal size +- Custom mappings while debugging +- Pre-launch building strategies +- Disabling the WinBar +- Advanced UI customisation +- Customising the WinBar +- Example - FAQ =============================================================================== @@ -262,6 +276,8 @@ Supported debugging features ~ - flexible configuration syntax that can be checked in to source control - breakpoints (function, line and exception breakpoints) +- instruction breakpoints +- data breakpoints - conditional breakpoints (function, line) - step in/out/over/up, stop, restart - run to cursor @@ -308,7 +324,7 @@ runtime dependencies). They are categorised by their level of support: -------------------------------------------------------------------------------------------------------------------------------------------------------------- | Go | Tested | '--enable-go' | delve | Go 1.16+ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- -| TCL | Supported | '--all' or '--enable-tcl' | tclpro | TCL 8.5 | +| TCL | Supported | '--all' or '--enable-tcl' | tclpro | TCL >= 8.5 < 9.0 | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | Bourne Shell | Supported | '--all' or '--enable-bash' | vscode-bash-debug | Bash v?? | -------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -316,8 +332,6 @@ runtime dependencies). They are categorised by their level of support: -------------------------------------------------------------------------------------------------------------------------------------------------------------- | Node.js | Supported | '--force-enable-node' | vscode-js-debug | Node >= 18 | -------------------------------------------------------------------------------------------------------------------------------------------------------------- -| Node.js (legacy) | Supported | '--force-enable-node_legacy' | vscode-node-debug2 | 6 < Node < 12, Npm | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | Javascript | Supported | '--force-enable-chrome' | debugger-for-chrome | Chrome | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | Javascript | Supported | '--force-enable-firefox' | vscode-firefox-debug | Firefox | @@ -646,7 +660,7 @@ Example: > { "adapters": { - "lldb-vscode": { + "lldb-dap": { "variables": { "LLVM": { "shell": "brew --prefix llvm" @@ -657,7 +671,7 @@ Example: "pidSelect": "ask" }, "command": [ - "${LLVM}/bin/lldb-vscode" + "lldb-dap" ], "env": { "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" @@ -1303,6 +1317,33 @@ exception' then answer 'Y' to that (for example). You can configure your choices in the '.vimspector.json'. See the configuration guide [26] for details on that. +------------------------------------------------------------------------------- + *vimspector-data-breakpoints* +Data breakpoints ~ + +Data breakpoints are not supported by all debug adapters. They are breakpoints +which trigger when some memory is read or written. They can be created: + +- For a given variable in the variables window ('' on variable) + +- For a given child variable in the watches or variables windows ('' on + child variable) + +- For an arbitrary expression which evaluates to an address ('' in watch + window, not on any variable) + +When specifying an expression, you can also specify a size. + +In general, if you hit '' (or whatever mapping you have) in the Variables +or Watch window, you'll be adding a Data Breakpoint. If the context looks like +a variable, then Vimspector will ask the debug adapter to create a data +breakpoint on that variable expression. Otherwise, you'll be asked to enter an +expression, or an address and a size, depending on the capabilities of the +debugger. + +NOTE: Not all debug adapters support data breakpoints, and the ability to +actually create them often depends on the hardware of the target. + ------------------------------------------------------------------------------- *vimspector-api-summary* API Summary ~ @@ -1340,6 +1381,8 @@ and 'toggle' ('t') from there. - 'call vimspector#BreakpointsAsQuickFix()' - return the current set of breakpoints in vim quickfix format +- 'call vimspector#AddDataBreakpoint()' - add a data breakpoint + Examples: - 'call vimspector#ToggleBreakpoint()' - toggle breakpoint on current line @@ -1489,6 +1532,7 @@ Variables and scopes ~ - View the type of the variable via mouse hover. - When changing the stack frame the locals window updates. - While paused, hover to see values. +- Create a data breakpoint with ''. Image: locals window (see reference [28]) @@ -1547,6 +1591,7 @@ mode to add a new watch expression. - Set the value of the variable with '' (control + '') or '' (if 'modifyOtherKeys' doesn't work for you) - Delete with ''. +- Create a data breakpoint with ''. Image: watch window (see reference [30]) @@ -1892,15 +1937,15 @@ Currently tested with the following debug adapters. *vimspector-c-c-rust-etc.* C, C++, Rust, etc. ~ +- Recommended: CodeLLDB - vscode-cpptools [37] - -- On macOS, I _strongly_ recommend using CodeLLDB instead for C and C++ +- lldb-dap [38] +- I _strongly_ recommend using CodeLLDB over cpptools for almost all projects. It's really excellent, has fewer dependencies and doesn't open console apps in another Terminal window. -Example '.vimspector.json' (works with both 'vscode-cpptools' and -'lldb-vscode'. For 'lldb-vscode' replace the name of the adapter with -'lldb-vscode': +Example '.vimspector.json' (works with both 'vscode-cpptools' and 'lldb-dap'. +For 'lldb-dap' replace the name of the adapter with 'lldb-dap': - vscode-cpptools Linux/MacOS: > @@ -1952,6 +1997,28 @@ licensing. } } < +- 'lldb-dap' +> + "lldb-dap": { + "adapter": { + "command": [ + // TODO: Replace this with the path to your installation of lldb + "/opt/homebrew/Cellar/llvm/bin/lldb-dap" + ], + "name": "lldb" + }, + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/${fileBasenameNoExtension}", + "args": [ + "*${args}" + ], + "stopOnEntry": true, + "runInTerminal": true, + "cwd": "${workspaceRoot}" + } + } +< ------------------------------------------------------------------------------- *vimspector-data-visualization-pretty-printing* Data visualization / pretty printing ~ @@ -1998,26 +2065,26 @@ The cpptools documentation describes how to attach cpptools to gdbserver using *vimspector-c-remote-launch-attach* C++ Remote launch and attach ~ -If you're feeling fancy, check out the reference guide [38] for an example of +If you're feeling fancy, check out the reference guide [39] for an example of getting Vimspector to remotely launch and attach. - CodeLLDB (MacOS) -CodeLLDB is superior to vscode-cpptools in a number of ways on macOS at least. +CodeLLDB is superior to vscode-cpptools in a number of ways. See Rust. -- lldb-vscode (MacOS) +- lldb-dap (MacOS) -An alternative is to to use 'lldb-vscode', which comes with llvm. Here's how: +An alternative is to to use 'lldb-dap', which comes with llvm. Here's how: - Install llvm (e.g. with HomeBrew: 'brew install llvm') - Create a file named - '/path/to/vimspector/gadgets/macos/.gadgets.d/lldb-vscode.json': + '/path/to/vimspector/gadgets/macos/.gadgets.d/lldb-dap.json': > { "adapters": { - "lldb-vscode": { + "lldb-dap": { "variables": { "LLVM": { "shell": "brew --prefix llvm" @@ -2028,7 +2095,7 @@ An alternative is to to use 'lldb-vscode', which comes with llvm. Here's how: "pidSelect": "ask" }, "command": [ - "${LLVM}/bin/lldb-vscode" + "${LLVM}/bin/lldb-dap" ], "env": { "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" @@ -2043,8 +2110,8 @@ An alternative is to to use 'lldb-vscode', which comes with llvm. Here's how: Rust ~ Rust is supported with any gdb/lldb-based debugger. So it works fine with -'vscode-cpptools' and 'lldb-vscode' above. However, support for rust is best in -'CodeLLDB' [39]. +'vscode-cpptools' and 'lldb-dap' above. However, support for rust is best in +'CodeLLDB' [40]. - './install_gadget.py --enable-rust' or ':VimspectorInstall CodeLLDB' - Example: 'support/test/rust/vimspector_test' @@ -2056,7 +2123,8 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with "filetypes": [ "rust" ], "configuration": { "request": "launch", - "program": "${workspaceRoot}/target/debug/vimspector_test" + "program": "${workspaceRoot}/target/debug/vimspector_test", + "sourceLanguages": [ "rust" ] } }, "attach": { @@ -2065,7 +2133,8 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with "configuration": { "request": "attach", "program": "${workspaceRoot}/${fileBasenameNoExtension}", - "PID": "${PID}" + "PID": "${PID}", + "sourceLanguages": [ "rust" ] } } } @@ -2078,14 +2147,14 @@ Rust is supported with any gdb/lldb-based debugger. So it works fine with load of javascript nonesense behind every VSCode plugin. I can't possibly document all the wierdnesses, but the following are known -- To use the "custom" launch [40], you can't use '"request": "custom"' - this +- To use the "custom" launch [41], you can't use '"request": "custom"' - this is invalid. Instead use '"request": "launch", "custom": true'. Because - reasons [41] + reasons [42] - All the integration with 'cargo' is done in the vscode javascript madness, so is not supported. -- The stuff about remote agents [42] uses '"request": custom'; see the point +- The stuff about remote agents [43] uses '"request": custom'; see the point about "custom" launch above - Source Mapping (i.e., enabling 'step-into' for standard library functions) @@ -2160,13 +2229,13 @@ Example: } } < - Image: Screenshot 2022-10-09 at 11 27 13 (see reference [43]) + Image: Screenshot 2022-10-09 at 11 27 13 (see reference [44]) ------------------------------------------------------------------------------- *vimspector-python* Python ~ -- Python: debugpy [44] +- Python: debugpy [45] - Install with 'install_gadget.py --enable-python' or ':VimspectorInstall debugpy', ideally requires a working compiler and the python development @@ -2210,7 +2279,7 @@ little different from how we normally configure things. Specifically, you need to: - Start your application with debugpy, specifying the '--listen' argument. - See the debugpy documentation [45] for details. + See the debugpy documentation [46] for details. - Use the built-in "multi-session" adapter. This just asks for the host/port to connect to. For example: @@ -2230,17 +2299,17 @@ to: } } < -See details of the launch configuration [46] for explanation of things like +See details of the launch configuration [47] for explanation of things like 'pathMappings'. Additional documentation, including how to do this when the remote machine can -only be contacted via SSH are provided by debugpy [47]. +only be contacted via SSH are provided by debugpy [48]. ------------------------------------------------------------------------------- *vimspector-python-remote-launch-attach* Python Remote launch and attach ~ -If you're feeling fancy, checkout the reference guide [38] for an example of +If you're feeling fancy, checkout the reference guide [39] for an example of getting Vimspector to remotely launch and attach. ------------------------------------------------------------------------------- @@ -2269,7 +2338,9 @@ TCL ~ - TCL (TclProDebug) -See my fork of TclProDebug [48] for instructions. +Requires TCL 8.x. Does not work with TCL 9. + +See my fork of TclProDebug [49] for instructions. ------------------------------------------------------------------------------- *vimspector-c* @@ -2335,21 +2406,21 @@ Use Variables to configure the following: The debugger (delve) is launched in a terminal window so that you can see its output and pass input to the debuggee. -See vscode-go docs [49] for full launch options. Yes, it seems that's the only +See vscode-go docs [50] for full launch options. Yes, it seems that's the only place they are documented (apparently, they are not documented by delve itself). -The vscode-go docs also have useful troubleshooting information [50] +The vscode-go docs also have useful troubleshooting information [51] - Go (legacy vscode-go) Requires: - 'install_gadget.py --enable-go' or ':VimspectorInstall vscode-go' -- Delve [51] installed, e.g. 'go get -u github.com/go-delve/delve/cmd/dlv' +- Delve [52] installed, e.g. 'go get -u github.com/go-delve/delve/cmd/dlv' - Delve to be in your PATH, or specify the 'dlvToolPath' launch option -NOTE: Vimspector uses the "legacy" vscode-go debug adapter [52] rather than the +NOTE: Vimspector uses the "legacy" vscode-go debug adapter [53] rather than the "built-in" DAP support in Delve. You can track https://github.com/puremourning/vimspector/issues/186 for that. > @@ -2370,7 +2441,7 @@ https://github.com/puremourning/vimspector/issues/186 for that. } } < -See the vscode-go docs for troubleshooting information [53] +See the vscode-go docs for troubleshooting information [54] ------------------------------------------------------------------------------- *vimspector-php* @@ -2464,8 +2535,8 @@ JavaScript and TypeScript ~ - Node.js -This uses vscode-js-debug [54], the debugger that is used in vscode as well. -For additional configurations, check the documentation here [55]. +This uses vscode-js-debug [55], the debugger that is used in vscode as well. +For additional configurations, check the documentation here [56]. To install vscode-js-debug, run 'VimspectorInstall vscode-js-debug' from vim or run the install script 'install_gadget.py --force-enable-node'. There are @@ -2500,7 +2571,7 @@ typescript looks like this: < 'vscode-js-debug' supports a number of different "types" and can do some stuff that may or may not work. The 'type' field is sadly not documented, but the -valid values are defined here in the DebugType enum [56]. +valid values are defined here in the DebugType enum [57]. Vimspector has only been tested with 'pwa-node' type. @@ -2509,42 +2580,6 @@ multiple debug sessions. For a user, that shouldn't change anything (other than perhaps a slightly confusing stack trace). But it does make things more complicated and so there may be subtle bugs. -- Node.js (legacy) - -**NOTE**: This configuration uses the _deprecated_ legacy debug adapter and -will be removed in future. Please update your configurations to use the -'js-debug' adapter. You _may_ be able to just change the adapter name. - -Requires: - -- 'install_gadget.py --force-enable-node' - -- For installation, a Node.js environment that is < node 12. I believe this - is an incompatibility with gulp. Advice, use nvm [57] with 'nvm install - --lts 10; nvm use --lts 10; ./install_gadget.py --force-enable-node ...' - -- Options described here: - https://code.visualstudio.com/docs/nodejs/nodejs-debugging - -- Example: 'support/test/node/simple' -> - { - "configurations": { - "run": { - "adapter": "vscode-node", - "filetypes": [ "javascript", "typescript" ], // optional - "configuration": { - "request": "launch", - "protocol": "auto", - "stopOnEntry": true, - "console": "integratedTerminal", - "program": "${workspaceRoot}/simple.js", - "cwd": "${workspaceRoot}" - } - } - } - } -< - Chrome/Firefox This uses the chrome/firefox debugger (they are very similar), see https://mark @@ -3331,26 +3366,26 @@ References ~ [35] https://user-images.githubusercontent.com/10584846/232473234-666d1a77-81f2-40d5-bc65-ebab774888ce.png [36] https://puremourning.github.io/vimspector-web/img/vimspector-output-window.png [37] https://github.com/Microsoft/vscode-cpptools -[38] https://puremourning.github.io/vimspector/configuration.html#remote-debugging-support -[39] https://github.com/vadimcn/vscode-lldb#features -[40] https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#custom-launch -[41] https://github.com/vadimcn/vscode-lldb/blob/master/extension/main.ts#L397-L401 -[42] https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#connecting-to-a-gdbserver-style-agent -[43] https://user-images.githubusercontent.com/10584846/194751648-72419216-2e4c-4ddc-adf7-9008f7e4f3c2.png -[44] https://github.com/microsoft/debugpy -[45] https://github.com/microsoft/debugpy#debugpy-cli-usage -[46] https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings -[47] https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH -[48] https://github.com/puremourning/TclProDebug -[49] https://github.com/golang/vscode-go/blob/master/docs/debugging.md#launchjson-attributes -[50] https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting -[51] https://github.com/go-delve/delve/tree/master/Documentation/installation -[52] https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md -[53] https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md#troubleshooting -[54] https://github.com/microsoft/vscode-js-debug -[55] https://github.com/microsoft/vscode-js-debug/blob/main/OPTIONS.md -[56] https://github.com/microsoft/vscode-js-debug/blob/main/src/common/contributionUtils.ts#L61 -[57] https://github.com/nvm-sh/nvm +[38] https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.lldb-dap +[39] https://puremourning.github.io/vimspector/configuration.html#remote-debugging-support +[40] https://github.com/vadimcn/vscode-lldb#features +[41] https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#custom-launch +[42] https://github.com/vadimcn/vscode-lldb/blob/master/extension/main.ts#L397-L401 +[43] https://github.com/vadimcn/vscode-lldb/blob/master/MANUAL.md#connecting-to-a-gdbserver-style-agent +[44] https://user-images.githubusercontent.com/10584846/194751648-72419216-2e4c-4ddc-adf7-9008f7e4f3c2.png +[45] https://github.com/microsoft/debugpy +[46] https://github.com/microsoft/debugpy#debugpy-cli-usage +[47] https://github.com/microsoft/debugpy/wiki/Debug-configuration-settings +[48] https://github.com/microsoft/debugpy/wiki/Debugging-over-SSH +[49] https://github.com/puremourning/TclProDebug +[50] https://github.com/golang/vscode-go/blob/master/docs/debugging.md#launchjson-attributes +[51] https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting +[52] https://github.com/go-delve/delve/tree/master/Documentation/installation +[53] https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md +[54] https://github.com/golang/vscode-go/blob/master/docs/debugging-legacy.md#troubleshooting +[55] https://github.com/microsoft/vscode-js-debug +[56] https://github.com/microsoft/vscode-js-debug/blob/main/OPTIONS.md +[57] https://github.com/microsoft/vscode-js-debug/blob/main/src/common/contributionUtils.ts#L61 [58] https://github.com/Microsoft/java-debug [59] https://github.com/ycm-core/YouCompleteMe#java-semantic-completion [60] https://github.com/ycm-core/YouCompleteMe#troubleshooting diff --git a/docs/Gemfile b/docs/Gemfile index 18f79a6e6..c83685cd2 100644 --- a/docs/Gemfile +++ b/docs/Gemfile @@ -29,4 +29,4 @@ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby] gem "wdm", "~> 0.1.0" if Gem.win_platform? -gem "webrick", "~> 1.7" +gem "webrick", "~> 1.8" diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index b5a74e7c8..7185dbe68 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -224,7 +224,7 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) - rexml (3.3.3) + rexml (3.3.6) strscan rouge (3.26.0) ruby2_keywords (0.0.5) @@ -251,7 +251,7 @@ GEM unf_ext unf_ext (0.0.8.2) unicode-display_width (1.8.0) - webrick (1.8.1) + webrick (1.8.2) PLATFORMS ruby @@ -261,7 +261,7 @@ DEPENDENCIES jekyll-feed (~> 0.6) minima (~> 2.0) tzinfo-data - webrick (~> 1.7) + webrick (~> 1.8) BUNDLED WITH 2.3.8 diff --git a/docs/schema/vimspector.schema.json b/docs/schema/vimspector.schema.json index 7b319637a..6445d577e 100644 --- a/docs/schema/vimspector.schema.json +++ b/docs/schema/vimspector.schema.json @@ -113,6 +113,11 @@ "type": "string", "description": "Name or container id of the docker run container to connect to (via docker exec). Note the container must already be running (Vimspector will not start it) and it must have the port forwarded to the host if subsequently connecting via a port (for example docker run -p 8765:8765 -it simple_python)." }, + "docker_args": { + "type": "array", + "items": {"type": "string"}, + "description": "Extra command line args to pass to docker exec." + }, "ssh": { "type": "object", "description": "Optional to customize the ssh client and its arguments to execute for remote-launch or remote-attach.", diff --git a/gh-md-toc b/gh-md-toc index 792d6ff5c..35239bf5f 100755 --- a/gh-md-toc +++ b/gh-md-toc @@ -14,7 +14,7 @@ # substr($0, length($0), 1) # # 3.2 Get level from 3.1 and insert corresponding number of spaces before '*': -# sprintf("%*s", substr($0, length($0), 1)*3, " ") +# sprintf("%*s", (level-1)*'"$nb_spaces"', "") # # 4. Find head's text and insert it inside "* [ ... ]": # substr($0, match($0, /a>.*<\/h/)+2, RLENGTH-5) @@ -23,7 +23,7 @@ # substr($0, match($0, "href=\"[^\"]+?\" ")+6, RLENGTH-8) # -gh_toc_version="0.6.1" +gh_toc_version="0.10.0" gh_user_agent="gh-md-toc v$gh_toc_version" @@ -47,23 +47,44 @@ gh_toc_load() { # # Converts local md file into html by GitHub # -# ➥ curl -X POST --data '{"text": "Hello world github/linguist#1 **cool**, and #1!"}' https://api.github.com/markdown +# -> curl -X POST --data '{"text": "Hello world github/linguist#1 **cool**, and #1!"}' https://api.github.com/markdown #

Hello world github/linguist#1 cool, and #1!

'" gh_toc_md2html() { local gh_file_md=$1 + local skip_header=$2 + URL=https://api.github.com/markdown/raw - if [ ! -z "$GH_TOC_TOKEN" ]; then + + if [ -n "$GH_TOC_TOKEN" ]; then TOKEN=$GH_TOC_TOKEN else - TOKEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" + TOKEN_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" + if [ -f "$TOKEN_FILE" ]; then + TOKEN="$(cat "$TOKEN_FILE")" + fi fi - if [ -f "$TOKEN" ]; then - URL="$URL?access_token=$(cat $TOKEN)" + if [ -n "${TOKEN}" ]; then + AUTHORIZATION="Authorization: token ${TOKEN}" + fi + + local gh_tmp_file_md=$gh_file_md + if [ "$skip_header" = "yes" ]; then + if grep -Fxq "" "$gh_src"; then + # cut everything before the toc + gh_tmp_file_md=$gh_file_md~~ + sed '1,//d' "$gh_file_md" > "$gh_tmp_file_md" + fi fi + # echo $URL 1>&2 - OUTPUT="$(curl -s --user-agent "$gh_user_agent" \ - --data-binary @"$gh_file_md" -H "Content-Type:text/plain" \ - $URL)" + OUTPUT=$(curl -s \ + --user-agent "$gh_user_agent" \ + --data-binary @"$gh_tmp_file_md" \ + -H "Content-Type:text/plain" \ + -H "$AUTHORIZATION" \ + "$URL") + + rm -f "${gh_file_md}~~" if [ "$?" != "0" ]; then echo "XXNetworkErrorXX" @@ -96,6 +117,10 @@ gh_toc(){ local gh_src_copy=$1 local gh_ttl_docs=$2 local need_replace=$3 + local no_backup=$4 + local no_footer=$5 + local indent=$6 + local skip_header=$7 if [ "$gh_src" = "" ]; then echo "Please, enter URL or local path for a README.md" @@ -114,7 +139,7 @@ gh_toc(){ fi if [ "$(gh_is_url "$gh_src")" == "yes" ]; then - gh_toc_load "$gh_src" | gh_toc_grab "$gh_src_copy" + gh_toc_load "$gh_src" | gh_toc_grab "$gh_src_copy" "$indent" if [ "${PIPESTATUS[0]}" != "0" ]; then echo "Could not load remote document." echo "Please check your url or network connectivity" @@ -127,7 +152,8 @@ gh_toc(){ echo fi else - local rawhtml=$(gh_toc_md2html "$gh_src") + local rawhtml + rawhtml=$(gh_toc_md2html "$gh_src" "$skip_header") if [ "$rawhtml" == "XXNetworkErrorXX" ]; then echo "Parsing local markdown file requires access to github API" echo "Please make sure curl is installed and check your network connectivity" @@ -136,14 +162,15 @@ gh_toc(){ if [ "$rawhtml" == "XXRateLimitXX" ]; then echo "Parsing local markdown file requires access to github API" echo "Error: You exceeded the hourly limit. See: https://developer.github.com/v3/#rate-limiting" - TOKEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" - echo "or place github auth token here: $TOKEN" + TOKEN_FILE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" + echo "or place GitHub auth token here: ${TOKEN_FILE}" exit 1 fi - local toc=`echo "$rawhtml" | gh_toc_grab "$gh_src_copy"` + local toc + toc=`echo "$rawhtml" | gh_toc_grab "$gh_src_copy" "$indent"` echo "$toc" if [ "$need_replace" = "yes" ]; then - if grep -Fxq "" $gh_src && grep -Fxq "" $gh_src; then + if grep -Fxq "" "$gh_src" && grep -Fxq "" "$gh_src"; then echo "Found markers" else echo "You don't have or in your file...exiting" @@ -151,26 +178,37 @@ gh_toc(){ fi local ts="<\!--ts-->" local te="<\!--te-->" - local dt=`date +'%F_%H%M%S'` + local dt + dt=$(date +'%F_%H%M%S') local ext=".orig.${dt}" local toc_path="${gh_src}.toc.${dt}" - local toc_footer="" + local toc_createdby="" + local toc_footer + toc_footer="" # http://fahdshariff.blogspot.ru/2012/12/sed-mutli-line-replacement-between-two.html # clear old TOC - sed -i${ext} "/${ts}/,/${te}/{//!d;}" "$gh_src" + sed -i"${ext}" "/${ts}/,/${te}/{//!d;}" "$gh_src" # create toc file echo "${toc}" > "${toc_path}" - echo -e "\n${toc_footer}\n" >> "$toc_path" + if [ "${no_footer}" != "yes" ]; then + echo -e "\n${toc_createdby}\n${toc_footer}\n" >> "$toc_path" + fi + # insert toc file - if [[ "`uname`" == "Darwin" ]]; then + if ! sed --version > /dev/null 2>&1; then sed -i "" "/${ts}/r ${toc_path}" "$gh_src" else sed -i "/${ts}/r ${toc_path}" "$gh_src" fi echo + if [ "${no_backup}" = "yes" ]; then + rm "$toc_path" "$gh_src$ext" + fi echo "!! TOC was added into: '$gh_src'" - echo "!! Origin version of the file: '${gh_src}${ext}'" - echo "!! TOC added into a separate file: '${toc_path}'" + if [ -z "${no_backup}" ]; then + echo "!! Origin version of the file: '${gh_src}${ext}'" + echo "!! TOC added into a separate file: '${toc_path}'" + fi echo fi fi @@ -179,33 +217,81 @@ gh_toc(){ # # Grabber of the TOC from rendered html # -# $1 — a source url of document. -# It's need if TOC is generated for multiple documents. +# $1 - a source url of document. +# It's need if TOC is generated for multiple documents. +# $2 - number of spaces used to indent. # gh_toc_grab() { - # if closed is on the new line, then move it on the prev line - # for example: - # was: The command foo1 - # - # became: The command foo1 + + href_regex="/href=\"[^\"]+?\"/" + common_awk_script=' + modified_href = "" + split(href, chars, "") + for (i=1;i <= length(href); i++) { + c = chars[i] + res = "" + if (c == "+") { + res = " " + } else { + if (c == "%") { + res = "\\x" + } else { + res = c "" + } + } + modified_href = modified_href res + } + print sprintf("%*s", (level-1)*'"$2"', "") "* [" text "](" gh_url modified_href ")" + ' + if [ "`uname -s`" == "OS/390" ]; then + grepcmd="pcregrep -o" + echoargs="" + awkscript='{ + level = substr($0, 3, 1) + text = substr($0, match($0, /<\/span><\/a>[^<]*<\/h/)+11, RLENGTH-14) + href = substr($0, match($0, '$href_regex')+6, RLENGTH-7) + '"$common_awk_script"' + }' + else + grepcmd="grep -Eo" + echoargs="-e" + awkscript='{ + level = substr($0, 3, 1) + text = substr($0, match($0, /">.*<\/h/)+2, RLENGTH-5) + href = substr($0, match($0, '$href_regex')+6, RLENGTH-7) + '"$common_awk_script"' + }' + fi + + # if closed is on the new line, then move it on the prev line + # for example: + # was: The command foo1 + # + # became: The command foo1 sed -e ':a' -e 'N' -e '$!ba' -e 's/\n<\/h/<\/h/g' | + + # Sometimes a line can start with . Fix that. + sed -e ':a' -e 'N' -e '$!ba' -e 's/\n//g' | sed 's/<\/code>//g' | + + # remove g-emoji + sed 's/]*[^<]*<\/g-emoji> //g' | + # now all rows are like: - # ... title.. # format result line - # * $0 — whole string + # * $0 - whole string # * last element of each row: ".*<\/h/)+2, RLENGTH-5) - href = substr($0, match($0, "href=\"[^\"]+?\"")+6, RLENGTH-7) - print sprintf("%*s", level*3, " ") "* [" text "](" gh_url href ")" }' | - sed 'y/+/ /; s/%/\\x/g')" + echo $echoargs "$(awk -v "gh_url=$1" "$awkscript")" } + # perl -lpE 's/(\[[^\]]*\]\()(.*?)(\))/my ($pre, $in, $post)=($1, $2, $3) ; $in =~ s{\+}{ }g; $in =~ s{%}{\\x}g; $pre.$in.$post/ems')" + # # Returns filename only from full path or url # @@ -213,50 +299,86 @@ gh_toc_get_filename() { echo "${1##*/}" } +show_version() { + echo "$gh_toc_version" + echo + echo "os: `uname -s`" + echo "arch: `uname -m`" + echo "kernel: `uname -r`" + echo "shell: `$SHELL --version`" + echo + for tool in curl wget grep awk sed; do + printf "%-5s: " $tool + if type $tool &>/dev/null; then + $tool --version | head -n 1 + else + echo "not installed" + fi + done +} + +show_help() { + local app_name + app_name=$(basename "$0") + echo "GitHub TOC generator ($app_name): $gh_toc_version" + echo "" + echo "Usage:" + echo " $app_name [options] src [src] Create TOC for a README file (url or local path)" + echo " $app_name - Create TOC for markdown from STDIN" + echo " $app_name --help Show help" + echo " $app_name --version Show version" + echo "" + echo "Options:" + echo " --indent Set indent size. Default: 3." + echo " --insert Insert new TOC into original file. For local files only. Default: false." + echo " See https://github.com/ekalinin/github-markdown-toc/issues/41 for details." + echo " --no-backup Remove backup file. Set --insert as well. Default: false." + echo " --hide-footer Do not write date & author of the last TOC update. Set --insert as well. Default: false." + echo " --skip-header Hide entry of the topmost headlines. Default: false." + echo " See https://github.com/ekalinin/github-markdown-toc/issues/125 for details." + echo "" +} + # -# Options hendlers +# Options handlers # gh_toc_app() { local need_replace="no" + local indent=3 if [ "$1" = '--help' ] || [ $# -eq 0 ] ; then - local app_name=$(basename "$0") - echo "GitHub TOC generator ($app_name): $gh_toc_version" - echo "" - echo "Usage:" - echo " $app_name [--insert] src [src] Create TOC for a README file (url or local path)" - echo " $app_name - Create TOC for markdown from STDIN" - echo " $app_name --help Show help" - echo " $app_name --version Show version" + show_help return fi if [ "$1" = '--version' ]; then - echo "$gh_toc_version" - echo - echo "os: `lsb_release -d | cut -f 2`" - echo "kernel: `cat /proc/version`" - echo "shell: `$SHELL --version`" - echo - for tool in curl wget grep awk sed; do - printf "%-5s: " $tool - echo `$tool --version | head -n 1` - done + show_version return fi + if [ "$1" = '--indent' ]; then + indent="$2" + shift 2 + fi + if [ "$1" = "-" ]; then if [ -z "$TMPDIR" ]; then TMPDIR="/tmp" - elif [ -n "$TMPDIR" -a ! -d "$TMPDIR" ]; then + elif [ -n "$TMPDIR" ] && [ ! -d "$TMPDIR" ]; then mkdir -p "$TMPDIR" fi local gh_tmp_md - gh_tmp_md=$(mktemp $TMPDIR/tmp.XXXXXX) - while read input; do + if [ "`uname -s`" == "OS/390" ]; then + local timestamp + timestamp=$(date +%m%d%Y%H%M%S) + gh_tmp_md="$TMPDIR/tmp.$timestamp" + else + gh_tmp_md=$(mktemp "$TMPDIR/tmp.XXXXXX") + fi + while read -r input; do echo "$input" >> "$gh_tmp_md" done - gh_toc_md2html "$gh_tmp_md" | gh_toc_grab "" + gh_toc_md2html "$gh_tmp_md" | gh_toc_grab "" "$indent" return fi @@ -265,14 +387,32 @@ gh_toc_app() { shift fi + if [ "$1" = '--no-backup' ]; then + need_replace="yes" + no_backup="yes" + shift + fi + + if [ "$1" = '--hide-footer' ]; then + need_replace="yes" + no_footer="yes" + shift + fi + + if [ "$1" = '--skip-header' ]; then + skip_header="yes" + shift + fi + + for md in "$@" do echo "" - gh_toc "$md" "$#" "$need_replace" + gh_toc "$md" "$#" "$need_replace" "$no_backup" "$no_footer" "$indent" "$skip_header" done echo "" - echo "Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)" + echo "" } # diff --git a/python3/vimspector/breakpoints.py b/python3/vimspector/breakpoints.py index 2aab632eb..7721e2ed6 100644 --- a/python3/vimspector/breakpoints.py +++ b/python3/vimspector/breakpoints.py @@ -181,6 +181,9 @@ def ToggleBreakpointView( self, breakpoint_list ): else: self._UpdateView( breakpoint_list ) + def ShowBreakpointsView( self, breakpoint_list ): + self._UpdateView( breakpoint_list ) + def RefreshBreakpoints( self, breakpoint_list ): self._UpdateView( breakpoint_list, show=False ) @@ -219,6 +222,7 @@ def __init__( self, self._func_breakpoints = [] self._exception_breakpoints = None self._configured_breakpoints = {} + self._data_breakponts = [] self._server_capabilities = {} @@ -289,13 +293,22 @@ def ConnectionClosed( self, connection: DebugAdapterConnection ): def ToggleBreakpointsView( self ): self._breakpoints_view.ToggleBreakpointView( self.BreakpointsAsQuickFix() ) + def ShowBreakpointsView( self ): + self._breakpoints_view.ShowBreakpointsView( self.BreakpointsAsQuickFix() ) + def ToggleBreakpointViewBreakpoint( self ): bp = self._breakpoints_view.GetBreakpointForLine() if not bp: return + + # FIXME: what about instruction breakpoints if bp.get( 'type' ) == 'F': + # FIXME: We don't really handle 'DISABLED' state for function breakpoints, + # so they are just deleted self.ClearFunctionBreakpoint( bp.get( 'filename' ) ) + elif bp.get( 'type' ) == 'D': + self.ToggleDataBreakpoint( bp[ 'session_id' ], bp[ 'data_id' ] ) else: # This should find the breakpoint by the "current" line in lnum. If not, # pass an empty options just in case we end up in "ADD" codepath. @@ -315,6 +328,11 @@ def ToggleAllBreakpointsViewBreakpoint( self ): enabled += 1 else: disabled += 1 + for dbp in self._line_breakpoints: + if bp[ 'state' ] == 'ENABLED': + enabled += 1 + else: + disabled += 1 if enabled > disabled: new_state = 'DISABLED' @@ -324,9 +342,13 @@ def ToggleAllBreakpointsViewBreakpoint( self ): for filename, bps in self._line_breakpoints.items(): for bp in bps: bp[ 'state' ] = new_state + for dbp in self._data_breakponts: + dbp[ 'state' ] = new_state # FIXME: We don't really handle 'DISABLED' state for function breakpoints, # so they are not touched + # FIXME: Same for exception breakpoints + # FIXME: Same for instruction breakpoints self.UpdateUI() def JumpToBreakpointViewBreakpoint( self ): @@ -344,6 +366,9 @@ def EditBreakpointOptionsViewBreakpoint( self ): if not vbp: return + if vbp.get( 'type' ) != 'L': + return + # Try to find the actual breakpoint bp, index = self._FindLineBreakpoint( vbp.get( 'filename' ), vbp.get( 'lnum' ) ) @@ -385,8 +410,11 @@ def ClearBreakpointViewBreakpoint( self ): if not bp: return + # FIXME: what about instruction breakpoints if bp.get( 'type' ) == 'F': self.ClearFunctionBreakpoint( bp.get( 'filename' ) ) + elif bp.get( 'type' ) == 'D': + self.ClearDataBreakpoint( bp[ 'session_id' ], bp[ 'data_id' ] ) else: self.ClearLineBreakpoint( bp.get( 'filename' ), bp.get( 'lnum' ) ) @@ -395,6 +423,7 @@ def BreakpointsAsQuickFix( self ): qf = [] for file_name, breakpoints in self._line_breakpoints.items(): for bp in breakpoints: + msg = [] self._SignToLine( file_name, bp ) line = bp[ 'line' ] @@ -405,8 +434,11 @@ def BreakpointsAsQuickFix( self ): if server_bp[ 'verified' ]: line = server_bp.get( 'line', line ) state = 'VERIFIED' + msg = [ server_bp.get( 'message' ) ] valid = 1 break + elif 'message' in server_bp: + msg.append( server_bp[ 'message' ] ) else: state = bp[ 'state' ] valid = 1 @@ -423,14 +455,22 @@ def BreakpointsAsQuickFix( self ): desc = "Instruction" sfx = f" at { utils.Hex( bp.get( 'address', '' ) ) }" + if msg: + msg = list( filter( lambda x: x, msg ) ) + + if msg: + msg = f"{ ', '.join( msg ) } - " + else: + msg = '' + qf.append( { 'filename': file_name, 'lnum': line, 'col': 1, 'type': 'L', 'valid': valid, - 'text': ( f"{desc} breakpoint{sfx} - " - f"{state}: {json.dumps( bp['options'] )}" + 'text': ( f"{desc} breakpoint{sfx} - {state}: {msg}" + f"{json.dumps( bp['options'] )}" f"\t{ line_value }" ) } ) for bp in self._func_breakpoints: @@ -448,6 +488,37 @@ def BreakpointsAsQuickFix( self ): bp[ 'function' ], json.dumps( bp[ 'options' ] ) ) } ) + for bp in self._data_breakponts: + msg = '' + if 'server_bp' in bp: + state = 'PENDING' + for conn, server_bp in bp[ 'server_bp' ].items(): + if conn != bp[ 'conn' ]: + continue + msg = server_bp.get( 'message' ) + if server_bp[ 'verified' ]: + state = 'VERIFIED' + break + else: + state = bp[ 'state' ] + + if msg: + msg = f"{ msg } - " + else: + msg = '' + + qf.append( { + 'filename': bp[ 'info' ][ 'description' ], + 'data_id': bp[ 'info' ][ 'dataId' ], + 'session_id': bp[ 'conn' ], + 'lnum': 1, + 'col': 1, + 'type': 'D', + 'valid': 0, + 'text': f"{ bp['name'] }: Data breakpoint - {state}: {msg}" + f"{ bp['info' ][ 'description' ] }: " + + json.dumps( bp[ 'options' ] ) + } ) return qf @@ -459,6 +530,7 @@ def ClearBreakpoints( self ): self._line_breakpoints = defaultdict( list ) self._func_breakpoints = [] self._exception_breakpoints = None + self._data_breakponts = [] self.UpdateUI() @@ -523,23 +595,21 @@ def _ClearServerBreakpointData( self, conn: DebugAdapterConnection ): if not bp[ 'server_bp' ]: del bp[ 'server_bp' ] - # Clear all instruction breakpoints because they aren't truly portable # across sessions. - # - # TODO: It might be possible to re-resolve the address stored in the - # breakpoint, though this would only work in a limited way (as load - # addresses will frequently not be the same across runs) - - def ShouldKeep( bp ): + def ShouldKeepInsBP( bp ): if not bp[ 'is_instruction_breakpoint' ]: return True if 'address' in bp and bp[ 'session_id' ] != conn.GetSessionId(): return True return False - breakpoints[ : ] = [ bp for bp in breakpoints if ShouldKeep( bp ) ] + breakpoints[ : ] = [ bp for bp in breakpoints if ShouldKeepInsBP( bp ) ] + + # Erase any data breakpoints for this connection too + self._data_breakponts[ : ] = [ bp for bp in self._data_breakponts + if bp[ 'conn' ] != conn.GetSessionId() ] def _CopyServerLineBreakpointProperties( self, @@ -559,7 +629,7 @@ def UpdatePostedBreakpoint( self, bp = self._FindPostedBreakpoint( conn, server_bp.get( 'id' ) ) if bp is None: self._logger.warn( "Unexpected update to breakpoint with id %s:" - "breakpiont not found. %s", + "breakpoint not found. %s", server_bp.get( 'id' ), server_bp ) # FIXME ? self.AddPostedBreakpoint( server_bp ) @@ -736,7 +806,7 @@ def ClearTemporaryBreakpoint( self, file_name, line_num ): # FIXME: We should use the _FindPostedBreakpoint here instead, as that's way # more accurate at this point. Some servers can now identifyt he breakpoint # ID that actually triggered too. For now, we still have - # _UpdateServerBreakpoints change the _user_ breakpiont line and we check + # _UpdateServerBreakpoints change the _user_ breakpoint line and we check # for that _here_, though we could check ['server_bp']['line'] updates = False for bp, index in self._AllBreakpointsOnLine( file_name, line_num ): @@ -776,7 +846,7 @@ def _UpdateServerBreakpoints( self, conn, breakpoints, bp_idxs ): is_temporary = bool( user_bp[ 'options' ].get( 'temporary' ) ) if not is_temporary: - # We don't modify the 'user" breakpiont + # We don't modify the 'user" breakpoint continue # FIXME: Tempoarary instruction breakpoints would not have a line; we @@ -807,7 +877,49 @@ def AddFunctionBreakpoint( self, function, options ): # 'condition': ..., # 'hitCondition': ..., } ) + self.UpdateUI() + + + def AddDataBreakpoint( self, + conn: DebugAdapterConnection, + name, + info, + options ): + self._data_breakponts.append( { + 'state': 'ENABLED', + 'conn': conn.GetSessionId(), + 'name': name, + 'info': info, + 'options': options, + 'is_instruction_breakpoint': False + } ) + # We don't have a way to render breakpoints in the variables view right now, + # so instead when you add a data breakpoint, we force-show the breakpoints + # window + self.ShowBreakpointsView() + self.UpdateUI() + + + def ToggleDataBreakpoint( self, session_id, data_id ): + for dbp in self._data_breakponts: + if dbp[ 'conn' ] != session_id: + continue + if dbp[ 'info' ][ 'dataId' ] != data_id: + continue + if dbp[ 'state' ] == 'ENABLED': + dbp[ 'state' ] = 'DISABLED' + else: + dbp[ 'state' ] = 'ENABLED' + self.UpdateUI() + return + + + def ClearDataBreakpoint( self, session_id, data_id ): + self._data_breakponts = [ + item for item in self._data_breakponts + if item[ 'conn' ] != session_id or item[ 'info' ][ 'dataId' ] != data_id + ] self.UpdateUI() @@ -942,9 +1054,9 @@ def response_handler( conn, msg, bp_idxs = [] ): # function breakpoint as well as every line breakpoint. We need to # implement that: # - pass the indices in here - # - make _FindPostedBreakpoint also search function breakpionts + # - make _FindPostedBreakpoint also search function breakpoints # - make sure that ConnectionClosed also cleares the server_bp data for - # function breakpionts + # function breakpoints # - make sure that we have tests for this, because i'm sure we don't! for connection in self._connections: self._awaiting_bp_responses += 1 @@ -1014,6 +1126,42 @@ def response_handler( conn, msg, bp_idxs = [] ): failure_handler = response_received ) + if self._server_capabilities.get( 'supportsDataBreakpoints' ): + connection: DebugAdapterConnection + for connection in self._connections: + breakpoints = [] + bp_idxs = [] + for bp in self._data_breakponts: + if bp[ 'conn' ] != connection.GetSessionId(): + continue + if not bp[ 'info' ].get( 'dataId' ): + continue + + bp.pop( 'server_bp', None ) + + if bp[ 'state' ] != 'ENABLED': + continue + + data_bp = {} + data_bp.update( bp[ 'options' ] ) + data_bp[ 'dataId' ] = bp[ 'info' ][ 'dataId' ] + bp_idxs.append( ( len( breakpoints ), bp ) ) + breakpoints.append( data_bp ) + + self._awaiting_bp_responses += 1 + connection.DoRequest( + lambda msg, conn=connection: response_handler( conn, + msg, + bp_idxs ), + { + 'command': 'setDataBreakpoints', + 'arguments': { + 'breakpoints': breakpoints, + }, + }, + failure_handler = response_received + ) + if self._exception_breakpoints: for connection in self._connections: self._awaiting_bp_responses += 1 @@ -1112,6 +1260,13 @@ def Save( self ): if bps: line[ file_name ] = bps + # TODO: Some way to persis data breakpoints? Currently they require + # variablesReference, which is clearly not something that can be persisted + # + # That said, the spec now seems to support data bps on expressions, though i + # can't see any servers which support that. + # + # There's now even a 'canPersist' field on the DataBreakpointInfoResponse return { 'line': line, 'function': self._func_breakpoints, @@ -1183,6 +1338,11 @@ def _HideBreakpoints( self ): signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' ) del bp[ 'sign_id' ] + # TODO could/should we show a sign in the variables view when there's a data + # brakpoint on the variable? Not sure how best to actually do that, but + # maybe the variable view can pass that info when calling AddDataBreakpoint, + # such as the variablesReference/name + def _SignToLine( self, file_name, bp ): if bp[ 'is_instruction_breakpoint' ]: diff --git a/python3/vimspector/core_utils.py b/python3/vimspector/core_utils.py index 10fe8fc09..3c10d2e1e 100644 --- a/python3/vimspector/core_utils.py +++ b/python3/vimspector/core_utils.py @@ -99,4 +99,8 @@ def override( target_dict: typing.MutableMapping, def NormalizePath( filepath ): absolute_path = os.path.abspath( filepath ) + # Normalise windows drive letters to uppercase + drive, tail = os.path.splitdrive( absolute_path ) + if drive: + absolute_path = drive.upper() + tail return absolute_path if os.path.isfile( absolute_path ) else filepath diff --git a/python3/vimspector/debug_session.py b/python3/vimspector/debug_session.py index 1df0f4611..afa210a03 100644 --- a/python3/vimspector/debug_session.py +++ b/python3/vimspector/debug_session.py @@ -32,6 +32,7 @@ install, output, stack_trace, + session_manager, utils, variables, settings, @@ -62,6 +63,17 @@ def wrapper( self: "DebugSession", *args, **kwargs ): return wrapper return decorator + def ParentSession(): + def decorator( fct ): + @functools.wraps( fct ) + def wrapper( self: "DebugSession", *args, **kwargs ): + current = self + while current.parent_session: + current = current.parent_session + return fct( current, *args, **kwargs ) + return wrapper + return decorator + def ParentOnly( otherwise=None ): def decorator( fct ): @functools.wraps( fct ) @@ -1016,6 +1028,115 @@ def OnDisassemblyWindowScrolled( self, win_id ): self._disassemblyView.OnWindowScrolled( win_id ) + @ParentSession() + def AddDataBreakpoint( self, opts, buf = None, line_num = None ): + # Use the parent session, because the _connection_ comes from the + # variable/watch result that is actually chosen + + def add_bp( conn, name, msg ): + breakpoint_info = msg.get( 'body' ) + if not breakpoint_info: + utils.UserMessage( "Can't set data breakpoint here" ) + return + + if breakpoint_info[ 'dataId' ] is None: + utils.UserMessage( + f"Can't set data breakpoint here: {breakpoint_info[ 'description' ]}" + ) + return + + access_types = breakpoint_info.get( 'accessTypes' ) + if access_types and 'accessType' not in opts: + access_type = utils.SelectFromList( f'What type of access for {name}?', + access_types ) + if not access_type: + return + opts[ 'accessType' ] = access_type + + self._breakpoints.AddDataBreakpoint( conn, + name, + breakpoint_info, + opts ) + + con: debug_adapter_connection.DebugAdapterConnection = None + arguments: dict = None + + # Check if we were requesting on a specific child variable in the + # watch/locals window. If so, use variablesReference. + con, arguments = self._variablesView.GetDataBreakpointInfoRequest( + buf, + line_num ) + + if not con: + # No watch variable was found, so enter an expression and pass it in + # 'name', with optional 'bytes' and 'asAddress' arguments. + arguments = {} + con = self._stackTraceView.GetCurrentSession().Connection() + + if not con: + return + + address_allowed = bool( session_manager.Get().GetSession( + con.GetSessionId() )._server_capabilities.get( + 'supportsDataBreakpointBytes' ) ) + + if address_allowed: + expr = utils.AskForInput( + 'Expression to watch (or empty for address): ' ) + + if expr is None: + return + + if not expr: + expr = utils.AskForInput( 'Address to watch: ' ) + arguments[ 'asAddress' ] = True + + if not expr: + return + + size = utils.AskForInput( 'Bytes to watch (empty for default): ' ) + if size is None: + return + + if size != '': + try: + arguments[ 'bytes' ] = int( size ) + except ValueError: + utils.UserMessage( "Invalid size", error=True ) + return + else: + expr = utils.AskForInput( 'Expression to watch: ' ) + + if not expr: + return + + arguments = { + 'name': expr, + 'frameId': self._stackTraceView.GetCurrentFrame()[ 'id' ] + } | arguments + + if not con or not arguments: + utils.UserMessage( "Nothing set" ) + return + + if not session_manager.Get().GetSession( + con.GetSessionId() )._server_capabilities.get( + 'supportsDataBreakpoints' ): + utils.UserMessage( "Server does not support data breakpoints" ) + return + + con.DoRequest( + lambda msg: add_bp( con, arguments[ 'name' ], msg ), { + 'command': 'dataBreakpointInfo', + 'arguments': arguments, + }, + failure_handler = lambda reason, msg: utils.UserMessage( + reason, + error=True + ) + ) + + @CurrentSession() @IfConnected() def AddWatch( self, expression ): @@ -1683,6 +1804,8 @@ def _GetShellCommand( self ): def _GetDockerCommand( self, remote ): docker = [ 'docker', 'exec', '-t' ] + if 'docker_args' in remote: + docker += remote[ 'docker_args' ] docker.append( remote[ 'container' ] ) return docker diff --git a/python3/vimspector/gadgets.py b/python3/vimspector/gadgets.py index 44d482183..a84f7f7d5 100644 --- a/python3/vimspector/gadgets.py +++ b/python3/vimspector/gadgets.py @@ -353,7 +353,7 @@ gadget ), 'all': { 'path': 'github.com/go-delve/delve/cmd/dlv', - 'version': '1.22.1', + 'version': '1.23.1', }, 'adapters': { "delve": { @@ -463,27 +463,6 @@ }, }, }, - 'vscode-node-debug2': { - 'language': 'node_legacy', - 'enabled': False, - 'repo': { - 'url': 'https://github.com/microsoft/vscode-node-debug2', - 'ref': 'v1.43.0' - }, - 'do': lambda name, root, gadget: installer.InstallNodeDebug( name, - root, - gadget ), - 'adapters': { - 'vscode-node': { - 'name': 'node2', - 'type': 'node2', - 'command': [ - 'node', - '${gadgetDir}/vscode-node-debug2/out/src/nodeDebug.js' - ] - }, - }, - }, 'vscode-firefox-debug': { 'language': 'firefox', 'enabled': False, @@ -546,12 +525,12 @@ '${version}/${file_name}', }, 'all': { - 'version': 'v1.10.0', + 'version': 'v1.11.0', }, 'macos': { - 'file_name': 'codelldb-x86_64-darwin.vsix', + 'file_name': 'codelldb-darwin-x64.vsix', 'checksum': - '91b10d5670a40434c308c09cb511a5b3e096c82b446a0bbbe4224af33204f5cf', + '5be44ccc6d1e44a0cad5c67458a6968c0c6baf091093005221d467f10dd68dc6', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/debugserver', @@ -560,14 +539,14 @@ ], }, 'macos_arm64': { - 'file_name': 'codelldb-aarch64-darwin.vsix', + 'file_name': 'codelldb-darwin-arm64.vsix', 'checksum': - '4ab0795a726bc52d6e2fa8ebc610baa3f262ebea89adac478cf4a34c72167a41', + '6634c094def2463d38b7b220bcebb49bac81391ef2e9988c4d41e88a996d726c', }, 'linux': { - 'file_name': 'codelldb-x86_64-linux.vsix', + 'file_name': 'codelldb-linux-x64.vsix', 'checksum': - 'd12bff19811974e14688e9754d8d7b9a2430868c3bac883d695032a4acd012ca', + 'b857287f70a18a4fc2d7563aa9fdbcfa9cb2b37d5666fc78394fc8131ee335e2', 'make_executable': [ 'adapter/codelldb', 'lldb/bin/lldb', @@ -576,19 +555,19 @@ ], }, 'linux_arm64': { - 'file_name': 'codelldb-aarch64-linux.vsix', + 'file_name': 'codelldb-linux-arm64.vsix', 'checksum': - '0a81f6617834754537520b7bae2ea9ad50d26b372f8c8bd967dae099e4b27d06', + 'ebbd358dddc1538384cdfb94823da85d13a7a3a4c3eac466de8bb5394f81386a', }, 'linux_armv7': { - 'file_name': 'codelldb-arm-linux.vsix', + 'file_name': 'codelldb-linux-armhf.vsix', 'checksum': - '4bfc5ee753d4359c9ba3cf8fc726f4245a62fd283b718b5120ef1b404baf68c9', + 'a22f1b38a94a94cb2cb814399de9da153cd2ddb2539b97353f05b60668fe0e9f', }, 'windows': { - 'file_name': 'codelldb-x86_64-windows.vsix', + 'file_name': 'codelldb-win32-x64.vsix', 'checksum': - '2f251384e4356edcffe168439714d00de5ca434b263719cbdaf63c9d2f0ffe64', + '375807832e2e9e41dd66f000200d4a55978977f3f10ad9799286f1f9fbe017e6', 'make_executable': [] }, 'adapters': { @@ -597,9 +576,7 @@ 'type': 'CodeLLDB', "command": [ "${gadgetDir}/CodeLLDB/adapter/codelldb", - "--port", "${unusedLocalPort}" ], - "port": "${unusedLocalPort}", "configuration": { "type": "lldb", "name": "lldb", diff --git a/python3/vimspector/installer.py b/python3/vimspector/installer.py index d450989eb..24083a3ea 100644 --- a/python3/vimspector/installer.py +++ b/python3/vimspector/installer.py @@ -436,10 +436,15 @@ def InstallTclProDebug( name, root, gadget ): # '/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System' # '/Library/Frameworks/Tcl.framework/Versions' # '/Current', - for p in [ '/usr/local/opt/tcl-tk/lib', '/opt/homebrew/opt/tcl-tk/lib' ]: - if os.path.exists( os.path.join( p, 'tclConfig.sh' ) ): - configure.append( '--with-tcl=' + p ) - break + for tcl in [ "tcl-tk@8", "tcl-tk" ]: + for p in [ f'/usr/local/opt/{tcl}/lib', f'/opt/homebrew/opt/{tcl}/lib' ]: + if os.path.exists( os.path.join( p, 'tclConfig.sh' ) ): + Print( f"Found tclConfig.sh in {p}" ) + configure.append( '--with-tcl=' + p ) + break + else: + continue + break with CurrentWorkingDir( os.path.join( root, 'lib', 'tclparser' ) ): diff --git a/python3/vimspector/settings.py b/python3/vimspector/settings.py index 26d6258b3..a4295048e 100644 --- a/python3/vimspector/settings.py +++ b/python3/vimspector/settings.py @@ -92,6 +92,7 @@ 'delete': [ '' ], 'set_value': [ '', '' ], 'read_memory': [ 'm' ], + 'add_data_breakpoint': [ '' ], }, 'stack_trace': { 'expand_or_jump': [ '', '<2-LeftMouse>' ], diff --git a/python3/vimspector/variables.py b/python3/vimspector/variables.py index 71a5e748f..e815c7642 100644 --- a/python3/vimspector/variables.py +++ b/python3/vimspector/variables.py @@ -62,13 +62,25 @@ def IsContained( self ): def VariablesReference( self ): assert False + @abc.abstractmethod + def FrameID( self ): + assert False + + @abc.abstractmethod + def Name( self ): + assert False + + @abc.abstractmethod def MemoryReference( self ): - assert None + assert False @abc.abstractmethod def HoverText( self ): return "" + def Update( self, connection ): + self.connection = connection + class Scope( Expandable ): """Holds an expandable scope (a DAP scope dict), with expand/collapse state""" @@ -82,7 +94,14 @@ def VariablesReference( self ): def MemoryReference( self ): return None - def Update( self, scope ): + def FrameID( self ): + return None + + def Name( self ): + return self.scope[ 'name' ] + + def Update( self, connection, scope ): + super().Update( connection ) self.scope = scope def HoverText( self ): @@ -91,8 +110,12 @@ def HoverText( self ): class WatchResult( Expandable ): """Holds the result of a Watch expression with expand/collapse.""" - def __init__( self, connection: DebugAdapterConnection, result: dict ): + def __init__( self, + connection: DebugAdapterConnection, + watch, + result: dict ): super().__init__( connection ) + self.watch = watch self.result = result # A new watch result is marked as changed self.changed = True @@ -103,9 +126,15 @@ def VariablesReference( self ): def MemoryReference( self ): return self.result.get( 'memoryReference' ) + def FrameID( self ): + return self.watch.expression.get( 'frameId' ) + + def Name( self ): + return self.watch.expression.get( 'expression' ) + def Update( self, connection, result ): + super().Update( connection ) self.changed = False - self.connection = connection if self.result[ 'result' ] != result[ 'result' ]: self.changed = True self.result = result @@ -121,8 +150,8 @@ def HoverText( self ): class WatchFailure( WatchResult ): - def __init__( self, connection: DebugAdapterConnection, reason ): - super().__init__( connection, { 'result': reason } ) + def __init__( self, connection: DebugAdapterConnection, watch, reason ): + super().__init__( connection, watch, { 'result': reason } ) self.changed = True @@ -130,7 +159,8 @@ class Variable( Expandable ): """Holds one level of an expanded value tree. Also itself expandable.""" def __init__( self, connection: DebugAdapterConnection, - container: Expandable, variable: dict ): + container: Expandable, + variable: dict ): super().__init__( connection = connection, container = container ) self.variable = variable # A new variable appearing is marked as changed @@ -142,9 +172,15 @@ def VariablesReference( self ): def MemoryReference( self ): return self.variable.get( 'memoryReference' ) + def FrameID( self ): + return self.container.FrameID() + + def Name( self ): + return self.variable[ 'name' ] + def Update( self, connection, variable ): + super().Update( connection ) self.changed = False - self.connection = connection if self.variable[ 'value' ] != variable[ 'value' ]: self.changed = True self.variable = variable @@ -171,6 +207,11 @@ def __init__( self, connection: DebugAdapterConnection, expression: dict ): self.result = None def SetCurrentFrame( self, connection, frame ): + if connection is None: + self.connection = None + self.result.connection = None + return + if self.connection is None: self.connection = connection elif self.connection != connection: @@ -227,6 +268,9 @@ def AddExpandMappings( mappings = None ): for mapping in utils.GetVimList( mappings, 'read_memory' ): vim.command( f'nnoremap { mapping } ' ':call vimspector#ReadMemory()' ) + for mapping in utils.GetVimList( mappings, 'add_data_breakpoint' ): + vim.command( f'nnoremap { mapping } ' + ':call vimspector#AddDataBreakpoint()' ) @@ -323,7 +367,7 @@ def ConnectionClosed( self, connection ): ] for w in self._watches: if w.connection == connection: - w.connection = None + w.SetCurrentFrame( None, None ) def Reset( self ): @@ -363,7 +407,7 @@ def scopes_consumer( message ): if not found: scope = Scope( connection, scope_body ) else: - scope.Update( scope_body ) + scope.Update( connection, scope_body ) new_scopes.append( scope ) @@ -434,7 +478,7 @@ def handler( message ): watch = self._variable_eval if watch.result is None or watch.result.connection != connection: - watch.result = WatchResult( connection, message[ 'body' ] ) + watch.result = WatchResult( connection, watch, message[ 'body' ] ) else: watch.result.Update( connection, message[ 'body' ] ) @@ -543,7 +587,9 @@ def _UpdateWatchExpression( self, watch: Watch, message: dict ): if watch.result is not None: watch.result.Update( watch.connection, message[ 'body' ] ) else: - watch.result = WatchResult( watch.connection, message[ 'body' ] ) + watch.result = WatchResult( watch.connection, + watch, + message[ 'body' ] ) if ( watch.result.IsExpandable() and watch.result.IsExpanded() ): @@ -563,7 +609,7 @@ def _WatchExpressionFailed( self, reason: str, watch: Watch ): # We already have a result for this watch. Wut ? return - watch.result = WatchFailure( watch.connection, reason ) + watch.result = WatchFailure( watch.connection, watch, reason ) self._DrawWatches() def _GetVariable( self, buf = None, line_num = None ): @@ -677,7 +723,6 @@ def GetMemoryReference( self ): if variable is None: return None, None - # TODO: Return the connection too! return variable.connection, variable.MemoryReference() @@ -855,4 +900,28 @@ def SetSyntax( self, syntax ): syntax, self._vars.buf, self._watch.buf ) + + + def GetDataBreakpointInfoRequest( self, buf, line_num ): + variable: Expandable + view: View + + variable, view = self._GetVariable( buf, line_num ) + if variable is None: + return None, None + + arguments = { + 'name': variable.Name() + } + frameId = variable.FrameID() + if frameId: + arguments[ 'frameId' ] = frameId + + if variable.IsContained(): + arguments[ 'variablesReference' ] = ( + variable.container.VariablesReference() ) + + return variable.connection, arguments + + # vim: sw=2 diff --git a/support/test/cpp/simple_c_program/.vimspector.json b/support/test/cpp/simple_c_program/.vimspector.json index f277fc774..fdbe4a92d 100644 --- a/support/test/cpp/simple_c_program/.vimspector.json +++ b/support/test/cpp/simple_c_program/.vimspector.json @@ -1,10 +1,32 @@ { "adapters": { + "lldb-dap": { + "attach": { + "pidProperty": "pid", + "pidSelect": "ask" + }, + "command": [ + "/opt/homebrew/opt/llvm/bin/lldb-dap" + ], + "env": { + "LLDB_LAUNCH_FLAG_LAUNCH_IN_TTY": "YES" + }, + "name": "lldb", + "configuration": { + "runInTerminal": true + } + }, + "custom-lldb-dap": { + "extends": "lldb-dap", + "command": [ + "$HOME/Development/llvm-project/build/bin/lldb-dap" + ] + }, "custom-codelldb": { "extends": "CodeLLDB", "command": [ "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb", - "--port", "${unusedLocalPort}" + "--liblldb", "$HOME/Development/llvm-project/build/lib/liblldb.dylib" ] }, "CodeLLDB - StopOnEntry": { @@ -23,6 +45,7 @@ "adapter": "custom-codelldb", "configuration": { "request": "launch", + "expressions": "native", "program": "${workspaceRoot}/test" } }, @@ -47,6 +70,17 @@ "stopOnEntry": true } }, + "lldb-dap": { + "adapter": "lldb-dap", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/test" + } + }, + "lldb-dap-custom": { + "extends": "lldb-dap", + "adapter": "custom-lldb-dap" + }, "lldb-vscode": { "adapter": "lldb-vscode", "variables": { @@ -64,7 +98,7 @@ "adapter": "vscode-cpptools", "variables": { "BUILDME": { - "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${workspaceRoot}/test_c.cpp" + "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${file}" }, "arch": { "shell": "uname -m" @@ -86,7 +120,7 @@ "adapter": "vscode-cpptools", "variables": { "BUILDME": { - "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${workspaceRoot}/test_c.cpp" + "shell": "g++ -o ${workspaceRoot}/test -g -std=c++17 ${file}" } }, "configuration": { @@ -100,6 +134,12 @@ "extends": "cpptools (lldb)", "configuration": { "request": "attach" + }, + "breakpoints": { + "exception": { + "cpp_throw": "", + "cpp_catch": "" + } } }, "CodeLLDB-attach": { @@ -107,6 +147,12 @@ "configuration": { "request": "attach", "pid": "${PickProcess(\"test\")}" + }, + "breakpoints": { + "exception": { + "cpp_throw": "", + "cpp_catch": "" + } } } } diff --git a/support/test/cpp/simple_c_program/memory.cpp b/support/test/cpp/simple_c_program/memory.cpp new file mode 100644 index 000000000..cac551ba1 --- /dev/null +++ b/support/test/cpp/simple_c_program/memory.cpp @@ -0,0 +1,24 @@ +struct Test +{ + int x; + int y; +}; + +int main( int argc , char ** argv ) +{ + Test x[] = { + { 1, 2 }, + { 3, 4 }, + { 5, 6 }, + }; + + Test y = { 7, 8 }; + + x[0].x += argc; + argv[ 0 ][ 0 ] = 'x' ; + + y.x += **argv; + y.y += argc * **argv; + + return argc; +} diff --git a/support/test/cpp/simple_c_program/test_c.cpp b/support/test/cpp/simple_c_program/test_c.cpp index cd696b18d..5551e884f 100644 --- a/support/test/cpp/simple_c_program/test_c.cpp +++ b/support/test/cpp/simple_c_program/test_c.cpp @@ -12,6 +12,8 @@ namespace Test int somethingInt; char somethingChar; } something; + + char big[ sizeof(void*) * 100 ]; }; TestStruct _t; @@ -25,7 +27,7 @@ namespace Test void foo( TestStruct m ) { - TestStruct t{ true, {11} }; + TestStruct t{ true, {11}, {} }; bar( t ); } } @@ -37,10 +39,20 @@ int main ( int argc, char ** argv ) printf( "HOME: %s\n", getenv( "HOME" ) ); - Test::TestStruct t{ true, {99} }; + Test::TestStruct t{ true, {99}, { ' ', } }; foo( t ); // ADL! for ( int i = 0; i < 100 ; ++i ) { - Test::foo( { true, {i} } ); + Test::foo( { true, {i}, {0} } ); } + + t.big[ sizeof(void*) * 0 ] = 'r'; + t.big[ sizeof(void*) * 1 ] = 'o'; + t.big[ sizeof(void*) * 2 ] = 'f'; + t.big[ sizeof(void*) * 3 ] = 'l'; + //t.big[ sizeof(void*) * 4 ] = '0'; + + std::cout << t.big << '\n'; + + return 0; } diff --git a/support/test/go/structs/.gitignore b/support/test/go/structs/.gitignore new file mode 100644 index 000000000..242c034c1 --- /dev/null +++ b/support/test/go/structs/.gitignore @@ -0,0 +1 @@ +hello_world diff --git a/support/test/go/structs/.vimspector.json b/support/test/go/structs/.vimspector.json new file mode 100644 index 000000000..da54999a1 --- /dev/null +++ b/support/test/go/structs/.vimspector.json @@ -0,0 +1,29 @@ +{ + "configurations": { + "run-legacy": { + "adapter": "vscode-go", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/hello-world.go", + "mode": "debug", + "trace": true, + "env": { "GO111MODULE": "off" } + } + }, + "run-delve": { + "adapter": "delve", + "configuration": { + "request": "launch", + "env": { "GO111MODULE": "off" }, + + "mode": "debug", // debug|test + "program": "${workspaceRoot}/hello-world.go" + + // "args": [], + // "buildFlags": ... + // "stackTraceDepth": ..., + // "showGlobalVariables": true, + } + } + } +} diff --git a/support/test/go/structs/__debug_bin b/support/test/go/structs/__debug_bin new file mode 100755 index 000000000..919aef79b Binary files /dev/null and b/support/test/go/structs/__debug_bin differ diff --git a/support/test/go/structs/hello-world.go b/support/test/go/structs/hello-world.go new file mode 100644 index 000000000..efff2c069 --- /dev/null +++ b/support/test/go/structs/hello-world.go @@ -0,0 +1,25 @@ +package main +import "fmt" + +type Toaster struct { + Power int + Colour string +} + +type Test struct { + Test string + Toast Toaster +} + +func main() { + var v = "test" + test := Test{ + Test: "This is\na\ntest", + Toast: Toaster{ + Power: 10, + Colour: "green", + }, + } + fmt.Println("hello world: " + v) + fmt.Println("Hi " + test.Test) +} diff --git a/support/test/java/test_project/.vimspector.json b/support/test/java/test_project/.vimspector.json index 39f4639ba..58219a917 100644 --- a/support/test/java/test_project/.vimspector.json +++ b/support/test/java/test_project/.vimspector.json @@ -7,6 +7,7 @@ "mainClass": "com.vimspector.test.TestApplication", "sourcePaths": [ "${workspaceRoot}/src/main/java" ], "classPaths": [ "${workspaceRoot}/target/classes" ], + "project": "TestApplication", "args": "hello world!", "stopOnEntry": true, "console": "integratedTerminal", @@ -20,6 +21,7 @@ "configuration": { "request": "attach", "sourcePaths": [ "${workspaceRoot}/src/main/java" ], + "project": "TestApplication", "stopOnEntry": true, "hostName": "localhost", "port": "${JVMDebugPort}", @@ -32,6 +34,7 @@ "adapter": "vscode-javac", "configuration": { "request": "attach", + "project": "TestApplication", "port": "${debugPort}", "sourceRoots": [ "${workspaceRoot}/src/main/java" diff --git a/support/test/python/django/requirements.txt b/support/test/python/django/requirements.txt index e200bc7b2..0c41bab5f 100644 --- a/support/test/python/django/requirements.txt +++ b/support/test/python/django/requirements.txt @@ -1 +1 @@ -Django==4.2.15 +Django==4.2.17 diff --git a/support/test/rust/vimspector_test/src/main.rs b/support/test/rust/vimspector_test/src/main.rs index 509a6d43c..9cea16605 100644 --- a/support/test/rust/vimspector_test/src/main.rs +++ b/support/test/rust/vimspector_test/src/main.rs @@ -1,10 +1,26 @@ +struct Point { + x: i32, + y: i32, +} + struct Foo { x: i32, } fn main() { let s = "World!"; + println!("Hello, {}!", s); + let f = Foo { x: 42 }; let g = &f; println!("Hello, {} {} {}!", s, g.x, f.x); + + let mut p = Point{ x: 1, y: 11 }; + + p.x = 11; + p.y = 11; + p.x += 11; + p.y += 11; + + println!("Point: {}, {}", p.x, p.y); } diff --git a/support/vimspector_process_list/go.mod b/support/vimspector_process_list/go.mod index dacd189d8..43c52115c 100644 --- a/support/vimspector_process_list/go.mod +++ b/support/vimspector_process_list/go.mod @@ -2,15 +2,15 @@ module github.com/puremourning/vimspector/support/vimspector_process_list go 1.19 -require github.com/shirou/gopsutil/v3 v3.23.4 +require github.com/shirou/gopsutil/v3 v3.24.5 require ( - github.com/go-ole/go-ole v1.2.6 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/shoenig/go-m1cpu v0.1.5 // indirect - github.com/tklauser/go-sysconf v0.3.11 // indirect - github.com/tklauser/numcpus v0.6.0 // indirect - github.com/yusufpapurcu/wmi v1.2.2 // indirect - golang.org/x/sys v0.7.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/tklauser/go-sysconf v0.3.14 // indirect + github.com/tklauser/numcpus v0.9.0 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + golang.org/x/sys v0.26.0 // indirect ) diff --git a/support/vimspector_process_list/go.sum b/support/vimspector_process_list/go.sum index e12874754..9babb46ef 100644 --- a/support/vimspector_process_list/go.sum +++ b/support/vimspector_process_list/go.sum @@ -3,19 +3,30 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0= +github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= +github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= +github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -27,15 +38,24 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= +github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo= +github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/tests/ci/image/Dockerfile b/tests/ci/image/Dockerfile index 3b86ef06b..036059aca 100644 --- a/tests/ci/image/Dockerfile +++ b/tests/ci/image/Dockerfile @@ -3,7 +3,7 @@ FROM ubuntu:20.04 ENV DEBIAN_FRONTEND=noninteractive ENV LC_ALL C.UTF-8 ARG GOARCH=amd64 -ARG GOVERSION=1.20.1 +ARG GOVERSION=1.23.2 ARG NODE_MAJOR=18 ARG VIM_VERSION=v8.2.4797 ARG NVIM_VERSION=v0.8.3 diff --git a/tests/testdata/cpp/simple/.vimspector.json b/tests/testdata/cpp/simple/.vimspector.json index 3cf58c2d0..79003517e 100644 --- a/tests/testdata/cpp/simple/.vimspector.json +++ b/tests/testdata/cpp/simple/.vimspector.json @@ -76,6 +76,22 @@ "MIMode": "lldb" } }, + "lldb-dap": { + "adapter": "lldb-dap", + "configuration": { + "request": "launch", + "program": "${workspaceRoot}/${fileBasenameNoExtension}", + "args": [ + "A", "eh", + "B", "bee", + "C", "Sea", + "D", "Ceedy" + ], + "stopOnEntry": true, + "runInTerminal": true, + "cwd": "${workspaceRoot}" + } + }, "CodeLLDB": { "adapter": "CodeLLDB", // "adapter": { @@ -129,12 +145,21 @@ }, "name": "lldb" }, + "lldb-dap": { + "variables": { + "LLVM": { + "shell": "brew --prefix llvm" + } + }, + "command": [ + "${LLVM}/bin/lldb-dap" + ], + "name": "lldb" + }, "CodeLLDB-localbuild": { "extends": "CodeLLDB", "command": [ - "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb", - "--port", - "${unusedLocalPort}" + "$HOME/Development/vimspector/CodeLLDB/build/adapter/codelldb" ] } } diff --git a/tox.ini b/tox.ini index 7a6c06e7c..2ed322fba 100644 --- a/tox.ini +++ b/tox.ini @@ -1,4 +1,4 @@ [flake8] -ignore = E111,E114,E121,E125,E126,E127,E128,E129,E131,E133,E201,E202,E203,E211,E221,E222,E241,E251,E261,E303,E402,W503,W504 +ignore = E111,E114,E121,E125,E126,E127,E128,E129,E131,E133,E201,E202,E203,E211,E221,E222,E241,E251,E261,E303,E402,W503,W504,YCM201,YCM202 max-line-length = 80 exclude = python3/vimspector/vendor