Can rewrite-clj read metadata? I'm particularly interested in ^:deprecated and ^:added - I wrote a tiny documentation generator using Babashka, and that' the only bit that I'm missing and I couldn't figure out how to do. I did notice that the ^:deprecated string appears when I use rewrite-clj.node but I don't see an obvious way of reading that programmatically without using regexes (uh)
yes
btw you could maybe also use the clj-kondo analysis data, this spits out data about vars as well by reading rewrite-clj nodes
This is used in #quickdoc for documentation generation
I noticed that your doc generator uses kondo pod, I was thinking of taking that route eventually but just for my own education I'd love to learn to how to do this just with rewrite-clj :-)
alright
(I also looked into how Kondo does this, but couldn't dive that deep because of time constraints)
user=> (p/parse-string "^:deprecated x")
<meta: ^:deprecated x>
This returns a meta nodeWhat is the part, from there, that you don't understand?
that part, I get but it's not clear how to read the meta part, here's the relevant part of my code: https://gist.github.com/lukaszkorecki/bddc0c296e044b9e6d0ddfc5623adfd7
when I use (z/sexpr) - metadata is not included
user=> (meta (n/sexpr (p/parse-string "^:deprecated x")))
{:deprecated true}hmm, I remember trying that out - let me double check
user=> (meta (z/sexpr (z/of-string "^:deprecated x")))
{:deprecated true}I see, the above works, but why this doesn't?
# bb
Babashka v1.3.188 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.
user=> (require '[rewrite-clj.zip :as z] '[rewrite-clj.parser :as p])
user=> (meta (z/sexpr (z/of-string "(defn ^:deprecated create \"some doc\" [] :x)")))
nil
user=>because the metadata is not on defn but on the create symbol
ohh
I assumed I can do something like (into [] (s/expr (z/of-string ...fn source...))) and read the meta that way
ok, that's helpful - I'll keep digging, thank you!
thank you @borkdude, that was super useful, final impl looks like this:
(defn get-fns-info [parsed]
(let [fn-info (atom [])]
(-> parsed
(z/prewalk (fn [thing]
(when (and
(z/list? thing)
(= "defn" (str (first (z/sexpr thing)))))
(let [sexpr (z/sexpr thing)
[_f name docstring & _rest] sexpr
node (z/node thing)
metadata (when-let [meta? (first (filter #(= :meta (:tag %)) (remove n/whitespace? (n/children node))))]
(meta (n/sexpr meta?)))
source (str node)
position (zipmap [:line :column] (z/position thing))]
(swap! fn-info conj
{:name name
:metadata metadata
:position position
:source source
:docstring (when (string? docstring)
docstring)})))
thing)))
(sort-by #(-> % :position :line) (deref fn-info))))