|
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] |
13 | 9 | [multiformats.base.b58 :as b58]
|
14 | 10 | [multiformats.hash :as hash]
|
15 |
| - [nextjournal.clerk.parser :as parser] |
| 11 | + [nextjournal.clerk.analyzer.impl :as ana :refer [analyze*]] |
16 | 12 | [nextjournal.clerk.classpath :as cp]
|
17 | 13 | [nextjournal.clerk.config :as config]
|
| 14 | + [nextjournal.clerk.parser :as parser] |
18 | 15 | [nextjournal.clerk.walk :as walk]
|
19 | 16 | [taoensso.nippy :as nippy]
|
20 | 17 | [weavejester.dependency :as dep]))
|
|
63 | 60 | (comp (keep :class)
|
64 | 61 | (filter class?)
|
65 | 62 | (map ensure-symbol))
|
66 |
| - (ana-ast/nodes analyzed)) |
| 63 | + (ana/nodes analyzed)) |
67 | 64 | (into #{}
|
68 | 65 | (comp (filter (comp #{:const} :op))
|
69 | 66 | (filter (comp #{:class} :type))
|
70 | 67 | (keep :form)
|
71 | 68 | (map ensure-symbol))
|
72 |
| - (ana-ast/nodes analyzed)))) |
| 69 | + (ana/nodes analyzed)))) |
73 | 70 |
|
74 | 71 | #_(map type (:deps (analyze '(+ 1 2))))
|
75 | 72 |
|
|
83 | 80 |
|
84 | 81 | #_(rewrite-defcached '(nextjournal.clerk/defcached foo :bar))
|
85 | 82 |
|
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 |
| - |
97 | 83 | (defn form->ex-data
|
98 | 84 | "Returns ex-data map with the form and its location info from metadata."
|
99 | 85 | [form]
|
100 | 86 | (merge (select-keys (meta form) [:line :col :clojure.core/eval-file])
|
101 | 87 | {:form form}))
|
102 | 88 |
|
103 |
| -(defn- analyze-form |
104 |
| - ([form] (analyze-form {} form)) |
| 89 | +(defn- analyze-form* |
| 90 | + ([form] (analyze-form* {} form)) |
105 | 91 | ([bindings form]
|
106 | 92 | (binding [config/*in-clerk* true]
|
107 | 93 | (try
|
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}))) |
| 94 | + (analyze* (assoc (ana/to-env bindings) |
| 95 | + :ns (ns-name *ns*)) form) |
115 | 96 | (catch java.lang.AssertionError e
|
116 | 97 | (throw (ex-info "Failed to analyze form"
|
117 | 98 | (form->ex-data form)
|
118 | 99 | e)))))))
|
119 | 100 |
|
| 101 | +(defn analyze-form [form] |
| 102 | + (with-bindings {clojure.lang.Compiler/LOADER (clojure.lang.RT/makeClassLoader)} |
| 103 | + (binding [ana/*deps* (or ana/*deps* (atom #{}))] |
| 104 | + (-> (analyze-form* (rewrite-defcached form)) |
| 105 | + (ana/resolve-syms-pass) |
| 106 | + (ana/macroexpand-pass))))) |
| 107 | + |
120 | 108 | (defn ^:private var->protocol [v]
|
121 | 109 | (or (:protocol (meta v))
|
122 | 110 | v))
|
|
138 | 126 |
|
139 | 127 | (defn analyze [form]
|
140 | 128 | (let [!deps (atom #{})
|
141 |
| - mexpander (fn [form env] |
142 |
| - (let [f (if (seq? form) (first form) form) |
143 |
| - v (ana-utils/resolve-sym f env)] |
144 |
| - (when (and (not (-> env :locals (get f))) (var? v)) |
145 |
| - (swap! !deps conj v))) |
146 |
| - (ana-jvm/macroexpand-1 form env)) |
147 |
| - analyzed (analyze-form {#'ana/macroexpand-1 mexpander} (rewrite-defcached form)) |
148 |
| - nodes (ana-ast/nodes analyzed) |
| 129 | + analyzed (binding [ana/*deps* !deps] |
| 130 | + (analyze-form form)) |
| 131 | + _ (ana/prewalk (ana/only-nodes |
| 132 | + #{:var :binding :symbol} |
| 133 | + (fn [var-node] |
| 134 | + (case (:op var-node) |
| 135 | + :var (let [var (:var var-node)] |
| 136 | + (swap! !deps conj var)) |
| 137 | + :binding (when-let [t (:tag (meta (:form var-node)))] |
| 138 | + (when-let [clazz (try (resolve t) |
| 139 | + (catch Exception _ nil))] |
| 140 | + (when (class? clazz) |
| 141 | + (swap! !deps conj (.getName ^Class clazz))))) |
| 142 | + :symbol (when-not (:local? var-node) |
| 143 | + (let [form (:form var-node)] |
| 144 | + (if (qualified-symbol? form) |
| 145 | + (let [clazz-sym (symbol (namespace form))] |
| 146 | + (when-let [clazz (try (resolve clazz-sym) |
| 147 | + (catch Exception _ nil))] |
| 148 | + (when (class? clazz) |
| 149 | + (swap! !deps conj (.getName ^Class clazz))))) |
| 150 | + (when-let [clazz (try (resolve form) |
| 151 | + (catch Exception _ nil))] |
| 152 | + (when (class? clazz) |
| 153 | + (swap! !deps conj (.getName ^Class clazz)))))))) |
| 154 | + var-node)) analyzed) |
| 155 | + nodes (ana/nodes analyzed) |
149 | 156 | {:keys [vars declared]} (get-vars+forward-declarations nodes)
|
150 | 157 | vars- (set/difference vars declared)
|
151 | 158 | var (when (and (= 1 (count vars))
|
|
0 commit comments