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

feat(lsp): add support for semantic tokens #15723

Closed
wants to merge 1 commit into from

Conversation

theHamsta
Copy link
Member

@theHamsta theHamsta commented Sep 19, 2021

Another take on #14122 . I updated @smolck PR to the new LSP handler signatures and added some basic highlighting.

  • reword commits to confirm conventional commits
  • Align highlight mapping with the strategy of vim.treesitter.highlight (e.g. default link of thinks like cppLspComment)
    • current solution tries to have similar behavior as tree-sitter
    • mapping for token types: LspComment, cppLspComment automatically linked to LspComment
    • mapping for token modifiers: LspDeprecated, cppLspDeprecated
    • TODO: do we need a combination of type and modifier like LspFunctionDeprecated? or should be just provide a overwritable function that does the mapping ft x token x modifiers -> hl
  • handle refreshing -> proper implementation in follow-up with partial refreshing, for now just full request on autocmd)
  • implement partial refreshes of semantic tokens -> follow-up PR
  • documentation

Fixes nvim-treesitter/nvim-treesitter#1632 @cryptomilk I think this would fit your use case. When your run autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.buf.semantic_tokens_full() with clangd and LspComment linked to Comment.

semantic_tokens.mp4

Open question should the default semantic token handler handle highlighting? Should this be opt in?

  • my opinion would be to handle the highlighting. Semantic token would still do no highlighting as the highlight groups are not mapped. Users would opt-in partially or completely by a example config that the docs provide

@theHamsta theHamsta marked this pull request as draft September 19, 2021 15:48
@github-actions github-actions bot added lsp lua stdlib labels Sep 19, 2021
@theHamsta theHamsta force-pushed the lsp_semantic_tokens branch 2 times, most recently from 60b997a to 41e17b5 Compare September 20, 2021 18:05
@theHamsta theHamsta force-pushed the lsp_semantic_tokens branch 8 times, most recently from 911df2a to f14ac82 Compare September 22, 2021 19:11
@theHamsta theHamsta force-pushed the lsp_semantic_tokens branch 4 times, most recently from 632d812 to 1a194af Compare September 26, 2021 10:44
@theHamsta theHamsta requested review from jdrouhard and mjlbach and removed request for jdrouhard August 13, 2022 12:39
Co-authored-by: Stephan Seitz <[email protected]>
Co-authored-by: smolck <[email protected]>
@mfussenegger
Copy link
Member

mfussenegger commented Aug 18, 2022

For me the two issues that should to be addressed before this would be good to merge are:

a) A concept to handle multiple LSP clients. Either the API needs to support client filters (like vim.lsp.buf.format, or rename) or there would need to be some kind of aggregate logic. I'm not sure which variant makes more sense for semantic tokens. That's also missing from other parts like codelens, but we learned that retrofitting this can be a bit painful (e.g. due to breaking changes). It's better to consider this from the start then trying to shoehorn it on top later.

b) Showcase how multiple plugins would consume the tokens. (and probably improve the API for that, because I think each pluggin wrapping a function isn't ideal - it should probably be possible for one consumer to stop consuming / de-register itself - e.g. autocmds could be a solution as already mentioned)

Given that both of these are influencing the public API I'd rather see this addressed before merging, not after. But if another core maintainer disagrees and wants to push this forward I won't object.

@theHamsta
Copy link
Member Author

theHamsta commented Aug 26, 2022

#19931 could also be a possibility for mapping semantic token highlights in future #tokenType.modifierA.modifier or even the same format that VSCode uses

{
  "name": "Red Theme",
  "tokenColors": [
    {
      "scope": "comment",
      "settings": {
        "foreground": "#dd0000",
        "fontStyle": "italic"
      }
    }
  ],
  "semanticHighlighting": true,
  "semanticTokenColors": {
    "variable.readonly:java": "#ff0011"
  }
}

variable.readonly:java is called a selector and has the form (*|tokenType)(.tokenModifier)*(:tokenLanguage)?.

https://code.visualstudio.com/api/language-extensions/semantic-highlight-guide#semantic-coloring-in-color-themes

@tiagovla
Copy link
Contributor

LSP 3.17 added decorator to the SemanticTokenTypes.

@christianparpart
Copy link

I was trying out branch, and I am running into some issues, sadly.

Nothing seems to be highlighted by default. So I scrolled through this PR and found out that you'd need to call the given function as follows to refresh highlighting. - But calling lua vim.lsp.buf.semantic_tokens_full() will result into an error, as follows:

Error executing vim.schedule lua callback: ...local/share/nvim/runtime/lua/vim/lsp/semantic_tokens.lua:70: attempt to index local 'config' (a nil value)
stack traceback:
        ...local/share/nvim/runtime/lua/vim/lsp/semantic_tokens.lua:70: in function 'handler'
        /usr/local/share/nvim/runtime/lua/vim/lsp.lua:1372: in function ''
        vim/_editor.lua: in function <vim/_editor.lua:0>

Also, terminating vim takes about 2 seconds on a really strong desktop machine, and I wonder what might hold it back. Some timeout maybe?

Regardless of the slow program-exit, I'd really like to give this branch a try because I need a way to test semantic tokens from the server side and would prefer to stick with (neo)vim for that. What am I maybe missing?

p.s.: Would you mind doing a git rebase ... on top of latest master? Seems like your base is pretty outdated already. :)

