clj-kondo

https://github.com/clj-kondo/clj-kondo
Volodymyr Huzar 2021-03-09T13:40:26.224300Z

I have a problem with linting usage of plumbing.core/?>

(let [live? true]
  (-> {}
    (plumbing.core/?> live? (assoc :live live))))
I am receiving two :invalid-arity errors
error: Insufficient input.
error: Expected: associative collection or nil, received: keyword.
Any thoughts on how to fix or ignore linting where it is used?

borkdude 2021-03-09T13:42:02.224600Z

Is this macro syntactically similar to one in core?

borkdude 2021-03-09T13:44:59.224900Z

it seems similar to cond-> am I right?

borkdude 2021-03-09T13:48:59.225600Z

@vguzar I think this macro can be regarded as deprecated in favor of clojure.core/cond-> which I think does the same, but I could be missing something

borkdude 2021-03-09T13:49:58.226300Z

But if you want to keep using it, you can use {:lint-as {plumbing.core/?> clojure.core/cond->}}

Volodymyr Huzar 2021-03-09T13:51:39.228100Z

seems like you are right that cond-> should be used instead, but I don’t think :lint-as will work as it is used differently but let me check. By the way is it possible to deprecate by clj-kondo?

borkdude 2021-03-09T13:52:42.228500Z

You mean say in your config: I regard these functions are deprecated, so give me a warning when you use them?

Volodymyr Huzar 2021-03-09T13:53:11.228800Z

yes, something like that

Volodymyr Huzar 2021-03-09T13:54:06.229900Z

as I suspected lint-as doesn’t help, ” No matching clause: “?>“” is shown as an error

borkdude 2021-03-09T13:54:20.230300Z

We do have a deprecated var linter: https://github.com/clj-kondo/clj-kondo/blob/master/doc/linters.md#deprecated-var But no way to add your own vars to that. That could be useful, but it's done automatically if the var is marked deprecated in the library already

borkdude 2021-03-09T13:55:11.230900Z

That's a weird error message. Let me try this.

borkdude 2021-03-09T13:59:40.231600Z

I can reproduce that, but it seems like a bug

Volodymyr Huzar 2021-03-09T14:00:38.232400Z

It could be useful to have your own set of deprecated 3rd party stuff, like stop use that and start use this instead

borkdude 2021-03-09T14:01:48.233Z

yeah, I agree. similar stuff has been considered for clojure.core/read-string for example, but there are cases where you still might want to use that

borkdude 2021-03-09T14:02:57.235Z

but if a var is deprecated in favor of something else that is compatible then that config would make sense for :deprecated-var {:deprecated-var {foo.bar/baz foo.bar/quux}} => Var foo.bar/baz is deprecated. Use foo.bar/quux instead

👍 1
teodorlu 2021-03-10T15:14:30.267600Z

{:deprecated-var {foo.bar/baz foo.bar/quux}}
Shot from the sideline, I'd prefer to be able to specify both what should be used instead (quux), and the reason for deprecation. So if you're designing a data structure for this, I'd put a map on the right side. Example:
{:deprecated-var {foo.bar/baz {:use-instead foo.bar/quux
                               :reason "baz has a bad API design, it doesn't handle X use case"}}}

borkdude 2021-03-10T15:15:24.267800Z

yes, good idea. I also want to put a map in between: {:deprecated-var {:some-name {foo.bar/baz ...}}} but I don't know what this name should be

teodorlu 2021-03-10T15:16:38.268Z

Something like

{:deprecated {:vars {foo.bar/baz {:use-instead foo.bar/quux
                                  :reason "..."}}}}
? Not sure what you want to achieve.

borkdude 2021-03-10T15:18:20.268400Z

Usually the structure is {:linter-name {:exclude {...}} so every setting has an explicit name within the linter map

👍 1
Volodymyr Huzar 2021-03-09T14:11:08.237600Z

and here I have another question which could be related to what you have said in corner cases. Is it possible to mark some rules not be run on specific namespaces. For example I want

:private-call
rule fails on production code but ignore it for tests. Could I use something like
:private-call {:level :error
               :exclude {:namespaces [".*-tests$"]}} 
?

borkdude 2021-03-09T14:14:45.238Z

In tests you can use #'my.private/var

borkdude 2021-03-09T14:16:11.238700Z

or you can turn it off in the namespace config:

(ns foo
  {:clj-kondo/config '{:linters {:private-call {:level :off}}}})

Volodymyr Huzar 2021-03-09T14:21:21.240300Z

so it is not possible to set in configuration that some particular rule will be disabled for all namespaces matching pattern “.*-tests$“, is it?

borkdude 2021-03-09T14:24:37.240500Z

no

borkdude 2021-03-09T14:24:49.240700Z

This is what you use the namespace local config for

borkdude 2021-03-09T14:25:43.241200Z

Are you using this in ClojureScript? AFAIK the Clojure compiler forbids using private vars unless via the var object

borkdude 2021-03-09T14:37:22.241700Z

Can you create an issue about the deprecated var idea? I am fixing the bug with lint-as + cond-> as we speak.

1
borkdude 2021-03-09T14:39:26.241900Z

Fixed on master

👍 1
Volodymyr Huzar 2021-03-09T14:50:19.243Z

> Are you using this in ClojureScript? Yes, I’m, probably it should be okay to make them public in such case

borkdude 2021-03-09T14:51:30.243300Z

In CLJS using #'foo/bar also works

1
Volodymyr Huzar 2021-03-09T15:20:04.244100Z

@borkdude issue for third-party deprecation is created https://github.com/clj-kondo/clj-kondo/issues/1207 Feel free to edit the description by itself

🙏 1
Volodymyr Huzar 2021-03-09T15:31:48.248300Z

> In CLJS using `#'foo/bar` also works Maybe I got you wrong but this doesn’t work for cljs. (to add I am not so experience in Clojure syntax 😶) I have tried to change from

(ns test
  (:require [foo :refer [bar]))

(def test-bar bar)
to
(ns test)

(def test-bar #'foo/bar)
and it fixed the linter but broken the test in the same time

borkdude 2021-03-09T15:38:00.248700Z

You should still require the namespace

borkdude 2021-03-09T15:38:39.249400Z

You don't have to define test-bar, you can do it like this:

(ns test
  (:require foo))
(#'foo/bar 1 2 3)

borkdude 2021-03-09T15:46:13.250100Z

foo=> (ns foo)
WARNING: foo is a single segment namespace at line 1
nil
foo=> (def ^:private x 1)
#'foo/x
foo=> @#'foo/x
1
foo=> (ns bar (:require foo))
WARNING: bar is a single segment namespace at line 1
Execution error (ExceptionInfo) at (<cljs repl>:1).
No such namespace: foo, could not locate foo.cljs, foo.cljc, or JavaScript source providing "foo"
foo=> @#'foo/x
1
This is from a REPL session

Volodymyr Huzar 2021-03-09T15:50:01.250800Z

thanks, by bad knowledge on clojure syntax I have missed @