Skip to content

Commit 55e0e72

Browse files
arichiardibbatsov
authored andcommitted
Introduce orchard.resource
This patch brings in orchard the code necessary for resource resolution and does a bit of refactoring: javadoc is now in orchard.java, where it belongs, and a new orchard.java.resource namespace has been created containing the actual reusable resource code.
1 parent 536b9b9 commit 55e0e72

File tree

5 files changed

+119
-45
lines changed

5 files changed

+119
-45
lines changed

src/orchard/info.clj

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
(:require
55
[clojure.edn :as edn]
66
[clojure.java.io :as io]
7-
[clojure.java.javadoc :as javadoc]
87
[orchard.classpath :as cp]
9-
[orchard.java :as java]
108
[orchard.cljs.analysis :as cljs-ana]
119
[orchard.cljs.meta :as cljs-meta]
10+
[orchard.java :as java]
1211
[orchard.meta :as m]
13-
[orchard.misc :as u]))
12+
[orchard.misc :as u]
13+
[orchard.resource :as resource]))
1414

1515
(defn normalize-ns-meta
1616
"Normalize cljs namespace metadata to look like a clj."
@@ -199,22 +199,6 @@ resolved (real) namespace and name here"}
199199
[class member]
200200
(java/member-info class member))
201201

202-
(defn- resource-full-path [relative-path]
203-
(io/resource relative-path (cp/boot-aware-classloader)))
204-
205-
(defn resource-path
206-
"If it's a resource, return a tuple of the relative path and the full resource path."
207-
[x]
208-
(or (if-let [full (resource-full-path x)]
209-
[x full])
210-
(if-let [[_ relative] (re-find #".*jar!/(.*)" x)]
211-
(if-let [full (resource-full-path relative)]
212-
[relative full]))
213-
;; handles load-file on jar resources from a cider buffer
214-
(if-let [[_ relative] (re-find #".*jar:(.*)" x)]
215-
(if-let [full (resource-full-path relative)]
216-
[relative full]))))
217-
218202
(defn file-path
219203
"For a file path, return a URL to the file if it exists and does not
220204
represent a form evaluated at the REPL."
@@ -227,7 +211,7 @@ resolved (real) namespace and name here"}
227211

228212
(defn file-info
229213
[path]
230-
(let [[resource-relative resource-full] (resource-path path)]
214+
(let [[resource-relative resource-full] (resource/resource-path-tuple path)]
231215
(merge {:file (or (file-path path) resource-full path)}
232216
;; Classpath-relative path if possible
233217
(if resource-relative
@@ -238,25 +222,4 @@ resolved (real) namespace and name here"}
238222
resources on the classpath; then use online javadoc content for core API
239223
classes. If no source is available, return the relative path as is."
240224
[^String path]
241-
{:javadoc
242-
(or (resource-full-path path)
243-
;; [bug#308] `*remote-javadocs*` is outdated WRT Java
244-
;; 8, so we try our own thing first.
245-
(when (re-find #"^(java|javax|jdk|org.omg|org.w3c.dom|org.xml.sax)/" path)
246-
(apply str ["https://docs.oracle.com"
247-
(if (>= u/java-api-version 11) "/en/java/javase/" "/javase/")
248-
u/java-api-version
249-
"/docs/api/"
250-
path]))
251-
;; If that didn't work, _then_ we fallback on `*remote-javadocs*`.
252-
(some (let [classname (.replaceAll path "/" ".")]
253-
(fn [[prefix url]]
254-
(when (.startsWith classname prefix)
255-
(str url path))))
256-
@javadoc/*remote-javadocs*)
257-
path)})
258-
259-
;; TODO: Seems those were hardcoded here accidentally - we should
260-
;; probably provide a simple API to register remote JavaDocs.
261-
(javadoc/add-remote-javadoc "com.amazonaws." "http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/")
262-
(javadoc/add-remote-javadoc "org.apache.kafka." "https://kafka.apache.org/090/javadoc/index.html?")
225+
{:javadoc (java/resolve-javadoc-path path)})

src/orchard/java.clj

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
{:author "Jeff Valk"}
44
(:require
55
[clojure.java.io :as io]
6+
[clojure.java.javadoc :as javadoc]
67
[clojure.reflect :as r]
78
[clojure.string :as str]
89
[orchard.classpath :as cp]
9-
[orchard.misc :as util])
10+
[orchard.misc :as util]
11+
[orchard.resource :as resource])
1012
(:import
1113
(clojure.lang IPersistentMap)
1214
(clojure.reflect Constructor Field JavaReflector Method)
@@ -343,10 +345,37 @@
343345
(first ms)
344346
{:candidates (zipmap (map :class ms) ms)})))))
345347

348+
(defn resolve-javadoc-path
349+
"Resolve a relative javadoc path to a URL and return as a map. Prefer javadoc
350+
resources on the classpath; then use online javadoc content for core API
351+
classes. If no source is available, return the relative path as is."
352+
[^String path]
353+
(or (resource/resource-full-path path)
354+
;; [bug#308] `*remote-javadocs*` is outdated WRT Java
355+
;; 8, so we try our own thing first.
356+
(when (re-find #"^(java|javax|jdk|org.omg|org.w3c.dom|org.xml.sax)/" path)
357+
(apply str ["https://docs.oracle.com"
358+
(if (>= util/java-api-version 11) "/en/java/javase/" "/javase/")
359+
util/java-api-version
360+
"/docs/api/"
361+
path]))
362+
;; If that didn't work, _then_ we fallback on `*remote-javadocs*`.
363+
(some (let [classname (.replaceAll path "/" ".")]
364+
(fn [[prefix url]]
365+
(when (.startsWith classname prefix)
366+
(str url path))))
367+
@javadoc/*remote-javadocs*)
368+
path))
369+
346370
;;; ## Initialization
347371
;;
348372
;; On startup, cache info for the most commonly referenced classes.
349373
(future
350374
(doseq [class (->> (ns-imports 'clojure.core)
351375
(map #(-> % ^Class val .getName symbol)))]
352376
(class-info class)))
377+
378+
;; TODO: Seems those were hardcoded here accidentally - we should
379+
;; probably provide a simple API to register remote JavaDocs.
380+
(javadoc/add-remote-javadoc "com.amazonaws." "http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/")
381+
(javadoc/add-remote-javadoc "org.apache.kafka." "https://kafka.apache.org/090/javadoc/index.html?")

src/orchard/resource.clj

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
(ns orchard.resource
2+
"Resolve JVM resource-related information."
3+
{:added "0.5.0"}
4+
(:require
5+
[clojure.java.io :as io]
6+
[orchard.classpath :as cp]))
7+
8+
(defn- trim-leading-separator
9+
"Trim the java.io.File/separator at the beginning of s."
10+
[s]
11+
(if (.startsWith s java.io.File/separator)
12+
(subs s 1)
13+
s))
14+
15+
(defn project-resources
16+
"Get a list of classpath resources."
17+
[]
18+
(mapcat
19+
(fn [directory]
20+
(->> directory
21+
(file-seq)
22+
(filter (memfn isFile))
23+
(map (fn [file]
24+
(let [relpath (-> file
25+
(.getPath)
26+
(.replaceFirst
27+
(.getPath directory)
28+
"")
29+
(trim-leading-separator))]
30+
{:root directory
31+
:file file
32+
:relpath relpath
33+
:url (io/resource relpath)})))
34+
(remove #(.startsWith (:relpath %) "META-INF/"))
35+
(remove #(re-matches #".*\.(clj[cs]?|java|class)" (:relpath %)))))
36+
(filter (memfn isDirectory) (map io/as-file (cp/classpath (cp/boot-aware-classloader))))))
37+
38+
(defn resource-full-path [relative-path]
39+
(io/resource relative-path (cp/boot-aware-classloader)))
40+
41+
(defn resource-path-tuple
42+
"If it's a resource, return a tuple of the relative path and the full
43+
resource path."
44+
[path]
45+
(or (if-let [full (resource-full-path path)]
46+
[path full])
47+
(if-let [[_ relative] (re-find #".*jar!/(.*)" path)]
48+
(if-let [full (resource-full-path relative)]
49+
[relative full]))
50+
;; handles load-file on jar resources from a cider buffer
51+
(if-let [[_ relative] (re-find #".*jar:(.*)" path)]
52+
(if-let [full (resource-full-path relative)]
53+
[relative full]))))
54+
55+
(defn resource-path
56+
"Return the resource path for the given name."
57+
{:added "0.5.0"}
58+
[name]
59+
(some-> name (resource-full-path) (.getPath)))
60+
61+
(defn resource-maps
62+
"Return a seq of resource maps:
63+
64+
{:file \"the absolute path to the resource\"
65+
:relpath \"the path of the resource relative to the classpath\"}
66+
67+
If the project does not contain resources, it returns nil."
68+
{:added "0.5.0"}
69+
[]
70+
(map #(select-keys % [:file :relpath])
71+
(project-resources)))

test/orchard/info_test.clj

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,7 @@
491491
(is (= (class (file "orchard/test_ns.cljc"))
492492
java.net.URL))
493493
(is (relative "clojure/core.clj"))
494-
(is (nil? (relative "notclojure/core.clj")))
495-
(is (nil? (info/resource-path "jar:file:fake.jar!/fake/file.clj"))))
494+
(is (nil? (relative "notclojure/core.clj"))))
496495

497496
(deftest qualify-sym-test
498497
(is (= '+ (info/qualify-sym nil '+)))

test/orchard/resource_test.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(ns orchard.resource-test
2+
(:require
3+
[clojure.test :refer [deftest testing is]]
4+
[orchard.resource :as resource]))
5+
6+
(deftest resource-path-tuple-test
7+
(is (nil? (resource/resource-path-tuple "jar:file:fake.jar!/fake/file.clj"))))
8+
9+
(deftest project-resources-test
10+
(testing "get the correct resources for the orchard project"
11+
(is (= "see-also.edn" (-> (resource/project-resources) first :relpath)))
12+
(is (= java.net.URL (-> (resource/project-resources) first :url class)))))

0 commit comments

Comments
 (0)