Fork me on GitHub
#clj-kondo
<
2023-08-09
>
Jake Pearson15:08:10

Hi. I continue to work on getting all the lints out of my team's repos this week. I got to a bunch of unresolved symbols due to our usage of hugsql. I found @borkdude response on https://stackoverflow.com/questions/61727582/how-to-avoid-unresolved-symbol-with-clj-kond-when-using-hugsql-def-db-fns-macro, but wondered if a more automatic solution would be possible. I wrote the following code (that appears to do what I want from my REPL):

(ns hugsql
  (:require [clojure.string :as string]))

(defn def-names [resource-path]
  (let [lines (-> (str "src/" resource-path)
                  clojure.core/slurp
                  string/split-lines)]
    (->> lines
         (filter (fn [line]
                   (string/starts-with? line "-- :name")))
         (map (fn [line]
                (-> line
                    (string/split #" ")
                    (nth 2)))))))

(defmacro def-db-fns [file _options]
  (->> (for [defn-name (def-names file)]
         `(defn ~defn-name [db arg-map]))
       (cons 'do)))
And mapped it in my clj-kondo config. I now get the following output in clj-kondo:
WARNING: error while trying to read hook for hugsql.core/def-db-fns: Could not resolve symbol: clojure.core/slurp
Is there a way to read a file using the SCI parser that clj-kondo uses?

Stig Brautaset15:08:38

We put this bit in a separate “queries” namespace:

(hugsql/def-db-fns "select_things.sql")
The indirection means that clj-kondo doesn’t complain.

Stig Brautaset15:08:57

And we don’t have to put declare anywhere.

Jake Pearson16:08:23

Ok! I can do that.

Jake Pearson16:08:06

Thanks. Let me give that a try.

Jake Pearson16:08:44

Hmm, I think I did what you suggested, but I still get a lint:

src/voltron/queries/db.clj:17:4: warning: Unresolved var: queries/select-stuff
changed from unresolved symbol to unresolved var. Did you make any other changes?

Stig Brautaset16:08:26

No, I don’t think so. I don’t see any exclusions in our config file.

Jake Pearson16:08:38

I'll try making a little repo and see if I can get it to work.

borkdude16:08:50

You can get rid off those unresolved-var stuffs by adding a bit more config:

{:linters {:unresolved-var {:exclude [the-hug-sql-vars.ns]}}}

👍 2
Jake Pearson16:08:00

@U03N9E40Q2F On my trivial example project, your suggestion worked. Something must be a little different in my real repo.

👍 2
Stig Brautaset16:08:28

Older version of clj-kondo?

Jake Pearson16:08:49

clj-kondo v2023.07.13

borkdude16:08:55

The difference comes from having a non-empty .cache entry for that namespace or not

👍 2
Jake Pearson16:08:17

That makes sense. Thanks.

borkdude16:08:18

if there is a non-empty one, then clj-kondo thinks its knows that namespace and will start to warn about that namespace

Jake Pearson16:08:17

I deleted my cache and the warning went away. Thanks everyone for the help. And @borkdude for the great tool.

❤️ 2
Jake Pearson15:08:55

I think everything is working now, but I was still wondering if there is a way to read in a file in the interpreter that kondo uses?

borkdude15:08:49

what would be the use case for this?

Jake Pearson15:08:35

The thing I can think of would be the example I wrote at the top of this thread. Hugsql reads in a file to generate defs so I would love to get the same functionality instead of excluding a namespace from some lints.

borkdude15:08:25

are you using clojure-lsp perhaps?

Jake Pearson15:08:01

I use lsp through calva, but for PR checks we use clj-kondo from the command line.

borkdude15:08:16

ok. for clojure-lsp you could use stubs: https://clojure-lsp.io/settings/#stub-generation it uses this little library: https://github.com/clj-easy/stub you could just create some stubs manually and add that to a :clj-kondo alias in your deps.edn and add it to the lint classpath

borkdude15:08:35

this would probably be an easier route than trying to parse .sql files in a clj-kondo hook

Jake Pearson15:08:58

Thanks, I'll take a look

Joel21:08:34

Seems like a leading hyphen in a function name as in -my-function is very common to denote a “private” function. Is there a Kondo check for misuse? (Invoking the function from another namespace)

borkdude21:08:42

if the function is private, you should use the ^:private metadata. - does not always mean private, e.g. -main is a common convention

Joel21:08:06

Yeah, I knew it wasn’t “canon”, but I see it a lot, I suppose to avoid the extra referencing in the tests.

seancorfield21:08:40

In particular -main uses a - to indicate that it should be compiled to a Java main function -- so you'll see a leading hyphen in any code that is gen-class'd for producing Java-compatible methods.

borkdude21:08:08

- is also a convention in ClojureScript protocols, it doesn't necessarily mean private. it could mean "lower level function" but it was specifically NOT made private, because other namespaces (of the same library) sometimes need to call into those lower level functions

✔️ 2
hifumi12323:08:34

heh, borkdude beat me to it. My immediate instinct on the comment about - prefixes was to bring up specifically naming conventions in ClojureScript protocol functions, and the fact that it is the default prefix when you use :gen-class in JVM Clojure. 🙂

hifumi12323:08:39

With that said, in the CLJS world -foo typically points to an implementation detail. It may be useful to write a linter that warns on this prefix, but enabling it by default would not be a good idea, and it is not very useful at all in JVM Clojure