clj-kondo

https://github.com/clj-kondo/clj-kondo
2021-06-02T14:01:28.150100Z

So I'm looking at the codebase to try and add an exclude config to use blocks. It looks like the :use lint is different from the other ns lints in that it's registered immediately rather than just associng in something new to register a finding for later. For this would it be better to try and refactor the use finding to work the same way as e.g. refer-all, or would it be better to just add an additional requirement in the and expression that gates registering the finding?

2021-06-02T14:02:09.150700Z

The latter is most certainly easier, but it's inconsistent with the rest.

borkdude 2021-06-02T14:05:49.150900Z

What is the problem you're trying to solve?

borkdude 2021-06-02T14:07:22.152400Z

you're trying to unify the code for :use and :refer :all in clj-kondo's codebase?

2021-06-02T14:07:42.152800Z

More or less. I just want the :use linter to have an :exclude config

borkdude 2021-06-02T14:08:45.153100Z

you could also migrate to :refer :all

borkdude 2021-06-02T14:08:52.153500Z

but that's only a workaround ;)

borkdude 2021-06-02T14:09:30.154100Z

but I'm open to improvements, as long as the tests pass and there are no perf regressions

2021-06-02T14:09:31.154200Z

Yeah.

2021-06-02T14:10:18.155200Z

Right. I was more or less asking if you'd prefer if I just add a one-liner that just doesn't register the use finding if the config excludes the ns, or if you'd prefer that I try to make use work like refer does

borkdude 2021-06-02T14:11:39.156Z

I would have to look into that, don't remember the exact code. I think :refer :all has some logic that prefetches some vars from the cache to improve linting, does :use also have that?

2021-06-02T14:15:19.156700Z

yeah, looks like there's a call to reg-var-usage!

borkdude 2021-06-02T14:20:52.158400Z

What it does is look at the cache in case of :refer :all so it can actually resolve names better. clj-kondo has a hard time with use and refer all because it has nothing to go by statically

2021-06-02T14:20:55.158600Z

it just assoces stuff into the :referred-all segment and passes that on so that it would get used here

R.A. Porter 2021-06-02T14:25:46.161Z

