1616
1717package org .intellij .erlang .debugger .xdebug ;
1818
19+ import com .ericsson .otp .erlang .OtpErlangAtom ;
1920import com .ericsson .otp .erlang .OtpErlangObject ;
2021import com .ericsson .otp .erlang .OtpErlangPid ;
22+ import com .ericsson .otp .erlang .OtpErlangTuple ;
2123import com .intellij .execution .ExecutionException ;
2224import com .intellij .execution .configurations .GeneralCommandLine ;
2325import com .intellij .execution .process .OSProcessHandler ;
7274import static org .intellij .erlang .debugger .ErlangDebuggerLog .LOG ;
7375
7476public class ErlangXDebugProcess extends XDebugProcess implements ErlangDebuggerEventListener {
75- private final XDebugSession mySession ;
7677 private final ExecutionEnvironment myExecutionEnvironment ;
7778 private final ErlangRunningState myRunningState ;
7879 private final ErlangDebuggerNode myDebuggerNode ;
@@ -83,11 +84,16 @@ public class ErlangXDebugProcess extends XDebugProcess implements ErlangDebugger
8384 private ConcurrentHashMap <ErlangSourcePosition , XLineBreakpoint <ErlangLineBreakpointProperties >> myPositionToLineBreakpointMap =
8485 new ConcurrentHashMap <>();
8586 private XDebuggerEvaluator .XEvaluationCallback myEvalCallback = null ;
87+ // right after evaluating an expression, the erlang debugger will trigger a new "breakpoint reached" event
88+ // unfortunately, that means this plugin will try to concurrently render the new state of the bindings as
89+ // well as the result from the evaluation, which Intellij doesn't seem to handle too well, resulting in
90+ // the debugging session losing track of what the current frame is... so we just ignore the next "breakpoint
91+ // reached" event right after evaluating an expression - better ideas welcome!
92+ private boolean ignoreNextBreakpointReachedEvent = false ;
8693
8794 public ErlangXDebugProcess (@ NotNull XDebugSession session , ExecutionEnvironment env ) throws ExecutionException {
8895 //TODO add debug build targets and make sure the project is built using them.
8996 super (session );
90- mySession = session ;
9197
9298 session .setPauseActionSupported (false );
9399
@@ -124,17 +130,36 @@ public ErlangDebugLocationResolver getLocationResolver() {
124130 public synchronized void evaluateExpression (@ NotNull String expression ,
125131 @ NotNull XDebuggerEvaluator .XEvaluationCallback callback ,
126132 @ NotNull ErlangTraceElement traceElement ) {
127- // need to pause the debugging session otherwise the callback might get invalidated
128- mySession .pause ();
129133 myEvalCallback = callback ;
134+ // see the comment about ignoreNextBreakpointReachedEvent
135+ ignoreNextBreakpointReachedEvent = true ;
130136 myDebuggerNode .evaluate (expression , traceElement );
131137 }
132138
133139 @ Override
134140 public synchronized void handleEvaluationResponse (OtpErlangObject response ) {
135141 if (myEvalCallback != null ) {
136- myEvalCallback .evaluated (ErlangXValueFactory .create (response ));
137- mySession .resume ();
142+ String error = null ;
143+
144+ if (response instanceof OtpErlangAtom && ((OtpErlangAtom ) response ).atomValue ().equals ("Parse error" )) {
145+ // it is a parsing error
146+ error = "Parse error" ;
147+ } else if (response instanceof OtpErlangTuple ) {
148+ OtpErlangObject [] elements = ((OtpErlangTuple ) response ).elements ();
149+
150+ // is it an uncaught exception?
151+ if (elements .length == 2
152+ && elements [0 ] instanceof OtpErlangAtom
153+ && ((OtpErlangAtom ) elements [0 ]).atomValue ().equals ("EXIT" )) {
154+ error = "Uncaught exception: " + elements [1 ];
155+ }
156+ }
157+
158+ if (error == null ) {
159+ myEvalCallback .evaluated (ErlangXValueFactory .create (response ));
160+ } else {
161+ myEvalCallback .errorOccurred (error );
162+ }
138163 }
139164 }
140165
@@ -178,6 +203,12 @@ public void breakpointIsSet(String module, int line) {
178203
179204 @ Override
180205 public void breakpointReached (final OtpErlangPid pid , List <ErlangProcessSnapshot > snapshots ) {
206+ if (ignoreNextBreakpointReachedEvent ) {
207+ // see the comment about ignoreNextBreakpointReachedEvent
208+ ignoreNextBreakpointReachedEvent = false ;
209+ return ;
210+ }
211+
181212 ErlangProcessSnapshot processInBreakpoint = ContainerUtil .find (snapshots , erlangProcessSnapshot -> erlangProcessSnapshot .getPid ().equals (pid ));
182213 assert processInBreakpoint != null ;
183214 ErlangSourcePosition breakPosition = ErlangSourcePosition .create (myLocationResolver , processInBreakpoint );
0 commit comments