clojure.tools.analyzer.query-test自2015年11月3日以来一直失败,它从未在CI中运行。
git bisect确定提交a61b1699c15911d17f834745521a9837a8916eec引入了错误
我检查了CI和最新的构建中没有执行query-test,这可能是由于未找到datomic.Datom。
请参阅
https://build.clojure.org/job/tools.analyzer/728/console
预期
(let [ast (ast/prewalk (ast (defn x [] "misplaced docstring" 1))
index-vector-nodes)]
(q '[:find ?docstring
:where
[?def :op :def]
[?def :init ?fn]
[?fn :methods ?method]
[?method :body ?body]
[?body :statements ?statement]
[?statement :val ?docstring]
[?statement :type :string]
[?statement :idx 0]]
[ast]))
#{["misplaced docstring"]}
实际
(let [ast (ast/prewalk (ast (defn x [] "misplaced docstring" 1))
index-vector-nodes)]
(q '[:find ?docstring
:where
[?def :op :def]
[?def :init ?fn]
[?fn :methods ?method]
[?method :body ?body]
[?body :statements ?statement]
[?statement :val ?docstring]
[?statement :type :string]
[?statement :idx 0]]
[ast]))
#{}
完整repl重现
(require
'[clojure.tools.analyzer :as ana]
'[clojure.tools.analyzer.ast :as ast]
'[clojure.tools.analyzer.jvm :as ana.jvm]
'[clojure.tools.analyzer.env :refer [with-env]]
'[clojure.tools.analyzer.ast :refer :all]
'[clojure.test :refer [deftest is]]
'[clojure.tools.analyzer.ast.query :refer [q]]
'[clojure.tools.analyzer.ast :as ast]
'[clojure.tools.analyzer.utils :refer [compile-if]]
'[clojure.tools.analyzer.passes.index-vector-nodes :refer [index-vector-nodes]]
'[clojure.tools.analyzer.utils :refer [resolve-sym]])
(require '[clojure.tools.analyzer.passes.elide-meta :refer [elides elide-meta]])
(ns-unmap 'user 'macroexpand-1)
(defn desugar-host-expr [[op & expr :as form]]
(if (symbol? op)
(let [opname (name op)]
(cond
(= (first opname) \.) ; (.foo bar ..)
(let [[target & args] expr
args (list* (symbol (subs opname 1)) args)]
(with-meta (list '. target (if (= 1 (count args)) ;; we don't know if (.foo bar) ia
(first args) args)) ;; a method call or a field access
(meta form)))
(= (last opname) \.) ;; (class. ..)
使用元信息列表(new (symbol (subs opname 0 (dec (count opname)))) expr)
(形式元信息)
:else form)
form)
(定义函数 macroexpand-1 [form env])
(如果 form 是一个序列)
(let [op 为序列的第一个元素)
(如果 op 是特殊情况)
form
(let [v 对 op 进行解析在 env 中)
(如果 env 中没有 locals 且 v 是一个宏)
(:macro (meta v))
(应用 v form env 其余形式); (m &form &env & args)
(简化主表达式表达式))
form)
(定义宏 foo [] 1)
(定义 e {:context :ctx/expr
:locals {}
:ns 'user)
(定义 e1 (atom {:namespaces {'user {:mappings (into (ns-map 'clojure.core)
{'foo #'foo})
:aliases {}
:ns 'user}
'clojure.core {:mappings (ns-map 'clojure.core)
:aliases {}
:ns 'clojure.core}}})
(定义宏 ast [form])
`(binding [ana/macroexpand-1 macroexpand-1
ana/create-var ~(fn [sym env]
`(doto (borrow (:ns env) sym)
`(reset-meta! (meta sym))))
ana/parse ana/-parse
ana/var? ~var?
elides {:all #{:line :column :file :source-span}}]
`(with-env e1
`(postwalk (ana/analyze '~form e) elide-meta))
(定义宏 mexpand [form])
`(with-env e1
(macroexpand-1 '~form e))
(let [ast (ast/prewalk (ast (defn x [] "misplaced docstring" 1))
index-vector-nodes)]
(q '[:find ?docstring
:where
[?def :op :def]
[?def :init ?fn]
[?fn :methods ?method]
[?method :body ?body]
[?body :statements ?statement]
[?statement :val ?docstring]
[?statement :type :string]
[?statement :idx 0]]
[ast]))
数据逻辑查询似乎仍然有效。
(let [ast (ast/prewalk (ast (defn x [] "misplaced docstring" 1))
index-vector-nodes)]
(求 [:find ?fn
:where
[?def :op :def]
[:def :init ?fn]])
[ast]))
#{[:op :with-meta,