Fork me on GitHub
#clj-kondo
<
2022-05-03
>
marciol17:05:18

Hey friends, I'm trying to discover why my ignore hints aren't working, but don't know even how to start debugging the issue. I'm using the "2022.02.09" version of clj-kondo.

marciol17:05:40

It's very strange because the :config-in-ns works.

borkdude17:05:01

config-in-ns is only available in the last version, so it's very strange that that would work, unless you're using clj-kondo via a downstream tool like clojure-lsp

marciol17:05:45

Yes, via clojure-lsp

marciol17:05:23

I tested other hints, just the :private-call isn't working

marciol17:05:32

All others do

borkdude17:05:48

could be a bug

marciol17:05:53

Yes, I'll get the version of clojure-lsp I'm using, maybe the bug was already fixed by the way. Thanks @borkdude

borkdude17:05:01

$ clj-kondo --lint - <<< '#_:clj-kondo/ignore (defn- foo [])'
linting took 13ms, errors: 0, warnings: 0

marciol17:05:47

~/Projects/Work/my-app (container-info *) $ lein lint
OpenJDK 64-Bit Server VM warning: Options -Xverify:none and -noverify were deprecated in JDK 13 and will likely be removed in a future release.
Retrieving clj-kondo/clj-kondo/2022.04.25/clj-kondo-2022.04.25.pom from clojars
Retrieving org/babashka/sci/0.3.2/sci-0.3.2.pom from clojars
Retrieving org/ow2/asm/asm/9.2/asm-9.2.pom from central
Retrieving org/ow2/ow2/1.5/ow2-1.5.pom from central
Retrieving org/ow2/asm/asm/9.2/asm-9.2.jar from central
Retrieving org/babashka/sci/0.3.2/sci-0.3.2.jar from clojars
Retrieving clj-kondo/clj-kondo/2022.04.25/clj-kondo-2022.04.25.jar from clojars
test/com/my_app/my_ns/some_test.clj:79:1: error: #'my-app.my-ns/get-something is private
linting took 140ms, errors: 2, warnings: 0

marciol17:05:16

it's weird because I have all those hints on source

borkdude17:05:54

oh private-call, I mixed this up with unused-private-var :)

borkdude17:05:33

