-
Notifications
You must be signed in to change notification settings - Fork 9
/
plugin_v2.clj
158 lines (143 loc) · 6.55 KB
/
plugin_v2.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
(ns cider.enrich-classpath.plugin-v2
(:refer-clojure :exclude [time])
(:require
[cider.enrich-classpath :as enrich-classpath]
[cider.enrich-classpath.jdk :as jdk]
[cider.enrich-classpath.logging :refer [debug info warn]]
[clojure.string :as string]
[leiningen.core.classpath :as leiningen.classpath]
[leiningen.core.main]
[leiningen.javac :as javac]))
(defn format-nrepl-options [{:keys [transport nrepl-handler socket nrepl-middleware host port]}]
(->> [["--transport" (when (qualified-symbol? transport)
(pr-str (str transport)))]
["--handler" (when (qualified-symbol? nrepl-handler)
(pr-str (str nrepl-handler)))]
["--socket" (some-> socket not-empty pr-str)]
["--middleware" (when-let [s (some->> nrepl-middleware
(filterv qualified-symbol?)
(not-empty)
(pr-str))]
(str "\"" s "\""))]
["--host" (some-> host not-empty pr-str)]
["--port" (some-> port str not-empty)]]
(filter second)
(reduce into [])
(string/join " ")))
(defn format-jvm-opts [{:keys [jvm-opts compile-path]}]
(let [a jvm-opts
b (some->> compile-path
not-empty
string/trim
(str "-Dclojure.compile.path="))
all (cond-> a
b (conj b)
true jdk/maybe-add-opens)
res (not-empty (string/join " " all))]
(if res
(str " " res " ")
"")))
(defn wrap-try
"Wraps `init` in a try/catch because otherwise `clojure.main`
can fail at startup, while 'init' errors can often be remediated by the user later."
[init-ns init global-vars]
;; Note that we don't need to suppress output (I formerly did that for stdout/stderr).
;; This code runs after the classpath has been enriched and the `java` command has been generated.
(let [{clojure-global-vars true
other-global-vars false} (group-by (fn [[sym]]
(contains? #{nil "clojure.core"} (namespace sym)))
global-vars)]
(apply list `try (reduce into [] [(mapv (fn [[var-sym value]]
(list `set! var-sym value))
clojure-global-vars)
(when init-ns
[(list `doto (list `quote init-ns) `require `in-ns)])
(mapv (fn [[var-sym value]]
(list `set! var-sym value))
other-global-vars)
(when init
[init])
[(list `catch `Throwable 'e
(list '.printStackTrace 'e))]]))))
(defn build-init-form [{{:keys [init init-ns]} :repl-options
:keys [global-vars]}]
(or (when (or init init-ns (seq global-vars))
(str " --eval "
(pr-str (pr-str (wrap-try init-ns init global-vars)))
" "))
" "))
(defn remove-enrich-middleware [mw]
(into []
(remove #{`middleware
'cider.enrich-classpath/middleware})
mw))
(defn remove-enrich-middleware-from-map [m]
(into {}
(map (fn [[profile-name profile-content]]
[profile-name (cond-> profile-content
(and (map? profile-content) ;; avoid hitting composite profiles
(:middleware profile-content))
(update :middleware remove-enrich-middleware))]))
m))
(def default-main "nrepl.cmdline")
(defn middleware* [{:keys [repl-options java-source-paths]
{:keys [main]
:or {main default-main}} :enrich-classpath
:as project}]
(when (seq java-source-paths)
(binding [leiningen.core.main/*exit-process?* false]
(warn "enrich-classpath has triggered javac.")
(javac/javac (with-meta (-> project
(update :middleware remove-enrich-middleware)
(update :profiles remove-enrich-middleware-from-map))
(-> project
meta
(update-in [:without-profiles :middleware] remove-enrich-middleware)
(update-in [:without-profiles :profiles] remove-enrich-middleware-from-map)
(update :profiles remove-enrich-middleware-from-map))))))
(let [java (or (some-> project :java not-empty string/trim)
"java")
nrepl-options (format-nrepl-options repl-options)
sep (System/getProperty "path.separator")
orig (cond-> project
;; XXX condition could be better: instead of this, resolve deps+mged-deps, check all of them (i.e. the transitives ones)
(not-any? (comp '#{nrepl/nrepl nrepl} first) (:dependencies project))
(update :dependencies conj '[nrepl/nrepl "1.0.0"])
true
(assoc :pedantic? false)
true
leiningen.classpath/get-classpath)
orig (string/join sep orig)
{{{:keys [tools
dependencies
managed-dependencies
java-source-paths
jdk-sources]} :results} :enrich-classpath}
(enrich-classpath/middleware (-> project
(assoc-in [:enrich-classpath :shorten] true)
(assoc-in [:enrich-classpath :only-present-results?] true)))
suffix
(->> [dependencies
managed-dependencies
java-source-paths
tools
jdk-sources]
(reduce into [])
(remove empty?)
(string/join sep))
enriched-classpath (str orig sep suffix)
init-form (build-init-form project)]
(format "%s -cp %s%sclojure.main%s-m %s %s"
java
enriched-classpath
(format-jvm-opts project)
init-form
main
(if (= main default-main)
nrepl-options
""))))
(defn middleware [project]
;; XXX failsafe. as a last resource, `echo` the strace
(println (middleware* project))
;; XXX exit 1 too
(leiningen.core.main/exit 0))