Fork me on GitHub
#lsp
<
2023-06-29
>
Alexander Kouznetsov00:06:30

Is it possible to run clojure-lsp/unused-public-var linter when running clj-kondo from a command line? I’d like to get the same level of warning regardless of CLI/editor.

ericdallo00:06:28

You probably want to use clojure-lsp from CLI

ericdallo00:06:51

clojure-lsp diagnostics will bring all kondo diagnostics + all LSP diagnostics

gratitude-thank-you 2
Alexander Kouznetsov00:06:59

In order to avoid unused-public-var linter warning I tried to modify a clj-kondo hook to generate a usage of a var defined by my macro but that didn’t affect the linter. Basically it was replacing my macro call with

(do
  (declare unused-var)
  (unused-var ...)
  ...)
Is this expected?

ericdallo00:06:48

Could you elaborate why you do that to avoid the linter? There are plenty settings to configure the linter to avoid false positives https://clojure-lsp.io/settings/#clojure-lspunused-public-var

Alexander Kouznetsov00:06:49

One reason is that I want to co-locate macro and any configuration it requires. Another is that I didn’t manage to make it work yet. And third, I didn’t realize this linter is external to clj-kondo. So I assumed hook would cover the case.

Alexander Kouznetsov00:06:02

Ideally I want to put these configs inside the macro body similar to:

