This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2021-11-22
Channels
- # announcements (39)
- # architecture (9)
- # aws (2)
- # babashka (17)
- # beginners (73)
- # calva (6)
- # cider (27)
- # clj-kondo (140)
- # cljdoc (67)
- # cljsrn (1)
- # clojure (99)
- # clojure-dev (4)
- # clojure-europe (35)
- # clojure-nl (7)
- # clojure-spec (19)
- # clojure-uk (2)
- # clojurescript (40)
- # community-development (3)
- # cursive (10)
- # datalevin (2)
- # datavis (2)
- # datomic (27)
- # deps-new (5)
- # events (2)
- # fulcro (38)
- # integrant (6)
- # jobs (3)
- # keyboards (1)
- # leiningen (13)
- # lsp (3)
- # malli (10)
- # meander (5)
- # membrane (1)
- # membrane-term (9)
- # missionary (3)
- # off-topic (29)
- # polylith (3)
- # reagent (3)
- # reitit (5)
- # remote-jobs (2)
- # reveal (7)
- # shadow-cljs (20)
- # tools-build (4)
- # tools-deps (8)
- # vim (10)
- # xtdb (3)
Perhaps if not a macro, then something that clj-kondo could do (in principle)? https://clojurians.slack.com/archives/C03S1KBA2/p1637568739382000
@orestis you can make custom macro/function hooks in which you can do this checking yourself
hm, would hiccup syntax also work? e.g. the ideal use case is that the callsite is:
[text/Text {:variant "Large" :color "Main"} "here is some text"]
and I can validate "Large"
and "Main"
against a static set of values.
then you would have to add a hook for text/Text
(with the namespace fully qualified)
you could consider using https://github.com/borkdude/grasp to search for this pattern, but this is more offline than in your editor
@orestis Here is a full example:
user=> (require '[grasp.api :as g])
nil
user=> (def spec (g/vec (g/rsym 'foo.text/Text) (s/and map? #(:variant %))))
#'user/spec
user=>
user=> (g/grasp-string "(require '[foo.text :as text]) [text/Text {:variant \"Foo\"}])" spec)
[[text/Text {:variant "Foo"}]]
user=>
user=> (def results *1)
#'user/results
user=> (map (fn [res] (-> res second :variant)) results)
("Foo")
user=>
@benjamin.schwerdtner It works out of the box with clj-kondo, but if you have a dependency of Clojure older than 1.11 alpha such and so, it's not in there. And if this dependency is used for linting then it overwrites the built-in cache for clojure.
my /usr/bin/clojure
is clojure 1.10 so and so. I guess that is the problem? The lint target uses 1.11
have you linted your dependencies and how? which version of clj-kondo are you using?
So this is back on friday, but I also get the lsp errors in my flycheck error list that I get integration for with treemacs-list-errors, and I definitely go through them all, and I definitely get the errors that don't have line numbers that way.
Ah, I see that was resolved.
What would be a reason I'm getting an unresolved var warning for a #'
var form with the fully qualified name of a public var?
hmm. I'll take a look in the ns to see how it's defined
ah, they're using a custom def macro.
Funnily enough, I'm getting this, but it's a bit weird, since I'm seeing, in the same namespace, where it is saying unsolved var (yet the var exists in the other namespace), and just above the undefined vars, are vars it can find, that have the same macro.
kondo only reports a single var once per file I believe
but did you visit that file recently? e.g. has clj-kondo linted that one - perhaps it has recent modifications or you checked out a git branch?
that's just a snippet. Imagine, if you will, that that list continues on for several more lines. clj-kondo finds most of the public-routes
, but raises the same exception for others in the list (that do exist!)
making a minimal repro sometimes isn't that hard. yesterday I cut down a minimal repro from several hundred lines to 5 characters in a minute ;)
and this is the only way I can help. I haven't got any other ideas without more info
I have a nice template that will generate a project for me, having to try to reproduce there
@mynomoto the idea is that you can find matching results and then transform those results, e.g. using s/conform
or whatever you like
There you will need something like grasp + rewrite-clj. Grasp gives you the locations, and rewrite-clj allows you to update clojure code.
yes, but this fork cannot be used to update code. since it does not have the whitespace
if you use rewrite-clj's zippers, you can navigate while it also takes into account whitespace. yes: my fork just ignore the whitespace during reading. if you don't have those tokens, you cannot produce the code reliably anymore. well, I guess you could by just looking at the locations and inserting whitespace, but you won't know if there were tabs or spaces.
I did this basically because I wanted to use rewrite-clj only for analysis, not rewriting
@mynomoto like borkdude suggests, the rewrite-clj zip API will skip whitespace and comments while navigating but it preserves them.
@mynomoto carve is a tool which uses clj-kondo for analysis, gets locations and then uses the original rewrite-clj to update code
I think it's good to have separate tools for what you want: finding problem locations in code vs updating code using locations
Would it be significant that if I run clj-kondo
on the command line, for that particular file, it does not report unresolved var, but when editing the file in my editor, that uses clojure-lsp (with clj-kondo under the hood), that the warning is produced?
yes, the cache is versioned with the version of clj-kondo, so if clojure-lsp uses a different version, then the used cache won't be the same
Right, if I get clj-kondo to lint the entire source directory, the warning is displayed.
yeah, the unresolved-var
linter from kondo is one of the linters that relies on the cache, since it need to know the namespaces available + their var-definitions
you can repro manually with kondo if you lint with the same version clojure-lsp as well
I was simply trying to determine by a process of elimination what is causing the warning to be displayed
@borkdude did you say that it's possible for clj-kondo to show all unresolved vars, not just the first one?
@borkdude I can reproduce it. I'm going to raise an issue for you to have a look when you have time 🙂 I also have a project you can use.
I think a better solution would be if compojure.sweet.api had some proper clj-kondo hook expansions, but I'm not sure how much this is used anymore, it has becomes a little bit of a legacy compared to reitit right?
What's the recommended approach for projects that get clj-kondo
configs exported into them from dependencies? Check that into version control or not?
Untracked files:
(use "git add <file>..." to include in what will be committed)
../.clj-kondo/com.github.seancorfield/next.jdbc/
(because the latest version of next.jdbc
exports its hooks etc)
@seancorfield yes, just check it into source control. so anyone who check outs your project has the same linting, and also CI has the same linting.
you also have to add this to .clj-kondo/config.edn
:config-paths ["com.github.seancorfield/next.jdbc"]
I'm considering doing this automatically (implicitly) but I'm not yet sure if this is a good idea or what could go wrong
the danger would be: malfunctioning configs or never-ending loops in hooks for example
We could have a file to which we append automatically when importing/copying configs
.clj-kondo/config-paths.edn
(wrapped implicitly in a map):
"com.github.seancorfield/next.jdbc" true
".../..." false
and when there is already an entry (e.g. with false
) then we do not override that.
Hmm, glad I asked. I didn't realize I needed to manually update config when something got exported into my project.
yes, the reason is that I think people should be able to opt in or opt out of these configs
we could also just have a .config_ignore
file which contains paths not to ever import.
Hi, I wrote my own hook is it enough to just run clj-kondo --lint "src"
after updating config.edn
or am I missing something?
Because it seems like it doesn't include my newest changes
config.edn
{:linters {:translate/unwrapped {:level :error}}
:hooks {:analyze-call {foo/unwrapped hooks.unwrapped/register-unwrapped}}}
and the hook:
(ns hooks.unwrapped
(:require [clj-kondo.hooks-api :as api]))
(defn register-unwrapped [{:keys [:node]}]
(let [test (println "HELLO")]
(api/reg-finding!
{:message "HELLO WORLD"
:type :translate/unwrapped
:row (:row (meta node))
:col (:col (meta node))})
))
@U0281QDFE1X in which directory did you put the hook code?
@borkdude .clj-kondo/hooks/unwrapped.clj
it's the hook file path from the root of the project
and you don't see anything when you lint
(require '[foo.bar :as foo])
(foo/unwrapped 1 2 3)
?So I run clj-kondo --lint "src"
and I get old warnings, but no errors, also no println
It seems that clj-kondo works, but it does not run the hook. As there should be errors from this hook
Hmm what do you mean by > and you don't see anything when you lint > (require '[foo.bar :as foo]) > (foo/unwrapped 1 2 3) ohh so this hook is not run automatically through every namespace?
I think I've misunderstood how hooks work.
I was expecting it to run this hook through all functions in "src" directory and if the hook function gets to the (reg-finding! ...)
it reports error
:analyze-call {foo.bar/baz ....}
is executed for functions like this:
(require '[foo.bar :as fbar])
(fbaz/baz 1 2 3) ;; <-- the hook sees this node
Now I understand how hook works. Thanks! I want to add a lint rule, for checking reagent dom tree. There is a bug that if there is text that is not wrapped in :span tag, google translate add tags to it and react throws error that it cannot remove the child. So I wanted to check every function if there is for example "[:div "Hello"] and throw message that this "Hello" needs to be wrapped in [:span]
Makes sense. Currently hooks don't really provide access to this. Perhaps you can use something like https://github.com/borkdude/grasp. I gave an example of that here: https://clojurians.slack.com/archives/CHY97NXE2/p1637573107258800
Thanks! But with hook, couldn't I just hook to every "defn" function call to see if there is div?