From 67519e0b6b27dff0dece9a73491c4e0a28f608fc Mon Sep 17 00:00:00 2001 From: vemv Date: Sat, 19 Aug 2023 21:03:43 +0200 Subject: [PATCH 1/6] Categorize more frames as `:tooling` --- CHANGELOG.md | 13 ++++++ src/haystack/analyzer.clj | 21 +++++++--- test/haystack/analyzer_test.clj | 70 +++++++++++++++++++++++++++------ 3 files changed, 85 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f7cb53c..a4411ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ ## Changes * `analyzer`: include a `:phase` key for the causes that include a `:clojure.error/phase`. +* Categorize more frames as `:tooling` + * `:tooling` now intends to more broadly hide things that are commonly Clojure-internal / irrelevant to the application programmer. + * New exhaustive list: + * `cider.*` + * `clojure.core/apply` + * `clojure.core/binding-conveyor-fn` + * `clojure.core/eval` + * `clojure.core/with-bindings` + * `clojure.lang.Compiler` + * `clojure.lang.RT` + * `clojure.main/repl` + * `nrepl.*` + * `java.lang.Thread/run` (if it's the root element of the stacktrace) ## 0.1.0 diff --git a/src/haystack/analyzer.clj b/src/haystack/analyzer.clj index 3bce9a9..54d8c49 100644 --- a/src/haystack/analyzer.clj +++ b/src/haystack/analyzer.clj @@ -120,17 +120,26 @@ (flag-frame frame :repl) frame)) +(defn- tool? [frame-name last?] + (boolean (or (re-find #"^clojure\.lang\.AFn|^clojure\.lang\.RestFn|^clojure\.lang\.RT|clojure\.lang\.Compiler|^nrepl\.|^cider\.|^clojure\.core/eval|^clojure\.core/apply|^clojure\.core/with-bindings|^clojure\.core/binding-conveyor-fn|^clojure\.main/repl" + frame-name) + (and last? + ;; Everything runs from a Thread, so this frame, if at root, is irrelevant. + ;; However one can invoke this method 'by hand', which is why we also observe `last?`. + (re-find #"^java\.lang\.Thread/run" frame-name))))) + (defn- flag-tooling "Walk the call stack from top to bottom, flagging frames below the first call to `clojure.lang.Compiler` or `nrepl.*` as `:tooling` to distinguish compilation and nREPL middleware frames from user code." [frames] - (let [tool-regex #"^clojure\.lang\.Compiler|^nrepl\.|^cider\." - tool? #(re-find tool-regex (or (:name %) "")) - flag #(if (tool? %) - (flag-frame % :tooling) - %)] - (map flag frames))) + (let [last-index (dec (count frames))] + (into [] + (map-indexed (fn [i {frame-name :name :as frame}] + (cond-> frame + (some-> frame-name (tool? (= i last-index))) + (flag-frame :tooling)))) + frames))) (defn directory-namespaces "Looks for all namespaces inside of directories on the class diff --git a/test/haystack/analyzer_test.clj b/test/haystack/analyzer_test.clj index 33543e9..1d02f31 100644 --- a/test/haystack/analyzer_test.clj +++ b/test/haystack/analyzer_test.clj @@ -341,7 +341,7 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url)))) (testing "last frame" (is (= {:name "java.lang.Thread/run" @@ -350,7 +350,7 @@ :class "java.lang.Thread" :method "run" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (last stacktrace) :file-url))))))) (testing "second cause" (let [{:keys [class data message stacktrace]} (second causes)] @@ -369,7 +369,7 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url))))))) (testing "third cause" (let [{:keys [class data message stacktrace]} (nth causes 2)] @@ -388,7 +388,7 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url))))))))) (deftest test-analyze-short-clojure-tagged-literal-println @@ -411,7 +411,7 @@ :class "java.lang.Thread" :method "run" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url))))))))) (deftest test-analyze-java @@ -434,7 +434,7 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url)))) (testing "last frame" (is (= {:name "java.lang.Thread/run" @@ -443,7 +443,7 @@ :class "java.lang.Thread" :method "run" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (last stacktrace) :file-url))))))) (testing "second cause" (let [{:keys [class data message stacktrace]} (second causes)] @@ -462,7 +462,7 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url)))) (testing "last frame" (is (= {:name "clojure.lang.Compiler$InvokeExpr/eval" @@ -490,7 +490,7 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (first stacktrace) :file-url)))) (testing "last frame" (is (= {:name "clojure.lang.Compiler$InvokeExpr/eval" @@ -544,12 +544,12 @@ :class "clojure.lang.AFn" :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (nth stacktrace 0) :file-url)))) (testing "2nd frame" (is (= {:class "clojure.lang.AFn" :file "AFn.java" - :flags #{:java} + :flags #{:java :tooling} :line 144 :method "applyTo" :name "clojure.lang.AFn/applyTo" @@ -572,7 +572,7 @@ :line 160 :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (nth stacktrace 0) :file-url))))))) (testing "third cause" (let [{:keys [class data message stacktrace]} (nth causes 2 nil)] @@ -591,7 +591,7 @@ :line 156 :method "applyToHelper" :type :java - :flags #{:java}} + :flags #{:java :tooling}} (dissoc (nth stacktrace 0) :file-url)))))))) (let [{:keys [major minor]} *clojure-version*] @@ -604,3 +604,47 @@ (catch Throwable e (sut/analyze e))) (map :phase)))))))) + +(deftest tool? + (are [frame-name expected] (testing frame-name + (is (= expected + (#'sut/tool? frame-name false))) + true) + "cider.foo" true + "acider.foo" false + ;; `+` is "application" level, should not be hidden: + "clojure.core/+" false + ;; `apply` typically is internal, should be hidden: + "clojure.core/apply" true + "clojure.core/binding-conveyor-fn/fn" true + "clojure.core/eval" true + "clojure.core/with-bindings*" true + "clojure.lang.AFn/applyTo" true + "clojure.lang.AFn/applyToHelper" true + "clojure.lang.RestFn/invoke" true + "clojure.main/repl" true + "nrepl.foo" true + "anrepl.foo" false + ;; important case - `Numbers` is relevant, should not be hidden: + "clojure.lang.Numbers/divide" false) + + (is (not (#'sut/tool? "java.lang.Thread/run" false))) + (is (#'sut/tool? "java.lang.Thread/run" true))) + +(deftest flag-tooling + (is (= [{:name "cider.foo", :flags #{:tooling}} + {:name "java.lang.Thread/run"} ;; does not get the flag because it's not the root frame + {:name "don't touch me 1"} + {:name "nrepl.foo", :flags #{:tooling}} + {:name "clojure.lang.RestFn/invoke", :flags #{:tooling}} + {:name "don't touch me 2"} + ;; gets the flag because it's not the root frame: + {:name "java.lang.Thread/run", :flags #{:tooling}}] + (#'sut/flag-tooling [{:name "cider.foo"} + {:name "java.lang.Thread/run"} + {:name "don't touch me 1"} + {:name "nrepl.foo"} + {:name "clojure.lang.RestFn/invoke"} + {:name "don't touch me 2"} + {:name "java.lang.Thread/run"}])) + "Adds the flag when appropiate, leaving other entries untouched")) From 48dc0f9d69fcb42fdee0cc775b35b5676daf79e0 Mon Sep 17 00:00:00 2001 From: vemv Date: Sun, 20 Aug 2023 02:34:21 +0200 Subject: [PATCH 2/6] Use `demunge` --- src/haystack/analyzer.clj | 13 +++++++------ test/haystack/analyzer_test.clj | 30 ++++++++++++++++-------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/src/haystack/analyzer.clj b/src/haystack/analyzer.clj index 54d8c49..2752f8a 100644 --- a/src/haystack/analyzer.clj +++ b/src/haystack/analyzer.clj @@ -121,12 +121,13 @@ frame)) (defn- tool? [frame-name last?] - (boolean (or (re-find #"^clojure\.lang\.AFn|^clojure\.lang\.RestFn|^clojure\.lang\.RT|clojure\.lang\.Compiler|^nrepl\.|^cider\.|^clojure\.core/eval|^clojure\.core/apply|^clojure\.core/with-bindings|^clojure\.core/binding-conveyor-fn|^clojure\.main/repl" - frame-name) - (and last? - ;; Everything runs from a Thread, so this frame, if at root, is irrelevant. - ;; However one can invoke this method 'by hand', which is why we also observe `last?`. - (re-find #"^java\.lang\.Thread/run" frame-name))))) + (let [demunged (repl/demunge frame-name)] + (boolean (or (re-find #"^clojure\.lang\.AFn|^clojure\.lang\.RestFn|^clojure\.lang\.RT|clojure\.lang\.Compiler|^nrepl\.|^cider\.|^clojure\.core/eval|^clojure\.core/apply|^clojure\.core/with-bindings|^clojure\.core/binding-conveyor-fn|^clojure\.main/repl" + demunged) + (and last? + ;; Everything runs from a Thread, so this frame, if at root, is irrelevant. + ;; However one can invoke this method 'by hand', which is why we also observe `last?`. + (re-find #"^java\.lang\.Thread/run" demunged)))))) (defn- flag-tooling "Walk the call stack from top to bottom, flagging frames below the first call diff --git a/test/haystack/analyzer_test.clj b/test/haystack/analyzer_test.clj index 1d02f31..41abf5d 100644 --- a/test/haystack/analyzer_test.clj +++ b/test/haystack/analyzer_test.clj @@ -610,23 +610,25 @@ (is (= expected (#'sut/tool? frame-name false))) true) - "cider.foo" true - "acider.foo" false + "cider.foo" true + "acider.foo" false ;; `+` is "application" level, should not be hidden: - "clojure.core/+" false + "clojure.core/+" false ;; `apply` typically is internal, should be hidden: - "clojure.core/apply" true - "clojure.core/binding-conveyor-fn/fn" true - "clojure.core/eval" true - "clojure.core/with-bindings*" true - "clojure.lang.AFn/applyTo" true - "clojure.lang.AFn/applyToHelper" true - "clojure.lang.RestFn/invoke" true - "clojure.main/repl" true - "nrepl.foo" true - "anrepl.foo" false + "clojure.core/apply" true + "clojure.core/binding-conveyor-fn/fn" true + "clojure.core/eval" true + "clojure.core/with-bindings*" true + "clojure.lang.AFn/applyTo" true + "clojure.lang.AFn/applyToHelper" true + "clojure.lang.RestFn/invoke" true + "clojure.main/repl" true + "clojure.main$repl$read_eval_print__9234$fn__9235/invoke" true + "nrepl.foo" true + "nrepl.middleware.interruptible_eval$evaluate/invokeStatic" true + "anrepl.foo" false ;; important case - `Numbers` is relevant, should not be hidden: - "clojure.lang.Numbers/divide" false) + "clojure.lang.Numbers/divide" false) (is (not (#'sut/tool? "java.lang.Thread/run" false))) (is (#'sut/tool? "java.lang.Thread/run" true))) From 66ae61856b6c040c3fd508a89f2921e252772d25 Mon Sep 17 00:00:00 2001 From: vemv Date: Sun, 20 Aug 2023 02:34:33 +0200 Subject: [PATCH 3/6] Refine some docstrings --- src/haystack/analyzer.clj | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/haystack/analyzer.clj b/src/haystack/analyzer.clj index 2752f8a..9ee3196 100644 --- a/src/haystack/analyzer.clj +++ b/src/haystack/analyzer.clj @@ -54,7 +54,7 @@ (or (info/file-path path) (second (resource/resource-path-tuple path)))) (defn- frame->url - "Return a java.net.URL to the file referenced in the frame, if possible. + "Return a `java.net.URL` to the file referenced in the frame, if possible. Useful for handling clojure vars which may not exist. Uncomprehensive list of reasons for this: * Failed refresh @@ -336,7 +336,7 @@ (flag-tooling))))) (defn- analyze-cause - "Analyze the `cause-data` of an exception in `Throwable->map` format." + "Analyze the `cause-data` of an exception, in `Throwable->map` format." [cause-data print-fn] (let [pprint-str #(let [writer (StringWriter.)] (print-fn % writer) @@ -378,8 +378,8 @@ "Return the analyzed cause chain for `exception` beginning with the thrown exception. `exception` can be an instance of `Throwable` or a map in the same format as `Throwable->map`. For `ex-info` - exceptions, the response contains a :data slot with the pretty - printed data. For clojure.spec asserts, the :spec slot contains a + exceptions, the response contains a `:data` slot with the pretty + printed data. For clojure.spec asserts, the `:spec` slot contains a map of pretty printed components describing spec failures." {:added "0.1.0"} ([exception] From 4c361ec35789bd2374909c46c4a8d5e4d58b8000 Mon Sep 17 00:00:00 2001 From: vemv Date: Sun, 20 Aug 2023 02:48:53 +0200 Subject: [PATCH 4/6] Fix cljs tests, run them on CI --- .circleci/config.yml | 11 +++++---- Makefile | 4 ++-- README.org | 17 +++++++------- project.clj | 23 ++++++++++--------- test/haystack/parser/clojure/repl_test.cljc | 2 +- .../parser/clojure/stacktrace_test.cljc | 2 +- test/haystack/parser/java_test.cljc | 2 +- 7 files changed, 33 insertions(+), 28 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 829efdb..a989c2f 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -16,7 +16,7 @@ defaults: &defaults executors: openjdk8: docker: - - image: circleci/clojure:openjdk-8-lein-2.9.5 + - image: circleci/clojure:openjdk-8-lein-2.9.1-node environment: LEIN_ROOT: "true" # we intended to run lein as root JVM_OPTS: -Xmx3200m # limit the maximum heap size to prevent out of memory errors @@ -32,7 +32,7 @@ executors: openjdk11: docker: - - image: circleci/clojure:openjdk-11-lein-2.9.5 + - image: circleci/clojure:openjdk-11-lein-2.9.3-buster-node environment: LEIN_ROOT: "true" # we intended to run lein as root JVM_OPTS: -Xmx3200m --illegal-access=deny # forbid reflective access (this flag doesn't exist for JDK8 or JDK17+) @@ -40,7 +40,7 @@ executors: openjdk17: docker: - - image: circleci/clojure:openjdk-17-lein-2.9.5-buster + - image: circleci/clojure:openjdk-17-lein-2.9.5-buster-node environment: LEIN_ROOT: "true" # we intended to run lein as root JVM_OPTS: -Xmx3200m @@ -153,8 +153,11 @@ jobs: cache_version: << parameters.clojure_version >>|<< parameters.jdk_version >> steps: - run: - name: Running tests + name: Running JVM tests command: make test + - run: + name: Running cljs tests + command: make test-cljs ###################################################################### # diff --git a/Makefile b/Makefile index 5f27307..6e4f85e 100644 --- a/Makefile +++ b/Makefile @@ -8,8 +8,8 @@ clean: test: clean lein with-profile -user,-dev,+$(VERSION) test -test-cljs: - lein cljsbuild once +test-cljs: clean + lein with-profile -user,-dev,+cljsbuild cljsbuild once node target/cljs/test.js cljfmt: diff --git a/README.org b/README.org index 7233896..12ff669 100644 --- a/README.org +++ b/README.org @@ -186,14 +186,6 @@ We get back a sequence of maps, one for each cause, which contain additional information about each frame discovered from the class path. ** Development -*** Deployment - -Here's how to deploy to Clojars: - -#+begin_src sh -git tag -a v0.1.0 -m "0.1.0" -git push --tags -#+end_src *** Creating a parser @@ -255,6 +247,15 @@ for writing Instaparse grammars: - If your parser fails on an input, [[https://github.com/Engelberg/instaparse#revealing-hidden-information][reveal hidden information]] to get a better understanding of what happened. +*** Deployment + +Here's how to deploy to Clojars: + +#+begin_src sh +git tag -a v0.1.0 -m "0.1.0" +git push --tags +#+end_src + ** Changelog [[CHANGELOG.md][CHANGELOG.md]] diff --git a/project.clj b/project.clj index dc07f4f..66de8e6 100644 --- a/project.clj +++ b/project.clj @@ -2,7 +2,7 @@ ;; whenever we perform a deployment. (defproject mx.cider/haystack (or (not-empty (System/getenv "PROJECT_VERSION")) "0.0.0") - :description "" + :description "Let's make the most of Clojure's infamous stacktraces!" :url "https://github.com/clojure-emacs/haystack" :license {:name "Eclipse Public License" :url "https://www.eclipse.org/legal/epl-v10.html"} @@ -16,15 +16,7 @@ :username :env/clojars_username :password :env/clojars_password :sign-releases false}]] - :plugins [[lein-cljsbuild "1.1.8"]] - :cljsbuild {:builds - [{:id "test" - :compiler - {:main haystack.test.runner - :output-dir "target/cljs/test" - :output-to "target/cljs/test.js" - :target :nodejs} - :source-paths ["src" "test"]}]} + :profiles {:provided {:dependencies [[org.clojure/clojure "1.11.1"] [org.clojure/clojurescript "1.11.4"]]} @@ -40,7 +32,16 @@ "https://oss.sonatype.org/content/repositories/snapshots"]] :dependencies [[org.clojure/clojure "1.12.0-master-SNAPSHOT"] [org.clojure/clojure "1.12.0-master-SNAPSHOT" :classifier "sources"]]} - + :cljsbuild {:plugins [[lein-cljsbuild "1.1.8"]] + :dependencies [[lein-doo "0.1.11"]] + :cljsbuild {:builds + [{:id "test" + :compiler + {:main haystack.test.runner + :output-dir "target/cljs/test" + :output-to "target/cljs/test.js" + :target :nodejs} + :source-paths ["src" "test"]}]}} :cljfmt [:test {:plugins [[lein-cljfmt "0.9.0" :exclusions [org.clojure/clojure org.clojure/clojurescript]]]}] diff --git a/test/haystack/parser/clojure/repl_test.cljc b/test/haystack/parser/clojure/repl_test.cljc index f0b4405..927f49a 100644 --- a/test/haystack/parser/clojure/repl_test.cljc +++ b/test/haystack/parser/clojure/repl_test.cljc @@ -113,7 +113,7 @@ :reason #?(:clj [{:tag :regexp :expecting "[a-zA-Z0-9_$/-]"} {:tag :regexp :expecting "[^\\S\\r\\n]+"}] - :cljs [{:tag :regexp, :expecting "/^[a-zA-Z0-9_$\\/-]/"} + :cljs [{:tag :regexp, :expecting "/^[a-zA-Z0-9_$/-]/"} {:tag :regexp, :expecting "/^[^\\S\\r\\n]+/"}]) :line 1 :column 1 diff --git a/test/haystack/parser/clojure/stacktrace_test.cljc b/test/haystack/parser/clojure/stacktrace_test.cljc index 22e853a..dd3c2a4 100644 --- a/test/haystack/parser/clojure/stacktrace_test.cljc +++ b/test/haystack/parser/clojure/stacktrace_test.cljc @@ -115,7 +115,7 @@ :reason #?(:clj [{:tag :regexp :expecting "[a-zA-Z0-9_$/-]"} {:tag :regexp :expecting "[^\\S\\r\\n]+"}] - :cljs [{:tag :regexp, :expecting "/^[a-zA-Z0-9_$\\/-]/"} + :cljs [{:tag :regexp, :expecting "/^[a-zA-Z0-9_$/-]/"} {:tag :regexp, :expecting "/^[^\\S\\r\\n]+/"}]) :line 1 :column 1 diff --git a/test/haystack/parser/java_test.cljc b/test/haystack/parser/java_test.cljc index ab1d769..2a753b9 100644 --- a/test/haystack/parser/java_test.cljc +++ b/test/haystack/parser/java_test.cljc @@ -115,7 +115,7 @@ :reason #?(:clj [{:tag :regexp, :expecting "[a-zA-Z0-9_$/-]"} {:tag :regexp, :expecting "[^\\S\\r\\n]+"}] - :cljs [{:tag :regexp, :expecting "/^[a-zA-Z0-9_$\\/-]/"} + :cljs [{:tag :regexp, :expecting "/^[a-zA-Z0-9_$/-]/"} {:tag :regexp, :expecting "/^[^\\S\\r\\n]+/"}]) :line 1 :column 1 From d93e177c55e8817d54bfa4203af10a9bd849db25 Mon Sep 17 00:00:00 2001 From: vemv Date: Sun, 20 Aug 2023 13:13:38 +0200 Subject: [PATCH 5/6] PR feedback --- src/haystack/analyzer.clj | 10 ++++++---- test/haystack/analyzer_test.clj | 8 ++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/haystack/analyzer.clj b/src/haystack/analyzer.clj index 9ee3196..6ae355f 100644 --- a/src/haystack/analyzer.clj +++ b/src/haystack/analyzer.clj @@ -120,10 +120,12 @@ (flag-frame frame :repl) frame)) -(defn- tool? [frame-name last?] +(def ^:private tooling-frame-re + #"^clojure\.lang\.AFn|^clojure\.lang\.RestFn|^clojure\.lang\.RT|clojure\.lang\.Compiler|^nrepl\.|^cider\.|^clojure\.core/eval|^clojure\.core/apply|^clojure\.core/with-bindings|^clojure\.core/binding-conveyor-fn|^clojure\.main/repl") + +(defn- tooling-frame-name? [frame-name last?] (let [demunged (repl/demunge frame-name)] - (boolean (or (re-find #"^clojure\.lang\.AFn|^clojure\.lang\.RestFn|^clojure\.lang\.RT|clojure\.lang\.Compiler|^nrepl\.|^cider\.|^clojure\.core/eval|^clojure\.core/apply|^clojure\.core/with-bindings|^clojure\.core/binding-conveyor-fn|^clojure\.main/repl" - demunged) + (boolean (or (re-find tooling-frame-re demunged) (and last? ;; Everything runs from a Thread, so this frame, if at root, is irrelevant. ;; However one can invoke this method 'by hand', which is why we also observe `last?`. @@ -138,7 +140,7 @@ (into [] (map-indexed (fn [i {frame-name :name :as frame}] (cond-> frame - (some-> frame-name (tool? (= i last-index))) + (some-> frame-name (tooling-frame-name? (= i last-index))) (flag-frame :tooling)))) frames))) diff --git a/test/haystack/analyzer_test.clj b/test/haystack/analyzer_test.clj index 41abf5d..27472c4 100644 --- a/test/haystack/analyzer_test.clj +++ b/test/haystack/analyzer_test.clj @@ -605,10 +605,10 @@ (sut/analyze e))) (map :phase)))))))) -(deftest tool? +(deftest tooling-frame-name? (are [frame-name expected] (testing frame-name (is (= expected - (#'sut/tool? frame-name false))) + (#'sut/tooling-frame-name? frame-name false))) true) "cider.foo" true "acider.foo" false @@ -630,8 +630,8 @@ ;; important case - `Numbers` is relevant, should not be hidden: "clojure.lang.Numbers/divide" false) - (is (not (#'sut/tool? "java.lang.Thread/run" false))) - (is (#'sut/tool? "java.lang.Thread/run" true))) + (is (not (#'sut/tooling-frame-name? "java.lang.Thread/run" false))) + (is (#'sut/tooling-frame-name? "java.lang.Thread/run" true))) (deftest flag-tooling (is (= [{:name "cider.foo", :flags #{:tooling}} From 49006cc8537cc87ccf90ec16b8e3c399099e8946 Mon Sep 17 00:00:00 2001 From: vemv Date: Sun, 20 Aug 2023 13:20:01 +0200 Subject: [PATCH 6/6] Refine docstring --- src/haystack/analyzer.clj | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/haystack/analyzer.clj b/src/haystack/analyzer.clj index 6ae355f..6fc5933 100644 --- a/src/haystack/analyzer.clj +++ b/src/haystack/analyzer.clj @@ -132,9 +132,10 @@ (re-find #"^java\.lang\.Thread/run" demunged)))))) (defn- flag-tooling - "Walk the call stack from top to bottom, flagging frames below the first call - to `clojure.lang.Compiler` or `nrepl.*` as `:tooling` to - distinguish compilation and nREPL middleware frames from user code." + "Given a collection of stack `frames`, marks the 'tooling' ones as such. + + A 'tooling' frame is one that generally represents Clojure, JVM, nREPL or CIDER internals, + and that is therefore not relevant to application-level code." [frames] (let [last-index (dec (count frames))] (into []