           forms
           (recur (conj forms form)))))))
 
+(defn ^:dynamic run-passes
+  "Passes were copied from tools.analyzer.jvm and tweaked for the needs of
+   refactor-nrepl
+
+   Applies the following passes in the correct order to the AST:
+   * uniquify
+   * add-binding-atom
+   * cleanup
+   * source-info
+   * elide-meta
+   * warn-earmuff
+   * collect
+   * jvm.box
+   * jvm.constant-lifter
+   * jvm.annotate-branch
+   * jvm.annotate-loops
+   * jvm.annotate-class-id
+   * jvm.annotate-internal-name
+   * jvm.annotate-methods
+   * jvm.fix-case-test
+   * jvm.clear-locals
+   * jvm.classify-invoke
+   * jvm.infer-tag
+   * jvm.annotate-tag
+   * jvm.validate-loop-locals
+   * jvm.analyze-host-expr"
+  [ast]
+  (-> ast
+
+      uniquify-locals
+      add-binding-atom
+
+      (prewalk (fn [ast]
+                 (-> ast
+                     warn-earmuff
+                     source-info
+                     elide-meta
+                     annotate-methods
+                     fix-case-test
+                     annotate-class-id
+                     annotate-internal-name)))
+
+      ((fn analyze [ast]
+         (postwalk ast
+                   (fn [ast]
+                     (-> ast
+                         annotate-tag
+                         analyze-host-expr
+                         infer-tag
+                         classify-invoke
+                         constant-lift
+                         (validate-loop-locals analyze))))))
+
+      (prewalk (fn [ast]
+                 (-> ast
+                     box
+                     annotate-loops ;; needed for clear-locals to safely clear locals in a loop
+                     annotate-branch ;; needed for clear-locals
+                     ensure-tag)))
+
+      ((collect {:what       #{:constants
+                               :callsites}
+                 :where      #{:deftype :reify :fn}
+                 :top-level? false}))
+
+      ;; needs to be run in a separate pass to avoid collecting
+      ;; constants/callsites in :loop
+      (collect-closed-overs {:what  #{:closed-overs}
+                             :where #{:deftype :reify :fn :loop :try}
+                             :top-level? false})
+
+      ;; needs to be run after collect-closed-overs
+      clear-locals))
+
 (defn string-ast [string]
-     (binding [ana/macroexpand-1 ana.jvm/macroexpand-1
-               ana/create-var    ana.jvm/create-var
-               ana/parse         ana.jvm/parse
-               ana/var?          var?]
-       (try
-         (let [[_ aliases] (parse-ns string)]
-           (with-env (ana.jvm/global-env)
-             (-> string
-                 rts/indexing-push-back-reader
-                 read-all-forms
-                 (ana/analyze e)
-                 (prewalk ana.si/source-info)
-                 (assoc :alias-info aliases))))
-         (catch Exception e
-           (.printStackTrace e)
-           {}))))
+  (binding [ana/macroexpand-1 ana.jvm/macroexpand-1
+            ana/create-var    ana.jvm/create-var
+            ana/parse         ana.jvm/parse
+            ana/var?          var?]
+    (try
+      (let [[_ aliases] (parse-ns string)]
+        (with-env (ana.jvm/global-env)
+          (-> string
+              rts/indexing-push-back-reader
+              read-all-forms
+              (ana/analyze e)
+              run-passes
+              (assoc :alias-info aliases))))
+      (catch Exception e
+        (.printStackTrace e)
+        {}))))

(ns refactor-nrepl.analyzer
  (:refer-clojure :exclude [macroexpand-1 read read-string])
  (:require [clojure.tools.analyzer :as ana]
            [clojure.tools.analyzer.passes.source-info :as ana.si]
            [clojure.tools.analyzer.jvm :as ana.jvm]
            [clojure.tools.analyzer.ast :refer :all]
            [clojure.tools.analyzer.env :refer [with-env deref-env]]
            [clojure.tools.analyzer.utils :refer [source-info]]
            [clojure.tools.reader :as r]
            [clojure.tools.reader.reader-types :as rts]
            [clojure.tools.namespace.parse :refer [read-ns-decl deps-from-ns-decl]])
  (:import java.io.PushbackReader))

(def e (ana.jvm/empty-env))

                               (map first %))))]
    [(second ns-decl) aliases]))

(defn read-all-forms [reader]
  (let [eof (reify)]
    (loop [forms []]
