Compare commits
329 commits
restart-ch
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c12519b9d | ||
|
|
2bb8561eb6 |
||
|
|
a868102b5e |
||
|
|
dc862fe565 | ||
|
|
b4bcfca932 |
||
|
|
3df0602a69 |
||
|
|
1c2dda4a6a |
||
|
|
db5ed8e802 | ||
|
|
17ca1522f8 | ||
|
|
561a5b9aa2 | ||
|
|
46cfdc678d | ||
|
|
51d78fce5f |
||
|
|
14f34ea6d1 |
||
|
|
a720d0e1d5 | ||
|
|
7c7e3f9c3f | ||
|
|
57ce099280 | ||
|
|
27eb464b8e |
||
|
|
f1e2c12e5b | ||
|
|
26cd7c5c7e |
||
|
|
59c9cd10ab | ||
|
|
9c806d2a01 |
||
|
|
3af97f1928 |
||
|
|
da39c4955c |
||
|
|
21ebb22fd4 | ||
|
|
aa0cddc0da |
||
|
|
5075f3a11a | ||
|
|
bab81953d7 |
||
|
|
0500e41429 |
||
|
|
1cbb400d42 |
||
|
|
5ea1f0d9d4 | ||
|
|
a51b8b23c9 | ||
|
|
99c0c4f763 |
||
|
|
daa8865fea |
||
|
|
f4d756fe86 |
||
|
|
d43904eb57 | ||
|
|
aacd62f09f | ||
|
|
0e9497ce8f | ||
|
|
2708e8e6ec |
||
|
|
adf6163653 |
||
|
|
0af9d70b0d |
||
|
|
9113dbb698 | ||
|
|
08679d1c3e | ||
|
|
4e04a862cb | ||
|
|
a7e8e93920 | ||
|
|
2b84439413 | ||
|
|
0c88cc8bad | ||
|
|
a47d0b921c |
||
|
|
026ac22280 | ||
|
|
297c0bea56 | ||
|
|
a9a26a5a60 |
||
|
|
1e25313cb5 | ||
|
|
bc15c94513 | ||
|
|
f389d65a24 | ||
|
|
b4195eee93 | ||
|
|
6ad9101cf2 |
||
|
|
a41db89523 | ||
|
|
dd88e051a4 | ||
|
|
fa92c2a8d5 | ||
|
|
6709b45c77 |
||
|
|
278fc3cd8c | ||
|
|
13a5a1b947 | ||
|
|
7d83419a4f | ||
|
|
7b3016aa90 |
||
|
|
d70d51a614 | ||
|
|
caeb6610ed |
||
|
|
0d9e7835a8 | ||
|
|
054ea35428 | ||
|
|
244d7d8fdf | ||
|
|
35e5b3d56e | ||
|
|
842d9fbc2d | ||
|
|
6a24a17f2e |
||
|
|
91e0426e88 |
||
|
|
bf24b37190 |
||
|
|
2d589475eb |
||
|
|
1414f261a1 | ||
|
|
a39017dd06 | ||
|
|
c05335c799 | ||
|
|
efc5c76866 | ||
|
|
154e727b96 | ||
|
|
6b74e584d5 | ||
|
|
85bb8594ab | ||
|
|
63fd3165fb | ||
|
|
afb912dd08 | ||
|
|
b92a89f0d4 | ||
|
|
6f88b400e1 | ||
|
|
af2670ef9a |
||
|
|
2b24611036 |
||
|
|
d84ebdd0ee |
||
|
|
6b67d165b9 | ||
|
|
a53d68f043 | ||
|
|
6d3f3e207b | ||
|
|
5716bbefa9 |
||
|
|
2615cff97a | ||
|
|
01ea50cb70 | ||
|
|
7d2770f3c4 | ||
|
|
2a635294d0 | ||
|
|
38c843219e | ||
|
|
c012f9520e | ||
|
|
943ae6c7c9 | ||
|
|
82db32780b | ||
|
|
4cb4b814a1 |
||
|
|
d2b92b7ce5 | ||
|
|
5bd83d3e37 | ||
|
|
f6517892c1 |
||
|
|
edcb057ead | ||
|
|
06f9bfc057 | ||
|
|
804b499286 | ||
|
|
49a9a4b367 | ||
|
|
f2d407256e | ||
|
|
94242fa532 | ||
|
|
ba83a59e88 | ||
|
|
675a68c601 | ||
|
|
e1078375fe | ||
|
|
26452289a8 | ||
|
|
ec9122284e | ||
|
|
131cfcdd33 | ||
|
|
c2082cffae | ||
|
|
9e1a1ab4b5 | ||
|
|
32f9a6ec43 | ||
|
|
d8d6eb2286 | ||
|
|
1d38b8198f |
||
|
|
f40ac5db23 | ||
|
|
11edcddd9c |
||
|
|
f9c5a33301 |
||
|
|
fdfa8b265b |
||
|
|
a8651e257b |
||
|
|
d8eb6a0463 | ||
|
|
09efcf5e50 | ||
|
|
5201995279 | ||
|
|
fd03e074f3 |
||
|
|
fd0c6e7675 | ||
|
|
6fac220ee5 | ||
|
|
0810d7154c | ||
|
|
476300f815 | ||
|
|
95b900a0a7 |
||
|
|
0e0cc6d4ae | ||
|
|
c33fddd150 |
||
|
|
448ee33a6a | ||
|
|
ae289a88c7 | ||
|
|
3c7311e33a | ||
|
|
d561c4aea5 | ||
|
|
3c54cd268f | ||
|
|
bcf4120ba4 | ||
|
|
50dc55e0e8 | ||
|
|
716181e056 | ||
|
|
840ee09242 | ||
|
|
0bb8416e11 | ||
|
|
d81bdf30ef | ||
|
|
e70b8f37a3 |
||
|
|
5754e96067 | ||
|
|
4958de92d3 | ||
|
|
6b546cd621 | ||
|
|
323e22b8a9 | ||
|
|
5a1eb9250a | ||
|
|
cc84e15932 | ||
|
|
7dcb15f11c | ||
|
|
44711899cb | ||
|
|
0313efa06f | ||
|
|
51d551fe52 | ||
|
|
ae137ecdd0 | ||
|
|
d6c68d691c | ||
|
|
47680565c4 | ||
|
|
8c39a861bd | ||
|
|
639e89f5db | ||
|
|
5a23ec5beb | ||
|
|
e0b0a7f3d2 | ||
|
|
0ff9dc5f9e | ||
|
|
0c79384529 | ||
|
|
789377eab4 | ||
|
|
4466fce20b | ||
|
|
13102dc711 | ||
|
|
91bebc1826 | ||
|
|
3239963893 | ||
|
|
31e44548d3 | ||
|
|
e5e13ffcdd | ||
|
|
894ca522d3 | ||
|
|
322b7e0a38 | ||
|
|
bc1146df3b | ||
|
|
d2ed8a828c | ||
|
|
fccafd6739 | ||
|
|
672ac78fef | ||
|
|
64f2c8eb01 | ||
|
|
cb174c176d | ||
|
|
2d082cc923 | ||
|
|
0d703779dc | ||
|
|
f3c39e12ab | ||
|
|
cfae062da1 | ||
|
|
0b4da4c82b | ||
|
|
64e38b57ab | ||
|
|
0895c5e829 | ||
|
|
052d63dee5 | ||
|
|
93568ba05d | ||
|
|
e0b1d6ed81 | ||
|
|
3c857cebf4 | ||
|
|
2f1c93a2ac | ||
|
|
cb441be7bc | ||
|
|
b9ed7f34b4 | ||
|
|
04a5e889f9 | ||
|
|
f60b259dbc | ||
|
|
b95ae00054 | ||
|
|
4617250f41 | ||
|
|
0ced5eb1d4 | ||
|
|
747ad9b804 | ||
|
|
d2990d7bae | ||
|
|
819d6366ac | ||
|
|
4e994968ff | ||
|
|
7432be9532 | ||
|
|
07858cc250 | ||
|
|
4c0ba92ac6 | ||
|
|
7c4eef9096 | ||
|
|
85ca867cc2 |
||
|
|
cb922bdc83 |
||
|
|
e99ac0d658 |
||
|
|
0cc4322b18 | ||
|
|
7f77842ab8 | ||
|
|
4454dead0f |
||
|
|
30eec0d93c | ||
|
|
52eff32651 |
||
|
|
5303de8195 |
||
|
|
75e8450cf3 | ||
|
|
35f7e08fbb | ||
|
|
d38da376c2 | ||
|
|
1f20115960 | ||
|
|
442a18f8f2 |
||
|
|
e010d3217c | ||
|
|
1556e63ef0 |
||
|
|
205eb7cdb3 |
||
|
|
44a0f819e2 |
||
|
|
4206d0e57c | ||
|
|
b180b14ed4 |
||
|
|
d52eb3a6e9 | ||
|
|
b72aa18dec | ||
|
|
07ea3880ac |
||
|
|
38ed75dda7 |
||
|
|
0ad826704b |
||
|
|
65708f55e0 |
||
|
|
7bd22d2bbd | ||
|
|
ce8dd9113c | ||
|
|
ec68811c8a | ||
|
|
47c404f823 | ||
|
|
41a98026fa |
||
|
|
523ea29faa |
||
|
|
d0fc7815b3 |
||
|
|
0942aa4523 | ||
|
|
f59ba048cb |
||
|
|
f20c4c9725 | ||
|
|
f8d1e484f9 |
||
|
|
66130389c5 | ||
|
|
61179b7670 | ||
|
|
f161ce1e8c | ||
|
|
d04a8400f9 |
||
|
|
b65d9536ad | ||
|
|
28c5534704 | ||
|
|
2eb32f3153 |
||
|
|
8261cde3c9 | ||
|
|
573121ee08 |
||
|
|
632e6696ef | ||
|
|
c531686d39 | ||
|
|
2eac9ddff8 | ||
|
|
8e2d352eb8 | ||
|
|
4ac9785217 |
||
|
|
4a45753a4c | ||
|
|
e15c50a4f4 | ||
|
|
17a9494dbc |
||
|
|
4db4880b6d |
||
|
|
4c2b3bd886 |
||
|
|
e6500d39d8 |
||
|
|
ff4acb17d1 |
||
|
|
4f03e4f65a | ||
|
|
23130d74ad |
||
|
|
5ab92a7e67 | ||
|
|
979c1e8779 | ||
|
|
a9d0ebde0b | ||
|
|
82307ff1ba | ||
|
|
7d5ad3ffa1 | ||
|
|
8801c2dac4 | ||
|
|
e1c1347bdd | ||
|
|
c769e8a479 | ||
|
|
53b1d12447 | ||
|
|
8e3a734141 | ||
|
|
0f0d684e92 | ||
|
|
42cdff043a | ||
|
|
f0785c11f2 | ||
|
|
a5d66a7477 | ||
|
|
2399a79cae | ||
|
|
e9e0e9e5b9 | ||
|
|
e2ca9b5318 | ||
|
|
e5a765409a |
||
|
|
f87aa4aa19 | ||
|
|
07ec08e664 | ||
|
|
3330c704d7 | ||
|
|
87ce1734ea | ||
|
|
48e075624a |
||
|
|
b36f9e893a | ||
|
|
b7de25e3d1 |
||
|
|
47c2cef2a1 | ||
|
|
cd3b5f5baa | ||
|
|
5b88837919 | ||
|
|
888c558aa4 |
||
|
|
85865e0012 | ||
|
|
7be6d852c6 |
||
|
|
96a594e4cf |
||
|
|
69bb2737d1 | ||
|
|
1eb2bc2199 | ||
|
|
2819e224e7 | ||
|
|
2bdb30a45e | ||
|
|
3f3a001283 |
||
|
|
5ae3d9f336 |
||
|
|
30741f8813 |
||
|
|
2225735b80 | ||
|
|
fb86ef924b | ||
|
|
97bef33660 |
||
|
|
d5b9411256 | ||
|
|
7b048367f7 |
||
|
|
80985148e7 | ||
|
|
0d112d70a0 | ||
|
|
78bec87f4e |
||
|
|
c76e20cd9b |
||
|
|
ea36b60a07 |
||
|
|
5057906317 |
||
|
|
8d17572538 | ||
|
|
f3c5944dd2 | ||
|
|
1eb9933e2a |
||
|
|
1b9763a4fc | ||
|
|
16f22b396f | ||
|
|
f6726de058 |
||
|
|
3d442c978f |
||
|
|
692a0d8d39 |
||
|
|
bd09206caf |
112 changed files with 10662 additions and 2248 deletions
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
10
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
|
@ -17,12 +17,12 @@ assignees: ''
|
|||
|
||||
> Please answer the following questions
|
||||
|
||||
* Does your issue reproduce using `vim -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No]
|
||||
* Does your issue reproduce using `vim --clean -Nu /path/to/vimspector/support/minimal_vimrc` ? \[Yes/No]
|
||||
* If you are using Neovim, does your issue reproduce using Vim? \[Yes/No]
|
||||
|
||||
> List of steps to reproduce:
|
||||
|
||||
> 1. Run `vim -Nu /path/to/vimspector/support/minimal_vimrc`
|
||||
> 1. Run `vim ---clean Nu /path/to/vimspector/support/minimal_vimrc`
|
||||
> 2. Open _this project_...
|
||||
> 3. Press _this sequence of keys_
|
||||
|
||||
|
|
@ -57,6 +57,12 @@ discussing on Gitter rather than raising an issue.
|
|||
* Version of Vimspector: (e.g. output of `git rev-parse HEAD` if cloned or the
|
||||
name of the tarball used to install otherwise)
|
||||
|
||||
* Output of `:VimspectorDebugInfo`
|
||||
|
||||
```
|
||||
paste here
|
||||
```
|
||||
|
||||
* Output of `vim --version` or `nvim --version`
|
||||
|
||||
```
|
||||
|
|
|
|||
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
12
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Questions and support
|
||||
url: http://gitter.im/vimspector/Lobby
|
||||
about: Please ask and answer questions here.
|
||||
- name: Discussions
|
||||
url: https://github.com/puremourning/vimspector/discussions
|
||||
about: Please post questions and useful hints here
|
||||
- name: Support for additional languages
|
||||
url: https://github.com/puremourning/vimspector/wiki/languages
|
||||
about: Please see here for information on support for additional languages
|
||||
|
||||
43
.github/workflows/build.yaml
vendored
43
.github/workflows/build.yaml
vendored
|
|
@ -13,7 +13,7 @@ defaults:
|
|||
|
||||
jobs:
|
||||
PythonLint:
|
||||
runs-on: ubuntu-16.04
|
||||
runs-on: ubuntu-18.04
|
||||
container: 'puremourning/vimspector:test'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
@ -22,7 +22,7 @@ jobs:
|
|||
- name: 'Run flake8'
|
||||
run: '$HOME/.local/bin/flake8 python3/ *.py'
|
||||
VimscriptLint:
|
||||
runs-on: 'ubuntu-16.04'
|
||||
runs-on: 'ubuntu-18.04'
|
||||
container: 'puremourning/vimspector:test'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
|
@ -32,12 +32,13 @@ jobs:
|
|||
run: $HOME/.local/bin/vint autoload/ compiler/ plugin/ tests/ syntax/
|
||||
|
||||
Linux:
|
||||
runs-on: 'ubuntu-16.04'
|
||||
runs-on: 'ubuntu-18.04'
|
||||
container:
|
||||
image: 'puremourning/vimspector:test'
|
||||
options: --cap-add=SYS_PTRACE --security-opt seccomp=unconfined
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: |
|
||||
eval $(/home/linuxbrew/.linuxbrew/bin/brew shellenv)
|
||||
go get -u github.com/go-delve/delve/cmd/dlv
|
||||
|
|
@ -79,17 +80,26 @@ jobs:
|
|||
name: 'package-linux'
|
||||
path: 'package/linux-${{ github.run_id }}.tar.gz'
|
||||
|
||||
# - name: Start SSH session if failed
|
||||
# uses: luchihoratiu/debug-via-ssh@main
|
||||
# if: failure()
|
||||
# with:
|
||||
# NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }}
|
||||
# SSH_PASS: ${{ secrets.SSH_PASS }}
|
||||
|
||||
MacOS:
|
||||
runs-on: 'macos-10.15'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- run: |
|
||||
brew update
|
||||
brew update-reset
|
||||
brew doctor || true
|
||||
for p in macvim tcl-tk llvm; do
|
||||
brew install $p
|
||||
brew outdated $p || brew upgrade $p
|
||||
for p in python@3.8 tcl-tk llvm lua luajit love; do
|
||||
brew install $p || brew outdated $p || brew upgrade $p
|
||||
done
|
||||
brew install --cask macvim
|
||||
brew link --overwrite python@3.8
|
||||
name: 'Install vim and deps'
|
||||
|
||||
- run: go get -u github.com/go-delve/delve/cmd/dlv
|
||||
|
|
@ -101,6 +111,16 @@ jobs:
|
|||
path: gadgets/macos/download
|
||||
name: Cache gadgets
|
||||
|
||||
- name: 'Install .NET Core SDK 3.1'
|
||||
uses: actions/setup-dotnet@v1.7.2
|
||||
with:
|
||||
dotnet-version: 3.1
|
||||
|
||||
- uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: ^11
|
||||
name: "Switch to xcode 11 because of .NET debugging bug"
|
||||
|
||||
- run: vim --version
|
||||
name: 'Print vim version information'
|
||||
|
||||
|
|
@ -128,8 +148,15 @@ jobs:
|
|||
name: 'package-macos'
|
||||
path: 'package/macos-${{ github.run_id }}.tar.gz'
|
||||
|
||||
# - name: Start SSH session if failed
|
||||
# uses: luchihoratiu/debug-via-ssh@main
|
||||
# if: failure()
|
||||
# with:
|
||||
# NGROK_AUTH_TOKEN: ${{ secrets.NGROK_AUTH_TOKEN }}
|
||||
# SSH_PASS: ${{ secrets.SSH_PASS }} # [V]imspector
|
||||
|
||||
PublishRelease:
|
||||
runs-on: 'ubuntu-16.04'
|
||||
runs-on: 'ubuntu-18.04'
|
||||
needs:
|
||||
- Linux
|
||||
- MacOS
|
||||
|
|
|
|||
27
.github/workflows/lock_old_issues.yaml
vendored
Normal file
27
.github/workflows/lock_old_issues.yaml
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
name: "Lock Old Issues"
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 0 * * *'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
lock:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dessant/lock-threads@v2
|
||||
with:
|
||||
github-token: ${{ github.token }}
|
||||
issue-lock-inactive-days: '60'
|
||||
# issue-exclude-created-before: ''
|
||||
# issue-exclude-labels: ''
|
||||
# issue-lock-labels: ''
|
||||
# issue-lock-comment: ''
|
||||
# issue-lock-reason: 'resolved'
|
||||
# pr-lock-inactive-days: '365'
|
||||
# pr-exclude-created-before: ''
|
||||
# pr-exclude-labels: ''
|
||||
# pr-lock-labels: ''
|
||||
# pr-lock-comment: ''
|
||||
# pr-lock-reason: 'resolved'
|
||||
process-only: 'issues'
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -6,6 +6,7 @@ tests/*.res
|
|||
tests/messages
|
||||
tests/debuglog
|
||||
test.log
|
||||
*.testlog
|
||||
gadgets/
|
||||
package/
|
||||
*.pyc
|
||||
|
|
@ -19,3 +20,4 @@ support/test/csharp/*.exe*
|
|||
configurations/
|
||||
venv/
|
||||
test-base/
|
||||
tags
|
||||
|
|
|
|||
|
|
@ -9,9 +9,8 @@ pull_request_rules:
|
|||
# CI https://doc.mergify.io/conditions.html#github-actions
|
||||
- status-success=PythonLint
|
||||
- status-success=VimscriptLint
|
||||
- status-success=Linux
|
||||
- status-success=MacOS
|
||||
|
||||
|
||||
actions: &merge-actions
|
||||
merge:
|
||||
method: merge
|
||||
|
|
|
|||
|
|
@ -42,7 +42,17 @@ def Settings( **kwargs ):
|
|||
return {
|
||||
'sys_path': [
|
||||
p.join( PATH_TO_THIS_DIR, 'python3' )
|
||||
]
|
||||
],
|
||||
'ls': {
|
||||
'python': {
|
||||
'analysis': {
|
||||
'extraPaths': [
|
||||
p.join( PATH_TO_THIS_DIR, 'python3' ),
|
||||
],
|
||||
'useLibraryCodeForTypes': True
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if IgnoreExtraConf:
|
||||
|
|
|
|||
|
|
@ -46,6 +46,23 @@ The GitHub issue tracker is for *bug reports* and *features requests* for the
|
|||
Vimspector project, and on-topic comments and follow-ups to them. It is not for
|
||||
general discussion, general support or for any other purpose.
|
||||
|
||||
Please **search the issue tracker for similar issues** before creating a new
|
||||
one. There's no point in duplication; if an existing open issue addresses your
|
||||
problem, please comment there instead of creating a duplicate. However, if the
|
||||
issue you found is **closed as resolved** (e.g. with a PR or the original user's
|
||||
problem was resolved), raise a **new issue**, because you've found a new
|
||||
problem. Reference the original issue if you think that's useful information.
|
||||
|
||||
Closed issues which have been inactive for 60 days will be locked, this helps to
|
||||
keep discussions focussed. If you believe you are still experiencing an issue
|
||||
which has been closed, please raise a new issue, completing the issue template.
|
||||
|
||||
If you do find a similar _open_ issue, **don't just post 'me too' or similar**
|
||||
responses. This almost never helps resolve the issue, and just causes noise for
|
||||
the maintainers. Only post if it will aid the maintainers in solving the issue;
|
||||
if there are existing diagnostics requested in the thread, perform
|
||||
them and post the results.
|
||||
|
||||
Please do not be offended if your Issue or comment is closed or hidden, for any
|
||||
of the following reasons:
|
||||
|
||||
|
|
@ -53,6 +70,7 @@ of the following reasons:
|
|||
* The issue or comment is off-topic
|
||||
* The issue does not represent a Vimspector bug or feature request
|
||||
* The issue cannot be reasonably reproduced using the minimal vimrc
|
||||
* The issue is a duplicate of an existing issue
|
||||
* etc.
|
||||
|
||||
Issue titles are important. It's not usually helpful to write a title like
|
||||
|
|
@ -83,11 +101,47 @@ in the issue report.
|
|||
The minimal vimrc is in `support/test/minimal_vimrc` and can be used as follows:
|
||||
|
||||
```
|
||||
vim -Nu /path/to/vimspector/support/minimal_vimrc
|
||||
vim --clean -Nu /path/to/vimspector/support/minimal_vimrc
|
||||
```
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Vimspector is open to all contributors with ideas great and small! However,
|
||||
there is a limit to the intended scope of the plugin and the amount of time the
|
||||
maintainer has to support and... well... maintain features. It's probably well
|
||||
understood that the contributor's input typically ends when a PR is megred, but
|
||||
the maintainers have to keep it working forever.
|
||||
|
||||
### Small changes
|
||||
|
||||
For bug fixes, documentation changes, gadget versin updates, etc. please just
|
||||
send a PR, I'm super happy to merge these!
|
||||
|
||||
If you are unsure, or looking for some pointers, feel free to ask in Gitter, or
|
||||
mention is in the PR.
|
||||
|
||||
### Larger changes
|
||||
|
||||
For larger features that might be in any way controvertial, or increase the
|
||||
complexity of the overall plugin, please come to Gitter and talk to the
|
||||
maintainer(s) first. This saves a lot of potential back-and-forth and makes sure
|
||||
that we're "on the same page" about the idea and the ongoing maintenance.
|
||||
|
||||
In addition, if you like hacking, feel free to raise a PR tagged with `[RFC]` in
|
||||
the title and we can discuss the idea. I still prefer to discuss these things on
|
||||
Gitter rather than back-and-forth on GitHub, though.
|
||||
|
||||
Please don't be offended if the maintainer(s) request significant rework for (or
|
||||
perhaps even dismiss) a PR that's not gone through this process.
|
||||
|
||||
Please also don't be offended if the maintainer(s) ask if you're willing to
|
||||
provide ongoing support for the feature. As an OSS project manned entirely in
|
||||
what little spare time the maintainer(s) have, we're always looking for
|
||||
contributions and contributors who will help with support and maintenance of
|
||||
larger new features.
|
||||
|
||||
### PR Guidelines
|
||||
|
||||
When contributing pull requests, I ask that:
|
||||
|
||||
* You provide a clear and complete summary of the change, the use case and how
|
||||
|
|
@ -95,6 +149,8 @@ When contributing pull requests, I ask that:
|
|||
* You avoid using APIs that are not available in the versions listed in the
|
||||
dependencies on README.md
|
||||
* You add tests for your PR.
|
||||
* You test your changes in both Vim and Neovim at the supported versions (and
|
||||
state that in the PR).
|
||||
* You follow the style of the code as-is; the python code is YCM-stye, it is
|
||||
*not* PEP8, nor should it be.
|
||||
|
||||
|
|
@ -129,10 +185,10 @@ Vimspector creator.
|
|||
### Code Style
|
||||
|
||||
The code style of the Python code is "YCM" style, because that's how I like it.
|
||||
[`flake8`][] is used to check for certain errors and code style.
|
||||
`flake8` is used to check for certain errors and code style.
|
||||
|
||||
The code style of the Vimscript is largely the same, and it is linted by
|
||||
[`vint`][].
|
||||
`vint`.
|
||||
|
||||
To run them:
|
||||
|
||||
|
|
@ -144,7 +200,31 @@ To run them:
|
|||
|
||||
They're also run by CI, so please check for lint failures. The canonical
|
||||
definition of the command to run is the command run in CI, i.e. in
|
||||
`azure-pipelines.yml`.
|
||||
`.git/workflows/build.yml`.
|
||||
|
||||
### Debugging Vimspector
|
||||
|
||||
You can debug vimspector's python code using vimspector! We can use debugpy,
|
||||
from within Vim's embedded python and connect to it. Here's how:
|
||||
|
||||
1. In one instance of vim, run the following to get debugpy to start listening
|
||||
for us to connect: `:py3 __import__( 'vimspector', fromlist=[ 'developer' ]
|
||||
).developer.SetUpDebugpy()`
|
||||
|
||||
2. In another instance of Vim, set a breakpoint in the vimspector python code
|
||||
you want to debug and launch vimspector (e.g. `<F5>`). Select the `Python:
|
||||
attach to vim` profile. This will attach to the debugpy running in the other
|
||||
vim.
|
||||
|
||||
3. Back in the first vim (the debuggee), trigger the vimspector code in
|
||||
question, e.g. by starting to debug something else.
|
||||
|
||||
4. You'll see it pause, and the 2nd vim (the debugger), you should be able to
|
||||
step through and inspect as with any other python remote debugging.
|
||||
|
||||
NB. It's also possible to debug the vimscript code using vimspector, but this
|
||||
requires unreleased vim patches and a fair amount of faff. You can always use
|
||||
`:debug` (see the help) for this though.
|
||||
|
||||
# Code of conduct
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@
|
|||
" See the License for the specific language governing permissions and
|
||||
" limitations under the License.
|
||||
|
||||
if !has( 'python3' )
|
||||
finish
|
||||
endif
|
||||
|
||||
" Boilerplate {{{
|
||||
let s:save_cpo = &cpoptions
|
||||
|
|
@ -27,45 +30,62 @@ EOF
|
|||
endfunction
|
||||
|
||||
|
||||
let s:enabled = vimspector#internal#state#Reset()
|
||||
let s:enabled = v:null
|
||||
|
||||
function! vimspector#Launch() abort
|
||||
if !s:enabled
|
||||
function! s:Initialised() abort
|
||||
return s:enabled != v:null
|
||||
endfunction
|
||||
|
||||
function! s:Enabled() abort
|
||||
if !s:Initialised()
|
||||
let s:enabled = vimspector#internal#state#Reset()
|
||||
endif
|
||||
|
||||
return s:enabled
|
||||
endfunction
|
||||
|
||||
function! vimspector#Launch( ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Start()
|
||||
py3 _vimspector_session.Start( *vim.eval( 'a:000' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#LaunchWithSettings( settings ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Start( launch_variables = vim.eval( 'a:settings' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#Reset() abort
|
||||
if !s:enabled
|
||||
function! vimspector#Reset( ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Reset()
|
||||
if a:0 == 0
|
||||
let options = {}
|
||||
else
|
||||
let options = a:1
|
||||
endif
|
||||
py3 _vimspector_session.Reset( **vim.eval( 'options' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#Restart() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Restart()
|
||||
endfunction
|
||||
|
||||
function! vimspector#ClearBreakpoints() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ClearBreakpoints()
|
||||
endfunction
|
||||
|
||||
function! vimspector#ToggleBreakpoint( ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
|
|
@ -76,8 +96,43 @@ function! vimspector#ToggleBreakpoint( ... ) abort
|
|||
py3 _vimspector_session.ToggleBreakpoint( vim.eval( 'options' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#SetLineBreakpoint( file_name, line_num, ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
let options = {}
|
||||
else
|
||||
let options = a:1
|
||||
endif
|
||||
py3 _vimspector_session.SetLineBreakpoint(
|
||||
\ vim.eval( 'a:file_name' ),
|
||||
\ int( vim.eval( 'a:line_num' ) ),
|
||||
\ vim.eval( 'options' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#ClearLineBreakpoint( file_name, line_num ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ClearLineBreakpoint(
|
||||
\ vim.eval( 'a:file_name' ),
|
||||
\ int( vim.eval( 'a:line_num' ) ) )
|
||||
endfunction
|
||||
|
||||
|
||||
function! vimspector#RunToCursor() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.RunTo(
|
||||
\ vim.eval( "expand( '%' )" ),
|
||||
\ int( vim.eval( "line( '.' )" ) ) )
|
||||
endfunction
|
||||
|
||||
|
||||
function! vimspector#AddFunctionBreakpoint( function, ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
|
|
@ -90,74 +145,120 @@ function! vimspector#AddFunctionBreakpoint( function, ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#StepOver() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.StepOver()
|
||||
endfunction
|
||||
|
||||
function! vimspector#StepInto() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.StepInto()
|
||||
endfunction
|
||||
|
||||
function! vimspector#StepOut() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.StepOut()
|
||||
endfunction
|
||||
|
||||
function! vimspector#Continue() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Continue()
|
||||
endfunction
|
||||
|
||||
function! vimspector#Pause() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Pause()
|
||||
endfunction
|
||||
|
||||
function! vimspector#Stop() abort
|
||||
if !s:enabled
|
||||
function! vimspector#PauseContinueThread() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.Stop()
|
||||
py3 _vimspector_session.PauseContinueThread()
|
||||
endfunction
|
||||
|
||||
function! vimspector#SetCurrentThread() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.SetCurrentThread()
|
||||
endfunction
|
||||
|
||||
function! vimspector#Stop( ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
let options = {}
|
||||
else
|
||||
let options = a:1
|
||||
endif
|
||||
py3 _vimspector_session.Stop( **vim.eval( 'options' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#ExpandVariable() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ExpandVariable()
|
||||
endfunction
|
||||
|
||||
function! vimspector#SetVariableValue( ... ) abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
py3 _vimspector_session.SetVariableValue()
|
||||
else
|
||||
py3 _vimspector_session.SetVariableValue( new_value = vim.eval( 'a:1' ) )
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! vimspector#DeleteWatch() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.DeleteWatch()
|
||||
endfunction
|
||||
|
||||
function! vimspector#GoToFrame() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ExpandFrameOrThread()
|
||||
endfunction
|
||||
|
||||
function! vimspector#UpFrame() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.UpFrame()
|
||||
endfunction
|
||||
|
||||
function! vimspector#DownFrame() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.DownFrame()
|
||||
endfunction
|
||||
|
||||
function! vimspector#AddWatch( ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 0
|
||||
let expr = input( 'Enter watch expression: ' )
|
||||
let expr = input( 'Enter watch expression: ',
|
||||
\ '',
|
||||
\ 'custom,vimspector#CompleteExpr' )
|
||||
else
|
||||
let expr = a:1
|
||||
endif
|
||||
|
|
@ -170,7 +271,7 @@ function! vimspector#AddWatch( ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#AddWatchPrompt( expr ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
stopinsert
|
||||
|
|
@ -179,24 +280,24 @@ function! vimspector#AddWatchPrompt( expr ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#Evaluate( expr ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ShowOutput( 'Console' )
|
||||
py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) )
|
||||
py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ), True )
|
||||
endfunction
|
||||
|
||||
function! vimspector#EvaluateConsole( expr ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
stopinsert
|
||||
setlocal nomodified
|
||||
py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ) )
|
||||
py3 _vimspector_session.EvaluateConsole( vim.eval( 'a:expr' ), False )
|
||||
endfunction
|
||||
|
||||
function! vimspector#ShowOutput( ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
if a:0 == 1
|
||||
|
|
@ -207,7 +308,7 @@ function! vimspector#ShowOutput( ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#ShowOutputInWindow( win_id, category ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 __import__( 'vimspector',
|
||||
|
|
@ -217,21 +318,31 @@ function! vimspector#ShowOutputInWindow( win_id, category ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#ToggleLog() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ToggleLog()
|
||||
endfunction
|
||||
|
||||
function! vimspector#ListBreakpoints() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
py3 _vimspector_session.ListBreakpoints()
|
||||
endfunction
|
||||
|
||||
function! vimspector#GetConfigurations() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
let configurations = py3eval(
|
||||
\ 'list( _vimspector_session.GetConfigurations( {} )[ 1 ].keys() )'
|
||||
\ . ' if _vimspector_session else []' )
|
||||
return configurations
|
||||
endfunction
|
||||
|
||||
function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
let buffers = py3eval( '_vimspector_session.GetOutputBuffers() '
|
||||
|
|
@ -239,37 +350,15 @@ function! vimspector#CompleteOutput( ArgLead, CmdLine, CursorPos ) abort
|
|||
return join( buffers, "\n" )
|
||||
endfunction
|
||||
|
||||
py3 <<EOF
|
||||
def _vimspector_GetExprCompletions( ArgLead, prev_non_keyword_char ):
|
||||
if not _vimspector_session:
|
||||
return []
|
||||
|
||||
items = []
|
||||
for candidate in _vimspector_session.GetCompletionsSync(
|
||||
ArgLead,
|
||||
prev_non_keyword_char ):
|
||||
|
||||
label = candidate.get( 'text', candidate[ 'label' ] )
|
||||
|
||||
start = prev_non_keyword_char - 1
|
||||
|
||||
if 'start' in candidate and 'length' in candidate:
|
||||
start = candidate[ 'start' ]
|
||||
|
||||
items.append( ArgLead[ 0 : start ] + label )
|
||||
|
||||
return items
|
||||
EOF
|
||||
|
||||
function! vimspector#CompleteExpr( ArgLead, CmdLine, CursorPos ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
let col = len( a:ArgLead )
|
||||
let prev_non_keyword_char = match( a:ArgLead[ 0 : col - 1 ], '\k*$' ) + 1
|
||||
|
||||
return join( py3eval( '_vimspector_GetExprCompletions( '
|
||||
return join( py3eval( '_vimspector_session.GetCommandLineCompletions( '
|
||||
\ . 'vim.eval( "a:ArgLead" ), '
|
||||
\ . 'int( vim.eval( "prev_non_keyword_char" ) ) )' ),
|
||||
\ "\n" )
|
||||
|
|
@ -390,7 +479,7 @@ function! vimspector#OmniFuncConsole( find_start, query ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#Install( bang, ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
let prefix = vimspector#internal#state#GetAPIPrefix()
|
||||
|
|
@ -402,7 +491,7 @@ function! vimspector#Install( bang, ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#CompleteInstall( ArgLead, CmdLine, CursorPos ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
return py3eval( '"\n".join('
|
||||
|
|
@ -412,7 +501,7 @@ function! vimspector#CompleteInstall( ArgLead, CmdLine, CursorPos ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#Update( bang, ... ) abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
|
|
@ -425,7 +514,7 @@ function! vimspector#Update( bang, ... ) abort
|
|||
endfunction
|
||||
|
||||
function! vimspector#AbortInstall() abort
|
||||
if !s:enabled
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
|
|
@ -434,6 +523,49 @@ function! vimspector#AbortInstall() abort
|
|||
endfunction
|
||||
|
||||
|
||||
function! vimspector#OnBufferCreated( file_name ) abort
|
||||
if len( a:file_name ) == 0
|
||||
return
|
||||
endif
|
||||
|
||||
" Don't actually load up vimsepctor python in autocommands that trigger
|
||||
" regularly. We'll only create the session obkect in s:Enabled()
|
||||
if !s:Initialised()
|
||||
return
|
||||
endif
|
||||
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
py3 _vimspector_session.RefreshSigns( vim.eval( 'a:file_name' ) )
|
||||
endfunction
|
||||
|
||||
function! vimspector#ShowEvalBalloon( is_visual ) abort
|
||||
if a:is_visual
|
||||
let expr = py3eval( '__import__( "vimspector", fromlist = [ "utils" ] )'
|
||||
\ . '.utils.GetVisualSelection('
|
||||
\ . ' int( vim.eval( "winbufnr( winnr() )" ) ) )' )
|
||||
let expr = join( expr, '\n' )
|
||||
else
|
||||
let expr = expand( '<cexpr>' )
|
||||
endif
|
||||
|
||||
return py3eval( '_vimspector_session.ShowEvalBalloon('
|
||||
\ . ' int( vim.eval( "winnr()" ) ), "'
|
||||
\ . expr
|
||||
\ . '", 0 )' )
|
||||
endfunction
|
||||
|
||||
function! vimspector#PrintDebugInfo() abort
|
||||
if !s:Enabled()
|
||||
return
|
||||
endif
|
||||
|
||||
py3 _vimspector_session.PrintDebugInfo()
|
||||
endfunction
|
||||
|
||||
|
||||
" Boilerplate {{{
|
||||
let &cpoptions=s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
|
|
|||
|
|
@ -19,16 +19,323 @@ let s:save_cpo = &cpoptions
|
|||
set cpoptions&vim
|
||||
" }}}
|
||||
|
||||
" Returns: py.ShowBalloon( winnr, expresssion )
|
||||
function! vimspector#internal#balloon#BalloonExpr() abort
|
||||
" winnr + 1 because for *no good reason* winnr is 0 based here unlike
|
||||
" everywhere else
|
||||
" int() because for *no good reason* winnr is a string.
|
||||
return py3eval('_vimspector_session.ShowBalloon('
|
||||
\ . 'int( vim.eval( "v:beval_winnr" ) ) + 1,'
|
||||
\ . 'vim.eval( "v:beval_text" ) )' )
|
||||
scriptencoding utf-8
|
||||
|
||||
let s:popup_win_id = 0
|
||||
let s:nvim_border_win_id = 0
|
||||
"
|
||||
" tooltip dimensions
|
||||
let s:min_width = 1
|
||||
let s:min_height = 1
|
||||
let s:max_width = 80
|
||||
let s:max_height = 20
|
||||
|
||||
let s:is_neovim = has( 'nvim' )
|
||||
|
||||
|
||||
" This is used as the balloonexpr in vim to show the Tooltip at the hover
|
||||
" position
|
||||
function! vimspector#internal#balloon#HoverTooltip() abort
|
||||
return py3eval( '_vimspector_session.ShowEvalBalloon('
|
||||
\ . ' int( vim.eval( "v:beval_winnr" ) ) + 1,'
|
||||
\ . ' vim.eval( "v:beval_text"),'
|
||||
\ . ' 1 )' )
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#balloon#CreateTooltip( is_hover, ... ) abort
|
||||
let body = []
|
||||
if a:0 > 0
|
||||
let body = a:1
|
||||
endif
|
||||
|
||||
if s:popup_win_id != 0
|
||||
call vimspector#internal#balloon#Close()
|
||||
endif
|
||||
|
||||
if s:is_neovim
|
||||
call s:CreateNeovimTooltip( body )
|
||||
else
|
||||
let config = {
|
||||
\ 'wrap': 0,
|
||||
\ 'filtermode': 'n',
|
||||
\ 'maxwidth': s:max_width,
|
||||
\ 'maxheight': s:max_height,
|
||||
\ 'minwidth': s:min_width,
|
||||
\ 'minheight': s:min_height,
|
||||
\ 'scrollbar': 1,
|
||||
\ 'border': [],
|
||||
\ 'padding': [ 0, 1, 0, 1],
|
||||
\ 'drag': 1,
|
||||
\ 'resize': 1,
|
||||
\ 'close': 'button',
|
||||
\ 'callback': 'vimspector#internal#balloon#CloseCallback',
|
||||
\ }
|
||||
|
||||
let config = vimspector#internal#popup#SetBorderChars( config )
|
||||
|
||||
if a:is_hover
|
||||
let config[ 'filter' ] = 'vimspector#internal#balloon#MouseFilter'
|
||||
let config[ 'mousemoved' ] = [ 0, 0, 0 ]
|
||||
let s:popup_win_id = popup_beval( body, config )
|
||||
else
|
||||
let config[ 'filter' ] = 'vimspector#internal#balloon#CursorFilter'
|
||||
let config[ 'moved' ] = 'any'
|
||||
let config[ 'cursorline' ] = 1
|
||||
let config[ 'mapping' ] = 0
|
||||
let s:popup_win_id = popup_atcursor( body, config )
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
return s:popup_win_id
|
||||
endfunction
|
||||
|
||||
" Filters for vim {{{
|
||||
function! vimspector#internal#balloon#MouseFilter( winid, key ) abort
|
||||
if a:key ==# "\<Esc>"
|
||||
call vimspector#internal#balloon#Close()
|
||||
return 0
|
||||
endif
|
||||
|
||||
if index( [ "\<leftmouse>", "\<2-leftmouse>" ], a:key ) < 0
|
||||
return 0
|
||||
endif
|
||||
|
||||
let handled = 0
|
||||
let mouse_coords = getmousepos()
|
||||
|
||||
" close the popup if mouse is clicked outside the window
|
||||
if mouse_coords[ 'winid' ] != a:winid
|
||||
call vimspector#internal#balloon#Close()
|
||||
return 0
|
||||
endif
|
||||
|
||||
" place the cursor according to the click
|
||||
call win_execute( a:winid,
|
||||
\ ':call cursor( '
|
||||
\ . mouse_coords[ 'line' ]
|
||||
\ . ', '
|
||||
\ . mouse_coords[ 'column' ]
|
||||
\ . ' )' )
|
||||
|
||||
" expand the variable if we got double click
|
||||
if a:key ==? "\<2-leftmouse>"
|
||||
call py3eval( '_vimspector_session.ExpandVariable('
|
||||
\ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],'
|
||||
\ . 'line_num = ' . line( '.', a:winid )
|
||||
\ . ')' )
|
||||
let handled = 1
|
||||
endif
|
||||
|
||||
return handled
|
||||
endfunction
|
||||
|
||||
function! s:MatchKey( key, candidates ) abort
|
||||
for candidate in a:candidates
|
||||
" If the mapping string looks like a special character, then try and
|
||||
" expand it. This is... a hack. The whole thing only works if the mapping
|
||||
" is a single key (anyway), and so we assume any string starting with < is a
|
||||
" special key (which will be the common case) and try and map it. If it
|
||||
" fails... it fails.
|
||||
if candidate[ 0 ] == '<'
|
||||
try
|
||||
execute 'let candidate = "\' . candidate . '"'
|
||||
endtry
|
||||
endif
|
||||
|
||||
if candidate ==# a:key
|
||||
return v:true
|
||||
endif
|
||||
endfor
|
||||
|
||||
return v:false
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#balloon#CursorFilter( winid, key ) abort
|
||||
let mappings = py3eval(
|
||||
\ "__import__( 'vimspector',"
|
||||
\." fromlist = [ 'settings' ] ).settings.Dict("
|
||||
\." 'mappings' )[ 'variables' ]" )
|
||||
|
||||
if index( [ "\<LeftMouse>", "\<2-LeftMouse>" ], a:key ) >= 0
|
||||
return vimspector#internal#balloon#MouseFilter( a:winid, a:key )
|
||||
endif
|
||||
|
||||
if s:MatchKey( a:key, mappings.expand_collapse )
|
||||
call py3eval( '_vimspector_session.ExpandVariable('
|
||||
\ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],'
|
||||
\ . 'line_num = ' . line( '.', a:winid )
|
||||
\ . ')' )
|
||||
return 1
|
||||
elseif s:MatchKey( a:key, mappings.set_value )
|
||||
call py3eval( '_vimspector_session.SetVariableValue('
|
||||
\ . 'buf = vim.buffers[ ' . winbufnr( a:winid ) . ' ],'
|
||||
\ . 'line_num = ' . line( '.', a:winid )
|
||||
\ . ')' )
|
||||
return 1
|
||||
endif
|
||||
|
||||
return popup_filter_menu( a:winid, a:key )
|
||||
endfunction
|
||||
|
||||
" }}}
|
||||
|
||||
" Closing {{{
|
||||
|
||||
function! vimspector#internal#balloon#CloseCallback( ... ) abort
|
||||
let s:popup_win_id = 0
|
||||
let s:nvim_border_win_id = 0
|
||||
return py3eval( '_vimspector_session.CleanUpTooltip()' )
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#balloon#Close() abort
|
||||
if s:popup_win_id == 0
|
||||
return
|
||||
endif
|
||||
|
||||
if s:is_neovim
|
||||
call nvim_win_close( s:popup_win_id, v:true )
|
||||
call nvim_win_close( s:nvim_border_win_id, v:true )
|
||||
|
||||
call vimspector#internal#balloon#CloseCallback()
|
||||
else
|
||||
call popup_close(s:popup_win_id)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}
|
||||
|
||||
" Neovim pollyfill {{{
|
||||
|
||||
function! vimspector#internal#balloon#ResizeTooltip() abort
|
||||
if !s:is_neovim
|
||||
" Vim does this for us
|
||||
return
|
||||
endif
|
||||
|
||||
if s:popup_win_id <= 0 || s:nvim_border_win_id <= 0
|
||||
" nothing to resize
|
||||
return
|
||||
endif
|
||||
|
||||
noautocmd call win_gotoid( s:popup_win_id )
|
||||
let buf_lines = getline( 1, '$' )
|
||||
|
||||
let width = s:min_width
|
||||
let height = min( [ max( [ s:min_height, len( buf_lines ) ] ),
|
||||
\ s:max_height ] )
|
||||
|
||||
" calculate the longest line
|
||||
for l in buf_lines
|
||||
let width = max( [ width, len( l ) ] )
|
||||
endfor
|
||||
|
||||
let width = min( [ width, s:max_width ] )
|
||||
|
||||
let opts = {
|
||||
\ 'width': width,
|
||||
\ 'height': height,
|
||||
\ }
|
||||
|
||||
" resize the content window
|
||||
call nvim_win_set_config( s:popup_win_id, opts )
|
||||
|
||||
" resize the border window
|
||||
let opts[ 'width' ] = width + 4
|
||||
let opts[ 'height' ] = height + 2
|
||||
|
||||
call nvim_win_set_config( s:nvim_border_win_id, opts )
|
||||
call nvim_buf_set_lines( nvim_win_get_buf( s:nvim_border_win_id ),
|
||||
\ 0,
|
||||
\ -1,
|
||||
\ v:true,
|
||||
\ s:GenerateBorder( width, height ) )
|
||||
endfunction
|
||||
|
||||
" neovim doesn't have the border support, so we have to make our own.
|
||||
" FIXME: This will likely break if the user has `ambiwidth=2`
|
||||
function! s:GenerateBorder( width, height ) abort
|
||||
|
||||
let top = '╭' . repeat('─',a:width + 2) . '╮'
|
||||
let mid = '│' . repeat(' ',a:width + 2) . '│'
|
||||
let bot = '╰' . repeat('─',a:width + 2) . '╯'
|
||||
let lines = [ top ] + repeat( [ mid ], a:height ) + [ bot ]
|
||||
|
||||
return lines
|
||||
endfunction
|
||||
|
||||
function! s:CreateNeovimTooltip( body ) abort
|
||||
" generate border for the float window by creating a background buffer and
|
||||
" overlaying the content buffer
|
||||
" see https://github.com/neovim/neovim/issues/9718#issuecomment-546603628
|
||||
let buf_id = nvim_create_buf( v:false, v:true )
|
||||
call nvim_buf_set_lines( buf_id,
|
||||
\ 0,
|
||||
\ -1,
|
||||
\ v:true,
|
||||
\ s:GenerateBorder( s:max_width, s:max_height ) )
|
||||
|
||||
" default the dimensions initially, then we'll calculate the real size and
|
||||
" resize it.
|
||||
let opts = {
|
||||
\ 'relative': 'cursor',
|
||||
\ 'width': s:max_width + 2,
|
||||
\ 'height': s:max_height + 2,
|
||||
\ 'col': 0,
|
||||
\ 'row': 1,
|
||||
\ 'anchor': 'NW',
|
||||
\ 'style': 'minimal'
|
||||
\ }
|
||||
|
||||
" this is the border window
|
||||
let s:nvim_border_win_id = nvim_open_win( buf_id, 0, opts )
|
||||
call nvim_win_set_option( s:nvim_border_win_id, 'signcolumn', 'no' )
|
||||
call nvim_win_set_option( s:nvim_border_win_id, 'relativenumber', v:false )
|
||||
call nvim_win_set_option( s:nvim_border_win_id, 'number', v:false )
|
||||
|
||||
" when calculating where to display the content window, we need to account
|
||||
" for the border
|
||||
let opts.row += 1
|
||||
let opts.height -= 2
|
||||
let opts.col += 2
|
||||
let opts.width -= 4
|
||||
|
||||
" create the content window
|
||||
let buf_id = nvim_create_buf( v:false, v:true )
|
||||
call nvim_buf_set_lines( buf_id, 0, -1, v:true, a:body )
|
||||
call nvim_buf_set_option( buf_id, 'modifiable', v:false )
|
||||
let s:popup_win_id = nvim_open_win( buf_id, v:false, opts )
|
||||
|
||||
" Apparently none of these work, when 'style' is 'minimal'
|
||||
call nvim_win_set_option( s:popup_win_id, 'wrap', v:false )
|
||||
call nvim_win_set_option( s:popup_win_id, 'cursorline', v:true )
|
||||
call nvim_win_set_option( s:popup_win_id, 'signcolumn', 'no' )
|
||||
call nvim_win_set_option( s:popup_win_id, 'relativenumber', v:false )
|
||||
call nvim_win_set_option( s:popup_win_id, 'number', v:false )
|
||||
|
||||
" Move the cursor into the popup window, as this is the only way we can
|
||||
" interract with the popup in neovim
|
||||
noautocmd call win_gotoid( s:popup_win_id )
|
||||
|
||||
nnoremap <silent> <buffer> <Esc> <cmd>quit<CR>
|
||||
call py3eval( "__import__( 'vimspector', "
|
||||
\." fromlist = [ 'variables' ] )."
|
||||
\.' variables.AddExpandMappings()' )
|
||||
|
||||
" Close the popup whenever we leave this window
|
||||
augroup vimspector#internal#balloon#nvim_float
|
||||
autocmd!
|
||||
autocmd WinLeave <buffer>
|
||||
\ :call vimspector#internal#balloon#Close()
|
||||
\ | autocmd! vimspector#internal#balloon#nvim_float
|
||||
augroup END
|
||||
|
||||
call vimspector#internal#balloon#ResizeTooltip()
|
||||
endfunction
|
||||
|
||||
" }}}
|
||||
|
||||
|
||||
" Boilerplate {{{
|
||||
let &cpoptions=s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ function! vimspector#internal#channel#StartDebugSession( config ) abort
|
|||
\ )
|
||||
endif
|
||||
|
||||
let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ]
|
||||
let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ]
|
||||
|
||||
echo 'Connecting to ' . l:addr . '... (waiting fo up to 10 seconds)'
|
||||
let s:ch = ch_open( l:addr,
|
||||
|
|
@ -95,21 +95,44 @@ EOF
|
|||
endfunction
|
||||
|
||||
function! vimspector#internal#channel#StopDebugSession() abort
|
||||
if exists( 's:ch' ) && ch_status( s:ch ) ==# 'open'
|
||||
|
||||
if exists( 's:job' )
|
||||
" We started the job, so we need to kill it and wait to read all the data
|
||||
" from the socket
|
||||
|
||||
if job_status( s:job ) ==# 'run'
|
||||
call job_stop( s:job, 'term' )
|
||||
endif
|
||||
|
||||
while job_status( s:job ) ==# 'run'
|
||||
call job_stop( s:job, 'kill' )
|
||||
endwhile
|
||||
|
||||
unlet s:job
|
||||
|
||||
if exists( 's:ch' ) && count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0
|
||||
" We're going to block on this channel reading, then manually call the
|
||||
" close callback, so remove the automatic close callback to avoid tricky
|
||||
" re-entrancy
|
||||
call ch_setoptions( s:ch, { 'close_cb': '' } )
|
||||
endif
|
||||
|
||||
elseif exists( 's:ch' ) &&
|
||||
\ count( [ 'closed', 'fail' ], ch_status( s:ch ) ) == 0
|
||||
|
||||
" channel is open, close it and trigger the callback. The callback is _not_
|
||||
" triggered when manually calling ch_close. if we get here and the channel
|
||||
" is not open, then we there is a _OnClose callback waiting for us, so do
|
||||
" nothing.
|
||||
call ch_close( s:ch )
|
||||
call s:_OnClose( s:ch )
|
||||
endif
|
||||
|
||||
if exists( 's:job' )
|
||||
if job_status( s:job ) ==# 'run'
|
||||
call job_stop( s:job, 'kill' )
|
||||
endif
|
||||
unlet s:job
|
||||
endif
|
||||
" block until we've read all data from the socket and handled it.
|
||||
while count( [ 'open', 'buffered' ], ch_status( s:ch ) ) == 1
|
||||
let data = ch_read( s:ch, { 'timeout': 10 } )
|
||||
call s:_OnServerData( s:ch, data )
|
||||
endwhile
|
||||
call s:_OnClose( s:ch )
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#channel#Reset() abort
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ function! vimspector#internal#neochannel#StartDebugSession( config ) abort
|
|||
endtry
|
||||
endif
|
||||
|
||||
let l:addr = get( a:config, 'host', 'localhost' ) . ':' . a:config[ 'port' ]
|
||||
let l:addr = get( a:config, 'host', '127.0.0.1' ) . ':' . a:config[ 'port' ]
|
||||
|
||||
let attempt = 1
|
||||
while attempt <= 10
|
||||
|
|
|
|||
|
|
@ -159,15 +159,16 @@ function! s:_OnCommandEvent( category, id, data, event ) abort
|
|||
call setbufvar( buffer, '&modified', 0 )
|
||||
endtry
|
||||
|
||||
" if the buffer is visible, scroll it
|
||||
" if the buffer is visible, scroll it, but don't allow autocommands to fire,
|
||||
" as this may close the current window!
|
||||
let w = bufwinnr( buffer )
|
||||
if w > 0
|
||||
let cw = winnr()
|
||||
try
|
||||
execute w . 'wincmd w'
|
||||
normal! Gz-
|
||||
noautocmd execute w . 'wincmd w'
|
||||
noautocmd normal! Gz-
|
||||
finally
|
||||
execute cw . 'wincmd w'
|
||||
noautocmd execute cw . 'wincmd w'
|
||||
endtry
|
||||
endif
|
||||
elseif a:event ==# 'exit'
|
||||
|
|
|
|||
|
|
@ -80,6 +80,56 @@ function! vimspector#internal#neopopup#HideSplash( id ) abort
|
|||
unlet s:db[ a:id ]
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#neopopup#Confirm( confirm_id,
|
||||
\ text,
|
||||
\ options,
|
||||
\ default_value,
|
||||
\ keys ) abort
|
||||
|
||||
" Neovim doesn't have an equivalent of popup_dialog, and it's way too much
|
||||
" effort to write one, so we just use confirm()...
|
||||
" Annoyingly we can't use confirm() here because for some reason it doesn't
|
||||
" render properly in a channel callback. So we use input() and mimic dialog
|
||||
" behaviour.
|
||||
let prompt = a:text
|
||||
for opt in a:options
|
||||
let prompt .= ' ' . opt
|
||||
endfor
|
||||
let prompt .= ': '
|
||||
|
||||
try
|
||||
let result = input( prompt, a:keys[ a:default_value - 1 ] )
|
||||
catch /.*/
|
||||
let result = -1
|
||||
endtry
|
||||
|
||||
" Map the results to what the vim popup stuff would return (s:ConfirmCallback
|
||||
" in popup.vim), i.e.:
|
||||
" - 1-based index of selected item, or
|
||||
" - -1 or 0 for cancellation
|
||||
if result == ''
|
||||
" User pressed ESC/ctrl-c
|
||||
let result = -1
|
||||
else
|
||||
let index = 1
|
||||
for k in a:keys
|
||||
if k ==? result
|
||||
let result = index
|
||||
break
|
||||
endif
|
||||
let index += 1
|
||||
endfor
|
||||
|
||||
if index > len( a:keys )
|
||||
let result = -1
|
||||
endif
|
||||
endif
|
||||
|
||||
py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback(
|
||||
\ int( vim.eval( 'a:confirm_id' ) ),
|
||||
\ int( vim.eval( 'result' ) ) )
|
||||
endfunction
|
||||
|
||||
" Boilerplate {{{
|
||||
let &cpoptions=s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
" See the License for the specific language governing permissions and
|
||||
" limitations under the License.
|
||||
scriptencoding utf-8
|
||||
|
||||
|
||||
" Boilerplate {{{
|
||||
|
|
@ -32,6 +33,113 @@ function! vimspector#internal#popup#HideSplash( id ) abort
|
|||
call popup_hide( a:id )
|
||||
endfunction
|
||||
|
||||
let s:current_selection = 0
|
||||
let s:selections = []
|
||||
let s:text = []
|
||||
|
||||
function! s:UpdatePopup( id ) abort
|
||||
let buf = copy( s:text )
|
||||
call extend( buf, s:DrawButtons() )
|
||||
call popup_settext( a:id, buf )
|
||||
endfunction
|
||||
|
||||
function! s:ConfirmKeyFilter( keys, id, key ) abort
|
||||
if a:key ==# "\<CR>"
|
||||
call popup_close( a:id, s:current_selection + 1 )
|
||||
return 1
|
||||
elseif index( [ "\<Tab>", "\<Right>" ], a:key ) >= 0
|
||||
let s:current_selection = ( s:current_selection + 1 ) % len( s:selections )
|
||||
call s:UpdatePopup( a:id )
|
||||
return 1
|
||||
elseif index( [ "\<S-Tab>", "\<Left>" ], a:key ) >= 0
|
||||
let s:current_selection = s:current_selection == 0
|
||||
\ ? len( s:selections ) - 1: s:current_selection - 1
|
||||
call s:UpdatePopup( a:id )
|
||||
return 1
|
||||
elseif a:key ==# "\<Esc>" || a:key ==# "\<C-c>"
|
||||
call popup_close( a:id, -1 )
|
||||
return 1
|
||||
endif
|
||||
|
||||
let index = 1
|
||||
for key in a:keys
|
||||
if a:key ==? key
|
||||
call popup_close( a:id, index )
|
||||
return 1
|
||||
endif
|
||||
let index += 1
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:ConfirmCallback( confirm_id, id, result ) abort
|
||||
py3 __import__( 'vimspector', fromlist = [ 'utils' ] ).utils.ConfirmCallback(
|
||||
\ int( vim.eval( 'a:confirm_id' ) ),
|
||||
\ int( vim.eval( 'a:result' ) ) )
|
||||
endfunction
|
||||
|
||||
function! s:SelectionPosition( idx ) abort
|
||||
return a:idx == 0 ? 0 : len( join( s:selections[ : a:idx - 1 ], ' ' ) ) + 1
|
||||
endfunction
|
||||
|
||||
function! s:DrawButtons() abort
|
||||
return [ {
|
||||
\ 'text': join( s:selections, ' ' ),
|
||||
\ 'props': [
|
||||
\ {
|
||||
\ 'col': s:SelectionPosition( s:current_selection ) + 1,
|
||||
\ 'length': len( s:selections[ s:current_selection ] ),
|
||||
\ 'type': 'VimspectorSelectedItem'
|
||||
\ },
|
||||
\ ]
|
||||
\ } ]
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#popup#Confirm(
|
||||
\ confirm_id,
|
||||
\ text,
|
||||
\ options,
|
||||
\ default_value,
|
||||
\ keys ) abort
|
||||
|
||||
silent! call prop_type_add( 'VimspectorSelectedItem', {
|
||||
\ 'highlight': 'PMenuSel'
|
||||
\ } )
|
||||
|
||||
let lines = split( a:text, "\n", v:true )
|
||||
let buf = []
|
||||
for line in lines
|
||||
call add( buf, { 'text': line, 'props': [] } )
|
||||
endfor
|
||||
|
||||
call add( buf, { 'text': '', 'props': [] } )
|
||||
|
||||
let s:selections = a:options
|
||||
let s:current_selection = ( a:default_value - 1 )
|
||||
|
||||
let s:text = copy( buf )
|
||||
call extend( buf, s:DrawButtons() )
|
||||
|
||||
let config = {
|
||||
\ 'callback': function( 's:ConfirmCallback', [ a:confirm_id ] ),
|
||||
\ 'filter': function( 's:ConfirmKeyFilter', [ a:keys ] ),
|
||||
\ 'mapping': v:false,
|
||||
\ }
|
||||
let config = vimspector#internal#popup#SetBorderChars( config )
|
||||
|
||||
return popup_dialog( buf, config )
|
||||
endfunction
|
||||
|
||||
function! vimspector#internal#popup#SetBorderChars( config ) abort
|
||||
" When ambiwidth is single, use prettier characters for the border. This
|
||||
" would look silly when ambiwidth is double.
|
||||
if &ambiwidth ==# 'single' && &encoding ==? 'utf-8'
|
||||
let a:config[ 'borderchars' ] = [ '─', '│', '─', '│', '╭', '╮', '┛', '╰' ]
|
||||
endif
|
||||
|
||||
return a:config
|
||||
endfunction
|
||||
|
||||
|
||||
" Boilerplate {{{
|
||||
let &cpoptions=s:save_cpo
|
||||
unlet s:save_cpo
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ function! vimspector#internal#state#Reset() abort
|
|||
catch /.*/
|
||||
echohl WarningMsg
|
||||
echom 'Exception while loading vimspector:' v:exception
|
||||
echom 'From:' v:throwpoint
|
||||
echom 'Vimspector unavailable: Requires Vim compiled with Python 3.6'
|
||||
echohl None
|
||||
return v:false
|
||||
|
|
|
|||
1085
doc/vimspector-ref.txt
Normal file
1085
doc/vimspector-ref.txt
Normal file
File diff suppressed because it is too large
Load diff
2394
doc/vimspector.txt
Normal file
2394
doc/vimspector.txt
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -28,3 +28,5 @@ gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw, :jruby]
|
|||
# Performance-booster for watching directories on Windows
|
||||
gem "wdm", "~> 0.1.0" if Gem.win_platform?
|
||||
|
||||
|
||||
gem "webrick", "~> 1.7"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activesupport (6.0.3.2)
|
||||
activesupport (6.0.3.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
tzinfo (~> 1.1)
|
||||
zeitwerk (~> 2.2, >= 2.2.2)
|
||||
addressable (2.7.0)
|
||||
addressable (2.8.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
coffee-script (2.4.1)
|
||||
coffee-script-source
|
||||
|
|
@ -16,46 +16,49 @@ GEM
|
|||
colorator (1.1.0)
|
||||
commonmarker (0.17.13)
|
||||
ruby-enum (~> 0.5)
|
||||
concurrent-ruby (1.1.7)
|
||||
dnsruby (1.61.4)
|
||||
concurrent-ruby (1.1.8)
|
||||
dnsruby (1.61.5)
|
||||
simpleidn (~> 0.1)
|
||||
em-websocket (0.5.1)
|
||||
em-websocket (0.5.2)
|
||||
eventmachine (>= 0.12.9)
|
||||
http_parser.rb (~> 0.6.0)
|
||||
ethon (0.12.0)
|
||||
ffi (>= 1.3.0)
|
||||
eventmachine (1.2.7)
|
||||
execjs (2.7.0)
|
||||
faraday (1.0.1)
|
||||
faraday (1.3.0)
|
||||
faraday-net_http (~> 1.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffi (1.13.1)
|
||||
ruby2_keywords
|
||||
faraday-net_http (1.0.1)
|
||||
ffi (1.15.0)
|
||||
forwardable-extended (2.6.0)
|
||||
gemoji (3.0.1)
|
||||
github-pages (207)
|
||||
github-pages-health-check (= 1.16.1)
|
||||
github-pages (214)
|
||||
github-pages-health-check (= 1.17.0)
|
||||
jekyll (= 3.9.0)
|
||||
jekyll-avatar (= 0.7.0)
|
||||
jekyll-coffeescript (= 1.1.1)
|
||||
jekyll-commonmark-ghpages (= 0.1.6)
|
||||
jekyll-default-layout (= 0.1.4)
|
||||
jekyll-feed (= 0.13.0)
|
||||
jekyll-feed (= 0.15.1)
|
||||
jekyll-gist (= 1.5.0)
|
||||
jekyll-github-metadata (= 2.13.0)
|
||||
jekyll-mentions (= 1.5.1)
|
||||
jekyll-mentions (= 1.6.0)
|
||||
jekyll-optional-front-matter (= 0.3.2)
|
||||
jekyll-paginate (= 1.1.0)
|
||||
jekyll-readme-index (= 0.3.0)
|
||||
jekyll-redirect-from (= 0.15.0)
|
||||
jekyll-redirect-from (= 0.16.0)
|
||||
jekyll-relative-links (= 0.6.1)
|
||||
jekyll-remote-theme (= 0.4.1)
|
||||
jekyll-remote-theme (= 0.4.3)
|
||||
jekyll-sass-converter (= 1.5.2)
|
||||
jekyll-seo-tag (= 2.6.1)
|
||||
jekyll-seo-tag (= 2.7.1)
|
||||
jekyll-sitemap (= 1.4.0)
|
||||
jekyll-swiss (= 1.0.0)
|
||||
jekyll-theme-architect (= 0.1.1)
|
||||
jekyll-theme-cayman (= 0.1.1)
|
||||
jekyll-theme-dinky (= 0.1.1)
|
||||
jekyll-theme-hacker (= 0.1.1)
|
||||
jekyll-theme-hacker (= 0.1.2)
|
||||
jekyll-theme-leap-day (= 0.1.1)
|
||||
jekyll-theme-merlot (= 0.1.1)
|
||||
jekyll-theme-midnight (= 0.1.1)
|
||||
|
|
@ -66,20 +69,20 @@ GEM
|
|||
jekyll-theme-tactile (= 0.1.1)
|
||||
jekyll-theme-time-machine (= 0.1.1)
|
||||
jekyll-titles-from-headings (= 0.5.3)
|
||||
jemoji (= 0.11.1)
|
||||
kramdown (= 2.3.0)
|
||||
jemoji (= 0.12.0)
|
||||
kramdown (= 2.3.1)
|
||||
kramdown-parser-gfm (= 1.1.0)
|
||||
liquid (= 4.0.3)
|
||||
mercenary (~> 0.3)
|
||||
minima (= 2.5.1)
|
||||
nokogiri (>= 1.10.4, < 2.0)
|
||||
rouge (= 3.19.0)
|
||||
rouge (= 3.26.0)
|
||||
terminal-table (~> 1.4)
|
||||
github-pages-health-check (1.16.1)
|
||||
github-pages-health-check (1.17.0)
|
||||
addressable (~> 2.3)
|
||||
dnsruby (~> 1.60)
|
||||
octokit (~> 4.0)
|
||||
public_suffix (~> 3.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
typhoeus (~> 1.3)
|
||||
html-pipeline (2.14.0)
|
||||
activesupport (>= 2)
|
||||
|
|
@ -114,14 +117,14 @@ GEM
|
|||
rouge (>= 2.0, < 4.0)
|
||||
jekyll-default-layout (0.1.4)
|
||||
jekyll (~> 3.0)
|
||||
jekyll-feed (0.13.0)
|
||||
jekyll-feed (0.15.1)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-gist (1.5.0)
|
||||
octokit (~> 4.2)
|
||||
jekyll-github-metadata (2.13.0)
|
||||
jekyll (>= 3.4, < 5.0)
|
||||
octokit (~> 4.0, != 4.4.0)
|
||||
jekyll-mentions (1.5.1)
|
||||
jekyll-mentions (1.6.0)
|
||||
html-pipeline (~> 2.3)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-optional-front-matter (0.3.2)
|
||||
|
|
@ -129,18 +132,19 @@ GEM
|
|||
jekyll-paginate (1.1.0)
|
||||
jekyll-readme-index (0.3.0)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
jekyll-redirect-from (0.15.0)
|
||||
jekyll-redirect-from (0.16.0)
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-relative-links (0.6.1)
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-remote-theme (0.4.1)
|
||||
jekyll-remote-theme (0.4.3)
|
||||
addressable (~> 2.0)
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
rubyzip (>= 1.3.0)
|
||||
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
|
||||
rubyzip (>= 1.3.0, < 3.0)
|
||||
jekyll-sass-converter (1.5.2)
|
||||
sass (~> 3.4)
|
||||
jekyll-seo-tag (2.6.1)
|
||||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-seo-tag (2.7.1)
|
||||
jekyll (>= 3.8, < 5.0)
|
||||
jekyll-sitemap (1.4.0)
|
||||
jekyll (>= 3.7, < 5.0)
|
||||
jekyll-swiss (1.0.0)
|
||||
|
|
@ -153,8 +157,8 @@ GEM
|
|||
jekyll-theme-dinky (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-hacker (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
jekyll-theme-hacker (0.1.2)
|
||||
jekyll (> 3.5, < 5.0)
|
||||
jekyll-seo-tag (~> 2.0)
|
||||
jekyll-theme-leap-day (0.1.1)
|
||||
jekyll (~> 3.5)
|
||||
|
|
@ -188,41 +192,44 @@ GEM
|
|||
jekyll (>= 3.3, < 5.0)
|
||||
jekyll-watch (2.2.1)
|
||||
listen (~> 3.0)
|
||||
jemoji (0.11.1)
|
||||
jemoji (0.12.0)
|
||||
gemoji (~> 3.0)
|
||||
html-pipeline (~> 2.2)
|
||||
jekyll (>= 3.0, < 5.0)
|
||||
kramdown (2.3.0)
|
||||
kramdown (2.3.1)
|
||||
rexml
|
||||
kramdown-parser-gfm (1.1.0)
|
||||
kramdown (~> 2.0)
|
||||
liquid (4.0.3)
|
||||
listen (3.2.1)
|
||||
listen (3.5.1)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
rb-inotify (~> 0.9, >= 0.9.10)
|
||||
mercenary (0.3.6)
|
||||
mini_portile2 (2.4.0)
|
||||
mini_portile2 (2.5.1)
|
||||
minima (2.5.1)
|
||||
jekyll (>= 3.5, < 5.0)
|
||||
jekyll-feed (~> 0.9)
|
||||
jekyll-seo-tag (~> 2.1)
|
||||
minitest (5.14.1)
|
||||
minitest (5.14.4)
|
||||
multipart-post (2.1.1)
|
||||
nokogiri (1.10.10)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
octokit (4.18.0)
|
||||
nokogiri (1.11.5)
|
||||
mini_portile2 (~> 2.5.0)
|
||||
racc (~> 1.4)
|
||||
octokit (4.20.0)
|
||||
faraday (>= 0.9)
|
||||
sawyer (~> 0.8.0, >= 0.5.3)
|
||||
pathutil (0.16.2)
|
||||
forwardable-extended (~> 2.6)
|
||||
public_suffix (3.1.1)
|
||||
public_suffix (4.0.6)
|
||||
racc (1.5.2)
|
||||
rb-fsevent (0.10.4)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rexml (3.2.4)
|
||||
rouge (3.19.0)
|
||||
ruby-enum (0.8.0)
|
||||
rexml (3.2.5)
|
||||
rouge (3.26.0)
|
||||
ruby-enum (0.9.0)
|
||||
i18n
|
||||
ruby2_keywords (0.0.4)
|
||||
rubyzip (2.3.0)
|
||||
safe_yaml (1.0.5)
|
||||
sass (3.7.4)
|
||||
|
|
@ -233,20 +240,21 @@ GEM
|
|||
sawyer (0.8.2)
|
||||
addressable (>= 2.3.5)
|
||||
faraday (> 0.8, < 2.0)
|
||||
simpleidn (0.1.1)
|
||||
simpleidn (0.2.1)
|
||||
unf (~> 0.1.4)
|
||||
terminal-table (1.8.0)
|
||||
unicode-display_width (~> 1.1, >= 1.1.1)
|
||||
thread_safe (0.3.6)
|
||||
typhoeus (1.4.0)
|
||||
ethon (>= 0.9.0)
|
||||
tzinfo (1.2.7)
|
||||
tzinfo (1.2.9)
|
||||
thread_safe (~> 0.1)
|
||||
unf (0.1.4)
|
||||
unf_ext
|
||||
unf_ext (0.0.7.7)
|
||||
unicode-display_width (1.7.0)
|
||||
zeitwerk (2.4.0)
|
||||
webrick (1.7.0)
|
||||
zeitwerk (2.4.2)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
|
@ -256,6 +264,7 @@ DEPENDENCIES
|
|||
jekyll-feed (~> 0.6)
|
||||
minima (~> 2.0)
|
||||
tzinfo-data
|
||||
webrick (~> 1.7)
|
||||
|
||||
BUNDLED WITH
|
||||
2.0.2
|
||||
2.2.3
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
To update/install:
|
||||
|
||||
gem install bundler
|
||||
bundle install
|
||||
bundle install --path vendor/bundle
|
||||
|
||||
To run a local server/test the build
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ for Vimspector.
|
|||
* [Debug profile configuration](#debug-profile-configuration)
|
||||
* [Replacements and variables](#replacements-and-variables)
|
||||
* [The splat operator](#the-splat-operator)
|
||||
* [Default values](#default-values)
|
||||
* [Default values](#default-values)
|
||||
* [Coercing Types](#coercing-types)
|
||||
* [Configuration Format](#configuration-format)
|
||||
* [Files and locations](#files-and-locations)
|
||||
* [Adapter configurations](#adapter-configurations)
|
||||
|
|
@ -20,7 +21,7 @@ for Vimspector.
|
|||
* [Configuration selection](#configuration-selection)
|
||||
* [Specifying a default configuration](#specifying-a-default-configuration)
|
||||
* [Preventing automatic selection](#preventing-automatic-selection)
|
||||
* [Exception breakpionts](#exception-breakpionts)
|
||||
* [Exception Breakpoints](#exception-breakpoints)
|
||||
* [Predefined Variables](#predefined-variables)
|
||||
* [Remote Debugging Support](#remote-debugging-support)
|
||||
* [Python (debugpy) Example](#python-debugpy-example)
|
||||
|
|
@ -29,7 +30,7 @@ for Vimspector.
|
|||
* [Appendix: Configuration file format](#appendix-configuration-file-format)
|
||||
* [Appendix: Editor configuration](#appendix-editor-configuration)
|
||||
|
||||
<!-- Added by: ben, at: Fri 31 Jul 2020 22:13:39 BST -->
|
||||
<!-- Added by: ben, at: Thu 13 Aug 2020 17:42:11 BST -->
|
||||
|
||||
<!--te-->
|
||||
|
||||
|
|
@ -164,7 +165,7 @@ the following variable substitutions:
|
|||
the shell command. Note these variables can be supplied by both the debug and
|
||||
adapter configurations and can be either static strings or shell commands.
|
||||
|
||||
### The splat operator
|
||||
#### The splat operator
|
||||
|
||||
Often we want to create a single `.vimspector.json` entry which encompasses many
|
||||
use cases, as it is tedious to write every use case/start up option in JSON.
|
||||
|
|
@ -205,7 +206,7 @@ You can also combine with static values:
|
|||
This would yield the intuitive result:
|
||||
`[ "First", "one", "two three", "four", "Last" ]`
|
||||
|
||||
### Default values
|
||||
#### Default values
|
||||
|
||||
You can specify replacements with default values. In this case if the user has
|
||||
not specified a value, they are prompted but with the default value
|
||||
|
|
@ -236,7 +237,7 @@ the closing `}`. For example, the is a common and useful case:
|
|||
This will prompt the user to specify `script`, but it will default to the path
|
||||
to the current file.
|
||||
|
||||
### Coercing Types
|
||||
#### Coercing Types
|
||||
|
||||
Sometimes, you want to provide an option for a boolean parameter, or want to
|
||||
allow the user to specify more than just strings. Vimspector allows you to do
|
||||
|
|
@ -270,7 +271,7 @@ JSON value `true`, and the suffix is stripped fom the key, resulting in the
|
|||
following:
|
||||
|
||||
```json
|
||||
"stopOnEntry#json": true
|
||||
"stopOnEntry": true
|
||||
```
|
||||
|
||||
Which is what we need.
|
||||
|
|
@ -282,7 +283,7 @@ can force Vimspector to treat the value as a string by appending `#s`, as in:
|
|||
"unlikelyKeyName#json#s": "this is a string, not JSON data"
|
||||
```
|
||||
|
||||
#### Advanced usage
|
||||
***Advanced usage:***
|
||||
|
||||
The most common usage for this is for number and bool types, but it works for
|
||||
objects too. If you want to be able to specify a whole object (e.g. a whole
|
||||
|
|
@ -632,19 +633,26 @@ Vimspector then orchestrates the various tools to set you up.
|
|||
// Command to launch the debugee and attach the debugger;
|
||||
// %CMD% replaced with the remote-cmdLine configured in the launch
|
||||
// configuration. (mandatory)
|
||||
"launchCommmand": [
|
||||
"python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"runCommand": [
|
||||
"python", "-m", "debugpy",
|
||||
"--listen", "0.0.0.0:${port}",
|
||||
"--wait-for-client",
|
||||
"%CMD%"
|
||||
]
|
||||
|
||||
// Optional alternative to launchCommmand (if you need to run multiple
|
||||
// Optional alternative to runCommand (if you need to run multiple
|
||||
// commands)
|
||||
// "launchCommmands": [
|
||||
// "runCommands": [
|
||||
// [ /* first command */ ],
|
||||
// [ /* second command */ ]
|
||||
// ]
|
||||
|
||||
}
|
||||
|
||||
// optional delay to wait after running runCommand(s). This is often
|
||||
// needed because of the way docker handles TCP, or if you're using some
|
||||
// wrapper (e.g. to start the JVM)
|
||||
// "delay": "1000m" // format as per :help sleep
|
||||
},
|
||||
"attach": {
|
||||
"remote": {
|
||||
|
|
@ -684,6 +692,10 @@ Vimspector then orchestrates the various tools to set you up.
|
|||
// "args": [ "-o", "StrictHostKeyChecking=no" ]
|
||||
// },
|
||||
}
|
||||
// optional delay to wait after running runCommand(s). This is often
|
||||
// needed because of the way docker handles TCP, or if you're using some
|
||||
// wrapper (e.g. to start the JVM)
|
||||
// "delay": "1000m" // format as per :help sleep
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
@ -710,7 +722,7 @@ Vimspector then orchestrates the various tools to set you up.
|
|||
"variables": {
|
||||
// Just an example of how to specify a variable manually rather than
|
||||
// vimspector asking for input from the user
|
||||
"ServiceName": "${fileBasenameNoExtention}"
|
||||
"ServiceName": "${fileBasenameNoExtension}"
|
||||
},
|
||||
|
||||
"adapter": "python-remote",
|
||||
|
|
@ -753,7 +765,7 @@ and have to tell cpptools a few more options.
|
|||
"remote": {
|
||||
"host": "${host}",
|
||||
"account": "${account}",
|
||||
"launchCommmand": [
|
||||
"runCommand": [
|
||||
"gdbserver",
|
||||
"--once",
|
||||
"--no-startup-with-shell",
|
||||
|
|
@ -837,19 +849,25 @@ port.
|
|||
// Command to launch the debugee and attach the debugger;
|
||||
// %CMD% replaced with the remote-cmdLine configured in the launch
|
||||
// configuration. (mandatory)
|
||||
"launchCommmand": [
|
||||
"python", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"runCommand": [
|
||||
"python", "-m", "debugpy",
|
||||
"--listen", "0.0.0.0:${port}",
|
||||
"--wait-for-client",
|
||||
"%CMD%"
|
||||
]
|
||||
|
||||
// Optional alternative to launchCommmand (if you need to run multiple
|
||||
// Optional alternative to runCommand (if you need to run multiple
|
||||
// commands)
|
||||
// "launchCommmands": [
|
||||
// "runCommands": [
|
||||
// [ /* first command */ ],
|
||||
// [ /* second command */ ]
|
||||
// ]
|
||||
|
||||
}
|
||||
|
||||
// optional delay to wait after running runCommand(s). This is often
|
||||
// needed because of the way docker handles TCP
|
||||
"delay": "1000m" // format as per :help sleep
|
||||
},
|
||||
"attach": {
|
||||
"remote": {
|
||||
|
|
@ -885,6 +903,11 @@ port.
|
|||
// ]
|
||||
|
||||
}
|
||||
|
||||
// optional delay to wait after running runCommand(s). This is often
|
||||
// needed because of the way docker handles TCP, or if you're using some
|
||||
// wrapper (e.g. to start the JVM)
|
||||
"delay": "1000m" // format as per :help sleep
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -38,11 +38,144 @@
|
|||
]
|
||||
}
|
||||
},
|
||||
"adapter-common": {
|
||||
"adapter-launchattach": {
|
||||
"properties": {
|
||||
"launch": {
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/adapter-remote" },
|
||||
{
|
||||
"properties": {
|
||||
"delay": {
|
||||
"type": "string",
|
||||
"description": "A time in the format understood by :help :sleep to wait after running the attachCommand(s)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"attach": {
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/adapter-remote" },
|
||||
{
|
||||
"type": "object",
|
||||
"required": [ "pidSelect" ],
|
||||
"properties": {
|
||||
"pidSelect": {
|
||||
"enum": [ "ask", "none" ]
|
||||
},
|
||||
"pidProperty": {
|
||||
"type": "string",
|
||||
"description": "The launch config property which the PID should be injected into. Required when 'pidSelect' is 'ask'."
|
||||
},
|
||||
"delay": {
|
||||
"type": "string",
|
||||
"description": "A time in the format understood by :help :sleep to wait after running the attachCommand(s)"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"adapter-remote": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"remote": {
|
||||
"type": "object",
|
||||
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
|
||||
"allOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{ "required": [ "host" ] },
|
||||
{ "required": [ "container" ] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string",
|
||||
"description": "Remote account name used when ssh'ing. Defaults to the current user account."
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "Name of the remote host to connect to (via passwordless SSH)."
|
||||
},
|
||||
"container": {
|
||||
"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 <tt>docker run -p 8765:8765 -it simple_python</tt>)."
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"oneOf": [
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{ "required": [ "attachCommand" ] },
|
||||
{ "required": [ "attachCommands" ] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"initCompleteCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "For remote-attach. Remote command to execute after initialization of the debug adapter. Can be used to work around buggy attach behaviour on certain platforms (advanced usage). Can contain the special token %PID% which is replaced with the PID returned by 'pidCommand'"
|
||||
},
|
||||
"pidCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Required for remote-attach. Remote command to execute to return the PID to attach to."
|
||||
},
|
||||
"attachCommands": {
|
||||
"type": [ "array" ],
|
||||
"items": { "type": "array", "items": { "type": "string" } },
|
||||
"description": "For remote-attach. List of commands to execute remotely to set up the attach. Can contain the special token %PID% which is replaced with the PID returned by the remote 'pidCommand'."
|
||||
},
|
||||
"attachCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "A single command to execute for remote-attach. Like attachCommands but for a single command. If attachCommands is supplied, this is not used."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{
|
||||
"oneOf": [
|
||||
{ "required": [ "runCommand" ] },
|
||||
{ "required": [ "runCommands" ] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"properties": {
|
||||
"runCommands": {
|
||||
"type": [ "array" ],
|
||||
"items": { "type": "array", "items": { "type": "string" } },
|
||||
"description": "For remote-launch. List of commands to execute remotely to set up the launch. An entry in the array can be the special token '%CMD%' which is replaced with the evaluated 'remote-cmdLine' value in the debug configuration. This is useful to parameterize launcging remotely under something like gdbserver."
|
||||
},
|
||||
"runCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "A single command to execute for remote-launch. Like runCommands but for a single command."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"adapter": {
|
||||
"allOf": [
|
||||
{ "type": "object" },
|
||||
{ "$ref": "#/definitions/variables" },
|
||||
{ "$ref": "#/definitions/adapter-remote" },
|
||||
{ "$ref": "#/definitions/adapter-attach" },
|
||||
{
|
||||
"properties": {
|
||||
"name": {
|
||||
|
|
@ -54,136 +187,30 @@
|
|||
"description": "Base debug configuration. Can be used to set default values for all debug configurations. When reading individual debug configurations from 'configurations', those configurations are merged with this object. Definitions in the debug configuration override anything in this object. Typical usage for this is to set the 'type' parameter, which some debug adapters are very picky about, or to set e.g. the path to an underlying debugger."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"adapter-attach": {
|
||||
"properties": {
|
||||
"attach": {
|
||||
"type": "object",
|
||||
"required": [ "pidSelect" ],
|
||||
"properties": {
|
||||
"pidSelect": {
|
||||
"enum": [ "ask", "none" ]
|
||||
},
|
||||
"pidProperty": {
|
||||
"type": "string",
|
||||
"description": "The launch config property which the PID should be injected into. Required when 'pidSelect' is 'ask'."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"adapter-remote": {
|
||||
"properties": {
|
||||
"remote": {
|
||||
"type": "object",
|
||||
"oneOf": [
|
||||
{
|
||||
"required": [
|
||||
"host"
|
||||
]
|
||||
},
|
||||
{
|
||||
"required": [
|
||||
"container"
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "Configures how Vimspector will marshal remote debugging requests. When remote debugging, Vimspector will either ssh to 'account'@'host' or docker exec -it to 'container' and run 'pidCommand', 'attachCommands', 'runCommands', etc. based on the 'remote-command' option in the debug configuration. If 'remote-command' is 'launch', it runs 'runCommand(s)', otherwise (it's 'attach') vimspector runs 'pidCommand', followed by 'attachCommand(s)'.Then it starts up the debug adapter with the debug configuration as normal. Usually this is configured with an 'attach' request (whether we remotely 'launched' or not). Once the initialization exchange is complete, Vimspector runs the optional 'initCompleteCommand' which can be used to force the application to break, e.g. by sending it SIGINT. This is required on some platforms which have buggy gdbservers (for example)",
|
||||
"properties": {
|
||||
"account": {
|
||||
"type": "string",
|
||||
"description": "Remote account name used when ssh'ing. Defaults to the current user account."
|
||||
},
|
||||
"host": {
|
||||
"type": "string",
|
||||
"description": "Name of the remote host to connect to (via passwordless SSH)."
|
||||
},
|
||||
"container": {
|
||||
"type": "string",
|
||||
"description": "Name or container id of the docker run container to connect to (via docker exec -it)."
|
||||
},
|
||||
"pidCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "Required for remote-attach. Remote command to execute to return the PID to attach to."
|
||||
},
|
||||
"initCompleteCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "For remote-attach. Remote command to execute after initialization of the debug adapter. Can be used to work around buggy attach behaviour on certain platforms (advanced usage). Can contain the special token %PID% which is replaced with the PID returned by 'pidCommand'"
|
||||
},
|
||||
"attachCommands": {
|
||||
"type": [ "array" ],
|
||||
"items": { "type": "array", "items": { "type": "string" } },
|
||||
"description": "For remote-attach. List of commands to execute remotely to set up the attach. Can contain the special token %PID% which is replaced with the PID returned by the remote 'pidCommand'."
|
||||
},
|
||||
"attachCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "A single command to execute for remote-attach. Like attachCommands but for a single command. If attachCommands is supplied, this is not used."
|
||||
},
|
||||
"runCommands": {
|
||||
"type": [ "array" ],
|
||||
"items": { "type": "array", "items": { "type": "string" } },
|
||||
"description": "For remote-launch. List of commands to execute remotely to set up the launch. An entry in the array can be the special token '%CMD%' which is replaced with the evaluated 'remote-cmdLine' value in the debug configuration. This is useful to parameterize launcging remotely under something like gdbserver."
|
||||
},
|
||||
"runCommand": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" },
|
||||
"description": "A single command to execute for remote-launch. Like runCommands but for a single command."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"adapter": {
|
||||
"oneOf": [
|
||||
},
|
||||
{ "$ref": "#/definitions/adapter-launchattach" },
|
||||
{
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/adapter-common" },
|
||||
{
|
||||
"required": [ "port" ],
|
||||
"properties": {
|
||||
"port": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [ "ask" ]
|
||||
},
|
||||
{
|
||||
"type": "integer"
|
||||
}
|
||||
],
|
||||
"description": "If supplied, indicates that a socket connection should be made to this port on 'localhost'. If the value is 'ask', then the user is asked to enter the port number to connect to."
|
||||
}
|
||||
}
|
||||
}
|
||||
"anyOf": [
|
||||
{ "required": [ "command" ] },
|
||||
{ "required": [ "port" ] },
|
||||
{ "required": [ "command", "port" ] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"allOf": [
|
||||
{ "$ref": "#/definitions/adapter-common" },
|
||||
{
|
||||
"required": [ "command" ],
|
||||
"properties": {
|
||||
"command": {
|
||||
"type": [ "string", "array" ],
|
||||
"description": "Command line to execute the debug adapter.",
|
||||
"items": { "type": "string" }
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
"description": "Name/value pairs to set in the environment when starting the adapter."
|
||||
},
|
||||
"cwd": {
|
||||
"type": "string",
|
||||
"description": "Directory from which to start the adapter. Defaults to the working directory of the window on launch"
|
||||
}
|
||||
}
|
||||
"properties": {
|
||||
"host": {
|
||||
"type": "string",
|
||||
"default": "127.0.0.1",
|
||||
"description": "Connect to this host in multi-session mode"
|
||||
},
|
||||
"port": {
|
||||
"oneOf": [
|
||||
{ "type": "string" },
|
||||
{ "type": "integer" }
|
||||
],
|
||||
"description": "If supplied, indicates that a socket connection should be made to this port on 'host'. If the value is 'ask', then the user is asked to enter the port number to connect to."
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -114,32 +114,35 @@ parser.add_argument( '--sudo',
|
|||
|
||||
done_languages = set()
|
||||
for name, gadget in gadgets.GADGETS.items():
|
||||
lang = gadget[ 'language' ]
|
||||
if lang in done_languages:
|
||||
continue
|
||||
langs = gadget[ 'language' ]
|
||||
if not isinstance( langs, list ):
|
||||
langs = [ langs ]
|
||||
for lang in langs:
|
||||
if lang in done_languages:
|
||||
continue
|
||||
|
||||
done_languages.add( lang )
|
||||
if not gadget.get( 'enabled', True ):
|
||||
parser.add_argument(
|
||||
'--force-enable-' + lang,
|
||||
action = 'store_true',
|
||||
help = 'Install the unsupported {} debug adapter for {} support'.format(
|
||||
name,
|
||||
lang ) )
|
||||
continue
|
||||
|
||||
done_languages.add( lang )
|
||||
if not gadget.get( 'enabled', True ):
|
||||
parser.add_argument(
|
||||
'--force-enable-' + lang,
|
||||
'--enable-' + lang,
|
||||
action = 'store_true',
|
||||
help = 'Install the unsupported {} debug adapter for {} support'.format(
|
||||
help = 'Install the {} debug adapter for {} support'.format(
|
||||
name,
|
||||
lang ) )
|
||||
continue
|
||||
|
||||
parser.add_argument(
|
||||
'--enable-' + lang,
|
||||
action = 'store_true',
|
||||
help = 'Install the {} debug adapter for {} support'.format(
|
||||
name,
|
||||
lang ) )
|
||||
|
||||
parser.add_argument(
|
||||
'--disable-' + lang,
|
||||
action = 'store_true',
|
||||
help = "Don't install the {} debug adapter for {} support "
|
||||
'(when supplying --all)'.format( name, lang ) )
|
||||
parser.add_argument(
|
||||
'--disable-' + lang,
|
||||
action = 'store_true',
|
||||
help = "Don't install the {} debug adapter for {} support "
|
||||
'(when supplying --all)'.format( name, lang ) )
|
||||
|
||||
parser.add_argument(
|
||||
"--no-check-certificate",
|
||||
|
|
@ -182,15 +185,25 @@ all_adapters = installer.ReadAdapters(
|
|||
manifest = installer.Manifest()
|
||||
|
||||
for name, gadget in gadgets.GADGETS.items():
|
||||
if not gadget.get( 'enabled', True ):
|
||||
if ( not args.force_all
|
||||
and not getattr( args, 'force_enable_' + gadget[ 'language' ] ) ):
|
||||
continue
|
||||
else:
|
||||
if not args.all and not getattr( args, 'enable_' + gadget[ 'language' ] ):
|
||||
continue
|
||||
if getattr( args, 'disable_' + gadget[ 'language' ] ):
|
||||
continue
|
||||
langs = gadget[ 'language' ]
|
||||
if not isinstance( langs, list ):
|
||||
langs = [ langs ]
|
||||
skip = 0
|
||||
for lang in langs:
|
||||
if not gadget.get( 'enabled', True ):
|
||||
if ( not args.force_all
|
||||
and not getattr( args, 'force_enable_' + lang ) ):
|
||||
skip = skip + 1
|
||||
continue
|
||||
else:
|
||||
if not args.all and not getattr( args, 'enable_' + lang ):
|
||||
skip = skip + 1
|
||||
continue
|
||||
if getattr( args, 'disable_' + lang ):
|
||||
skip = skip + 1
|
||||
continue
|
||||
if skip == len( langs ):
|
||||
continue
|
||||
|
||||
if not args.upgrade:
|
||||
manifest.Clear( name )
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@
|
|||
" See the License for the specific language governing permissions and
|
||||
" limitations under the License.
|
||||
|
||||
if !has( 'python3' )
|
||||
echohl WarningMsg
|
||||
echom 'Vimspector unavailable: Requires Vim compiled with +python3'
|
||||
echohl None
|
||||
finish
|
||||
endif
|
||||
|
||||
" Boilerplate {{{
|
||||
let s:save_cpo = &cpoptions
|
||||
set cpoptions&vim
|
||||
|
|
@ -28,11 +35,6 @@ if exists( 'g:loaded_vimpector' )
|
|||
endif
|
||||
"}}}
|
||||
|
||||
" TODO:
|
||||
" - Check Vim version (for jobs)
|
||||
" - Check python support
|
||||
" - Add commands/mappings/menus?
|
||||
|
||||
let g:loaded_vimpector = 1
|
||||
let g:vimspector_home = expand( '<sfile>:p:h:h' )
|
||||
|
||||
|
|
@ -40,6 +42,8 @@ let s:mappings = get( g:, 'vimspector_enable_mappings', '' )
|
|||
|
||||
nnoremap <silent> <Plug>VimspectorContinue
|
||||
\ :<c-u>call vimspector#Continue()<CR>
|
||||
nnoremap <silent> <Plug>VimspectorLaunch
|
||||
\ :<c-u>call vimspector#Launch( v:true )<CR>
|
||||
nnoremap <silent> <Plug>VimspectorStop
|
||||
\ :<c-u>call vimspector#Stop()<CR>
|
||||
nnoremap <silent> <Plug>VimspectorRestart
|
||||
|
|
@ -62,6 +66,21 @@ nnoremap <silent> <Plug>VimspectorStepInto
|
|||
nnoremap <silent> <Plug>VimspectorStepOut
|
||||
\ :<c-u>call vimspector#StepOut()<CR>
|
||||
|
||||
nnoremap <silent> <Plug>VimspectorRunToCursor
|
||||
\ :<c-u>call vimspector#RunToCursor()<CR>
|
||||
|
||||
" Eval for normal mode
|
||||
nnoremap <silent> <Plug>VimspectorBalloonEval
|
||||
\ :<c-u>call vimspector#ShowEvalBalloon( 0 )<CR>
|
||||
" And for visual modes
|
||||
xnoremap <silent> <Plug>VimspectorBalloonEval
|
||||
\ :<c-u>call vimspector#ShowEvalBalloon( 1 )<CR>
|
||||
|
||||
nnoremap <silent> <Plug>VimspectorUpFrame
|
||||
\ :<c-u>call vimspector#UpFrame()<CR>
|
||||
nnoremap <silent> <Plug>VimspectorDownFrame
|
||||
\ :<c-u>call vimspector#DownFrame()<CR>
|
||||
|
||||
if s:mappings ==# 'VISUAL_STUDIO'
|
||||
nmap <F5> <Plug>VimspectorContinue
|
||||
nmap <S-F5> <Plug>VimspectorStop
|
||||
|
|
@ -74,12 +93,14 @@ if s:mappings ==# 'VISUAL_STUDIO'
|
|||
nmap <S-F11> <Plug>VimspectorStepOut
|
||||
elseif s:mappings ==# 'HUMAN'
|
||||
nmap <F5> <Plug>VimspectorContinue
|
||||
nmap <leader><F5> <Plug>VimspectorLaunch
|
||||
nmap <F3> <Plug>VimspectorStop
|
||||
nmap <F4> <Plug>VimspectorRestart
|
||||
nmap <F6> <Plug>VimspectorPause
|
||||
nmap <F9> <Plug>VimspectorToggleBreakpoint
|
||||
nmap <leader><F9> <Plug>VimspectorToggleConditionalBreakpoint
|
||||
nmap <F8> <Plug>VimspectorAddFunctionBreakpoint
|
||||
nmap <leader><F8> <Plug>VimspectorRunToCursor
|
||||
nmap <F10> <Plug>VimspectorStepOver
|
||||
nmap <F11> <Plug>VimspectorStepInto
|
||||
nmap <F12> <Plug>VimspectorStepOut
|
||||
|
|
@ -94,12 +115,15 @@ command! -bar -nargs=? -complete=custom,vimspector#CompleteOutput
|
|||
command! -bar
|
||||
\ VimspectorToggleLog
|
||||
\ call vimspector#ToggleLog()
|
||||
command! -bar -nargs=1 -complete=custom,vimspector#CompleteExpr
|
||||
command! -bar
|
||||
\ VimspectorDebugInfo
|
||||
\ call vimspector#PrintDebugInfo()
|
||||
command! -nargs=1 -complete=custom,vimspector#CompleteExpr
|
||||
\ VimspectorEval
|
||||
\ call vimspector#Evaluate( <f-args> )
|
||||
command! -bar
|
||||
\ VimspectorReset
|
||||
\ call vimspector#Reset()
|
||||
\ call vimspector#Reset( { 'interactive': v:true } )
|
||||
|
||||
" Installer commands
|
||||
command! -bar -bang -nargs=* -complete=custom,vimspector#CompleteInstall
|
||||
|
|
@ -116,9 +140,17 @@ command! -bar -nargs=0
|
|||
|
||||
" Dummy autocommands so that we can call this whenever
|
||||
augroup VimspectorUserAutoCmds
|
||||
au!
|
||||
au User VimspectorUICreated silent
|
||||
au User VimspectorTerminalOpened silent
|
||||
autocmd!
|
||||
autocmd User VimspectorUICreated silent
|
||||
autocmd User VimspectorTerminalOpened silent
|
||||
autocmd user VimspectorJumpedToFrame silent
|
||||
autocmd user VimspectorDebugEnded silent
|
||||
augroup END
|
||||
|
||||
" FIXME: Only register this _while_ debugging is active
|
||||
augroup Vimspector
|
||||
autocmd!
|
||||
autocmd BufNew * call vimspector#OnBufferCreated( expand( '<afile>' ) )
|
||||
augroup END
|
||||
|
||||
" boilerplate {{{
|
||||
|
|
|
|||
|
|
@ -141,50 +141,123 @@ class ProjectBreakpoints( object ):
|
|||
|
||||
self.UpdateUI()
|
||||
|
||||
def _FindLineBreakpoint( self, file_name, line ):
|
||||
file_name = os.path.abspath( file_name )
|
||||
for index, bp in enumerate( self._line_breakpoints[ file_name ] ):
|
||||
self._SignToLine( file_name, bp )
|
||||
if bp[ 'line' ] == line:
|
||||
return bp, index
|
||||
|
||||
return None, None
|
||||
|
||||
|
||||
def _PutLineBreakpoint( self, file_name, line, options ):
|
||||
self._line_breakpoints[ os.path.abspath( file_name ) ].append( {
|
||||
'state': 'ENABLED',
|
||||
'line': line,
|
||||
'options': options,
|
||||
# 'sign_id': <filled in when placed>,
|
||||
#
|
||||
# Used by other breakpoint types (specified in options):
|
||||
# 'condition': ...,
|
||||
# 'hitCondition': ...,
|
||||
# 'logMessage': ...
|
||||
} )
|
||||
|
||||
|
||||
def _DeleteLineBreakpoint( self, bp, file_name, index ):
|
||||
if 'sign_id' in bp:
|
||||
signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' )
|
||||
del self._line_breakpoints[ os.path.abspath( file_name ) ][ index ]
|
||||
|
||||
|
||||
def ToggleBreakpoint( self, options ):
|
||||
line, column = vim.current.window.cursor
|
||||
line, _ = vim.current.window.cursor
|
||||
file_name = vim.current.buffer.name
|
||||
|
||||
if not file_name:
|
||||
return
|
||||
|
||||
found_bp = False
|
||||
action = 'New'
|
||||
for index, bp in enumerate( self._line_breakpoints[ file_name ] ):
|
||||
self._SignToLine( file_name, bp )
|
||||
if bp[ 'line' ] == line:
|
||||
found_bp = True
|
||||
if bp[ 'state' ] == 'ENABLED' and not self._connection:
|
||||
bp[ 'state' ] = 'DISABLED'
|
||||
action = 'Disable'
|
||||
else:
|
||||
if 'sign_id' in bp:
|
||||
signs.UnplaceSign( bp[ 'sign_id' ], 'VimspectorBP' )
|
||||
del self._line_breakpoints[ file_name ][ index ]
|
||||
action = 'Delete'
|
||||
break
|
||||
|
||||
self._logger.debug( "Toggle found bp at {}:{} ? {} ({})".format(
|
||||
file_name,
|
||||
line,
|
||||
found_bp,
|
||||
action ) )
|
||||
|
||||
if not found_bp:
|
||||
self._line_breakpoints[ file_name ].append( {
|
||||
'state': 'ENABLED',
|
||||
'line': line,
|
||||
'options': options,
|
||||
# 'sign_id': <filled in when placed>,
|
||||
#
|
||||
# Used by other breakpoint types (specified in options):
|
||||
# 'condition': ...,
|
||||
# 'hitCondition': ...,
|
||||
# 'logMessage': ...
|
||||
} )
|
||||
bp, index = self._FindLineBreakpoint( file_name, line )
|
||||
if bp is None:
|
||||
# ADD
|
||||
self._PutLineBreakpoint( file_name, line, options )
|
||||
elif bp[ 'state' ] == 'ENABLED' and not self._connection:
|
||||
# DISABLE
|
||||
bp[ 'state' ] = 'DISABLED'
|
||||
else:
|
||||
# DELETE
|
||||
self._DeleteLineBreakpoint( bp, file_name, index )
|
||||
|
||||
self.UpdateUI()
|
||||
|
||||
|
||||
def SetLineBreakpoint( self, file_name, line_num, options, then = None ):
|
||||
bp, _ = self._FindLineBreakpoint( file_name, line_num )
|
||||
if bp is not None:
|
||||
bp[ 'options' ] = options
|
||||
return
|
||||
self._PutLineBreakpoint( file_name, line_num, options )
|
||||
self.UpdateUI( then )
|
||||
|
||||
|
||||
def ClearLineBreakpoint( self, file_name, line_num ):
|
||||
bp, index = self._FindLineBreakpoint( file_name, line_num )
|
||||
if bp is None:
|
||||
return
|
||||
self._DeleteLineBreakpoint( bp, file_name, index )
|
||||
self.UpdateUI()
|
||||
|
||||
|
||||
def ClearTemporaryBreakpoint( self, file_name, line_num ):
|
||||
bp, index = self._FindLineBreakpoint( file_name, line_num )
|
||||
if bp is None:
|
||||
return
|
||||
if bp[ 'options' ].get( 'temporary' ):
|
||||
self._DeleteLineBreakpoint( bp, file_name, index )
|
||||
self.UpdateUI()
|
||||
|
||||
|
||||
def ClearTemporaryBreakpoints( self ):
|
||||
to_delete = []
|
||||
for file_name, breakpoints in self._line_breakpoints.items():
|
||||
for index, bp in enumerate( breakpoints ):
|
||||
if bp[ 'options' ].get( 'temporary' ):
|
||||
to_delete.append( ( bp, file_name, index ) )
|
||||
|
||||
for entry in to_delete:
|
||||
self._DeleteLineBreakpoint( *entry )
|
||||
|
||||
|
||||
def _UpdateTemporaryBreakpoints( self, breakpoints, temp_idxs ):
|
||||
# adjust any temporary breakpoints to match the server result
|
||||
# TODO: Maybe now is the time to ditch the split breakpoints nonesense
|
||||
for temp_idx, user_bp in temp_idxs:
|
||||
if temp_idx >= len( breakpoints ):
|
||||
# Just can't trust servers ?
|
||||
self._logger.debug( "Server Error - invalid breakpoints list did not "
|
||||
"contain entry for temporary breakpoint at index "
|
||||
f"{ temp_idx } i.e. { user_bp }" )
|
||||
continue
|
||||
|
||||
bp = breakpoints[ temp_idx ]
|
||||
|
||||
if 'line' not in bp or not bp[ 'verified' ]:
|
||||
utils.UserMessage(
|
||||
"Unable to set temporary breakpoint at line "
|
||||
f"{ user_bp[ 'line' ] } execution will continue...",
|
||||
persist = True,
|
||||
error = True )
|
||||
|
||||
self._logger.debug( f"Updating temporary breakpoint { user_bp } line "
|
||||
f"{ user_bp[ 'line' ] } to { bp[ 'line' ] }" )
|
||||
|
||||
# if it was moved, update the user-breakpoint so that we unset it
|
||||
# again properly
|
||||
user_bp[ 'line' ] = bp[ 'line' ]
|
||||
|
||||
|
||||
|
||||
def AddFunctionBreakpoint( self, function, options ):
|
||||
self._func_breakpoints.append( {
|
||||
'state': 'ENABLED',
|
||||
|
|
@ -200,11 +273,13 @@ class ProjectBreakpoints( object ):
|
|||
self.UpdateUI()
|
||||
|
||||
|
||||
def UpdateUI( self ):
|
||||
def UpdateUI( self, then = None ):
|
||||
if self._connection:
|
||||
self.SendBreakpoints()
|
||||
self.SendBreakpoints( then )
|
||||
else:
|
||||
self._ShowBreakpoints()
|
||||
if then:
|
||||
then()
|
||||
|
||||
|
||||
def SetBreakpointsHandler( self, handler ):
|
||||
|
|
@ -224,15 +299,25 @@ class ProjectBreakpoints( object ):
|
|||
|
||||
awaiting = 0
|
||||
|
||||
def response_received():
|
||||
def response_received( *failure_args ):
|
||||
nonlocal awaiting
|
||||
awaiting = awaiting - 1
|
||||
|
||||
if failure_args and self._connection:
|
||||
reason, msg = failure_args
|
||||
utils.UserMessage( 'Unable to set breakpoint: {0}'.format( reason ),
|
||||
persist = True,
|
||||
error = True )
|
||||
|
||||
if awaiting == 0 and doneHandler:
|
||||
doneHandler()
|
||||
|
||||
def response_handler( source, msg ):
|
||||
def response_handler( source, msg, temp_idxs = [] ):
|
||||
if msg:
|
||||
self._breakpoints_handler.AddBreakpoints( source, msg )
|
||||
|
||||
breakpoints = ( msg.get( 'body' ) or {} ).get( 'breakpoints' ) or []
|
||||
self._UpdateTemporaryBreakpoints( breakpoints, temp_idxs )
|
||||
response_received()
|
||||
|
||||
|
||||
|
|
@ -243,9 +328,9 @@ class ProjectBreakpoints( object ):
|
|||
|
||||
|
||||
# TODO: add the _configured_breakpoints to line_breakpoints
|
||||
# TODO: the line numbers might have changed since pressing the F9 key!
|
||||
|
||||
for file_name, line_breakpoints in self._line_breakpoints.items():
|
||||
temp_idxs = []
|
||||
breakpoints = []
|
||||
for bp in line_breakpoints:
|
||||
self._SignToLine( file_name, bp )
|
||||
|
|
@ -259,8 +344,15 @@ class ProjectBreakpoints( object ):
|
|||
dap_bp = {}
|
||||
dap_bp.update( bp[ 'options' ] )
|
||||
dap_bp.update( { 'line': bp[ 'line' ] } )
|
||||
|
||||
dap_bp.pop( 'temporary', None )
|
||||
|
||||
if bp[ 'options' ].get( 'temporary' ):
|
||||
temp_idxs.append( [ len( breakpoints ), bp ] )
|
||||
|
||||
breakpoints.append( dap_bp )
|
||||
|
||||
|
||||
source = {
|
||||
'name': os.path.basename( file_name ),
|
||||
'path': file_name,
|
||||
|
|
@ -268,7 +360,13 @@ class ProjectBreakpoints( object ):
|
|||
|
||||
awaiting = awaiting + 1
|
||||
self._connection.DoRequest(
|
||||
lambda msg: response_handler( source, msg ),
|
||||
# The source=source here is critical to ensure that we capture each
|
||||
# source in the iteration, rather than ending up passing the same source
|
||||
# to each callback.
|
||||
lambda msg, source=source, temp_idxs=temp_idxs: response_handler(
|
||||
source,
|
||||
msg,
|
||||
temp_idxs = temp_idxs ),
|
||||
{
|
||||
'command': 'setBreakpoints',
|
||||
'arguments': {
|
||||
|
|
@ -277,7 +375,7 @@ class ProjectBreakpoints( object ):
|
|||
},
|
||||
'sourceModified': False, # TODO: We can actually check this
|
||||
},
|
||||
failure_handler = lambda *_: response_received()
|
||||
failure_handler = response_received
|
||||
)
|
||||
|
||||
# TODO: Add the _configured_breakpoints to function breakpoints
|
||||
|
|
@ -301,7 +399,7 @@ class ProjectBreakpoints( object ):
|
|||
'breakpoints': breakpoints,
|
||||
}
|
||||
},
|
||||
failure_handler = lambda *_: response_received()
|
||||
failure_handler = response_received
|
||||
)
|
||||
|
||||
if self._exception_breakpoints:
|
||||
|
|
@ -312,7 +410,7 @@ class ProjectBreakpoints( object ):
|
|||
'command': 'setExceptionBreakpoints',
|
||||
'arguments': self._exception_breakpoints
|
||||
},
|
||||
failure_handler = lambda *_: response_received()
|
||||
failure_handler = response_received
|
||||
)
|
||||
|
||||
if awaiting == 0 and doneHandler:
|
||||
|
|
@ -369,6 +467,12 @@ class ProjectBreakpoints( object ):
|
|||
# pay any attention to them anyway.
|
||||
self._exception_breakpoints[ 'exceptionOptions' ] = []
|
||||
|
||||
|
||||
def Refresh( self, file_name ):
|
||||
# TODO: Just this file ?
|
||||
self._ShowBreakpoints()
|
||||
|
||||
|
||||
def _ShowBreakpoints( self ):
|
||||
for file_name, line_breakpoints in self._line_breakpoints.items():
|
||||
for bp in line_breakpoints:
|
||||
|
|
@ -383,17 +487,21 @@ class ProjectBreakpoints( object ):
|
|||
else 'vimspectorBPCond' if 'condition' in bp[ 'options' ]
|
||||
else 'vimspectorBP' )
|
||||
|
||||
signs.PlaceSign( bp[ 'sign_id' ],
|
||||
'VimspectorBP',
|
||||
sign,
|
||||
file_name,
|
||||
bp[ 'line' ] )
|
||||
if utils.BufferExists( file_name ):
|
||||
signs.PlaceSign( bp[ 'sign_id' ],
|
||||
'VimspectorBP',
|
||||
sign,
|
||||
file_name,
|
||||
bp[ 'line' ] )
|
||||
|
||||
|
||||
def _SignToLine( self, file_name, bp ):
|
||||
if 'sign_id' not in bp:
|
||||
return bp[ 'line' ]
|
||||
|
||||
if not utils.BufferExists( file_name ):
|
||||
return bp[ 'line' ]
|
||||
|
||||
signs = vim.eval( "sign_getplaced( '{}', {} )".format(
|
||||
utils.Escape( file_name ),
|
||||
json.dumps( { 'id': bp[ 'sign_id' ], 'group': 'VimspectorBP', } ) ) )
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ class CodeView( object ):
|
|||
self._logger = logging.getLogger( __name__ )
|
||||
utils.SetUpLogging( self._logger )
|
||||
|
||||
# FIXME: This ID is by group, so should be module scope
|
||||
self._next_sign_id = 1
|
||||
self._breakpoints = defaultdict( list )
|
||||
self._signs = {
|
||||
|
|
@ -41,14 +42,25 @@ class CodeView( object ):
|
|||
self._current_frame = None
|
||||
|
||||
with utils.LetCurrentWindow( self._window ):
|
||||
vim.command( 'nnoremenu WinBar.■\\ Stop :call vimspector#Stop()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.▶\\ Cont :call vimspector#Continue()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.▷\\ Pause :call vimspector#Pause()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.↷\\ Next :call vimspector#StepOver()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.→\\ Step :call vimspector#StepInto()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.←\\ Out :call vimspector#StepOut()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.⟲: :call vimspector#Restart()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.✕ :call vimspector#Reset()<CR>' )
|
||||
if utils.UseWinBar():
|
||||
# Buggy neovim doesn't render correctly when the WinBar is defined:
|
||||
# https://github.com/neovim/neovim/issues/12689
|
||||
vim.command( 'nnoremenu WinBar.■\\ Stop '
|
||||
':call vimspector#Stop()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.▶\\ Cont '
|
||||
':call vimspector#Continue()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.▷\\ Pause '
|
||||
':call vimspector#Pause()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.↷\\ Next '
|
||||
':call vimspector#StepOver()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.→\\ Step '
|
||||
':call vimspector#StepInto()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.←\\ Out '
|
||||
':call vimspector#StepOut()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.⟲: '
|
||||
':call vimspector#Restart()<CR>' )
|
||||
vim.command( 'nnoremenu WinBar.✕ '
|
||||
':call vimspector#Reset()<CR>' )
|
||||
|
||||
if not signs.SignDefined( 'vimspectorPC' ):
|
||||
signs.DefineSign( 'vimspectorPC',
|
||||
|
|
@ -93,16 +105,12 @@ class CodeView( object ):
|
|||
sign = 'vimspectorPCBP'
|
||||
break
|
||||
|
||||
try:
|
||||
if utils.BufferExists( frame[ 'source' ][ 'path' ] ):
|
||||
signs.PlaceSign( self._signs[ 'vimspectorPC' ],
|
||||
'VimspectorCode',
|
||||
sign,
|
||||
frame[ 'source' ][ 'path' ],
|
||||
frame[ 'line' ] )
|
||||
except vim.error as e:
|
||||
# Ignore 'invalid buffer name'
|
||||
if 'E158' not in str( e ):
|
||||
raise
|
||||
|
||||
|
||||
def SetCurrentFrame( self, frame ):
|
||||
|
|
@ -119,7 +127,6 @@ class CodeView( object ):
|
|||
return False
|
||||
|
||||
self._current_frame = frame
|
||||
self._DisplayPC()
|
||||
|
||||
if not self._window.valid:
|
||||
return False
|
||||
|
|
@ -127,6 +134,7 @@ class CodeView( object ):
|
|||
utils.JumpToWindow( self._window )
|
||||
try:
|
||||
utils.OpenFileInCurrentWindow( frame[ 'source' ][ 'path' ] )
|
||||
vim.command( 'doautocmd <nomodeline> User VimspectorJumpedToFrame' )
|
||||
except vim.error:
|
||||
self._logger.exception( 'Unexpected vim error opening file {}'.format(
|
||||
frame[ 'source' ][ 'path' ] ) )
|
||||
|
|
@ -148,6 +156,8 @@ class CodeView( object ):
|
|||
self.current_syntax = utils.ToUnicode(
|
||||
vim.current.buffer.options[ 'syntax' ] )
|
||||
|
||||
self.ShowBreakpoints()
|
||||
|
||||
return True
|
||||
|
||||
def Clear( self ):
|
||||
|
|
@ -165,25 +175,29 @@ class CodeView( object ):
|
|||
|
||||
def AddBreakpoints( self, source, breakpoints ):
|
||||
for breakpoint in breakpoints:
|
||||
if 'source' not in breakpoint:
|
||||
if source:
|
||||
breakpoint[ 'source' ] = source
|
||||
else:
|
||||
self._logger.warn( 'missing source in breakpoint {0}'.format(
|
||||
json.dumps( breakpoint ) ) )
|
||||
continue
|
||||
source = breakpoint.get( 'source' ) or source
|
||||
if not source or 'path' not in source:
|
||||
self._logger.warn( 'missing source/path in breakpoint {0}'.format(
|
||||
json.dumps( breakpoint ) ) )
|
||||
continue
|
||||
|
||||
self._breakpoints[ breakpoint[ 'source' ][ 'path' ] ].append(
|
||||
breakpoint )
|
||||
breakpoint[ 'source' ] = source
|
||||
self._breakpoints[ source[ 'path' ] ].append( breakpoint )
|
||||
|
||||
self._logger.debug( 'Breakpoints at this point: {0}'.format(
|
||||
json.dumps( self._breakpoints, indent = 2 ) ) )
|
||||
|
||||
self.ShowBreakpoints()
|
||||
|
||||
|
||||
def AddBreakpoint( self, breakpoint ):
|
||||
self.AddBreakpoints( None, [ breakpoint ] )
|
||||
|
||||
|
||||
def UpdateBreakpoint( self, bp ):
|
||||
if 'id' not in bp:
|
||||
self.AddBreakpoints( None, [ bp ] )
|
||||
self.AddBreakpoint( bp )
|
||||
return
|
||||
|
||||
for _, breakpoint_list in self._breakpoints.items():
|
||||
for index, breakpoint in enumerate( breakpoint_list ):
|
||||
|
|
@ -193,7 +207,27 @@ class CodeView( object ):
|
|||
return
|
||||
|
||||
# Not found. Assume new
|
||||
self.AddBreakpoints( None, [ bp ] )
|
||||
self.AddBreakpoint( bp )
|
||||
|
||||
|
||||
def RemoveBreakpoint( self, bp ):
|
||||
for _, breakpoint_list in self._breakpoints.items():
|
||||
found_index = None
|
||||
for index, breakpoint in enumerate( breakpoint_list ):
|
||||
if 'id' in breakpoint and breakpoint[ 'id' ] == bp[ 'id' ]:
|
||||
found_index = index
|
||||
break
|
||||
|
||||
if found_index is not None:
|
||||
del breakpoint_list[ found_index ]
|
||||
self.ShowBreakpoints()
|
||||
return
|
||||
|
||||
|
||||
def Refresh( self, file_name ):
|
||||
# TODO: jsut the file ?
|
||||
self.ShowBreakpoints()
|
||||
|
||||
|
||||
def _UndisplaySigns( self ):
|
||||
for sign_id in self._signs[ 'breakpoints' ]:
|
||||
|
|
@ -216,12 +250,13 @@ class CodeView( object ):
|
|||
sign_id = self._next_sign_id
|
||||
self._next_sign_id += 1
|
||||
self._signs[ 'breakpoints' ].append( sign_id )
|
||||
signs.PlaceSign( sign_id,
|
||||
'VimspectorCode',
|
||||
'vimspectorBP' if breakpoint[ 'verified' ]
|
||||
else 'vimspectorBPDisabled',
|
||||
file_name,
|
||||
breakpoint[ 'line' ] )
|
||||
if utils.BufferExists( file_name ):
|
||||
signs.PlaceSign( sign_id,
|
||||
'VimspectorCode',
|
||||
'vimspectorBP' if breakpoint[ 'verified' ]
|
||||
else 'vimspectorBPDisabled',
|
||||
file_name,
|
||||
breakpoint[ 'line' ] )
|
||||
|
||||
# We need to also check if there's a breakpoint on this PC line and chnge
|
||||
# the PC
|
||||
|
|
|
|||
51
python3/vimspector/custom/java.py
Normal file
51
python3/vimspector/custom/java.py
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
# vimspector - A multi-language debugging system for Vim
|
||||
# Copyright 2021 Ben Jackson
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from vimspector.debug_session import DebugSession
|
||||
from vimspector import utils, settings
|
||||
|
||||
|
||||
class JavaDebugAdapter( object ):
|
||||
def __init__( self, debug_session: DebugSession ):
|
||||
self.debug_session = debug_session
|
||||
|
||||
def OnEvent_hotcodereplace( self, message ):
|
||||
# Hack for java debug server hot-code-replace
|
||||
body = message.get( 'body' ) or {}
|
||||
|
||||
if body.get( 'type' ) != 'hotcodereplace':
|
||||
return
|
||||
|
||||
if body.get( 'changeType' ) == 'BUILD_COMPLETE':
|
||||
def handler( result ):
|
||||
if result == 1:
|
||||
self.debug_session._connection.DoRequest( None, {
|
||||
'command': 'redefineClasses',
|
||||
'arguments': {},
|
||||
} )
|
||||
|
||||
mode = settings.Get( 'java_hotcodereplace_mode' )
|
||||
if mode == 'ask':
|
||||
utils.Confirm( self.debug_session._api_prefix,
|
||||
'Code has changed, hot reload?',
|
||||
handler,
|
||||
default_value = 1 )
|
||||
elif mode == 'always':
|
||||
self.debug_session._connection.DoRequest( None, {
|
||||
'command': 'redefineClasses',
|
||||
'arguments': {},
|
||||
} )
|
||||
elif body.get( 'message' ):
|
||||
utils.UserMessage( 'Hot code replace: ' + body[ 'message' ] )
|
||||
|
|
@ -29,14 +29,14 @@ class PendingRequest( object ):
|
|||
|
||||
|
||||
class DebugAdapterConnection( object ):
|
||||
def __init__( self, handler, send_func ):
|
||||
def __init__( self, handlers, send_func ):
|
||||
self._logger = logging.getLogger( __name__ )
|
||||
utils.SetUpLogging( self._logger )
|
||||
|
||||
self._Write = send_func
|
||||
self._SetState( 'READ_HEADER' )
|
||||
self._buffer = bytes()
|
||||
self._handler = handler
|
||||
self._handlers = handlers
|
||||
self._next_message_id = 0
|
||||
self._outstanding_requests = {}
|
||||
|
||||
|
|
@ -124,7 +124,7 @@ class DebugAdapterConnection( object ):
|
|||
|
||||
def Reset( self ):
|
||||
self._Write = None
|
||||
self._handler = None
|
||||
self._handlers = None
|
||||
|
||||
while self._outstanding_requests:
|
||||
_, request = self._outstanding_requests.popitem()
|
||||
|
|
@ -169,6 +169,10 @@ class DebugAdapterConnection( object ):
|
|||
self._headers = {}
|
||||
|
||||
def _SendMessage( self, msg ):
|
||||
if not self._Write:
|
||||
# Connection was destroyed
|
||||
return False
|
||||
|
||||
msg = json.dumps( msg )
|
||||
self._logger.debug( 'Sending Message: {0}'.format( msg ) )
|
||||
|
||||
|
|
@ -222,7 +226,12 @@ class DebugAdapterConnection( object ):
|
|||
|
||||
# self._logger.debug( 'Message received (raw): %s', payload )
|
||||
|
||||
message = json.loads( payload )
|
||||
try:
|
||||
message = json.loads( payload, strict = False )
|
||||
except Exception:
|
||||
self._logger.exception( "Invalid message received: %s", payload )
|
||||
self._SetState( 'READ_HEADER' )
|
||||
raise
|
||||
|
||||
self._logger.debug( 'Message received: {0}'.format( message ) )
|
||||
|
||||
|
|
@ -233,7 +242,7 @@ class DebugAdapterConnection( object ):
|
|||
|
||||
|
||||
def _OnMessageReceived( self, message ):
|
||||
if not self._handler:
|
||||
if not self._handlers:
|
||||
return
|
||||
|
||||
if message[ 'type' ] == 'response':
|
||||
|
|
@ -266,25 +275,21 @@ class DebugAdapterConnection( object ):
|
|||
self._logger.error( 'Request failed: {0}'.format( reason ) )
|
||||
if request.failure_handler:
|
||||
request.failure_handler( reason, message )
|
||||
elif 'OnFailure' in dir( self._handler ):
|
||||
self._handler.OnFailure( reason, request.msg, message )
|
||||
else:
|
||||
utils.UserMessage( 'Request failed: {0}'.format( reason ) )
|
||||
for h in self._handlers:
|
||||
if 'OnFailure' in dir( h ):
|
||||
h.OnFailure( reason, request.msg, message )
|
||||
|
||||
elif message[ 'type' ] == 'event':
|
||||
method = 'OnEvent_' + message[ 'event' ]
|
||||
if method in dir( self._handler ):
|
||||
getattr( self._handler, method )( message )
|
||||
else:
|
||||
utils.UserMessage( 'Unhandled event: {0}'.format( message[ 'event' ] ),
|
||||
persist = True )
|
||||
for h in self._handlers:
|
||||
if method in dir( h ):
|
||||
getattr( h, method )( message )
|
||||
elif message[ 'type' ] == 'request':
|
||||
method = 'OnRequest_' + message[ 'command' ]
|
||||
if method in dir( self._handler ):
|
||||
getattr( self._handler, method )( message )
|
||||
else:
|
||||
utils.UserMessage(
|
||||
'Unhandled request: {0}'.format( message[ 'command' ] ),
|
||||
persist = True )
|
||||
for h in self._handlers:
|
||||
if method in dir( h ):
|
||||
getattr( h, method )( message )
|
||||
|
||||
|
||||
def _KillTimer( request ):
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import shlex
|
|||
import subprocess
|
||||
import functools
|
||||
import vim
|
||||
import importlib
|
||||
|
||||
from vimspector import ( breakpoints,
|
||||
code,
|
||||
|
|
@ -68,6 +69,7 @@ class DebugSession( object ):
|
|||
|
||||
self._configuration = None
|
||||
self._adapter = None
|
||||
self._launch_config = None
|
||||
|
||||
self._ResetServerState()
|
||||
|
||||
|
|
@ -77,8 +79,28 @@ class DebugSession( object ):
|
|||
self._launch_complete = False
|
||||
self._on_init_complete_handlers = []
|
||||
self._server_capabilities = {}
|
||||
self.ClearTemporaryBreakpoints()
|
||||
|
||||
def Start( self, launch_variables = None ):
|
||||
def GetConfigurations( self, adapters ):
|
||||
current_file = utils.GetBufferFilepath( vim.current.buffer )
|
||||
filetypes = utils.GetBufferFiletypes( vim.current.buffer )
|
||||
configurations = {}
|
||||
|
||||
for launch_config_file in PathsToAllConfigFiles( VIMSPECTOR_HOME,
|
||||
current_file,
|
||||
filetypes ):
|
||||
self._logger.debug( f'Reading configurations from: {launch_config_file}' )
|
||||
if not launch_config_file or not os.path.exists( launch_config_file ):
|
||||
continue
|
||||
|
||||
with open( launch_config_file, 'r' ) as f:
|
||||
database = json.loads( minify( f.read() ) )
|
||||
configurations.update( database.get( 'configurations' ) or {} )
|
||||
adapters.update( database.get( 'adapters' ) or {} )
|
||||
|
||||
return launch_config_file, configurations
|
||||
|
||||
def Start( self, force_choose=False, launch_variables = None ):
|
||||
# We mutate launch_variables, so don't mutate the default argument.
|
||||
# https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments
|
||||
if launch_variables is None:
|
||||
|
|
@ -88,11 +110,17 @@ class DebugSession( object ):
|
|||
launch_variables )
|
||||
self._configuration = None
|
||||
self._adapter = None
|
||||
self._launch_config = None
|
||||
|
||||
current_file = utils.GetBufferFilepath( vim.current.buffer )
|
||||
filetypes = utils.GetBufferFiletypes( vim.current.buffer )
|
||||
configurations = {}
|
||||
adapters = {}
|
||||
launch_config_file, configurations = self.GetConfigurations( adapters )
|
||||
|
||||
if not configurations:
|
||||
utils.UserMessage( 'Unable to find any debug configurations. '
|
||||
'You need to tell vimspector how to launch your '
|
||||
'application.' )
|
||||
return
|
||||
|
||||
glob.glob( install.GetGadgetDir( VIMSPECTOR_HOME ) )
|
||||
for gadget_config_file in PathsToAllGadgetConfigs( VIMSPECTOR_HOME,
|
||||
|
|
@ -105,26 +133,13 @@ class DebugSession( object ):
|
|||
a = json.loads( minify( f.read() ) ).get( 'adapters' ) or {}
|
||||
adapters.update( a )
|
||||
|
||||
for launch_config_file in PathsToAllConfigFiles( VIMSPECTOR_HOME,
|
||||
current_file,
|
||||
filetypes ):
|
||||
self._logger.debug( f'Reading configurations from: {launch_config_file}' )
|
||||
if not launch_config_file or not os.path.exists( launch_config_file ):
|
||||
continue
|
||||
|
||||
with open( launch_config_file, 'r' ) as f:
|
||||
database = json.loads( minify( f.read() ) )
|
||||
adapters.update( database.get( 'adapters' ) or {} )
|
||||
configurations.update( database.get( 'configurations' or {} ) )
|
||||
|
||||
if not configurations:
|
||||
utils.UserMessage( 'Unable to find any debug configurations. '
|
||||
'You need to tell vimspector how to launch your '
|
||||
'application.' )
|
||||
return
|
||||
|
||||
if 'configuration' in launch_variables:
|
||||
configuration_name = launch_variables.pop( 'configuration' )
|
||||
elif force_choose:
|
||||
# Always display the menu
|
||||
configuration_name = utils.SelectFromList(
|
||||
'Which launch configuration?',
|
||||
sorted( configurations.keys() ) )
|
||||
elif ( len( configurations ) == 1 and
|
||||
next( iter( configurations.values() ) ).get( "autoselect", True ) ):
|
||||
configuration_name = next( iter( configurations.keys() ) )
|
||||
|
|
@ -273,6 +288,7 @@ class DebugSession( object ):
|
|||
def start():
|
||||
self._configuration = configuration
|
||||
self._adapter = adapter
|
||||
self._launch_config = None
|
||||
|
||||
self._logger.info( 'Configuration: %s',
|
||||
json.dumps( self._configuration ) )
|
||||
|
|
@ -284,6 +300,7 @@ class DebugSession( object ):
|
|||
else:
|
||||
vim.current.tabpage = self._uiTab
|
||||
|
||||
self._Prepare()
|
||||
self._StartDebugAdapter()
|
||||
self._Initialise()
|
||||
|
||||
|
|
@ -309,7 +326,7 @@ class DebugSession( object ):
|
|||
|
||||
if self._connection:
|
||||
self._logger.debug( "_StopDebugAdapter with callback: start" )
|
||||
self._StopDebugAdapter( start )
|
||||
self._StopDebugAdapter( interactive = False, callback = start )
|
||||
return
|
||||
|
||||
start()
|
||||
|
|
@ -374,14 +391,15 @@ class DebugSession( object ):
|
|||
self._connection = None
|
||||
|
||||
@IfConnected()
|
||||
def Stop( self ):
|
||||
def Stop( self, interactive = False ):
|
||||
self._logger.debug( "Stop debug adapter with no callback" )
|
||||
self._StopDebugAdapter()
|
||||
self._StopDebugAdapter( interactive = interactive )
|
||||
|
||||
def Reset( self ):
|
||||
def Reset( self, interactive = False ):
|
||||
if self._connection:
|
||||
self._logger.debug( "Stop debug adapter with callback : self._Reset()" )
|
||||
self._StopDebugAdapter( lambda: self._Reset() )
|
||||
self._StopDebugAdapter( interactive = interactive,
|
||||
callback = lambda: self._Reset() )
|
||||
else:
|
||||
self._Reset()
|
||||
|
||||
|
|
@ -401,6 +419,7 @@ class DebugSession( object ):
|
|||
self._outputView.Reset()
|
||||
self._codeView.Reset()
|
||||
vim.command( 'tabclose!' )
|
||||
vim.command( 'doautocmd <nomodeline> User VimspectorDebugEnded' )
|
||||
self._stackTraceView = None
|
||||
self._variablesView = None
|
||||
self._outputView = None
|
||||
|
|
@ -423,43 +442,98 @@ class DebugSession( object ):
|
|||
},
|
||||
} )
|
||||
|
||||
self._stackTraceView.OnContinued()
|
||||
self._codeView.SetCurrentFrame( None )
|
||||
|
||||
@IfConnected()
|
||||
def StepInto( self ):
|
||||
if self._stackTraceView.GetCurrentThreadId() is None:
|
||||
threadId = self._stackTraceView.GetCurrentThreadId()
|
||||
if threadId is None:
|
||||
return
|
||||
|
||||
self._connection.DoRequest( None, {
|
||||
def handler( *_ ):
|
||||
self._stackTraceView.OnContinued( { 'threadId': threadId } )
|
||||
self._codeView.SetCurrentFrame( None )
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'stepIn',
|
||||
'arguments': {
|
||||
'threadId': self._stackTraceView.GetCurrentThreadId()
|
||||
'threadId': threadId
|
||||
},
|
||||
} )
|
||||
|
||||
@IfConnected()
|
||||
def StepOut( self ):
|
||||
if self._stackTraceView.GetCurrentThreadId() is None:
|
||||
threadId = self._stackTraceView.GetCurrentThreadId()
|
||||
if threadId is None:
|
||||
return
|
||||
|
||||
self._connection.DoRequest( None, {
|
||||
def handler( *_ ):
|
||||
self._stackTraceView.OnContinued( { 'threadId': threadId } )
|
||||
self._codeView.SetCurrentFrame( None )
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'stepOut',
|
||||
'arguments': {
|
||||
'threadId': self._stackTraceView.GetCurrentThreadId()
|
||||
'threadId': threadId
|
||||
},
|
||||
} )
|
||||
|
||||
|
||||
def Continue( self ):
|
||||
if self._connection:
|
||||
self._stackTraceView.Continue()
|
||||
else:
|
||||
if not self._connection:
|
||||
self.Start()
|
||||
return
|
||||
|
||||
threadId = self._stackTraceView.GetCurrentThreadId()
|
||||
if threadId is None:
|
||||
utils.UserMessage( 'No current thread', persist = True )
|
||||
return
|
||||
|
||||
def handler( msg ):
|
||||
self._stackTraceView.OnContinued( {
|
||||
'threadId': threadId,
|
||||
'allThreadsContinued': ( msg.get( 'body' ) or {} ).get(
|
||||
'allThreadsContinued',
|
||||
True )
|
||||
} )
|
||||
self._codeView.SetCurrentFrame( None )
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'continue',
|
||||
'arguments': {
|
||||
'threadId': threadId,
|
||||
},
|
||||
} )
|
||||
|
||||
@IfConnected()
|
||||
def Pause( self ):
|
||||
self._stackTraceView.Pause()
|
||||
if self._stackTraceView.GetCurrentThreadId() is None:
|
||||
utils.UserMessage( 'No current thread', persist = True )
|
||||
return
|
||||
|
||||
self._connection.DoRequest( None, {
|
||||
'command': 'pause',
|
||||
'arguments': {
|
||||
'threadId': self._stackTraceView.GetCurrentThreadId(),
|
||||
},
|
||||
} )
|
||||
|
||||
@IfConnected()
|
||||
def ExpandVariable( self ):
|
||||
self._variablesView.ExpandVariable()
|
||||
def PauseContinueThread( self ):
|
||||
self._stackTraceView.PauseContinueThread()
|
||||
|
||||
@IfConnected()
|
||||
def SetCurrentThread( self ):
|
||||
self._stackTraceView.SetCurrentThread()
|
||||
|
||||
@IfConnected()
|
||||
def ExpandVariable( self, buf = None, line_num = None ):
|
||||
self._variablesView.ExpandVariable( buf, line_num )
|
||||
|
||||
@IfConnected()
|
||||
def SetVariableValue( self, new_value = None, buf = None, line_num = None ):
|
||||
self._variablesView.SetVariableValue( new_value, buf, line_num )
|
||||
|
||||
@IfConnected()
|
||||
def AddWatch( self, expression ):
|
||||
|
|
@ -467,21 +541,22 @@ class DebugSession( object ):
|
|||
expression )
|
||||
|
||||
@IfConnected()
|
||||
def EvaluateConsole( self, expression ):
|
||||
def EvaluateConsole( self, expression, verbose ):
|
||||
self._outputView.Evaluate( self._stackTraceView.GetCurrentFrame(),
|
||||
expression )
|
||||
expression,
|
||||
verbose )
|
||||
|
||||
@IfConnected()
|
||||
def DeleteWatch( self ):
|
||||
self._variablesView.DeleteWatch()
|
||||
|
||||
|
||||
@IfConnected()
|
||||
def ShowBalloon( self, winnr, expression ):
|
||||
"""Proxy: ballonexpr -> variables.ShowBallon"""
|
||||
def ShowEvalBalloon( self, winnr, expression, is_hover ):
|
||||
frame = self._stackTraceView.GetCurrentFrame()
|
||||
# Check if RIP is in a frame
|
||||
if frame is None:
|
||||
self._logger.debug( 'Balloon: Not in a stack frame' )
|
||||
self._logger.debug( 'Tooltip: Not in a stack frame' )
|
||||
return ''
|
||||
|
||||
# Check if cursor in code window
|
||||
|
|
@ -492,12 +567,24 @@ class DebugSession( object ):
|
|||
return ''
|
||||
|
||||
# Return variable aware function
|
||||
return self._variablesView.ShowBalloon( frame, expression )
|
||||
return self._variablesView.VariableEval( frame, expression, is_hover )
|
||||
|
||||
|
||||
def CleanUpTooltip( self ):
|
||||
return self._variablesView.CleanUpTooltip()
|
||||
|
||||
@IfConnected()
|
||||
def ExpandFrameOrThread( self ):
|
||||
self._stackTraceView.ExpandFrameOrThread()
|
||||
|
||||
@IfConnected()
|
||||
def UpFrame( self ):
|
||||
self._stackTraceView.UpFrame()
|
||||
|
||||
@IfConnected()
|
||||
def DownFrame( self ):
|
||||
self._stackTraceView.DownFrame()
|
||||
|
||||
def ToggleLog( self ):
|
||||
if self._HasUI():
|
||||
return self.ShowOutput( 'Vimspector' )
|
||||
|
|
@ -559,10 +646,68 @@ class DebugSession( object ):
|
|||
return response[ 'body' ][ 'targets' ]
|
||||
|
||||
|
||||
@IfConnected( otherwise=[] )
|
||||
def GetCommandLineCompletions( self, ArgLead, prev_non_keyword_char ):
|
||||
items = []
|
||||
for candidate in self.GetCompletionsSync( ArgLead, prev_non_keyword_char ):
|
||||
label = candidate.get( 'text', candidate[ 'label' ] )
|
||||
start = prev_non_keyword_char - 1
|
||||
if 'start' in candidate and 'length' in candidate:
|
||||
start = candidate[ 'start' ]
|
||||
items.append( ArgLead[ 0 : start ] + label )
|
||||
|
||||
return items
|
||||
|
||||
def RefreshSigns( self, file_name ):
|
||||
if self._connection:
|
||||
self._codeView.Refresh( file_name )
|
||||
else:
|
||||
self._breakpoints.Refresh( file_name )
|
||||
|
||||
|
||||
def _SetUpUI( self ):
|
||||
vim.command( 'tab split' )
|
||||
self._uiTab = vim.current.tabpage
|
||||
|
||||
mode = settings.Get( 'ui_mode' )
|
||||
|
||||
if mode == 'auto':
|
||||
# Go vertical if there isn't enough horizontal space for at least:
|
||||
# the left bar width
|
||||
# + the code min width
|
||||
# + the terminal min width
|
||||
# + enough space for a sign column and number column?
|
||||
min_width = ( settings.Int( 'sidebar_width' )
|
||||
+ 1 + 2 + 3
|
||||
+ settings.Int( 'code_minwidth' )
|
||||
+ 1 + settings.Int( 'terminal_minwidth' ) )
|
||||
|
||||
min_height = ( settings.Int( 'code_minheight' ) + 1 +
|
||||
settings.Int( 'topbar_height' ) + 1 +
|
||||
settings.Int( 'bottombar_height' ) + 1 +
|
||||
2 )
|
||||
|
||||
mode = ( 'vertical'
|
||||
if vim.options[ 'columns' ] < min_width
|
||||
else 'horizontal' )
|
||||
|
||||
if vim.options[ 'lines' ] < min_height:
|
||||
mode = 'horizontal'
|
||||
|
||||
self._logger.debug( 'min_width/height: %s/%s, actual: %s/%s - result: %s',
|
||||
min_width,
|
||||
min_height,
|
||||
vim.options[ 'columns' ],
|
||||
vim.options[ 'lines' ],
|
||||
mode )
|
||||
|
||||
if mode == 'vertical':
|
||||
self._SetUpUIVertical()
|
||||
else:
|
||||
self._SetUpUIHorizontal()
|
||||
|
||||
|
||||
def _SetUpUIHorizontal( self ):
|
||||
# Code window
|
||||
code_window = vim.current.window
|
||||
self._codeView = code.CodeView( code_window, self._api_prefix )
|
||||
|
|
@ -603,12 +748,73 @@ class DebugSession( object ):
|
|||
# TODO: If/when we support multiple sessions, we'll need some way to
|
||||
# indicate which tab was created and store all the tabs
|
||||
vim.vars[ 'vimspector_session_windows' ] = {
|
||||
'mode': 'horizontal',
|
||||
'tabpage': self._uiTab.number,
|
||||
'code': utils.WindowID( code_window, self._uiTab ),
|
||||
'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ),
|
||||
'variables': utils.WindowID( vars_window, self._uiTab ),
|
||||
'watches': utils.WindowID( watch_window, self._uiTab ),
|
||||
'output': utils.WindowID( output_window, self._uiTab ),
|
||||
'eval': None # this is going to be updated every time eval popup is opened
|
||||
}
|
||||
with utils.RestoreCursorPosition():
|
||||
with utils.RestoreCurrentWindow():
|
||||
with utils.RestoreCurrentBuffer( vim.current.window ):
|
||||
vim.command( 'doautocmd User VimspectorUICreated' )
|
||||
|
||||
|
||||
def _SetUpUIVertical( self ):
|
||||
# Code window
|
||||
code_window = vim.current.window
|
||||
self._codeView = code.CodeView( code_window, self._api_prefix )
|
||||
|
||||
# Call stack
|
||||
vim.command(
|
||||
f'topleft { settings.Int( "topbar_height" ) }new' )
|
||||
stack_trace_window = vim.current.window
|
||||
one_third = int( vim.eval( 'winwidth( 0 )' ) ) / 3
|
||||
self._stackTraceView = stack_trace.StackTraceView( self,
|
||||
stack_trace_window )
|
||||
|
||||
|
||||
# Watches
|
||||
vim.command( 'leftabove vertical new' )
|
||||
watch_window = vim.current.window
|
||||
|
||||
# Variables
|
||||
vim.command( 'leftabove vertical new' )
|
||||
vars_window = vim.current.window
|
||||
|
||||
|
||||
with utils.LetCurrentWindow( vars_window ):
|
||||
vim.command( f'{ one_third }wincmd |' )
|
||||
with utils.LetCurrentWindow( watch_window ):
|
||||
vim.command( f'{ one_third }wincmd |' )
|
||||
with utils.LetCurrentWindow( stack_trace_window ):
|
||||
vim.command( f'{ one_third }wincmd |' )
|
||||
|
||||
self._variablesView = variables.VariablesView( vars_window,
|
||||
watch_window )
|
||||
|
||||
|
||||
# Output/logging
|
||||
vim.current.window = code_window
|
||||
vim.command( f'rightbelow { settings.Int( "bottombar_height" ) }new' )
|
||||
output_window = vim.current.window
|
||||
self._outputView = output.DAPOutputView( output_window,
|
||||
self._api_prefix )
|
||||
|
||||
# TODO: If/when we support multiple sessions, we'll need some way to
|
||||
# indicate which tab was created and store all the tabs
|
||||
vim.vars[ 'vimspector_session_windows' ] = {
|
||||
'mode': 'vertical',
|
||||
'tabpage': self._uiTab.number,
|
||||
'code': utils.WindowID( code_window, self._uiTab ),
|
||||
'stack_trace': utils.WindowID( stack_trace_window, self._uiTab ),
|
||||
'variables': utils.WindowID( vars_window, self._uiTab ),
|
||||
'watches': utils.WindowID( watch_window, self._uiTab ),
|
||||
'output': utils.WindowID( output_window, self._uiTab ),
|
||||
'eval': None # this is going to be updated every time eval popup is opened
|
||||
}
|
||||
with utils.RestoreCursorPosition():
|
||||
with utils.RestoreCurrentWindow():
|
||||
|
|
@ -621,7 +827,7 @@ class DebugSession( object ):
|
|||
self.SetCurrentFrame( None )
|
||||
|
||||
@RequiresUI()
|
||||
def SetCurrentFrame( self, frame ):
|
||||
def SetCurrentFrame( self, frame, reason = '' ):
|
||||
if not frame:
|
||||
self._stackTraceView.Clear()
|
||||
self._variablesView.Clear()
|
||||
|
|
@ -629,11 +835,16 @@ class DebugSession( object ):
|
|||
if not self._codeView.SetCurrentFrame( frame ):
|
||||
return False
|
||||
|
||||
if frame:
|
||||
self._variablesView.SetSyntax( self._codeView.current_syntax )
|
||||
self._stackTraceView.SetSyntax( self._codeView.current_syntax )
|
||||
self._variablesView.LoadScopes( frame )
|
||||
self._variablesView.EvaluateWatches()
|
||||
# the codeView.SetCurrentFrame already checked the frame was valid and
|
||||
# countained a valid source
|
||||
self._variablesView.SetSyntax( self._codeView.current_syntax )
|
||||
self._stackTraceView.SetSyntax( self._codeView.current_syntax )
|
||||
self._variablesView.LoadScopes( frame )
|
||||
self._variablesView.EvaluateWatches()
|
||||
|
||||
if reason == 'stopped':
|
||||
self._breakpoints.ClearTemporaryBreakpoint( frame[ 'source' ][ 'path' ],
|
||||
frame[ 'line' ] )
|
||||
|
||||
return True
|
||||
|
||||
|
|
@ -652,7 +863,6 @@ class DebugSession( object ):
|
|||
json.dumps( self._adapter ) )
|
||||
|
||||
self._init_complete = False
|
||||
self._on_init_complete_handlers = []
|
||||
self._launch_complete = False
|
||||
self._run_on_server_exit = None
|
||||
|
||||
|
|
@ -668,12 +878,9 @@ class DebugSession( object ):
|
|||
self._adapter[ 'port' ] = port
|
||||
|
||||
self._connection_type = self._api_prefix + self._connection_type
|
||||
self._logger.debug( f"Connection Type: { self._connection_type }" )
|
||||
|
||||
# TODO: Do we actually need to copy and update or does Vim do that?
|
||||
env = os.environ.copy()
|
||||
if 'env' in self._adapter:
|
||||
env.update( self._adapter[ 'env' ] )
|
||||
self._adapter[ 'env' ] = env
|
||||
self._adapter[ 'env' ] = self._adapter.get( 'env', {} )
|
||||
|
||||
if 'cwd' not in self._adapter:
|
||||
self._adapter[ 'cwd' ] = os.getcwd()
|
||||
|
|
@ -687,56 +894,93 @@ class DebugSession( object ):
|
|||
self._splash_screen,
|
||||
"Unable to start adapter" )
|
||||
else:
|
||||
if 'custom_handler' in self._adapter:
|
||||
spec = self._adapter[ 'custom_handler' ]
|
||||
if isinstance( spec, dict ):
|
||||
module = spec[ 'module' ]
|
||||
cls = spec[ 'class' ]
|
||||
else:
|
||||
module, cls = spec.rsplit( '.', 1 )
|
||||
|
||||
CustomHandler = getattr( importlib.import_module( module ), cls )
|
||||
handlers = [ CustomHandler( self ), self ]
|
||||
else:
|
||||
handlers = [ self ]
|
||||
|
||||
self._connection = debug_adapter_connection.DebugAdapterConnection(
|
||||
self,
|
||||
handlers,
|
||||
lambda msg: utils.Call(
|
||||
"vimspector#internal#{}#Send".format( self._connection_type ),
|
||||
msg ) )
|
||||
|
||||
self._logger.info( 'Debug Adapter Started' )
|
||||
|
||||
def _StopDebugAdapter( self, callback = None ):
|
||||
self._splash_screen = utils.DisplaySplash(
|
||||
self._api_prefix,
|
||||
self._splash_screen,
|
||||
"Shutting down debug adapter..." )
|
||||
|
||||
def handler( *args ):
|
||||
self._splash_screen = utils.HideSplash( self._api_prefix,
|
||||
self._splash_screen )
|
||||
|
||||
if callback:
|
||||
self._logger.debug( "Setting server exit handler before disconnect" )
|
||||
assert not self._run_on_server_exit
|
||||
self._run_on_server_exit = callback
|
||||
|
||||
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
|
||||
self._connection_type ) )
|
||||
|
||||
def _StopDebugAdapter( self, interactive = False, callback = None ):
|
||||
arguments = {}
|
||||
if self._server_capabilities.get( 'supportTerminateDebuggee' ):
|
||||
# If we attached, we should _not_ terminate the debuggee
|
||||
arguments[ 'terminateDebuggee' ] = False
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'disconnect',
|
||||
'arguments': arguments,
|
||||
}, failure_handler = handler, timeout = 5000 )
|
||||
def disconnect():
|
||||
self._splash_screen = utils.DisplaySplash(
|
||||
self._api_prefix,
|
||||
self._splash_screen,
|
||||
"Shutting down debug adapter..." )
|
||||
|
||||
# TODO: Use the 'tarminate' request if supportsTerminateRequest set
|
||||
def handler( *args ):
|
||||
self._splash_screen = utils.HideSplash( self._api_prefix,
|
||||
self._splash_screen )
|
||||
|
||||
if callback:
|
||||
self._logger.debug( "Setting server exit handler before disconnect" )
|
||||
assert not self._run_on_server_exit
|
||||
self._run_on_server_exit = callback
|
||||
|
||||
vim.eval( 'vimspector#internal#{}#StopDebugSession()'.format(
|
||||
self._connection_type ) )
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'disconnect',
|
||||
'arguments': arguments,
|
||||
}, failure_handler = handler, timeout = 5000 )
|
||||
|
||||
if not interactive:
|
||||
disconnect()
|
||||
elif not self._server_capabilities.get( 'supportTerminateDebuggee' ):
|
||||
disconnect()
|
||||
elif not self._stackTraceView.AnyThreadsRunning():
|
||||
disconnect()
|
||||
else:
|
||||
def handle_choice( choice ):
|
||||
if choice == 1:
|
||||
# yes
|
||||
arguments[ 'terminateDebuggee' ] = True
|
||||
elif choice == 2:
|
||||
# no
|
||||
arguments[ 'terminateDebuggee' ] = False
|
||||
elif choice <= 0:
|
||||
# Abort
|
||||
return
|
||||
# Else, use server default
|
||||
|
||||
disconnect()
|
||||
|
||||
utils.Confirm( self._api_prefix,
|
||||
"Terminate debuggee?",
|
||||
handle_choice,
|
||||
default_value = 3,
|
||||
options = [ '(Y)es', '(N)o', '(D)efault' ],
|
||||
keys = [ 'y', 'n', 'd' ] )
|
||||
|
||||
|
||||
def _PrepareAttach( self, adapter_config, launch_config ):
|
||||
atttach_config = adapter_config.get( 'attach' )
|
||||
attach_config = adapter_config.get( 'attach' )
|
||||
|
||||
if not atttach_config:
|
||||
if not attach_config:
|
||||
return
|
||||
|
||||
if 'remote' in atttach_config:
|
||||
if 'remote' in attach_config:
|
||||
# FIXME: We almost want this to feed-back variables to be expanded later,
|
||||
# e.g. expand variables when we use them, not all at once. This would
|
||||
# remove the whole %PID% hack.
|
||||
remote = atttach_config[ 'remote' ]
|
||||
remote = attach_config[ 'remote' ]
|
||||
remote_exec_cmd = self._GetRemoteExecCommand( remote )
|
||||
|
||||
# FIXME: Why does this not use self._GetCommands ?
|
||||
|
|
@ -777,20 +1021,23 @@ class DebugSession( object ):
|
|||
self._codeView._window,
|
||||
self._remote_term )
|
||||
else:
|
||||
if atttach_config[ 'pidSelect' ] == 'ask':
|
||||
prop = atttach_config[ 'pidProperty' ]
|
||||
if attach_config[ 'pidSelect' ] == 'ask':
|
||||
prop = attach_config[ 'pidProperty' ]
|
||||
if prop not in launch_config:
|
||||
pid = utils.AskForInput( 'Enter PID to attach to: ' )
|
||||
if pid is None:
|
||||
return
|
||||
launch_config[ prop ] = pid
|
||||
return
|
||||
elif atttach_config[ 'pidSelect' ] == 'none':
|
||||
elif attach_config[ 'pidSelect' ] == 'none':
|
||||
return
|
||||
|
||||
raise ValueError( 'Unrecognised pidSelect {0}'.format(
|
||||
atttach_config[ 'pidSelect' ] ) )
|
||||
attach_config[ 'pidSelect' ] ) )
|
||||
|
||||
if 'delay' in attach_config:
|
||||
utils.UserMessage( f"Waiting ( { attach_config[ 'delay' ] } )..." )
|
||||
vim.command( f'sleep { attach_config[ "delay" ] }' )
|
||||
|
||||
|
||||
def _PrepareLaunch( self, command_line, adapter_config, launch_config ):
|
||||
|
|
@ -823,6 +1070,11 @@ class DebugSession( object ):
|
|||
self._codeView._window,
|
||||
self._remote_term )
|
||||
|
||||
if 'delay' in run_config:
|
||||
utils.UserMessage( f"Waiting ( {run_config[ 'delay' ]} )..." )
|
||||
vim.command( f'sleep { run_config[ "delay" ] }' )
|
||||
|
||||
|
||||
|
||||
def _GetSSHCommand( self, remote ):
|
||||
ssh = [ 'ssh' ] + remote.get( 'ssh', {} ).get( 'args', [] )
|
||||
|
|
@ -896,6 +1148,7 @@ class DebugSession( object ):
|
|||
def handle_initialize_response( msg ):
|
||||
self._server_capabilities = msg.get( 'body' ) or {}
|
||||
self._breakpoints.SetServerCapabilities( self._server_capabilities )
|
||||
self._variablesView.SetServerCapabilities( self._server_capabilities )
|
||||
self._Launch()
|
||||
|
||||
self._connection.DoRequest( handle_initialize_response, {
|
||||
|
|
@ -921,40 +1174,44 @@ class DebugSession( object ):
|
|||
message )
|
||||
self._outputView.Print( 'server', msg )
|
||||
|
||||
def _Launch( self ):
|
||||
|
||||
def _Prepare( self ):
|
||||
self._on_init_complete_handlers = []
|
||||
|
||||
self._logger.debug( "LAUNCH!" )
|
||||
adapter_config = self._adapter
|
||||
launch_config = {}
|
||||
launch_config.update( self._adapter.get( 'configuration', {} ) )
|
||||
launch_config.update( self._configuration[ 'configuration' ] )
|
||||
self._launch_config = {}
|
||||
self._launch_config.update( self._adapter.get( 'configuration', {} ) )
|
||||
self._launch_config.update( self._configuration[ 'configuration' ] )
|
||||
|
||||
request = self._configuration.get(
|
||||
'remote-request',
|
||||
launch_config.get( 'request', 'launch' ) )
|
||||
self._launch_config.get( 'request', 'launch' ) )
|
||||
|
||||
if request == "attach":
|
||||
self._splash_screen = utils.DisplaySplash(
|
||||
self._api_prefix,
|
||||
self._splash_screen,
|
||||
"Attaching to debugee..." )
|
||||
"Attaching to debuggee..." )
|
||||
|
||||
self._PrepareAttach( adapter_config, launch_config )
|
||||
self._PrepareAttach( self._adapter, self._launch_config )
|
||||
elif request == "launch":
|
||||
self._splash_screen = utils.DisplaySplash(
|
||||
self._api_prefix,
|
||||
self._splash_screen,
|
||||
"Launching debugee..." )
|
||||
"Launching debuggee..." )
|
||||
|
||||
# FIXME: This cmdLine hack is not fun.
|
||||
self._PrepareLaunch( self._configuration.get( 'remote-cmdLine', [] ),
|
||||
adapter_config,
|
||||
launch_config )
|
||||
self._adapter,
|
||||
self._launch_config )
|
||||
|
||||
# FIXME: name is mandatory. Forcefully add it (we should really use the
|
||||
# _actual_ name, but that isn't actually remembered at this point)
|
||||
if 'name' not in launch_config:
|
||||
launch_config[ 'name' ] = 'test'
|
||||
if 'name' not in self._launch_config:
|
||||
self._launch_config[ 'name' ] = 'test'
|
||||
|
||||
|
||||
def _Launch( self ):
|
||||
def failure_handler( reason, msg ):
|
||||
text = [
|
||||
'Launch Failed',
|
||||
|
|
@ -967,12 +1224,11 @@ class DebugSession( object ):
|
|||
self._splash_screen,
|
||||
text )
|
||||
|
||||
|
||||
self._connection.DoRequest(
|
||||
lambda msg: self._OnLaunchComplete(),
|
||||
{
|
||||
'command': launch_config[ 'request' ],
|
||||
'arguments': launch_config
|
||||
'command': self._launch_config[ 'request' ],
|
||||
'arguments': self._launch_config
|
||||
},
|
||||
failure_handler )
|
||||
|
||||
|
|
@ -1014,6 +1270,37 @@ class DebugSession( object ):
|
|||
self._stackTraceView.LoadThreads( True )
|
||||
|
||||
|
||||
@IfConnected()
|
||||
@RequiresUI()
|
||||
def PrintDebugInfo( self ):
|
||||
def Line():
|
||||
return ( "--------------------------------------------------------------"
|
||||
"------------------" )
|
||||
|
||||
def Pretty( obj ):
|
||||
if obj is None:
|
||||
return [ "None" ]
|
||||
return [ Line() ] + json.dumps( obj, indent=2 ).splitlines() + [ Line() ]
|
||||
|
||||
|
||||
debugInfo = [
|
||||
"Vimspector Debug Info",
|
||||
Line(),
|
||||
f"ConnectionType: { self._connection_type }",
|
||||
"Adapter: " ] + Pretty( self._adapter ) + [
|
||||
"Configuration: " ] + Pretty( self._configuration ) + [
|
||||
f"API Prefix: { self._api_prefix }",
|
||||
f"Launch/Init: { self._launch_complete } / { self._init_complete }",
|
||||
f"Workspace Root: { self._workspace_root }",
|
||||
"Launch Config: " ] + Pretty( self._launch_config ) + [
|
||||
"Server Capabilities: " ] + Pretty( self._server_capabilities ) + [
|
||||
]
|
||||
|
||||
self._outputView.ClearCategory( 'DebugInfo' )
|
||||
self._outputView.Print( "DebugInfo", debugInfo )
|
||||
self.ShowOutput( "DebugInfo" )
|
||||
|
||||
|
||||
def OnEvent_loadedSource( self, msg ):
|
||||
pass
|
||||
|
||||
|
|
@ -1050,7 +1337,9 @@ class DebugSession( object ):
|
|||
if reason == 'changed':
|
||||
self._codeView.UpdateBreakpoint( bp )
|
||||
elif reason == 'new':
|
||||
self._codeView.AddBreakpoints( None, bp )
|
||||
self._codeView.AddBreakpoint( bp )
|
||||
elif reason == 'removed':
|
||||
self._codeView.RemoveBreakpoint( bp )
|
||||
else:
|
||||
utils.UserMessage(
|
||||
'Unrecognised breakpoint event (undocumented): {0}'.format( reason ),
|
||||
|
|
@ -1074,19 +1363,33 @@ class DebugSession( object ):
|
|||
|
||||
self._connection.DoResponse( message, None, response )
|
||||
|
||||
def OnEvent_terminated( self, message ):
|
||||
# The debugging _session_ has terminated. This does not mean that the
|
||||
# debuggee has terminated (that's the exited event).
|
||||
#
|
||||
# We will handle this when the server actually exists.
|
||||
#
|
||||
# FIXME we should always wait for this event before disconnecting closing
|
||||
# any socket connection
|
||||
self.SetCurrentFrame( None )
|
||||
|
||||
|
||||
def OnEvent_exited( self, message ):
|
||||
utils.UserMessage( 'The debugee exited with status code: {}'.format(
|
||||
utils.UserMessage( 'The debuggee exited with status code: {}'.format(
|
||||
message[ 'body' ][ 'exitCode' ] ) )
|
||||
self._stackTraceView.OnExited( message )
|
||||
self._codeView.SetCurrentFrame( None )
|
||||
|
||||
def OnEvent_process( self, message ):
|
||||
utils.UserMessage( 'The debugee was started: {}'.format(
|
||||
utils.UserMessage( 'The debuggee was started: {}'.format(
|
||||
message[ 'body' ][ 'name' ] ) )
|
||||
|
||||
def OnEvent_module( self, message ):
|
||||
pass
|
||||
|
||||
def OnEvent_continued( self, message ):
|
||||
pass
|
||||
self._stackTraceView.OnContinued( message[ 'body' ] )
|
||||
self._codeView.SetCurrentFrame( None )
|
||||
|
||||
def Clear( self ):
|
||||
self._codeView.Clear()
|
||||
|
|
@ -1118,10 +1421,6 @@ class DebugSession( object ):
|
|||
else:
|
||||
self._logger.debug( "No server exit handler" )
|
||||
|
||||
def OnEvent_terminated( self, message ):
|
||||
# We will handle this when the server actually exists
|
||||
utils.UserMessage( "Debugging was terminated by the server." )
|
||||
|
||||
def OnEvent_output( self, message ):
|
||||
if self._outputView:
|
||||
self._outputView.OnOutput( message[ 'body' ] )
|
||||
|
|
@ -1162,6 +1461,26 @@ class DebugSession( object ):
|
|||
def ToggleBreakpoint( self, options ):
|
||||
return self._breakpoints.ToggleBreakpoint( options )
|
||||
|
||||
def RunTo( self, file_name, line ):
|
||||
self.ClearTemporaryBreakpoints()
|
||||
self.SetLineBreakpoint( file_name,
|
||||
line,
|
||||
{ 'temporary': True },
|
||||
lambda: self.Continue() )
|
||||
|
||||
|
||||
def ClearTemporaryBreakpoints( self ):
|
||||
return self._breakpoints.ClearTemporaryBreakpoints()
|
||||
|
||||
def SetLineBreakpoint( self, file_name, line_num, options, then = None ):
|
||||
return self._breakpoints.SetLineBreakpoint( file_name,
|
||||
line_num,
|
||||
options,
|
||||
then )
|
||||
|
||||
def ClearLineBreakpoint( self, file_name, line_num ):
|
||||
return self._breakpoints.ClearLineBreakpoint( file_name, line_num )
|
||||
|
||||
def ClearBreakpoints( self ):
|
||||
if self._connection:
|
||||
self._codeView.ClearBreakpoints()
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import os
|
|||
|
||||
GADGETS = {
|
||||
'vscode-cpptools': {
|
||||
'language': 'c',
|
||||
'language': [ 'c', 'cpp', 'rust' ],
|
||||
'download': {
|
||||
'url': 'https://github.com/Microsoft/vscode-cpptools/releases/download/'
|
||||
'${version}/${file_name}',
|
||||
|
|
@ -30,12 +30,12 @@ GADGETS = {
|
|||
root,
|
||||
gadget ),
|
||||
'all': {
|
||||
'version': '0.27.0',
|
||||
'version': '1.6.0',
|
||||
"adapters": {
|
||||
"vscode-cpptools": {
|
||||
"name": "cppdbg",
|
||||
"command": [
|
||||
"${gadgetDir}/vscode-cpptools/debugAdapters/OpenDebugAD7"
|
||||
"${gadgetDir}/vscode-cpptools/debugAdapters/bin/OpenDebugAD7"
|
||||
],
|
||||
"attach": {
|
||||
"pidProperty": "processId",
|
||||
|
|
@ -53,17 +53,17 @@ GADGETS = {
|
|||
'linux': {
|
||||
'file_name': 'cpptools-linux.vsix',
|
||||
'checksum':
|
||||
'3695202e1e75a03de18049323b66d868165123f26151f8c974a480eaf0205435',
|
||||
'c25299bcfb46b22d41aa3f125df7184e6282a35ff9fb69c47def744cb4778f55',
|
||||
},
|
||||
'macos': {
|
||||
'file_name': 'cpptools-osx.vsix',
|
||||
'file_name': 'cpptools-osx-arm64.vsix',
|
||||
'checksum':
|
||||
'cb061e3acd7559a539e5586f8d3f535101c4ec4e8a48195856d1d39380b5cf3c',
|
||||
'ceb3e8cdaa2b5bb45af50913ddd8402089969748af8d70f5d46480408287ba6f',
|
||||
},
|
||||
'windows': {
|
||||
'file_name': 'cpptools-win32.vsix',
|
||||
'checksum':
|
||||
'aa294368ed16d48c59e49c8000e146eae5a19ad07b654efed5db8ec93b24229e',
|
||||
'ef7ac5831874a3c7dbf0feb826bfda2be579aff9b6d990622fff1d0d4ede00d1',
|
||||
"adapters": {
|
||||
"vscode-cpptools": {
|
||||
"name": "cppdbg",
|
||||
|
|
@ -86,39 +86,16 @@ GADGETS = {
|
|||
},
|
||||
},
|
||||
},
|
||||
'vscode-python': {
|
||||
'language': 'python.legacy',
|
||||
'enabled': False,
|
||||
'download': {
|
||||
'url': 'https://github.com/Microsoft/vscode-python/releases/download/'
|
||||
'${version}/${file_name}',
|
||||
},
|
||||
'all': {
|
||||
'version': '2019.11.50794',
|
||||
'file_name': 'ms-python-release.vsix',
|
||||
'checksum':
|
||||
'6a9edf9ecabed14aac424e6007858068204a3638bf3bb4f235bd6035d823acc6',
|
||||
},
|
||||
'adapters': {
|
||||
"vscode-python": {
|
||||
"name": "vscode-python",
|
||||
"command": [
|
||||
"node",
|
||||
"${gadgetDir}/vscode-python/out/client/debugger/debugAdapter/main.js",
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
'debugpy': {
|
||||
'language': 'python',
|
||||
'download': {
|
||||
'url': 'https://github.com/microsoft/debugpy/archive/${file_name}'
|
||||
},
|
||||
'all': {
|
||||
'version': '1.0.0b12',
|
||||
'file_name': 'v1.0.0b12.zip',
|
||||
'version': '1.2.1',
|
||||
'file_name': 'v1.2.1.zip',
|
||||
'checksum':
|
||||
'210632bba2221fbb841c9785a615258819ceec401d1abdbeb5f2326f12cc72a1'
|
||||
'29a6c5d1053d2b6f3b1a63e1a8ecff93f951d3cc0b7548431592e9e3007239e6'
|
||||
},
|
||||
'do': lambda name, root, gadget: installer.InstallDebugpy( name,
|
||||
root,
|
||||
|
|
@ -157,6 +134,10 @@ GADGETS = {
|
|||
"vscode-java": {
|
||||
"name": "vscode-java",
|
||||
"port": "${DAPPort}",
|
||||
"configuration": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
'custom_handler': 'vimspector.custom.java.JavaDebugAdapter'
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
@ -193,7 +174,7 @@ GADGETS = {
|
|||
'language': 'tcl',
|
||||
'repo': {
|
||||
'url': 'https://github.com/puremourning/TclProDebug',
|
||||
'ref': 'master'
|
||||
'ref': 'v1.0.0'
|
||||
},
|
||||
'do': lambda name, root, gadget: installer.InstallTclProDebug( name,
|
||||
root,
|
||||
|
|
@ -222,26 +203,27 @@ GADGETS = {
|
|||
},
|
||||
},
|
||||
'netcoredbg': {
|
||||
'language': 'csharp',
|
||||
'language': [ 'csharp', 'fsharp', 'vbnet' ],
|
||||
'enabled': False,
|
||||
'download': {
|
||||
'url': 'https://github.com/Samsung/netcoredbg/releases/download/latest/'
|
||||
'${file_name}',
|
||||
'url': ( 'https://github.com/Samsung/netcoredbg/releases/download/'
|
||||
'${version}/${file_name}' ),
|
||||
'format': 'tar',
|
||||
},
|
||||
'all': {
|
||||
'version': 'master'
|
||||
'version': '1.2.0-782'
|
||||
},
|
||||
'macos': {
|
||||
'file_name': 'netcoredbg-osx-master.tar.gz',
|
||||
'checksum': '',
|
||||
'file_name': 'netcoredbg-osx.tar.gz',
|
||||
'checksum':
|
||||
'',
|
||||
},
|
||||
'linux': {
|
||||
'file_name': 'netcoredbg-linux-master.tar.gz',
|
||||
'file_name': 'netcoredbg-linux-bionic-amd64.tar.gz',
|
||||
'checksum': '',
|
||||
},
|
||||
'windows': {
|
||||
'file_name': 'netcoredbg-win64-master.zip',
|
||||
'file_name': 'netcoredbg-win64.zip',
|
||||
'checksum': '',
|
||||
},
|
||||
'do': lambda name, root, gadget: installer.MakeSymlink(
|
||||
|
|
@ -258,35 +240,9 @@ GADGETS = {
|
|||
"pidProperty": "processId",
|
||||
"pidSelect": "ask"
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
'vscode-mono-debug': {
|
||||
'language': 'csharp',
|
||||
'enabled': False,
|
||||
'download': {
|
||||
'url': 'https://marketplace.visualstudio.com/_apis/public/gallery/'
|
||||
'publishers/ms-vscode/vsextensions/mono-debug/${version}/'
|
||||
'vspackage',
|
||||
'target': 'vscode-mono-debug.vsix.gz',
|
||||
'format': 'zip.gz',
|
||||
},
|
||||
'all': {
|
||||
'file_name': 'vscode-mono-debug.vsix',
|
||||
'version': '0.15.8',
|
||||
'checksum':
|
||||
'723eb2b621b99d65a24f215cb64b45f5fe694105613a900a03c859a62a810470',
|
||||
},
|
||||
'adapters': {
|
||||
'vscode-mono-debug': {
|
||||
"name": "mono-debug",
|
||||
"command": [
|
||||
"mono",
|
||||
"${gadgetDir}/vscode-mono-debug/bin/Release/mono-debug.exe"
|
||||
],
|
||||
"attach": {
|
||||
"pidSelect": "none"
|
||||
},
|
||||
"configuration": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
|
|
@ -336,22 +292,25 @@ GADGETS = {
|
|||
'vscode-go': {
|
||||
'language': 'go',
|
||||
'download': {
|
||||
'url': 'https://github.com/microsoft/vscode-go/releases/download/'
|
||||
'${version}/${file_name}'
|
||||
'url': 'https://github.com/golang/vscode-go/releases/download/'
|
||||
'v${version}/${file_name}'
|
||||
},
|
||||
'all': {
|
||||
'version': '0.11.4',
|
||||
'file_name': 'Go-0.11.4.vsix',
|
||||
'version': '0.19.1',
|
||||
'file_name': 'go-0.19.1.vsix',
|
||||
'checksum':
|
||||
'ff7d7b944da5448974cb3a0086f4a2fd48e2086742d9c013d6964283d416027e'
|
||||
'7f9dc014245b030d9f562b28f3ea9b1fd6e2708fac996c53ff6a707f8204ec64',
|
||||
},
|
||||
'adapters': {
|
||||
'vscode-go': {
|
||||
'name': 'delve',
|
||||
'command': [
|
||||
'node',
|
||||
'${gadgetDir}/vscode-go/out/src/debugAdapter/goDebug.js'
|
||||
'${gadgetDir}/vscode-go/dist/debugAdapter.js'
|
||||
],
|
||||
"configuration": {
|
||||
"cwd": "${workspaceRoot}",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -360,14 +319,14 @@ GADGETS = {
|
|||
'enabled': False,
|
||||
'download': {
|
||||
'url':
|
||||
'https://github.com/felixfbecker/vscode-php-debug/releases/download/'
|
||||
'https://github.com/xdebug/vscode-php-debug/releases/download/'
|
||||
'${version}/${file_name}',
|
||||
},
|
||||
'all': {
|
||||
'version': 'v1.13.0',
|
||||
'file_name': 'php-debug.vsix',
|
||||
'version': 'v1.17.0',
|
||||
'file_name': 'php-debug-1.17.0.vsix',
|
||||
'checksum':
|
||||
'8a51e593458fd14623c1c89ebab87347b087d67087717f18bcf77bb788052718',
|
||||
'd0fff272503414b6696cc737bc2e18e060fdd5e5dc4bcaf38ae7373afd8d8bc9',
|
||||
},
|
||||
'adapters': {
|
||||
'vscode-php-debug': {
|
||||
|
|
@ -429,18 +388,18 @@ GADGETS = {
|
|||
},
|
||||
'CodeLLDB': {
|
||||
'language': 'rust',
|
||||
'enabled': False,
|
||||
'enabled': True,
|
||||
'download': {
|
||||
'url': 'https://github.com/vadimcn/vscode-lldb/releases/download/'
|
||||
'${version}/${file_name}',
|
||||
},
|
||||
'all': {
|
||||
'version': 'v1.5.3',
|
||||
'version': 'v1.6.6',
|
||||
},
|
||||
'macos': {
|
||||
'file_name': 'codelldb-x86_64-darwin.vsix',
|
||||
'file_name': 'codelldb-aarch64-darwin.vsix',
|
||||
'checksum':
|
||||
'7505bc1cdfcfd1cb981e2996aec62d63577440709bac31dcadb41a3b4b44631a',
|
||||
'5adc3b9139eabdafd825bd5efc55df4424a203fb2b6087b425cd434956e7ec58',
|
||||
'make_executable': [
|
||||
'adapter/codelldb',
|
||||
'lldb/bin/debugserver',
|
||||
|
|
@ -451,7 +410,7 @@ GADGETS = {
|
|||
'linux': {
|
||||
'file_name': 'codelldb-x86_64-linux.vsix',
|
||||
'checksum':
|
||||
'ce7efc3e94d775368e5942a02bf5c326b6809a0b4c389f79ffa6a8f6f6b72139',
|
||||
'eda2cd9b3089dcc0524c273e91ffb5875fe08c930bf643739a2cd1846e1f98d6',
|
||||
'make_executable': [
|
||||
'adapter/codelldb',
|
||||
'lldb/bin/lldb',
|
||||
|
|
@ -462,7 +421,7 @@ GADGETS = {
|
|||
'windows': {
|
||||
'file_name': 'codelldb-x86_64-windows.vsix',
|
||||
'checksum':
|
||||
'',
|
||||
'8ddebe8381a3d22dc3d95139c3797fda06b5cc34aadf300e13b1c516b9da95fe',
|
||||
'make_executable': []
|
||||
},
|
||||
'adapters': {
|
||||
|
|
@ -486,4 +445,31 @@ GADGETS = {
|
|||
},
|
||||
},
|
||||
},
|
||||
'local-lua-debugger-vscode': {
|
||||
'language': 'lua',
|
||||
'enabled': True,
|
||||
'repo': {
|
||||
'url': 'https://github.com/tomblind/local-lua-debugger-vscode.git',
|
||||
'ref': 'release-${version}'
|
||||
},
|
||||
'all': {
|
||||
'version': '0.2.0',
|
||||
},
|
||||
'do': lambda name, root, gadget: installer.InstallLuaLocal( name,
|
||||
root,
|
||||
gadget ),
|
||||
'adapters': {
|
||||
'lua-local': {
|
||||
'command': [
|
||||
'node',
|
||||
'${gadgetDir}/local-lua-debugger-vscode/extension/debugAdapter.js'
|
||||
],
|
||||
'name': 'lua-local',
|
||||
'configuration': {
|
||||
'interpreter': 'lua',
|
||||
'extensionPath': '${gadgetDir}/local-lua-debugger-vscode'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,10 +229,14 @@ def GadgetListToInstallerArgs( *gadget_list ):
|
|||
except KeyError:
|
||||
continue
|
||||
|
||||
lang = gadget[ "language" ]
|
||||
if isinstance( lang, list ):
|
||||
lang = lang[ 0 ]
|
||||
|
||||
if not gadget.get( 'enabled', True ):
|
||||
installer_args.append( f'--force-enable-{ gadget[ "language" ] }' )
|
||||
installer_args.append( f'--force-enable-{lang}' )
|
||||
else:
|
||||
installer_args.append( f'--enable-{ gadget[ "language" ] }' )
|
||||
installer_args.append( f'--enable-{lang}' )
|
||||
|
||||
return installer_args
|
||||
|
||||
|
|
@ -340,11 +344,12 @@ def WriteAdapters( all_adapters, to_file=None ):
|
|||
|
||||
|
||||
def InstallGeneric( name, root, gadget ):
|
||||
extension = os.path.join( root, 'extension' )
|
||||
extension_path = gadget.get( 'extension_path', 'extension' )
|
||||
extension = os.path.join( root, extension_path )
|
||||
for f in gadget.get( 'make_executable', [] ):
|
||||
MakeExecutable( os.path.join( extension, f ) )
|
||||
|
||||
MakeExtensionSymlink( name, root )
|
||||
MakeExtensionSymlink( name, root, extension_path )
|
||||
|
||||
|
||||
def InstallCppTools( name, root, gadget ):
|
||||
|
|
@ -353,7 +358,8 @@ def InstallCppTools( name, root, gadget ):
|
|||
# It's hilarious, but the execute bits aren't set in the vsix. So they
|
||||
# actually have javascript code which does this. It's just a horrible horrible
|
||||
# hack that really is not funny.
|
||||
MakeExecutable( os.path.join( extension, 'debugAdapters', 'OpenDebugAD7' ) )
|
||||
MakeExecutable(
|
||||
os.path.join( extension, 'debugAdapters', 'bin', 'OpenDebugAD7' ) )
|
||||
with open( os.path.join( extension, 'package.json' ) ) as f:
|
||||
package = json.load( f )
|
||||
runtime_dependencies = package[ 'runtimeDependencies' ]
|
||||
|
|
@ -425,6 +431,13 @@ def InstallNodeDebug( name, root, gadget ):
|
|||
MakeSymlink( name, root )
|
||||
|
||||
|
||||
def InstallLuaLocal( name, root, gadget ):
|
||||
with CurrentWorkingDir( root ):
|
||||
CheckCall( [ 'npm', 'install' ] )
|
||||
CheckCall( [ 'npm', 'run', 'build' ] )
|
||||
MakeSymlink( name, root )
|
||||
|
||||
|
||||
def InstallGagdet( name: str,
|
||||
gadget: dict,
|
||||
manifest: Manifest,
|
||||
|
|
@ -481,7 +494,7 @@ def InstallGagdet( name: str,
|
|||
url = string.Template( gadget[ 'repo' ][ 'url' ] ).substitute( spec )
|
||||
ref = string.Template( gadget[ 'repo' ][ 'ref' ] ).substitute( spec )
|
||||
|
||||
print( f"Installing {name}@{gadget[ 'repo' ][ 'ref' ]}..." )
|
||||
print( f"Installing {name}@{ref}..." )
|
||||
spec[ 'repo' ] = gadget[ 'repo' ]
|
||||
if not manifest.RequiresUpdate( name, spec ):
|
||||
save_adapters()
|
||||
|
|
@ -692,8 +705,8 @@ def ExtractZipTo( file_path, destination, format ):
|
|||
CheckCall( [ 'tar', 'zxvf', file_path ] )
|
||||
|
||||
|
||||
def MakeExtensionSymlink( name, root ):
|
||||
MakeSymlink( name, os.path.join( root, 'extension' ) ),
|
||||
def MakeExtensionSymlink( name, root, extension_path = 'extension' ):
|
||||
MakeSymlink( name, os.path.join( root, extension_path ) ),
|
||||
|
||||
|
||||
def MakeSymlink( link, pointing_to, in_folder = None ):
|
||||
|
|
|
|||
|
|
@ -32,8 +32,9 @@ class TabBuffer( object ):
|
|||
BUFFER_MAP = {
|
||||
'console': 'Console',
|
||||
'stdout': 'Console',
|
||||
'output': 'Console',
|
||||
'stderr': 'stderr',
|
||||
'telemetry': 'Telemetry',
|
||||
'telemetry': None,
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -64,8 +65,11 @@ class OutputView( object ):
|
|||
self._api_prefix = api_prefix
|
||||
VIEWS.add( self )
|
||||
|
||||
def Print( self, categroy, text ):
|
||||
self._Print( 'server', text.splitlines() )
|
||||
def Print( self, category, text: typing.Union[ str, list ] ):
|
||||
if not isinstance( text, list ):
|
||||
text = text.splitlines()
|
||||
|
||||
self._Print( category, text )
|
||||
|
||||
def OnOutput( self, event ):
|
||||
category = CategoryToBuffer( event.get( 'category' ) or 'output' )
|
||||
|
|
@ -77,6 +81,10 @@ class OutputView( object ):
|
|||
self._Print( category, text_lines )
|
||||
|
||||
def _Print( self, category, text_lines ):
|
||||
if category is None:
|
||||
# This category is supressed
|
||||
return
|
||||
|
||||
if category not in self._buffers:
|
||||
self._CreateBuffer( category )
|
||||
|
||||
|
|
@ -100,13 +108,26 @@ class OutputView( object ):
|
|||
|
||||
def Clear( self ):
|
||||
for category, tab_buffer in self._buffers.items():
|
||||
if tab_buffer.is_job:
|
||||
utils.CleanUpCommand( category, self._api_prefix )
|
||||
utils.CleanUpHiddenBuffer( tab_buffer.buf )
|
||||
self._CleanUpBuffer( category, tab_buffer )
|
||||
|
||||
# FIXME: nunmenu the WinBar ?
|
||||
self._buffers = {}
|
||||
|
||||
|
||||
def ClearCategory( self, category: str ):
|
||||
if category not in self._buffers:
|
||||
return
|
||||
|
||||
self._CleanUpBuffer( category, self._buffers[ category ] )
|
||||
|
||||
|
||||
def _CleanUpBuffer( self, category: str, tab_buffer: TabBuffer ):
|
||||
if tab_buffer.is_job:
|
||||
utils.CleanUpCommand( category, self._api_prefix )
|
||||
|
||||
utils.CleanUpHiddenBuffer( tab_buffer.buf )
|
||||
|
||||
|
||||
def WindowIsValid( self ):
|
||||
return self._window.valid
|
||||
|
||||
|
|
@ -210,6 +231,9 @@ class OutputView( object ):
|
|||
utils.CleanUpHiddenBuffer( buf_to_delete )
|
||||
|
||||
def _RenderWinBar( self, category ):
|
||||
if not utils.UseWinBar():
|
||||
return
|
||||
|
||||
if not self._window.valid:
|
||||
return
|
||||
|
||||
|
|
@ -227,7 +251,7 @@ class OutputView( object ):
|
|||
raise
|
||||
|
||||
vim.command(
|
||||
"nnoremenu 1.{0} WinBar.{1}{2} "
|
||||
"nnoremenu <silent> 1.{0} WinBar.{1}{2} "
|
||||
":call vimspector#ShowOutputInWindow( {3}, '{1}' )<CR>".format(
|
||||
tab_buffer.index,
|
||||
utils.Escape( category ),
|
||||
|
|
@ -248,7 +272,8 @@ class DAPOutputView( OutputView ):
|
|||
|
||||
self._connection = None
|
||||
for b in set( BUFFER_MAP.values() ):
|
||||
self._CreateBuffer( b )
|
||||
if b is not None:
|
||||
self._CreateBuffer( b )
|
||||
|
||||
self.AddLogFileView()
|
||||
self._ShowOutput( 'Console' )
|
||||
|
|
@ -260,14 +285,18 @@ class DAPOutputView( OutputView ):
|
|||
# Don't clear because output is probably still useful
|
||||
self._connection = None
|
||||
|
||||
def Evaluate( self, frame, expression ):
|
||||
self._Print( 'Console', [ 'Evaluating: ' + expression ] )
|
||||
def Evaluate( self, frame, expression, verbose ):
|
||||
if verbose:
|
||||
self._Print( 'Console', f"Evaluating: { expression }" )
|
||||
|
||||
def print_result( message ):
|
||||
result = message[ 'body' ][ 'result' ]
|
||||
if result is None:
|
||||
result = '<no result>'
|
||||
self._Print( 'Console', f' Result: { result }' )
|
||||
self._Print( 'Console', result.splitlines() )
|
||||
|
||||
def print_failure( reason, msg ):
|
||||
self._Print( 'Console', reason.splitlines() )
|
||||
|
||||
request = {
|
||||
'command': 'evaluate',
|
||||
|
|
@ -280,4 +309,6 @@ class DAPOutputView( OutputView ):
|
|||
if frame:
|
||||
request[ 'arguments' ][ 'frameId' ] = frame[ 'id' ]
|
||||
|
||||
self._connection.DoRequest( print_result, request )
|
||||
self._connection.DoRequest( print_result,
|
||||
request,
|
||||
print_failure )
|
||||
|
|
|
|||
|
|
@ -20,23 +20,50 @@ from vimspector import utils
|
|||
|
||||
DEFAULTS = {
|
||||
# UI
|
||||
'bottombar_height': 10,
|
||||
'sidebar_width': 50,
|
||||
'code_minwidth': 82,
|
||||
'terminal_maxwidth': 80,
|
||||
'terminal_minwidth': 10,
|
||||
'ui_mode': 'auto',
|
||||
'bottombar_height': 10,
|
||||
|
||||
# For ui_mode = 'horizontal':
|
||||
'sidebar_width': 50,
|
||||
'code_minwidth': 82,
|
||||
'terminal_maxwidth': 80,
|
||||
'terminal_minwidth': 10,
|
||||
|
||||
# For ui_mode = 'vertical':
|
||||
'topbar_height': 15,
|
||||
'code_minheight': 20,
|
||||
'terminal_maxheight': 15,
|
||||
'terminal_minheight': 5,
|
||||
|
||||
# Signs
|
||||
'sign_priority': {
|
||||
'vimspectorPC': 200,
|
||||
'vimspectorPCBP': 200,
|
||||
'vimspectorBP': 9,
|
||||
'vimspectorBPCond': 9,
|
||||
'vimspectorBPDisabled': 9,
|
||||
'vimspectorPC': 200,
|
||||
'vimspectorPCBP': 200,
|
||||
'vimspectorBP': 9,
|
||||
'vimspectorBPCond': 9,
|
||||
'vimspectorBPDisabled': 9,
|
||||
'vimspectorCurrentThread': 200,
|
||||
'vimspectorCurrentFrame': 200,
|
||||
},
|
||||
|
||||
# Installer
|
||||
'install_gadgets': [],
|
||||
|
||||
# Mappings
|
||||
'mappings': {
|
||||
'variables': {
|
||||
'expand_collapse': [ '<CR>', '<2-LeftMouse>' ],
|
||||
'delete': [ '<Del>' ],
|
||||
'set_value': [ '<C-CR>', '<leader><CR>' ]
|
||||
},
|
||||
'stack_trace': {
|
||||
'expand_or_jump': [ '<CR>', '<2-LeftMouse>' ],
|
||||
'focus_thread': [ '<leader><CR>' ],
|
||||
}
|
||||
},
|
||||
|
||||
# Custom
|
||||
'java_hotcodereplace_mode': 'ask',
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -68,9 +95,44 @@ if hasattr( vim, 'Dictionary' ):
|
|||
DICT_TYPE = vim.Dictionary
|
||||
|
||||
|
||||
def Dict( option: str ):
|
||||
d = DICT_TYPE( DEFAULTS.get( option, {} ) )
|
||||
d.update( utils.GetVimValue( vim.vars,
|
||||
f'vimspector_{ option }',
|
||||
{} ) )
|
||||
return d
|
||||
def Dict( option ):
|
||||
return _UpdateDict( DICT_TYPE( DEFAULTS.get( option, {} ) ),
|
||||
vim.vars.get( f'vimspector_{ option }', DICT_TYPE() ) )
|
||||
|
||||
|
||||
def _UpdateDict( target, override ):
|
||||
"""Apply the updates in |override| to the dict |target|. This is like
|
||||
dict.update, but recursive. i.e. if the existing element is a dict, then
|
||||
override elements of the sub-dict rather than wholesale replacing.
|
||||
e.g.
|
||||
UpdateDict(
|
||||
{
|
||||
'outer': { 'inner': { 'key': 'oldValue', 'existingKey': True } }
|
||||
},
|
||||
{
|
||||
'outer': { 'inner': { 'key': 'newValue' } },
|
||||
'newKey': { 'newDict': True },
|
||||
}
|
||||
)
|
||||
yields:
|
||||
{
|
||||
'outer': {
|
||||
'inner': {
|
||||
'key': 'newValue',
|
||||
'existingKey': True
|
||||
}
|
||||
},
|
||||
'newKey': { newDict: True }
|
||||
}
|
||||
"""
|
||||
|
||||
for key, value in override.items():
|
||||
current_value = target.get( key )
|
||||
if not isinstance( current_value, DICT_TYPE ):
|
||||
target[ key ] = value
|
||||
elif isinstance( value, DICT_TYPE ):
|
||||
target[ key ] = _UpdateDict( current_value, value )
|
||||
else:
|
||||
target[ key ] = value
|
||||
|
||||
return target
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ def DefineSign( name, text, double_text, texthl, col = 'right', **kwargs ):
|
|||
vim.command( cmd )
|
||||
|
||||
|
||||
def PlaceSign( sign_id, group, name, file, line ):
|
||||
def PlaceSign( sign_id, group, name, file_name, line ):
|
||||
priority = settings.Dict( 'sign_priority' )[ name ]
|
||||
|
||||
cmd = ( f'sign place { sign_id } '
|
||||
|
|
@ -37,7 +37,7 @@ def PlaceSign( sign_id, group, name, file, line ):
|
|||
f'name={ name } '
|
||||
f'priority={ priority } '
|
||||
f'line={ line } '
|
||||
f'file={ file }' )
|
||||
f'file={ file_name }' )
|
||||
|
||||
vim.command( cmd )
|
||||
|
||||
|
|
|
|||
|
|
@ -16,11 +16,75 @@
|
|||
import vim
|
||||
import os
|
||||
import logging
|
||||
import typing
|
||||
|
||||
from vimspector import utils
|
||||
from vimspector import utils, signs, settings
|
||||
|
||||
|
||||
class Thread:
|
||||
"""The state of a single thread."""
|
||||
PAUSED = 0
|
||||
RUNNING = 1
|
||||
TERMINATED = 3
|
||||
state = RUNNING
|
||||
|
||||
stopped_event: typing.Dict
|
||||
thread: typing.Dict
|
||||
stacktrace: typing.List[ typing.Dict ]
|
||||
id: str
|
||||
|
||||
def __init__( self, thread ):
|
||||
self.id = thread[ 'id' ]
|
||||
self.stopped_event = None
|
||||
self.Update( thread )
|
||||
|
||||
def Update( self, thread ):
|
||||
self.thread = thread
|
||||
self.stacktrace = None
|
||||
|
||||
def Paused( self, event ):
|
||||
self.state = Thread.PAUSED
|
||||
self.stopped_event = event
|
||||
|
||||
def Continued( self ):
|
||||
self.state = Thread.RUNNING
|
||||
self.stopped_event = None
|
||||
self.Collapse()
|
||||
|
||||
def Exited( self ):
|
||||
self.state = Thread.TERMINATED
|
||||
self.stopped_event = None
|
||||
|
||||
def State( self ):
|
||||
if self.state == Thread.PAUSED:
|
||||
return self.stopped_event.get( 'description' ) or 'paused'
|
||||
elif self.state == Thread.RUNNING:
|
||||
return 'running'
|
||||
return 'terminated'
|
||||
|
||||
def Expand( self, stack_trace ):
|
||||
self.stacktrace = stack_trace
|
||||
|
||||
def Collapse( self ):
|
||||
self.stacktrace = None
|
||||
|
||||
def IsExpanded( self ):
|
||||
return self.stacktrace is not None
|
||||
|
||||
def CanExpand( self ):
|
||||
return self.state == Thread.PAUSED
|
||||
|
||||
|
||||
class StackTraceView( object ):
|
||||
class ThreadRequestState:
|
||||
NO = 0
|
||||
REQUESTING = 1
|
||||
PENDING = 2
|
||||
|
||||
# FIXME: Make into a dict by id ?
|
||||
_threads: typing.List[ Thread ]
|
||||
_line_to_thread = typing.Dict[ int, Thread ]
|
||||
|
||||
def __init__( self, session, win ):
|
||||
self._logger = logging.getLogger( __name__ )
|
||||
utils.SetUpLogging( self._logger )
|
||||
|
|
@ -37,25 +101,55 @@ class StackTraceView( object ):
|
|||
self._sources = {}
|
||||
self._scratch_buffers = []
|
||||
|
||||
# FIXME: This ID is by group, so should be module scope
|
||||
self._current_thread_sign_id = 0 # 1 when used
|
||||
self._current_frame_sign_id = 0 # 2 when used
|
||||
|
||||
utils.SetUpHiddenBuffer( self._buf, 'vimspector.StackTrace' )
|
||||
utils.SetUpUIWindow( win )
|
||||
|
||||
vim.command( 'nnoremap <silent> <buffer> <CR> '
|
||||
':<C-U>call vimspector#GoToFrame()<CR>' )
|
||||
vim.command( 'nnoremap <silent> <buffer> <2-LeftMouse> '
|
||||
':<C-U>call vimspector#GoToFrame()<CR>' )
|
||||
mappings = settings.Dict( 'mappings' )[ 'stack_trace' ]
|
||||
|
||||
with utils.LetCurrentWindow( win ):
|
||||
for mapping in utils.GetVimList( mappings, 'expand_or_jump' ):
|
||||
vim.command( f'nnoremap <silent> <buffer> { mapping } '
|
||||
':<C-U>call vimspector#GoToFrame()<CR>' )
|
||||
|
||||
for mapping in utils.GetVimList( mappings, 'focus_thread' ):
|
||||
vim.command( f'nnoremap <silent> <buffer> { mapping } '
|
||||
':<C-U>call vimspector#SetCurrentThread()<CR>' )
|
||||
|
||||
if utils.UseWinBar():
|
||||
vim.command( 'nnoremenu <silent> 1.1 WinBar.Pause/Continue '
|
||||
':call vimspector#PauseContinueThread()<CR>' )
|
||||
vim.command( 'nnoremenu <silent> 1.2 WinBar.Expand/Collapse '
|
||||
':call vimspector#GoToFrame()<CR>' )
|
||||
vim.command( 'nnoremenu <silent> 1.3 WinBar.Focus '
|
||||
':call vimspector#SetCurrentThread()<CR>' )
|
||||
|
||||
win.options[ 'cursorline' ] = False
|
||||
win.options[ 'signcolumn' ] = 'auto'
|
||||
|
||||
|
||||
if not signs.SignDefined( 'vimspectorCurrentThread' ):
|
||||
signs.DefineSign( 'vimspectorCurrentThread',
|
||||
text = '▶ ',
|
||||
double_text = '▶',
|
||||
texthl = 'MatchParen',
|
||||
linehl = 'CursorLine' )
|
||||
|
||||
if not signs.SignDefined( 'vimspectorCurrentFrame' ):
|
||||
signs.DefineSign( 'vimspectorCurrentFrame',
|
||||
text = '▶ ',
|
||||
double_text = '▶',
|
||||
texthl = 'Special',
|
||||
linehl = 'CursorLine' )
|
||||
|
||||
self._line_to_frame = {}
|
||||
self._line_to_thread = {}
|
||||
|
||||
# TODO: We really need a proper state model
|
||||
#
|
||||
# AWAIT_CONNECTION -- OnServerReady / RequestThreads --> REQUESTING_THREADS
|
||||
# REQUESTING -- OnGotThreads / RequestScopes --> REQUESTING_SCOPES
|
||||
#
|
||||
# When we attach using gdbserver, this whole thing breaks because we request
|
||||
# the threads over and over and get duff data back on later threads.
|
||||
self._requesting_threads = False
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.NO
|
||||
self._pending_thread_request = None
|
||||
|
||||
|
||||
def GetCurrentThreadId( self ):
|
||||
|
|
@ -68,14 +162,22 @@ class StackTraceView( object ):
|
|||
self._current_frame = None
|
||||
self._current_thread = None
|
||||
self._current_syntax = ""
|
||||
self._threads = []
|
||||
self._threads.clear()
|
||||
self._sources = {}
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.NO
|
||||
self._pending_thread_request = None
|
||||
if self._current_thread_sign_id:
|
||||
signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' )
|
||||
self._current_thread_sign_id = 0
|
||||
if self._current_frame_sign_id:
|
||||
signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' )
|
||||
self._current_frame_sign_id = 0
|
||||
|
||||
with utils.ModifiableScratchBuffer( self._buf ):
|
||||
utils.ClearBuffer( self._buf )
|
||||
|
||||
def ConnectionUp( self, connection ):
|
||||
self._connection = connection
|
||||
self._requesting_threads = False
|
||||
|
||||
def ConnectionClosed( self ):
|
||||
self.Clear()
|
||||
|
|
@ -86,47 +188,95 @@ class StackTraceView( object ):
|
|||
utils.CleanUpHiddenBuffer( self._buf )
|
||||
for b in self._scratch_buffers:
|
||||
utils.CleanUpHiddenBuffer( b )
|
||||
|
||||
self._scratch_buffers = []
|
||||
self._buf = None
|
||||
|
||||
def LoadThreads( self, infer_current_frame ):
|
||||
pending_request = False
|
||||
if self._requesting_threads:
|
||||
pending_request = True
|
||||
def LoadThreads( self,
|
||||
infer_current_frame,
|
||||
reason = '',
|
||||
stopEvent = None ):
|
||||
if self._requesting_threads != StackTraceView.ThreadRequestState.NO:
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.PENDING
|
||||
self._pending_thread_request = ( infer_current_frame,
|
||||
reason,
|
||||
stopEvent )
|
||||
return
|
||||
|
||||
def consume_threads( message ):
|
||||
self._requesting_threads = False
|
||||
requesting = False
|
||||
if self._requesting_threads == StackTraceView.ThreadRequestState.PENDING:
|
||||
# We may have hit a thread event, so try again.
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.NO
|
||||
self.LoadThreads( *self._pending_thread_request )
|
||||
requesting = True
|
||||
|
||||
if not message[ 'body' ][ 'threads' ]:
|
||||
if pending_request:
|
||||
# We may have hit a thread event, so try again.
|
||||
self.LoadThreads( infer_current_frame )
|
||||
return
|
||||
else:
|
||||
# This is a protocol error. It is required to return at least one!
|
||||
utils.UserMessage( 'Server returned no threads. Is it running?',
|
||||
persist = True )
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.NO
|
||||
self._pending_thread_request = None
|
||||
|
||||
if not ( message.get( 'body' ) or {} ).get( 'threads' ):
|
||||
# This is a protocol error. It is required to return at least one!
|
||||
utils.UserMessage( 'Protocol error: Server returned no threads',
|
||||
persist = False,
|
||||
error = True )
|
||||
return
|
||||
|
||||
existing_threads = self._threads[ : ]
|
||||
self._threads.clear()
|
||||
|
||||
for thread in message[ 'body' ][ 'threads' ]:
|
||||
if stopEvent is not None:
|
||||
stoppedThreadId = stopEvent.get( 'threadId' )
|
||||
allThreadsStopped = stopEvent.get( 'allThreadsStopped', False )
|
||||
|
||||
# FIXME: This is horribly inefficient
|
||||
for t in message[ 'body' ][ 'threads' ]:
|
||||
thread = None
|
||||
for existing_thread in existing_threads:
|
||||
if existing_thread.id == t[ 'id' ]:
|
||||
thread = existing_thread
|
||||
thread.Update( t )
|
||||
break
|
||||
|
||||
if not thread:
|
||||
thread = Thread( t )
|
||||
|
||||
self._threads.append( thread )
|
||||
|
||||
if infer_current_frame and thread[ 'id' ] == self._current_thread:
|
||||
self._LoadStackTrace( thread, True )
|
||||
elif infer_current_frame and self._current_thread is None:
|
||||
self._current_thread = thread[ 'id' ]
|
||||
self._LoadStackTrace( thread, True )
|
||||
# If the threads were requested due to a stopped event, update any
|
||||
# stopped thread state. Note we have to do this here (rather than in the
|
||||
# stopped event handler) because we must apply this event to any new
|
||||
# threads that are received here.
|
||||
if stopEvent:
|
||||
if allThreadsStopped:
|
||||
thread.Paused( stopEvent )
|
||||
elif stoppedThreadId is not None and thread.id == stoppedThreadId:
|
||||
thread.Paused( stopEvent )
|
||||
|
||||
self._DrawThreads()
|
||||
# If this is a stopped event, load the stack trace for the "current"
|
||||
# thread. Don't do this on other thrads requests because some servers
|
||||
# just break when that happens.
|
||||
#
|
||||
# Don't do this if we're also satisfying a cached request already (we'll
|
||||
# do it then)
|
||||
if infer_current_frame and not requesting:
|
||||
if thread.id == self._current_thread:
|
||||
if thread.CanExpand():
|
||||
self._LoadStackTrace( thread, True, reason )
|
||||
requesting = True
|
||||
elif self._current_thread is None:
|
||||
self._current_thread = thread.id
|
||||
if thread.CanExpand():
|
||||
self._LoadStackTrace( thread, True, reason )
|
||||
requesting = True
|
||||
|
||||
if not requesting:
|
||||
self._DrawThreads()
|
||||
|
||||
def failure_handler( reason, msg ):
|
||||
# Make sure we request them again if the request fails
|
||||
self._requesting_threads = False
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.NO
|
||||
self._pending_thread_request = None
|
||||
|
||||
self._requesting_threads = True
|
||||
self._requesting_threads = StackTraceView.ThreadRequestState.REQUESTING
|
||||
self._connection.DoRequest( consume_threads, {
|
||||
'command': 'threads',
|
||||
}, failure_handler )
|
||||
|
|
@ -135,26 +285,42 @@ class StackTraceView( object ):
|
|||
self._line_to_frame.clear()
|
||||
self._line_to_thread.clear()
|
||||
|
||||
if self._current_thread_sign_id:
|
||||
signs.UnplaceSign( self._current_thread_sign_id, 'VimspectorStackTrace' )
|
||||
else:
|
||||
self._current_thread_sign_id = 1
|
||||
|
||||
with utils.ModifiableScratchBuffer( self._buf ):
|
||||
utils.ClearBuffer( self._buf )
|
||||
with utils.RestoreCursorPosition():
|
||||
utils.ClearBuffer( self._buf )
|
||||
|
||||
for thread in self._threads:
|
||||
icon = '+' if '_frames' not in thread else '-'
|
||||
for thread in self._threads:
|
||||
icon = '+' if not thread.IsExpanded() else '-'
|
||||
line = utils.AppendToBuffer(
|
||||
self._buf,
|
||||
f'{icon} Thread {thread.id}: {thread.thread["name"]} '
|
||||
f'({thread.State()})' )
|
||||
|
||||
line = utils.AppendToBuffer(
|
||||
self._buf,
|
||||
'{0} Thread: {1}'.format( icon, thread[ 'name' ] ) )
|
||||
if self._current_thread == thread.id:
|
||||
signs.PlaceSign( self._current_thread_sign_id,
|
||||
'VimspectorStackTrace',
|
||||
'vimspectorCurrentThread',
|
||||
self._buf.name,
|
||||
line )
|
||||
|
||||
self._line_to_thread[ line ] = thread
|
||||
self._line_to_thread[ line ] = thread
|
||||
self._DrawStackTrace( thread )
|
||||
|
||||
self._DrawStackTrace( thread )
|
||||
def _LoadStackTrace( self,
|
||||
thread: Thread,
|
||||
infer_current_frame,
|
||||
reason = '' ):
|
||||
|
||||
def _LoadStackTrace( self, thread, infer_current_frame ):
|
||||
def consume_stacktrace( message ):
|
||||
thread[ '_frames' ] = message[ 'body' ][ 'stackFrames' ]
|
||||
thread.Expand( message[ 'body' ][ 'stackFrames' ] )
|
||||
if infer_current_frame:
|
||||
for frame in thread[ '_frames' ]:
|
||||
if self._JumpToFrame( frame ):
|
||||
for frame in thread.stacktrace:
|
||||
if self._JumpToFrame( frame, reason ):
|
||||
break
|
||||
|
||||
self._DrawThreads()
|
||||
|
|
@ -162,32 +328,113 @@ class StackTraceView( object ):
|
|||
self._connection.DoRequest( consume_stacktrace, {
|
||||
'command': 'stackTrace',
|
||||
'arguments': {
|
||||
'threadId': thread[ 'id' ],
|
||||
'threadId': thread.id,
|
||||
}
|
||||
} )
|
||||
|
||||
def ExpandFrameOrThread( self ):
|
||||
|
||||
def _GetSelectedThread( self ) -> Thread:
|
||||
if vim.current.buffer != self._buf:
|
||||
return None
|
||||
|
||||
return self._line_to_thread.get( vim.current.window.cursor[ 0 ] )
|
||||
|
||||
|
||||
def GetSelectedThreadId( self ):
|
||||
thread = self._GetSelectedThread()
|
||||
return thread.id if thread else thread
|
||||
|
||||
def _SetCurrentThread( self, thread: Thread ):
|
||||
self._current_thread = thread.id
|
||||
self._DrawThreads()
|
||||
|
||||
def SetCurrentThread( self ):
|
||||
thread = self._GetSelectedThread()
|
||||
if thread:
|
||||
self._SetCurrentThread( thread )
|
||||
elif vim.current.buffer != self._buf:
|
||||
return
|
||||
elif vim.current.window.cursor[ 0 ] in self._line_to_frame:
|
||||
thread, frame = self._line_to_frame[ vim.current.window.cursor[ 0 ] ]
|
||||
self._SetCurrentThread( thread )
|
||||
self._JumpToFrame( frame )
|
||||
else:
|
||||
utils.UserMessage( "No thread selected" )
|
||||
|
||||
current_line = vim.current.window.cursor[ 0 ]
|
||||
def ExpandFrameOrThread( self ):
|
||||
thread = self._GetSelectedThread()
|
||||
|
||||
if current_line in self._line_to_frame:
|
||||
self._JumpToFrame( self._line_to_frame[ current_line ] )
|
||||
elif current_line in self._line_to_thread:
|
||||
thread = self._line_to_thread[ current_line ]
|
||||
if '_frames' in thread:
|
||||
del thread[ '_frames' ]
|
||||
with utils.RestoreCursorPosition():
|
||||
self._DrawThreads()
|
||||
else:
|
||||
if thread:
|
||||
if thread.IsExpanded():
|
||||
thread.Collapse()
|
||||
self._DrawThreads()
|
||||
elif thread.CanExpand():
|
||||
self._LoadStackTrace( thread, False )
|
||||
else:
|
||||
utils.UserMessage( "Thread is not stopped" )
|
||||
elif vim.current.buffer != self._buf:
|
||||
return
|
||||
elif vim.current.window.cursor[ 0 ] in self._line_to_frame:
|
||||
thread, frame = self._line_to_frame[ vim.current.window.cursor[ 0 ] ]
|
||||
self._JumpToFrame( frame )
|
||||
|
||||
def _JumpToFrame( self, frame ):
|
||||
|
||||
|
||||
def _GetFrameOffset( self, delta ):
|
||||
thread: Thread
|
||||
for thread in self._threads:
|
||||
if thread.id != self._current_thread:
|
||||
continue
|
||||
|
||||
if not thread.stacktrace:
|
||||
return
|
||||
|
||||
frame_idx = None
|
||||
for index, frame in enumerate( thread.stacktrace ):
|
||||
if frame == self._current_frame:
|
||||
frame_idx = index
|
||||
break
|
||||
|
||||
if frame_idx is not None:
|
||||
target_idx = frame_idx + delta
|
||||
if target_idx >= 0 and target_idx < len( thread.stacktrace ):
|
||||
return thread.stacktrace[ target_idx ]
|
||||
|
||||
break
|
||||
|
||||
|
||||
def UpFrame( self ):
|
||||
frame = self._GetFrameOffset( 1 )
|
||||
if not frame:
|
||||
utils.UserMessage( 'Top of stack' )
|
||||
else:
|
||||
self._JumpToFrame( frame, 'up' )
|
||||
|
||||
|
||||
def DownFrame( self ):
|
||||
frame = self._GetFrameOffset( -1 )
|
||||
if not frame:
|
||||
utils.UserMessage( 'Bottom of stack' )
|
||||
else:
|
||||
self._JumpToFrame( frame, 'down' )
|
||||
|
||||
|
||||
def AnyThreadsRunning( self ):
|
||||
for thread in self._threads:
|
||||
if thread.state != Thread.TERMINATED:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def _JumpToFrame( self, frame, reason = '' ):
|
||||
def do_jump():
|
||||
if 'line' in frame and frame[ 'line' ] > 0:
|
||||
# Should this set the current _Thread_ too ? If i jump to a frame in
|
||||
# Thread 2, should that become the focussed thread ?
|
||||
self._current_frame = frame
|
||||
return self._session.SetCurrentFrame( self._current_frame )
|
||||
self._DrawThreads()
|
||||
return self._session.SetCurrentFrame( self._current_frame, reason )
|
||||
return False
|
||||
|
||||
source = frame.get( 'source' ) or {}
|
||||
|
|
@ -202,59 +449,94 @@ class StackTraceView( object ):
|
|||
else:
|
||||
return do_jump()
|
||||
|
||||
|
||||
def PauseContinueThread( self ):
|
||||
thread = self._GetSelectedThread()
|
||||
if thread is None:
|
||||
utils.UserMessage( 'No thread selected' )
|
||||
elif thread.state == Thread.PAUSED:
|
||||
self._session._connection.DoRequest(
|
||||
lambda msg: self.OnContinued( {
|
||||
'threadId': thread.id,
|
||||
'allThreadsContinued': ( msg.get( 'body' ) or {} ).get(
|
||||
'allThreadsContinued',
|
||||
True )
|
||||
} ),
|
||||
{
|
||||
'command': 'continue',
|
||||
'arguments': {
|
||||
'threadId': thread.id,
|
||||
},
|
||||
} )
|
||||
elif thread.state == Thread.RUNNING:
|
||||
self._session._connection.DoRequest( None, {
|
||||
'command': 'pause',
|
||||
'arguments': {
|
||||
'threadId': thread.id,
|
||||
},
|
||||
} )
|
||||
else:
|
||||
utils.UserMessage(
|
||||
f'Thread cannot be modified in state {thread.State()}' )
|
||||
|
||||
|
||||
def OnContinued( self, event = None ):
|
||||
threadId = None
|
||||
allThreadsContinued = True
|
||||
|
||||
if event is not None:
|
||||
threadId = event[ 'threadId' ]
|
||||
allThreadsContinued = event.get( 'allThreadsContinued', False )
|
||||
|
||||
for thread in self._threads:
|
||||
if allThreadsContinued:
|
||||
thread.Continued()
|
||||
elif thread.id == threadId:
|
||||
thread.Continued()
|
||||
break
|
||||
|
||||
self._DrawThreads()
|
||||
|
||||
def OnStopped( self, event ):
|
||||
if 'threadId' in event:
|
||||
self._current_thread = event[ 'threadId' ]
|
||||
elif event.get( 'allThreadsStopped', False ) and self._threads:
|
||||
self._current_thread = self._threads[ 0 ][ 'id' ]
|
||||
threadId = event.get( 'threadId' )
|
||||
allThreadsStopped = event.get( 'allThreadsStopped', False )
|
||||
|
||||
if self._current_thread is not None:
|
||||
for thread in self._threads:
|
||||
if thread[ 'id' ] == self._current_thread:
|
||||
self._LoadStackTrace( thread, True )
|
||||
return
|
||||
# Work out if we should change the current thread
|
||||
if threadId is not None:
|
||||
self._current_thread = threadId
|
||||
elif self._current_thread is None and allThreadsStopped and self._threads:
|
||||
self._current_thread = self._threads[ 0 ].id
|
||||
|
||||
self.LoadThreads( True )
|
||||
self.LoadThreads( True, 'stopped', event )
|
||||
|
||||
def OnThreadEvent( self, event ):
|
||||
infer_current_frame = False
|
||||
if event[ 'reason' ] == 'started' and self._current_thread is None:
|
||||
self._current_thread = event[ 'threadId' ]
|
||||
self.LoadThreads( True )
|
||||
infer_current_frame = True
|
||||
|
||||
def Continue( self ):
|
||||
if self._current_thread is None:
|
||||
utils.UserMessage( 'No current thread', persist = True )
|
||||
if event[ 'reason' ] == 'exited':
|
||||
for thread in self._threads:
|
||||
if thread.id == event[ 'threadId' ]:
|
||||
thread.Exited()
|
||||
break
|
||||
|
||||
self.LoadThreads( infer_current_frame )
|
||||
|
||||
def OnExited( self, event ):
|
||||
for thread in self._threads:
|
||||
thread.Exited()
|
||||
|
||||
def _DrawStackTrace( self, thread: Thread ):
|
||||
if not thread.IsExpanded():
|
||||
return
|
||||
|
||||
self._session._connection.DoRequest( None, {
|
||||
'command': 'continue',
|
||||
'arguments': {
|
||||
'threadId': self._current_thread,
|
||||
},
|
||||
} )
|
||||
if self._current_frame_sign_id:
|
||||
signs.UnplaceSign( self._current_frame_sign_id, 'VimspectorStackTrace' )
|
||||
else:
|
||||
self._current_frame_sign_id = 2
|
||||
|
||||
self._session.ClearCurrentFrame()
|
||||
self.LoadThreads( True )
|
||||
|
||||
def Pause( self ):
|
||||
if self._current_thread is None:
|
||||
utils.UserMessage( 'No current thread', persist = True )
|
||||
return
|
||||
|
||||
self._session._connection.DoRequest( None, {
|
||||
'command': 'pause',
|
||||
'arguments': {
|
||||
'threadId': self._current_thread,
|
||||
},
|
||||
} )
|
||||
|
||||
def _DrawStackTrace( self, thread ):
|
||||
if '_frames' not in thread:
|
||||
return
|
||||
|
||||
stackFrames = thread[ '_frames' ]
|
||||
|
||||
for frame in stackFrames:
|
||||
for frame in thread.stacktrace:
|
||||
if frame.get( 'source' ):
|
||||
source = frame[ 'source' ]
|
||||
else:
|
||||
|
|
@ -278,7 +560,15 @@ class StackTraceView( object ):
|
|||
source[ 'name' ],
|
||||
frame[ 'line' ] ) )
|
||||
|
||||
self._line_to_frame[ line ] = frame
|
||||
if ( self._current_frame is not None and
|
||||
self._current_frame[ 'id' ] == frame[ 'id' ] ):
|
||||
signs.PlaceSign( self._current_frame_sign_id,
|
||||
'VimspectorStackTrace',
|
||||
'vimspectorCurrentFrame',
|
||||
self._buf.name,
|
||||
line )
|
||||
|
||||
self._line_to_frame[ line ] = ( thread, frame )
|
||||
|
||||
def _ResolveSource( self, source, and_then ):
|
||||
source_reference = int( source[ 'sourceReference' ] )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from vimspector import utils, settings
|
||||
|
||||
import os
|
||||
import vim
|
||||
|
||||
|
||||
|
|
@ -17,17 +18,58 @@ def LaunchTerminal( api_prefix,
|
|||
else:
|
||||
term = existing_term
|
||||
|
||||
cwd = params[ 'cwd' ]
|
||||
args = params[ 'args' ]
|
||||
env = params.get( 'env', {} )
|
||||
cwd = params[ 'cwd' ] or os.getcwd()
|
||||
args = params[ 'args' ] or []
|
||||
env = params.get( 'env' ) or {}
|
||||
|
||||
term_options = {
|
||||
'vertical': 1,
|
||||
'norestore': 1,
|
||||
'cwd': cwd,
|
||||
'env': env,
|
||||
}
|
||||
|
||||
if settings.Get( 'ui_mode' ) == 'horizontal':
|
||||
# force-horizontal
|
||||
term_options[ 'vertical' ] = 1
|
||||
elif utils.GetVimValue( vim.vars[ 'vimspector_session_windows' ],
|
||||
'mode' ) == 'horizontal':
|
||||
# horizontal, which means that we should have enough space for:
|
||||
# - sidebar
|
||||
# - code min
|
||||
# - term min width
|
||||
# - + 2 vertical spaders
|
||||
# - + 3 columns for signs
|
||||
term_options[ 'vertical' ] = 1
|
||||
|
||||
# if we don't have enough space for terminal_maxwidth, then see if we have
|
||||
# enough vertically for terminal_maxheight, in which case,
|
||||
# that seems a better fit
|
||||
term_horiz_max = ( settings.Int( 'sidebar_width' ) +
|
||||
1 + 2 + 3 +
|
||||
settings.Int( 'code_minwidth' ) +
|
||||
1 + settings.Int( 'terminal_maxwidth' ) )
|
||||
term_vert_max = ( settings.Int( 'bottombar_height' ) + 1 +
|
||||
settings.Int( 'code_minheight' ) + 1 +
|
||||
settings.Int( 'terminal_minheight' ) )
|
||||
|
||||
if ( vim.options[ 'columns' ] < term_horiz_max and
|
||||
vim.options[ 'lines' ] >= term_vert_max ):
|
||||
# Looks like it, let's try that layout
|
||||
term_options[ 'vertical' ] = 0
|
||||
|
||||
|
||||
else:
|
||||
# vertical - we need enough space horizontally for the code+terminal, but we
|
||||
# may fit better with code above terminal
|
||||
term_options[ 'vertical' ] = 0
|
||||
|
||||
term_horiz_max = ( settings.Int( 'code_minwidth' ) + 3 +
|
||||
settings.Int( 'terminal_maxwidth' ) + 1 )
|
||||
|
||||
if vim.options[ 'columns' ] > term_horiz_max:
|
||||
term_options[ 'vertical' ] = 1
|
||||
|
||||
|
||||
if not window_for_start or not window_for_start.valid:
|
||||
# TOOD: Where? Maybe we should just use botright vertical ...
|
||||
window_for_start = vim.current.window
|
||||
|
|
@ -49,13 +91,23 @@ def LaunchTerminal( api_prefix,
|
|||
# If we're making a vertical split from the code window, make it no more
|
||||
# than 80 columns and no fewer than 10. Also try and keep the code window
|
||||
# at least 82 columns
|
||||
if term_options[ 'vertical' ] and not term_options.get( 'curwin', 0 ):
|
||||
if term_options.get( 'curwin', 0 ):
|
||||
pass
|
||||
elif term_options[ 'vertical' ]:
|
||||
term_options[ 'term_cols' ] = max(
|
||||
min ( int( vim.eval( 'winwidth( 0 )' ) )
|
||||
- settings.Int( 'code_minwidth' ),
|
||||
settings.Int( 'terminal_maxwidth' ) ),
|
||||
settings.Int( 'terminal_minwidth' )
|
||||
)
|
||||
else:
|
||||
term_options[ 'term_rows' ] = max(
|
||||
min ( int( vim.eval( 'winheight( 0 )' ) )
|
||||
- settings.Int( 'code_minheight' ),
|
||||
settings.Int( 'terminal_maxheight' ) ),
|
||||
settings.Int( 'terminal_minheight' )
|
||||
)
|
||||
|
||||
|
||||
buffer_number = int(
|
||||
utils.Call(
|
||||
|
|
|
|||
|
|
@ -45,14 +45,20 @@ _logger = logging.getLogger( __name__ )
|
|||
SetUpLogging( _logger )
|
||||
|
||||
|
||||
def BufferNumberForFile( file_name ):
|
||||
return int( vim.eval( "bufnr( '{0}', 1 )".format( Escape( file_name ) ) ) )
|
||||
def BufferNumberForFile( file_name, create = True ):
|
||||
return int( vim.eval( "bufnr( '{0}', {1} )".format(
|
||||
Escape( file_name ),
|
||||
int( create ) ) ) )
|
||||
|
||||
|
||||
def BufferForFile( file_name ):
|
||||
return vim.buffers[ BufferNumberForFile( file_name ) ]
|
||||
|
||||
|
||||
def BufferExists( file_name ):
|
||||
return bool( int ( vim.eval( f"bufexists( '{ Escape( file_name ) }' )" ) ) )
|
||||
|
||||
|
||||
def NewEmptyBuffer():
|
||||
bufnr = int( vim.eval( 'bufadd("")' ) )
|
||||
Call( 'bufload', bufnr )
|
||||
|
|
@ -350,20 +356,63 @@ def SelectFromList( prompt, options ):
|
|||
return None
|
||||
|
||||
|
||||
def AskForInput( prompt, default_value = None ):
|
||||
def AskForInput( prompt, default_value = None, completion = None ):
|
||||
if default_value is None:
|
||||
default_option = ''
|
||||
else:
|
||||
default_option = ", '{}'".format( Escape( default_value ) )
|
||||
default_value = ''
|
||||
|
||||
args = [ prompt, default_value ]
|
||||
|
||||
if completion is not None:
|
||||
if completion == 'expr':
|
||||
args.append( 'custom,vimspector#CompleteExpr' )
|
||||
else:
|
||||
args.append( completion )
|
||||
|
||||
with InputSave():
|
||||
try:
|
||||
return vim.eval( "input( '{}' {} )".format( Escape( prompt ),
|
||||
default_option ) )
|
||||
return Call( 'input', *args )
|
||||
except ( KeyboardInterrupt, vim.error ):
|
||||
return None
|
||||
|
||||
|
||||
CONFIRM = {}
|
||||
CONFIRM_ID = 0
|
||||
|
||||
|
||||
def ConfirmCallback( confirm_id, result ):
|
||||
try:
|
||||
handler = CONFIRM.pop( confirm_id )
|
||||
except KeyError:
|
||||
UserMessage( f"Internal error: unexpected callback id { confirm_id }",
|
||||
persist = True,
|
||||
error = True )
|
||||
return
|
||||
|
||||
handler( result )
|
||||
|
||||
|
||||
def Confirm( api_prefix,
|
||||
prompt,
|
||||
handler,
|
||||
default_value = 2,
|
||||
options: list = None,
|
||||
keys: list = None ):
|
||||
if not options:
|
||||
options = [ '(Y)es', '(N)o' ]
|
||||
if not keys:
|
||||
keys = [ 'y', 'n' ]
|
||||
|
||||
global CONFIRM_ID
|
||||
CONFIRM_ID += 1
|
||||
CONFIRM[ CONFIRM_ID ] = handler
|
||||
Call( f'vimspector#internal#{ api_prefix }popup#Confirm',
|
||||
CONFIRM_ID,
|
||||
prompt,
|
||||
options,
|
||||
default_value,
|
||||
keys )
|
||||
|
||||
|
||||
def AppendToBuffer( buf, line_or_lines, modified=False ):
|
||||
line = 1
|
||||
try:
|
||||
|
|
@ -392,8 +441,10 @@ def AppendToBuffer( buf, line_or_lines, modified=False ):
|
|||
|
||||
|
||||
|
||||
def ClearBuffer( buf ):
|
||||
def ClearBuffer( buf, modified = False ):
|
||||
buf[ : ] = None
|
||||
if not modified:
|
||||
buf.options[ 'modified' ] = False
|
||||
|
||||
|
||||
def SetBufferContents( buf, lines, modified=False ):
|
||||
|
|
@ -454,8 +505,8 @@ VAR_MATCH = re.compile(
|
|||
{(?P<braceddefault> # or An {id:default} - default param, as
|
||||
(?P<defname>[_a-z][_a-z0-9]*) # an ID
|
||||
: # then a colon
|
||||
(?P<default>(?:[^}]|\})*) # then anything up to }, or a \}
|
||||
)} | #
|
||||
(?P<default>(?:\\}|[^}])*) # then anything up to }, or a \}
|
||||
)} | # then a }
|
||||
(?P<invalid>) # or Something else - invalid
|
||||
)
|
||||
""",
|
||||
|
|
@ -483,7 +534,6 @@ def _Substitute( template, mapping ):
|
|||
if mo.group( 'braceddefault' ) is not None:
|
||||
named = mo.group( 'defname' )
|
||||
if named not in mapping:
|
||||
''
|
||||
raise MissingSubstitution(
|
||||
named,
|
||||
mo.group( 'default' ).replace( '\\}', '}' ) )
|
||||
|
|
@ -525,8 +575,11 @@ def ExpandReferencesInString( orig_s,
|
|||
if default_value is None and e.default_value is not None:
|
||||
try:
|
||||
default_value = _Substitute( e.default_value, mapping )
|
||||
except MissingSubstitution:
|
||||
default_value = e.default_value
|
||||
except MissingSubstitution as e2:
|
||||
if e2.name in calculus:
|
||||
default_value = calculus[ e2.name ]()
|
||||
else:
|
||||
default_value = e.default_value
|
||||
|
||||
mapping[ key ] = AskForInput( 'Enter value for {}: '.format( key ),
|
||||
default_value )
|
||||
|
|
@ -628,15 +681,19 @@ def ParseVariables( variables_list,
|
|||
return new_variables
|
||||
|
||||
|
||||
def DisplayBaloon( is_term, display ):
|
||||
def DisplayBalloon( is_term, display, is_hover = False ):
|
||||
if not is_term:
|
||||
display = '\n'.join( display )
|
||||
# To enable the Windows GUI to display the balloon correctly
|
||||
# Refer https://github.com/vim/vim/issues/1512#issuecomment-492070685
|
||||
vim.eval( "balloon_show( '' )" )
|
||||
display = '\n'.join( display )
|
||||
|
||||
vim.eval( "balloon_show( {0} )".format(
|
||||
json.dumps( display ) ) )
|
||||
created_win_id = int( vim.eval(
|
||||
"vimspector#internal#balloon#CreateTooltip({}, {})".format(
|
||||
int( is_hover ), json.dumps( display )
|
||||
)
|
||||
) )
|
||||
|
||||
return created_win_id
|
||||
|
||||
|
||||
def GetBufferFilepath( buf ):
|
||||
|
|
@ -697,7 +754,7 @@ def SetSyntax( current_syntax, syntax, *args ):
|
|||
syntax = ''
|
||||
|
||||
if current_syntax == syntax:
|
||||
return
|
||||
return syntax
|
||||
|
||||
# We use set syn= because just setting vim.Buffer.options[ 'syntax' ]
|
||||
# doesn't actually trigger the Syntax autocommand, and i'm not sure that
|
||||
|
|
@ -713,6 +770,28 @@ def GetBufferFiletypes( buf ):
|
|||
return ft.split( '.' )
|
||||
|
||||
|
||||
def GetVisualSelection( bufnr ):
|
||||
start_line, start_col = vim.current.buffer.mark( "<" )
|
||||
end_line, end_col = vim.current.buffer.mark( ">" )
|
||||
|
||||
|
||||
# lines are 1 based, but columns are 0 based
|
||||
# don't ask me why...
|
||||
start_line -= 1
|
||||
end_line -= 1
|
||||
|
||||
lines = vim.buffers[ bufnr ][ start_line : end_line + 1 ]
|
||||
# Do end first, in case it's on the same line as start (as doing start first
|
||||
# would change the offset)
|
||||
lines[ -1 ] = lines[ -1 ][ : end_col + 1 ]
|
||||
lines[ 0 ] = lines[ 0 ][ start_col : ]
|
||||
|
||||
_logger.debug( f'Visual selection: { lines } from '
|
||||
f'{ start_line }/{ start_col } -> { end_line }/{ end_col }' )
|
||||
|
||||
return lines
|
||||
|
||||
|
||||
def DisplaySplash( api_prefix, splash, text ):
|
||||
if splash:
|
||||
return Call( f'vimspector#internal#{api_prefix}popup#UpdateSplash',
|
||||
|
|
@ -779,3 +858,9 @@ def WindowID( window, tab=None ):
|
|||
if tab is None:
|
||||
tab = window.tabpage
|
||||
return int( Call( 'win_getid', window.number, tab.number ) )
|
||||
|
||||
|
||||
def UseWinBar():
|
||||
# Buggy neovim doesn't render correctly when the WinBar is defined:
|
||||
# https://github.com/neovim/neovim/issues/12689
|
||||
return not int( Call( 'has', 'nvim' ) )
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import logging
|
|||
from functools import partial
|
||||
import typing
|
||||
|
||||
from vimspector import utils
|
||||
from vimspector import utils, settings
|
||||
|
||||
|
||||
class Expandable:
|
||||
|
|
@ -32,8 +32,9 @@ class Expandable:
|
|||
a 'variablesReference' to be resolved by the 'variables' request. Records the
|
||||
current state expanded/collapsed. Implementations just implement
|
||||
VariablesReference to get the variables."""
|
||||
def __init__( self ):
|
||||
def __init__( self, container: 'Expandable' = None ):
|
||||
self.variables: typing.List[ 'Variable' ] = None
|
||||
self.container: Expandable = container
|
||||
# None is Falsy and represents collapsed _by default_. WHen set to False,
|
||||
# this means the user explicitly collapsed it. When True, the user expanded
|
||||
# it (or we expanded it by default).
|
||||
|
|
@ -48,6 +49,9 @@ class Expandable:
|
|||
def IsExpandable( self ):
|
||||
return self.VariablesReference() > 0
|
||||
|
||||
def IsContained( self ):
|
||||
return self.container is not None
|
||||
|
||||
@abc.abstractmethod
|
||||
def VariablesReference( self ):
|
||||
assert False
|
||||
|
|
@ -84,10 +88,16 @@ class WatchResult( Expandable ):
|
|||
self.result = result
|
||||
|
||||
|
||||
class WatchFailure( WatchResult ):
|
||||
def __init__( self, reason ):
|
||||
super().__init__( { 'result': reason } )
|
||||
self.changed = True
|
||||
|
||||
|
||||
class Variable( Expandable ):
|
||||
"""Holds one level of an expanded value tree. Also itself expandable."""
|
||||
def __init__( self, variable: dict ):
|
||||
super().__init__()
|
||||
def __init__( self, container: Expandable, variable: dict ):
|
||||
super().__init__( container = container )
|
||||
self.variable = variable
|
||||
# A new variable appearing is marked as changed
|
||||
self.changed = True
|
||||
|
|
@ -111,17 +121,48 @@ class Watch:
|
|||
self.expression = expression
|
||||
self.result = None
|
||||
|
||||
@staticmethod
|
||||
def New( frame, expression, context ):
|
||||
watch = {
|
||||
'expression': expression,
|
||||
'context': context,
|
||||
}
|
||||
if frame:
|
||||
watch[ 'frameId' ] = frame[ 'id' ]
|
||||
|
||||
return Watch( watch )
|
||||
|
||||
|
||||
class View:
|
||||
lines: typing.Dict[ int, Expandable ]
|
||||
draw: typing.Callable
|
||||
syntax: str
|
||||
|
||||
def __init__( self, win, lines, draw ):
|
||||
self.lines = lines
|
||||
self.draw = draw
|
||||
self.buf = win.buffer
|
||||
self.syntax = None
|
||||
if win is not None:
|
||||
self.buf = win.buffer
|
||||
utils.SetUpUIWindow( win )
|
||||
|
||||
utils.SetUpUIWindow( win )
|
||||
|
||||
class BufView( View ):
|
||||
def __init__( self, buf, lines, draw ):
|
||||
super().__init__( None, lines, draw )
|
||||
self.buf = buf
|
||||
|
||||
|
||||
def AddExpandMappings( mappings = None ):
|
||||
if mappings is None:
|
||||
mappings = settings.Dict( 'mappings' )[ 'variables' ]
|
||||
for mapping in utils.GetVimList( mappings, 'expand_collapse' ):
|
||||
vim.command( f'nnoremap <silent> <buffer> { mapping } '
|
||||
':<C-u>call vimspector#ExpandVariable()<CR>' )
|
||||
|
||||
for mapping in utils.GetVimList( mappings, 'set_value' ):
|
||||
vim.command( f'nnoremap <silent> <buffer> { mapping } '
|
||||
':<C-u>call vimspector#SetVariableValue()<CR>' )
|
||||
|
||||
|
||||
class VariablesView( object ):
|
||||
|
|
@ -131,19 +172,22 @@ class VariablesView( object ):
|
|||
|
||||
self._connection = None
|
||||
self._current_syntax = ''
|
||||
self._server_capabilities = None
|
||||
|
||||
def AddExpandMappings():
|
||||
vim.command( 'nnoremap <silent> <buffer> <CR> '
|
||||
':<C-u>call vimspector#ExpandVariable()<CR>' )
|
||||
vim.command( 'nnoremap <silent> <buffer> <2-LeftMouse> '
|
||||
':<C-u>call vimspector#ExpandVariable()<CR>' )
|
||||
self._variable_eval: Scope = None
|
||||
self._variable_eval_view: View = None
|
||||
|
||||
mappings = settings.Dict( 'mappings' )[ 'variables' ]
|
||||
|
||||
# Set up the "Variables" buffer in the variables_win
|
||||
self._scopes: typing.List[ Scope ] = []
|
||||
self._vars = View( variables_win, {}, self._DrawScopes )
|
||||
utils.SetUpHiddenBuffer( self._vars.buf, 'vimspector.Variables' )
|
||||
with utils.LetCurrentWindow( variables_win ):
|
||||
AddExpandMappings()
|
||||
if utils.UseWinBar():
|
||||
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
|
||||
':call vimspector#SetVariableValue()<CR>' )
|
||||
AddExpandMappings( mappings )
|
||||
|
||||
# Set up the "Watches" buffer in the watches_win (and create a WinBar in
|
||||
# there)
|
||||
|
|
@ -155,16 +199,20 @@ class VariablesView( object ):
|
|||
'vimspector#AddWatchPrompt',
|
||||
'vimspector#OmniFuncWatch' )
|
||||
with utils.LetCurrentWindow( watches_win ):
|
||||
AddExpandMappings()
|
||||
vim.command(
|
||||
'nnoremap <buffer> <DEL> :call vimspector#DeleteWatch()<CR>' )
|
||||
AddExpandMappings( mappings )
|
||||
for mapping in utils.GetVimList( mappings, 'delete' ):
|
||||
vim.command(
|
||||
f'nnoremap <buffer> { mapping } :call vimspector#DeleteWatch()<CR>' )
|
||||
|
||||
vim.command( 'nnoremenu 1.1 WinBar.New '
|
||||
':call vimspector#AddWatch()<CR>' )
|
||||
vim.command( 'nnoremenu 1.2 WinBar.Expand/Collapse '
|
||||
':call vimspector#ExpandVariable()<CR>' )
|
||||
vim.command( 'nnoremenu 1.3 WinBar.Delete '
|
||||
':call vimspector#DeleteWatch()<CR>' )
|
||||
if utils.UseWinBar():
|
||||
vim.command( 'nnoremenu <silent> 1.1 WinBar.New '
|
||||
':call vimspector#AddWatch()<CR>' )
|
||||
vim.command( 'nnoremenu <silent> 1.2 WinBar.Expand/Collapse '
|
||||
':call vimspector#ExpandVariable()<CR>' )
|
||||
vim.command( 'nnoremenu <silent> 1.3 WinBar.Delete '
|
||||
':call vimspector#DeleteWatch()<CR>' )
|
||||
vim.command( 'nnoremenu <silent> 1.1 WinBar.Set '
|
||||
':call vimspector#SetVariableValue()<CR>' )
|
||||
|
||||
# Set the (global!) balloon expr if supported
|
||||
has_balloon = int( vim.eval( "has( 'balloon_eval' )" ) )
|
||||
|
|
@ -176,7 +224,9 @@ class VariablesView( object ):
|
|||
'balloonexpr': vim.options[ 'balloonexpr' ],
|
||||
'balloondelay': vim.options[ 'balloondelay' ],
|
||||
}
|
||||
vim.options[ 'balloonexpr' ] = 'vimspector#internal#balloon#BalloonExpr()'
|
||||
vim.options[ 'balloonexpr' ] = ( "vimspector#internal#"
|
||||
"balloon#HoverTooltip()" )
|
||||
|
||||
vim.options[ 'balloondelay' ] = 250
|
||||
|
||||
if has_balloon:
|
||||
|
|
@ -194,21 +244,30 @@ class VariablesView( object ):
|
|||
utils.ClearBuffer( self._vars.buf )
|
||||
with utils.ModifiableScratchBuffer( self._watch.buf ):
|
||||
utils.ClearBuffer( self._watch.buf )
|
||||
self.ClearTooltip()
|
||||
self._current_syntax = ''
|
||||
|
||||
def ConnectionUp( self, connection ):
|
||||
self._connection = connection
|
||||
|
||||
def SetServerCapabilities( self, capabilities ):
|
||||
self._server_capabilities = capabilities
|
||||
|
||||
def ConnectionClosed( self ):
|
||||
self.Clear()
|
||||
self._connection = None
|
||||
self._server_capabilities = None
|
||||
|
||||
def Reset( self ):
|
||||
self._server_capabilities = None
|
||||
|
||||
for k, v in self._oldoptions.items():
|
||||
vim.options[ k ] = v
|
||||
|
||||
utils.CleanUpHiddenBuffer( self._vars.buf )
|
||||
utils.CleanUpHiddenBuffer( self._watch.buf )
|
||||
self.ClearTooltip()
|
||||
|
||||
|
||||
def LoadScopes( self, frame ):
|
||||
def scopes_consumer( message ):
|
||||
|
|
@ -260,15 +319,97 @@ class VariablesView( object ):
|
|||
},
|
||||
} )
|
||||
|
||||
def AddWatch( self, frame, expression ):
|
||||
watch = {
|
||||
'expression': expression,
|
||||
'context': 'watch',
|
||||
}
|
||||
if frame:
|
||||
watch[ 'frameId' ] = frame[ 'id' ]
|
||||
def _DrawBalloonEval( self ):
|
||||
watch = self._variable_eval
|
||||
view = self._variable_eval_view
|
||||
|
||||
self._watches.append( Watch( watch ) )
|
||||
with utils.RestoreCursorPosition():
|
||||
with utils.ModifiableScratchBuffer( view.buf ):
|
||||
utils.ClearBuffer( view.buf )
|
||||
view.syntax = utils.SetSyntax( view.syntax,
|
||||
self._current_syntax,
|
||||
view.buf )
|
||||
|
||||
self._DrawWatchResult( view,
|
||||
0,
|
||||
watch,
|
||||
is_short = True )
|
||||
|
||||
vim.eval( "vimspector#internal#balloon#ResizeTooltip()" )
|
||||
|
||||
def ClearTooltip( self ):
|
||||
# This will actually end up calling CleanUpTooltip via the popup close
|
||||
# callback
|
||||
vim.eval( 'vimspector#internal#balloon#Close()' )
|
||||
|
||||
def CleanUpTooltip( self ) :
|
||||
# remove reference to old tooltip window
|
||||
self._variable_eval_view = None
|
||||
vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = None
|
||||
|
||||
def VariableEval( self, frame, expression, is_hover ):
|
||||
"""Callback to display variable under cursor `:h ballonexpr`"""
|
||||
if not self._connection:
|
||||
return ''
|
||||
|
||||
def handler( message ):
|
||||
|
||||
watch = self._variable_eval
|
||||
if watch.result is None:
|
||||
watch.result = WatchResult( message[ 'body' ] )
|
||||
else:
|
||||
watch.result.Update( message[ 'body' ] )
|
||||
|
||||
popup_win_id = utils.DisplayBalloon( self._is_term, [], is_hover )
|
||||
# record the global eval window id
|
||||
vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = int( popup_win_id )
|
||||
popup_bufnr = int( vim.eval( "winbufnr({})".format( popup_win_id ) ) )
|
||||
|
||||
# We don't need to do any UI window setup here, as it's already done as
|
||||
# part of the popup creation, so just pass the buffer to the View instance
|
||||
self._variable_eval_view = BufView(
|
||||
vim.buffers[ popup_bufnr ],
|
||||
{},
|
||||
self._DrawBalloonEval
|
||||
)
|
||||
|
||||
if watch.result.IsExpandable():
|
||||
# Always expand the first level
|
||||
watch.result.expanded = Expandable.EXPANDED_BY_US
|
||||
|
||||
if watch.result.IsExpanded():
|
||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||
self._variable_eval_view.draw,
|
||||
watch.result ), {
|
||||
'command': 'variables',
|
||||
'arguments': {
|
||||
'variablesReference': watch.result.VariablesReference(),
|
||||
},
|
||||
} )
|
||||
|
||||
self._DrawBalloonEval()
|
||||
|
||||
def failure_handler( reason, message ):
|
||||
display = [ reason ]
|
||||
float_win_id = utils.DisplayBalloon( self._is_term, display, is_hover )
|
||||
# record the global eval window id
|
||||
vim.vars[ 'vimspector_session_windows' ][ 'eval' ] = int( float_win_id )
|
||||
|
||||
self._variable_eval = Watch.New( frame,
|
||||
expression,
|
||||
'hover' )
|
||||
|
||||
# Send async request
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'evaluate',
|
||||
'arguments': self._variable_eval.expression,
|
||||
}, failure_handler )
|
||||
|
||||
# Return working (meanwhile)
|
||||
return ''
|
||||
|
||||
def AddWatch( self, frame, expression ):
|
||||
self._watches.append( Watch.New( frame, expression, 'watch' ) )
|
||||
self.EvaluateWatches()
|
||||
|
||||
def DeleteWatch( self ):
|
||||
|
|
@ -295,11 +436,14 @@ class VariablesView( object ):
|
|||
|
||||
def EvaluateWatches( self ):
|
||||
for watch in self._watches:
|
||||
self._connection.DoRequest( partial( self._UpdateWatchExpression,
|
||||
watch ), {
|
||||
'command': 'evaluate',
|
||||
'arguments': watch.expression,
|
||||
} )
|
||||
self._connection.DoRequest(
|
||||
partial( self._UpdateWatchExpression, watch ),
|
||||
{
|
||||
'command': 'evaluate',
|
||||
'arguments': watch.expression,
|
||||
},
|
||||
failure_handler = lambda reason, msg, watch=watch:
|
||||
self._WatchExpressionFailed( reason, watch ) )
|
||||
|
||||
def _UpdateWatchExpression( self, watch: Watch, message: dict ):
|
||||
if watch.result is not None:
|
||||
|
|
@ -320,19 +464,42 @@ class VariablesView( object ):
|
|||
|
||||
self._DrawWatches()
|
||||
|
||||
def ExpandVariable( self ):
|
||||
if vim.current.buffer == self._vars.buf:
|
||||
def _WatchExpressionFailed( self, reason: str, watch: Watch ):
|
||||
if watch.result is not None:
|
||||
# We already have a result for this watch. Wut ?
|
||||
return
|
||||
|
||||
watch.result = WatchFailure( reason )
|
||||
self._DrawWatches()
|
||||
|
||||
def _GetVariable( self, buf = None, line_num = None ):
|
||||
none = ( None, None )
|
||||
|
||||
if buf is None:
|
||||
buf = vim.current.buffer
|
||||
|
||||
if line_num is None:
|
||||
line_num = vim.current.window.cursor[ 0 ]
|
||||
|
||||
if buf == self._vars.buf:
|
||||
view = self._vars
|
||||
elif vim.current.buffer == self._watch.buf:
|
||||
elif buf == self._watch.buf:
|
||||
view = self._watch
|
||||
elif ( self._variable_eval_view is not None
|
||||
and buf == self._variable_eval_view.buf ):
|
||||
view = self._variable_eval_view
|
||||
else:
|
||||
return
|
||||
return none
|
||||
|
||||
current_line = vim.current.window.cursor[ 0 ]
|
||||
if current_line not in view.lines:
|
||||
return
|
||||
if line_num not in view.lines:
|
||||
return none
|
||||
|
||||
variable = view.lines[ current_line ]
|
||||
return view.lines[ line_num ], view
|
||||
|
||||
def ExpandVariable( self, buf = None, line_num = None ):
|
||||
variable, view = self._GetVariable( buf, line_num )
|
||||
if variable is None:
|
||||
return
|
||||
|
||||
if variable.IsExpanded():
|
||||
# Collapse
|
||||
|
|
@ -353,25 +520,101 @@ class VariablesView( object ):
|
|||
},
|
||||
} )
|
||||
|
||||
def _DrawVariables( self, view, variables, indent ):
|
||||
def SetVariableValue( self, new_value = None, buf = None, line_num = None ):
|
||||
variable: Variable
|
||||
view: View
|
||||
|
||||
if not self._server_capabilities.get( 'supportsSetVariable' ):
|
||||
return
|
||||
|
||||
variable, view = self._GetVariable( buf, line_num )
|
||||
if variable is None:
|
||||
return
|
||||
|
||||
if not variable.IsContained():
|
||||
return
|
||||
|
||||
if new_value is None:
|
||||
new_value = utils.AskForInput( 'New Value: ',
|
||||
variable.variable.get( 'value', '' ),
|
||||
completion = 'expr' )
|
||||
|
||||
if new_value is None:
|
||||
return
|
||||
|
||||
|
||||
def handler( message ):
|
||||
# Annoyingly the response to setVariable request doesn't return a
|
||||
# Variable, but some part of it, so take a copy of the existing Variable
|
||||
# dict and update it, then call its update method with the updated copy.
|
||||
new_variable = dict( variable.variable )
|
||||
new_variable.update( message[ 'body' ] )
|
||||
|
||||
# Clear any existing known children (FIXME: Is this the right thing to do)
|
||||
variable.variables = None
|
||||
|
||||
# If the variable is expanded, re-request its children
|
||||
if variable.IsExpanded():
|
||||
self._connection.DoRequest( partial( self._ConsumeVariables,
|
||||
view.draw,
|
||||
variable ), {
|
||||
'command': 'variables',
|
||||
'arguments': {
|
||||
'variablesReference': variable.VariablesReference()
|
||||
},
|
||||
} )
|
||||
|
||||
variable.Update( new_variable )
|
||||
view.draw()
|
||||
|
||||
def failure_handler( reason, message ):
|
||||
utils.UserMessage( f'Cannot set value: { reason }', error = True )
|
||||
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'setVariable',
|
||||
'arguments': {
|
||||
'variablesReference': variable.container.VariablesReference(),
|
||||
'name': variable.variable[ 'name' ],
|
||||
'value': new_value
|
||||
},
|
||||
}, failure_handler = failure_handler )
|
||||
|
||||
|
||||
|
||||
def _DrawVariables( self, view, variables, indent, is_short = False ):
|
||||
assert indent > 0
|
||||
for variable in variables:
|
||||
line = utils.AppendToBuffer(
|
||||
view.buf,
|
||||
'{indent}{marker}{icon} {name} ({type_}): {value}'.format(
|
||||
text = ''
|
||||
if is_short:
|
||||
text = '{indent}{icon} {name}: {value}'.format(
|
||||
# We borrow 1 space of indent to draw the change marker
|
||||
indent = ' ' * ( indent - 1 ),
|
||||
icon = '+' if ( variable.IsExpandable()
|
||||
and not variable.IsExpanded() ) else '-',
|
||||
name = variable.variable.get( 'name', '' ),
|
||||
value = variable.variable.get( 'value', '<unknown>' )
|
||||
)
|
||||
else:
|
||||
text = '{indent}{marker}{icon} {name} ({type_}): {value}'.format(
|
||||
# We borrow 1 space of indent to draw the change marker
|
||||
indent = ' ' * ( indent - 1 ),
|
||||
marker = '*' if variable.changed else ' ',
|
||||
icon = '+' if ( variable.IsExpandable()
|
||||
and not variable.IsExpanded() ) else '-',
|
||||
name = variable.variable[ 'name' ],
|
||||
name = variable.variable.get( 'name', '' ),
|
||||
type_ = variable.variable.get( 'type', '' ),
|
||||
value = variable.variable.get( 'value',
|
||||
'<unknown>' ) ).split( '\n' ) )
|
||||
value = variable.variable.get( 'value', '<unknown>' )
|
||||
)
|
||||
|
||||
line = utils.AppendToBuffer(
|
||||
view.buf,
|
||||
text.split( '\n' )
|
||||
)
|
||||
|
||||
view.lines[ line ] = variable
|
||||
|
||||
if variable.ShouldDrawDrillDown():
|
||||
self._DrawVariables( view, variable.variables, indent + 2 )
|
||||
self._DrawVariables( view, variable.variables, indent + 2, is_short )
|
||||
|
||||
def _DrawScopes( self ):
|
||||
# FIXME: The drawing is dumb and draws from scratch every time. This is
|
||||
|
|
@ -398,7 +641,7 @@ class VariablesView( object ):
|
|||
'Expression: '
|
||||
+ watch.expression[ 'expression' ] )
|
||||
watch.line = line
|
||||
self._DrawWatchResult( 2, watch )
|
||||
self._DrawWatchResult( self._watch, 2, watch )
|
||||
|
||||
def _DrawScope( self, indent, scope ):
|
||||
icon = '+' if scope.IsExpandable() and not scope.IsExpanded() else '-'
|
||||
|
|
@ -414,27 +657,36 @@ class VariablesView( object ):
|
|||
indent += 2
|
||||
self._DrawVariables( self._vars, scope.variables, indent )
|
||||
|
||||
def _DrawWatchResult( self, indent, watch ):
|
||||
def _DrawWatchResult( self, view, indent, watch, is_short = False ):
|
||||
if not watch.result:
|
||||
return
|
||||
|
||||
assert indent > 0
|
||||
icon = '+' if ( watch.result.IsExpandable() and
|
||||
not watch.result.IsExpanded() ) else '-'
|
||||
assert is_short or indent > 0
|
||||
|
||||
line = '{indent}{marker}{icon} Result: {result}'.format(
|
||||
if is_short:
|
||||
# The first result is always expanded in a hover (short format)
|
||||
icon = ''
|
||||
marker = ''
|
||||
leader = ''
|
||||
else:
|
||||
icon = '+' if ( watch.result.IsExpandable() and
|
||||
not watch.result.IsExpanded() ) else '-'
|
||||
marker = '*' if watch.result.changed else ' '
|
||||
leader = ' Result: '
|
||||
|
||||
line = '{indent}{marker}{icon}{leader}{result}'.format(
|
||||
# We borrow 1 space of indent to draw the change marker
|
||||
indent = ' ' * ( indent - 1 ),
|
||||
marker = '*' if watch.result.changed else ' ',
|
||||
marker = marker,
|
||||
icon = icon,
|
||||
leader = leader,
|
||||
result = watch.result.result.get( 'result', '<unknown>' ) )
|
||||
|
||||
line = utils.AppendToBuffer( self._watch.buf, line.split( '\n' ) )
|
||||
self._watch.lines[ line ] = watch.result
|
||||
line = utils.AppendToBuffer( view.buf, line.split( '\n' ) )
|
||||
view.lines[ line ] = watch.result
|
||||
|
||||
if watch.result.ShouldDrawDrillDown():
|
||||
indent = 4
|
||||
self._DrawVariables( self._watch, watch.result.variables, indent )
|
||||
self._DrawVariables( view, watch.result.variables, indent + 2, is_short )
|
||||
|
||||
def _ConsumeVariables( self, draw, parent, message ):
|
||||
new_variables = []
|
||||
|
|
@ -449,9 +701,8 @@ class VariablesView( object ):
|
|||
variable = v
|
||||
found = True
|
||||
break
|
||||
|
||||
if not found:
|
||||
variable = Variable( variable_body )
|
||||
variable = Variable( parent, variable_body )
|
||||
else:
|
||||
variable.Update( variable_body )
|
||||
|
||||
|
|
@ -471,47 +722,10 @@ class VariablesView( object ):
|
|||
|
||||
draw()
|
||||
|
||||
def ShowBalloon( self, frame, expression ):
|
||||
"""Callback to display variable under cursor `:h ballonexpr`"""
|
||||
if not self._connection:
|
||||
return ''
|
||||
|
||||
def handler( message ):
|
||||
# TODO: this result count be expandable, but we have no way to allow the
|
||||
# user to interact with the balloon to expand it, unless we use a popup
|
||||
# instead, but even then we don't really want to trap the cursor.
|
||||
body = message[ 'body' ]
|
||||
result = body[ 'result' ]
|
||||
if result is None:
|
||||
result = 'null'
|
||||
display = [
|
||||
'Type: ' + body.get( 'type', '<unknown>' ),
|
||||
'Value: ' + result
|
||||
]
|
||||
utils.DisplayBaloon( self._is_term, display )
|
||||
|
||||
def failure_handler( reason, message ):
|
||||
display = [ reason ]
|
||||
utils.DisplayBaloon( self._is_term, display )
|
||||
|
||||
# Send async request
|
||||
self._connection.DoRequest( handler, {
|
||||
'command': 'evaluate',
|
||||
'arguments': {
|
||||
'expression': expression,
|
||||
'frameId': frame[ 'id' ],
|
||||
'context': 'hover',
|
||||
}
|
||||
}, failure_handler )
|
||||
|
||||
# Return working (meanwhile)
|
||||
return '...'
|
||||
|
||||
|
||||
def SetSyntax( self, syntax ):
|
||||
# TODO: Switch to View.syntax
|
||||
self._current_syntax = utils.SetSyntax( self._current_syntax,
|
||||
syntax,
|
||||
self._vars.buf,
|
||||
self._watch.buf )
|
||||
|
||||
# vim: sw=2
|
||||
|
|
|
|||
12
run_tests
12
run_tests
|
|
@ -21,7 +21,7 @@ out_fd=1
|
|||
|
||||
while [ -n "$1" ]; do
|
||||
case "$1" in
|
||||
"--basedir")
|
||||
"--basedir"|"--base-dir"|"--test-base")
|
||||
shift
|
||||
SetBaseDir $1
|
||||
shift
|
||||
|
|
@ -36,7 +36,7 @@ while [ -n "$1" ]; do
|
|||
INSTALL=$1
|
||||
shift
|
||||
;;
|
||||
"--update")
|
||||
"--update"|"--upgrade")
|
||||
UPDATE=1
|
||||
shift
|
||||
;;
|
||||
|
|
@ -91,7 +91,8 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "script" ]; then
|
|||
if ! python3 $(dirname $0)/install_gadget.py \
|
||||
--basedir ${BASEDIR} \
|
||||
${INSTALLER_ARGS} \
|
||||
--all; then
|
||||
--all \
|
||||
--force-enable-csharp; then
|
||||
echo "Script installation reported errors" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -102,7 +103,7 @@ if [ "$INSTALL" = "1" ] || [ "$INSTALL" = "vim" ]; then
|
|||
--cmd "${BASEDIR_CMD}" \
|
||||
-c 'autocmd User VimspectorInstallSuccess qa!' \
|
||||
-c 'autocmd User VimspectorInstallFailed cquit!' \
|
||||
-c "VimspectorInstall --all"; then
|
||||
-c "VimspectorInstall --all netcoredbg"; then
|
||||
echo "Vim installation reported errors" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
|
@ -144,6 +145,9 @@ set -e
|
|||
pushd tests/testdata/cpp/simple
|
||||
make clean all
|
||||
popd
|
||||
pushd support/test/csharp
|
||||
dotnet build
|
||||
popd
|
||||
set +e
|
||||
echo "%DONE - built test programs"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,12 @@
|
|||
" setup boilerplate to make this file usable with vim -Nu <tihs file> {{{
|
||||
scriptencoding utf-8
|
||||
execute 'source' expand( '<sfile>:p:h' ) . '/minimal_vimrc'
|
||||
set noequalalways
|
||||
let mapleader = ','
|
||||
let maplocalleader = "\<Space>"
|
||||
" }}}
|
||||
|
||||
" Custom Layout {{{
|
||||
|
||||
function! s:CustomiseUI()
|
||||
let wins = g:vimspector_session_windows
|
||||
|
|
@ -31,6 +38,10 @@ function! s:CustomiseUI()
|
|||
endfunction
|
||||
|
||||
function s:SetUpTerminal()
|
||||
if !has_key( g:vimspector_session_windows, 'terminal' )
|
||||
" There's a neovim bug which means that this doesn't work in neovim
|
||||
return
|
||||
endif
|
||||
let terminal_win = g:vimspector_session_windows.terminal
|
||||
|
||||
" Make the terminal window at most 80 columns wide, ensuring there is enough
|
||||
|
|
@ -43,7 +54,7 @@ function s:SetUpTerminal()
|
|||
let padding = 4
|
||||
let cols = max( [ min( [ &columns - left_bar - code - padding, 80 ] ), 10 ] )
|
||||
call win_gotoid( terminal_win )
|
||||
execute cols . 'wincmd |'
|
||||
execute string(cols) . 'wincmd |'
|
||||
endfunction
|
||||
|
||||
function! s:CustomiseWinBar()
|
||||
|
|
@ -66,9 +77,85 @@ augroup TestUICustomistaion
|
|||
autocmd User VimspectorUICreated call s:CustomiseWinBar()
|
||||
augroup END
|
||||
|
||||
" }}}
|
||||
|
||||
" Custom sign priority {{{
|
||||
|
||||
let g:vimspector_sign_priority = {
|
||||
\ 'vimspectorBP': 3,
|
||||
\ 'vimspectorBPCond': 2,
|
||||
\ 'vimspectorBPDisabled': 1,
|
||||
\ 'vimspectorPC': 999,
|
||||
\ }
|
||||
|
||||
" }}}
|
||||
|
||||
" Custom mappings while debuggins {{{
|
||||
let s:mapped = {}
|
||||
|
||||
function! s:OnJumpToFrame() abort
|
||||
if has_key( s:mapped, string( bufnr() ) )
|
||||
return
|
||||
endif
|
||||
|
||||
nmap <silent> <buffer> <LocalLeader>dn <Plug>VimspectorStepOver
|
||||
nmap <silent> <buffer> <LocalLeader>ds <Plug>VimspectorStepInto
|
||||
nmap <silent> <buffer> <LocalLeader>df <Plug>VimspectorStepOut
|
||||
nmap <silent> <buffer> <LocalLeader>dc <Plug>VimspectorContinue
|
||||
nmap <silent> <buffer> <LocalLeader>di <Plug>VimspectorBalloonEval
|
||||
xmap <silent> <buffer> <LocalLeader>di <Plug>VimspectorBalloonEval
|
||||
|
||||
let s:mapped[ string( bufnr() ) ] = { 'modifiable': &modifiable }
|
||||
|
||||
setlocal nomodifiable
|
||||
|
||||
endfunction
|
||||
|
||||
function! s:OnDebugEnd() abort
|
||||
|
||||
let original_buf = bufnr()
|
||||
let hidden = &hidden
|
||||
|
||||
try
|
||||
set hidden
|
||||
for bufnr in keys( s:mapped )
|
||||
try
|
||||
execute 'noautocmd buffer' bufnr
|
||||
silent! nunmap <buffer> <LocalLeader>dn
|
||||
silent! nunmap <buffer> <LocalLeader>ds
|
||||
silent! nunmap <buffer> <LocalLeader>df
|
||||
silent! nunmap <buffer> <LocalLeader>dc
|
||||
silent! nunmap <buffer> <LocalLeader>di
|
||||
silent! xunmap <buffer> <LocalLeader>di
|
||||
|
||||
let &l:modifiable = s:mapped[ bufnr ][ 'modifiable' ]
|
||||
endtry
|
||||
endfor
|
||||
finally
|
||||
execute 'noautocmd buffer' original_buf
|
||||
let &hidden = hidden
|
||||
endtry
|
||||
|
||||
let s:mapped = {}
|
||||
endfunction
|
||||
|
||||
augroup TestCustomMappings
|
||||
au!
|
||||
autocmd User VimspectorJumpedToFrame call s:OnJumpToFrame()
|
||||
autocmd User VimspectorDebugEnded call s:OnDebugEnd()
|
||||
augroup END
|
||||
|
||||
" }}}
|
||||
|
||||
" Custom mappings for special buffers {{{
|
||||
|
||||
let g:vimspector_mappings = {
|
||||
\ 'stack_trace': {},
|
||||
\ 'variables': {
|
||||
\ 'set_value': [ '<Tab>', '<C-CR>', 'C' ],
|
||||
\ }
|
||||
\ }
|
||||
|
||||
" }}}
|
||||
|
||||
" vim: foldmethod=marker
|
||||
|
|
|
|||
8
support/gadget_upgrade/README.md
Normal file
8
support/gadget_upgrade/README.md
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Manually updating shipped gadgets
|
||||
|
||||
Download the gadget files manuall from their official source into this dir.
|
||||
Run `./checksum.py <list of files>` to get the checksums.
|
||||
|
||||
Update ../../python3/vimspector/gadgets.py with the new version and the
|
||||
checksums.
|
||||
|
||||
13
support/gadget_upgrade/checksum.py
Executable file
13
support/gadget_upgrade/checksum.py
Executable file
|
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import hashlib
|
||||
import sys
|
||||
|
||||
|
||||
def GetChecksumSHA254( file_path ):
|
||||
with open( file_path, 'rb' ) as existing_file:
|
||||
return hashlib.sha256( existing_file.read() ).hexdigest()
|
||||
|
||||
|
||||
for arg in sys.argv[ 1: ]:
|
||||
print( f"{ arg } = { GetChecksumSHA254( arg ) }" )
|
||||
15
support/test/bash/.vimspector.json
Normal file
15
support/test/bash/.vimspector.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json",
|
||||
"configurations": {
|
||||
"Run Current Script": {
|
||||
"adapter": "vscode-bash",
|
||||
"autoselect": false,
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"cwd": "${fileDirname}",
|
||||
"args": [ "*${args}" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,29 @@
|
|||
{
|
||||
"configurations": {
|
||||
"simple_c_program - Launch": {
|
||||
"adapter": "vscode-cpptools",
|
||||
"CodeLLDB": {
|
||||
"adapter": "CodeLLDB",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/test",
|
||||
"stopAtEntry": true
|
||||
}
|
||||
},
|
||||
"lldb-vscode": {
|
||||
"adapter": "lldb-vscode",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/test",
|
||||
"stopAtEntry": true
|
||||
}
|
||||
},
|
||||
"cpptools": {
|
||||
"adapter": "vscode-cpptools",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/test",
|
||||
"stopOnEntry": true,
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
def Settings( **kwargs ):
|
||||
return {
|
||||
'flags': [ '-x', 'c++', '-Wall', '-Wextra' ]
|
||||
'flags': [ '-x', 'c++', '-Wall', '-Wextra', '-std=c++17' ]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
namespace Test
|
||||
|
|
@ -33,6 +35,8 @@ int main ( int argc, char ** argv )
|
|||
{
|
||||
int x{ 10 };
|
||||
|
||||
printf( "HOME: %s\n", getenv( "HOME" ) );
|
||||
|
||||
Test::TestStruct t{ true, {99} };
|
||||
foo( t );
|
||||
}
|
||||
|
|
|
|||
1
support/test/csharp/.gitignore
vendored
1
support/test/csharp/.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
bin/
|
||||
obj/Debug
|
||||
obj/
|
||||
|
|
|
|||
|
|
@ -1,21 +1,57 @@
|
|||
{
|
||||
"configurations": {
|
||||
"launch - netcoredbg": {
|
||||
"adapter": "netcoredbg",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/Debug/netcoreapp2.2/csharp.dll",
|
||||
"args": [],
|
||||
"stopAtEntry": true
|
||||
}
|
||||
"adapters": {
|
||||
"netcoredbg-debuglog": {
|
||||
"attach": {
|
||||
"pidProperty": "processId",
|
||||
"pidSelect": "ask"
|
||||
},
|
||||
"launch - mono": {
|
||||
"adapter": "vscode-mono-debug",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/Program.exe"
|
||||
}
|
||||
"command": [
|
||||
"${gadgetDir}/netcoredbg/netcoredbg",
|
||||
"--interpreter=vscode",
|
||||
"--engineLogging=${workspaceRoot}/netcoredbg.engine.log",
|
||||
"--log=${workspaceRoot}/netcoredbg.log"
|
||||
],
|
||||
"configuration": {
|
||||
"cwd": "${workspaceRoot}"
|
||||
},
|
||||
"name": "netcoredbg"
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
//
|
||||
// NOTE:
|
||||
// If you add to this, you must update tests/get_configurations.test.vim
|
||||
//
|
||||
|
||||
"launch - netcoredbg": {
|
||||
"adapter": "netcoredbg",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll",
|
||||
"args": [],
|
||||
"stopAtEntry": false
|
||||
}
|
||||
},
|
||||
"launch - netcoredbg - with debug log": {
|
||||
"adapter": "netcoredbg-debuglog",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/bin/Debug/netcoreapp3.1/csharp.dll",
|
||||
"args": [],
|
||||
"stopAtEntry": false
|
||||
}
|
||||
},
|
||||
"launch - mono": {
|
||||
"adapter": "vscode-mono-debug",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/Program.exe",
|
||||
"console": "integratedTerminal",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"args": [],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,36 @@
|
|||
|
||||
namespace csharp
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello World!");
|
||||
}
|
||||
class Program
|
||||
{
|
||||
string toaster = "Making round of toast";
|
||||
static int max_bread = 100;
|
||||
int bread = max_bread;
|
||||
|
||||
void PrintToast( int r ) {
|
||||
int this_round = ( max_bread - bread - r);
|
||||
Console.WriteLine( this.toaster + ": " + this_round );
|
||||
}
|
||||
|
||||
void MakeToast( int rounds ) {
|
||||
if (this.bread - rounds < 0) {
|
||||
throw new Exception( "No moar bread!" );
|
||||
}
|
||||
|
||||
this.bread -= rounds;
|
||||
for (int r = 0; r < rounds; ++r) {
|
||||
this.PrintToast( r );
|
||||
}
|
||||
|
||||
Console.WriteLine( "Got only " + this.bread + " left" );
|
||||
}
|
||||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Program p = new Program();
|
||||
for (int x = 1; x < 10; ++ x) {
|
||||
p.MakeToast( x );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26124.0
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csharp", "csharp.csproj", "{91DB205F-E422-430B-BBB8-955110C7B3B6}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -15,4 +17,18 @@ Global
|
|||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x64.Build.0 = Release|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{91DB205F-E422-430B-BBB8-955110C7B3B6}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
|||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"version": 1,
|
||||
"dgSpecHash": "6/vdr7YprlSIoQecv/nNuLNflFpO0X7eN7jHUinZTsgian9nYpmHMWirsDWMi5l+29TH+Qy8O/QfaB/48QtjRQ==",
|
||||
"success": true
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
|
||||
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
|
||||
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">/Users/ben/.vim/bundle/vimspector/support/test/csharp/obj/project.assets.json</ProjectAssetsFile>
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">/Users/ben/.nuget/packages/</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">/Users/ben/.nuget/packages/;/usr/local/share/dotnet/sdk/NuGetFallbackFolder</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.9.4</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.props" Condition="Exists('/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.props')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="/usr/local/share/dotnet/sdk/NuGetFallbackFolder/netstandard.library/2.0.3/build/netstandard2.0/NETStandard.Library.targets" Condition="Exists('/usr/local/share/dotnet/sdk/NuGetFallbackFolder/netstandard.library/2.0.3/build/netstandard2.0/NETStandard.Library.targets')" />
|
||||
<Import Project="/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.targets" Condition="Exists('/usr/local/share/dotnet/sdk/NuGetFallbackFolder/microsoft.netcore.app/2.2.0/build/netcoreapp2.2/Microsoft.NETCore.App.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
|
|
@ -1,742 +0,0 @@
|
|||
{
|
||||
"version": 3,
|
||||
"targets": {
|
||||
".NETCoreApp,Version=v2.2": {
|
||||
"Microsoft.NETCore.App/2.2.0": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.DotNetHostPolicy": "2.2.0",
|
||||
"Microsoft.NETCore.Platforms": "2.2.0",
|
||||
"Microsoft.NETCore.Targets": "2.0.0",
|
||||
"NETStandard.Library": "2.0.3"
|
||||
},
|
||||
"compile": {
|
||||
"ref/netcoreapp2.2/Microsoft.CSharp.dll": {},
|
||||
"ref/netcoreapp2.2/Microsoft.VisualBasic.dll": {},
|
||||
"ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.AppContext.dll": {},
|
||||
"ref/netcoreapp2.2/System.Buffers.dll": {},
|
||||
"ref/netcoreapp2.2/System.Collections.Concurrent.dll": {},
|
||||
"ref/netcoreapp2.2/System.Collections.Immutable.dll": {},
|
||||
"ref/netcoreapp2.2/System.Collections.NonGeneric.dll": {},
|
||||
"ref/netcoreapp2.2/System.Collections.Specialized.dll": {},
|
||||
"ref/netcoreapp2.2/System.Collections.dll": {},
|
||||
"ref/netcoreapp2.2/System.ComponentModel.Annotations.dll": {},
|
||||
"ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll": {},
|
||||
"ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll": {},
|
||||
"ref/netcoreapp2.2/System.ComponentModel.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll": {},
|
||||
"ref/netcoreapp2.2/System.ComponentModel.dll": {},
|
||||
"ref/netcoreapp2.2/System.Configuration.dll": {},
|
||||
"ref/netcoreapp2.2/System.Console.dll": {},
|
||||
"ref/netcoreapp2.2/System.Core.dll": {},
|
||||
"ref/netcoreapp2.2/System.Data.Common.dll": {},
|
||||
"ref/netcoreapp2.2/System.Data.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Contracts.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Debug.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Process.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Tools.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll": {},
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Tracing.dll": {},
|
||||
"ref/netcoreapp2.2/System.Drawing.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.Drawing.dll": {},
|
||||
"ref/netcoreapp2.2/System.Dynamic.Runtime.dll": {},
|
||||
"ref/netcoreapp2.2/System.Globalization.Calendars.dll": {},
|
||||
"ref/netcoreapp2.2/System.Globalization.Extensions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Globalization.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.Compression.Brotli.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.Compression.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.IsolatedStorage.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.Pipes.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll": {},
|
||||
"ref/netcoreapp2.2/System.IO.dll": {},
|
||||
"ref/netcoreapp2.2/System.Linq.Expressions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Linq.Parallel.dll": {},
|
||||
"ref/netcoreapp2.2/System.Linq.Queryable.dll": {},
|
||||
"ref/netcoreapp2.2/System.Linq.dll": {},
|
||||
"ref/netcoreapp2.2/System.Memory.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Http.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.HttpListener.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Mail.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.NameResolution.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.NetworkInformation.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Ping.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Requests.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Security.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.ServicePoint.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.Sockets.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.WebClient.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.WebProxy.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.WebSockets.Client.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.WebSockets.dll": {},
|
||||
"ref/netcoreapp2.2/System.Net.dll": {},
|
||||
"ref/netcoreapp2.2/System.Numerics.Vectors.dll": {},
|
||||
"ref/netcoreapp2.2/System.Numerics.dll": {},
|
||||
"ref/netcoreapp2.2/System.ObjectModel.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.Extensions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.Metadata.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Reflection.dll": {},
|
||||
"ref/netcoreapp2.2/System.Resources.Reader.dll": {},
|
||||
"ref/netcoreapp2.2/System.Resources.ResourceManager.dll": {},
|
||||
"ref/netcoreapp2.2/System.Resources.Writer.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Extensions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Handles.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Loader.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Numerics.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.dll": {},
|
||||
"ref/netcoreapp2.2/System.Runtime.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Claims.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.Principal.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.SecureString.dll": {},
|
||||
"ref/netcoreapp2.2/System.Security.dll": {},
|
||||
"ref/netcoreapp2.2/System.ServiceModel.Web.dll": {},
|
||||
"ref/netcoreapp2.2/System.ServiceProcess.dll": {},
|
||||
"ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Text.Encoding.dll": {},
|
||||
"ref/netcoreapp2.2/System.Text.RegularExpressions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Overlapped.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Thread.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.ThreadPool.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.Timer.dll": {},
|
||||
"ref/netcoreapp2.2/System.Threading.dll": {},
|
||||
"ref/netcoreapp2.2/System.Transactions.Local.dll": {},
|
||||
"ref/netcoreapp2.2/System.Transactions.dll": {},
|
||||
"ref/netcoreapp2.2/System.ValueTuple.dll": {},
|
||||
"ref/netcoreapp2.2/System.Web.HttpUtility.dll": {},
|
||||
"ref/netcoreapp2.2/System.Web.dll": {},
|
||||
"ref/netcoreapp2.2/System.Windows.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.Linq.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.ReaderWriter.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.Serialization.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.XDocument.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.XPath.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.XmlDocument.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.XmlSerializer.dll": {},
|
||||
"ref/netcoreapp2.2/System.Xml.dll": {},
|
||||
"ref/netcoreapp2.2/System.dll": {},
|
||||
"ref/netcoreapp2.2/WindowsBase.dll": {},
|
||||
"ref/netcoreapp2.2/mscorlib.dll": {},
|
||||
"ref/netcoreapp2.2/netstandard.dll": {}
|
||||
},
|
||||
"build": {
|
||||
"build/netcoreapp2.2/Microsoft.NETCore.App.props": {},
|
||||
"build/netcoreapp2.2/Microsoft.NETCore.App.targets": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.DotNetAppHost/2.2.0": {
|
||||
"type": "package"
|
||||
},
|
||||
"Microsoft.NETCore.DotNetHostPolicy/2.2.0": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.DotNetHostResolver": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.DotNetHostResolver/2.2.0": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.DotNetAppHost": "2.2.0"
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/2.2.0": {
|
||||
"type": "package",
|
||||
"compile": {
|
||||
"lib/netstandard1.0/_._": {}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard1.0/_._": {}
|
||||
}
|
||||
},
|
||||
"Microsoft.NETCore.Targets/2.0.0": {
|
||||
"type": "package",
|
||||
"compile": {
|
||||
"lib/netstandard1.0/_._": {}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard1.0/_._": {}
|
||||
}
|
||||
},
|
||||
"NETStandard.Library/2.0.3": {
|
||||
"type": "package",
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.Platforms": "1.1.0"
|
||||
},
|
||||
"compile": {
|
||||
"lib/netstandard1.0/_._": {}
|
||||
},
|
||||
"runtime": {
|
||||
"lib/netstandard1.0/_._": {}
|
||||
},
|
||||
"build": {
|
||||
"build/netstandard2.0/NETStandard.Library.targets": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"Microsoft.NETCore.App/2.2.0": {
|
||||
"sha512": "7z5l8Jp324S8bU8+yyWeYHXUFYvKyiI5lqS1dXgTzOx1H69Qbf6df12kCKlNX45LpMfCMd4U3M6p7Rl5Zk7SLA==",
|
||||
"type": "package",
|
||||
"path": "microsoft.netcore.app/2.2.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"LICENSE.TXT",
|
||||
"Microsoft.NETCore.App.versions.txt",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"build/netcoreapp2.2/Microsoft.NETCore.App.PlatformManifest.txt",
|
||||
"build/netcoreapp2.2/Microsoft.NETCore.App.props",
|
||||
"build/netcoreapp2.2/Microsoft.NETCore.App.targets",
|
||||
"microsoft.netcore.app.2.2.0.nupkg.sha512",
|
||||
"microsoft.netcore.app.nuspec",
|
||||
"ref/netcoreapp2.2/Microsoft.CSharp.dll",
|
||||
"ref/netcoreapp2.2/Microsoft.CSharp.xml",
|
||||
"ref/netcoreapp2.2/Microsoft.VisualBasic.dll",
|
||||
"ref/netcoreapp2.2/Microsoft.VisualBasic.xml",
|
||||
"ref/netcoreapp2.2/Microsoft.Win32.Primitives.dll",
|
||||
"ref/netcoreapp2.2/Microsoft.Win32.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.AppContext.dll",
|
||||
"ref/netcoreapp2.2/System.Buffers.dll",
|
||||
"ref/netcoreapp2.2/System.Buffers.xml",
|
||||
"ref/netcoreapp2.2/System.Collections.Concurrent.dll",
|
||||
"ref/netcoreapp2.2/System.Collections.Concurrent.xml",
|
||||
"ref/netcoreapp2.2/System.Collections.Immutable.dll",
|
||||
"ref/netcoreapp2.2/System.Collections.Immutable.xml",
|
||||
"ref/netcoreapp2.2/System.Collections.NonGeneric.dll",
|
||||
"ref/netcoreapp2.2/System.Collections.NonGeneric.xml",
|
||||
"ref/netcoreapp2.2/System.Collections.Specialized.dll",
|
||||
"ref/netcoreapp2.2/System.Collections.Specialized.xml",
|
||||
"ref/netcoreapp2.2/System.Collections.dll",
|
||||
"ref/netcoreapp2.2/System.Collections.xml",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.Annotations.dll",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.Annotations.xml",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.DataAnnotations.dll",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.dll",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.EventBasedAsync.xml",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.TypeConverter.dll",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.TypeConverter.xml",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.dll",
|
||||
"ref/netcoreapp2.2/System.ComponentModel.xml",
|
||||
"ref/netcoreapp2.2/System.Configuration.dll",
|
||||
"ref/netcoreapp2.2/System.Console.dll",
|
||||
"ref/netcoreapp2.2/System.Console.xml",
|
||||
"ref/netcoreapp2.2/System.Core.dll",
|
||||
"ref/netcoreapp2.2/System.Data.Common.dll",
|
||||
"ref/netcoreapp2.2/System.Data.Common.xml",
|
||||
"ref/netcoreapp2.2/System.Data.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Contracts.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Contracts.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Debug.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Debug.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.DiagnosticSource.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.FileVersionInfo.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Process.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Process.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.StackTrace.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.StackTrace.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.TextWriterTraceListener.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Tools.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Tools.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.TraceSource.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.TraceSource.xml",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Tracing.dll",
|
||||
"ref/netcoreapp2.2/System.Diagnostics.Tracing.xml",
|
||||
"ref/netcoreapp2.2/System.Drawing.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.Drawing.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.Drawing.dll",
|
||||
"ref/netcoreapp2.2/System.Dynamic.Runtime.dll",
|
||||
"ref/netcoreapp2.2/System.Globalization.Calendars.dll",
|
||||
"ref/netcoreapp2.2/System.Globalization.Extensions.dll",
|
||||
"ref/netcoreapp2.2/System.Globalization.dll",
|
||||
"ref/netcoreapp2.2/System.IO.Compression.Brotli.dll",
|
||||
"ref/netcoreapp2.2/System.IO.Compression.FileSystem.dll",
|
||||
"ref/netcoreapp2.2/System.IO.Compression.ZipFile.dll",
|
||||
"ref/netcoreapp2.2/System.IO.Compression.ZipFile.xml",
|
||||
"ref/netcoreapp2.2/System.IO.Compression.dll",
|
||||
"ref/netcoreapp2.2/System.IO.Compression.xml",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.dll",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.DriveInfo.xml",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.Watcher.dll",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.Watcher.xml",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.dll",
|
||||
"ref/netcoreapp2.2/System.IO.FileSystem.xml",
|
||||
"ref/netcoreapp2.2/System.IO.IsolatedStorage.dll",
|
||||
"ref/netcoreapp2.2/System.IO.IsolatedStorage.xml",
|
||||
"ref/netcoreapp2.2/System.IO.MemoryMappedFiles.dll",
|
||||
"ref/netcoreapp2.2/System.IO.MemoryMappedFiles.xml",
|
||||
"ref/netcoreapp2.2/System.IO.Pipes.dll",
|
||||
"ref/netcoreapp2.2/System.IO.Pipes.xml",
|
||||
"ref/netcoreapp2.2/System.IO.UnmanagedMemoryStream.dll",
|
||||
"ref/netcoreapp2.2/System.IO.dll",
|
||||
"ref/netcoreapp2.2/System.Linq.Expressions.dll",
|
||||
"ref/netcoreapp2.2/System.Linq.Expressions.xml",
|
||||
"ref/netcoreapp2.2/System.Linq.Parallel.dll",
|
||||
"ref/netcoreapp2.2/System.Linq.Parallel.xml",
|
||||
"ref/netcoreapp2.2/System.Linq.Queryable.dll",
|
||||
"ref/netcoreapp2.2/System.Linq.Queryable.xml",
|
||||
"ref/netcoreapp2.2/System.Linq.dll",
|
||||
"ref/netcoreapp2.2/System.Linq.xml",
|
||||
"ref/netcoreapp2.2/System.Memory.dll",
|
||||
"ref/netcoreapp2.2/System.Memory.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Http.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Http.xml",
|
||||
"ref/netcoreapp2.2/System.Net.HttpListener.dll",
|
||||
"ref/netcoreapp2.2/System.Net.HttpListener.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Mail.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Mail.xml",
|
||||
"ref/netcoreapp2.2/System.Net.NameResolution.dll",
|
||||
"ref/netcoreapp2.2/System.Net.NameResolution.xml",
|
||||
"ref/netcoreapp2.2/System.Net.NetworkInformation.dll",
|
||||
"ref/netcoreapp2.2/System.Net.NetworkInformation.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Ping.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Ping.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Requests.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Requests.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Security.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Security.xml",
|
||||
"ref/netcoreapp2.2/System.Net.ServicePoint.dll",
|
||||
"ref/netcoreapp2.2/System.Net.ServicePoint.xml",
|
||||
"ref/netcoreapp2.2/System.Net.Sockets.dll",
|
||||
"ref/netcoreapp2.2/System.Net.Sockets.xml",
|
||||
"ref/netcoreapp2.2/System.Net.WebClient.dll",
|
||||
"ref/netcoreapp2.2/System.Net.WebClient.xml",
|
||||
"ref/netcoreapp2.2/System.Net.WebHeaderCollection.dll",
|
||||
"ref/netcoreapp2.2/System.Net.WebHeaderCollection.xml",
|
||||
"ref/netcoreapp2.2/System.Net.WebProxy.dll",
|
||||
"ref/netcoreapp2.2/System.Net.WebProxy.xml",
|
||||
"ref/netcoreapp2.2/System.Net.WebSockets.Client.dll",
|
||||
"ref/netcoreapp2.2/System.Net.WebSockets.Client.xml",
|
||||
"ref/netcoreapp2.2/System.Net.WebSockets.dll",
|
||||
"ref/netcoreapp2.2/System.Net.WebSockets.xml",
|
||||
"ref/netcoreapp2.2/System.Net.dll",
|
||||
"ref/netcoreapp2.2/System.Numerics.Vectors.dll",
|
||||
"ref/netcoreapp2.2/System.Numerics.Vectors.xml",
|
||||
"ref/netcoreapp2.2/System.Numerics.dll",
|
||||
"ref/netcoreapp2.2/System.ObjectModel.dll",
|
||||
"ref/netcoreapp2.2/System.ObjectModel.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.DispatchProxy.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.DispatchProxy.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.ILGeneration.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.Lightweight.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.Emit.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.Extensions.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.Metadata.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.Metadata.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.TypeExtensions.dll",
|
||||
"ref/netcoreapp2.2/System.Reflection.TypeExtensions.xml",
|
||||
"ref/netcoreapp2.2/System.Reflection.dll",
|
||||
"ref/netcoreapp2.2/System.Resources.Reader.dll",
|
||||
"ref/netcoreapp2.2/System.Resources.ResourceManager.dll",
|
||||
"ref/netcoreapp2.2/System.Resources.ResourceManager.xml",
|
||||
"ref/netcoreapp2.2/System.Resources.Writer.dll",
|
||||
"ref/netcoreapp2.2/System.Resources.Writer.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.CompilerServices.VisualC.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Extensions.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Extensions.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Handles.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.RuntimeInformation.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.WindowsRuntime.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.InteropServices.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Loader.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Loader.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Numerics.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Numerics.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Formatters.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Json.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Json.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Xml.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.Xml.xml",
|
||||
"ref/netcoreapp2.2/System.Runtime.Serialization.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.dll",
|
||||
"ref/netcoreapp2.2/System.Runtime.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Claims.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Claims.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Algorithms.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Csp.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Csp.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Encoding.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Encoding.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Primitives.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.Primitives.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Cryptography.X509Certificates.xml",
|
||||
"ref/netcoreapp2.2/System.Security.Principal.dll",
|
||||
"ref/netcoreapp2.2/System.Security.Principal.xml",
|
||||
"ref/netcoreapp2.2/System.Security.SecureString.dll",
|
||||
"ref/netcoreapp2.2/System.Security.dll",
|
||||
"ref/netcoreapp2.2/System.ServiceModel.Web.dll",
|
||||
"ref/netcoreapp2.2/System.ServiceProcess.dll",
|
||||
"ref/netcoreapp2.2/System.Text.Encoding.Extensions.dll",
|
||||
"ref/netcoreapp2.2/System.Text.Encoding.Extensions.xml",
|
||||
"ref/netcoreapp2.2/System.Text.Encoding.dll",
|
||||
"ref/netcoreapp2.2/System.Text.RegularExpressions.dll",
|
||||
"ref/netcoreapp2.2/System.Text.RegularExpressions.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Overlapped.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Overlapped.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Dataflow.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Extensions.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Extensions.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Parallel.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.Parallel.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Tasks.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Thread.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Thread.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.ThreadPool.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.ThreadPool.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.Timer.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.Timer.xml",
|
||||
"ref/netcoreapp2.2/System.Threading.dll",
|
||||
"ref/netcoreapp2.2/System.Threading.xml",
|
||||
"ref/netcoreapp2.2/System.Transactions.Local.dll",
|
||||
"ref/netcoreapp2.2/System.Transactions.Local.xml",
|
||||
"ref/netcoreapp2.2/System.Transactions.dll",
|
||||
"ref/netcoreapp2.2/System.ValueTuple.dll",
|
||||
"ref/netcoreapp2.2/System.Web.HttpUtility.dll",
|
||||
"ref/netcoreapp2.2/System.Web.HttpUtility.xml",
|
||||
"ref/netcoreapp2.2/System.Web.dll",
|
||||
"ref/netcoreapp2.2/System.Windows.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.Linq.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.ReaderWriter.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.ReaderWriter.xml",
|
||||
"ref/netcoreapp2.2/System.Xml.Serialization.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.XDocument.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.XDocument.xml",
|
||||
"ref/netcoreapp2.2/System.Xml.XPath.XDocument.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.XPath.XDocument.xml",
|
||||
"ref/netcoreapp2.2/System.Xml.XPath.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.XPath.xml",
|
||||
"ref/netcoreapp2.2/System.Xml.XmlDocument.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.XmlSerializer.dll",
|
||||
"ref/netcoreapp2.2/System.Xml.XmlSerializer.xml",
|
||||
"ref/netcoreapp2.2/System.Xml.dll",
|
||||
"ref/netcoreapp2.2/System.dll",
|
||||
"ref/netcoreapp2.2/WindowsBase.dll",
|
||||
"ref/netcoreapp2.2/mscorlib.dll",
|
||||
"ref/netcoreapp2.2/netstandard.dll",
|
||||
"runtime.json"
|
||||
]
|
||||
},
|
||||
"Microsoft.NETCore.DotNetAppHost/2.2.0": {
|
||||
"sha512": "DrhaKInRKKvN6Ns2VNIlC7ZffLOp9THf8cO6X4fytPRJovJUbF49/zzx4WfgX9E44FMsw9hT8hrKiIqDSHvGvA==",
|
||||
"type": "package",
|
||||
"path": "microsoft.netcore.dotnetapphost/2.2.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"microsoft.netcore.dotnetapphost.2.2.0.nupkg.sha512",
|
||||
"microsoft.netcore.dotnetapphost.nuspec",
|
||||
"runtime.json"
|
||||
]
|
||||
},
|
||||
"Microsoft.NETCore.DotNetHostPolicy/2.2.0": {
|
||||
"sha512": "FJie7IoPZFaPgNDxhZGmDBQP/Bs5vPdfca/G2Wf9gd6LIvMYkZcibtmJwB4tcf4KXkaOYfIOo4Cl9sEPMsSzkw==",
|
||||
"type": "package",
|
||||
"path": "microsoft.netcore.dotnethostpolicy/2.2.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"microsoft.netcore.dotnethostpolicy.2.2.0.nupkg.sha512",
|
||||
"microsoft.netcore.dotnethostpolicy.nuspec",
|
||||
"runtime.json"
|
||||
]
|
||||
},
|
||||
"Microsoft.NETCore.DotNetHostResolver/2.2.0": {
|
||||
"sha512": "spDm3AJYmebthDNhzY17YLPtvbc+Y1lCLVeiIH1uLJ/hZaM+40pBiPefFR8J1u66Ndkqi8ipR2tEbqPnYnjRhw==",
|
||||
"type": "package",
|
||||
"path": "microsoft.netcore.dotnethostresolver/2.2.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"microsoft.netcore.dotnethostresolver.2.2.0.nupkg.sha512",
|
||||
"microsoft.netcore.dotnethostresolver.nuspec",
|
||||
"runtime.json"
|
||||
]
|
||||
},
|
||||
"Microsoft.NETCore.Platforms/2.2.0": {
|
||||
"sha512": "T/J+XZo+YheFTJh8/4uoeJDdz5qOmOMkjg6/VL8mHJ9AnP8+fmV/kcbxeXsob0irRNiChf+V0ig1MCRLp/+Kog==",
|
||||
"type": "package",
|
||||
"path": "microsoft.netcore.platforms/2.2.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
".signature.p7s",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"lib/netstandard1.0/_._",
|
||||
"microsoft.netcore.platforms.2.2.0.nupkg.sha512",
|
||||
"microsoft.netcore.platforms.nuspec",
|
||||
"runtime.json",
|
||||
"useSharedDesignerContext.txt",
|
||||
"version.txt"
|
||||
]
|
||||
},
|
||||
"Microsoft.NETCore.Targets/2.0.0": {
|
||||
"sha512": "odP/tJj1z6GylFpNo7pMtbd/xQgTC3Ex2If63dRTL38bBNMwsBnJ+RceUIyHdRBC0oik/3NehYT+oECwBhIM3Q==",
|
||||
"type": "package",
|
||||
"path": "microsoft.netcore.targets/2.0.0",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"lib/netstandard1.0/_._",
|
||||
"microsoft.netcore.targets.2.0.0.nupkg.sha512",
|
||||
"microsoft.netcore.targets.nuspec",
|
||||
"runtime.json",
|
||||
"useSharedDesignerContext.txt",
|
||||
"version.txt"
|
||||
]
|
||||
},
|
||||
"NETStandard.Library/2.0.3": {
|
||||
"sha512": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==",
|
||||
"type": "package",
|
||||
"path": "netstandard.library/2.0.3",
|
||||
"files": [
|
||||
".nupkg.metadata",
|
||||
"LICENSE.TXT",
|
||||
"THIRD-PARTY-NOTICES.TXT",
|
||||
"build/netstandard2.0/NETStandard.Library.targets",
|
||||
"build/netstandard2.0/ref/Microsoft.Win32.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.AppContext.dll",
|
||||
"build/netstandard2.0/ref/System.Collections.Concurrent.dll",
|
||||
"build/netstandard2.0/ref/System.Collections.NonGeneric.dll",
|
||||
"build/netstandard2.0/ref/System.Collections.Specialized.dll",
|
||||
"build/netstandard2.0/ref/System.Collections.dll",
|
||||
"build/netstandard2.0/ref/System.ComponentModel.Composition.dll",
|
||||
"build/netstandard2.0/ref/System.ComponentModel.EventBasedAsync.dll",
|
||||
"build/netstandard2.0/ref/System.ComponentModel.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.ComponentModel.TypeConverter.dll",
|
||||
"build/netstandard2.0/ref/System.ComponentModel.dll",
|
||||
"build/netstandard2.0/ref/System.Console.dll",
|
||||
"build/netstandard2.0/ref/System.Core.dll",
|
||||
"build/netstandard2.0/ref/System.Data.Common.dll",
|
||||
"build/netstandard2.0/ref/System.Data.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.Contracts.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.Debug.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.FileVersionInfo.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.Process.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.StackTrace.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.TextWriterTraceListener.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.Tools.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.TraceSource.dll",
|
||||
"build/netstandard2.0/ref/System.Diagnostics.Tracing.dll",
|
||||
"build/netstandard2.0/ref/System.Drawing.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.Drawing.dll",
|
||||
"build/netstandard2.0/ref/System.Dynamic.Runtime.dll",
|
||||
"build/netstandard2.0/ref/System.Globalization.Calendars.dll",
|
||||
"build/netstandard2.0/ref/System.Globalization.Extensions.dll",
|
||||
"build/netstandard2.0/ref/System.Globalization.dll",
|
||||
"build/netstandard2.0/ref/System.IO.Compression.FileSystem.dll",
|
||||
"build/netstandard2.0/ref/System.IO.Compression.ZipFile.dll",
|
||||
"build/netstandard2.0/ref/System.IO.Compression.dll",
|
||||
"build/netstandard2.0/ref/System.IO.FileSystem.DriveInfo.dll",
|
||||
"build/netstandard2.0/ref/System.IO.FileSystem.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.IO.FileSystem.Watcher.dll",
|
||||
"build/netstandard2.0/ref/System.IO.FileSystem.dll",
|
||||
"build/netstandard2.0/ref/System.IO.IsolatedStorage.dll",
|
||||
"build/netstandard2.0/ref/System.IO.MemoryMappedFiles.dll",
|
||||
"build/netstandard2.0/ref/System.IO.Pipes.dll",
|
||||
"build/netstandard2.0/ref/System.IO.UnmanagedMemoryStream.dll",
|
||||
"build/netstandard2.0/ref/System.IO.dll",
|
||||
"build/netstandard2.0/ref/System.Linq.Expressions.dll",
|
||||
"build/netstandard2.0/ref/System.Linq.Parallel.dll",
|
||||
"build/netstandard2.0/ref/System.Linq.Queryable.dll",
|
||||
"build/netstandard2.0/ref/System.Linq.dll",
|
||||
"build/netstandard2.0/ref/System.Net.Http.dll",
|
||||
"build/netstandard2.0/ref/System.Net.NameResolution.dll",
|
||||
"build/netstandard2.0/ref/System.Net.NetworkInformation.dll",
|
||||
"build/netstandard2.0/ref/System.Net.Ping.dll",
|
||||
"build/netstandard2.0/ref/System.Net.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.Net.Requests.dll",
|
||||
"build/netstandard2.0/ref/System.Net.Security.dll",
|
||||
"build/netstandard2.0/ref/System.Net.Sockets.dll",
|
||||
"build/netstandard2.0/ref/System.Net.WebHeaderCollection.dll",
|
||||
"build/netstandard2.0/ref/System.Net.WebSockets.Client.dll",
|
||||
"build/netstandard2.0/ref/System.Net.WebSockets.dll",
|
||||
"build/netstandard2.0/ref/System.Net.dll",
|
||||
"build/netstandard2.0/ref/System.Numerics.dll",
|
||||
"build/netstandard2.0/ref/System.ObjectModel.dll",
|
||||
"build/netstandard2.0/ref/System.Reflection.Extensions.dll",
|
||||
"build/netstandard2.0/ref/System.Reflection.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.Reflection.dll",
|
||||
"build/netstandard2.0/ref/System.Resources.Reader.dll",
|
||||
"build/netstandard2.0/ref/System.Resources.ResourceManager.dll",
|
||||
"build/netstandard2.0/ref/System.Resources.Writer.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.CompilerServices.VisualC.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Extensions.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Handles.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.InteropServices.RuntimeInformation.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.InteropServices.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Numerics.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Serialization.Formatters.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Serialization.Json.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Serialization.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Serialization.Xml.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.Serialization.dll",
|
||||
"build/netstandard2.0/ref/System.Runtime.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Claims.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Cryptography.Algorithms.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Cryptography.Csp.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Cryptography.Encoding.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Cryptography.Primitives.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Cryptography.X509Certificates.dll",
|
||||
"build/netstandard2.0/ref/System.Security.Principal.dll",
|
||||
"build/netstandard2.0/ref/System.Security.SecureString.dll",
|
||||
"build/netstandard2.0/ref/System.ServiceModel.Web.dll",
|
||||
"build/netstandard2.0/ref/System.Text.Encoding.Extensions.dll",
|
||||
"build/netstandard2.0/ref/System.Text.Encoding.dll",
|
||||
"build/netstandard2.0/ref/System.Text.RegularExpressions.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.Overlapped.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.Tasks.Parallel.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.Tasks.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.Thread.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.ThreadPool.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.Timer.dll",
|
||||
"build/netstandard2.0/ref/System.Threading.dll",
|
||||
"build/netstandard2.0/ref/System.Transactions.dll",
|
||||
"build/netstandard2.0/ref/System.ValueTuple.dll",
|
||||
"build/netstandard2.0/ref/System.Web.dll",
|
||||
"build/netstandard2.0/ref/System.Windows.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.Linq.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.ReaderWriter.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.Serialization.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.XDocument.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.XPath.XDocument.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.XPath.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.XmlDocument.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.XmlSerializer.dll",
|
||||
"build/netstandard2.0/ref/System.Xml.dll",
|
||||
"build/netstandard2.0/ref/System.dll",
|
||||
"build/netstandard2.0/ref/mscorlib.dll",
|
||||
"build/netstandard2.0/ref/netstandard.dll",
|
||||
"build/netstandard2.0/ref/netstandard.xml",
|
||||
"lib/netstandard1.0/_._",
|
||||
"netstandard.library.2.0.3.nupkg.sha512",
|
||||
"netstandard.library.nuspec"
|
||||
]
|
||||
}
|
||||
},
|
||||
"projectFileDependencyGroups": {
|
||||
".NETCoreApp,Version=v2.2": [
|
||||
"Microsoft.NETCore.App >= 2.2.0"
|
||||
]
|
||||
},
|
||||
"packageFolders": {
|
||||
"/Users/ben/.nuget/packages/": {},
|
||||
"/usr/local/share/dotnet/sdk/NuGetFallbackFolder": {}
|
||||
},
|
||||
"project": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj",
|
||||
"projectName": "csharp",
|
||||
"projectPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/csharp.csproj",
|
||||
"packagesPath": "/Users/ben/.nuget/packages/",
|
||||
"outputPath": "/Users/ben/.vim/bundle/vimspector/support/test/csharp/obj/",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"/usr/local/share/dotnet/sdk/NuGetFallbackFolder"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"/Users/ben/.nuget/NuGet/NuGet.Config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"netcoreapp2.2"
|
||||
],
|
||||
"sources": {
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp2.2": {
|
||||
"projectReferences": {}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
}
|
||||
},
|
||||
"frameworks": {
|
||||
"netcoreapp2.2": {
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"suppressParent": "All",
|
||||
"target": "Package",
|
||||
"version": "[2.2.0, )",
|
||||
"autoReferenced": true
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,22 @@
|
|||
{
|
||||
"adapters": {
|
||||
"dlv-dap": {
|
||||
"variables": {
|
||||
"port": "${unusedLocalPort}"
|
||||
},
|
||||
"command": [
|
||||
"$HOME/go/bin/dlv",
|
||||
"dap",
|
||||
"--listen",
|
||||
"127.0.0.1:${port}"
|
||||
],
|
||||
"port": "${port}"
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"run": {
|
||||
"adapter": "vscode-go",
|
||||
"default": true,
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/hello-world.go",
|
||||
|
|
@ -10,6 +25,35 @@
|
|||
"trace": true,
|
||||
"env": { "GO111MODULE": "off" }
|
||||
}
|
||||
},
|
||||
"run-dap": {
|
||||
"adapter": "dlv-dap",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"env": { "GO111MODULE": "off" },
|
||||
|
||||
"mode": "debug", // debug|test
|
||||
"program": "${workspaceRoot}/hello-world.go"
|
||||
|
||||
// "args": [],
|
||||
// "buildFlags": ...
|
||||
// "stackTraceDepth": ...,
|
||||
// "showGlobalVariables": true,
|
||||
}
|
||||
},
|
||||
"run-exec": {
|
||||
// NOTE: To use this you _must_ disable optimistaion:
|
||||
// go build -o hello_world -gcflags="all=-N -l"
|
||||
// https://github.com/golang/vscode-go/blob/master/docs/debugging.md#troubleshooting
|
||||
"adapter": "vscode-go",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/hello-world",
|
||||
"mode": "exec",
|
||||
"dlvToolPath": "$HOME/go/bin/dlv",
|
||||
"trace": true,
|
||||
"env": { "GO111MODULE": "off" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
29
support/test/go/name-starts-with-vowel/.vimspector.json
Normal file
29
support/test/go/name-starts-with-vowel/.vimspector.json
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"configurations": {
|
||||
"run-cmd": {
|
||||
"adapter": "vscode-go",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/cmd/namestartswithvowel/main.go",
|
||||
"mode": "debug",
|
||||
"dlvToolPath": "$HOME/go/bin/dlv",
|
||||
"dlvLoadConfig": {
|
||||
"maxArrayValues": 1000,
|
||||
"maxStringLen": 1000
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-current-file": {
|
||||
"adapter": "vscode-go",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"mode": "test",
|
||||
"program": "${fileDirname}",
|
||||
"cwd": "${fileDirname}",
|
||||
"dlvToolPath": "$GOPATH/bin/dlv",
|
||||
"env": {},
|
||||
"args": []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
support/test/go/name-starts-with-vowel/README.md
Normal file
33
support/test/go/name-starts-with-vowel/README.md
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
# Purpose
|
||||
|
||||
This example comes with two example vimspector configs for the Go programming language.
|
||||
|
||||
1) `run-cmd` will launch the main programme under `cmd/namestartswithvowel`.
|
||||
1) `test-current-file` will run the tests in the current file in debug mode.
|
||||
|
||||
## Example use-cases
|
||||
|
||||
### run-cmd
|
||||
|
||||
* Open `cmd/namestartswithvowel/main.go`
|
||||
* Add a breakpoint somewhere within the programme
|
||||
* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping)
|
||||
* Select the first launch configuration (`1: run-cmd`)
|
||||
|
||||
### test-current-file
|
||||
|
||||
* Open `internal/vowels/vowels_test.go`
|
||||
* Add a breakpoint somewhere within the test
|
||||
* Start the debugger (`:call vimspector#Continue()` or your relevant keymapping)
|
||||
* Select the second launch configuration (`2: test-current-file`)
|
||||
|
||||
## Additional Configuration
|
||||
|
||||
There are two additional configuration options specified under `run-cmd`; these parameters configure the maximum string/array size to be shown while debugging.
|
||||
|
||||
```
|
||||
"dlvLoadConfig": {
|
||||
"maxArrayValues": 1000,
|
||||
"maxStringLen": 1000
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"example.com/internal/vowels"
|
||||
)
|
||||
|
||||
func main() {
|
||||
names := []string{"Simon", "Bob", "Jennifer", "Amy", "Duke", "Elizabeth"}
|
||||
|
||||
for _, n := range names {
|
||||
if vowels.NameStartsWithVowel(n) {
|
||||
fmt.Printf("%s starts with a vowel!\n", n)
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("%s does not start with a vowel!\n", n)
|
||||
}
|
||||
}
|
||||
3
support/test/go/name-starts-with-vowel/go.mod
Normal file
3
support/test/go/name-starts-with-vowel/go.mod
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
module example.com
|
||||
|
||||
go 1.16
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package vowels
|
||||
|
||||
import "strings"
|
||||
|
||||
func NameStartsWithVowel(name string) bool {
|
||||
s := strings.Split(strings.ToLower(name), "")
|
||||
|
||||
return s[0] == "a" || s[0] == "e" || s[0] == "i" || s[0] == "o" || s[0] == "u"
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
package vowels
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNameStartsWithVowel(t *testing.T) {
|
||||
testCases := []struct {
|
||||
input string
|
||||
expectedOutput bool
|
||||
}{
|
||||
{
|
||||
input: "Simon",
|
||||
expectedOutput: false,
|
||||
},
|
||||
{
|
||||
input: "Andy",
|
||||
expectedOutput: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range testCases {
|
||||
t.Run(fmt.Sprintf("%s should product %t", tt.input, tt.expectedOutput), func(t *testing.T) {
|
||||
out := NameStartsWithVowel(tt.input)
|
||||
if out != tt.expectedOutput {
|
||||
t.Errorf("%s produced %t, when %t was expected", tt.input, out, tt.expectedOutput)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<artifactId>TestApplication</artifactId>
|
||||
<version>1</version>
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
<maven.compiler.source>11</maven.compiler.source>
|
||||
<maven.compiler.target>11</maven.compiler.target>
|
||||
</properties>
|
||||
</project>
|
||||
|
|
|
|||
2
support/test/kotlin/.gitignore
vendored
Normal file
2
support/test/kotlin/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
.gradle
|
||||
build
|
||||
21
support/test/kotlin/.vimspector.json
Normal file
21
support/test/kotlin/.vimspector.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"configurations": {
|
||||
"kotlin-debug-adapter launch": {
|
||||
"adapter": "cust_kotlin-debug-adapter",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"projectRoot": "${workspaceFolder}",
|
||||
"mainClass": "vimspector/test/ApplicationKt"
|
||||
}
|
||||
},
|
||||
"kotlin-debug-adapter attach": {
|
||||
"adapter": "cust_kotlin-debug-adapter",
|
||||
"configuration": {
|
||||
"request": "attach",
|
||||
"projectRoot": "${workspaceFolder}",
|
||||
"hostName": "${hostName}",
|
||||
"port": "${port}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
25
support/test/kotlin/build.gradle.kts
Normal file
25
support/test/kotlin/build.gradle.kts
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
plugins {
|
||||
kotlin("jvm") version "1.4.0"
|
||||
|
||||
application
|
||||
}
|
||||
|
||||
repositories {
|
||||
// Use jcenter for resolving dependencies.
|
||||
// You can declare any Maven/Ivy/file repository here.
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Align versions of all Kotlin components
|
||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
|
||||
|
||||
// Use the Kotlin JDK 8 standard library.
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
|
||||
}
|
||||
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClassName = "vimspector.test.ApplicationKt"
|
||||
}
|
||||
|
||||
1
support/test/kotlin/settings.gradle.kts
Normal file
1
support/test/kotlin/settings.gradle.kts
Normal file
|
|
@ -0,0 +1 @@
|
|||
rootProject.name = "vimspector-test"
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package vimspector.test
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println("Hello World!")
|
||||
}
|
||||
18
support/test/lua/love-headless/.vimspector.json
Normal file
18
support/test/lua/love-headless/.vimspector.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#",
|
||||
"configurations": {
|
||||
"love": {
|
||||
"adapter": "lua-local",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"type": "lua-local",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": {
|
||||
"command": "love"
|
||||
},
|
||||
"args": ["${workspaceFolder}"],
|
||||
"stopOnEntry": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
12
support/test/lua/love-headless/conf.lua
Normal file
12
support/test/lua/love-headless/conf.lua
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
function love.conf(t)
|
||||
t.modules.audio = false
|
||||
t.modules.font = false
|
||||
t.modules.graphics = false
|
||||
t.modules.image = false
|
||||
t.modules.mouse = false
|
||||
t.modules.physics = false
|
||||
t.modules.sound = false
|
||||
t.modules.touch = false
|
||||
t.modules.video = false
|
||||
t.modules.window = false
|
||||
end
|
||||
10
support/test/lua/love-headless/main.lua
Normal file
10
support/test/lua/love-headless/main.lua
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
if pcall(require, 'lldebugger') then
|
||||
require('lldebugger').start()
|
||||
end
|
||||
|
||||
local time = 0
|
||||
|
||||
function love.update(dt)
|
||||
time = time + dt
|
||||
love.event.quit()
|
||||
end
|
||||
18
support/test/lua/love/.vimspector.json
Normal file
18
support/test/lua/love/.vimspector.json
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#",
|
||||
"configurations": {
|
||||
"love": {
|
||||
"adapter": "lua-local",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"type": "lua-local",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": {
|
||||
"command": "love"
|
||||
},
|
||||
"args": ["${workspaceFolder}"],
|
||||
"stopOnEntry": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
support/test/lua/love/main.lua
Normal file
21
support/test/lua/love/main.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
if pcall(require, 'lldebugger') then
|
||||
require('lldebugger').start()
|
||||
end
|
||||
|
||||
local rect = {0, 0, 64, 64}
|
||||
|
||||
|
||||
function love.update(dt)
|
||||
rect[1] = rect[1] + 10 * dt
|
||||
rect[2] = rect[2] + 10 * dt
|
||||
end
|
||||
|
||||
|
||||
function love.draw()
|
||||
love.graphics.rectangle('fill', rect[1], rect[2], rect[3], rect[4])
|
||||
end
|
||||
|
||||
|
||||
function love.keypressed()
|
||||
love.event.quit()
|
||||
end
|
||||
31
support/test/lua/simple/.vimspector.json
Normal file
31
support/test/lua/simple/.vimspector.json
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
{
|
||||
"$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json#",
|
||||
"configurations": {
|
||||
"lua": {
|
||||
"adapter": "lua-local",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"type": "lua-local",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": {
|
||||
"lua": "lua",
|
||||
"file": "simple.lua",
|
||||
"stopOnEntry": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"luajit": {
|
||||
"adapter": "lua-local",
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"type": "lua-local",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"program": {
|
||||
"lua": "luajit",
|
||||
"file": "simple.lua",
|
||||
"stopOnEntry": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
support/test/lua/simple/simple.lua
Normal file
21
support/test/lua/simple/simple.lua
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
local separator = ' '
|
||||
|
||||
|
||||
local function createMessage()
|
||||
local words = {}
|
||||
table.insert(words, 'Hello')
|
||||
table.insert(words, 'world')
|
||||
return table.concat(words, separator)
|
||||
end
|
||||
|
||||
|
||||
local function withEmphasis(func)
|
||||
return function()
|
||||
return func() .. '!'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
createMessage = withEmphasis(createMessage)
|
||||
|
||||
print(createMessage())
|
||||
|
|
@ -3,7 +3,7 @@ var msg = 'Hello, world!'
|
|||
var obj = {
|
||||
test: 'testing',
|
||||
toast: function() {
|
||||
return 'toasty' . this.test;
|
||||
return 'toasty' + this.test;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
21
support/test/python/multiple_files/.vimspector.json
Normal file
21
support/test/python/multiple_files/.vimspector.json
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"configurations": {
|
||||
"run": {
|
||||
"adapter": "debugpy",
|
||||
"default": true,
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/moo.py",
|
||||
"cwd": "${workspaceRoot}",
|
||||
"stopOnEntry": true
|
||||
},
|
||||
"breakpoints": {
|
||||
"exception": {
|
||||
"raised": "N",
|
||||
"uncaught": "",
|
||||
"userUnhandled": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
15
support/test/python/multiple_files/cow.py
Normal file
15
support/test/python/multiple_files/cow.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
def Say( *args, **kwargs ):
|
||||
print( *args, **kwargs )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
def Quiet():
|
||||
pass
|
||||
13
support/test/python/multiple_files/moo.py
Normal file
13
support/test/python/multiple_files/moo.py
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import cow
|
||||
|
||||
|
||||
def Moo():
|
||||
for i in range( 1, 100 ):
|
||||
cow.Say( 'Moo' )
|
||||
|
||||
for i in range( 1, 100 ):
|
||||
cow.Say( 'Ooom' )
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
Moo()
|
||||
|
|
@ -1,5 +1,56 @@
|
|||
{
|
||||
"$schema": "https://puremourning.github.io/vimspector/schema/vimspector.schema.json",
|
||||
"adapters": {
|
||||
"run_with_debugpy": {
|
||||
"command": [ "${workspaceRoot}/run_with_debugpy" ],
|
||||
"port": 9876,
|
||||
"env": {
|
||||
"DEBUG_PORT": "9876"
|
||||
}
|
||||
},
|
||||
"python-remote-docker": {
|
||||
"variables": {
|
||||
"port": "8765"
|
||||
},
|
||||
"port": "${port}",
|
||||
"launch": {
|
||||
"remote": {
|
||||
"container": "${ContainerID}",
|
||||
"runCommand": [
|
||||
"python3", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"--wait-for-client",
|
||||
"%CMD%"
|
||||
]
|
||||
},
|
||||
"delay": "5000m"
|
||||
}
|
||||
},
|
||||
"python-remote-ssh": {
|
||||
"variables": {
|
||||
"port": "8765"
|
||||
},
|
||||
"port": "${port}",
|
||||
"host": "${host}",
|
||||
"launch": {
|
||||
"remote": {
|
||||
"host": "${host}",
|
||||
"account": "${account}",
|
||||
"runCommand": [
|
||||
"python3", "-m", "debugpy", "--listen", "0.0.0.0:${port}",
|
||||
"--wait-for-client",
|
||||
"%CMD%"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"Use custom gadget": {
|
||||
"adapter": "test_custom",
|
||||
"configuration": {
|
||||
"request": "launch"
|
||||
}
|
||||
},
|
||||
// This is a comment.
|
||||
"run legacy vscode-python": {
|
||||
"adapter": "vscode-python", /* coment goes here too */
|
||||
|
|
@ -32,6 +83,33 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"attach-run": {
|
||||
"adapter": "run_with_debugpy",
|
||||
"configuration": {
|
||||
"request": "attach"
|
||||
},
|
||||
"breakpoints": {
|
||||
"exception": {
|
||||
"raised": "N",
|
||||
"uncaught": "",
|
||||
"userUnhandled": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"docker-attach": {
|
||||
"adapter": "python-remote-docker",
|
||||
"remote-cmdLine": [ "/root/main.py" ],
|
||||
"remote-request": "launch",
|
||||
"configuration": {
|
||||
"request": "attach",
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": "/root"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"run": {
|
||||
"adapter": "debugpy",
|
||||
"configuration": {
|
||||
|
|
@ -52,6 +130,11 @@
|
|||
},
|
||||
"run - default": {
|
||||
"adapter": "debugpy",
|
||||
"variables": {
|
||||
"MAKE_ENV_OUTPUT": {
|
||||
"shell": "${workspaceRoot}/make_env.sh"
|
||||
}
|
||||
},
|
||||
"configuration": {
|
||||
"request": "launch",
|
||||
"type": "python",
|
||||
|
|
@ -60,8 +143,8 @@
|
|||
"stopOnEntry#json": "${StopOnEntry:true}",
|
||||
"console": "integratedTerminal",
|
||||
"args#json": "${args:[]}",
|
||||
"env#json": "${env:{\\}}",
|
||||
"igored#json#s": "string not json"
|
||||
"igored#json#s": "string not json",
|
||||
"env#json": "${MAKE_ENV_OUTPUT}"
|
||||
},
|
||||
"breakpoints": {
|
||||
"exception": {
|
||||
|
|
@ -99,6 +182,23 @@
|
|||
"stopOnEntry": false,
|
||||
"console": "integratedTerminal"
|
||||
}
|
||||
},
|
||||
"run - remote host": {
|
||||
"adapter": "python-remote-ssh",
|
||||
"remote-cmdLine": [
|
||||
"${remoteRoot}/main.py"
|
||||
],
|
||||
"remote-request": "launch",
|
||||
"configuration": {
|
||||
"request": "attach",
|
||||
"redirectOutput": true,
|
||||
"pathMappings": [
|
||||
{
|
||||
"localRoot": "${workspaceRoot}",
|
||||
"remoteRoot": "${remoteRoot}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
support/test/python/simple_python/Dockerfile
Normal file
22
support/test/python/simple_python/Dockerfile
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
FROM ubuntu:18.04
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y dist-upgrade && \
|
||||
apt-get -y install sudo \
|
||||
lsb-release \
|
||||
ca-certificates \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
ca-cacert \
|
||||
locales \
|
||||
language-pack-en \
|
||||
libncurses5-dev libncursesw5-dev \
|
||||
git && \
|
||||
apt-get -y autoremove
|
||||
|
||||
## cleanup of files from setup
|
||||
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
RUN pip3 install debugpy
|
||||
|
||||
ADD main.py /root/main.py
|
||||
11
support/test/python/simple_python/build-container
Executable file
11
support/test/python/simple_python/build-container
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$1" = "--continue" ]; then
|
||||
OPTS=""
|
||||
else
|
||||
OPTS="--no-cache"
|
||||
fi
|
||||
|
||||
docker build ${OPTS} -t puremourning/vimspector:simple_python .
|
||||
9
support/test/python/simple_python/make_env.sh
Executable file
9
support/test/python/simple_python/make_env.sh
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
cat <<"EOF"
|
||||
{
|
||||
"Something": "Value1",
|
||||
"SomethingElse": "Value2"
|
||||
}
|
||||
EOF
|
||||
|
||||
15
support/test/python/simple_python/print_env.py
Normal file
15
support/test/python/simple_python/print_env.py
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
|
||||
|
||||
def Main():
|
||||
print( os.environ.get( 'Something', 'ERROR' ) )
|
||||
print( os.environ.get( 'SomethingElse', 'ERROR' ) )
|
||||
|
||||
for k, v in os.environ:
|
||||
print( f'{ k } = "{ v }"' )
|
||||
|
||||
|
||||
Main()
|
||||
|
||||
|
|
@ -1,9 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
PYTHON=python3
|
||||
|
||||
if [ -n "$1" ]; then
|
||||
PYTHON=$1
|
||||
if [ -z "$DEBUG_PORT" ]; then
|
||||
DEBUG_PORT=5678
|
||||
fi
|
||||
|
||||
pushd $(dirname $0)
|
||||
|
|
@ -11,10 +9,11 @@ pushd $(dirname $0)
|
|||
rm -rf env
|
||||
fi
|
||||
|
||||
$PYTHON -m venv env
|
||||
python3 -m venv env
|
||||
. env/bin/activate
|
||||
python -m pip install -r requirements.txt
|
||||
echo "using port $DEBUG_PORT"
|
||||
echo "*** Launching ***"
|
||||
python -m debugpy --wait-for-client --listen 0.0.0.0:5678 main.py
|
||||
python -m debugpy --wait-for-client --listen 0.0.0.0:${DEBUG_PORT} main.py
|
||||
popd
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
set SCALAR g
|
||||
array set ARRAY {key1 value1 key2 value2}
|
||||
|
||||
set LIST [list a b c {def} {g h i j} k l m]
|
||||
|
||||
proc Wrap { body } {
|
||||
uplevel 1 $body
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +1,12 @@
|
|||
function! SetUp()
|
||||
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||
call ThisTestIsFlaky()
|
||||
endfunction
|
||||
|
||||
function! ClearDown()
|
||||
call vimspector#test#setup#ClearDown()
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Mappings_Are_Added_HUMAN()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
||||
function! Test_Mappings_Are_Added_HUMAN()
|
||||
call assert_true( hasmapto( 'vimspector#Continue()' ) )
|
||||
call assert_false( hasmapto( 'vimspector#Launch()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Stop()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Restart()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOver()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepInto()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOut()' ) )
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Mappings_Are_Added_VISUAL_STUDIO()
|
||||
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
|
||||
endfunction
|
||||
|
||||
function! Test_Mappings_Are_Added_VISUAL_STUDIO()
|
||||
call assert_true( hasmapto( 'vimspector#Continue()' ) )
|
||||
call assert_false( hasmapto( 'vimspector#Launch()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Stop()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Restart()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOver()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepInto()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOut()' ) )
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Signs_Placed_Using_API_Are_Shown()
|
||||
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
|
||||
endfunction
|
||||
|
|
@ -78,68 +47,6 @@ function! Test_Signs_Placed_Using_API_Are_Shown()
|
|||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Use_Mappings_HUMAN()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
||||
function! Test_Use_Mappings_HUMAN()
|
||||
lcd testdata/cpp/simple
|
||||
edit simple.cpp
|
||||
call setpos( '.', [ 0, 15, 1 ] )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
|
||||
" Add the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Disable the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBPDisabled',
|
||||
\ 9 )
|
||||
|
||||
" Delete the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
|
||||
" Add it again
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Here we go. Start Debugging
|
||||
call feedkeys( "\<F5>", 'xt' )
|
||||
|
||||
call assert_equal( 2, len( gettabinfo() ) )
|
||||
let cur_tabnr = tabpagenr()
|
||||
call assert_equal( 5, len( gettabinfo( cur_tabnr )[ 0 ].windows ) )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||
|
||||
" Step
|
||||
call feedkeys( "\<F10>", 'xt' )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cp', 16 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_StopAtEntry()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
|
@ -200,8 +107,8 @@ function Test_DisableBreakpointWhileDebugging()
|
|||
\ 16 )
|
||||
\ } )
|
||||
|
||||
" Add the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call setpos( '.', [ 0, 1, 1 ] )
|
||||
call vimspector#SetLineBreakpoint( 'simple.cpp', 16 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorCode',
|
||||
|
|
@ -211,7 +118,6 @@ function Test_DisableBreakpointWhileDebugging()
|
|||
\ } )
|
||||
|
||||
" Run to breakpoint
|
||||
call setpos( '.', [ 0, 15, 1 ] )
|
||||
call feedkeys( "\<F5>", 'xt' )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call WaitForAssert( {->
|
||||
|
|
@ -258,6 +164,58 @@ function Test_DisableBreakpointWhileDebugging()
|
|||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
function! Test_Add_Breakpoints_In_File_Then_Open()
|
||||
lcd testdata/cpp/simple
|
||||
|
||||
" Set and clear without file open
|
||||
call vimspector#SetLineBreakpoint( 'simple.cpp', 16 )
|
||||
call vimspector#ClearLineBreakpoint( 'simple.cpp', 16 )
|
||||
|
||||
" Clear non-set breakpoint
|
||||
call vimspector#ClearLineBreakpoint( 'simple.cpp', 1 )
|
||||
|
||||
" Re-add
|
||||
call vimspector#SetLineBreakpoint( 'simple.cpp', 16 )
|
||||
|
||||
" Open and expect sign to be added
|
||||
edit simple.cpp
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 16,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
call vimspector#LaunchWithSettings( { 'configuration': 'run-to-breakpoint' } )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
function! Test_Add_Breakpoints_In_NonOpenedFile_RunToBreak()
|
||||
lcd testdata/cpp/simple
|
||||
|
||||
" add
|
||||
call vimspector#SetLineBreakpoint( 'simple.cpp', 16 )
|
||||
|
||||
call vimspector#LaunchWithSettings( {
|
||||
\ 'configuration': 'run-to-breakpoint-specify-file',
|
||||
\ 'prog': 'simple'
|
||||
\ } )
|
||||
call WaitFor( {-> bufexists( 'simple.cpp' ) } )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 )
|
||||
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 16,
|
||||
\ 'vimspectorPCBP',
|
||||
\ 200 )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Insert_Code_Above_Breakpoint()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
|
@ -308,7 +266,6 @@ function! Test_Insert_Code_Above_Breakpoint()
|
|||
" Delete it
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 26 )
|
||||
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Conditional_Line_Breakpoint()
|
||||
|
|
@ -323,8 +280,8 @@ function! Test_Conditional_Line_Breakpoint()
|
|||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
|
||||
|
||||
" Add the conditional breakpoint
|
||||
call feedkeys( "\\\<F9>argc==0\<CR>\<CR>", 'xt' )
|
||||
" Add the conditional breakpoint (note , is the mapleader)
|
||||
call feedkeys( ",\<F9>argc==0\<CR>\<CR>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 16,
|
||||
\ 'vimspectorBPCond',
|
||||
|
|
@ -360,8 +317,11 @@ function! Test_Conditional_Line_Breakpoint()
|
|||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
call setpos( '.', [ 0, 17, 1 ] )
|
||||
call vimspector#ToggleBreakpoint( { 'condition': 'argc == 1' } )
|
||||
call setpos( '.', [ 0, 1, 1 ] )
|
||||
call vimspector#SetLineBreakpoint(
|
||||
\ 'simple.cpp',
|
||||
\ 17,
|
||||
\ { 'condition': 'argc == 1' } )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 17,
|
||||
|
|
@ -400,8 +360,8 @@ function! Test_Conditional_Line_Breakpoint_Hit()
|
|||
exe 'edit' fn
|
||||
call setpos( '.', [ 0, 14, 1 ] )
|
||||
|
||||
" Add the conditional breakpoint (3 times)
|
||||
call feedkeys( "\\\<F9>\<CR>3\<CR>", 'xt' )
|
||||
" Add the conditional breakpoint (3 times) (note , is the mapleader)
|
||||
call feedkeys( ",\<F9>\<CR>3\<CR>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 14,
|
||||
|
|
@ -576,7 +536,7 @@ function! Test_Custom_Breakpoint_Priority()
|
|||
\ 'vimspectorBPDisabled',
|
||||
\ 4 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
|
||||
|
||||
call setpos( '.', [ 0, 17, 1 ] )
|
||||
call vimspector#ToggleBreakpoint( { 'condition': '1' } )
|
||||
|
|
@ -663,7 +623,7 @@ function! Test_Custom_Breakpoint_Priority_Partial()
|
|||
\ 'vimspectorBPDisabled',
|
||||
\ 4 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
|
||||
|
||||
call setpos( '.', [ 0, 17, 1 ] )
|
||||
call vimspector#ToggleBreakpoint( { 'condition': '1' } )
|
||||
|
|
@ -723,3 +683,72 @@ function! Test_Custom_Breakpoint_Priority_Partial()
|
|||
%bwipeout!
|
||||
unlet! g:vimspector_sign_priority
|
||||
endfunction
|
||||
|
||||
function! Test_Add_Line_BP_In_Other_File_While_Debugging()
|
||||
call ThisTestIsFlaky()
|
||||
let moo = 'moo.py'
|
||||
let cow = 'cow.py'
|
||||
lcd ../support/test/python/multiple_files
|
||||
exe 'edit' moo
|
||||
|
||||
call vimspector#Launch()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( moo, 1, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( moo, 1 )
|
||||
|
||||
call cursor( 6, 3 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( moo, 1 )
|
||||
call WaitForAssert( {->
|
||||
\vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 6,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 ) } )
|
||||
|
||||
exe 'edit' cow
|
||||
call cursor( 2, 1 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 6 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 2,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 ) } )
|
||||
|
||||
call vimspector#Continue()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( moo, 6, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( moo, 6 )
|
||||
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 2 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 6,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 6,
|
||||
\ 'vimspectorPCBP',
|
||||
\ 200 )
|
||||
|
||||
call vimspector#Continue()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( cow, 2, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( cow, 2 )
|
||||
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 6 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 2,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 2,
|
||||
\ 'vimspectorPCBP',
|
||||
\ 200 )
|
||||
|
||||
lcd -
|
||||
call vimspector#test#setup#Reset()
|
||||
%bwipe!
|
||||
endfunction
|
||||
|
|
|
|||
|
|
@ -1,44 +1,13 @@
|
|||
function! SetUp()
|
||||
set ambiwidth=double
|
||||
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||
call ThisTestIsFlaky()
|
||||
endfunction
|
||||
|
||||
function! ClearDown()
|
||||
call vimspector#test#setup#ClearDown()
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Mappings_Are_Added_HUMAN()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
||||
function! Test_Mappings_Are_Added_HUMAN()
|
||||
call assert_true( hasmapto( 'vimspector#Continue()' ) )
|
||||
call assert_false( hasmapto( 'vimspector#Launch()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Stop()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Restart()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOver()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepInto()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOut()' ) )
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Mappings_Are_Added_VISUAL_STUDIO()
|
||||
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
|
||||
endfunction
|
||||
|
||||
function! Test_Mappings_Are_Added_VISUAL_STUDIO()
|
||||
call assert_true( hasmapto( 'vimspector#Continue()' ) )
|
||||
call assert_false( hasmapto( 'vimspector#Launch()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Stop()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Restart()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOver()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepInto()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOut()' ) )
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Signs_Placed_Using_API_Are_Shown()
|
||||
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
|
||||
endfunction
|
||||
|
|
@ -132,7 +101,7 @@ function! Test_Use_Mappings_HUMAN()
|
|||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cp', 16 )
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
|
|
@ -324,8 +293,8 @@ function! Test_Conditional_Line_Breakpoint()
|
|||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
|
||||
|
||||
" Add the conditional breakpoint
|
||||
call feedkeys( "\\\<F9>argc==0\<CR>\<CR>", 'xt' )
|
||||
" Add the conditional breakpoint (, is mapleader)
|
||||
call feedkeys( ",\<F9>argc==0\<CR>\<CR>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 16,
|
||||
\ 'vimspectorBPCond',
|
||||
|
|
@ -401,8 +370,8 @@ function! Test_Conditional_Line_Breakpoint_Hit()
|
|||
exe 'edit' fn
|
||||
call setpos( '.', [ 0, 14, 1 ] )
|
||||
|
||||
" Add the conditional breakpoint (3 times)
|
||||
call feedkeys( "\\\<F9>\<CR>3\<CR>", 'xt' )
|
||||
" Add the conditional breakpoint (3 times) (, is mapleader)
|
||||
call feedkeys( ",\<F9>\<CR>3\<CR>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 14,
|
||||
|
|
@ -577,7 +546,7 @@ function! Test_Custom_Breakpoint_Priority()
|
|||
\ 'vimspectorBPDisabled',
|
||||
\ 4 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
|
||||
|
||||
call setpos( '.', [ 0, 17, 1 ] )
|
||||
call vimspector#ToggleBreakpoint( { 'condition': '1' } )
|
||||
|
|
@ -664,7 +633,7 @@ function! Test_Custom_Breakpoint_Priority_Partial()
|
|||
\ 'vimspectorBPDisabled',
|
||||
\ 4 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 16 )
|
||||
|
||||
call setpos( '.', [ 0, 17, 1 ] )
|
||||
call vimspector#ToggleBreakpoint( { 'condition': '1' } )
|
||||
|
|
@ -724,3 +693,73 @@ function! Test_Custom_Breakpoint_Priority_Partial()
|
|||
%bwipeout!
|
||||
unlet! g:vimspector_sign_priority
|
||||
endfunction
|
||||
|
||||
|
||||
function! Test_Add_Line_BP_In_Other_File_While_Debugging()
|
||||
call ThisTestIsFlaky()
|
||||
let moo = 'moo.py'
|
||||
let cow = 'cow.py'
|
||||
lcd ../support/test/python/multiple_files
|
||||
exe 'edit' moo
|
||||
|
||||
call vimspector#Launch()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( moo, 1, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( moo, 1 )
|
||||
|
||||
call cursor( 6, 3 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( moo, 1 )
|
||||
call WaitForAssert( {->
|
||||
\vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 6,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 ) } )
|
||||
|
||||
exe 'edit' cow
|
||||
call cursor( 2, 1 )
|
||||
call vimspector#ToggleBreakpoint()
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 6 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 2,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 ) } )
|
||||
|
||||
call vimspector#Continue()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( moo, 6, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( moo, 6 )
|
||||
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 2 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 6,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 6,
|
||||
\ 'vimspectorPCBP',
|
||||
\ 200 )
|
||||
|
||||
call vimspector#Continue()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( cow, 2, 1 )
|
||||
call vimspector#test#signs#AssertPCIsAtLineInBuffer( cow, 2 )
|
||||
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorCode', 6 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 2,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
call vimspector#test#signs#AssertSignAtLine(
|
||||
\ 'VimspectorCode',
|
||||
\ 2,
|
||||
\ 'vimspectorPCBP',
|
||||
\ 200 )
|
||||
|
||||
lcd -
|
||||
call vimspector#test#setup#Reset()
|
||||
%bwipe!
|
||||
endfunction
|
||||
|
|
|
|||
|
|
@ -4,8 +4,19 @@ ENV DEBIAN_FRONTEND=noninteractive
|
|||
ENV LC_ALL C.UTF-8
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl \
|
||||
dirmngr \
|
||||
apt-transport-https \
|
||||
lsb-release \
|
||||
ca-certificates \
|
||||
software-properties-common && \
|
||||
curl -sL https://deb.nodesource.com/setup_12.x | bash - && \
|
||||
add-apt-repository ppa:bartbes/love-stable -y && \
|
||||
apt-get update && \
|
||||
apt-get -y dist-upgrade && \
|
||||
apt-get -y install python3-dev \
|
||||
apt-get -y install gcc-8 \
|
||||
g++-8 \
|
||||
python3-dev \
|
||||
python3-pip \
|
||||
python3-venv \
|
||||
ca-cacert \
|
||||
|
|
@ -17,14 +28,18 @@ RUN apt-get update && \
|
|||
tcllib \
|
||||
gdb \
|
||||
lldb \
|
||||
curl \
|
||||
nodejs \
|
||||
npm && \
|
||||
lua5.1 \
|
||||
luajit \
|
||||
love && \
|
||||
apt-get -y autoremove
|
||||
|
||||
RUN ln -fs /usr/share/zoneinfo/Europe/London /etc/localtime && \
|
||||
dpkg-reconfigure --frontend noninteractive tzdata
|
||||
|
||||
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 1 \
|
||||
--slave /usr/bin/g++ g++ /usr/bin/g++-8
|
||||
|
||||
## cleanup of files from setup
|
||||
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
|
|
@ -55,6 +70,12 @@ RUN mkdir -p /home/linuxbrew/.linuxbrew &&\
|
|||
|
||||
RUN /home/linuxbrew/.linuxbrew/bin/brew install golang
|
||||
|
||||
# dotnet
|
||||
RUN curl -sSL https://dot.net/v1/dotnet-install.sh \
|
||||
| bash /dev/stdin --channel LTS --install-dir /usr/share/dotnet && \
|
||||
update-alternatives --install /usr/bin/dotnet dotnet \
|
||||
/usr/share/dotnet/dotnet 1
|
||||
|
||||
# clean up
|
||||
RUN /home/linuxbrew/.linuxbrew/bin/brew cleanup && \
|
||||
rm -rf ~/.cache && \
|
||||
|
|
|
|||
22
tests/get_configurations.test.vim
Normal file
22
tests/get_configurations.test.vim
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
function! SetUp()
|
||||
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||
endfunction
|
||||
|
||||
function! ClearDown()
|
||||
call vimspector#test#setup#ClearDown()
|
||||
endfunction
|
||||
|
||||
function Test_Get_Configurations()
|
||||
lcd ../support/test/csharp/
|
||||
|
||||
let configs = vimspector#GetConfigurations()
|
||||
call assert_equal([
|
||||
\ 'launch - netcoredbg',
|
||||
\ 'launch - netcoredbg - with debug log',
|
||||
\ 'launch - mono',
|
||||
\ ], configs)
|
||||
|
||||
lcd -
|
||||
%bwipe!
|
||||
endfunction
|
||||
|
||||
65
tests/language_csharp.test.vim
Normal file
65
tests/language_csharp.test.vim
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
function! SetUp()
|
||||
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||
endfunction
|
||||
|
||||
function! ClearDown()
|
||||
call vimspector#test#setup#ClearDown()
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Go_Simple()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
||||
function! Test_CSharp_Simple()
|
||||
let fn='Program.cs'
|
||||
lcd ../support/test/csharp
|
||||
exe 'edit ' . fn
|
||||
|
||||
call vimspector#SetLineBreakpoint( fn, 31 )
|
||||
call vimspector#LaunchWithSettings( {
|
||||
\ 'configuration': 'launch - netcoredbg'
|
||||
\ } )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 )
|
||||
\ } )
|
||||
|
||||
call vimspector#StepOver()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 32, 12 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 32 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
|
||||
function! Test_Run_To_Cursor()
|
||||
let fn='Program.cs'
|
||||
lcd ../support/test/csharp
|
||||
exe 'edit ' . fn
|
||||
|
||||
call vimspector#SetLineBreakpoint( fn, 31 )
|
||||
call vimspector#LaunchWithSettings( {
|
||||
\ 'configuration': 'launch - netcoredbg'
|
||||
\ } )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 31, 7 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 31 )
|
||||
\ } )
|
||||
|
||||
call cursor( 33, 1 )
|
||||
call vimspector#RunToCursor()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 33, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 33 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
|
|
@ -45,3 +45,28 @@ function! Test_Go_Simple()
|
|||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
|
||||
function! Test_Run_To_Cursor()
|
||||
let fn='hello-world.go'
|
||||
lcd ../support/test/go/hello_world
|
||||
exe 'edit ' . fn
|
||||
|
||||
call vimspector#SetLineBreakpoint( fn, 4 )
|
||||
call vimspector#Launch()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 4, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 4 )
|
||||
\ } )
|
||||
|
||||
call cursor( 5, 1 )
|
||||
call vimspector#RunToCursor()
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 5, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 5 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
|
|
|||
74
tests/language_lua.test.vim
Normal file
74
tests/language_lua.test.vim
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
function! SetUp()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||
endfunction
|
||||
|
||||
function! ClearDown()
|
||||
call vimspector#test#setup#ClearDown()
|
||||
endfunction
|
||||
|
||||
|
||||
function! BaseTest( configuration )
|
||||
let fn='simple.lua'
|
||||
lcd ../support/test/lua/simple
|
||||
exe 'edit ' . fn
|
||||
|
||||
call vimspector#SetLineBreakpoint( fn, 5 )
|
||||
call vimspector#LaunchWithSettings( { 'configuration': a:configuration } )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 5, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 5 )
|
||||
\ } )
|
||||
|
||||
" Step
|
||||
call feedkeys( "\<F10>", 'xt' )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 6, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 6 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
|
||||
function! Test_Lua_Simple()
|
||||
call BaseTest( 'lua' )
|
||||
endfunction
|
||||
|
||||
|
||||
function! Test_Lua_Luajit()
|
||||
call BaseTest( 'luajit' )
|
||||
endfunction
|
||||
|
||||
|
||||
function! Test_Lua_Love()
|
||||
let fn='main.lua'
|
||||
lcd ../support/test/lua/love-headless
|
||||
exe 'edit ' . fn
|
||||
|
||||
call vimspector#SetLineBreakpoint( fn, 8 )
|
||||
call vimspector#LaunchWithSettings( { 'configuration': 'love' } )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 8, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 8 )
|
||||
\ } )
|
||||
|
||||
" Step
|
||||
call feedkeys( "\<F10>", 'xt' )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( fn, 9, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( fn, 9 )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
|
@ -50,3 +50,59 @@ function! vimspector#test#setup#Reset() abort
|
|||
call popup_clear()
|
||||
endfunction
|
||||
|
||||
let s:g_stack = {}
|
||||
|
||||
function! vimspector#test#setup#PushGlobal( name, value ) abort
|
||||
if !has_key( s:g_stack, a:name )
|
||||
let s:g_stack[ a:name ] = []
|
||||
endif
|
||||
|
||||
let old_value = get( g:, a:name, v:null )
|
||||
call add( s:g_stack[ a:name ], old_value )
|
||||
let g:[ a:name ] = a:value
|
||||
|
||||
return old_value
|
||||
endfunction
|
||||
|
||||
function! vimspector#test#setup#PopGlobal( name ) abort
|
||||
if !has_key( s:g_stack, a:name ) || len( s:g_stack[ a:name ] ) == 0
|
||||
return v:null
|
||||
endif
|
||||
|
||||
let old_value = s:g_stack[ a:name ][ -1 ]
|
||||
call remove( s:g_stack[ a:name ], -1 )
|
||||
|
||||
if old_value is v:null
|
||||
silent! call remove( g:, a:name )
|
||||
else
|
||||
let g:[ a:name ] = old_value
|
||||
endif
|
||||
|
||||
return old_value
|
||||
endfunction
|
||||
|
||||
let s:o_stack = {}
|
||||
|
||||
function! vimspector#test#setup#PushOption( name, value ) abort
|
||||
if !has_key( s:o_stack, a:name )
|
||||
let s:o_stack[ a:name ] = []
|
||||
endif
|
||||
|
||||
let old_value = v:null
|
||||
execute 'let old_value = &' . a:name
|
||||
call add( s:o_stack[ a:name ], old_value )
|
||||
execute 'set ' . a:name . '=' . a:value
|
||||
return old_value
|
||||
endfunction
|
||||
|
||||
function! vimspector#test#setup#PopOption( name ) abort
|
||||
if !has_key( s:o_stack, a:name ) || len( s:o_stack[ a:name ] ) == 0
|
||||
return v:null
|
||||
endif
|
||||
|
||||
let old_value = s:o_stack[ a:name ][ -1 ]
|
||||
call remove( s:o_stack[ a:name ], -1 )
|
||||
|
||||
execute 'set ' . a:name . '=' . old_value
|
||||
return old_value
|
||||
endfunction
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
function! vimspector#test#signs#AssertCursorIsAtLineInBuffer( buffer,
|
||||
\ line,
|
||||
\ column ) abort
|
||||
call WaitFor( {-> bufexists( a:buffer ) } )
|
||||
call WaitForAssert( {->
|
||||
\ assert_equal( fnamemodify( a:buffer, ':p' ),
|
||||
\ fnamemodify( bufname( '%' ), ':p' ),
|
||||
|
|
@ -15,6 +16,7 @@ function! vimspector#test#signs#AssertCursorIsAtLineInBuffer( buffer,
|
|||
endfunction
|
||||
|
||||
function! vimspector#test#signs#AssertPCIsAtLineInBuffer( buffer, line ) abort
|
||||
call WaitFor( {-> bufexists( a:buffer ) } )
|
||||
let signs = sign_getplaced( a:buffer, {
|
||||
\ 'group': 'VimspectorCode',
|
||||
\ } )
|
||||
|
|
@ -70,7 +72,11 @@ function! vimspector#test#signs#AssertSignGroupSingletonAtLine( group,
|
|||
endfunction
|
||||
|
||||
|
||||
function! vimspector#test#signs#AssertSignAtLine( group, line, sign_name, priority ) abort
|
||||
function! vimspector#test#signs#AssertSignAtLine(
|
||||
\ group,
|
||||
\ line,
|
||||
\ sign_name,
|
||||
\ priority ) abort
|
||||
|
||||
let signs = sign_getplaced( '%', {
|
||||
\ 'group': a:group,
|
||||
|
|
@ -106,7 +112,7 @@ endfunction
|
|||
function! vimspector#test#signs#AssertSignGroupEmptyAtLine( group, line ) abort
|
||||
let signs = sign_getplaced( '%', {
|
||||
\ 'group': a:group,
|
||||
\ 'lnum': line( '.' )
|
||||
\ 'lnum': a:line,
|
||||
\ } )
|
||||
|
||||
return assert_equal( 1,
|
||||
|
|
|
|||
|
|
@ -51,7 +51,10 @@ func s:WaitForCommon(expr, assert, timeout)
|
|||
let start = reltime()
|
||||
endif
|
||||
|
||||
let iters = 0
|
||||
|
||||
while 1
|
||||
let iters += 1
|
||||
let errors_before = len( v:errors )
|
||||
if type(a:expr) == v:t_func
|
||||
let success = a:expr()
|
||||
|
|
@ -65,6 +68,10 @@ func s:WaitForCommon(expr, assert, timeout)
|
|||
return slept
|
||||
endif
|
||||
|
||||
if iters % 20 == 0
|
||||
redraw!
|
||||
endif
|
||||
|
||||
if slept >= a:timeout
|
||||
break
|
||||
endif
|
||||
|
|
@ -91,3 +98,31 @@ endfunc
|
|||
function! ThisTestIsFlaky()
|
||||
let g:test_is_flaky = v:true
|
||||
endfunction
|
||||
|
||||
function! AssertMatchList( expected, actual ) abort
|
||||
let ret = assert_equal( len( a:expected ), len( a:actual ) )
|
||||
let len = min( [ len( a:expected ), len( a:actual ) ] )
|
||||
let idx = 0
|
||||
while idx < len
|
||||
let ret += assert_match( a:expected[ idx ], a:actual[ idx ] )
|
||||
let idx += 1
|
||||
endwhile
|
||||
return ret
|
||||
endfunction
|
||||
|
||||
|
||||
function! GetBufLine( buf, start, end = '$' )
|
||||
if type( a:start ) != v:t_string && a:start < 0
|
||||
let start = getbufinfo( a:buf )[ 0 ].linecount + a:start
|
||||
else
|
||||
let start = a:start
|
||||
endif
|
||||
|
||||
if type( a:end ) != v:t_string && a:end < 0
|
||||
let end = getbufinfo( a:buf )[ 0 ].linecount + a:end
|
||||
else
|
||||
let end = a:end
|
||||
endif
|
||||
|
||||
return getbufline( a:buf, start, end )
|
||||
endfunction
|
||||
|
|
|
|||
|
|
@ -82,6 +82,16 @@ func! Abort( timer_id )
|
|||
qa!
|
||||
endfunc
|
||||
|
||||
func! TestLog( msg )
|
||||
if type( a:msg ) == v:t_string
|
||||
let msg = [ a:msg ]
|
||||
else
|
||||
let msg = a:msg
|
||||
endif
|
||||
|
||||
call extend( s:messages, msg )
|
||||
endfunc
|
||||
|
||||
func RunTheTest(test)
|
||||
echo 'Executing ' . a:test
|
||||
|
||||
|
|
@ -152,8 +162,6 @@ func RunTheTest(test)
|
|||
augroup END
|
||||
|
||||
exe 'call ' . a:test
|
||||
|
||||
au! EarlyExit
|
||||
catch /^\cskipped/
|
||||
call add(s:messages, ' Skipped')
|
||||
call add(s:skipped,
|
||||
|
|
@ -193,6 +201,8 @@ func RunTheTest(test)
|
|||
call s:TestFailed()
|
||||
endtry
|
||||
|
||||
au! EarlyExit
|
||||
|
||||
call timer_stop( timer )
|
||||
|
||||
" In case 'insertmode' was set and something went wrong, make sure it is
|
||||
|
|
@ -371,7 +381,7 @@ for s:test in sort(s:tests)
|
|||
if len(v:errors) > 0
|
||||
\ && $TEST_NO_RETRY == ''
|
||||
\ && g:test_is_flaky
|
||||
for retry in range( 5 )
|
||||
for retry in range( 10 )
|
||||
call add( s:messages, 'Found errors in ' . s:test . '. Retrying.' )
|
||||
call extend( s:messages, v:errors )
|
||||
|
||||
|
|
|
|||
143
tests/mappings.test.vim
Normal file
143
tests/mappings.test.vim
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
function! SetUp()
|
||||
call vimspector#test#setup#SetUpWithMappings( v:none )
|
||||
endfunction
|
||||
|
||||
function! ClearDown()
|
||||
call vimspector#test#setup#ClearDown()
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Mappings_Are_Added_HUMAN()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
||||
function! Test_Mappings_Are_Added_HUMAN()
|
||||
call assert_true( hasmapto( 'vimspector#Continue()' ) )
|
||||
call assert_false( hasmapto( 'vimspector#Launch()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Stop()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Restart()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOver()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepInto()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOut()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#RunToCursor()' ) )
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Mappings_Are_Added_VISUAL_STUDIO()
|
||||
let g:vimspector_enable_mappings = 'VISUAL_STUDIO'
|
||||
endfunction
|
||||
|
||||
function! Test_Mappings_Are_Added_VISUAL_STUDIO()
|
||||
call assert_true( hasmapto( 'vimspector#Continue()' ) )
|
||||
call assert_false( hasmapto( 'vimspector#Launch()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Stop()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#Restart()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#ToggleBreakpoint()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#AddFunctionBreakpoint' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOver()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepInto()' ) )
|
||||
call assert_true( hasmapto( 'vimspector#StepOut()' ) )
|
||||
endfunction
|
||||
|
||||
function! SetUp_Test_Use_Mappings_HUMAN()
|
||||
let g:vimspector_enable_mappings = 'HUMAN'
|
||||
endfunction
|
||||
|
||||
function! Test_Use_Mappings_HUMAN()
|
||||
call ThisTestIsFlaky()
|
||||
lcd testdata/cpp/simple
|
||||
edit simple.cpp
|
||||
call setpos( '.', [ 0, 15, 1 ] )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
|
||||
" Add the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Disable the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBPDisabled',
|
||||
\ 9 )
|
||||
|
||||
" Delete the breakpoint
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
|
||||
" Add and clear using API
|
||||
call vimspector#SetLineBreakpoint( 'simple.cpp', 15 )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine( 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
call vimspector#ClearLineBreakpoint( 'simple.cpp', 15 )
|
||||
call vimspector#test#signs#AssertSignGroupEmptyAtLine( 'VimspectorBP', 15 )
|
||||
|
||||
" Add it again
|
||||
call feedkeys( "\<F9>", 'xt' )
|
||||
call vimspector#test#signs#AssertSignGroupSingletonAtLine(
|
||||
\ 'VimspectorBP',
|
||||
\ 15,
|
||||
\ 'vimspectorBP',
|
||||
\ 9 )
|
||||
|
||||
" Here we go. Start Debugging
|
||||
call feedkeys( "\<F5>", 'xt' )
|
||||
|
||||
call assert_equal( 2, len( gettabinfo() ) )
|
||||
let cur_tabnr = tabpagenr()
|
||||
call assert_equal( 5, len( gettabinfo( cur_tabnr )[ 0 ].windows ) )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 15, 1 )
|
||||
|
||||
" Step
|
||||
call feedkeys( "\<F10>", 'xt' )
|
||||
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 16, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 16 )
|
||||
\ } )
|
||||
|
||||
" Run to cursor (note , is the mapleader)
|
||||
call cursor( 9, 1 )
|
||||
call feedkeys( ",\<F8>", 'xt' )
|
||||
call vimspector#test#signs#AssertCursorIsAtLineInBuffer( 'simple.cpp', 9, 1 )
|
||||
call WaitForAssert( {->
|
||||
\ vimspector#test#signs#AssertPCIsAtLineInBuffer( 'simple.cpp', 9 )
|
||||
\ } )
|
||||
|
||||
" Stop
|
||||
call feedkeys( "\<F3>", 'xt' )
|
||||
call WaitForAssert( {->
|
||||
\ assert_equal( [],
|
||||
\ getbufline( g:vimspector_session_windows.variables,
|
||||
\ 1,
|
||||
\ '$' ) )
|
||||
\ } )
|
||||
call WaitForAssert( {->
|
||||
\ assert_equal( [],
|
||||
\ getbufline( g:vimspector_session_windows.stack_trace,
|
||||
\ 1,
|
||||
\ '$' ) )
|
||||
\ } )
|
||||
call WaitForAssert( {->
|
||||
\ assert_equal( [],
|
||||
\ getbufline( g:vimspector_session_windows.watches,
|
||||
\ 1,
|
||||
\ '$' ) )
|
||||
\ } )
|
||||
|
||||
call vimspector#test#setup#Reset()
|
||||
|
||||
lcd -
|
||||
%bwipeout!
|
||||
endfunction
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue