This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2023-02-05
Channels
- # babashka (13)
- # beginners (146)
- # biff (3)
- # calva (18)
- # cider (6)
- # clerk (29)
- # clj-commons (1)
- # clj-kondo (75)
- # clojure (42)
- # clojure-belgium (2)
- # clojure-europe (13)
- # clr (9)
- # conjure (2)
- # datomic (2)
- # gratitude (3)
- # hyperfiddle (3)
- # off-topic (26)
- # reitit (5)
- # releases (1)
- # shadow-cljs (2)
- # timbre (3)
Does kondo support detecting keywords that could be mistyped? Eg. if a namespaced or even plain keyword appears only once in the codebase it might be a typo?
It doesn't do this, but clojure-lsp might be able to do this as it keeps all the keywords of the whole project in memory
I produced an interesting bug the other day by doing search-replace from in-line strings to a var. There was a case statement that broke since case doesn’t support dereferencing vars.
This has come up before but it isn't possible to detect if the users intentionally matches the literal symbol or not
What we could however detect if when the argument is a certain type (string) and nothing in the case matches that type, we could warn
Ah right. If this was an optional linter, it could be easily be circumvented by using the quoted form for the (rare?) cases you want to match against a symbol
user=> (case 'foo-var foo-var "something" nil) ;; warn on this
"something"
user=> (case 'foo-var 'foo-var "something" nil) ;; but not on this
"something"
My personal opinion (without any data to back it) is that using case as-designed (of not dereferencing symbols) is probably not that much used and a confusing bug (for beginners, at least).
huh, the second case is also not valid, quoted symbols in case is never what you want
This is just co-incidental since 'foo-bar
expands by the reader into (quote foo-bar)
so it would also match the symbol quote
:
user=> (case 'quote 'foo-var "something" nil)
"something"
user=> (let [a "foo" b "bar"] (case "foo" 'a :a 'b :b))
Syntax error macroexpanding case at (REPL:1:24).
Duplicate case test constant: quote
That is, I was away from the REPL - if I was writing new code I'd have caught it, but since it was old code that was being refactored, then it slipped under my radar.
in clj-kondo's codebase there is actually a case statement which matches against the names of vars as symbol so that would be one counter-example, but agreed that this is probably an exception to the rule. also using class names in case is an often source of confusion
I think in most "day-to-day" codebases that linter could be enabled, and then disabled for very specific instances of case statements (still should be an optional linter, I guess)
I wonder if an optional linter needs to be so accurate as to look into locals or vars, or instead just ban symbols altogether
I'd say just ban symbols. It would be good to scan existing codebases for such usages of case. You can do so using grasp: https://github.com/borkdude/grasp
I always mean to use grasp but I alway forget what it's called. You should pack it in babashka 🙂
So that it could be e.g. invoked by the command line. (Not really suggesting that, I've no idea about it 😄 )
According to grasp here are some counter-examples:
| :line | :column | :uri |
|-------+---------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 176 | 17 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/util/instrument.clj |
| 40 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/enlighten.clj |
| 176 | 20 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/fipp/v0v6v26/fipp/clojure.cljc |
| 320 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
| 413 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
| 325 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
| 434 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
| 257 | 5 | jar:file:/Users/borkdude/.m2/repository/nrepl/nrepl/1.0.0/nrepl-1.0.0.jar!/nrepl/bencode.clj |
| 282 | 16 | jar:file:/Users/borkdude/.m2/repository/nrepl/nrepl/1.0.0/nrepl-1.0.0.jar!/nrepl/cmdline.clj |
| 1216 | 23 | jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
| 1284 | 31 | jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
| 144 | 3 | jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/utils.cljc |
| 358 | 4 | jar:file:/Users/borkdude/.m2/repository/org/clojure/clojure/1.11.0/clojure-1.11.0.jar!/clojure/test.clj |
| 176 | 9 | jar:file:/Users/borkdude/.m2/repository/org/clojure/clojure/1.11.0/clojure-1.11.0.jar!/clojure/core/server.clj |
| 46 | 6 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
| 58 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
| 20 | 7 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer/passes/collect_closed_overs.clj |
| 50 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer/passes/elide_meta.clj |
| 21 | 6 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer/passes/add_binding_atom.clj |
| 809 | 4 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer.clj |
| 320 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
| 413 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
| 325 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
| 434 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
| 427 | 4 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/jvm.clj |
| 151 | 3 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/passes/jvm/analyze_host_expr.clj |
| 26 | 3 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/passes/jvm/annotate_host_info.clj |
| 327 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader/edn.cljs |
| 436 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader.cljs |
| 415 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader.clj |
| 322 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader/edn.clj |
Here is the first counter-example:
https://github.com/clojure-emacs/cider-nrepl/blob/d219ce610d9030108c273fab933538fb3b24d8be/src/cider/nrepl/middleware/util/instrument.clj#L176
You can go through the rest to learn more :)
I've just matched against (System/getProperty "java.class.path")
I found one case (!) where it matches the default case as a symbol which it shouldn't, let me fix that
Pushed, less cases now:
| :line | :column | :uri |
|-------+---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 176 | 17 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/util/instrument.clj |
| 40 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/middleware/enlighten.clj |
| 320 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
| 413 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
| 325 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
| 434 | 5 | jar:file:/Users/borkdude/.m2/repository/cider/cider-nrepl/0.28.6/cider-nrepl-0.28.6.jar!/cider/nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
| 1216 | 23 | jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
| 1284 | 31 | jar:file:/Users/borkdude/.m2/repository/org/babashka/sci/0.3.2/sci-0.3.2.jar!/sci/impl/analyzer.cljc |
| 46 | 6 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
| 58 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/extract_definition.clj |
| 809 | 4 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzer/v1v1v0/clojure/tools/analyzer.clj |
| 320 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader/edn.clj |
| 413 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/clojure/tools/reader.clj |
| 325 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader/edn.cljs |
| 434 | 5 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsreader/v1v3v6/cljs/tools/reader.cljs |
| 427 | 4 | jar:file:/Users/borkdude/.m2/repository/refactor-nrepl/refactor-nrepl/3.5.5/refactor-nrepl-3.5.5.jar!/refactor_nrepl/inlined_deps/toolsanalyzerjvm/v1v2v2/clojure/tools/analyzer/jvm.clj |
| 327 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader/edn.cljs |
| 436 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/cljs/tools/reader.cljs |
| 415 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader.clj |
| 322 | 5 | jar:file:/Users/borkdude/.m2/repository/org/clojure/tools.reader/1.3.4/tools.reader-1.3.4.jar!/clojure/tools/reader/edn.clj |
It would be good to scan your entire .m2 folder and see if any non-tooling libraries have any examples :)
| :line | :column | :uri |
|-------+---------+---------------------------------------------------------------------|
| 59 | 21 | file:/Users/orestis/dev/nosco/nosco-gamma/cljs/nosco/ui/inputs.cljs |
| 176 | 17 | |
| 40 | 5 | |
| 320 | 5 | |
| 413 | 5 | |
| 325 | 5 | |
| 434 | 5 | |
| 32 | 5 | |
| 1087 | 22 | |
| 58 | 6 | |
| 1216 | 23 | |
| 1284 | 31 | |
| 427 | 4 | |
| 327 | 5 | |
| 436 | 5 | |
| 415 | 5 | |
| 322 | 5 | |
| 415 | 5 | |
| 322 | 5 | |
| 809 | 4 | |
I see this - the first file is the bug we found (the fix is in a branch) but the rest seems to not have any uris?https://github.com/redplanetlabs/proxy-plus/blob/master/src/com/rpl/proxy_plus.clj#L58 an interesting case
Everything else is tools.reader, tools.analyzer, clj-kondo plus variations of those vendored in other deps.
yeah, so it seems mostly clojure-related / low level libraries that tend to use this
Plus a bug: https://github.com/dm3/clojure.java-time/blob/master/src/java_time/format.clj#L32
clojure-lsp should have a refactoring to change an if to a cond - but in this case it's even a cond->
clj-kondo would have detected this since it expands -> and ->> and so on, but grasp is mostly for doing research on the feasibility of features for clj-kondo, SCI etc so it doesn't have to be 100% accurate
Ah interesting. So I guess grasp is not meant to be used as e.g. a very custom lint step or for answering definitive questions about a codebase.
if you want to have it 100% accurate wrt macros (which are always the problem when it comes to static analysis) you could double-check with tools.analyzer or so.