diff options
author | Stuart Halloway <stu@thinkrelevance.com> | 2010-04-22 21:45:24 -0400 |
---|---|---|
committer | Stuart Halloway <stu@thinkrelevance.com> | 2010-04-24 14:34:34 -0400 |
commit | c73a4bad6297251ab5545affd6baf79d2390f8c6 (patch) | |
tree | cdd708a0a1bb4732236ed91fd52869bfb12fdc99 | |
parent | c487e48a65ee7cef66ef017c87a754fc88ba57e0 (diff) |
re-import changed deftype, see #303
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
-rw-r--r-- | src/clj/clojure/core_deftype.clj | 3 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Namespace.java | 26 | ||||
-rw-r--r-- | test/clojure/test_clojure/ns_libs.clj | 39 |
3 files changed, 63 insertions, 5 deletions
diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj index 0a90356e..f18b690f 100644 --- a/src/clj/clojure/core_deftype.clj +++ b/src/clj/clojure/core_deftype.clj @@ -18,7 +18,6 @@ (vector name (vec (map tag args)) (tag name))) cname (with-meta (symbol (str *ns* "." name)) (meta name))] `(do (gen-interface :name ~cname :methods ~(vec (map psig sigs))) - (ns-unmap (find-ns '~(ns-name *ns*)) '~name) (import ~cname)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;; reify/deftype ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -289,7 +288,6 @@ ~(emit-defrecord name gname (vec hinted-fields) (vec interfaces) methods) (defmethod print-method ~classname [o# w#] ((var print-defrecord) o# w#)) - (ns-unmap (find-ns '~(ns-name *ns*)) '~name) (import ~classname) #_(defn ~name ([~@fields] (new ~classname ~@fields nil nil)) @@ -379,7 +377,6 @@ fields (vec (map #(with-meta % nil) fields))] `(do ~(emit-deftype* name gname (vec hinted-fields) (vec interfaces) methods) - (ns-unmap (find-ns '~(ns-name *ns*)) '~name) (import ~classname)))) diff --git a/src/jvm/clojure/lang/Namespace.java b/src/jvm/clojure/lang/Namespace.java index 09d87037..85505d91 100644 --- a/src/jvm/clojure/lang/Namespace.java +++ b/src/jvm/clojure/lang/Namespace.java @@ -86,6 +86,30 @@ Object reference(Symbol sym, Object val){ throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name); } +public static boolean areDifferentInstancesOfSameClassName(Class cls1, Class cls2) { + return (cls1 != cls2) && (cls1.getName().equals(cls2.getName())); +} + +Class referenceClass(Symbol sym, Class val){ + if(sym.ns != null) + { + throw new IllegalArgumentException("Can't intern namespace-qualified symbol"); + } + IPersistentMap map = getMappings(); + Class c = (Class) map.valAt(sym); + while((c == null) || (areDifferentInstancesOfSameClassName(c, val))) + { + IPersistentMap newMap = map.assoc(sym, val); + mappings.compareAndSet(map, newMap); + map = getMappings(); + c = (Class) map.valAt(sym); + } + if(c == val) + return c; + + throw new IllegalStateException(sym + " already refers to: " + c + " in namespace: " + name); +} + public void unmap(Symbol sym) throws Exception{ if(sym.ns != null) { @@ -101,7 +125,7 @@ public void unmap(Symbol sym) throws Exception{ } public Class importClass(Symbol sym, Class c){ - return (Class) reference(sym, c); + return referenceClass(sym, c); } diff --git a/test/clojure/test_clojure/ns_libs.clj b/test/clojure/test_clojure/ns_libs.clj index c5b9666a..10844ded 100644 --- a/test/clojure/test_clojure/ns_libs.clj +++ b/test/clojure/test_clojure/ns_libs.clj @@ -6,7 +6,7 @@ ; the terms of this license. ; You must not remove this notice, or any other, from this software. -; Author: Frantisek Sodomka +; Authors: Frantisek Sodomka, Stuart Halloway (ns clojure.test-clojure.ns-libs (:use clojure.test)) @@ -34,3 +34,40 @@ (is (thrown? Exception (use :foo))) (is (thrown? Exception (use)))) +(deftest reimporting-deftypes + (let [inst1 (binding [*ns* *ns*] + (eval '(do (ns exporter) + (defrecord ReimportMe [a]) + (ns importer) + (import exporter.ReimportMe) + (ReimportMe. 1)))) + inst2 (binding [*ns* *ns*] + (eval '(do (ns exporter) + (defrecord ReimportMe [a b]) + (ns importer) + (import exporter.ReimportMe) + (ReimportMe. 1 2))))] + (testing "you can reimport a changed class and see the changes" + (is (= [:a] (keys inst1))) + (is (= [:a :b] (keys inst2)))) + (testing "you cannot import same local name from a different namespace" + (is (thrown? clojure.lang.Compiler$CompilerException + #"ReimportMe already refers to: class exporter.ReimportMe in namespace: importer" + (binding [*ns* *ns*] + (eval '(do (ns exporter-2) + (defrecord ReimportMe [a b]) + (ns importer) + (import exporter-2.ReimportMe) + (ReimportMe. 1 2))))))))) + +(deftest naming-types + (testing "you cannot use a name already referred from another namespace" + (is (thrown? IllegalStateException + #"String already refers to: class java.lang.String" + (definterface String))) + (is (thrown? IllegalStateException + #"StringBuffer already refers to: class java.lang.StringBuffer" + (deftype StringBuffer []))) + (is (thrown? IllegalStateException + #"Integer already refers to: class java.lang.Integer" + (defrecord Integer []))))) |