diff --git a/src/slam/hound/asplode.clj b/src/slam/hound/asplode.clj index a5a7f43..b2be166 100644 --- a/src/slam/hound/asplode.clj +++ b/src/slam/hound/asplode.clj @@ -216,6 +216,20 @@ stripped-ns (-> (apply dissoc ns-map ns-clauses) (assoc :old old-ns) (merge (preserve-ns-references old-ns))) - body (take-while #(not= ::done %) - (repeatedly #(read rdr false ::done)))] - [stripped-ns (doall body)]))) + ;; All unqualified, unquoted symbols are qualified to *ns* by the + ;; reader during syntax-quote expansion, so we must be sure that + ;; *ns* is set to the file's namespace in order for the regrow step + ;; to work properly. + ;; + ;; Unfortunately, this means we are introducing the potentially + ;; surprising side effect of creating a namespace on read. This + ;; cannot be helped, as there is no way of creating a Namespace + ;; object that is not added to the global map of namespaces. + ;; + ;; In practice, however, this is unlikely to be a problem; + ;; slam.hound/regrow loads all namespaces on the classpath anyway. + body (binding [*ns* (create-ns (:name ns-map))] + (doall + (take-while #(not= ::done %) + (repeatedly #(read rdr false ::done)))))] + [stripped-ns body]))) diff --git a/test/slam/hound/asplode_test.clj b/test/slam/hound/asplode_test.clj index 8b6a240..3e3d660 100644 --- a/test/slam/hound/asplode_test.clj +++ b/test/slam/hound/asplode_test.clj @@ -196,4 +196,9 @@ :exclude {clojure.core #{test compile}} :meta {:doc "Testing some things going on here."} :name slamhound.sample} - ((do something))]))) + ((do something))])) + (testing "output is constant regardless of *ns*" + (let [buf "(ns slamhound.sample) (eval `foo)"] + (is (= (asplode (StringReader. buf)) + (binding [*ns* (find-ns 'user)] + (asplode (StringReader. buf))))))))