diff --git a/src/clj/clojure/genclass.clj b/src/clj/clojure/genclass.clj index 710e58a1a3..afef85c8ef 100644 --- a/src/clj/clojure/genclass.clj +++ b/src/clj/clojure/genclass.clj @@ -101,15 +101,26 @@ 'char Character/TYPE 'chars (Class/forName "[C")}) -(defn- ^Class the-class [x] - (cond - (class? x) x - (contains? prim->class x) (prim->class x) - :else (let [strx (str x)] - (clojure.lang.RT/classForName - (if (some #{\. \[} strx) - strx - (str "java.lang." strx)))))) +(defn- the-array-class [sym] + (clojure.lang.RT/classForName + (let [cn (namespace sym)] + (clojure.lang.Compiler$HostExpr/buildArrayClassDescriptor + (if (or (clojure.lang.Compiler/primClass (symbol cn)) (some #{\.} cn)) + sym + (symbol (str "java.lang." cn) (name sym))))))) + +(defn- ^Class the-class [x] + (cond + (class? x) x + (symbol? x) (cond (contains? prim->class x) (prim->class x) + (clojure.lang.Compiler$HostExpr/looksLikeArrayClass x) + (the-array-class x) + :else (let [strx (str x)] + (clojure.lang.RT/classForName + (if (some #{\. \[} strx) + strx + (str "java.lang." strx))))) + :else (clojure.lang.RT/classForName x))) ;; someday this can be made codepoint aware (defn- valid-java-method-name diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 6324456fa1..80c25e79e6 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -1124,10 +1124,11 @@ static Class tagToClass(Object tag) { throw new IllegalArgumentException("Unable to resolve classname: " + tag); } - public static Class maybeArrayClass(Symbol sym) { - if(sym.ns == null || !Util.isPosDigit(sym.name)) - return null; + public static boolean looksLikeArrayClass(Symbol sym) { + return sym.ns != null && Util.isPosDigit(sym.name); + } + public static String buildArrayClassDescriptor(Symbol sym) { int dim = sym.name.charAt(0) - '0'; Symbol componentClassName = Symbol.intern(null, sym.ns); Class componentClass = primClass(componentClassName); @@ -1137,7 +1138,7 @@ public static Class maybeArrayClass(Symbol sym) { if(componentClass == null) throw Util.sneakyThrow(new ClassNotFoundException("Unable to resolve component classname: " - + componentClassName)); + + componentClassName)); StringBuilder arrayDescriptor = new StringBuilder(); @@ -1149,7 +1150,14 @@ public static Class maybeArrayClass(Symbol sym) { : "L" + componentClass.getName() + ";"; arrayDescriptor.append(ccDescr); - return maybeClass(arrayDescriptor.toString(), true); + return arrayDescriptor.toString(); + } + + public static Class maybeArrayClass(Symbol sym) { + if(!looksLikeArrayClass(sym)) + return null; + + return maybeClass(buildArrayClassDescriptor(sym), true); } } @@ -9184,7 +9192,7 @@ static Class retType(Class tc, Class ret){ return tc; } - static Class primClass(Symbol sym){ + public static Class primClass(Symbol sym){ if(sym == null) return null; Class c = null; diff --git a/test/clojure/test_clojure/genclass.clj b/test/clojure/test_clojure/genclass.clj index 18e808dc11..48ad866365 100644 --- a/test/clojure/test_clojure/genclass.clj +++ b/test/clojure/test_clojure/genclass.clj @@ -149,3 +149,13 @@ (visitSource [source debug] (.append sourceFile source)))] (.accept classReader sourceVisitor 0) (is (= "examples.clj" (str sourceFile))))) + +(deftest array-descriptors->class + (are [descr c] (= (#'clojure.core/the-class descr) c) + "[Ljava.util.UUID;" java.util.UUID/1 + 'String java.lang.String + 'String/1 java.lang.String/1 + 'java.util.UUID java.util.UUID + 'java.util.UUID/2 java.util.UUID/2 + 'int/1 int/1 + 'boolean/9 boolean/9))