Skip to content

Commit 9ac3758

Browse files
committed
Reflectively look up inherited methods when not found in target class
1 parent 239db17 commit 9ac3758

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

src/clojure/java/doc/impl.clj

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,26 @@
175175
(defn- filter-methods [all-methods method-name param-tags]
176176
(filterv #(method-matches? (:signature %) method-name param-tags) all-methods))
177177

178+
(defn- reflection-type-name [^Class c]
179+
(if (.isArray c)
180+
(str (reflection-type-name (.getComponentType c)) "[]")
181+
(.getSimpleName c)))
182+
183+
(defn- reflection-params-match? [^java.lang.reflect.Method method param-tags]
184+
(let [param-type-names (mapv reflection-type-name (.getParameterTypes method))]
185+
(params-match? param-type-names param-tags)))
186+
187+
(defn- find-declaring-class [^String class-name method-name param-tags]
188+
(let [klass (Class/forName class-name)
189+
name-matches? (fn [^java.lang.reflect.Method m] (= method-name (.getName m)))
190+
inherited? (fn [^java.lang.reflect.Method m] (not= class-name (.getName (.getDeclaringClass m))))
191+
params-compatible? (fn [^java.lang.reflect.Method m] (or (nil? param-tags) (reflection-params-match? m param-tags)))
192+
matching (->> (.getMethods klass)
193+
(filter (fn [^java.lang.reflect.Method m]
194+
(and (name-matches? m) (inherited? m) (params-compatible? m)))))]
195+
(when-let [^java.lang.reflect.Method method (first matching)]
196+
(.getName (.getDeclaringClass method)))))
197+
178198
(defn- compress-array-syntax
179199
"java to clojure param-tag syntax: String[][] -> String/2"
180200
[java-type]
@@ -249,9 +269,14 @@
249269
:class-description-md (when class-html (html-to-md class-html))
250270
:methods all-methods}]
251271
(if method-part
252-
(let [filtered (filter-methods all-methods method-part param-tags)]
272+
(let [filtered (filter-methods all-methods method-part param-tags)
273+
declaring-class (when (empty? filtered)
274+
(find-declaring-class class-name method-part param-tags))]
253275
(assoc result :selected-method
254-
(mapv #(get-method-detail doc %) filtered)))
276+
(cond
277+
(seq filtered) (mapv #(get-method-detail doc %) filtered)
278+
declaring-class (:selected-method (parse-javadoc (str declaring-class "/." method-part) param-tags))
279+
:else [])))
255280
result)))
256281

257282
(defn print-javadoc [{:keys [classname class-description-md selected-method]}]

test/clojure/java/doc/impl_test.clj

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,37 @@
413413
(is (nil? (#'sut/find-method-section doc "valueOf" ["String"])))
414414
(is (nil? (#'sut/find-method-section doc "nonExistent" ["int"])))))
415415

416+
(deftest reflection-type-name-test
417+
418+
(testing "primitive types"
419+
(is (= "int" (#'sut/reflection-type-name Integer/TYPE)))
420+
(is (= "boolean" (#'sut/reflection-type-name Boolean/TYPE)))
421+
(is (= "char" (#'sut/reflection-type-name Character/TYPE)))
422+
(is (= "long" (#'sut/reflection-type-name Long/TYPE))))
423+
424+
(testing "simple class"
425+
(is (= "String" (#'sut/reflection-type-name String)))
426+
(is (= "Object" (#'sut/reflection-type-name Object))))
427+
428+
(testing "single dimension array"
429+
(is (= "int[]" (#'sut/reflection-type-name (Class/forName "[I"))))
430+
(is (= "String[]" (#'sut/reflection-type-name (Class/forName "[Ljava.lang.String;")))))
431+
432+
(testing "multi dimensional array"
433+
(is (= "int[][]" (#'sut/reflection-type-name (Class/forName "[[I"))))
434+
(is (= "String[][]" (#'sut/reflection-type-name (Class/forName "[[Ljava.lang.String;"))))))
435+
436+
(deftest find-declaring-class-test
437+
438+
(testing "inherited method found"
439+
(is (= "java.util.zip.ZipEntry" (#'sut/find-declaring-class "java.util.jar.JarEntry" "getName" nil))))
440+
441+
(testing "directly declared method returns nil"
442+
(is (nil? (#'sut/find-declaring-class "java.lang.String" "length" nil))))
443+
444+
(testing "nonexistent method returns nil"
445+
(is (nil? (#'sut/find-declaring-class "java.lang.String" "totallyFakeMethod" nil)))))
446+
416447
(testing "distinguishes between overloads with different param counts"
417448
(let [html "<html><body>
418449
<section id='run(java.util.Map)'>

0 commit comments

Comments
 (0)