From f0761c41ab226ca6c1b1ded703e6764be6a99661 Mon Sep 17 00:00:00 2001 From: Oleksandr Yakushev Date: Fri, 3 Jul 2026 12:36:46 +0300 Subject: [PATCH] [inspector] Remove datafy section --- CHANGELOG.md | 2 + src/orchard/inspect.clj | 110 +------------------ test/orchard/inspect_test.clj | 199 +--------------------------------- 3 files changed, 11 insertions(+), 300 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a98d3e23..f71bd588 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## master (unreleased) +- [#406](https://github.com/clojure-emacs/orchard/pull/406): Inspector: remove Datafy section. + ## 0.43.0 (2026-06-24) - [#402](https://github.com/clojure-emacs/orchard/pull/402): Add `orchard.xref/type-protocols` (the protocols a type implements, both `extend`-style and inline) and `orchard.xref/protocols-with-method` (the protocols declaring a method of a given name). diff --git a/src/orchard/inspect.clj b/src/orchard/inspect.clj index 8834644e..05365099 100644 --- a/src/orchard/inspect.clj +++ b/src/orchard/inspect.clj @@ -9,7 +9,6 @@ Pretty wild, right?" (:require - [clojure.core.protocols :refer [datafy nav]] [clojure.reflect :as reflect] [clojure.set :as set] [clojure.string :as str] @@ -638,98 +637,6 @@ (unindent)) inspector)) -;;;; Datafy - -(defn- datafy* [o] - ;; Don't datafy known types which we already render nicely, because datafying - ;; them causes the Datafy section to unnecessarily appear in the inspector. - (if (or (var? o) (class? o) (instance? clojure.lang.ARef o) (instance? Throwable o)) - o - (datafy o))) - -(defn- datafy-kvs [original-object kvs keep-same?] - ;; keep-same? should be true for datafying collections that were produced by - ;; datafying the root, and false if we datafy elements of the original coll. - (let [differs? (volatile! false) - result (into {} - (keep (fn [[k v]] - (when-some [dat (some->> (nav original-object k v) - datafy*)] - (let [same? (= dat v)] - (when-not same? - (vreset! differs? true)) - (when (or (not same?) keep-same?) - [k dat]))))) - kvs)] - (when-not (empty? result) - result))) - -(defn- datafy-seq [s keep-same?] - (let [differs? (volatile! false) - result (mapv #(let [dat (datafy* %) - same? (= dat %)] - (when-not same? - (vreset! differs? true)) - (when (or (not same?) keep-same?) - dat)) - s)] - (when (or @differs? keep-same?) - result))) - -(defn- datafy-root [obj] - (let [datafied (datafy* obj)] - (when-not (identical? obj datafied) - datafied))) - -(defn- datafy-displayed-value - "Datafy either the current value or its paginated view. Return datafied - representation if it differs from value and boolean `mirror?` that tells if - the datafied representation mirrors the structure of the input collection." - [{:keys [value chunk]}] - (if-let [datafied (datafy-root value)] - ;; If the root value has datafy representation, check if it's a collection. - ;; If so, additionally datafy its items or map values. - (let [datafied (case (object-type datafied) - :map (datafy-kvs datafied datafied true) - (:list :set) (datafy-seq datafied true) - datafied)] - ;; Only render the datafy section if the datafied version of the object is - ;; different than object, since we don't want to show the same data twice. - (when-not (identical? datafied value) - [datafied false])) - - (when (pageable? value) - ;; If the value is a type that can be paged, then only datafy the - ;; displayed chunk. - (let [chunk (or chunk value) - datafied (if (= (object-type value) :map) - (datafy-kvs value chunk false) - (datafy-seq chunk false))] - (when datafied - [datafied true]))))) - -(defn- render-datafy [{:keys [start-idx] :as inspector}] - (if-let [[datafied mirror?] (datafy-displayed-value inspector)] - (as-> inspector ins - (render-section-header ins "Datafy") - (indent ins) - - (if mirror? - ;; If datafy is a "mirror" of the inspected object, then display it - ;; using the same pagination rules as the main chunk. - (-> ins - (render-leading-page-ellipsis) - (render-items datafied {:map? (map? datafied) - :start-idx start-idx - :skip-nils? true}) - (render-trailing-page-ellipsis)) - ;; Otherwise, render datafied representation as a collection if it is - ;; small enough, or as a single value. - (render-value-maybe-expand ins datafied)) - - (unindent ins)) - inspector)) - ;; Hex view mode (defn- byte->ascii [b] @@ -805,7 +712,6 @@ (indent) (render-collection-paged) (unindent) - (render-datafy) (render-page-info))) (defmethod inspect :list [inspector obj] (inspect-coll inspector obj)) @@ -823,7 +729,6 @@ (render-hexdump ins) (render-collection-paged ins)) (unindent ins) - (render-datafy ins) (render-page-info ins))) (defn- render-var-value [inspector ^clojure.lang.Var obj] @@ -834,8 +739,7 @@ (defmethod inspect :var [inspector obj] (-> (render-class-name inspector obj) (render-var-value obj) - (render-meta-information obj) - (render-datafy))) + (render-meta-information obj))) (defn- render-indent-str-lines [inspector s] (reduce #(-> (render-indent %1 (str %2)) @@ -931,8 +835,7 @@ (seq non-static-accessible) (render-fields "Instance fields" non-static-accessible) (seq static-accessible) (render-fields "Static fields" static-accessible) (seq non-static-nonaccessible) (render-fields "Private instance fields" non-static-nonaccessible) - (seq static-nonaccessible) (render-fields "Private static fields" static-nonaccessible) - true (render-datafy))))) + (seq static-nonaccessible) (render-fields "Private static fields" static-nonaccessible))))) (defn- render-class-section [inspector section elements print-fn & [sort-fn]] (if-not (seq elements) @@ -1016,8 +919,7 @@ (print-fn #(.toGenericString ^Constructor %))) (render-class-section :Fields (.getFields obj) (print-fn #(.toGenericString ^Field %))) - (render-class-methods obj (print-fn #(.toGenericString ^Method %))) - (render-datafy)))) + (render-class-methods obj (print-fn #(.toGenericString ^Method %)))))) (defmethod inspect :method [inspector ^Method obj] (as-> inspector ins @@ -1088,8 +990,7 @@ (render-section-header ins "Trace") (indent ins) (render-items ins (.getStackTrace root-cause) {}) - (unindent ins) - (render-datafy ins)))) + (unindent ins)))) (defmethod inspect :stack-trace-element [inspector ^StackTraceElement obj] (-> inspector @@ -1171,8 +1072,7 @@ (render-meta-information obj) (render-ns-refers obj) (render-ns-imports obj) - (render-ns-interns obj) - (render-datafy))) + (render-ns-interns obj))) (defn render-path "Render the navigation path to the currently inspected value." diff --git a/test/orchard/inspect_test.clj b/test/orchard/inspect_test.clj index f3172f74..ccb38977 100644 --- a/test/orchard/inspect_test.clj +++ b/test/orchard/inspect_test.clj @@ -2,7 +2,6 @@ (:require [clojure.string :as str] [clojure.test :refer [deftest is testing]] - [clojure.walk :as walk] [matcher-combinators.matchers :as matchers] [orchard.inspect :as inspect] [orchard.misc :as misc :refer [java-api-version]] @@ -10,21 +9,6 @@ (:import (orchard.java PrivateFieldClass))) -(defn- demunge-str [s] - (-> s - (str/replace #"(?i)\$([a-z-]+)__([0-9]+)(@[a-f0-9]+)?" "\\$$1") - (str/replace #"(?i)(fn|eval)--([0-9]+)" "$1"))) - -(defn- demunge - ([rendered] - (demunge rendered demunge-str)) - ([rendered demunge-fn] - (walk/prewalk (fn [form] - (if (string? form) - (demunge-fn form) - form)) - rendered))) - ;; Simplifies writing test structures for `match?`. (def nil-result @@ -83,9 +67,6 @@ (defn- section [rendered name] (get (group-sections rendered) name)) -(defn- datafy-section [rendered] - (section rendered "Datafy")) - (defn- contents-section [rendered] (section rendered "Contents")) @@ -96,12 +77,6 @@ (when-let [sec (section rendered "Page Info")] (last sec))) -(defn- extend-datafy-class [m] - (vary-meta m assoc 'clojure.core.protocols/datafy (fn [x] (assoc x :class (.getSimpleName (class x)))))) - -(defn- extend-nav-vector [m] - (vary-meta m assoc 'clojure.core.protocols/nav (fn [coll k v] [k (get coll k v)]))) - (defn inspect [value & [config]] (inspect/start config value)) @@ -650,42 +625,6 @@ render (section "Meta Information")))))) -(deftest inspect-coll-nav-test - (testing "inspecting a collection extended with the Datafiable and Navigable protocols" - (is+ {"Contents" - [" 0. " [:value "{:x 0}" pos?] [:newline] - " 1. " [:value "{:x 1}" pos?] [:newline] - " ..."] - - "Datafy" - [" 0. " [:value "{:class \"PersistentHashMap\", :x 0}" pos?] [:newline] - " 1. " [:value "{:class \"PersistentHashMap\", :x 1}" pos?] [:newline] - " ..."] - - "Page Info" - [" Page size: 2, showing page: 1 of ?"]} - (-> (inspect (->> (iterate inc 0) - (map #(hash-map :x %)) - (map extend-datafy-class) - (map extend-nav-vector))) - (set-page-size 2) - render - group-sections)) - (testing "follows the same pagination rules" - (is+ [" ..." [:newline] - " 4. " [:value "{:class \"PersistentHashMap\", :x 4}" pos?] [:newline] - " 5. " [:value "{:class \"PersistentHashMap\", :x 5}" pos?] [:newline] - " ..."] - (-> (inspect (->> (iterate inc 0) - (map #(hash-map :x %)) - (map extend-datafy-class) - (map extend-nav-vector))) - (set-page-size 2) - (inspect/next-page) - (inspect/next-page) - render - datafy-section))))) - (deftest inspect-configure-length-test (testing "inspect respects :max-atom-length and :max-coll-size configuration" (is+ (matchers/prefix @@ -936,10 +875,7 @@ " Count: 1" [:newline] [:newline] " --- Contents:" [:newline] - " " [:value ":a" 2] " = " [:value "1" 3]] - - "Datafy" - matchers/absent} + " " [:value ":a" 2] " = " [:value "1" 3]]} (-> (inspect (atom {:a 1})) render group-sections))) (testing "small collection is rendered fully" @@ -1005,58 +941,9 @@ [" " [:value #=(str "{ends-with? #'clojure.string/ends-with?, " "replace-first-char #'clojure.string/replace-first-char, " "capitalize #'clojure.string/capitalize, " - "reverse #'clojure.string/reverse, join #'clojure.string/join, ...}") pos?]] - - "Datafy" - [" " [:value ":name" 9] " = " [:value "clojure.string" pos?] - [:newline] - " " [:value ":publics" pos?] " = " - [:value #=(str "{blank? #'clojure.string/blank?, capitalize " - "#'clojure.string/capitalize, ends-with? #'clojure.string/ends-with?, " - "escape #'clojure.string/escape, includes? #'clojure.string/includes?, ...}") pos?] - [:newline] - " " [:value ":imports" pos?] " = " - [:value #=(str "{AbstractMethodError java.lang.AbstractMethodError, Appendable java.lang.Appendable, " - "ArithmeticException java.lang.ArithmeticException, ArrayIndexOutOfBoundsException " - "java.lang.ArrayIndexOutOfBoundsException, ArrayStoreException java.lang.ArrayStoreException, ...}") pos?] - [:newline] - " " [:value ":interns" pos?] " = " - [:value #=(str "{blank? #'clojure.string/blank?, capitalize #'clojure.string/capitalize, ends-with? #'clojure.string/ends-with?, " - "escape #'clojure.string/escape, includes? #'clojure.string/includes?, ...}") pos?]]} + "reverse #'clojure.string/reverse, join #'clojure.string/join, ...}") pos?]]} (-> (find-ns 'clojure.string) inspect render group-sections)))) -(deftest inspect-datafiable-metadata-extension-test - (testing "inspecting a map extended with the Datafiable protocol" - (is+ {nil - ["Class: " [:value "clojure.lang.PersistentArrayMap" 0] [:newline] - "Count: 1"] - - "Meta Information" - [" " [:value "clojure.core.protocols/datafy" 1] - " = " - [:value "#function[orchard.inspect-test/extend-datafy-class/fn]" 2]] - - "Datafy" - [" " [:value ":name" pos?] " = " [:value "\"John Doe\"" pos?] [:newline] - " " [:value ":class" pos?] " = " [:value "\"PersistentArrayMap\"" pos?]]} - (-> (extend-datafy-class {:name "John Doe"}) - inspect render demunge group-sections)))) - -(deftest inspect-navigable-metadata-extension-test - (testing "inspecting a map extended with the Navigable protocol" - (is+ {nil - ["Class: " [:value "clojure.lang.PersistentArrayMap" 0] [:newline] - "Count: 1"] - - "Meta Information" - [" " [:value "clojure.core.protocols/nav" pos?] - " = " [:value "#function[orchard.inspect-test/extend-nav-vector/fn]" pos?]] - - "Datafy" - [" " [:value ":name" pos?] " = " [:value "[:name \"John Doe\"]" pos?]]} - (-> (extend-nav-vector {:name "John Doe"}) - inspect render demunge group-sections)))) - (deftest inspect-throwable-test (testing "inspecting a throwable" (is+ {nil @@ -1532,10 +1419,10 @@ (testing "when :pov-ns is passed, use it to compact qualified keywords" (is+ [" " [:value "::foo" pos?] " = " [:value "1" pos?] [:newline] " " [:value "::str/bar" pos?] " = " [:value "2" pos?] [:newline] - " " [:value "::walk/baz" pos?] " = " [:value "3" pos?]] + " " [:value "::misc/baz" pos?] " = " [:value "3" pos?]] (-> {::foo 1 ::str/bar 2 - :clojure.walk/baz 3} + :orchard.misc/baz 3} (inspect {:pov-ns 'orchard.inspect-test}) render contents-section)))) @@ -1605,84 +1492,6 @@ (remove-tap test-tap-handler)))) -(deftest datafy-test - (testing "When `(datafy x)` is identical to `x`, no Datafy section is included" - (is+ nil (-> {:foo :bar} inspect render datafy-section)) - (is+ nil (-> {:foo :bar :nilable nil} inspect render datafy-section))) - (testing "datafy is not included for records" - (is+ nil (-> (->TestRecord 1 2 3 4) inspect render datafy-section))) - (testing "if datafied repr doesn't mirror the original, don't page datafied" - (is+ {"Contents" - [" " [:value ":a" pos?] - " = " - [:value "1" pos?] - [:newline] - " ..."] - - "Datafy" - [" " [:value "[0 1 2 3 4 ...]" pos?]]} - (-> {:a 1, :b 2} - (with-meta {'clojure.core.protocols/datafy - (fn [_] (range 30))}) - inspect - (set-page-size 1) - render - group-sections)) - - (testing "if datafied is small enough, render it as a collection" - (is+ [" 0. " [:value "0" pos?] - [:newline] - " 1. " [:value "1" pos?] - [:newline] - " 2. " [:value "2" pos?]] - (-> {:a 1, :b 2} - (with-meta {'clojure.core.protocols/datafy - (fn [_] (range 3))}) - inspect - (set-page-size 5) - render - datafy-section)))) - (testing "datafy doesn't show if the differing datafied is not on the current page" - (is+ nil (-> {:a 1, :b (with-meta [] {'clojure.core.protocols/datafy - (fn [_] :datafied)})} - inspect - (set-page-size 1) - render - datafy-section)) - (is+ [" ..." [:newline] - " " [:value ":b" pos?] " = " [:value ":datafied" pos?]] - (-> {:a 1, :b (with-meta [] {'clojure.core.protocols/datafy - (fn [_] :datafied)})} - inspect - (set-page-size 1) - inspect/next-page - render - datafy-section)) - (is+ nil (-> [1 2 3 (with-meta [] {'clojure.core.protocols/datafy - (fn [_] :datafied)})] - inspect - (set-page-size 2) - render - datafy-section)) - (is+ [" ..." [:newline] - " 3. " [:value ":datafied" pos?]] - (-> [1 2 3 (with-meta [] {'clojure.core.protocols/datafy - (fn [_] :datafied)})] - inspect - (set-page-size 2) - inspect/next-page - render - datafy-section))) - (testing "only show those items in collection that have unique datafication" - (is+ [" 3. " [:value string? pos?]] - (-> [1 2 3 (with-meta [] {'clojure.core.protocols/datafy - (fn [_] (range 3))})] - inspect render datafy-section)) - (is+ [" " [:value ":c" pos?] " = " [:value string? pos?]] - (-> {:a 1 :b 2 :c (with-meta [] {'clojure.core.protocols/datafy - (fn [_] (range 3))})} - inspect render datafy-section)))) - (deftest private-field-access-test (testing "Inspection of private fields is attempted (may fail depending on the JDK and the module of the given class)" (if (< java-api-version 17)