Fork me on GitHub
#cursive
<
2017-12-15
>
cfleming00:12:54

Hmm. Unfortunately you probably can’t. The issue is that the generated code has no line/col information in it, so you can’t associate the expansion with anywhere in the source code.

cfleming00:12:21

You can look at the expansion using the Cursive macroexpander, but that won’t help you with the exact location of the error within the expansion.

cfleming00:12:57

If that file generates a java class, doesn’t the NPE come from that class?

cfleming00:12:09

Or is the NPE in the macro itself?

cfleming00:12:53

Oh I see, it’s using gen-class.

kenny00:12:13

Getting this invokeNoArgInstanceMember at the top of the stack trace so I'm guessing it isn't generating a method for a call that someone else is expecting. The stacktrace just points to line 126 though.

cfleming00:12:23

Can you post the last couple of stacktrace lines? DM if you’d rather.

kenny00:12:42

Can't navigate to the source on the line selected because there is no source. Though, it may be useful to look at.

kenny00:12:02

Here's the textual version:

NullPointerException   clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:301)
                                          clojure.core/eval                       core.clj: 3206
                                                        ...                                     
                                         dev.user/eval48615                      REPL Input     
            compute.memcached.session-store/memcached-store              session_store.clj:   16
                   compute.memcached.core/binary-connection                       core.clj:   32
                clojurewerkz.spyglass.client/bin-connection                     client.clj:   95
                   net.spy.memcached.MemcachedClient.<init>           MemcachedClient.java:  209
net.spy.memcached.DefaultConnectionFactory.createConnection  DefaultConnectionFactory.java:  209
               net.spy.memcached.MemcachedConnection.<init>       MemcachedConnection.java:  282
    net.spy.memcached.MemcachedConnection.createConnections       MemcachedConnection.java:  345
                       AbstractLogger.java:  161
                       AbstractLogger.java:  150
               net.spy.memcached.compat.log.Log4JLogger.log               Log4JLogger.java:   99
                              org.apache.log4j.Category.log                  Category.java:  297
                org.apache.log4j.Category.differentiatedLog                  Category.java:  193
   com.github.fzakaria.slf4j.timbre.TimbreLoggerAdapter.log                                     
                                                        ...                                     
                                    slf4j-timbre.adapter/fn                    adapter.clj:  126
                                                        ...                                     
java.lang.NullPointerException: 

cfleming00:12:44

That’s pretty nasty.

kenny00:12:12

Ha. Indeed.

cfleming00:12:12

At a guess, looking at invokeNoArgInstanceMember, I’d say the target is null because it calls target.getClass().

cfleming00:12:41

So in some interop call within the expansion, the receiver is null.

cfleming00:12:30

So - this# or caller#

kenny00:12:51

No idea who's passing that in though. I can actually walk the calls to get to that null though. I forget the method someone was trying to call on it but it's probably useful.

cfleming00:12:34

Actually, you should be able to put an exception breakpoint on NPE.

kenny00:12:45

The class?

cfleming00:12:47

Reproduce the problem, and the debugger will stop you in invokeNoArg….

cfleming00:12:55

No, one sec.

cfleming00:12:36

Open breakpoints, hit +, select Java Exception Breakpoint, then search for NPE

cfleming00:12:48

Then the debugger will break whenever one is thrown.

cfleming00:12:15

That will stop you in invokeNoArgInstanceMember, and you can see what is null, and hopefully based on the other params you might get an idea.

kenny00:12:19

How do I open breakpoints? I usually just ctrl+shift+n for the file I want and add one in.

cfleming00:12:31

Are you debugging right now?

kenny00:12:50

Found it 🙂

cfleming00:12:52

Shift-Cmd-F8

cfleming00:12:00

Or the icon with …. right

cfleming00:12:13

Seriously, exception breakpoints are the best thing ever

cfleming00:12:25

95% of my debugging starts with them.

kenny00:12:54

BTW is there a way to skip through all the frames to get back into the REPL?

cfleming00:12:11

F9 will start running again

cfleming00:12:14

Is that what you mean?

kenny00:12:01

Kinda. Except I may need to hit F9 ten times to get back to the REPL.

cfleming00:12:14

Yeah, unfortunately.

kenny00:12:48

That helps! I at least get to see that nasty generated class.

cfleming00:12:08

Right, and you might be able to figure out what’s going on.

kenny00:12:42

might... 🙃

cfleming00:12:16

Well, your odds are some number greater than zero.

kenny00:12:37

Thanks to this awesome debugger!

cfleming00:12:04

Sometimes it’s a lifesaver, for sure.

kenny00:12:51

Any way to see values of vars defined in a method in this generated class?

cfleming00:12:01

When you’re paused at the breakpoint, you can use Evaluate Expression

cfleming00:12:33

You’re in Java, so you probably want var7.get()

kenny00:12:49

It doesn't appear to be at the right scope. All the vars except var7 are available.

kenny00:12:23

Well.. No vars defined within the method are available.

cfleming00:12:33

Which line are you paused at there - var7 is a local

kenny00:12:55

Looks like it's paused at the method definition line.

kenny00:12:03

public void...

cfleming00:12:22

Ok, you’ll need to step a bit until var7 is in scope

kenny00:12:46

Stepping takes me elsewhere.

kenny00:12:10

This method only exists in the stack once.

cfleming00:12:01

I suspect it’s getting confused. What you’re looking at there is the decompilation of a gen-class’ed class. It’s possible that the generated bytecode doesn’t have accurate line information.

cfleming00:12:18

Right, it has a line number of -1

cfleming00:12:42

So all the debugger knows is that you’re in there somewhere.

kenny00:12:57

And there's no way to step inside of the method to test things out?

cfleming00:12:09