I don't know if this is a problem with Cursive, the IJ file watcher plugin, or clj-kondo, but I'm seeing the following, where the indicator in the IDE is highlighting the fn inside the sexpr instead of either the whole sexpr or the int fn itself (what I'd expect). The output below shows the correct columns, which correspond to the open paren for the subs sexprs.

borkdude 2021-06-02T14:26:50.161700Z

can you make a minimal repro in text? then I'd be happy to try out what it does in emacs. you could also just disable clj-kondo to see if that is or is not the problem?

R.A. Porter 2021-06-02T14:45:26.161900Z

This function does it for me:

(ns alignment)

(defn foo
  [s]
  (let [sub1 (subs s 0 10)
        x (int (subs sub1 0 2))
        y (int (subs sub1 3 5))]
    (+ x y)))

R.A. Porter 2021-06-02T14:45:55.162100Z

With clj-kondo turned off, it doesn't highlight the subs fns; with clj-kondo turned on, it does.

borkdude 2021-06-02T14:48:15.163900Z

The reason it highlights it is that subs returns a string but int expects a char, although in CLJS that may just work

R.A. Porter 2021-06-02T14:50:03.164100Z

My expectation is that it would highlight either int or the entire function call for subs if that's not what is intended, I'll just have to adjust my expectation.

borkdude 2021-06-02T14:51:42.164800Z

I’ll try in emacs when I get back to home

borkdude 2021-06-02T15:28:31.165300Z

I think it's just an artifact of how the tooling works, clj-kondo does the right thing I think

👍 1
borkdude 2021-06-02T15:30:26.165800Z

@suskeyhose feedback: this kind of stuff:

(set (get-in ctx [:config :linters :use :exclude])
is done in config.clj in a way that it caches this result

borkdude 2021-06-02T15:30:43.166Z

I mean, getting values from the config

2021-06-02T15:31:49.166200Z

Oh, cool. I'll try taking a look at that. This is why I wanted to make it a draft, so I'd find some things that I wouldn't have thought of otherwise. 🙂

2021-06-02T15:33:19.166500Z

That's interesting, it looks like all the other config access in this file is just threading it through keywords

borkdude 2021-06-02T15:34:41.166700Z

?

2021-06-02T15:37:47.167200Z

But maybe I'm missing something here and the caching happens earlier, looks like it does in the linters.clj file

borkdude 2021-06-02T15:38:25.167400Z

in config.clj

borkdude 2021-06-02T15:38:27.167600Z

as I said

borkdude 2021-06-02T15:38:54.167800Z

the above are just checks whether the config is enabled or not

2021-06-02T15:39:02.168Z

Right, I was looking for usages of it.

borkdude 2021-06-02T15:39:10.168200Z

but sometimes more work is needed, such as the set conversion you are doing

borkdude 2021-06-02T15:39:30.168400Z

and this should optimally only happen once

borkdude 2021-06-02T15:40:04.168600Z

but as people can also have namespace-local config, this should be cached per version of the config

2021-06-02T15:40:14.168800Z

Ah, makes sense. I did make a coersion function there. Actually, I'm looking at this and it appears that there may be a bug/feature which is that the config for refer-all appears to apply to both use and refer-all

borkdude 2021-06-02T15:40:39.169Z

that may just be a feature

2021-06-02T15:41:06.169200Z

Then this pr should probably just update the documentation

borkdude 2021-06-02T15:41:30.169400Z

nice

2021-06-02T15:44:15.169600Z

I think it's a little weird that there's two different linters and yet only one configuration, but if this is fine, then I'll just update the docs.

borkdude 2021-06-02T15:45:42.169800Z

:refer :all and :use are very similar in their effect

borkdude 2021-06-02T15:46:16.170100Z

whether you write (:use clojure.test) or (:require [clojure.test :refer :all]) shouldn't matter

borkdude 2021-06-02T15:46:29.170300Z

if you want to ignore one, you probably want to ignore the other too

2021-06-02T15:46:42.170500Z

Yeah, I agree with you, but it just seems weird that there's two different linters for it then.

borkdude 2021-06-02T15:47:56.170700Z

not sure why that was again, but clj-kondo tries to discourage the use of both as you get worse linting with it anyway.

borkdude 2021-06-02T15:48:02.170900Z

I personally never use either

2021-06-02T15:48:20.171100Z

That's definitely fair. I don't under normal circumstances.

borkdude 2021-06-02T15:48:36.171300Z

there are exceptions like DSL-like things

2021-06-02T15:50:14.171500Z

Yup. In any case, the PR is updated, it only adds a config section to the use linter which refers back to the refer-all linter

borkdude 2021-06-02T15:51:06.171700Z

merged

2021-06-02T15:51:15.171900Z

Awesome, thanks

2021-06-02T19:19:53.172500Z

Does the lint-as clojure.core/defn have issues with multiple fn bodies?

borkdude 2021-06-02T19:23:43.172700Z

it should not

2021-06-02T19:27:43.173800Z

Hmm. I'm trying to mess with specter again and multi-path isn't linting correctly. I've set the lint-as for defdynamicnav to lint-as defn, but it's saying it can't resolve path1 and path2

(defdynamicnav multi-path
  "A path that branches on multiple paths. For updates,
   applies updates to the paths in order."
  ([] STAY)
  ([path] path)
  ([path1 path2]
   (late-bound-richnav [late1 (late-path path1)
                        late2 (late-path path2)]
     (select* [this vals structure next-fn]
       (let [res1 (i/exec-select* late1 vals structure next-fn)]
         (if (reduced? res1)
           res1
...

borkdude 2021-06-02T19:28:23.174200Z

can you make an example I can actually try locally, so a complete form? this will make it easier for me to help you

2021-06-02T19:28:36.174400Z

Sure, sorry about that

2021-06-02T19:29:32.174900Z

(defdynamicnav something
  "blah"
  ([] nil)
  ([path] path)
  ([item1 item2]
   [item1 item2]))

2021-06-02T19:29:46.175300Z

This recrates the error, all defdynamicnav has to be is some random macro that has lint-as set to defn

2021-06-02T19:30:34.175700Z

Hmm. It seems like it might be something specific to this config. I want to do a little more testing.

borkdude 2021-06-02T19:30:37.175900Z

This works:

(ns foo
  {:clj-kondo/config '{:lint-as {bar/defdynamicnav clojure.core/defn}}}
  (:require [bar :refer [defdynamicnav]]))

(defdynamicnav something
  "blah"
  ([] nil)
  ([path] path)
  ([item1 item2]
   [item1 item2]))

2021-06-02T19:31:06.176600Z

Yeah, it worked fine for me just now too when I defined my own macro. Maybe it's that defdynamicnav is being created wrong or something.

2021-06-02T19:31:20.176800Z

I need to go through this a little more slowly.