Skip to content

Commit 01c755e

Browse files
authored
Make read-namespace handle read conditionals gracefully (#145)
Fixes #142
1 parent 9a41a60 commit 01c755e

File tree

3 files changed

+44
-28
lines changed

3 files changed

+44
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@
1111
* added `orchard.xref/fn-deps-class` as a lower level API so you can still get the main functions deps only
1212
* added `orchard.xref/fn-transitive-deps`
1313

14+
### Bugs fixed
15+
16+
* [142](https://github.com/clojure-emacs/orchard/issues/142): Make read-namespace handle read conditionals gracefully
17+
1418
## 0.8.0 (2021-12-15)
1519

1620
### Changes

src/orchard/namespace.clj

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
{:author "Jeff Valk"
77
:added "0.5"}
88
(:require
9-
[clojure.edn :as edn]
109
[clojure.java.io :as io]
1110
[clojure.string :as str]
1211
[orchard.java.classpath :as cp]
@@ -20,13 +19,21 @@
2019
(defn read-namespace
2120
"Returns the namespace name from the first top-level `ns` form in the file."
2221
[url]
23-
(try
24-
(with-open [r (PushbackReader. (io/reader url))]
25-
(->> (repeatedly #(edn/read r))
26-
(filter #(and (list? %) (= (first %) 'ns))) ; ns form
27-
(map second) ; ns name
28-
(first)))
29-
(catch Exception _)))
22+
(with-open [r (PushbackReader. (io/reader url))]
23+
(loop []
24+
(let [found (try
25+
(binding [*read-eval* false]
26+
(read {:read-cond :allow
27+
:eof ::eof}
28+
r))
29+
(catch Exception _
30+
::fail))]
31+
(cond
32+
(#{::eof ::fail} found) nil
33+
(and (list? found)
34+
(-> found first #{`ns 'ns}))
35+
(second found)
36+
:else (recur))))))
3037

3138
(defn canonical-source
3239
"Returns the URL of the source file for the namespace object or symbol,

test/orchard/namespace_test.clj

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@
44
[clojure.string :as str]
55
[clojure.test :refer [deftest is testing]]
66
[orchard.misc :as misc]
7-
[orchard.namespace :as n]))
7+
[orchard.namespace :as sut]))
88

99
(deftest project-namespaces-test
10-
(is (contains? (into #{} (n/project-namespaces))
10+
(is (contains? (into #{} (sut/project-namespaces))
1111
'orchard.namespace)))
1212

1313
(deftest loaded-namespaces-test
1414
;; If we don't pass the second arg, some cider ns will be returned
15-
(is (some #(re-find #".*orchard" %) (n/loaded-namespaces)))
15+
(is (some #(re-find #".*orchard" %) (sut/loaded-namespaces)))
1616
;; Shouldn't return any orchard namespaces
1717
(is (not-any? #(re-find #".*orchard" %)
18-
(n/loaded-namespaces [".*orchard"]))))
18+
(sut/loaded-namespaces [".*orchard"]))))
1919

2020
(defn- change-case
2121
"Utility fn to change the case of a URL path, to help with case sensitivity
@@ -28,43 +28,48 @@
2828
(if (= string lower) upper lower))))
2929

3030
(deftest project-nses-ignore-case-on-windows-test
31-
(let [orig-project-root n/project-root]
31+
(let [orig-project-root sut/project-root]
3232
(testing "Project nses is case sensitive on non Windows oses"
3333
(with-redefs [misc/os-windows? (constantly false)
34-
n/project-root (change-case orig-project-root)]
35-
(is (not (seq (n/project-namespaces))))))
34+
sut/project-root (change-case orig-project-root)]
35+
(is (not (seq (sut/project-namespaces))))))
3636
(testing "Project nses ignore cases on Windows oses"
3737
(with-redefs [misc/os-windows? (constantly true)
38-
n/project-root (change-case orig-project-root)]
39-
(is (seq (n/project-namespaces)))))))
38+
sut/project-root (change-case orig-project-root)]
39+
(is (seq (sut/project-namespaces)))))))
4040

4141
(deftest has-tests-errors
42-
(is (n/has-tests? (find-ns 'orchard.namespace-test))))
42+
(is (sut/has-tests? (find-ns 'orchard.namespace-test))))
4343

44-
(deftest namespace-parsing
44+
(deftest read-namespace-test
4545
(testing "Namespace parsing"
4646
(let [url (-> (System/getProperty "java.io.tmpdir")
4747
(io/file "orchard.namespace-test.txt")
4848
(io/as-url))
4949
uri (.toURI url)]
5050
(testing "of an empty file"
5151
(spit url "")
52-
(is (nil? (n/read-namespace uri))))
52+
(is (nil? (sut/read-namespace uri))))
5353
(testing "of an unparsable file"
5454
(spit url "(]$@(")
55-
(is (nil? (n/read-namespace uri))))
55+
(is (nil? (sut/read-namespace uri))))
5656
(testing "of non-list tokens"
5757
(spit url "these are (still) tokens")
58-
(is (nil? (n/read-namespace uri))))
58+
(is (nil? (sut/read-namespace uri))))
5959
(testing "when tokens precede the ns form"
6060
(spit url "there [is a] (ns here) after all")
61-
(is (= (n/read-namespace uri) 'here)))
61+
(is (= 'here (sut/read-namespace uri))))
6262
(testing "when multiple ns forms are present"
6363
(spit url "(ns ns1) (ns ns2) (ns ns3)")
64-
(is (= (n/read-namespace uri) 'ns1)))
64+
(is (= 'ns1 (sut/read-namespace uri))))
6565
(testing "of top-level forms only"
6666
(spit url "(comment (ns ns1)) (ns ns2) (ns ns3)")
67-
(is (= (n/read-namespace uri) 'ns2)))
67+
(is (= 'ns2 (sut/read-namespace uri))))
68+
(testing "of namespace with read conditionals in its `ns` form"
69+
(is (= 'orchard.test-ns (-> "orchard/test_ns.cljc"
70+
io/resource
71+
io/as-url
72+
sut/read-namespace))))
6873
(io/delete-file url))))
6974

7075
(deftest namespace-resolution
@@ -76,8 +81,8 @@
7681
orchard.namespace
7782
orchard.cljs.test-canonical-source]]
7883
(testing "namespace symbols to source files"
79-
(is (every? identity (map n/canonical-source nses))))
84+
(is (every? identity (map sut/canonical-source nses))))
8085
(testing "source files to namespace symbols"
81-
(is (= nses (map (comp n/read-namespace ; src -> ns
82-
n/canonical-source) ; ns -> src
86+
(is (= nses (map (comp sut/read-namespace ; src -> ns
87+
sut/canonical-source) ; ns -> src
8388
nses)))))))

0 commit comments

Comments
 (0)