Welcome! Please see the About page for a little more info on how this works.

0 votes
in tools.analyzer by
clojure.tools.analyzer.query-test has been failing since 2015-11-03, it never runs in CI.

git bisect determined commit a61b1699c15911d17f834745521a9837a8916eec introduced the failure

I checked CI and the latest build doesn't execute query-test, presumably because datomic.Datom isn't found.
See https://build.clojure.org/job/tools.analyzer/728/console

Expected:

(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"]}


Actual:


(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]))
#{}


full repl repro:

(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. ..)
        (with-meta (list* 'new (symbol (subs opname 0 (dec (count opname)))) expr)
                   (meta form))

        :else form))
    form))

(defn macroexpand-1 [form env]
  (if (seq? form)
    (let [op (first form)]
      (if (ana/specials op)
        form
        (let [v (resolve-sym op env)]
          (if (and (not (-> env :locals (get op))) ;; locals cannot be macros
                   (:macro (meta v)))
            (apply v form env (rest form)) ; (m &form &env & args)
            (desugar-host-expr form)))))
    form))

(defmacro foo [] 1)

(def e {:context    :ctx/expr
        :locals     {}
        :ns         'user})

(def 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}}}))
(defmacro ast [form]
  `(binding [ana/macroexpand-1 macroexpand-1
             ana/create-var    ~(fn [sym env]
                                  (doto (intern (: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))))

(defmacro 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]))


It appears the datalog query still works.


(let [ast (ast/prewalk (ast (defn x [] "misplaced docstring" 1))
                       index-vector-nodes)]
  (q '[:find ?fn
       :where
       [?def :op :def]
       [?def :init ?fn]]
     [ast]))

#{[{:op :with-meta, :env {:context :ctx/expr, :locals {}, :ns user}, :form (fn* ([] "misplaced docstring" 1)), :meta {:op :map, :env {:context :ctx/expr, :locals {}, :ns user}, :keys [{:op :const, :env {:context :ctx/expr, :locals {}, :ns user}, :type :keyword, :literal? true, :val :rettag, :form :rettag, :idx 0}], :vals [{:op :const, :env {:context :ctx/expr, :locals {}, :ns user}, :type :nil, :literal? true, :val nil, :form nil, :idx 0}], :form {:rettag nil}, :children [:keys :vals]}, :expr {:op :fn, :env {:context :ctx/expr, :locals {}, :ns user}, :form (fn* ([] "misplaced docstring" 1)), :variadic? false, :max-fixed-arity 0, :methods [{:children [:params :body], :loop-id loop_4101, :params [], :fixed-arity 0, :op :fn-method, :env {:context :ctx/expr, :locals {}, :ns user, :once false}, :variadic? false, :form ([] "misplaced docstring" 1), :idx 0, :body {:op :do, :env {:context :ctx/return, :locals {}, :ns user, :once false, :loop-id loop_4101, :loop-locals 0}, :form (do "misplaced docstring" 1), :statements [{:op :const, :env {:context :ctx/statement, :locals {}, :ns user, :once false, :loop-id loop_4101, :loop-locals 0}, :type :string, :literal? true, :val "misplaced docstring", :form "misplaced docstring", :idx 0}], :ret {:op :const, :env {:context :ctx/return, :locals {}, :ns user, :once false, :loop-id loop_4101, :loop-locals 0}, :type :number, :literal? true, :val 1, :form 1}, :children [:statements :ret], :body? true}}], :once false, :children [:methods]}, :children [:meta :expr], :raw-forms ((clojure.core/fn ([] "misplaced docstring" 1)))}]}

2 Answers

0 votes
by

Comment made by: jlane

Cleaned up the ticket.

0 votes
by
Reference: https://clojure.atlassian.net/browse/TANAL-129 (reported by jlane)
...