Skip to content

Commit

Permalink
re-import changed deftype, see #303
Browse files Browse the repository at this point in the history
Signed-off-by: Stuart Halloway <stu@thinkrelevance.com>
  • Loading branch information
stuarthalloway committed Apr 24, 2010
1 parent c487e48 commit c73a4ba
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 5 deletions.
3 changes: 0 additions & 3 deletions src/clj/clojure/core_deftype.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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))))


Expand Down
26 changes: 25 additions & 1 deletion src/jvm/clojure/lang/Namespace.java
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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);

}

Expand Down
39 changes: 38 additions & 1 deletion test/clojure/test_clojure/ns_libs.clj
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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 [])))))

0 comments on commit c73a4ba

Please sign in to comment.