microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
164.94k stars 29.52k forks source link

When Debug: Inline Values is set together with Word wrap, breakpoints are not correctly focused #150083

Open ldorigo opened 2 years ago

ldorigo commented 2 years ago

Issue Type: Bug

As the title shows, having word wrap enabled together with Debug: Inline values causes the debugger to focus the editor in the incorrect place when pausing on a breakpoint.

It appears to be because it first focuses on the relevant line, and only then displays the inline values, which then wrap at the line length limit and cause the breakpoint line to move further down.

To reproduce just debug a long file with values whose repr doesn't fit on a single line, (simple example at the end of the issue), and set a breakpoint on one of the last lines.

Screenshot: Screenshot_20220521_145704

Notice how the debugger viewlet shows that the debugger is paused on line 67, but since each line shows an inline value that takes 2 lines when wrapping, the editor is incorrectly focused on half of that (around line 33).

I don't know if the fix should be to delay focusing the breakpointed line until after the inline values have been displayed, or to ignore the word wrap setting for inline values --- wrapping them usually just makes them hard to read and I usually just toggle word wrap in these cases.

Simple example:

x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
breakpoint()
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}
x = {i: x for i, x in enumerate(range(500))}

VS Code version: Code 1.67.2 (c3511e6c69bb39013c4a4b7b9566ec1ca73fc4d5, 2022-05-17T18:23:40.286Z) OS version: Linux x64 5.15.37-1-lts Restricted Mode: No

System Info |Item|Value| |---|---| |CPUs|AMD Ryzen 7 3700X 8-Core Processor (16 x 4239)| |GPU Status|2d_canvas: enabled
canvas_oop_rasterization: disabled_off
direct_rendering_display_compositor: disabled_off_ok
gpu_compositing: enabled
multiple_raster_threads: enabled_on
oop_rasterization: disabled_off
opengl: enabled_on
rasterization: disabled_software
raw_draw: disabled_off_ok
skia_renderer: enabled_on
video_decode: disabled_software
video_encode: disabled_software
vulkan: disabled_off
webgl: enabled
webgl2: enabled| |Load (avg)|1, 1, 1| |Memory (System)|31.36GB (0.69GB free)| |Process Argv|--crash-reporter-id 66ea3ec9-05eb-4edd-8d35-34bbe6c1aba1| |Screen Reader|no| |VM|0%| |DESKTOP_SESSION|plasma-i3| |XDG_CURRENT_DESKTOP|KDE| |XDG_SESSION_DESKTOP|KDE-i3| |XDG_SESSION_TYPE|x11|
Extensions (59) Extension|Author (truncated)|Version ---|---|--- vscode-sqlite|ale|0.14.0 docs-view|bie|0.0.11 path-intellisense|chr|2.8.0 clippy-ai|cli|0.3.2 gitignore|cod|0.7.0 systemd-unit-file|coo|1.0.6 vscode-office|cwe|2.5.4 vscode-markdownlint|Dav|0.47.0 githistory|don|0.6.19 xml|Dot|2.5.1 copilot-nightly|Git|1.22.5959 vscode-pull-request-github|Git|0.42.0 gitkraken-authentication|git|1.0.3 gitignore-templates|has|1.0.1 beautify|Hoo|1.5.0 latex-workshop|Jam|8.26.0 vscode-edit-csv|jan|0.6.9 svg|joc|1.4.18 vscode-map-preview|jum|0.5.9 restructuredtext|lex|189.0.0 bash-ide-vscode|mad|1.13.0 rainbow-csv|mec|2.3.0 gitignore|mic|1.0.1 vscode-docker|ms-|1.22.0 csharp|ms-|1.24.4 black-formatter|ms-|2022.1.11371002 gather|ms-|2022.3.0 python|ms-|2022.6.2 vscode-pylance|ms-|2022.5.2 jupyter|ms-|2022.4.1021342353 jupyter-keymap|ms-|1.0.0 jupyter-renderers|ms-|1.0.6 remote-containers|ms-|0.234.0 remote-ssh|ms-|0.80.0 remote-ssh-edit|ms-|0.80.0 cmake-tools|ms-|1.10.5 cpptools|ms-|1.9.8 hexeditor|ms-|1.9.6 vscode-python-typehint|njq|1.4.1 platformio-ide|pla|2.4.3 show-offset|ram|0.0.4 bash-debug|rog|0.3.9 zsh-debug|rog|0.1.3 jinjahtml|sam|0.17.0 git-merger|sha|0.4.1 wav-preview|suk|2.0.2 cython|tcw|0.1.0 html-preview-vscode|tht|0.2.5 shellcheck|tim|0.19.3 simple-rst|tro|1.5.2 cmake|twx|0.0.17 lorem-ipsum|Tyr|1.3.1 vscodeintellicode|Vis|1.2.21 vscode-icons|vsc|11.11.0 vim|vsc|1.22.2 gitblame|wad|8.2.0 markdown-all-in-one|yzh|3.4.3 json|Zai|2.0.2 grammarly|znc|0.22.0 (7 theme extensions excluded)
roblourens commented 2 years ago

Seems that we move the cursor to the right place, but when the wrapped decorations show up, the active line is not revealed. Seems like we would want to keep that in view.

But then in this state, I can't cursorDown at all. Can my my cursor in every other direction.

Recording 2022-05-23 at 10 29 21

lobsterkatie commented 1 year ago

I am still experiencing this, in both JS and Python. I'm using VSCode 1.77.0, but it's been happening for months. (I do think it's a regression, though, because I've had the same inline values and wrapping settings for years, and this only started happening some time in 2022.)

jpike88 commented 1 year ago

This bug is slowly driving me nuts. I sometimes have word wrap enabled, and it's jarring to have to adjust my scroll often while I work.

hediet commented 1 year ago

I can verify the reveal line issue, but I think this is a problem of the debugger feature (revealing line and then inserting inline values with line breaks will push lines below out of view), thus assigning this issue back to @roblourens. You may want to wait until all inline values show before you reveal the active line.

I created #186628 for the cursor issue.

roblourens commented 1 year ago

@hediet if I understand the code correctly, it's the other way around because when the editor scrolls, we show inline values for whatever the visible range is. So if the inline value decorations will make the editor scroll away, I need to scroll the editor once, then wait for the decorations to update, then scroll it again. That's pretty awkward. Is there some way that I can anchor the scroll position when adding the decorations?

hediet commented 1 year ago

So if the inline value decorations will make the editor scroll away, I need to scroll the editor once, then wait for the decorations to update, then scroll it again.

Until it converges, yes...

I can anchor the scroll position when adding the decorations?

By default it is anchored to the top line in the view port. I don't know if we can anchor it to the cursor. How would the API look like?

roblourens commented 1 year ago

I think anchoring it to the cursor makes more sense as a default, if it's in the viewport, isn't that likely where my attention is?

Otherwise, to me it seems like this needs to be part of the call to move the cursor, not the calls to show decorations. I think it makes more sense to say "reveal this line (even if decorations try to push it away)" rather than "show this decoration (and if it causes a scroll, anchor to the cursor)"

hediet commented 1 year ago

@alexdima what do you think? Currently the viewport is anchored by default to the first visible line. Should we change that to the line the cursor is in if the cursor is in the viewport (if not, fall back to the first visible line)?