Fork me on GitHub
#clj-kondo
<
2021-11-29
>
borkdude10:11:56

@chris441 For this purpose we have ns-analysis: it will return cached data. Clj-kondo does not read anything from disk while linting. It just lints the fileset you give it. But if you already have linted your files once, then ns-analysis gives back the vars for a certain namespace. See https://github.com/clj-kondo/clj-kondo/blob/master/doc/hooks.md.

borkdude10:11:09

Note that requiring-resolve etc in a clj-kondo macro (at "compile" time) just loads other hook code, it doesn't load your real dependency.

chrisn16:11:58

That is what I figured after looking at the data. Thanks, will checkout hooks a bit closer.

borkdude16:11:30

I think @hugod had a very similar use case like yours, this is why ns-analysis got added

hugod16:11:00

Using ns-analysis works well when using clojure-lsp, since it is generally kept from getting stale. I’ve used it for impprt-ns type macros, and also for some macros that import defrecord types.

borkdude16:11:22

It should also work with vanilla flycheck-clj-kondo etc, every time you visit the imported ns and change stuff there, the analysis cache is updated. If you're thinking of switching branches, then you could make a commit hook to re-lint your project.

borkdude16:11:56

But clojure-lsp also takes care of that

chrisn22:11:32

OK, that appears to be working in one sense - the errors I get out of clj-kondo now match the correct arities of the imported functions.

chrisn22:11:41

When I load the actual metadata produced, however, I note that the imported functions don't have a :fixed-arities map entry - I am careful to recreate the arities in the macro -

(defmacro export-symbols
  [src-ns & symbol-list]
  (let [analysis (:clj (hooks-api/ns-analysis src-ns))]
    `(do
       ~@(->> symbol-list
              (mapv
               (fn [sym-name]
                 (when-let [fn-data (get analysis sym-name)]
                   (if-let [arities (get fn-data :fixed-arities)]
                     `(defn ~sym-name
                        ~@(->> arities
                               (map (fn [arity]
                                      (let [argvec (mapv
                                                    #(symbol (str "arg-" %))
                                                    (range arity))]
                                        `(~argvec (apply + ~argvec)
                                          ;;This line is to disable the type detection of clj-kondo
                                                  ~(if-not (= 0 arity)
                                                     (first argvec)
                                                     :ok)))))))
                     `(def ~sym-name :defined)))))))))
So I would say this is perhaps finished or perhaps just partly working. I don't see argnames anywhere which is fine nor a docstring but I didn't see that in the metadata before so perhaps also fine.

hugod00:11:24

This is what I have

(defn import-namespace
  "Transform an import-ns into a sequence defn and defmacro"
  [{:keys [node]}]
  (let [[_ ns-name] (:children node)
        analysis    (-> (:string-value ns-name)
                        symbol
                        api/ns-analysis
                        :clj
                        vals)
        new-node
        (api/list-node
         (list*
          (api/token-node 'do)
          (->> analysis
               (remove :private)
               (mapv
                (fn
                  [{:keys [fixed-arities
                           macro
                           varargs-min-arity]
                    sym   :name}]
                  (if (or fixed-arities varargs-min-arity)
                    (api/list-node
                     (list*
                      (if macro
                        (api/token-node 'defmacro)
                        (api/token-node 'defn))
                      (api/token-node sym)
                      (if fixed-arities
                        (map
                         (fn [n]
                           (api/list-node
                            (list
                             (api/vector-node
                              (repeat n (api/token-node '_)))
                             (api/token-node
                              (symbol
                               (:string-value ns-name)
                               (str sym))))))
                         fixed-arities)
                        [(api/vector-node
                          (concat
                           (repeat varargs-min-arity (api/token-node '_))
                           [(api/token-node '&) (api/token-node '_)]))
                         (api/token-node
                          (symbol
                           (:string-value ns-name)
                           (str sym)))])))
                    (api/list-node
                     (list
                      (api/token-node 'def)
                      (api/token-node sym)
                      (api/token-node
                       (symbol
                        (:string-value ns-name)
                        (str sym)))))))))))]
    #_(prn :import-namespace (api/sexpr new-node))
    {:node (with-meta new-node (meta node))}))

borkdude22:11:51

You can look in the transit map in the .cache folder to see if the info is there. Perhaps it's just not exposed currently.

chrisn22:11:58

I am looking at the transit map. Here is the metadata of the source function:

{->reader
 {:row 146,
  :col 1,
  :fixed-arities #{1 2},
  :name ->reader,
  :ns tech.v3.datatype.base,
  :top-ns tech.v3.datatype.base},
and here is the metadata of the imported function:
{->reader
 {:row 40, :col 1, :name ->reader, :ns tech.v3.datatype, :top-ns tech.v3.datatype},
Now as I said above, clj-kondo is itself reporting arity issues correctly with the function so at runtime it is correct I am just curious about the metadata as my goal is for clojure-lsp to work correctly with this.

chrisn22:11:49

Ah, it is in the function expansion. clj-kondo lints to code correclty:

chrisn22:11:56

(base) chrisn@chrisn-lt3:~/dev/cnuernber/dtype-next$ scripts/clj-kondo | head
src/tech/v3/datatype.clj:299:3: error: tech.v3.datatype/->reader is called with 4 args but expects 1 or 2

chrisn22:11:23

It just didn't make it to the metadata cache itself

chrisn22:11:34

Or the cache didn't update or I am looking at the wrong cache.

borkdude22:11:07

clj-kondo command line may be a different version than what lsp uses (typically a recent snapshot)

borkdude22:11:28

and each version of clj-kondo caches under its own key

borkdude22:11:04

in the .cache dir: .cache/$version/...

chrisn22:11:12

Got it, that makes sense.

chrisn22:11:21

I was looking at the wrong cache.

chrisn22:11:12

clj-kondo's cache is now correct.

🎉 1