Can you get the value of log__var in Evaluate Expression?

cfleming00:12:38

Ok, then you can calculate the value that var7 will have yourself

kenny00:12:01

Right. Seems handy to be able to step inside though. I don't know the technical limitation there though.

cfleming00:12:23

The issue is that I suspect the bytecode generated for that method has no line number information.

cfleming00:12:44

Without that, the debugger can’t map back from the bytecode it’s currently executing to the source.

kenny00:12:14

Makes sense. It does seem like because this class is statically generated, there could be more help there. That also probably means more work for a niche use-case.

cfleming00:12:34

I suspect this is a limitation of how gen-class works.

kenny00:12:24

Could probably create some hackery to generate the class and then include that class in the JAR.

cfleming00:12:26

That’s also why the variables are named var1, var2 etc

cfleming00:12:49

The thing is, it’s not generating Java source, it’s generating bytecode directly.

kenny00:12:02

generate class, decompile, include? 🙂

cfleming00:12:08

If it were generating Java source, you’d get to debug that.

cfleming00:12:24

yeah, that would work 🙂

kenny00:12:38

At least gives you line numbers. But that's a lot of work.

cfleming00:12:20

You could save the generated class as a .java file, compile that and then put the .class at the front of the classpath so your version is loaded over the gen-classed one.

cfleming00:12:52

But it’s probably easier to just muddle around with what you have to be honest.

kenny00:12:06

Totally. Fortunately this generated method is small and that's more work than just figuring out the values on my own.

cfleming00:12:36

I’m not sure why that method has no debug info though. It seems like it should point to inside the syntax-quoted block of define-log-method

cfleming00:12:59

There’s a bytecode viewer plugin you could use if you’re feeling curious 🙂

kenny00:12:54

What would the bytecode viewer plugin tell me? Why there's no line number?

cfleming00:12:38

No, it would just confirm that there are none. You probably need bronsa or someone over in #clojure-dev to help with the why.

cfleming00:12:08

That’s way outside my knowledge of how multiple levels of macroexpansion interact with the compiler’s line number generation.

kenny00:12:05

Gotcha. I'd like to figure out this lovely error before delving down a rabbit hole 🙂

cfleming00:12:26

I suspect that one is a very hairy yak, too.

kenny00:12:45

The most interesting kind 😉

cfleming00:12:58

Haha, yes indeed.

kenny00:12:42

You know what'd be cool? A way to test changes to 3rd party sources inline.

cfleming00:12:15

How would that work?

cfleming00:12:47

Emacs actually allows you to edit the sources of libs and load them, which I would like to support.

cfleming00:12:59

I haven’t figured out how to support that yet though.

kenny00:12:38

Oh really? That seems quite useful. I'd imagine it by simply allowing edits in a library source (the yellow tabs). The tricky part would be making sure that edit is temporary.

kenny00:12:51

For example, I want to go into that adapter.clj file, edit a line, and see if that fixes my issue. To do that right now I have to clone the project, edit the line, bump the version number, install the jar, restart the REPL, then test.

kenny01:12:15

Back to the debugger.. Is there a way to save a var from one view and use it in another view?

cfleming01:12:17

How do you mean? Between which views?

Sebastian11:12:17

Hi, I'm trying Cursive right now and I wonder if there is integration for Vagrant. My dev setup usually involves a Vagrant vm which contains the jdk, leiningen, database, ... I was able to set up PyCharm and PHPStorm in a way that they used the Vagrant vm for executing code, running the debugger, doing package managing, which was very nice. Is this doable with Cursive as well?

mbjarland15:12:44

a question on debugging clojure clode in cursive. I would like to do a "step into" or "step over" per form and see them execute and highlight like they do in the following gif from cider: https://i.stack.imgur.com/wHaYC.gif maybe I just haven't figured cursive out, but it seems to me you can only debug on a 'per line' basis there which is not necessarily what you want in clojure. Is this true or am I just missing something?

mbjarland15:12:36

and while I'm here : ) is there a way to create a global execution configuration for "lein repl". I find that I do a lot of small projects and every single time I go and create a new execution configuration with the exact same choices checked

mbjarland15:12:02

yeah I'm aware of that checkbox, it's just that it doesn't seem to do what I would want it to do

mbjarland15:12:23

i.e. I check it in one project, open a new one and the configurations are still blank

mbjarland15:12:53

ah, you have to manually copy the runConfigurations file to your new project...

mbjarland15:12:36

not sure which is less painful, opening the dialog every time or switching to a terminal to locate and copy a file from some old project

manutter5115:12:07

Yeah, IntelliJ didn’t go out of their way to make that easy

kenny19:12:34

Had to run last night. The views I was talking about was each frame in the debugger.

lgouger19:12:48

found this on the Intellij discussions site : "If you enable Share checkbox in the run configuration panel it would be saved to .idea/runConfiguraions folder."

lgouger19:12:13

I guess I'm repeating what's already been shared. Nothing to see here, move along...

lgouger20:12:34

Added a request to an old Cursive-IDE issue #401 >>>I think this related, so commenting here rather than adding a new issue. Under Structural Editing, there are "Move Forward" and "Move Backward" actions, I'm requesting "Move Forward with Selection" and "Move Backward with Selection" be added as assignable actions. I currently have <option>-<right-arrow> assigned to the "Move Forward" action and I'd like a SHIFT variant <shift>-<option>-<right-arrow> to make the same movement while also extending the selection.

briantrice22:12:45

I’m having trouble searching https://github.com/cursive-ide/cursive/issues for what I’m looking for so Q: is Cursive interested in docstring or metadata support for referring to other namespaces or functions that are not directly required? Say, for CLJ/CLJS dependencies not formalizable as CLJC.