Skip to content

Commit 485b142

Browse files
Move JDK version-dependent functions to orchard.java.compatibility
1 parent a240648 commit 485b142

File tree

6 files changed

+48
-39
lines changed

6 files changed

+48
-39
lines changed

src/orchard/inspect.clj

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
[clojure.core.protocols :refer [datafy nav]]
1313
[clojure.string :as str]
1414
[orchard.inspect.analytics :as analytics]
15+
[orchard.java.compatibility :as compat]
1516
[orchard.pp :as pp]
1617
[orchard.print :as print])
1718
(:import
@@ -327,8 +328,8 @@
327328
;; Rendering
328329

329330
(defn render
330-
([{:keys [rendered] :as inspector} value]
331-
(assoc inspector :rendered (conj! rendered value)))
331+
([inspector value]
332+
(update inspector :rendered conj! value))
332333
([inspector value & values]
333334
(reduce render (render inspector value) values)))
334335

@@ -826,16 +827,6 @@
826827
(render-indent-str-lines obj)
827828
(unindent)))
828829

829-
(defn- field-val [^Field f, obj]
830-
(try
831-
(.get f obj)
832-
(catch Exception _
833-
(try
834-
(.setAccessible f true)
835-
(.get f obj)
836-
(catch Exception _
837-
::access-denied)))))
838-
839830
(defn- shorten-member-string [member-string, ^Class class]
840831
;; Ugly as hell, but easier than reimplementing all custom printing that
841832
;; java.lang.reflect does.
@@ -855,8 +846,10 @@
855846
res))
856847
all-fields (mapcat #(.getDeclaredFields ^Class %) class-chain)
857848
field-values (mapv (fn [^Field f]
858-
{:name (symbol (.getName f)), :value (field-val f obj)
859-
:static (Modifier/isStatic (.getModifiers f))})
849+
(let [static? (Modifier/isStatic (.getModifiers f))]
850+
{:name (symbol (.getName f))
851+
:value (compat/get-field-value f (when-not static? obj))
852+
:static static?}))
860853
all-fields)
861854
{static-accessible [true true]
862855
non-static-accessible [false true]
@@ -865,7 +858,7 @@
865858
(group-by (fn [{:keys [static value]}]
866859
;; Be careful to use identical? instead of = because an
867860
;; object might not implement equiv().
868-
[static (not (identical? ::access-denied value))])
861+
[static (not (identical? ::compat/access-denied value))])
869862
field-values)
870863
;; This is fine like this for now. If this condp ever grows bigger,
871864
;; consider refactoring it into something polymorphic.
@@ -891,7 +884,7 @@
891884
(->> field-values
892885
(map (fn [{:keys [name value]}]
893886
[name
894-
(if (identical? value ::access-denied)
887+
(if (identical? value ::compat/access-denied)
895888
;; This is a special value that can be
896889
;; detected client-side:
897890
(symbol "<non-inspectable value>")

src/orchard/java.clj

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
[clojure.java.javadoc :as javadoc]
66
[clojure.reflect :as reflect]
77
[clojure.string :as str]
8+
[orchard.java.compatibility :as compat]
89
[orchard.java.resource :as resource]
910
[orchard.java.source-files :as src-files]
1011
[orchard.misc :as misc]
@@ -61,21 +62,14 @@
6162
(when parser-next-source-info
6263
(parser-next-source-info klass source-url))))
6364

64-
;; As of Java 11, Javadoc URLs begin with the module name.
65-
(defn module-name
66-
"On JDK11+, return module name from the class if present; otherwise return nil"
67-
[class-or-sym]
68-
(when (>= misc/java-api-version 11)
69-
((requiring-resolve 'orchard.java.modules/module-name) class-or-sym)))
70-
7165
(defn javadoc-url
7266
"Return the relative `.html` javadoc path and member fragment."
7367
([class]
7468
(let [url (str (-> (str/replace (str class) "." "/")
7569
(str/replace "$" "."))
7670
".html")
7771
;; As of Java 11, Javadoc URLs begin with the module name.
78-
module (module-name class)]
72+
module (compat/module-name class)]
7973
(cond->> url
8074
module (format "%s/%s" module))))
8175
([class member argtypes]

src/orchard/java/compatibility.clj

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
(ns orchard.java.compatibility
2+
"Small utilities that unify code to work between different Java versions."
3+
(:require [orchard.misc :as misc])
4+
(:import java.lang.reflect.Field))
5+
6+
(defmacro ^:private module-name-macro [class-or-sym]
7+
;; On JDK8, always return nil.
8+
(when (>= misc/java-api-version 11)
9+
(let [klass (with-meta (gensym "klass") {:tag `Class})]
10+
`(let [~klass (cond-> ~class-or-sym
11+
(symbol? ~class-or-sym) resolve)]
12+
(some-> ~klass .getModule .getName)))))
13+
14+
(defn module-name
15+
"Return the module name for the class."
16+
[class-or-sym]
17+
(module-name-macro class-or-sym))
18+
19+
(defmacro get-field-value-macro [field obj]
20+
(if (>= misc/java-api-version 11)
21+
`(try (if (or (.canAccess ~field ~obj)
22+
(.trySetAccessible ~field))
23+
(.get ~field ~obj)
24+
::access-denied)
25+
(catch Exception ~'_ ::access-denied))
26+
;; Fallback to deprecated try-catch based flow on JDK8.
27+
`(try (when-not (.isAccessible ~field)
28+
(.setAccessible ~field true))
29+
(.get ~field ~obj)
30+
(catch Exception ~'_ ::access-denied))))
31+
32+
(defn get-field-value [^Field field, obj]
33+
(get-field-value-macro field obj))

src/orchard/java/modules.clj

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/orchard/java/parser_next.clj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
(:require
2323
[clojure.java.io :as io]
2424
[clojure.string :as str]
25-
[orchard.java.modules :as modules]
25+
[orchard.java.compatibility :as compat]
2626
[orchard.java.source-files :as src-files]
2727
[orchard.misc :as misc])
2828
(:import
@@ -432,7 +432,7 @@
432432
{:pre [(class? klass)]}
433433
(misc/with-lock lock ;; the jdk.javadoc.doclet classes aren't meant for concurrent modification/access.
434434
(let [class-sym (symbol (.getName klass))
435-
^DocletEnvironment root (parse-java source-url (modules/module-name klass))]
435+
^DocletEnvironment root (parse-java source-url (compat/module-name klass))]
436436
(when root
437437
(try
438438
(some #(when (#{ElementKind/CLASS

src/orchard/java/source_files.clj

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
:added "0.29"}
66
(:require [clojure.java.io :as io]
77
[clojure.string :as str]
8-
[orchard.misc :as misc])
8+
[orchard.java.compatibility :as compat])
99
(:import (java.io File IOException)
1010
(java.net URL)))
1111

@@ -41,8 +41,7 @@
4141
(defn- class->classfile-path
4242
"Infer a relative path to the classfile of the given `klass`."
4343
[^Class klass]
44-
(let [module (when (>= misc/java-api-version 11)
45-
((requiring-resolve 'orchard.java.modules/module-name) klass))
44+
(let [module (compat/module-name klass)
4645
classfile-name (-> (.getName klass)
4746
(str/replace #"\$.*" "") ;; Drop internal class.
4847
(str/replace "." "/")

0 commit comments

Comments
 (0)