|
1 | | -(ns nextjournal.clerk.analyzer2 |
| 1 | +(ns nextjournal.clerk.analyzer-old |
2 | 2 | {:nextjournal.clerk/no-cache true} |
3 | 3 | (:refer-clojure :exclude [hash]) |
4 | 4 | (:require [babashka.fs :as fs] |
5 | 5 | [clojure.core :as core] |
6 | 6 | [clojure.java.io :as io] |
7 | 7 | [clojure.set :as set] |
8 | 8 | [clojure.string :as str] |
| 9 | + [clojure.tools.analyzer :as ana] |
| 10 | + [clojure.tools.analyzer.ast :as ana-ast] |
| 11 | + [clojure.tools.analyzer.jvm :as ana-jvm] |
| 12 | + [clojure.tools.analyzer.utils :as ana-utils] |
9 | 13 | [multiformats.base.b58 :as b58] |
10 | 14 | [multiformats.hash :as hash] |
11 | | - [nextjournal.clerk.analyzer.impl :as ana :refer [analyze*]] |
12 | 15 | [nextjournal.clerk.classpath :as cp] |
13 | 16 | [nextjournal.clerk.config :as config] |
14 | 17 | [nextjournal.clerk.parser :as parser] |
|
60 | 63 | (comp (keep :class) |
61 | 64 | (filter class?) |
62 | 65 | (map ensure-symbol)) |
63 | | - (ana/nodes analyzed)) |
| 66 | + (ana-ast/nodes analyzed)) |
64 | 67 | (into #{} |
65 | 68 | (comp (filter (comp #{:const} :op)) |
66 | 69 | (filter (comp #{:class} :type)) |
67 | 70 | (keep :form) |
68 | 71 | (map ensure-symbol)) |
69 | | - (ana/nodes analyzed)))) |
| 72 | + (ana-ast/nodes analyzed)))) |
70 | 73 |
|
71 | 74 | #_(map type (:deps (analyze '(+ 1 2)))) |
72 | 75 |
|
|
80 | 83 |
|
81 | 84 | #_(rewrite-defcached '(nextjournal.clerk/defcached foo :bar)) |
82 | 85 |
|
| 86 | +(defn unresolvable-symbol-handler [ns sym ast-node] |
| 87 | + ast-node) |
| 88 | + |
| 89 | +(defn wrong-tag-handler [tag ast-node] |
| 90 | + ast-node) |
| 91 | + |
| 92 | +(def analyzer-passes-opts |
| 93 | + (assoc ana-jvm/default-passes-opts |
| 94 | + :validate/wrong-tag-handler wrong-tag-handler |
| 95 | + :validate/unresolvable-symbol-handler unresolvable-symbol-handler)) |
| 96 | + |
83 | 97 | (defn form->ex-data |
84 | 98 | "Returns ex-data map with the form and its location info from metadata." |
85 | 99 | [form] |
|
91 | 105 | ([bindings form] |
92 | 106 | (binding [config/*in-clerk* true] |
93 | 107 | (try |
94 | | - (analyze* (assoc (ana/to-env bindings) |
95 | | - :ns (ns-name *ns*)) form) |
| 108 | + (let [old-deftype-hack ana-jvm/-deftype] |
| 109 | + ;; NOTE: workaround for tools.analyzer `-deftype` + `eval` HACK, which redefines classes which doesn't work well with instance? checks |
| 110 | + (with-redefs [ana-jvm/-deftype (fn [name class-name args interfaces] |
| 111 | + (when-not (resolve class-name) |
| 112 | + (old-deftype-hack name class-name args interfaces)))] |
| 113 | + (ana-jvm/analyze form (ana-jvm/empty-env) {:bindings bindings |
| 114 | + :passes-opts analyzer-passes-opts}))) |
96 | 115 | (catch java.lang.AssertionError e |
97 | 116 | (throw (ex-info "Failed to analyze form" |
98 | 117 | (form->ex-data form) |
|
119 | 138 |
|
120 | 139 | (defn analyze [form] |
121 | 140 | (let [!deps (atom #{}) |
122 | | - analyzed (binding [ana/*deps* !deps] |
123 | | - (-> (analyze-form (rewrite-defcached form)) |
124 | | - (ana/resolve-syms-pass) |
125 | | - (ana/macroexpand-pass))) |
126 | | - _ (ana/prewalk (ana/only-nodes |
127 | | - #{:var :binding :symbol} |
128 | | - (fn [var-node] |
129 | | - (case (:op var-node) |
130 | | - :var (let [var (:var var-node)] |
131 | | - (swap! !deps conj var)) |
132 | | - :binding (when-let [t (:tag (meta (:form var-node)))] |
133 | | - (when-let [clazz (try (resolve t) |
134 | | - (catch Exception _ nil))] |
135 | | - (when (class? clazz) |
136 | | - (swap! !deps conj (.getName ^Class clazz))))) |
137 | | - :symbol (when-not (:local? var-node) |
138 | | - (let [form (:form var-node)] |
139 | | - (if (qualified-symbol? form) |
140 | | - (let [clazz-sym (symbol (namespace form))] |
141 | | - (when-let [clazz (try (resolve clazz-sym) |
142 | | - (catch Exception _ nil))] |
143 | | - (when (class? clazz) |
144 | | - (swap! !deps conj (.getName ^Class clazz))))) |
145 | | - (when-let [clazz (try (resolve form) |
146 | | - (catch Exception _ nil))] |
147 | | - (when (class? clazz) |
148 | | - (swap! !deps conj (.getName ^Class clazz)))))))) |
149 | | - var-node)) analyzed) |
150 | | - nodes (ana/nodes analyzed) |
| 141 | + !forms (atom []) |
| 142 | + mexpander (fn [form env] |
| 143 | + (swap! !forms conj form) |
| 144 | + (let [f (if (seq? form) (first form) form) |
| 145 | + v (ana-utils/resolve-sym f env)] |
| 146 | + (when (and (not (-> env :locals (get f))) (var? v)) |
| 147 | + (swap! !deps conj v))) |
| 148 | + (ana-jvm/macroexpand-1 form env)) |
| 149 | + analyzed (analyze-form {#'ana/macroexpand-1 mexpander} (rewrite-defcached form)) |
| 150 | + nodes (ana-ast/nodes analyzed) |
151 | 151 | {:keys [vars declared]} (get-vars+forward-declarations nodes) |
152 | 152 | vars- (set/difference vars declared) |
153 | 153 | var (when (and (= 1 (count vars)) |
|
168 | 168 | deref-deps |
169 | 169 | (class-deps analyzed) |
170 | 170 | (when (var? form) #{(symbol form)})) |
171 | | - ;; _ (def d deps) |
172 | 171 | hash-fn (-> form meta :nextjournal.clerk/hash-fn)] |
173 | 172 | (cond-> {#_#_:analyzed analyzed |
174 | 173 | :form form |
|
185 | 184 | (seq declared) (assoc :declared declared) |
186 | 185 | var (assoc :var var)))) |
187 | 186 |
|
188 | | -#_(analyze '(assoc {} (dissoc {} :a) 2)) |
| 187 | +#_(analyze '(assoc {} :a :b)) |
189 | 188 | #_(analyze '[[assoc]]) |
190 | | -#_(analyze '(let [inc assoc] |
191 | | - )) ;; let + assoc, no inc since it's a binding |
192 | | -#_(analyze '(fn [^String x] (.length x))) |
193 | | -#_(analyze '(.length "foo")) |
194 | | -#_(analyze '(quote [inc clojure.core/inc])) ;; no deps |
195 | | -#_(analyze 'String) |
196 | | -#_(analyze '(defprotocol Dude)) |
197 | | -#_(binding [*deps* (atom #{})] |
198 | | - (-> (analyze-form '(fn [^String x] (.length x))) |
199 | | - (resolve-syms-pass) |
200 | | - (macroexpand-pass))) |
| 189 | +#_(analyze nil) |
| 190 | +#_(analyze '(let [inc assoc])) |
| 191 | +#_(analyze '(Class/forName "dude")) |
| 192 | +#_(:deps (analyze '(fn [^String x] (.length x)))) |
| 193 | +#_(:deps (analyze '(ns foo (:import [java.lang String])))) |
201 | 194 |
|
202 | 195 | #_(:vars (analyze '(do (declare x y) (def x 0) (def z) (def w 0)))) ;=> x y z w |
203 | 196 | #_(:vars- (analyze '(do (def x 0) (declare x y) (def z) (def w 0)))) ;=> x z w |
|
559 | 552 | analyze-doc-deps |
560 | 553 | set-no-cache-on-redefs |
561 | 554 | make-deps-inherit-no-cache |
562 | | - (dissoc :analyzed-file-set :counter)))))) |
| 555 | + (dissoc :analyzed-file-set :counter)))))) |
563 | 556 |
|
564 | 557 | (comment |
565 | 558 | (reset! !file->analysis-cache {}) |
|
0 commit comments