Fork me on GitHub
#clj-kondo
<
2020-09-11
>
sogaiu05:09:36

nice to have more examples. @lee am finding yours to be particularly instructive, thanks 🙂

sogaiu05:09:35

i'm looking at examples of tweaking behavior of :unresolved-symbol here: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/config.clj#L42-L53 it looks like by using :exclude, one can ignore instances globally or within the context of a specific call (or calls). i don't suppose it's possible to ignore instances within specific files... the use case is when there is a file that has no ns form and is using in-ns instead, e.g. clojure's core_deftype.clj, core_print.clj, core_proxy.clj, etc. is there some good way to have the unresolved symbol errors turned off only within those files without modifying them? (i'd rather not turn off the unresolved symbols linting for specific symbols across all of clojure's source if possible.)

borkdude06:09:17

@sogaiu you can ignore files in the output but that will ignore the entire file

borkdude07:09:31

@sogaiu Maybe it might sense to also allow namespace local config in config.edn under :namespaces {clojure {pprint {:linters {...} :lint-as {}}}}

borkdude07:09:25

but this is generally only useful for sources you don't control

borkdude07:09:38

on the other hand, it might be nice if you don't want to have your config in the source

sogaiu07:09:49

that sounds interesting -- perhaps it can be noted as a future possibility. if there are other requests for it may be it can be revisited.

borkdude07:09:01

I'm also thinking about this in the context of REPL-assisted static analysis like https://github.com/clj-kondo/inspector. Right now it only dumps types for the :type-mismatch linter but we could have like a reverse analysis output format that clj-kondo can take in for linting.

sogaiu08:09:08

@borkdude i don't see the connection yet, but hopefully will get it in a bit 🙂 btw, regarding hooks and handling macros, have you had a look at colinfleming's 2015 conj talk: https://www.youtube.com/watch?v=kt4haSH2xcs ?

borkdude08:09:39

I've seen it yes

sogaiu08:09:57

ok, was curious as it has some mention of parsing macros.

sogaiu08:09:15

there is this repository that he released after too: https://github.com/cursive-ide/error-test

borkdude08:09:22

the connection between those two issues is: inform clj-kondo about vars in your namespace. either by suppressing things or really telling it what's there

sogaiu08:09:26

ah ok, thanks for the explanation.

borkdude08:09:10

I've considered that approach, and implemented a sexpr-based solution initally, but that didn't work since not all things can carry location metadata. So preserving the rewrite-clj nodes is better for linting and having a full Clojure environment for transforming those nodes is far more powerful than some DSL

borkdude08:09:58

We can still add clojure spec to the hooks API if you want to do validation on the sexpr directly

sogaiu08:09:09

ah, too bad that didn't work out. i guess if it means i get my real-time notification from clj-kondo, the being tied to rewrite-clj is a trade-off i'm ok with. (ofc, i am a rewrite-clj* fan 🙂 )

borkdude08:09:02

The hooks API is rather thin, so switching to some other solution than rewrite-clj might still be possible in the future (but I doubt it)

sogaiu08:09:02

ok -- well, i doubt i'll come up with anything useful, but a non-library specific approach has some application to other tooling so i'm interested in other ideas.

borkdude08:09:33

#lsp has a DSL for it

borkdude08:09:48

but they're switching to clj-kondo now for linting and possibly also analysis

borkdude08:09:15

I think they ran into some edge cases which couldn't be expressed in the DSL (@snoe)

sogaiu08:09:31

ah i didn't know about the lsp dsl thing -- thanks for the tip.

borkdude08:09:44

we can still support something like that as an easier thing instead of hooks which then writes the lower level hooks code for you

borkdude08:09:18

one benefit of hooks is also that you can emit custom warnings based on your macro input

borkdude08:09:28

there's already examples of this in the config repo

sogaiu08:09:32

yes i saw that -- looks cool.

sogaiu08:09:59

i have been studying the examples and trying to make something for defdirectives in clojure's source

borkdude08:09:02

I want to add predicates api/vector?, api/symbol? etc so people rely less on api/sexpr which can be a footgun

sogaiu08:09:09

in emacs-lisp, to get edebug to work with macros they have this way for macro definitions (i think) to express info about how to understand them: https://www.gnu.org/software/emacs/manual/html_node/elisp/Specification-List.html#Specification-List

sogaiu08:09:16

yeah, that makes sense

sogaiu08:09:53

i'm sure lread will be happier to see sexpr used less