(defmacro my-macro
  {:clj-kondo/lint-as 'clojure.core/defn}

ericdallo00:06:38

I think clj-kondo should support that config via code for custom linters like the ones from clojure-lsp, if not you can open an issue

Alexander Kouznetsov19:06:08

I think there is a way to control how linters are applied to a particular file where a macro is used. But I don’t see how I can control how a linter should be applied to a particular macro. My wild guess would be that the linter should see what is specified in the attr-map of the macro and correct its behavior based on that.

Nathan Nolk08:06:12

Hello, I installed clojure-lsp in EndeavourOS from the AUR. When I run lsp in vterm (in Emacs, the terminal) it runs fine, but when I try to use it in Emacs normally (in a project) it stays stuck on starting and never runs. The error I get is simply Internal Error. Any idea what might be causing the issue?

ericdallo11:06:10

could you get the LSP error buffer and clojude-lsp server logs?

Nathan Nolk12:06:15

Here are the clojure-lsp-server-logs, not sure how to get the buffer error:

2023-06-29T12:16:50.418Z  INFO [clojure-lsp.server:596] - [SERVER] Starting server...
2023-06-29T12:16:50.423Z  DEBUG [clojure-lsp.nrepl:21] - nrepl not found, skipping nrepl server start...
2023-06-29T12:16:50.429Z  INFO [clojure-lsp.server:483] - Initializing...
2023-06-29T12:16:50.434Z  ERROR [clojure-lsp.server:55] - Error receiving message: Internal error (-32603)
{:id 1, :method "initialize"}
com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine    PosixPlatformThreads.java:  203
            com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine         PlatformThreads.java:  775
                                                     java.lang.Thread.run                  Thread.java:  829
                       java.util.concurrent.ThreadPoolExecutor$Worker.run      ThreadPoolExecutor.java:  628
                        java.util.concurrent.ThreadPoolExecutor.runWorker      ThreadPoolExecutor.java: 1128
                                                                      ...                                   
                                        clojure.core.async/thread-call/fn                    async.clj:  487
                                            lsp4clj.server/thread-loop/fn                   server.clj:  121
                                         lsp4clj.server/dispatch-input/fn                   server.clj:  174
                                lsp4clj.server.ChanServer/receive-request                   server.clj:  342
                                  lsp4clj.server/pending-received-request                   server.clj:  236
                                                                      ...                                   
                                                    clojure-lsp.server/fn                   server.clj:  493
                                          clojure-lsp.handlers/initialize                 handlers.clj:  154
                                   clojure-lsp.startup/initialize-project                  startup.clj:  187
                                      clojure-lsp.config/resolve-for-root                   config.clj:   71
                               clojure-lsp.config/resolve-project-configs                   config.clj:   57
                                         clojure-lsp.shared/uri->filename                   shared.clj:  222
                                     clojure-lsp.shared/uri-obj->filepath                   shared.clj:  179
                                                  java.nio.file.Paths.get                   Paths.java:   97
                                                    java.nio.file.Path.of                    Path.java:  203
                                sun.nio.fs.UnixFileSystemProvider.getPath  UnixFileSystemProvider.java:  103
                                          sun.nio.fs.UnixUriUtils.fromUri            UnixUriUtils.java:   87
java.lang.IllegalArgumentException: Bad escape

ericdallo12:06:20

Hum, it's a server crash indeed, it seems something with a URI in a bad format

ericdallo12:06:45

is it possible to provide a sample github project where that happens so I can try myself? Also, check if you are using latest clojure-lsp, clojure-lsp --version

Nathan Nolk12:06:31

Here is the version: clojure-lsp 2023.05.04-19.38.01 clj-kondo 2023.04.15-SNAPSHOT

Nathan Nolk12:06:13

Do you want me to create a new github project and try there? Sadly I can't share the project I tried this in..

ericdallo12:06:56

yeah, it's probably something with your project, maybe you can try if that happens in https://github.com/ericdallo/clojure-sample that I use to test things

Nathan Nolk12:06:07

Ah thank you very much, let me try it out!

Nathan Nolk12:06:34

It works fine in your project

ericdallo12:06:37

@U05CWBL3BQX it's something with the project-root-uri as the exception happens https://github.com/clojure-lsp/clojure-lsp/blob/b318465bec4932b9e05ab1f2d6535c64441c07d0/lib/src/clojure_lsp/config.clj#L57, we can check what the client (emacs) is sending to the server

Nathan Nolk12:06:41

I see, it seems to be an issue on my end

ericdallo12:06:01

we can debug what emacs is sending

Nathan Nolk12:06:51

Do I need to open the project.clj file then? Or is it internal to emacs?

ericdallo12:06:04

try: • M-: (setq lsp-log-io t)lsp-workspace-restartlsp-workspace-show-log

Nathan Nolk12:06:16

While in the project, correct?

ericdallo12:06:27

then seek for the initialize request, we want to know what is being sent in the project-root-uri

ericdallo12:06:34

yes, in any clojure buffer

Nathan Nolk12:06:39

Thanks, let me try this

Nathan Nolk12:06:41

I think I know what the issue is!

Nathan Nolk12:06:02

The URI has Japanese kanji and it seems like UTF8 didn't work (or it wasn't encoded properly), so it gave me a bunch of nonsense

Nathan Nolk12:06:04

Here, let me paste it

Nathan Nolk12:06:44

[Trace - 02:29:10 午後] Sending request 'initialize - (7)'.
Params: {
  "processId": 10099,
  "rootPath": "/home/mayumin/Documents/Programming/文析",
  "clientInfo": {
    "name": "emacs",
    "version": "GNU Emacs 28.2 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.36, cairo version 1.17.6)\n of 2023-01-03"
  },
  "rootUri": "file:///home/mayumin/Documents/Programming/%E6%96%87%E6%9E%90",
  "capabilities": {
    "general": {
      "positionEncodings": [
        "utf-32",
        "utf-16"
      ]
    },

Nathan Nolk12:06:49

I assume this is what interests us

Nathan Nolk12:06:20

It is displaying %...% instead of 文析 (the name of the folder)

Nathan Nolk12:06:26

Should I simply rewrite it in English?

Nathan Nolk12:06:47

I'm confused because the rootPath is set correctly...

Nathan Nolk12:06:50

Here's the other part of the logs that displays the error:

[Trace - 02:29:10 午後] Received notification '$/progress'.
Params: {
  "token": "1",
  "value": {
    "kind": "begin",
    "title": "clojure-lsp",
    "percentage": 0
  }
}


[Trace - 02:29:10 午後] Received response 'initialize - (7)' in 42ms.
Result: {
  "code": -32603,
  "message": "Internal error",
  "data": {
    "id": 7,
    "method": "initialize"
  }
}

Nathan Nolk12:06:40

I can send the full logs if necessary, let me know 🙂

ericdallo12:06:41

yes, there is a huge chance that clojure-lsp code doesn't handle kenjis properly 🙃 I'd say to name it in english for now, you can open a issue on clojure-lsp to support that, I'm not sure how easy would be, I feel like we would face that issue in other places as well

Nathan Nolk12:06:30

Ahh this is fine then, I can live with it being written in English 🙂

ericdallo12:06:41

ah, actually it may even be a lsp-mode bug, I think not using kenjis is the easiest way

Nathan Nolk12:06:51

Can I simply close emacs, rename the folder and restart emacs/lsp?

Nathan Nolk12:06:03

Thank you, let me see if that does it

ericdallo12:06:12

or lsp-workspace-folders-remove and lsp again

Nathan Nolk12:06:00

Wonderful, it works!

Nathan Nolk12:06:11

Thank you very much, I'm glad we caught that 🙂

Alexander Kouznetsov19:06:38

How can I print clj-kondo config for clojure-lsp diagnostics command? I’m trying to configure clojure-lsp/unused-public-var linter but it seems to ignore my settings - I tried both .clj-kondo/config.edn and in namespace attr-map.

Alexander Kouznetsov20:06:46

Hmm. :level :off worked but not :exclude #{my-ns/my-macro} .

Alexander Kouznetsov20:06:23

Oops, I should’ve used instead :exclude-when-defined-by {my-ns/my-macro}. My bad.

Alexander Kouznetsov20:06:45

But that doesn’t work for me. I have :exclude option working to disable the linter in a namespace, but :exclude-when-defined-by with a specific macro name still triggers the warnings.

Alexander Kouznetsov21:06:49

Here is a full example:

(ns demo
  {:clj-kondo/config
     '{:linters {:clojure-lsp/unused-public-var
                   {:exclude-when-defined-by #{demo/defabctest}}}}}
  (:require
    [clojure.test :refer [is deftest]]))

(defmacro defabctest
  {:clj-kondo/lint-as 'clojure.core/defn}
  [name [sym] & body]
  `(deftest ~name
     (let [~sym 5]
       ~@body)))

(defabctest my-test [x]
  (is (= x 5)))

ericdallo21:06:09

@UHS6PHL31 unused-public-var is a clj-kondo custom-linter defined by clojure-lsp, AFAIK there is a clj-kondo bug that doesn't handle clj-kondo configs in code for custom-linters

ericdallo21:06:24

could you try that on .clj-kondo/config.edn first?

Alexander Kouznetsov21:06:28

But it doesn’t work in config file too.

ericdallo21:06:38

let me check then

gratitude-thank-you 2
ericdallo21:06:27

BTW, if your macro behaves like a deftest, you could lint-as clojure.test/deftest as well

Alexander Kouznetsov21:06:08

It doesn’t behave like deftest unfortunately, it has bindings like defn.

👍 2
Alexander Kouznetsov21:06:36

When I use config file, :level and :exclude work but not :exclude-when-defined-by.

ericdallo21:06:43

well your demo with configs on .clj-kondo works for me :thinking_face:

ericdallo21:06:55

let me push to my sample project

Alexander Kouznetsov21:06:18

Hmm, I can try a clean version - so far I was using calva’s clojure-lsp installation.

ericdallo21:06:33

should work the same

Alexander Kouznetsov21:06:16

What’s your config file content?

Alexander Kouznetsov21:06:37

Hmmm, I cloned it and it gives me this:

[100%] Project analyzed       
Finding diagnostics...
test/clojure_sample/core_test.clj:11:1: warning: [redefined-var] redefined var #'clojure-sample.core-test/a-test
src/clojure_sample/client.clj:11:13: info: [clojure-lsp/unused-public-var] Unused public var 'clojure-sample.client/my-test'

Alexander Kouznetsov21:06:00

$ clj-kondo --version
clj-kondo v2023.05.18
$ ~/.vscode/extensions/betterthantomorrow.calva-2.0.372/clojure-lsp --version            
clojure-lsp 2023.05.04-19.38.01
clj-kondo 2023.04.15-SNAPSHOT

Alexander Kouznetsov21:06:49

Installing a clean version of clojure-lsp now.

ericdallo21:06:58

I tested only on emacs, let me check via CLI

ericdallo21:06:26

indeed happens for cli only

Alexander Kouznetsov21:06:31

Same thing:

$ clojure-lsp --version
clojure-lsp 2023.05.04-19.38.01
clj-kondo 2023.04.15-SNAPSHOT

$ clojure-lsp diagnostics          
[100%] Project analyzed            
Finding diagnostics...
test/clojure_sample/core_test.clj:11:1: warning: [redefined-var] redefined var #'clojure-sample.core-test/a-test
src/clojure_sample/client.clj:11:13: info: [clojure-lsp/unused-public-var] Unused public var 'clojure-sample.client/my-test'

ericdallo21:06:49

looks like a clojure-lsp bug, let me check

Alexander Kouznetsov21:06:09

It also happening in VSCode + Calva

ericdallo21:06:13

I can't repro in Calva but can repro in CLI which is weird

ericdallo21:06:30

anyway, that's definitely a clojure-lsp bug, please open an issue so I can fix it later

gratitude-thank-you 2
Alexander Kouznetsov21:06:06

Thanks, will do. Here is my screenshot.

ericdallo23:06:21

@UHS6PHL31 I found out the issue doesn't happen in clojure-lsp master, but happens on latest release, so I suspect next release will fix it, could you confirm running a nightly clojure-lsp in Calva? (you can just type nightly in calva clojure-lsp version setting)

Alexander Kouznetsov17:06:15

Verified that it works in nightly. Thanks!

Alexander Kouznetsov21:06:22

But for my other macro it is still the issue. The pattern is the same - :level :off works but :exclude-when-defined-by and :exclude-when-defined-by-regex do not work. I’ll need to spend a bit more time to come up with a reproducible test case. Also, I’m wondering what’s happening with the hooks. Aren’t they affecting clojure-lsp linter? I see hooks as the only tool that is capable of completely resolving all macro issues and I’m wondering whether it can be used to somehow instruct clojure-lsp linter to ignore public vars a particular macro generates.

ericdallo16:07:00

yes, they can be related, we added to clj-kondo a option to defined a :defined-by in your hook, then clojure-lsp will use that when checking the exclude-when-defined-by, check how we did forhttps://github.com/nubank/state-flow/blob/master/resources/clj-kondo.exports/nubank/state-flow/nubank/state_flow.clj#L35

2
Alexander Kouznetsov00:02:34

I finally got to look deeper at it. Now I see that when a macroexpand hook is configured with a macro, then clojure-lsp sees the hook-specified defining var (`def` or deftest) but not the custom macro that does it. I’m checking if I this trick works for me but that currently requires to replace :macroexpand hook with an :analyze-call hook. Is there a way to support this with a :macroexpand hook?

Alexander Kouznetsov00:02:48

In other words, the :defined-by trick for the nubank’s state flow you mentioned, makes the following definition for my similar example:

:defined-by a/defmytest,
  :defined-by->lint-as clojure.core/defn,
Whereas without it all notion of the original macro a/defmytest is gone.
:defined-by clojure.core/defn,
  :defined-by->lint-as clojure.core/defn,
As I find :macroexpand hooks much more user-friednly. Is it possible to support such a feature for them?

Alexander Kouznetsov02:02:01

Looking at https://github.com/clj-kondo/clj-kondo/blob/586bf972f55c87f75ad5787a7925f4b4fb4a674e/src/clj_kondo/impl/hooks.clj#L208 it seems that this is currently not setting :defined-by but it might be possible to update the code to allow that.

Alexander Kouznetsov02:02:39

Probably we can just add one more line here to make it work: :defined-by (symbol (name ns-sym) (name var-sym)) WDYT? @U04V15CAJ

borkdude08:02:47

I haven't followed the whole discussion, perhaps you can summarize it for me?

Alexander Kouznetsov18:02:22

Sure, I’ll open an issue with a good description.