Skip to content

Commit 8355f23

Browse files
[inspect] Only show those datafied items in collection that have unique datafy repr
1 parent dba9b79 commit 8355f23

File tree

2 files changed

+94
-68
lines changed

2 files changed

+94
-68
lines changed

src/orchard/inspect.clj

Lines changed: 82 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -321,17 +321,18 @@
321321

322322
;; Rendering
323323

324-
(defn render-onto [inspector coll]
325-
(letfn [(render-one [{:keys [rendered] :as inspector} val]
326-
;; Special case: fuse two last strings together.
327-
(let [lst (peek (or rendered []))]
328-
(assoc inspector :rendered (if (and (string? lst) (string? val))
329-
(conj (pop rendered) (str lst val))
330-
(conj rendered val)))))]
331-
(reduce render-one inspector coll)))
324+
(defn render
325+
([{:keys [rendered] :as inspector} value]
326+
;; Special case: fuse two last strings together.
327+
(let [lst (peek (or rendered []))]
328+
(assoc inspector :rendered (if (and (string? lst) (string? value))
329+
(conj (pop rendered) (.concat ^String lst value))
330+
(conj rendered value)))))
331+
([inspector value & values]
332+
(reduce render (render inspector value) values)))
332333

333-
(defn render [inspector & values]
334-
(render-onto inspector values))
334+
(defn render-onto [inspector coll]
335+
(reduce render inspector coll))
335336

336337
(defn render-ln [inspector & values]
337338
(-> inspector
@@ -350,7 +351,7 @@
350351

351352
(defn- padding [{:keys [indentation]}]
352353
(when (and (number? indentation) (pos? indentation))
353-
(apply str (repeat indentation " "))))
354+
(String. (char-array indentation \space))))
354355

355356
(defn- render-indent [inspector & values]
356357
(let [padding (padding inspector)]
@@ -505,27 +506,37 @@
505506
(render-indent-ln ins divider)
506507
(reduce render-row ins pr-rows))))
507508

509+
(defn- leftpad [idx last-idx-len]
510+
(let [idx-s (str idx)
511+
idx-len (count idx-s)]
512+
(if (= idx-len last-idx-len)
513+
(str idx-s ". ")
514+
(str (String. (char-array (- last-idx-len idx-len) \space)) idx-s ". "))))
515+
508516
(defn- render-indexed-chunk
509517
"Render an indexed chunk of values. Renders all values in `chunk`, so `chunk`
510518
must be finite. If `mark-values?` is true, attach the indices to the values in
511-
the index."
512-
[{:keys [pretty-print] :as inspector} chunk idx-starts-from mark-values?]
513-
(let [n (count chunk)
514-
last-idx (+ idx-starts-from n -1)
515-
last-idx-len (count (str last-idx))
516-
idx-fmt (str "%" last-idx-len "s")]
517-
(loop [ins inspector, chunk (seq chunk), idx idx-starts-from]
519+
the index. If `skip-nils?` is true, don't render nil values."
520+
[{:keys [pretty-print] :as inspector} chunk {:keys [start-idx mark-values? skip-nils?]}]
521+
(let [start-idx (or start-idx 0)
522+
n (count chunk)
523+
last-idx (+ start-idx n -1)
524+
last-idx-len (count (str last-idx))]
525+
(loop [ins inspector, chunk (seq chunk), idx start-idx]
518526
(if chunk
519-
(let [header (str (format idx-fmt idx) ". ")
520-
indentation (if pretty-print (count header) 0)]
521-
(recur (-> ins
522-
(render-indent header)
523-
(indent indentation)
524-
(render-value (first chunk)
525-
(when mark-values?
526-
{:value-role :seq-item, :value-key idx}))
527-
(unindent indentation)
528-
(render-ln))
527+
(let [header (leftpad idx last-idx-len)
528+
indentation (if pretty-print (count header) 0)
529+
item (first chunk)]
530+
(recur (if-not (and (nil? item) skip-nils?)
531+
(-> ins
532+
(render-indent header)
533+
(indent indentation)
534+
(render-value item
535+
(when mark-values?
536+
{:value-role :seq-item, :value-key idx}))
537+
(unindent indentation)
538+
(render-ln))
539+
ins)
529540
(next chunk) (inc idx)))
530541
ins))))
531542

@@ -543,19 +554,20 @@
543554
(unindent))
544555
inspector))
545556

546-
(defn- render-items [inspector items map? start-idx mark-values?]
557+
(defn- render-items
558+
[inspector items {:keys [map? start-idx mark-values? skip-nils?] :as opts}]
547559
(if map?
548560
(render-map-values inspector items mark-values?)
549561
(if (= (:view-mode inspector) :table)
550-
(render-chunk-as-table inspector items start-idx)
551-
(render-indexed-chunk inspector items start-idx mark-values?))))
562+
(render-chunk-as-table inspector items (or start-idx 0))
563+
(render-indexed-chunk inspector items opts))))
552564

