Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamically load middleware #438

Merged
merged 3 commits into from Sep 16, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.

Always

Just for now

@@ -31,27 +31,27 @@

:profiles {:provided {:dependencies [[org.clojure/clojure "1.7.0"]]}

:dev {:repl-options {:nrepl-middleware [cider.nrepl.middleware.apropos/wrap-apropos
cider.nrepl.middleware.classpath/wrap-classpath
cider.nrepl.middleware.complete/wrap-complete
cider.nrepl.middleware.debug/wrap-debug
cider.nrepl.middleware.enlighten/wrap-enlighten
cider.nrepl.middleware.format/wrap-format
cider.nrepl.middleware.info/wrap-info
cider.nrepl.middleware.inspect/wrap-inspect
cider.nrepl.middleware.macroexpand/wrap-macroexpand
cider.nrepl.middleware.ns/wrap-ns
cider.nrepl.middleware.spec/wrap-spec
cider.nrepl.middleware.out/wrap-out
:dev {:repl-options {:nrepl-middleware [cider.nrepl/wrap-apropos

This comment has been minimized.

Copy link
@bbatsov

bbatsov Sep 7, 2017

Member

I definitely don't like that all the middleware wrappers ended up being in some utility namespace.

cider.nrepl/wrap-classpath
cider.nrepl/wrap-complete
cider.nrepl/wrap-debug
cider.nrepl/wrap-enlighten
cider.nrepl/wrap-format
cider.nrepl/wrap-info
cider.nrepl/wrap-inspect
cider.nrepl/wrap-macroexpand
cider.nrepl/wrap-ns
cider.nrepl/wrap-out
cider.nrepl/wrap-refresh
cider.nrepl/wrap-resource
cider.nrepl/wrap-spec
cider.nrepl/wrap-stacktrace
cider.nrepl/wrap-test
cider.nrepl/wrap-trace
cider.nrepl/wrap-tracker
cider.nrepl/wrap-undef
cider.nrepl.middleware.pprint/wrap-pprint
cider.nrepl.middleware.pprint/wrap-pprint-fn
cider.nrepl.middleware.refresh/wrap-refresh
cider.nrepl.middleware.resource/wrap-resource
cider.nrepl.middleware.stacktrace/wrap-stacktrace
cider.nrepl.middleware.test/wrap-test
cider.nrepl.middleware.trace/wrap-trace
cider.nrepl.middleware.track-state/wrap-tracker
cider.nrepl.middleware.undef/wrap-undef
cider.nrepl.middleware.version/wrap-version]}
:dependencies [[org.clojure/tools.nrepl "0.2.13"]
;; For developing the Leiningen plugin.

Large diffs are not rendered by default.

@@ -41,7 +41,7 @@
and may be case senstive. Types returned correspond to Apropos types.
Docstring search returns the full doc; symbol search returns an abbreviated
version."
[ns query search-ns docs? privates? case-sensitive? filter-regexps]
[{:keys [ns query search-ns docs? privates? case-sensitive? filter-regexps]}]

This comment has been minimized.

Copy link
@bbatsov

bbatsov Sep 7, 2017

Member

I saw this change at few places and it seems somewhat unrelated, so it should probably be in a separate commit for clarity's sake.

This comment has been minimized.

Copy link
@vspinu

vspinu Sep 10, 2017

Author Contributor

I don't remember exactly anymore, but I am pretty confident that this change is needed to make the handle-apropos behave as all other handle-xyz functions (i.e. take in two args - an nrepl handler and a map msg).

(let [ns-vars (if privates? ns-interns ns-publics)
var-doc* (if docs? var-doc (partial var-doc 1))
search-prop (if docs? var-doc var-name)
@@ -61,24 +61,9 @@

;;; ## Middleware

(defn handle-apropos
"Return a sequence of vars whose name matches the query pattern, or if
specified, having the pattern in their docstring."
[{:keys [ns query search-ns docs? privates? case-sensitive? filter-regexps] :as msg}]
{:apropos-matches (find-symbols ns query search-ns docs? privates? case-sensitive? filter-regexps)})
(defn apropos [msg]
{:apropos-matches (find-symbols msg)})

(defn wrap-apropos
"Middleware that handles apropos requests"
[handler]
(with-safe-transport handler
"apropos" handle-apropos))

;; nREPL middleware descriptor info
(set-descriptor!
#'wrap-apropos
{:handles
{"apropos"
{:doc (:doc (meta #'handle-apropos))
:requires {"query" "The search query."}
:optional {"filter-regexps" "All vars from namespaces matching any regexp from this list would be dropped from the result."}
:returns {"apropos-matches" "A list of matching symbols."}}}})
(defn handle-apropos [handler msg]
(with-safe-transport handler msg
"apropos" apropos))
@@ -9,15 +9,6 @@
(defn classpath-reply [msg]
{:classpath (classpath)})

(defn wrap-classpath
"Middleware that provides the java classpath."
[handler]
(with-safe-transport handler
(defn handle-classpath [handler msg]
(with-safe-transport handler msg
"classpath" classpath-reply))

(set-descriptor!
#'wrap-classpath
{:handles
{"classpath"
{:doc "Obtain a list of entries in the Java classpath."
:returns {"classpath" "A list of the Java classpath entries."}}}})
@@ -38,31 +38,8 @@
(jvm-complete-utils/flush-caches)
{})

(defn wrap-complete
"Middleware that looks up possible functions for the given (partial) symbol."
[handler]
(with-safe-transport handler
(defn handle-complete [handler msg]
(with-safe-transport handler msg
"complete" complete-reply
"complete-doc" doc-reply
"complete-flush-caches" flush-caches-reply))

(set-descriptor!
#'wrap-complete
(cljs/requires-piggieback
{:requires #{#'session/session}
:handles
{"complete"
{:doc "Return a list of symbols matching the specified (partial) symbol."
:requires {"ns" "The symbol's namespace"
"symbol" "The symbol to lookup"
"session" "The current session"}
:optional {"context" "Completion context for compliment."
"extra-metadata" "List of extra-metadata fields. Possible values: arglists, doc."}
:returns {"completions" "A list of possible completions"}}
"complete-doc"
{:doc "Retrieve documentation suitable for display in completion popup"
:requires {"ns" "The symbol's namespace"
"symbol" "The symbol to lookup"}
:returns {"completion-doc" "Symbol's documentation"}}
"complete-flush-caches"
{:doc "Forces the completion backend to repopulate all its caches"}}}))
@@ -601,46 +601,15 @@ this map (identified by a key), and will `dissoc` it afterwards."}
(response-for msg :status :done :list)
(transport/send (:transport msg))))

(defn wrap-debug [h]
(fn [{:keys [op input session] :as msg}]
(case op
"eval" (do (when (instance? clojure.lang.Atom session)
(swap! session assoc #'*skip-breaks* (atom nil)))
(h (maybe-debug msg)))
"debug-instrumented-defs" (instrumented-defs-reply msg)
"debug-input" (when-let [pro (@promises (:key msg))]
(deliver pro input))
"init-debugger" (initialize msg)
;; else
(h msg))))

(set-descriptor!
#'wrap-debug
(cljs/requires-piggieback
{:expects #{"eval"}
:requires #{#'pprint/wrap-pprint-fn #'session/session}
:handles
{"debug-input"
{:doc "Read client input on debug action."
:requires {"input" "The user's reply to the input request."}
:returns {"status" "done"}}
"init-debugger"
{:doc "Initialize the debugger so that `breakpoint` works correctly.
This usually does not respond immediately. It sends a response when a
breakpoint is reached or when the message is discarded."
:requires {"id" "A message id that will be responded to when a breakpoint is reached."}}
"debug-instrumented-defs"
{:doc "Return an alist of definitions currently thought to be instrumented on each namespace.
Due to Clojure's versatility, this could include false postives, but
there will not be false negatives. Instrumentations inside protocols
are not listed."
:returns {"status" "done"
"list" "The alist of (NAMESPACE . VARS) that are thought to be instrumented."}}
"debug-middleware"
{:doc "Debug a code form or fall back on regular eval."
:requires {"id" "A message id that will be responded to when a breakpoint is reached."
"code" "Code to debug, there must be a #dbg or a #break reader macro in it, or nothing will happen."
"file" "File where the code is located."
"ns" "Passed to \"eval\"."
"point" "Position in the file where the provided code begins."}
:returns {"status" "\"done\" if the message will no longer be used, or \"need-debug-input\" during debugging sessions"}}}}))
(defn handle-debug
[handler {:keys [op input session] :as msg}]
(case op
"eval" (do (when (instance? clojure.lang.Atom session)
(swap! session assoc #'*skip-breaks* (atom nil)))
(handler (maybe-debug msg)))
"debug-instrumented-defs" (instrumented-defs-reply msg)
"debug-input" (when-let [pro (@promises (:key msg))]
(deliver pro input))
"init-debugger" (initialize msg)
;; else
(handler msg)))
@@ -85,14 +85,8 @@
;; (ins/print-form form1 true)
(eval form1)))

(defn wrap-enlighten [h]
(fn [{:keys [op enlighten] :as msg}]
(if (and (= op "eval") enlighten)
(h (assoc msg :eval "cider.nrepl.middleware.enlighten/eval-with-enlighten"))
(h msg))))

(set-descriptor!
#'wrap-enlighten
;; We need to come before wrap-debug, so that the debugger can still
;; work if enlighten-mode is on.
{:expects #{"eval" #'d/wrap-debug}})
(defn handle-enlighten
[h {:keys [op enlighten] :as msg}]
(if (and (= op "eval") enlighten)
(h (assoc msg :eval "cider.nrepl.middleware.enlighten/eval-with-enlighten"))
(h msg)))
@@ -41,24 +41,7 @@
[{:keys [edn pprint-fn] :as msg}]
{:formatted-edn (format-edn edn pprint-fn)})

(defn wrap-format
"Middleware that provides code formatting."
[handler]
(with-safe-transport handler
(defn handle-format [handler msg]
(with-safe-transport handler msg
"format-code" format-code-reply
"format-edn" format-edn-reply))

(set-descriptor!
#'wrap-format
{:requires #{#'pprint/wrap-pprint-fn}
:handles
{"format-code"
{:doc "Reformats the given Clojure code, returning the result as a string."
:requires {"code" "The code to format."}
:returns {"formatted-code" "The formatted code."}}
"format-edn"
{:doc "Reformats the given EDN data, returning the result as a string."
:requires {"edn" "The data to format."}
:optional {"print-right-margin" "The maximum column width of the formatted result."
"pprint-fn" "Fully qualified name of the print function to be used."}
:returns {"formatted-edn" "The formatted data."}}}})
@@ -9,8 +9,6 @@
[cider.nrepl.middleware.util.misc :as u]
[cider.nrepl.middleware.util.meta :as m]
[cljs-tooling.info :as cljs-info]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.middleware.session :as session]
[cider.nrepl.middleware.util.spec :as spec]))

(defn- boot-class-loader
@@ -280,31 +278,8 @@
{:inputs (format-arglists [inputs])})
(catch Throwable _ {:status :no-eldoc})))

(defn wrap-info
"Middleware that looks up info for a symbol within the context of a particular namespace."
[handler]
(with-safe-transport handler
(defn handle-info [handler msg]
(with-safe-transport handler msg
"info" info-reply
"eldoc" eldoc-reply
"eldoc-datomic-query" eldoc-datomic-query-reply))

(set-descriptor!
#'wrap-info
(cljs/requires-piggieback
{:requires #{#'session/session}
:handles
{"info"
{:doc "Return a map of information about the specified symbol."
:requires {"symbol" "The symbol to lookup"
"ns" "The current namespace"}
:returns {"status" "done"}}
"eldoc"
{:doc "Return a map of information about the specified symbol."
:requires {"symbol" "The symbol to lookup"
"ns" "The current namespace"}
:returns {"status" "done"}}
"eldoc-datomic-query"
{:doc "Return a map containing the inputs of the datomic query."
:requires {"symbol" "The symbol to lookup"
"ns" "The current namespace"}
:returns {"status" "done"}}}}))
@@ -5,7 +5,6 @@
[cider.nrepl.middleware.util.misc :as u]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.misc :refer [response-for]]
[clojure.tools.nrepl.middleware.pr-values :refer [pr-values]]
[clojure.tools.nrepl.transport :as transport])
(:import clojure.tools.nrepl.transport.Transport))

@@ -82,56 +81,14 @@
(try (success msg (swap-inspector! msg inspect/set-page-size (:page-size msg)))
(catch Exception e (failure msg e :inspect-set-page-size-error))))

(defn wrap-inspect
"Middleware that adds a value inspector option to the eval op. Passing a
non-nil value in the `:inspect` slot will cause the last value returned by
eval to be inspected. Returns a string representation of the resulting
inspector's state in the `:value` slot."
[handler]
(fn [{:keys [op] :as msg}]
(case op
"eval" (eval-reply handler msg)
"inspect-pop" (pop-reply msg)
"inspect-push" (push-reply msg)
"inspect-refresh" (refresh-reply msg)
"inspect-get-path" (get-path-reply msg)
"inspect-next-page" (next-page-reply msg)
"inspect-prev-page" (prev-page-reply msg)
"inspect-set-page-size" (set-page-size-reply msg)
(handler msg))))

(set-descriptor!
#'wrap-inspect
(cljs/expects-piggieback
{:requires #{"clone" #'pr-values}
:expects #{"eval"}
:handles {"inspect-pop"
{:doc "Moves one level up in the inspector stack."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-push"
{:doc "Inspects the inside value specified by index."
:requires {"idx" "Index of the internal value currently rendered."
"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-refresh"
{:doc "Re-renders the currently inspected value."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-get-path"
{:doc "Returns the path to the current position in the inspected value."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-next-page"
{:doc "Jumps to the next page in paginated collection view."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-prev-page"
{:doc "Jumps to the previous page in paginated collection view."
:requires {"session" "The current session"}
:returns {"status" "\"done\""}}
"inspect-set-page-size"
{:doc "Sets the page size in paginated view to specified value."
:requires {"page-size" "New page size."
"session" "The current session"}
:returns {"status" "\"done\""}}}}))
(defn handle-inspect [handler msg]
(case (:op msg)
"eval" (eval-reply handler msg)
"inspect-pop" (pop-reply msg)
"inspect-push" (push-reply msg)
"inspect-refresh" (refresh-reply msg)
"inspect-get-path" (get-path-reply msg)
"inspect-next-page" (next-page-reply msg)
"inspect-prev-page" (prev-page-reply msg)
"inspect-set-page-size" (set-page-size-reply msg)
(handler msg)))
@@ -6,9 +6,6 @@
[cider.nrepl.middleware.util.misc :as u]
[cljs-tooling.util.analysis :as cljs-ana]
[clojure.pprint :as pp]
[clojure.tools.nrepl.middleware :refer [set-descriptor!]]
[clojure.tools.nrepl.misc :refer [response-for]]
[clojure.tools.nrepl.middleware.session :as session]
[clojure.tools.reader :as reader]
[clojure.walk :as walk])
(:import [clojure.lang Var]))
@@ -221,22 +218,6 @@
(defn macroexpansion-reply [msg]
{:expansion (macroexpansion msg)})

(defn wrap-macroexpand
"Middleware that provides a macroexpand op."
[handler]
(with-safe-transport handler
(defn handle-macroexpand [handler msg]
(with-safe-transport handler msg
"macroexpand" [macroexpansion-reply :macroexpand-error]))

(set-descriptor!
#'wrap-macroexpand
(cljs/requires-piggieback
{:requires #{#'session/session}
:handles
{"macroexpand"
{:doc "Produces macroexpansion of some form using the given expander."
:requires {"code" "The form to macroexpand."}
:optional {"ns" "The namespace in which to perform the macroexpansion. Defaults to 'user for Clojure and 'cljs.user for ClojureScript."
"expander" "The macroexpansion function to use. Possible values are \"macroexpand-1\", \"macroexpand\", or \"macroexpand-all\". Defaults to \"macroexpand\"."
"display-namespaces" "How to print namespace-qualified symbols in the result. Possible values are \"qualified\" to leave all namespaces qualified, \"none\" to elide all namespaces, or \"tidy\" to replace namespaces with their aliases in the given namespace. Defaults to \"qualified\"."
"print-meta" "If truthy, also print metadata of forms."}
:returns {"expansion" "The macroexpanded form."}}}}))
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.