@lewis6991
Copy link
Member

lewis6991 commented Sep 1, 2022

This PR doesn't implement buffer highlighting, it simply adds support for semantic tokens in the LSP client. You will need to implement the buffer highlighting yourself by providing a callback for on_token.

Also, terminating vim takes about 2 seconds on a really strong desktop machine, and I wonder what might hold it back. Some timeout maybe?

My guess is that you are running a debug build which defines -DEXITFREE. This will cause the hang on exit (see #18670). To avoid this simply compile a release build with make CMAKE_BUILD_TYPE=Release.

@iago-lito
Copy link

You will need to implement the buffer highlighting yourself by providing a callback for on_token

@lewis6991 Is it possible yet to highlight individual/contextualized tokens from this callback? Or would it essentially be still a sequence of :syn calls?

@lewis6991
Copy link
Member

lewis6991 commented Sep 1, 2022

You wouldn't use :syn calls, you would use nvim_buf_set_extmark

@kaiuri
Copy link

kaiuri commented Sep 9, 2022

@christianparpart

Regardless of the slow program-exit, I'd really like to give this branch a try because I need a way to test semantic tokens from the server side and would prefer to stick with (neo)vim for that. What am I maybe missing?

I suggest checking out nvim-semantic-tokens. Been using it daily without issues.

@jdrouhard
Copy link
Contributor

It seems this PR has stalled out again :(

@theHamsta - it looks like you gave up a bit ago on actually pushing this through. Totally understandable, maybe I could open a continuation PR to keep going.

@clason @lewis6991 @mfussenegger - To address @mfussenegger 's #15723 (comment), I think we need to hone in on exactly what form semantic tokens takes. Your (a) bullet contains two possibilities - we should decide on one. (b) is already sorta done-- @theHamsta and I both have different plugins that can consume the tokens. If we think the API for that should be improved, we should hammer that out. If this is better suited to a matrix discussion in neovim-dev, I'd be happy to hop on and discuss at some point.

At this point, I think it's time we close this PR and open a new one that attempts to address whatever remaining things you guys want to see before we can get this in.

Semantic tokens is a pretty major feature of LSP that the native client still doesn't support and it would be great if we could get some support for it (even if rudimentary) in before 0.9.0.

@christianparpart
Copy link

christianparpart commented Nov 14, 2022

@jdrouhard I absolutely feel with you. Last time I tried native LSP, the lag of semantic tokens was THE reason for me to switch back to coc.nvim. Since then I didn't even care about moving forward again, as no semantic highlighting is in fact a deal breaker for me. I can't complain too much here, as I can't contribute to it either. Lua isn't just my thing, so I'm happy for anyone to just finish this work such that others (not just me) could eventually start using the native LSP (again).

Meanwhile I keep watching, all the best,
Christian.

p.s.: one important note to drop. I was actively working on an LSP server myself, and the thing I've learned from it, is that users ARE actualy willing to take non-finished products gladly now rather than waiting a year or more until it is 100% complete. There's no such thing as perfect anyways. Release often and early they say. Use that as an advantage to re-iterate often, get early feedback, and improve while you go. ... and again, all the best to you guys. Cheres ;)

@mfussenegger
Copy link
Member

. (b) is already sorta done-- @theHamsta and I both have different plugins that can consume the tokens

I haven't seen yours, but afaik the one from theHamsta uses something like vim.lsp.with(semantic_tokens.on_full, {on_token = highlight_token, on_invalidate_range = clear_highlights, }) - which means no two plugins can consume tokens at the same time. I don't see this as solved.

Since my last comment autocmds gained support for a data property that allows to send arbitrary data. I think this makes using autocmds a even more attractive option to emit the tokens.

If this is better suited to a matrix discussion in neovim-dev, I'd be happy to hop on and discuss at some point.

Yes, matrix may be the better place to hash out the API


Regarding other comments: Please refrain from adding more comments that add no more additional information. We have already concluded that semantic tokens would be good to have in core. What's missing is someone who does the work and resolves the remaining issues.

Julian added a commit to Julian/dotfiles that referenced this pull request Nov 17, 2022
@jdrouhard jdrouhard mentioned this pull request Nov 18, 2022
4 tasks
@theHamsta
Copy link
Member Author

Superseeded by #21100

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
LSP integration
0.8 to-dos (Completion, extensibility)
Development

Successfully merging this pull request may close these issues.

Tree-sitter doesn't detect commented out C code using #if 0 ... #endif