-
-
Notifications
You must be signed in to change notification settings - Fork 883
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
Permit semantic token overrides to extend base set #3680
Conversation
lsp-semantic-tokens.el
Outdated
"Merge alist BASE with OVERRIDES. | ||
For keys present in both alists, the assignments made by | ||
OVERRIDES will take precedence." | ||
(let ((all-keys (-union (mapcar #'car base) (mapcar #'car overrides)))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Something like that seems to be more natural:
(let* ((copy-base (copy-alist base)))
(mapc (-lambda ((key . value)) (setf (alist-get key copy-base) value)) overrides)
copy-base)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How I tested it:
(let* ((base '((key1 . value1) (key2 . value2)))
(overrides '((key1 . override1)
(new-key . override2)))
(copy-base (copy-alist base)))
(mapc (-lambda ((key . value)) (setf (alist-get key copy-base) value)) overrides)
copy-base)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
Something to be aware of: the list of faces supplied for modifiers has a specific order, which is indexed by the bitmap when applying them. For example, here is the initialization reply capabilites from rust analyzer, which I have annotated with the bitmap positions "semanticTokensProvider": {
"legend": {
"tokenTypes": [
.......
],
"tokenModifiers": [
"documentation", 0
"declaration", 1
"definition", 2
"static", 3
"abstract", 4
"deprecated", 5
"readonly", 6
"defaultLibrary", 7
"async", 8
"attribute", 9
"callable", 10
"constant", 11
"consuming", 12
"controlFlow", 13
"crateRoot", 14
"injected", 15
"intraDocLink", 16
"library", 17
"mutable", 18
"public", 19
"reference", 20
"trait", 21
"unsafe" 22
]
},
"range": true,
"full": {
"delta": true
}
},
|
In fact, the spec says that the SemanticTokensLegend defines how the modifiers will be used by the server. This is a vector of names corresponding to the bitmap order the server will use. So the client needs to arrange things so that those face names line up with the bitmap positions when they are applied. Which sounds like there should be another stage of processing to do this lining up, ready for use. The simplest way to do this is to let the client registration specify the fonts in the order required, and not to change the order. Otherwise explicitly rearrange once the name -> face mapping is in place. |
that ordering should be established by |
But if the server ever changes the modifiers it uses, it may be more robust to explicitly use the order provided by the server in its initialize response, which is the |
yes, I believe that's what |
@sebastiansturm I like this PR and it kind of works for terraform client. But For terraform, I don't want to extend the base set - since it doesn't recognize some of them. I want only the one which I defnine and I need full control over it. For eg: there are no such tokens like this in terraform:
But because it's already defined in the variable |
thanks for trying out the PR! I would expect any extra faces passed to the server to be ignored by said server, so they won't end up in the face vector and shouldn't cause any overhead. Do you see any practical downside to the current approach? If so, we could of course just remove all definitions explicitly overridden by |
@sebastiansturm I think this should be fine, but I guess I would prefer as a client user - if I didn't have to pass any additional parameters to the language server if it's not required. But this definitely improves the current situation, so thank you for that! And I'm planning to patch the terraform client once this PR get's merged. Also one thing worth mentioning is that the parameters that are passed to the language server doesn't seem to preserve the order. While this is not a problem for terraform language server, I'm not sure if it will cause issues for other language server. Also, probably it's worth having two options:
Where the fist option completely overrides the one defined in |
thanks for the hint, not sure if I'll have time this week but I'll check the spec to see if token/modifier order is somehow important. I slightly changed my PR so that default tokens/modifiers can now be completely replaced by your overrides, depending on two new (optional) elements |
I could be mis-understanding, but from reading @alanz's comment here - I think that ordering matters: #3680 (comment) |
A later response by @sebastiansturm clarifies that it actually uses the order returned in the initialize response. So the key thing is to make sure all the required mappings are in place. |
I have tested this, and it works, using :semantic-tokens-faces-overrides `(:discard-default-modifiers t
:modifiers
,(lsp-rust-analyzer--semantic-modifiers)) in |
thank you! I think this should be good to go; @yyoncho or @ericdallo do you agree? |
Should there be a documentation update with it, or as well, related. It is not clear how to use this in practice. |
true. I added a comment to |
I think this can be merged; or (@yyoncho @ericdallo) is there anything else you'd like me to change? |
Sorry for the delay! |
This makes use of the machinery introduced by Sebastian here: emacs-lsp#3680 and avoids the whole with-eval-after-load hack that I used previously
* Permit semantic token overrides to extend base set * Rewrite lsp-semantic-tokens--apply-alist-overrides as suggested by yyoncho * Include face overrides in client capabilities * Add option to discard default tokens/modifiers * Document semantic-tokens-faces-overrides Co-authored-by: Sebastian Sturm <s.sturm@arkona-technologies.de>
This makes use of the machinery introduced by Sebastian here: emacs-lsp#3680 and avoids the whole with-eval-after-load hack that I used previously
This makes use of the machinery introduced by Sebastian here: emacs-lsp#3680 and avoids the whole with-eval-after-load hack that I used previously
This makes use of the machinery introduced by Sebastian here: #3680 and avoids the whole with-eval-after-load hack that I used previously
please don't merge -- I haven't tested this yet. As @alanz noted, the current implementation of
lsp--client-semantic-tokens-faces-overrides
doesn't allow client package authors to add new faces or modifiers to the base set; the present mini-PR should fix that (plan to try this out tomorrow, won't get to it today)