Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(diagnostic)!: replace 'show_*' functions with 'open_float' #16057

Merged
merged 4 commits into from
Oct 19, 2021

Conversation

gpanders
Copy link
Member

@gpanders gpanders commented Oct 17, 2021

show_line_diagnostics() and show_position_diagnostics() are almost identical; they differ only in the fact that the latter also accepts a column to form a full position, rather than just a line. This is not enough to justify two separate interfaces for this common functionality.

Renaming this to simply show_diagnostics() is one step forward, but that is also not a good name as the _diagnostics() suffix is redundant. However, we cannot name it simply show() since that function already exists with entirely different semantics.

Instead, combine these two into a single open_float() function that handles all of the cases of previewing diagnostics in a floating window. Also add a "float" key to vim.diagnostic.config() to provide global values of configuration options that can be overridden ephemerally. This makes the preview API consistent with the rest of the diagnostic API.

This is a breaking change.

Differences in API usage:

Before After
vim.diagnostic.show_line_diagnostics() vim.diagnostic.open_float(0, {scope="line"})
vim.diagnostic.show_position_diagnostics() vim.diagnostic.open_float(0, {scope="cursor"})
vim.diagnostic.goto_next { enable_popup = true, popup_opts = {...} vim.diagnostic.goto_next { float = {...} }
vim.diagnostic.show_line_diagnostics({opts}, buffer, 17) vim.diagnostic.open_float(buffer, {{opts}, scope="line", pos=17}
vim.diagnostic.show_position_diagnositcs({opts}, buffer, {row, col}) vim.diagnostic.open_float(buffer, {{opts}, scope="cursor", pos={row, col}}

@github-actions github-actions bot added diagnostic lsp lua stdlib refactor changes that are not features or bugfixes labels Oct 17, 2021
@clason
Copy link
Member

clason commented Oct 17, 2021

This is a breaking change.

Worth it :) (Especially with that handy migration table ❤️ )

@clason
Copy link
Member

clason commented Oct 17, 2021

Not perfectly sold on the where keyword, though -- that could be mistaken for the location of the float (although that would properly be set in the options table)?

But the alternatives I can come up with (at, location) have the same problem...

EDIT from, maybe?

@gpanders
Copy link
Member Author

Not perfectly sold on the where keyword, though -- that could be mistaken for the location of the float (although that would properly be set in the options table)?

But the alternatives I can come up with (at, location) have the same problem...

EDIT from, maybe?

Maybe scope?

@mjlbach
Copy link
Contributor

mjlbach commented Oct 17, 2021

I also prefer float over popup where possible, and would favor an enum over string based scope. Also, I kinda like show more than preview, as preview implies a slice of diagnostics, which you could argue is a slice of the diagnostic cache, but I like the semantics of show more and would also favor reworking other usages of it.

If we're doing this breaking change, I would also favor at the same time handling the deprecations of all of the lsp.diagnostics holdover, so we avoid multiple breaking changes, and merging this around the 0.6 feature freeze.

@mjlbach
Copy link
Contributor

mjlbach commented Oct 17, 2021

Also we should fix the flakey win32 test (unrelated to this PR, just noting). Gradually these windows tests are becoming more and more reliable...

2021-10-17T16:39:27.9031288Z   [  FAILED  ] test/functional\core\job_spec.lua @ 877: jobs jobstop() kills entire process tree #6530
2021-10-17T16:39:27.9032173Z   test/functional\core\job_spec.lua:949: retry() attempts: 428
2021-10-17T16:39:27.9033006Z   test\helpers.lua:73: Expected objects to be the same.
2021-10-17T16:39:27.9063321Z   Passed in:
2021-10-17T16:39:27.9063978Z   (boolean) false
2021-10-17T16:39:27.9064556Z   Expected:
2021-10-17T16:39:27.9065103Z   (boolean) true

@kylo252
Copy link
Contributor

kylo252 commented Oct 17, 2021

This is looking great already ❤️

I'm still not sure about the function name as I feel it can suggest that there's a more detailed diagnostics view, when in most cases the "preview" is all you're gonna get anyway. I think it might be worth it to (re-)consider vim.diagnostic.show_hover() instead.

@gpanders
Copy link
Member Author

I also prefer float over popup where possible

I don't think there are any (user-visible) instances of "popup" anywhere (except for the return type of preview()), please correct me if I'm wrong.

and would favor an enum over string based scope.

I would too, but with module scopes an enum quickly becomes unwieldy: vim.diagnostic.preview.BUFFER vs "buffer". That's why I stuck with a string. Maybe that's fine though since this function won't ever be called interactively.

Also, I kinda like show more than preview, as preview implies a slice of diagnostics, which you could argue is a slice of the diagnostic cache, but I like the semantics of show more and would also favor reworking other usages of it.

IMO show() and hide() are good names for what they do right now; namely, showing persistent decorations for diagnostics (virt text, signs, highlights, etc.). preview() is a "preview" in that it only shows ephemerally, it does not persist in the buffer in any way. Besides, the function that preview() calls is itself called open_floating_preview(), so there's precedent.

If we're doing this breaking change, I would also favor at the same time handling the deprecations of all of the lsp.diagnostics holdover, so we avoid multiple breaking changes, and merging this around the 0.6 feature freeze.

Are you suggesting hard-deprecating lsp.diagnostics by removing those functions completely? I'm not sure I agree with that approach, I think I'd favor introducing vim.diagnostic and soft-deprecating lsp.diagnostics (we can show an info message when these functions are used warning that they are deprecated. vim-fugitive did this IIRC) in 0.6 and then hard-deprecating (removing) them in the next release.

@mjlbach
Copy link
Contributor

mjlbach commented Oct 17, 2021

I don't think there are any (user-visible) instances of "popup" anywhere (except for the return type of preview()), please correct me if I'm wrong.

Referring to the internal usage, but I see you changed it.

Are you suggesting hard-deprecating lsp.diagnostics by removing those functions completely? I'm not sure I agree with that approach, I think I'd favor introducing vim.diagnostic and soft-deprecating lsp.diagnostics (we can show an info message when these functions are used warning that they are deprecated. vim-fugitive did this IIRC) in 0.6 and then hard-deprecating (removing) them in the next release.

I'm suggesting a soft deprecation with printed warnings and removing the compatibility layer during the stabilization period leading up to 0.6. Additionally we should be removing the remaining internal usages of deprecated functions (there are still some)

IMO show() and hide() are good names for what they do right now; namely, showing persistent decorations for diagnostics (virt text, signs, highlights, etc.). preview() is a "preview" in that it only shows ephemerally, it does not persist in the buffer in any way. Besides, the function that preview() calls is itself called open_floating_preview(), so there's precedent.

Fair, I still like display/hide and show() from the old style but I may be in the minority.

I would too, but with module scopes an enum quickly becomes unwieldy: vim.diagnostic.preview.BUFFER vs "buffer". That's why I stuck with a string. Maybe that's fine though since this function won't ever be called interactively.

I was thinking like vim.diagnostic.location.BUFFER with validation the location type is in the enum.

@justinmk
Copy link
Member

justinmk commented Oct 17, 2021

IMO show() and hide() are good names for what they do right now; namely, showing persistent decorations for diagnostics (virt text, signs, highlights, etc.). preview() is a "preview" in that it only shows ephemerally, it does not persist in the buffer in any way. Besides, the function that preview() calls is itself called open_floating_preview(), so there's precedent.

'previewwindow' has long-established semantics in Vim already. I wonder where open_floating_preview came from, its doc is Shows contents in a floating window.. That's literally what nvim_open_win does, but "preview" was thrown in the name... it could be named show_float or open_float. Please don't perpetuate "preview" because of this "precedent".

Fair, I still like display/hide and show() from the old style but I may be in the minority.

Those are better than randomly sprinkling "preview" in function names for no reason.

In general though the :help api names should be considered first. The verb "open" is established there. If "show" is needed for some reason, it should be a conscious reason.

@mjlbach
Copy link
Contributor

mjlbach commented Oct 17, 2021

@justinmk Yeah I've never liked preview as a name, or popup becomes of the semantic association with prior vim semantics.

"preview" was thrown in the name... it could be named show_float or open_float

+1 to changing this

@gpanders gpanders changed the title refactor(diagnostic)!: replace 'show_*' functions with 'preview' refactor(diagnostic)!: replace 'show_*' functions with 'open_float' Oct 17, 2021
runtime/doc/diagnostic.txt Show resolved Hide resolved
runtime/lua/vim/diagnostic.lua Outdated Show resolved Hide resolved
@ckipp01
Copy link
Contributor

ckipp01 commented Oct 19, 2021

Since this is a breaking change, I wanted to throw this out there as well (as a follow-up to a convo with @clason on Gitter). I know it's not exactly what you're addressing here, but might be worth at least thinking about it since we are breaking stuff. Right now we treating severity the same all over the space at a global level with severity_sort being set to false by default. Now that float stuff is being sort of extracted out, do we still want this? I know for things like signs, I find this odd at my error signs aren't shown ahead of my warning signs since both are treated as the same level. Especially when using LSP I sort of think the expectation is that errors take precedence and should be shown ahead of warnings. I am of the mindset that having severity_sort = true is a more sane default that false. Any thoughts on this or thoughts on if this could be addressed as we are now breaking float out?

@gpanders gpanders added this to the 0.6 milestone Oct 19, 2021
Copy link
Member

@justinmk justinmk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good direction. Thanks @gpanders again for your attention to detail :)

@gpanders gpanders force-pushed the diagnostic-preview branch 2 times, most recently from 1a97e2e to d94711b Compare October 19, 2021 14:53
@mjlbach
Copy link
Contributor

mjlbach commented Oct 19, 2021

+1 other than virt textual (unless you want to go even farther and make it virtual textual reality)

Right now we treating severity the same all over the space at a global level with severity_sort being set to false by default. Now that float stuff is being sort of extracted out, do we still want this? I know for things like signs, I find this odd at my error signs aren't shown ahead of my warning signs since both are treated as the same level. Especially when using LSP I sort of think the expectation is that errors take precedence and should be shown ahead of warnings. I am of the mindset that having severity_sort = true is a more sane default that false. Any thoughts on this or thoughts on if this could be addressed as we are now breaking float out?

This was me. I'm of two thoughts of this:

  • It's hypothetically possible for the server to control the diagnostic order (although I haven't checked if it's actually preserved)
  • I wanted to avoid unnecessary iteration + sort operations over tables

I'm not strongly opposed to making severity_sort the default, given it now serves more sources than lsp, but these were the original two justifications I gave for not making this the default as it was introduced.

Copy link
Contributor

@mjlbach mjlbach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

virt textual but then LGTM

'show_line_diagnostics()' and 'show_position_diagnostics()' are
almost identical; they differ only in the fact that the latter also
accepts a column to form a full position, rather than just a line. This
is not enough to justify two separate interfaces for this common
functionality.

Renaming this to simply 'show_diagnostics()' is one step forward, but
that is also not a good name as the '_diagnostics()' suffix is
redundant. However, we cannot name it simply 'show()' since that
function already exists with entirely different semantics.

Instead, combine these two into a single 'open_float()' function that
handles all of the cases of showing diagnostics in a floating window.
Also add a "float" key to 'vim.diagnostic.config()' to provide global
values of configuration options that can be overriden ephemerally. This
makes the float API consistent with the rest of the diagnostic API.

BREAKING CHANGE
Copy link
Member

@mfussenegger mfussenegger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Really great improvement 👍

error("Invalid value for option 'pos'")
end
elseif scope ~= "buffer" then
error("Invalid value for option 'scope'")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if worth it here - but including the user provided value and the valid options often help users figure out what went wrong.

Comment on lines +1167 to +1176
do
-- Resolve options with user settings from vim.diagnostic.config
-- Unlike the other decoration functions (e.g. set_virtual_text, set_signs, etc.) `open_float`
-- does not have a dedicated table for configuration options; instead, the options are mixed in
-- with its `opts` table which also includes "keyword" parameters. So we create a dedicated
-- options table that inherits missing keys from the global configuration before resolving.
local t = global_diagnostic_options.float
local float_opts = vim.tbl_extend("keep", opts, type(t) == "table" and t or {})
opts = get_resolved_options({ float = float_opts }, nil, bufnr).float
end
Copy link
Member Author

@gpanders gpanders Oct 19, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks to @kylo252 for pointing this out. open_float works differently than set_virtual_text and friends since it doesn't have a dedicated table for configuration options, so if we resolve opts directly that table clobbers the global configuration. As an example, consider

vim.diagnostic.config({ float = { show_header = false } })

vim.diagnostic.open_float(0, { scope = "line" })

If we pass {scope="line"} directly to get_resolved_options then it will assume that that is the full options table, which is missing show_header and therefore will default to its unset value (true) even though it's set to false in the global configuration.

One way to fix this would be to use tbl_deep_extend in get_resolved_options, which is what I tried first, but that removes the ability to use an empty table to revert to default values (#16043). Another way would be to make a nested opts table:

vim.diagnostic.open_float(0, {scope="line", opts = {...}})

But that seems confusing and non-intuitive to me. So instead just fill in missing keys from the global configuration before doing option resolution.

@gpanders gpanders merged commit 064411e into neovim:master Oct 19, 2021
@gpanders gpanders deleted the diagnostic-preview branch October 19, 2021 17:46
@sQVe
Copy link

sQVe commented Oct 19, 2021

@gpanders I just tried this out and one thing that no longer acts the same way is that triggering open_float twice doesn't move the cursor into the float. This was something that I thought was really useful for yanking diagnostics etc.

Is there a way to get this functionality?

Julian added a commit to Julian/dotfiles that referenced this pull request Oct 19, 2021
@gpanders
Copy link
Member Author

That is a regression, it's an easy fix though. I'll address that in a follow up PR.

@sQVe
Copy link

sQVe commented Oct 19, 2021

@gpanders Awesome 🎉 Thank you!

I also noted that show_header is supported in open_float but not in goto_next or goto_prev.

@gpanders
Copy link
Member Author

I also noted that show_header is supported in open_float but not in goto_next or goto_prev.

It is:

vim.diagnostic.goto_next { float = { show_header = true } }

@n3wborn
Copy link

n3wborn commented Oct 19, 2021

Damned ! Sorry, I didn't think my commit would appear here :/

ray-x added a commit to ray-x/navigator.lua that referenced this pull request Oct 19, 2021
megalithic added a commit to megalithic/dotfiles that referenced this pull request Oct 25, 2021
- nightly neovim/neovim#16057 changed how
  line diagnostics are shown/rendered.
@megalithic
Copy link

@gpanders I've noticed that this particular bug has crept back when using open_float via autocmd; should we be handling the closing of this float on BufLeave on our own? (#12477)

@gpanders
Copy link
Member Author

I would be surprised if this PR were the cause of that. It looks like "BufLeave" was removed from the default list of autocommands in #14649.

You can try adding

close_events = { "CursorMoved", "CursorMovedI", "BufHidden", "InsertCharPre", "BufLeave" }

to the options table you pass to open_float. If that works, feel free to send a PR adding "BufLeave" to the default list of close_events.

fitrh added a commit to fitrh/init.nvim that referenced this pull request Oct 29, 2021
fitrh added a commit to fitrh/init.nvim that referenced this pull request Oct 29, 2021
`open_float()` is replacement for `show_line_diagnostic()`, the opts
still the same, but buffer number required as the first arguments, 0 for
current buffer.

ref: neovim/neovim#16057
fitrh added a commit to fitrh/init.nvim that referenced this pull request Oct 29, 2021
lewis6991 pushed a commit to lewis6991/neovim that referenced this pull request Dec 12, 2021
…eovim#16057)

'show_line_diagnostics()' and 'show_position_diagnostics()' are
almost identical; they differ only in the fact that the latter also
accepts a column to form a full position, rather than just a line. This
is not enough to justify two separate interfaces for this common
functionality.

Renaming this to simply 'show_diagnostics()' is one step forward, but
that is also not a good name as the '_diagnostics()' suffix is
redundant. However, we cannot name it simply 'show()' since that
function already exists with entirely different semantics.

Instead, combine these two into a single 'open_float()' function that
handles all of the cases of showing diagnostics in a floating window.
Also add a "float" key to 'vim.diagnostic.config()' to provide global
values of configuration options that can be overridden ephemerally.
This makes the float API consistent with the rest of the diagnostic API.

BREAKING CHANGE
mrded added a commit to mrded/dotfiles that referenced this pull request Feb 18, 2022
adrien-tagheuer added a commit to acharruel/dotfiles that referenced this pull request Apr 5, 2022
Julian added a commit to Julian/dotfiles that referenced this pull request Jun 18, 2022
ctlusto added a commit to ctlusto/dotfiles that referenced this pull request Sep 7, 2023
There have been breaking changes to that API:
ref neovim/neovim#16057
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
diagnostic lsp lua stdlib refactor changes that are not features or bugfixes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants