16
16
17
17
package org .intellij .erlang .debugger .xdebug ;
18
18
19
+ import com .ericsson .otp .erlang .OtpErlangAtom ;
19
20
import com .ericsson .otp .erlang .OtpErlangObject ;
20
21
import com .ericsson .otp .erlang .OtpErlangPid ;
22
+ import com .ericsson .otp .erlang .OtpErlangTuple ;
21
23
import com .intellij .execution .ExecutionException ;
22
24
import com .intellij .execution .configurations .GeneralCommandLine ;
23
25
import com .intellij .execution .process .OSProcessHandler ;
72
74
import static org .intellij .erlang .debugger .ErlangDebuggerLog .LOG ;
73
75
74
76
public class ErlangXDebugProcess extends XDebugProcess implements ErlangDebuggerEventListener {
75
- private final XDebugSession mySession ;
76
77
private final ExecutionEnvironment myExecutionEnvironment ;
77
78
private final ErlangRunningState myRunningState ;
78
79
private final ErlangDebuggerNode myDebuggerNode ;
@@ -83,11 +84,16 @@ public class ErlangXDebugProcess extends XDebugProcess implements ErlangDebugger
83
84
private ConcurrentHashMap <ErlangSourcePosition , XLineBreakpoint <ErlangLineBreakpointProperties >> myPositionToLineBreakpointMap =
84
85
new ConcurrentHashMap <>();
85
86
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 ;
86
93
87
94
public ErlangXDebugProcess (@ NotNull XDebugSession session , ExecutionEnvironment env ) throws ExecutionException {
88
95
//TODO add debug build targets and make sure the project is built using them.
89
96
super (session );
90
- mySession = session ;
91
97
92
98
session .setPauseActionSupported (false );
93
99
@@ -124,17 +130,36 @@ public ErlangDebugLocationResolver getLocationResolver() {
124
130
public synchronized void evaluateExpression (@ NotNull String expression ,
125
131
@ NotNull XDebuggerEvaluator .XEvaluationCallback callback ,
126
132
@ NotNull ErlangTraceElement traceElement ) {
127
- // need to pause the debugging session otherwise the callback might get invalidated
128
- mySession .pause ();
129
133
myEvalCallback = callback ;
134
+ // see the comment about ignoreNextBreakpointReachedEvent
135
+ ignoreNextBreakpointReachedEvent = true ;
130
136
myDebuggerNode .evaluate (expression , traceElement );
131
137
}
132
138
133
139
@ Override
134
140
public synchronized void handleEvaluationResponse (OtpErlangObject response ) {
135
141
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
+ }
138
163
}
139
164
}
140
165
@@ -178,6 +203,12 @@ public void breakpointIsSet(String module, int line) {
178
203
179
204
@ Override
180
205
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
+
181
212
ErlangProcessSnapshot processInBreakpoint = ContainerUtil .find (snapshots , erlangProcessSnapshot -> erlangProcessSnapshot .getPid ().equals (pid ));
182
213
assert processInBreakpoint != null ;
183
214
ErlangSourcePosition breakPosition = ErlangSourcePosition .create (myLocationResolver , processInBreakpoint );
0 commit comments