553565
(defn- render-value-maybe-expand
554566
"If `obj` is a collection smaller than page-size, then render it as a
555567
collection, otherwise as a compact value."
556568
[{:keys [page-size] :as inspector} obj]
557569
(if (some-> (counted-length obj) (<= page-size))
558-
(render-items inspector obj (map? obj) 0 false)
570+
(render-items inspector obj {:map? (map? obj), :start-idx 0})
559571
(render-indented-value inspector obj)))
560572

561573
(defn- render-leading-page-ellipsis [{:keys [current-page] :as inspector}]
@@ -575,9 +587,11 @@
575587
(let [type (object-type value)]
576588
(-> inspector
577589
(render-leading-page-ellipsis)
578-
(render-items (or chunk value) (= type :map) (or start-idx 0)
579-
;; Set items are not indexed - don't mark.
580-
(not= type :set))
590+
(render-items (or chunk value)
591+
{:map? (= type :map)
592+
:start-idx start-idx
593+
;; Set items are not indexed - don't mark.
594+
:mark-values? (not= type :set)})
581595
(render-trailing-page-ellipsis))))
582596

583597
(defn render-meta-information [inspector obj]
@@ -604,25 +618,34 @@
604618

605619
;;;; Datafy
606620

607-
(defn- datafy-kvs [original-object kvs]
621+
(defn- datafy-kvs [original-object kvs keep-same?]
622+
;; keep-same? should be true for datafying collections that were produced by
623+
;; datafying the root, and false if we datafy elements of the original coll.
608624
(let [differs? (volatile! false)
609625
result (into {}
610626
(keep (fn [[k v]]
611627
(when-some [dat (some->> (nav original-object k v)
612628
datafy)]
613-
(when-not (= dat v)
614-
(vreset! differs? true))
615-
[k dat])))
629+
(let [same? (= dat v)]
630+
(when-not same?
631+
(vreset! differs? true))
632+
(when (or (not same?) keep-same?)
633+
[k dat])))))
616634
kvs)]
617-
(with-meta result {:differs @differs?})))
635+
(when-not (empty? result)
636+
result)))
618637

619-
(defn- datafy-seq [s]
638+
(defn- datafy-seq [s keep-same?]
620639
(let [differs? (volatile! false)
621-
result (mapv #(let [dat (datafy %)]
622-
(when-not (= dat %)
640+
result (mapv #(let [dat (datafy %)
641+
same? (= dat %)]
642+
(when-not same?
623643
(vreset! differs? true))
624-
dat) s)]
625-
(with-meta result {:differs @differs?})))
644+
(when (or (not same?) keep-same?)
645+
dat))
646+
s)]
647+
(when (or @differs? keep-same?)
648+
result)))
626649

627650
(defn- datafy-root [obj]
628651
(let [datafied (datafy obj)]
@@ -638,8 +661,8 @@
638661
;; If the root value has datafy representation, check if it's a collection.
639662
;; If so, additionally datafy its items or map values.
640663
(let [datafied (case (object-type datafied)
641-
:map (datafy-kvs datafied datafied)
642-
(:list :set) (datafy-seq datafied)
664+
:map (datafy-kvs datafied datafied true)
665+
(:list :set) (datafy-seq datafied true)
643666
datafied)]
644667
;; Only render the datafy section if the datafied version of the object is
645668
;; different than object, since we don't want to show the same data twice.
@@ -650,13 +673,10 @@
650673
;; If the value is a type that can be paged, then only datafy the
651674
;; displayed chunk.
652675
(let [chunk (or chunk value)
653-
map? (= (object-type value) :map)
654-
datafied (if map?
655-
(datafy-kvs value chunk)
656-
(datafy-seq chunk))]
657-
;; Only return the datafied representation if at least one value is
658-
;; different from the original.
659-
(when (:differs (meta datafied))
676+
datafied (if (= (object-type value) :map)
677+
(datafy-kvs value chunk false)
678+
(datafy-seq chunk false))]
679+
(when datafied
660680
[datafied true])))))
661681

