This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-11-03
Channels
- # announcements (55)
- # babashka (14)
- # beginners (49)
- # biff (9)
- # calva (73)
- # cider (14)
- # clerk (8)
- # clj-kondo (6)
- # clojure (92)
- # clojure-dev (4)
- # clojure-europe (18)
- # clojure-norway (62)
- # clojure-uk (5)
- # clojuredesign-podcast (4)
- # clojurescript (34)
- # cursive (40)
- # data-science (4)
- # datomic (5)
- # dev-tooling (1)
- # eastwood (6)
- # emacs (107)
- # figwheel-main (9)
- # fulcro (13)
- # gratitude (9)
- # hyperfiddle (5)
- # introduce-yourself (2)
- # off-topic (45)
- # overtone (23)
- # portal (5)
- # releases (3)
- # shadow-cljs (6)
- # specter (1)
- # squint (32)
- # timbre (4)
- # vscode (2)
I don't know if this is a calva or clojure-lsp issue, but I'll try here first. I often have a arguments or local bindings that share name with a namespace alias. For example permission
, as in (:require [bar.permission :as permission])
while in another unrelated namespace I have`(defn foo [permission] ,,,)`. Inside the foo
function, I will start writing perm
and autocomplete shows me permission
, I hit tab, and it seemingly achieve the desired effect. However, unknowingly, I have also added bar.permission
as a dependency to the current namespace. Because the first autocomplete suggestion that I get is for the alias rather than the local variable. And I often never discover this or discover it because it has added a circular dependency.
Would it be possible to prioritize local variables before namespace aliases in the autocomplete suggestions?
I'm almost sure we already prioritize that in clojure-lsp but there may be some frontend sorting(vscode side)
https://github.com/clojure-lsp/clojure-lsp/blob/master/lib/src/clojure_lsp/feature/completion.clj#L26 Top-down is less priority to more priority
You can debug if clojure-lsp is returning the completion items in the correct order
Here is a screenshot of the autocompletion. The local variable does not even show up
I turned on verbose logging but clearing it and just typing one character generates a massive log. Not sure where to look
Ok, here are entries with "completion"
[Trace - 16:20:13] Sending request 'textDocument/completion - (4785)'.
Params: {
"textDocument": {
"uri": "file:///Users/brjljo/BASS/bass4/test/clj/bass4/replace_fns.clj"
},
"position": {
"line": 26,
"character": 11
},
"context": {
"triggerKind": 1
}
}
[Trace - 16:20:13] Received response 'textDocument/completion - (4785)' in 33ms.
Result: [
{
"label": "permissions",
"kind": 6,
"detail": "",
"data": {
"unresolved": [
[
"documentation",
{
"name": "permissions",
"uri": "file:///Users/brjljo/BASS/bass4/test/clj/bass4/replace_fns.clj",
"name-row": 26,
"name-col": 6
}
]
]
},
"score": 15
},
{
"label": "permissions",
"kind": 10,
"detail": "alias to: bass4.admin.permissions",
"data": {
"unresolved": [
[
"alias",
{
"ns-to-add": "bass4.admin.permissions",
"alias-to-add": "permissions",
"uri": "file:///Users/brjljo/BASS/bass4/test/clj/bass4/replace_fns.clj"
}
]
]
},
"score": 9
}
]
[Trace - 16:20:13] Sending request 'completionItem/resolve - (4786)'.
Params: {
"label": "permissions",
"detail": "alias to: bass4.admin.permissions",
"insertTextFormat": 1,
"kind": 10,
"data": {
"unresolved": [
[
"alias",
{
"ns-to-add": "bass4.admin.permissions",
"alias-to-add": "permissions",
"uri": "file:///Users/brjljo/BASS/bass4/test/clj/bass4/replace_fns.clj"
}
]
]
}
}
[Trace - 16:20:13] Received response 'completionItem/resolve - (4786)' in 4ms.
Result: {
"label": "permissions",
"detail": "alias to: bass4.admin.permissions",
"insertTextFormat": 1,
"kind": 10
}
So server is no returning the local at all indeed, could you test if the same happens for let bindings or defn body?
Same for defn
and let
However, it does not happen if there is no matching alias (note permission
without trailing s). So now the alias permissions
is not even suggested
Sure! Is this related? An autocomplete suggestion when naming arguments
This will also require the namespace, which doesn't make much sense. But one should maybe not hit tab on autocompletion of argument names...
☝️:skin-tone-2: I've run into this a few times but never made sense of what causes it -- so massive thanks to @UGDTSFM4M for figuring out a repro!

