Fork me on GitHub

@didibus No, E.g. the weird-macro example is similar to jdbc’s with-connection while the clj-kondo macro just expands into constructs that are known but is much simpler


One other point is that clj-kondo has to deal with partial information. So it doesn’t go looking for namespaces elsewhere and find that macro for you


@borkdude have you tried core.match yet? I think that's the killer example for it.


I haven't yet, but that's a good one


@borkdude is it possible to mark a macro expansion as allowing unused variables? Consider an anaphoric macro like proxy(?) where this is bound, but possibly not used.


@dominicm Do you ask this in relation to the new macroexpand feature or in general?


The new macro expansion feature


I remember fixing something for proxy-super ( But if you're implementing a stand-in macro, then you can just emit this so it will be linted as used.


Heh, that's true. Hmm. Might be an option then :)


@borkdude that new macroexpansion feature looks great! I left some example macros that I've run across that might be useful to evaluate


Catching up on this thread from yesterday/earlier... So the idea is that you provide, essentially, a dumbed-down version of arbitrary macros in the config so that clj-kondo is better able to parse code and issue correct warnings?


The example shows it as text that is passed to SCI to evaluate -- would it be better to provide a (quoted) form instead so that folks writing these things can get code assist/syntax checking on the alternative macro definitions?


(but, yeah, looks very interesting -- and certainly SCI has allowed Chlorine to do amazing stuff, in user-land, to extend the functionality so the overall approach is sound)


@snoe Thanks!


@seancorfield Yes, you provide dumbed down version to teach clj-kondo about the syntax. The reason the code is not quoted is that this is supposed to be part of your .clj-kondo/config.edn and in EDN you can't use arbitrary code (not even quotes).


I'm still thinking about a way to refer to another file in that config.


I've been considering reader tags to refer to other files, but I want something that can work in both .edn files and as metadata. Reader tags can break people's code.


Ah, good point about EDN not being code-sufficient. What Chlorine did was to have the config be .cljs and treat the whole file as SCI-consumable.


(that's harder for kondo which traffics in (unquoted) symbols tho')


That works, but I want the code for each macro to be readable separately, as to not eval all macro stuff if only some of it is needed for linting e.g. one file


right now I have this:

{:macroexpand {foo/bar "foo/bar.clj"}}
which looks in .clj-kondo/foo/bar.clj for the macro


@snoe Did one more test. better-cond, only tested the :let construction:

(ns foo
  {:clj-kondo/config '{:macroexpand {better.cond/cond
(defn process-pairs [pairs]
  (loop [[[lhs rhs :as pair] & pairs] pairs
         new-body ['cond]]
    (if pair
        (= 1 (count pair)) (seq (conj new-body lhs))
        (not (keyword? lhs))
        (recur pairs
               (conj new-body lhs rhs))
        (= :let lhs)
        (seq (conj new-body :else (list 'let rhs
                                       (process-pairs pairs)))))
      (seq new-body))))

(def f
  (fn [{:keys [:sexpr]}]
    (let [expr (let [args (rest sexpr)
                     pairs (partition-all 2 args)]
                 (process-pairs pairs))]
      {:sexpr (with-meta expr
                (meta sexpr))})))"}}}
  (:require [better.cond :as b]))

(let [x 10]
    (= x 1) true
    :let [y (inc x)]      ;; binding is recognized
    (= 11 y) (subs y 0))) ;; yay, type error because y is not a string


I'm pretty sure more sophisticated things can be linted, as long as you're willing to provide the stand-in macro


that's awesome stuff - I think my dsl approach worked for "regular" looking macros a bit better than the lint-as but this is clearer and more generally applicable.


I'll add this to the unit tests 🙂