calva
calva copied to clipboard
Go-to-definition: How does jack-in get middleware working for legacy figwheel & sidecar with tools.nrepl on the classpath?
Gosh, I might have gone too deep down the rabbit hole this time...
I reviewed some similar issues found here: https://github.com/BetterThanTomorrow/calva/issues?q=is%3Aissue+is%3Aopen+go+to+definition - there are similarities but none of them really get at the heart of what I'm looking for. I also reviewed the docs, such as:
- https://calva.io/jack-in-guide/
- https://calva.io/clojure-lsp/
- https://calva.io/nrepl_and_cider-nrepl/
I'm working on a Leiningen project that leverages legacy figwheel and figwheel-sidecar. Clojure LSP and go-to-definition work wonderfully ... until I start the REPL. Once I do that, I can no longer click symbols to jump around the codebase and into dependencies. Some info:
- I'm opening the project from the root directory that has the
project.clj
. - I'm starting
lein repl
andnode
myself and connecting to them remotely usingConnect to a running REPL server in the project
command, and picking theLeiningen + Legacy Figwheel
option. - The problem occurs regardless of the port that nREPL picks for me.
Important note: If I use Calva's "jack-in" feature with Leiningen + Legacy Figwheel, the problem goes away. I have a useable REPL and Clojure LSP seems to be working normally. But if I try to reproduce the parameters for jacking in ...
lein update-in :dependencies conj '[nrepl,"1.0.0"]' -- update-in :dependencies conj '[cider/piggieback,"0.5.3"]' -- update-in :plugins conj '[cider/cider-nrepl,"0.28.5"]' -- update-in '[:repl-options,:nrepl-middleware]' conj '["cider.nrepl/cider-middleware"]' -- update-in '[:repl-options,:nrepl-middleware]' conj '["cider.piggieback/wrap-cljs-repl"]' -- repl :headless
nREPL server started on port 55552 on host 127.0.0.1 - nrepl://127.0.0.1:55552
... manually within my ~/.lein/profiles.clj
...
{:user {:plugins [[lein-pprint "1.3.2"]
[cider/cider-nrepl "0.28.5"]
[lein-hiera "1.1.0"]
[ns-graph "0.1.4"]
[lein-nomis-ns-graph "0.14.6"]]
:repl-options {:nrepl-middleware [cider.nrepl/cider-middleware
cider.piggieback/wrap-cljs-repl]}
:dependencies [[nrepl "1.0.0"]
[cider/piggieback "0.5.3"]
[org.clojure/tools.namespace "1.1.0"]
[djblue/portal "0.26.0"]]
:source-paths ["~/.lein/scripts"]}}
... and try to run the REPL myself, I get an error:
$ lein repl
[WARNING] No nREPL middleware descriptor in metadata of #'cider.nrepl/cider-middleware, see nrepl.middleware/set-descriptor!
Exception in thread "main" java.lang.IllegalArgumentException: Key must be integer, compiling:(/private/var/folders/j5/y9rm9r1j6plf55zsjgzwpyzm4qs72j/T/form-init8340597151867786306.clj:1:125)
This seems to be incompatible middleware, as noted here: https://nrepl.org/nrepl/troubleshooting.html#warnings-when-starting-nrepl - as expected, we've got a dependency pulling in something problematic:
$ lein deps :why org.clojure/tools.nrepl
[figwheel-sidecar 0.5.18]
[org.clojure/tools.nrepl 0.2.13]
How does Calva make this work for jacking-in? I've tried messing with the versions of the various dependencies in my profiles.clj
but I can't find a dependency version combo that works.
Here is a sample, partially redacted project.clj that closely mirrors the one I'm using for my project.
(defproject repo-name "0.1.19-SNAPSHOT"
:dependencies [[org.clojure/clojure "1.9.0"]
[org.clojure/clojurescript "1.10.520"]
[org.clojure/core.async "1.3.610"]
[io.nervous/cljs-lambda "0.3.5"]
[funcool/httpurr "1.1.0"]
[cljs-node-io "1.0.0"]
[honeysql "0.9.3"]
[camel-snake-kebab "0.4.1"]]
:plugins [[lein-npm "0.6.2"]
[lein-shell "0.5.0"]
[io.nervous/lein-cljs-lambda "0.6.6"]
[org.bodil/lein-noderepl "0.1.11"]
[lein-cljsbuild "1.1.7"]
[lein-figwheel "0.5.16"]
[s3-wagon-private/s3-wagon-private "1.3.5" :exclusions [commons-logging
commons-codec]]
[lein-cljfmt "0.8.0"]
[lein-nsorg "0.3.0"]
[lein-check-namespace-decls "1.0.2"]]
:cljfmt { ... }
:check-namespace-decls {:source-paths ["src" "test" "dev"]}
:repositories [ ... ]
:npm {:dependencies [[fast-json-patch "2.0.6"]
[aws-sdk "2.382.0"]
[ioredis "4.0.0"]
[redlock "3.1.2"]
[jsonwebtoken "8.3.0"]
[pg "7.4.3"]]
:devDependencies [[serverless-cljs-plugin "0.1.2"]
[serverless-apigw-binary "0.4.4"]
[ws "6.0.0"]]}
:cljs-lambda {:cljs-build-id "repo-name"}
:doo {:build "test-doo"
:alias {:default [:node]}}
:cljsbuild {:builds [{:id "development"
:source-paths ["src" "dev"]
:figwheel true
:compiler
{:main repo-name.repl
:output-to "target/fig-dev/dev.js"
:output-dir "target/fig"
:target :nodejs
:language-in :ecmascript5
:optimizations :none}}
{:id "repo-name"
:source-paths ["src"]
:compiler
{:output-to "target/repo-name/repo-name.js"
:output-dir "target/repo-name"
:target :nodejs
:language-in :ecmascript5
:optimizations :simple}}
{:id "test-doo"
:source-paths ["src" "test"]
:compiler {:main repo-name.runner
:output-to "target/doo/test.js"
:output-dir "target/doo/out"
:target :nodejs
:language-in :ecmascript5
:optimizations :none}}]}
:release-tasks [ ... ]
:aliases { ... }
:profiles {:dev {:dependencies [[cider/piggieback "0.4.0"]
[figwheel-sidecar "0.5.18"]
[lein-doo "0.1.10"]
[org.clojure/test.check "0.10.0-alpha3"]]
:plugins [[lein-doo "0.1.10"]]
:source-paths ["dev" "src"]
:repl-options {:nrepl-middleware [cider.piggieback/wrap-cljs-repl]}
:figwheel {}}})
Hello. It is a bit of a mystery to me how Leiningen treats:
- command line provided configuration
- configuration provided in the user profile
- configuration provided in the project
Maybe this is a situation where providing the configuration via the command line works in one way, and providing them in the user profile works in some other way.
I would try some different things:
- Start your REPL using using the command that Calva jack-in uses.
- Try with a user profile that only has the configuration that Calva jack-in provides (removing the possibility that some other of the config you have there trips things up)
- Try with removing all nrepl/cider dependencies from the project
- Try all the above with a minimal lein-figwheel project
Probably the first option there will work, because that is what Calva jack-in uses and you have confirmed it works. But if you want to be able to start it using only lein repl
, then the other experiments might shed some light.
I have as similar mystery with providing shadow-cljs middleware via the command line. Although in that mystery it is the other way around: providing the middleware configuration via the command line does not work. Providing it in the project works: https://codeberg.org/leiningen/leiningen/issues/10
Appreciate your response. I'll try that. I'll report back with findings.