662682
(defn- render-datafy [{:keys [start-idx] :as inspector}]
@@ -670,7 +690,9 @@
670690
;; using the same pagination rules as the main chunk.
671691
(-> ins
672692
(render-leading-page-ellipsis)
673-
(render-items datafied (map? datafied) (or start-idx 0) false)
693+
(render-items datafied {:map? (map? datafied)
694+
:start-idx start-idx
695+
:skip-nils? true})
674696
(render-trailing-page-ellipsis))
675697
;; Otherwise, render datafied representation as a collection if it is
676698
;; small enough, or as a single value.
@@ -978,7 +1000,7 @@
9781000
(unindent ins)
9791001
(render-section-header ins "Trace")
9801002
(indent ins)
981-
(render-items ins (.getStackTrace root-cause) false 0 false)
1003+
(render-items ins (.getStackTrace root-cause) {})
9821004
(unindent ins)
9831005
(render-datafy ins))))
9841006

@@ -987,7 +1009,7 @@
9871009
(render-labeled-value "Class" (class obj))
9881010
(render-section-header "Contents")
9891011
(indent)
990-
(render-items (StackTraceElement->vec obj) false 0 false)))
1012+
(render-items (StackTraceElement->vec obj) {})))
9911013

9921014
(defmethod inspect :aref [inspector ^clojure.lang.ARef obj]
9931015
(let [val (deref obj)]
@@ -1086,10 +1108,7 @@
10861108
(inspect value)
10871109
(render-path)
10881110
(render-view-mode)
1089-
(update :rendered seq))))
1090-
([inspector value]
1091-
(inspect-render (-> (assoc inspector :value value)
1092-
(dissoc :value-analysis)))))
1111+
(update :rendered seq)))))
10931112

10941113
;; Public entrypoints
10951114

@@ -1102,8 +1121,8 @@
11021121
(-> default-inspector-config
11031122
(merge (validate-config config))
11041123
(assoc :stack [], :path [], :pages-stack [], :current-page 0,
1105-
:view-modes-stack [], :view-mode :normal)
1106-
(inspect-render value))))
1124+
:view-modes-stack [], :view-mode :normal, :value value)
1125+
(inspect-render))))
11071126

11081127
(defn ^:deprecated clear
11091128
"If necessary, use `(start inspector nil) instead.`"

test/orchard/inspect_test.clj

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,12 +1119,11 @@
11191119
[:newline]
11201120
" " [:value ":doc" pos?]
11211121
" = "
1122-
[:value #=(str "\"Clojure String utilities\\n\\nIt is poor form to (:use clojure.string). "
1123-
"Instead, use require\\nwith :as to specify a prefix, e.g.\\n\\n(ns your.namespace.here\\n ...\"") pos?]
1122+
[:value string? pos?]
11241123
[:newline]
11251124
" " [:value ":author" pos?]
11261125
" = "
1127-
[:value "\"Stuart Sierra, Stuart Halloway, David Liebke\"" pos?]]
1126+
[:value string? pos?]]
11281127
(section result "Meta Information")))
11291128
(testing "renders the refer from section"
11301129
(is+ ["--- Refer from:"
@@ -1846,9 +1845,17 @@
18461845
(is+ nil (datafy-section rendered))
18471846
(is+ ["--- Datafy:" [:newline]
18481847
" ..." [:newline]
1849-
" 2. " [:value "3" pos?] [:newline]
18501848
" 3. " [:value ":datafied" pos?]]
1851-
(datafy-section (-> ins inspect/next-page render))))))
1849+
(datafy-section (-> ins inspect/next-page render)))))
1850+
(testing "only show those items in collection that have unique datafication"
1851+
(is+ ["--- Datafy:" [:newline]
1852+
" 3. " [:value string? pos?]]
1853+
(-> [1 2 3 (ex-info "datafy" {})]
1854+
inspect render datafy-section))
1855+
(is+ ["--- Datafy:" [:newline]
1856+
" " [:value ":c" pos?] " = " [:value string? pos?]]
1857+
(-> {:a 1 :b 2 :c (ex-info "datafy" {})}
1858+
inspect render datafy-section))))
18521859

18531860
(deftest private-field-access-test
18541861
(testing "Inspection of private fields is attempted (may fail depending on the JDK and the module of the given class)"

0 commit comments

Comments
 (0)