@marciol I recommend using (#'my-ns/private-var 1 2 3) instead, then clj-kondo will not warn

borkdude17:05:59

that's how you'd do it in JVM Clojure as well

marciol17:05:32

hmmm, nice. I'm trying to use it with circle-ci bond with-stub!

borkdude17:05:15

oh, that's a macro right? you could try :lint-as {circleci.bond/with-stub! clojure.core/binding]

borkdude17:05:31

as you can use private vars as bindings in JVM Clojure as well without warnings and clj-kondo respects this

marciol17:05:34

yes, it's a macro

marciol17:05:02

Thank you @borkdude, it's all I need gratitude-thank-you

rayat18:05:57

Hi, it looks like every use of & for rest/spread (not sure what it's technically called) is linted as an unresolved symbol? I don't think we've had any changes to our config recently that I'm aware would affect this. Any smells to follow? Any workarounds for the meantime? Example lint error:

Unresolved symbol: &

all-clear 1
borkdude18:05:32

Repro please. A screenshot and example lint error is not a repro we can do much with. Are you able to make an example file we can lint locally?

rayat19:05:42

Ah, your answer indicates this is not a known, or common user error, or some such thing, which is mostly what I had hoped for. I'll try to figure it out myself for now, and will reach out with repro if it persists. Thanks for responding so quickly and being down to help troubleshoot as usual!!!

borkdude19:05:37

Indeed, it doesn't ring a bell and should not happen with normal Clojure code

rayat15:05:18

In case you were curious, strangely, this is the result of something within the intersection of Calva, c-lsp, kondo and whatever peculiarities of our codebase working correctly now when it hadn't before. The & error was in fact not an false positive for rest/spread like kwarg args passing, but actually the usage of the special & "operator" within lilactown/helix. I ended up writing a couple hooks for helix to get everything working as expected. Thanks for everything again!

borkdude15:05:57

cool! Maybe you can contribute the hooks to helix for everybody to enjoy?

borkdude15:05:39

fantastic, good work @U037TPXKBGS!

rayat16:05:21

3 questions about hooks if you don't mind: 1. what's the diff between reg-finding and simply throwing? your hooks.md doc doesn't differentiate I think 2. looking thru the rewrite-clj docs and noticing all the talk of the zipper API, it does look nifty. Would the kondo use-case make sense for providing the zipper API? Or have I maybe misinterpreted its intended use case? 3. I wanted to also catch and provide error diagnostics for cases of, for example, passing maps as children to be rendered in helix components. I can do that most trivially by checking if there's a map-node as a child somewhere, but that doesn't work if the map was bound to a symbol/var elsewhere and then the latter is instead passed, making it a token-node. Is there anything I can do within a linting hook to maybe "resolve" references "1 or 2 levels deep" for error purposes?

borkdude16:05:57

1. simply throwing doesn't allow you to configure the linter name and level

rayat16:05:16

gosh you're responsive

borkdude16:05:55

2. the zipper API was exposed in the past, but I ended up removing it because I didn't find it very useful for hooks, but might add it back if people want it

rayat16:05:30

Do you mind if I submit a PR for adding some of this stuff/my learnings to the hooks docs?

borkdude16:05:26

Please do! 🙏

❤️ 1
rayat17:05:04

@borkdude would love help knowing how we can enable similar linting for the generated symbols in https://github.com/lilactown/helix/blob/master/src/helix/dom.cljc. That is, users typically import/require syms from that ns and use em like (d/div {:some 'props} "some children"). It has similar linting rules as $ , but I don't know how to tell kondo to lint every sym as such. Any ideas?

borkdude18:05:20

@U04V5V0V4 you could do this using :lint-as {helix.dom/a helix.foo.$}

borkdude18:05:32

you'd have to repeat it for every tag in the config

rayat18:05:10

Ah, and could I do that as part of a helix PR, such that when consumers update to whatever helix version includes the new hooks/lint configs, they don't have to copy over every dom/* :list-as? Also dragging in @U4YGF4NGM for his take > btw I think you've tagged the wrong fellow

rayat20:05:06

Would you be open to a special lint-as* type key in config.edn that would accept something like:

:lint-as* { helix.dom/* helix.core/$ }
tbf I cannot think of another use-case beyond this specific one, but if there'd been interest in the past by other, I'll cast a small vote into that pool 😛

borkdude20:05:50

I've solved this for namespaces like this: https://github.com/clj-kondo/clj-kondo/blob/master/doc/config.md#namespace-groups So you can define a group using a regex and then use the group name in the config. We could do the same thing for vars

rayat20:05:05

Oh cool, yeah that looks promising! It's not the biggest personal priority, and I'll see how @U4YGF4NGM feels about the upcoming big-ol-list of :lint-as that I'm opening, but if there's a way I can help out in your suggestion, lmk!

borkdude20:05:50

So something like:

{:var-groups [{:regex ".*" :name all}]}
{:lint-as {helix.dom/all helix.core/$}}

rayat20:05:51

Yep. Any clue what an exclusion override might look like with that? Eg in this helix case, almost all exported syms are applicable to $-like linting, except one or two of em.

borkdude20:05:21

I think you would have to take care of that in the regex

rayat20:05:16

sure, fair enough

borkdude20:05:20

Maybe it should look like:

{:var-groups [{:regex "helix.dom/.*" :name helix.dom/all}]}

borkdude20:05:39

didn't think hard enough about this specific case yet

borkdude20:05:46

so it would probably take me some more time

rayat20:05:48

Another question, in this helix case again, there are some platform reader tag-based syms exported, eg

#?(:clj (defmacro some-macro ...))
Would this lint those?

borkdude20:05:50

to properly do that

borkdude20:05:17

clj-kondo lints a .cljc file twice, once for :clj and once for :cljs

1
rayat20:05:26

I think the latter more explicit/specific version might make more sense

rayat20:05:30

Ah right I recall now

rayat18:05:23

Hey @borkdude I'm sorry if this is dumb as usual etc. but couldn't discern much from the hooks docs. Also, I lack knowledge of the correct jargon, so forgive that as well: My hooks are overall working nicely, but inside fn calls that I've written the hooks for, symbols imported from other ns's like (nsname/some-fn ...) are linted as errors with Unresolved var: nsname/some-fn. Any pointers or smells as to what my hooks are doing wrong? Are those nsname/some-fn references treated as just raw symbols or something, and not as imported/namespaced ones? FWIW there are no lint errors for the same fns/symbols outside of my hook'd fns. Inside my hook, those sorts of things are expanded as (api/token-node whatever-the-symbol-is-verbatim). Should I be using a different approach to those nodes, or making use of ns-analysis somehow? Thanks!

borkdude18:05:50

@U037TPXKBGS 👋 "dumb as usual" not at all! :) The hook expands into code and then clj-kondo takes over as if the user had written that code. Perhaps you could just try to make such a fully written out example, without hooks, and then see how that's working.

rayat18:05:41

hmm, I'm guessing you mean by throwing in a (prn (api/sexpr my-hook-return-val)) in my hooks and paste it in from cli?

borkdude18:05:08

no, I mean, write out an example that would normally be returned from the hook code

borkdude18:05:18

just normal code as how the user would write it

borkdude18:05:25

then I expect you would also see the unresolved var

rayat18:05:56

Well, that's assuming my hook is written correctly, right? That it accurately outputs what I would have written by hand?

rayat18:05:03

But ok I'll try that

rayat18:05:30

Okay... I didn't do anything, but a manual cli lint + couple of clojure lsp restarts later, and it's no longer false-positive-ing the symbol references... wtf lol

rayat18:05:49

DIdn't change any config or anything, and already restarted lsp server tons of times in the past 30 minutes

rayat18:05:57

Well, in any case, thanks again!!!

borkdude18:05:42

it could be that the other ns wasn't linted yet

1
borkdude18:05:45

or not refreshed

borkdude18:05:47

you're welcome

devn18:05:06

what’s the right way to get kondo to not complain about hiccup? i added a lint-as for hiccup.def/defelem and hiccup.def/defhtml, but i am still seeing unresolved symbols for things that were created with defhtml, and unresolved vars for things like hiccup.form/text-field

borkdude18:05:31

It depends on the syntax of those things :)

borkdude18:05:52

examples would be helpful

devn18:05:18

example meaning a link to the source of these things?

devn18:05:10

(defmacro defhtml
  "Define a function, but wrap its output in an implicit html macro."
  [name & fdecl]
  (let [[fhead fbody] (split-with #(not (or (list? %) (vector? %))) fdecl)
        wrap-html     (fn [[args & body]] `(~args (html ~@body)))]
    `(defn ~name
       ~@fhead
       ~@(if (vector? (first fbody))
           (wrap-html fbody)
           (map wrap-html fbody)))))

devn18:05:15

(defmacro defelem
  "Defines a function that will return a element vector. If the first argument
  passed to the resulting function is a map, it merges it with the attribute
  map of the returned element value."
  [name & fdecl]
  `(do (defn ~name ~@fdecl)
       (alter-meta! (var ~name) update-in [:arglists] #'update-arglists)
       (alter-var-root (var ~name) wrap-attrs)))

devn18:05:39

(defelem text-field
  "Creates a new text input field."
  ([name] (text-field name nil))
  ([name value] (input-field "text" name value)))

borkdude18:05:48

I'm more interested in the usages of those things

devn18:05:59

oh sure, sorry

borkdude18:05:01

as that is what matters for linting

devn18:05:53

(defn foo
  []
  (h.form/text-field {:class "hello"}))
gives me an unresolved var on h.form/text-field

borkdude18:05:52

you should do lint-as defelem clojure.core/defn and then re-lint your dependency

borkdude18:05:07

if you are using clojure-lsp, that means lsp-workspace-restart

devn18:05:22

defelem without it’s namespace?

borkdude18:05:32

no, with, I was just lazy in typing

devn18:05:44

i did a restart workspace, and have

{:list-as {hiccup.def/defelem clojure.core/defn
           hiccup.def/defhtml clojure.core/defn}}

devn18:05:50

let me do it one more time with feeling just to be sure

devn18:05:04

going to restart my emacs and manually delete the .cache dir

borkdude18:05:17

define, "the cache dir"

devn18:05:26

.clj-kondo/.cache

borkdude18:05:30

sounds good

devn19:05:12

clears all of them up except for:

(h.def/defhtml bar
  [& content]
  [:body content])

devn19:05:18

where bar and content are unresolved symbols

borkdude19:05:20

that's weird btw, I would expect that syntax to be equivalent to core defn

borkdude19:05:30

what does your lint as look like?

devn19:05:02

what i posted above, both being treated as clojure.core/defn — for kicks i tried to use the def-catch-all for defhtml, but same thing

borkdude19:05:11

can you post your exact config please?

borkdude19:05:28

sorry, I'm doing 10 things at once

borkdude19:05:43

I can take a look at this tomorrow

devn19:05:58

config posted above was :list-as, not :lint-as facepalm

borkdude19:05:05

hehe ok then

devn19:05:26

sorry for the bother!

rayat18:05:23

Hey @borkdude I'm sorry if this is dumb as usual etc. but couldn't discern much from the hooks docs. Also, I lack knowledge of the correct jargon, so forgive that as well: My hooks are overall working nicely, but inside fn calls that I've written the hooks for, symbols imported from other ns's like (nsname/some-fn ...) are linted as errors with Unresolved var: nsname/some-fn. Any pointers or smells as to what my hooks are doing wrong? Are those nsname/some-fn references treated as just raw symbols or something, and not as imported/namespaced ones? FWIW there are no lint errors for the same fns/symbols outside of my hook'd fns. Inside my hook, those sorts of things are expanded as (api/token-node whatever-the-symbol-is-verbatim). Should I be using a different approach to those nodes, or making use of ns-analysis somehow? Thanks!