sogaiu08:09:10

this rewrite-cljc-playground issue is related, right? https://github.com/lread/rewrite-cljc-playground/issues/5

borkdude08:09:53

Ah yes, thanks

borkdude08:09:43

Initially in the hooks API I called api/sexpr on the node, while also adding location as metadata. So people could write hooks directly on the sexpr. After transformation I printed this to a string including metadata and then read this in again using rewrite-clj

borkdude08:09:07

It works for a lot of the code, but not when you had expressions like (inc 1) in your macro arguments

borkdude09:09:02

That's mostly why I abandoned that approach

borkdude09:09:23

else you could have almost used your macro as is for expansion

sogaiu09:09:55

the current approach sounds safer

sogaiu09:09:51

i need to think a lot more about this -- was mostly curious about background. sorry i was so late to the party 🙂

borkdude09:09:28

no problem. I think it's pretty cool that we can now run a Clojure interpreter in a binary version of clj-kondo :)

sogaiu09:09:39

yes, i thought was pretty neat too!

sogaiu09:09:26

@borkdude so i don't see map-node here: https://github.com/borkdude/clj-kondo/blob/master/src/clj_kondo/impl/hooks.clj is that something that would be ok to add? or may be it's available some other way?

borkdude09:09:56

I think we could add that, but so far I've often found other ways of dealing with this

borkdude09:09:08

maybe you could give the example

borkdude09:09:25

of what's the input and how you are rewriting it

sogaiu09:09:09

so defdirectives i think is supposed to expand to:

(def directive-table {,,,})

borkdude09:09:27

why is it important that you expand exactly like that macro

borkdude09:09:34

clj-kondo doesn't do anything with that right

sogaiu09:09:01

lol -- no idea actually. may be it will be fine to do just (def directive-table nil)?

sogaiu09:09:52

happier to do less work 🙂

borkdude09:09:10

I would probably do this:

(defdirectives
  (\A
   [:mincol [0 Integer]
    :colinc [1 Integer]
    :minpad [0 Integer]
    :padchar [\space Character]]
   #{:at :colon :both}
   {}
   #(format-ascii print-str %1 %2 %3))
  )

;; =>

[[\A
  [:mincol [0 Integer]
   :colinc [1 Integer]
   :minpad [0 Integer]
   :padchar [\space Character]]]
 #{:at :colon :both}
 {}
 #(format-ascii print-str %1 %2 %3)]

borkdude09:09:29

it's important that all usages are still visible to clj-kondo

borkdude09:09:40

else you'll get warnings about unused imports, etc.

sogaiu09:09:08

i think i get what you're saying -- though perhaps it's sensible to wrap the bottom thing in a def form?

sogaiu09:09:43

ok, i'll give that a try. thanks!

borkdude09:09:28

that's one of the 💡 in writing hooks: you don't have to conform to the semantics of the original macro at all

sogaiu09:09:03

yes, i was noticing that in lread's example but i guess there were two parts of my brain that weren't communicating well 🙂

sogaiu09:09:13

should make things faster

borkdude09:09:10

there's also a time macro to measure performance

sogaiu09:09:48

thanks for the tip

sogaiu10:09:58

@borkdude ok, your suggested approach is mostly working out. there is one type of thing though that seems to lead to warnings: https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/cl_format.clj#L1373-L1379 those bits get wrapped in a fn form -- https://github.com/clojure/clojure/blob/master/src/clj/clojure/pprint/cl_format.clj#L1326 using a list-node with a fn token node and a vector followed by the form to wrap seems to work ok. does that sound sane?

borkdude10:09:01

what kind of warning did you get?

sogaiu10:09:20

one example is:

src/clj/clojure/pprint/cl_format.clj:1375:22: error: unresolved symbol params

borkdude10:09:55

right, so it expects some fixed set of named args it seems. someone went really wild with their macros there..

sogaiu11:09:58

i think with this, the number of errors when linting cl_format.clj are reduced: https://gist.github.com/sogaiu/2be50c906e52a686699c154d4423c91d

sogaiu11:09:40

i guess cl_format.clj is from a long while back -- it has defstruct

sogaiu11:09:29

thanks to your tip!

borkdude15:09:21

Rum hooks for defc and defcs now support multi-arity definitions at https://github.com/clj-kondo/config

borkdude18:09:25

Cool, someone wrote a hook to suggest turning long ->> chains into transducer equivalents: https://github.com/borkdude/clj-kondo/issues/323#issuecomment-691247062