Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Typed Clojure Support #2210

Open
owenRiddy opened this issue Nov 4, 2023 · 7 comments
Open

Typed Clojure Support #2210

owenRiddy opened this issue Nov 4, 2023 · 7 comments

Comments

@owenRiddy
Copy link

Is your feature request related to a problem? Please describe.

There is a well-known project to add a type checker to Clojure. I would like to use types, a linter and Clojure simultaneously and I have been experimenting with the idea in the PR, but it is a struggle.

I'm trying to use a hook to get my project to pass a lint. There is a lot to do, but picking on a specific problem I have a defn-like form that is syntactically quite different from defn, but semantically very similar. The hook mechanism lets me rewrite code for linting, but the analyzer doesn't seem to use the resulting code so I get unresolved symbol errors even though the defn form itself passes.

Describe the solution you'd like
What would the expected path be to go about adding clj-kondo support to a project like typedclojure? I am aware of support for schema that require code in the analyzer itself. I'm hoping that there is some sort of reg-var! function call in the hooks API so I don't have to write analyzer code. I don't understand how the analyzer works and it looks intimidating.

I'd also be worried about the long-term prospects of that approach since it would require coordination between clj-kondo and typedclojure that seems like an unnecessary maintenance challenge compared to a mechanism like using hooks.

Describe alternatives you've considered
#_:clj-kondo/ignore tempts me every day.

Additional context
N / A

@borkdude
Copy link
Member

borkdude commented Nov 4, 2023

Can you post some examples of what is causing false positives with clj-kondo for typed clojure? Please be as specific as possible, so let's focus on something concrete and small first.

@owenRiddy
Copy link
Author

owenRiddy commented Nov 4, 2023

I'm paraphrasing this code so the line numbers won't quite line up:

(ns example
  (:require
   [clojure.core.typed :as t]))

(t/defalias ExampleObject
  (t/HMap :mandatory {:name t/Str}
          :complete? true))

;; I'm trying to get this form to pass a lint
(t/defn init-example-object
  [hi :- t/Str] :- ExampleObject
  (prn hi)
  {:name "Default"})

;; And this one.
(init-example-object "Hello world")

I have a hook that rewrites t/defn to a node that looks a little like this (see the linked PR in typed-clojure for the specific code, if it matters):

(list*
    (api/token-node 'defn)
    (-> name :value)
    (api/vector-node processed-args)
    body)

because of this, the code in t/defn lints without errors even though there is a weird :- ExampleObject. So far, good! But I don't know how to get rid of this lingering lint error in the last form.

$ clj-kondo --lint src/
<... expected errors...>
src/example.clj:13:7: error: Unresolved symbol: init-example-object
linting took 28ms, errors: 2, warnings: 4

@borkdude
Copy link
Member

borkdude commented Nov 4, 2023

I think this error happens because (-> name :value) is not a node but a symbol. Just pass the name node there.

@borkdude
Copy link
Member

borkdude commented Nov 4, 2023

Also it is recommended to emit a fully qualified node symbol since defn can also be something that users import from somewhere else.:

(api/token-node 'defn)

=>

(api/token-node 'clojure.core/defn)

@owenRiddy
Copy link
Author

owenRiddy commented Nov 4, 2023

Ah I see. I tired

(list*
 (api/token-node 'clojure.core/defn)
 name
 (api/vector-node processed-args)
 body)

and it worked much better. Thanks.

While I have your attention then, I'll pester you with a related question & observation.

  1. Why is there explicit mention of schema.core in analyzer.clj instead of only a hook in the schema project?

  2. There have been a couple of similar bugs to that one in my work on hooks. I'm finding it hard to figure out what these node objects are. I suspect here the mistake I made was that knowing list-node have children that are nodes, I believed that token nodes had values that could also be used as nodes.

I've been getting confused, consistently, about when I'm supposed to reach in to a node and extract something and whether the extracted thing is a node or not.

I'd offer to write something for the docs, but I still don't know.

@borkdude
Copy link
Member

borkdude commented Nov 4, 2023

re 1: because at the time that got added, hooks didn't exist yet and it was a very common source of false positives
re 2: running clj-kondo with the --debug flag will get you some warnings about this

@borkdude
Copy link
Member

borkdude commented Nov 4, 2023

Btw if the syntax of the typed clojure defn is exactly the same as the schema one, you could probably also use :lint-as.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants