nrepl/piggieback

Stacktrace support

mfikes opened this issue · 20 comments

Stacktrace support has recently improved for REPLs (especially with respect to source mapping).

For Ambly standalone, for example:

ClojureScript:cljs.user> (ffirst 1)
Error: 1 is not ISeqable
    cljs.core/seq (cljs/core.cljs:951:20)
    cljs.core/first (cljs/core.cljs:960:16)
    cljs$core$ffirst (cljs/core.cljs:1393:11)
    (NO_SOURCE_FILE)

For Ambly on Piggieback, I get no output for lein repl:

cljs.user=> (ffirst 1)

cljs.user=> 

And in Cursive, I get:

(ffirst 1)
=> Error: 1 is not ISeqable
=> cljs$core$seq@file:///cljs/core.js:4667:17
cljs$core$first@file:///cljs/core.js:4697:22
cljs$core$ffirst@file:///cljs/core.js:5774:39


global code

Yeah, I see the same in cider as you do in Cursive. Not sure what to say about Leiningen, something's quite off there.

I don't have any immediate thoughts on what the issue is here. Just in case there are key options that piggieback wasn't setting (or causing to be set), I took out its creation of a compiler environment entirely (it now captures the one cljs.repl/repl* creates by default, which should be exactly equivalent to the usage in the quick start). But, no good stack traces. Here's what I'm seeing for options:

{:print-no-newline #<core$print clojure.core$print@51bcd9d0>,
 :output-dir ".cljs_nashorn_repl",
 :flush
 #<piggieback$run_cljs_repl$flush__7350 cemerick.piggieback$run_cljs_repl$flush__7350@7fced177>,
 :compiler-env nil,
 :read #<repl$repl_read cljs.repl$repl_read@fdf1f8b>,
 :ups-libs nil,
 :init
 #<piggieback$run_cljs_repl$fn__7352 cemerick.piggieback$run_cljs_repl$fn__7352@2f64b9d4>,
 :cache-analysis true,
 :optimizations :none,
 :ups-foreign-libs nil,
 :bind-err false,
 :print
 #<piggieback$run_cljs_repl$fn__7354 cemerick.piggieback$run_cljs_repl$fn__7354@537eded8>,
 :source-map-inline true,
 :prompt
 #<piggieback$run_cljs_repl$fn__7359 cemerick.piggieback$run_cljs_repl$fn__7359@2ce7f660>,
 :preamble ["cljs/imul.js"],
 :ups-externs nil,
 :reader
 #<repl$repl_STAR_$fn__5178 cljs.repl$repl_STAR_$fn__5178@7c19e30f>,
 :source-map true,
 :need-prompt
 #<core$constantly$fn__4085 clojure.core$constantly$fn__4085@24c52711>,
 :caught
 #<piggieback$run_cljs_repl$fn__7361 cemerick.piggieback$run_cljs_repl$fn__7361@6b8a10fa>,
 :quit-prompt
 #<piggieback$run_cljs_repl$fn__7363 cemerick.piggieback$run_cljs_repl$fn__7363@5414fa8c>}

…which seems sane, but then I'm not an expert on ClojureScript compiler options. :-P FWIW, piggieback relies on all the defaults for rendering of errors, etc. Happy for a clue.

For Ambly on Piggieback, I get no output for lein repl:

I'm seeing something similar - the exception does print if I try and eval something after this (even just pressing enter with no input).

@cichli this is probably related to :print-no-newline issue discussed elsewhere. The REPLs are using :print to print errors. I'm happy to change this so that :print is only used the expected way.

Nope, I got it; the delegating REPL env needs to satisfy IParseStackTrace et al. I didn't notice those before.

@cemerick you also need to implement IGetError and IParseError and check that the REPL you are wrapping doesn't implement it and invoke if they do etc.

@swannodette Yeah, not hard, but I'll have to be a little clever. Need one delegating REPL env type per "real" REPL env type so the satisfies? checks are equivalent.

So, the above commit works in terms of making sure the delegating REPL environment(s) stay true to the "real" ones w.r.t. satisfies?. And, this yields proper source-mapped stack traces, except for the arity error where cljs.repl is still calling the :print fn with multiple args, not related to evaluation results. I assume those calls are oversights at this point…

@cemerick ok will fix in ClojureScript master and cut a new release for people to try.

0.0-3153 going to central

With 0.0-3153, and with revisions to Ambly to avoid :print (which is done in cljs.repl in the one right place), I now get proper results:

Plain lein repl:

cljs.user=> (ffirst 1)

Error: 1 is not ISeqable
cljs$core$seq@file:///cljs/core.js:4667:17
cljs$core$first@file:///cljs/core.js:4697:22
cljs$core$ffirst@file:///cljs/core.js:5774:39


global code
cljs.user=>

Cursive:

(ffirst 1)
Error: 1 is not ISeqable
cljs$core$seq@file:///cljs/core.js:4667:17
cljs$core$first@file:///cljs/core.js:4697:22
cljs$core$ffirst@file:///cljs/core.js:5774:39


global code

I suppose that Piggieback could delegate to Ambly to parse and print stacktraces, which would lead to source mapping, etc.

@mfikes it seems @cemerick's commit should be delegating but perhaps for some reason it isn't?

@swannodette Yes. So, I cloned @cemerick 's new-cljs-repl, branch did a lein install, and that fixed it (perhaps a SNAPSHOT hasn't yet been pushed out):

lein repl

cljs.user=> (ffirst 1)

Error: 1 is not ISeqable
    cljs.core/seq (cljs/core.cljs:951:20)
    cljs.core/first (cljs/core.cljs:960:16)
    cljs$core$ffirst (cljs/core.cljs:1393:11)
    (NO_SOURCE_FILE)
cljs.user=>

Cursive:

(ffirst 1)
Error: 1 is not ISeqable
    cljs.core/seq (cljs/core.cljs:951:20)
    cljs.core/first (cljs/core.cljs:960:16)
    cljs$core$ffirst (cljs/core.cljs:1393:11)
    (NO_SOURCE_FILE)

No, I haven't cut a new snapshot yet. Was waiting for the upstream change, and want to tweak and clean up a few things first.

BTW, if anyone has any better ideas as to how to do the dynamic delegating type thing I recently committed, do let me know. It's basically a super-hacky, single purpose 'specify', which I'm not so thrilled with, but I don't have any better thoughts at the moment.

On March 25, 2015 5:20:59 PM EDT, Mike Fikes notifications@github.com wrote:

@swannodette Yes. So, I cloned @cemerick 's new-cljs-repl, branch did
a lein install, and that fixed it (perhaps a SNAPSHOT hasn't yet
been pushed out):

lein repl

cljs.user=> (ffirst 1)

Error: 1 is not ISeqable
  cljs.core/seq (cljs/core.cljs:951:20)
  cljs.core/first (cljs/core.cljs:960:16)
  cljs$core$ffirst (cljs/core.cljs:1393:11)
  (NO_SOURCE_FILE)
cljs.user=>

Cursive:

(ffirst 1)
Error: 1 is not ISeqable
  cljs.core/seq (cljs/core.cljs:951:20)
  cljs.core/first (cljs/core.cljs:960:16)
  cljs$core$ffirst (cljs/core.cljs:1393:11)
  (NO_SOURCE_FILE)

Reply to this email directly or view it on GitHub:
#55 (comment)

@cemerick no better ideas, that approach seems acceptable to me at the moment.

A new 0.2.0-SNAPSHOT is pushed now (and now requires nREPL 0.2.10, BTW…people will need to update that separately in their Leiningen :dev profile dependencies, as lein overrides any transitive or even "regular" nREPL dependency with its own default). Stack trace printing looks good for the environments that support the necessary protocols (using nashorn as the barometer here at the moment).

I can confirm that stack traces map and print properly in Ambly with Piggieback with the new SNAPSHOT and nREPL deps.

For the record, here is lein repl pulling down the new deps for me:

$ lein repl
(Retrieving com/cemerick/piggieback/0.2.0-SNAPSHOT/piggieback-0.2.0-20150326.112335-8.pom from clojars)
(Retrieving org/clojure/tools.nrepl/0.2.10/tools.nrepl-0.2.10.pom from central)
(Retrieving com/cemerick/piggieback/0.2.0-SNAPSHOT/piggieback-0.2.0-20150326.112335-8.jar from clojars)
(Retrieving org/clojure/tools.nrepl/0.2.10/tools.nrepl-0.2.10.jar from central)

@mfikes is that without you having an explicit :dev nREPL dependency?

And, thank you for the confirmation, etc. Closing.

@cemerick No, I have explicitly added

:profiles {:dev {:dependencies [[org.clojure/tools.nrepl "0.2.10"]]}}

If I remove it (and blow away stuff from .m2 first), I get:

$ lein repl
(Retrieving com/cemerick/piggieback/0.2.0-SNAPSHOT/piggieback-0.2.0-20150326.112335-8.pom from clojars)
(Retrieving org/clojure/tools.nrepl/0.2.3/tools.nrepl-0.2.3.pom from central)
(Retrieving com/cemerick/piggieback/0.2.0-SNAPSHOT/piggieback-0.2.0-20150326.112335-8.jar from clojars)
(Retrieving org/clojure/tools.nrepl/0.2.3/tools.nrepl-0.2.3.jar from central)
Error loading cemerick.piggieback: java.lang.IllegalStateException: var: #'clojure.tools.nrepl.middleware.interruptible-eval/queue-eval is not public, compiling:(cemerick/piggieback.clj:239:3)
Exception in thread "main" java.lang.RuntimeException: Unable to resolve var: cemerick.piggieback/wrap-cljs-repl in this context, compiling:(/private/var/folders/nm/97bx7f_n31z2t2g_gf2bn90w0h013l/T/form-init4239323351502141250.clj:1:1194)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6651)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.analyze(Compiler.java:6406)
    at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.analyze(Compiler.java:6406)
    at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:3719)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6646)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.access$100(Compiler.java:38)
    at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:6050)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.analyze(Compiler.java:6406)
    at clojure.lang.Compiler$BodyExpr$Parser.parse(Compiler.java:5782)
    at clojure.lang.Compiler$FnMethod.parse(Compiler.java:5217)
    at clojure.lang.Compiler$FnExpr.parse(Compiler.java:3846)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6642)
    at clojure.lang.Compiler.analyze(Compiler.java:6445)
    at clojure.lang.Compiler.eval(Compiler.java:6700)
    at clojure.lang.Compiler.eval(Compiler.java:6693)
    at clojure.lang.Compiler.load(Compiler.java:7130)
    at clojure.lang.Compiler.loadFile(Compiler.java:7086)
    at clojure.main$load_script.invoke(main.clj:274)
    at clojure.main$init_opt.invoke(main.clj:279)
    at clojure.main$initialize.invoke(main.clj:307)
    at clojure.main$null_opt.invoke(main.clj:342)
    at clojure.main$main.doInvoke(main.clj:420)
    at clojure.lang.RestFn.invoke(RestFn.java:421)
    at clojure.lang.Var.invoke(Var.java:383)
    at clojure.lang.AFn.applyToHelper(AFn.java:156)
    at clojure.lang.Var.applyTo(Var.java:700)
    at clojure.main.main(main.java:37)
Caused by: java.lang.RuntimeException: Unable to resolve var: cemerick.piggieback/wrap-cljs-repl in this context
    at clojure.lang.Util.runtimeException(Util.java:221)
    at clojure.lang.Compiler$TheVarExpr$Parser.parse(Compiler.java:659)
    at clojure.lang.Compiler.analyzeSeq(Compiler.java:6644)
    ... 33 more

Ok, yeah. That's very unfortunate. Looks like this is an on-again, off-again problem in Leiningen, currently tracked @ technomancy/leiningen#1771.