|
608 | 608 | (render-indent-str-lines obj)
|
609 | 609 | (unindent)))
|
610 | 610 |
|
| 611 | +(defn- field-val [^Field f, obj] |
| 612 | + (try |
| 613 | + (.get f obj) |
| 614 | + (catch Exception _ |
| 615 | + ::access-denied))) |
| 616 | + |
611 | 617 | (defmethod inspect :default [inspector obj]
|
612 | 618 | (let [class-chain (loop [c (class obj), res ()]
|
613 | 619 | (if c
|
614 | 620 | (recur (.getSuperclass c) (cons c res))
|
615 | 621 | res))
|
| 622 | + memoized-field-val (memoize field-val) |
616 | 623 | all-fields (mapcat #(.getDeclaredFields ^Class %) class-chain)
|
617 |
| - |
618 |
| - {static true, non-static false} |
619 |
| - (group-by #(Modifier/isStatic (.getModifiers ^Field %)) all-fields)] |
620 |
| - (letfn [(field-name [^Field f] |
621 |
| - (.getName f)) |
622 |
| - |
623 |
| - (field-val [^Field f] |
624 |
| - (let [^Exception e |
625 |
| - (try (.setAccessible f true) |
626 |
| - nil |
627 |
| - (catch Exception e |
628 |
| - ;; We want to handle specifically SecurityException |
629 |
| - ;; and j.l.r.InaccessibleObjectException, but the |
630 |
| - ;; latter only comes with Java9+, so let's just |
631 |
| - ;; catch everything instead. |
632 |
| - e))] |
633 |
| - (try (.get f obj) |
634 |
| - (catch java.lang.IllegalAccessException _ |
635 |
| - (symbol |
636 |
| - (format "<Access denied%s>" |
637 |
| - (when e (str " (" (.getName (.getClass e)) ")")))))))) |
638 |
| - |
639 |
| - (render-fields [inspector section-name fields] |
| 624 | + {static-accessible [true true] |
| 625 | + non-static-accessible [false true] |
| 626 | + static-nonaccessible [true false] |
| 627 | + non-static-nonaccessible [false false]} |
| 628 | + (group-by (fn [^Field f] |
| 629 | + [(Modifier/isStatic (.getModifiers f)) |
| 630 | + (not= ::access-denied (memoized-field-val f obj))]) |
| 631 | + all-fields)] |
| 632 | + (letfn [(render-fields [inspector section-name fields] |
640 | 633 | (if (seq fields)
|
641 | 634 | (-> inspector
|
642 | 635 | (render-section-header section-name)
|
643 | 636 | (indent)
|
644 | 637 | (render-map-values (->> fields
|
645 |
| - (map (fn [f] [(field-name f) (field-val f)])) |
| 638 | + (map (fn [^Field f] |
| 639 | + (let [v (memoized-field-val f obj)] |
| 640 | + [(-> f .getName symbol) |
| 641 | + (if (= v ::access-denied) |
| 642 | + ;; This is a special value that can be detected client-side: |
| 643 | + (symbol "<non-inspectable value>") |
| 644 | + v)]))) |
646 | 645 | (into (sorted-map))))
|
647 | 646 | (unindent))
|
648 | 647 | inspector))]
|
649 |
| - (-> inspector |
650 |
| - (render-labeled-value "Class" (class obj)) |
651 |
| - (render-labeled-value "Value" obj) |
652 |
| - (render-fields "Fields" non-static) |
653 |
| - (render-fields "Static fields" static) |
654 |
| - (render-datafy obj))))) |
| 648 | + (cond-> inspector |
| 649 | + true (render-labeled-value "Class" (class obj)) |
| 650 | + true (render-labeled-value "Value" obj) |
| 651 | + (seq non-static-accessible) (render-fields "Instance fields" non-static-accessible) |
| 652 | + (seq static-accessible) (render-fields "Static fields" static-accessible) |
| 653 | + (seq non-static-nonaccessible) (render-fields "Private instance fields" non-static-nonaccessible) |
| 654 | + (seq static-nonaccessible) (render-fields "Private static fields" static-nonaccessible) |
| 655 | + true (render-datafy obj))))) |
655 | 656 |
|
656 | 657 | (defn- render-section [obj inspector [section sort-key-fn]]
|
657 | 658 | (let [method (symbol (str ".get" (name section)))
|
|
0 commit comments