   {:pre [(number? line)
          (number? column)
          (not-empty file)]}
-  (let [ns-string (slurp file)
-        ast (ns-ast ns-string)]
-    (when-let [form-index (top-level-form-index line column ast)]
+  (let [file-content (slurp file)
+        ast (ns-ast file-content)]
+    (when-let [form-index (util/top-level-form-index line column ast)]
       (let [top-level-form-ast (nth ast form-index)
             local-var-name (->> top-level-form-ast
                                 nodes
-                                (filter #(and (#{:local :binding} (:op %)) (= var-name (-> % :form str)) (:local %)))
-                                (filter (partial node-at-loc? line column))
+                                (filter #(and (#{:local :binding} (:op %))
+                                              (= var-name (-> % :form str))
+                                              (:local %)))
+                                (filter (partial util/node-at-loc? line column))
                                 first
                                 :name)]
-        (->> (find-nodes [top-level-form-ast] #(and (#{:local :binding} (:op %)) (= local-var-name (-> % :name)) (:local %)))
-             (map #(conj (vec (take 4 %)) var-name (.getCanonicalPath (java.io.File. file)) (match ns-string (first %) (second %)))))))))
+        (map #(conj (vec (take 4 %))
+                    var-name
+                    (.getCanonicalPath (java.io.File. file))
+                    (match file-content
+                           (first %)
+                           (second %)))
+             (find-nodes [top-level-form-ast]
+                         #(and (#{:local :binding} (:op %))
+                               (= local-var-name (-> % :name))
+                               (:local %))))))))
 
 (defn find-symbol [{:keys [file ns name dir line column]}]
-  (throw-unless-clj-file file)
-  (or (when (and file (not-empty file)) (not-empty (find-local-symbol file name line column)))
+  (util/throw-unless-clj-file file)
+  (or (when (and file (not-empty file))
+        (not-empty (find-local-symbol file name line column)))
       (find-global-symbol file ns name dir)))
 
 (defn create-result-alist

(ns refactor-nrepl.find-symbol
  (:require [clojure.string :as str]
            [clojure.tools.analyzer.ast :refer :all]
            [refactor-nrepl
             [analyzer :refer [ns-ast]]
             [util :refer :all]]))

(defn- node->var [alias-info node]
  (let [class (or (:class node) (-> node
                                    :var
                                    str
                                    (str/replace "#'" "")
                                    (str/replace "clojure.core/" "")))
        full-class (get alias-info class class)]
    (str/join "/" (remove nil? [full-class (:field node)]))))

(defn- fn-invoked [alias-info node]
  (node->var alias-info (:fn node)))

(defn- fns-invoked? [fns alias-info node]
  (and (= :invoke (:op node))
       (fns (fn-invoked alias-info node))))

(defn- contains-var? [var-name alias-info node]
  (var-name (node->var alias-info node)))

(defn- find-nodes [ast pred]
  (->> ast
       (map nodes)
       flatten
       (filter pred)
       (map (juxt (comp :line :env)
                  (comp :end-line :env)

  "Finds fn invokes in the AST.
  Returns a list of line, end-line, column, end-column and fn name tuples"
  [ast fn-names]
  (find-nodes ast
              #(fns-invoked? (into #{} (str/split fn-names #","))
                             (util/alias-info ast)
                             %)))

(def ^:private symbol-regex #"[\w\.:\*\+\-_!\?]+")

(defn- contains-const?
  [var-name alias-info node]
  (let [[ns name] (str/split var-name #"/")
        const-node? (= :const (:op node))
        node-val-words (when const-node?
                         (->> (str (:val node))
                              (re-seq symbol-regex)
                              set))]
    (and const-node?
         (node-val-words ns)
         (or (not name) (node-val-words name))
         var-name)))

(defn- contains-var-or-const? [var-name alias-info node]
  (or (contains-var? #{var-name} alias-info node)
      (contains-const? var-name alias-info node)))

(defn- find-symbol-in-ast [name ast]
  (when ast
    (find-nodes ast
                (partial contains-var-or-const?
                         name
                         (util/alias-info ast)))))

(defn- match [file-content line end-line]
  (let [line-index (dec line)
