BetterThanTomorrow / calva

Clojure & ClojureScript Interactive Programming for VS Code
https://marketplace.visualstudio.com/items?itemName=betterthantomorrow.calva
Other
1.68k stars 217 forks source link

Go-to-definition: How does jack-in get middleware working for legacy figwheel & sidecar with tools.nrepl on the classpath? #1851

Open Lambeaux opened 2 years ago

Lambeaux commented 2 years ago

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:

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:

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 {}}})
PEZ commented 2 years ago

Hello. It is a bit of a mystery to me how Leiningen treats:

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:

  1. Start your REPL using using the command that Calva jack-in uses.
  2. 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)
  3. Try with removing all nrepl/cider dependencies from the project
  4. 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

Lambeaux commented 2 years ago

Appreciate your response. I'll try that. I'll report back with findings.