thanks @UGDTSFM4M, something weird is that on emacs it works as expected :thinking_face: Will try with calva now
@UGDTSFM4M this is what server returns for calva, which looks correct, so it's probably a calva bug, maybe <!subteam^S03BGSAUPTQ> can understand better that
2023-11-03T16:55:59.247Z DEBUG [clojure-lsp.server:55] - [Trace - 2023-11-03T16:55:59.247Z] Sending response 'textDocument/completion - (69)'. Request took 37ms.
Result: [ {
"label" : "ns-alias",
"kind" : 6,
"data" : {
"unresolved" : [ [ "documentation", {
"name" : "ns-alias",
"uri" : "file:///home/greg/dev/clojure-lsp/lib/src/clojure_lsp/feature/issue/another_ns.clj",
"name-row" : 3,
"name-col" : 6
} ] ]
},
"score" : 14
}, {
"label" : "ns-alias",
"kind" : 10,
"detail" : "alias to: clojure-lsp.feature.issue.aliased",
"data" : {
"unresolved" : [ [ "alias", {
"ns-to-add" : "clojure-lsp.feature.issue.aliased",
"alias-to-add" : "ns-alias",
"uri" : "file:///home/greg/dev/clojure-lsp/lib/src/clojure_lsp/feature/issue/another_ns.clj"
} ] ]
},
"score" : 9
}, {
"label" : "ns-aliases",
"kind" : 3,
"detail" : "clojure.core/ns-aliases",
"data" : {
"unresolved" : [ [ "documentation", {
"uri" : "file:///clojure.core.clj",
"name" : "ns-aliases",
"ns" : "clojure.core"
} ] ]
},
"score" : 6
} ]
I think it probably is outside what Calva can do much about. It’s VS Code’s lsp client that acts on this stuff. Calva basically only sets up the connection. (Speaking without having checked this specific feature, but it’s how almost all clojure-lsp functionality gets handled.
I don’t really have time to look into it, but I suspect this is a problem with nrepl. When we do completions we ask lsp + nrepl for suggestions and then merge them. I’d suspect that nrepl provides those alias completions with a higher score than the ones provided by clojure-lsp
Could you try asking for those completions without being connected to the repl?
Ah, thanks @U02EMBDU2JU. You read the thread better than I did. Could very well be nrepl.
btw we already have a completionProviderOptions = { priority: ['lsp', 'repl'], merge: true }
that we hardcode. It works the same as our definitionProviderPriority
.
We could expose it and allow people to set this. We didn’t do it because we were hoping that the default would always work out ok.
There can’t be a bug in the merge if there is no merge because you don’t use a repl 😅
I just checked the lsp spec. Score is not actually a thing for completion items. It’s supposed to use the label for sorting or, if available, the sortText. So since sortText is missing it’s probably using the label, which is the same for all three. So you’ll get a random sort?
The issue is not the sort, there is a missing completion of the var-definition ns-alias
Ah crap, sorry. I guess I didn’t read enough of the thread 😞
I suggest reading the issue, is pretty descriptive to avoid re-read the whole thread
Yeah, no you are actually correct, we do the merge wrong. We index ist by label so you don’t get the same item from lsp and from nrepl. That doesn’t work so well when you have the same label on multiple completions from the same source 😞
Yes, because we always run through the merge, since it “shouldn’t” make a difference if there’s nothing to actually merge 😞
results = [
...completions
.concat(results)
.reduce(
(m: Map<string | CompletionItemLabel, CompletionItem>, o: CompletionItem) =>
m.set(o.label, Object.assign(m.get(o.label) || {}, o)),
new Map()
)
.values(),
];
Since this is on the Calva side of things, I created a new issue here: https://github.com/BetterThanTomorrow/calva/issues/2336 However, I fail to reproduce it. Put my repro project here: https://github.com/BetterThanTomorrow/calva/tree/dev/test-data/projects/completions Could be that I am still misunderstanding the expectations, so would appreciate more clarity there. Can you test with that project @UGDTSFM4M and provide a bit more info on what you expect to happen as comments to the new issue?
@U0ETXRFEW that first ns-alias is related to the alias from other ns, if you hit it, it will require the ms in that current ns, we don't want that, we want the ns-alias suggestion from line 4, which should only complete the var-definition from line 4 and nothing else
Check my emacs screenshot https://clojurians.slack.com/archives/CBE668G4R/p1699029944638189?thread_ts=1699023626.527349&cid=CBE668G4R to see how calva should present
Why do we get the aliased to:
entry? Honest curiosity, I’m guessing there’s something I don’t understand.
This is a way to complete an alias that is not already required, pretty common feature, but when you have alias with the same name of locals/vars you face that issue in calva it seems
@UKFSJSM38 what’s the significance of the score
in the completions? Should a higher score overshadow a lower score for the same label
+`kind`?
I can't come up with any case where label + kind isn't unique. There might be some weird edge cases though
Huh, that looks weird. Kind 6 is a variable, right? How could you have two variables with the same name in scope without one shadowing the other?
Yeah, they are not both in scope.
;; another_ns.clj
(ns another-ns)
(def ns-alias 0)
(defn bar
[]
(ns-a)) ;; Autocomplete will only suggest "ns-alias alias to: aliased" LSP-OUTPUT
(defn foo
[ns-alias]
(ns-a|)) ;; Autocomplete will only suggest "ns-alias alias to: aliased"
(defn baz
[]
(let [ns-alias 0]
ns-a)) ;; Autocomplete will only suggest "ns-alias alias to: aliased"
(Cursor at |
)Huh, the def probably shouldn't be suggested at that point. Not that it makes any difference in the end, since only the details differ.
Well, we present the details, so it makes a difference. So here I suspect I have sorted out the wrong one, hence the question about score
.
But you're probably correct that the higher score should win. Until now we also just took the order that clojure-lsp returned as the display order. That's technically correct according to lsp spec, but we should probably sort by score if it exists.
Ah ignore me, the score and the order agree...
Well, “until now” has changed. I couldn’t get the merge to work with the old code, not even the updated version you provided me, so I wrote a new one. I seem to have not retained the order priority. But it seems prudent to rely on score, rather than order? (If, indeed, he score is trying to tell me what I think it is telling me.)
Sorry for that, my TS is getting very rusty 😅
actually… kind 6 is Class
in vscode index.d.ts
. and 5 in the LSP protocol. In fact it all seems shifted by 1… VS Code types:
export enum CompletionItemKind {
Text = 0,
Method = 1,
Function = 2,
Constructor = 3,
Field = 4,
Variable = 5,
Class = 6,
Interface = 7,
Module = 8,
Property = 9,
Unit = 10,
Value = 11,
Enum = 12,
Keyword = 13,
Snippet = 14,
Color = 15,
Reference = 17,
File = 16,
Folder = 18,
EnumMember = 19,
Constant = 20,
Struct = 21,
Event = 22,
Operator = 23,
TypeParameter = 24,
User = 25,
Issue = 26,
}
LSP https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#completionItemKind:
export namespace CompletionItemKind {
export const Text = 1;
export const Method = 2;
export const Function = 3;
export const Constructor = 4;
export const Field = 5;
export const Variable = 6;
export const Class = 7;
export const Interface = 8;
export const Module = 9;
export const Property = 10;
export const Unit = 11;
export const Value = 12;
export const Enum = 13;
export const Keyword = 14;
export const Snippet = 15;
export const Color = 16;
export const File = 17;
export const Reference = 18;
export const Folder = 19;
export const EnumMember = 20;
export const Constant = 21;
export const Struct = 22;
export const Event = 23;
export const Operator = 24;
export const TypeParameter = 25;
}
I wonder what’s up with that?Ah, some stupid languages have 0 being falsy… So LSP avoids that… Currently trips our merge up in interesting ways. 😃
That list only matches up to Color
-- after that, the items are in a different order:
Reference = 17,
File = 16,
... the same in both ... the following are in the first list and not in the second:
User = 25,
Issue = 26,
vs
export const File = 17;
export const Reference = 18;
Hi folks, I have a question - is there a way in calva to "remove" a namespace prefix?
Say I have com.foo.bar.quuz
- I would like to keep foo.quuz
Is it possible?
I don’t think so, but the use case it is not completely clear to me. Is it a refactor rename operation you’re after? I think that is supported by clojure-lsp. To test, you would press F2 on the symbol.
yeah it is a bulk refactor of every namespace (there are many, so F2) is not an option 😄
(F2 works for a symbol namespace FWIW)
yeah, would that change the ns
form?
Hi there! running into an issue where keywords aren't being highlighted correctly. Issues: - Keywords do not get syntax highlighting unless I: 1. Save the file. 2. Tab out of the editor window to another tab and tab back. - Highlighted keywords lose their highlighting if I make any change to the editor (e.g add a newline). All other syntax highlighting seems to be working fine. Anyone know what the issue is?