public void addBreakpoint( @NotNull final String isolateId, @Nullable final XSourcePosition position, @NotNull final VmServiceConsumers.BreakpointConsumerWrapper consumer) { if (position == null || position.getFile().getFileType() != DartFileType.INSTANCE) { consumer.sourcePositionNotApplicable(); return; } addRequest( () -> { final int line = position.getLine() + 1; for (String uri : myDebugProcess.getUrisForFile(position.getFile())) { myVmService.addBreakpointWithScriptUri(isolateId, uri, line, consumer); } }); }
private void setInitialBreakpointsAndResume(@NotNull final IsolateRef isolateRef) { if (myDebugProcess.isRemoteDebug()) { if (myDebugProcess.myRemoteProjectRootUri == null) { // need to detect remote project root path before setting breakpoints getIsolate( isolateRef.getId(), new VmServiceConsumers.GetIsolateConsumerWrapper() { @Override public void received(final Isolate isolate) { myDebugProcess.guessRemoteProjectRoot(isolate.getLibraries()); doSetInitialBreakpointsAndResume(isolateRef); } }); } else { doSetInitialBreakpointsAndResume(isolateRef); } } else { doSetInitialBreakpointsAndResume(isolateRef); } }
@Nullable private String evaluateExpression( final @NotNull String isolateId, final @Nullable Frame vmTopFrame, final @Nullable XExpression xExpression) { final String evalText = xExpression == null ? null : xExpression.getExpression(); if (vmTopFrame == null || StringUtil.isEmptyOrSpaces(evalText)) return null; final Ref<String> evalResult = new Ref<>(); final Semaphore semaphore = new Semaphore(); semaphore.down(); myDebugProcess .getVmServiceWrapper() .evaluateInFrame( isolateId, vmTopFrame, evalText, new XDebuggerEvaluator.XEvaluationCallback() { @Override public void evaluated(@NotNull final XValue result) { if (result instanceof DartVmServiceValue) { evalResult.set( getSimpleStringPresentation(((DartVmServiceValue) result).getInstanceRef())); } semaphore.up(); } @Override public void errorOccurred(@NotNull final String errorMessage) { evalResult.set( "Failed to evaluate log expression [" + evalText + "]: " + errorMessage); semaphore.up(); } }, true); semaphore.waitFor(1000); return evalResult.get(); }
@Override public void received(@NotNull final String streamId, @NotNull final Event event) { switch (event.getKind()) { case BreakpointAdded: // TODO Respond to breakpoints added by the observatory. // myBreakpointHandler.vmBreakpointAdded(null, event.getIsolate().getId(), // event.getBreakpoint()); break; case BreakpointRemoved: break; case BreakpointResolved: myBreakpointHandler.breakpointResolved(event.getBreakpoint()); break; case Extension: break; case GC: break; case Inspect: break; case IsolateExit: myDebugProcess.isolateExit(event.getIsolate()); break; case IsolateRunnable: break; case IsolateStart: break; case IsolateUpdate: break; case None: break; case PauseBreakpoint: case PauseException: case PauseInterrupted: myDebugProcess.isolateSuspended(event.getIsolate()); ApplicationManager.getApplication() .executeOnPooledThread( () -> { final ElementList<Breakpoint> breakpoints = event.getKind() == EventKind.PauseBreakpoint ? event.getPauseBreakpoints() : null; final InstanceRef exception = event.getKind() == EventKind.PauseException ? event.getException() : null; onIsolatePaused( event.getIsolate(), breakpoints, exception, event.getTopFrame(), event.getAtAsyncSuspension()); }); break; case PausePostRequest: // We get this event after an isolate reload call, when pause after reload has been // requested. // TODO: Set current breakpoints; resume the isolate. myDebugProcess.getVmServiceWrapper().resumeIsolate(event.getIsolate().getId(), null); break; case PauseExit: break; case PauseStart: myDebugProcess.getVmServiceWrapper().handleIsolate(event.getIsolate(), true); break; case Resume: myDebugProcess.isolateResumed(event.getIsolate()); break; case ServiceExtensionAdded: break; case VMUpdate: break; case WriteEvent: myDebugProcess.handleWriteEvent(event.getBytes()); break; case Unknown: break; } }
void onIsolatePaused( @NotNull final IsolateRef isolateRef, @Nullable final ElementList<Breakpoint> vmBreakpoints, @Nullable final InstanceRef exception, @Nullable final Frame vmTopFrame, boolean atAsyncSuspension) { if (vmTopFrame == null) { myDebugProcess.getSession().positionReached(new XSuspendContext() {}); return; } final DartVmServiceSuspendContext suspendContext = new DartVmServiceSuspendContext( myDebugProcess, isolateRef, vmTopFrame, exception, atAsyncSuspension); final XStackFrame xTopFrame = suspendContext.getActiveExecutionStack().getTopFrame(); final XSourcePosition sourcePosition = xTopFrame == null ? null : xTopFrame.getSourcePosition(); if (vmBreakpoints == null || vmBreakpoints.isEmpty()) { final StepOption latestStep = myDebugProcess.getVmServiceWrapper().getLatestStep(); if (latestStep == StepOption.Over && equalSourcePositions(myLatestSourcePosition, sourcePosition)) { // continue stepping to change current line myDebugProcess.getVmServiceWrapper().resumeIsolate(isolateRef.getId(), latestStep); } else { myLatestSourcePosition = sourcePosition; myDebugProcess.getSession().positionReached(suspendContext); } } else { if (vmBreakpoints.size() > 1) { // Shouldn't happen. IDE doesn't allow to set 2 breakpoints on one line. LOG.error(vmBreakpoints.size() + " breakpoints hit in one shot."); } // Remove any temporary (run to cursor) breakpoints. myBreakpointHandler.removeTemporaryBreakpoints(isolateRef.getId()); final XLineBreakpoint<XBreakpointProperties> xBreakpoint = myBreakpointHandler.getXBreakpoint(vmBreakpoints.get(0)); if (xBreakpoint == null) { // breakpoint could be set in the Observatory myLatestSourcePosition = sourcePosition; myDebugProcess.getSession().positionReached(suspendContext); return; } if ("false" .equals( evaluateExpression( isolateRef.getId(), vmTopFrame, xBreakpoint.getConditionExpression()))) { myDebugProcess.getVmServiceWrapper().resumeIsolate(isolateRef.getId(), null); return; } myLatestSourcePosition = sourcePosition; final String logExpression = evaluateExpression(isolateRef.getId(), vmTopFrame, xBreakpoint.getLogExpressionObject()); final boolean suspend = myDebugProcess.getSession().breakpointReached(xBreakpoint, logExpression, suspendContext); if (!suspend) { myDebugProcess.getVmServiceWrapper().resumeIsolate(isolateRef.getId(), null); } } }
@Override public void connectionClosed() { if (myDebugProcess.isRemoteDebug()) { myDebugProcess.getSession().stop(); } }
public void handleDebuggerConnected() { streamListen( VmService.DEBUG_STREAM_ID, new VmServiceConsumers.SuccessConsumerWrapper() { @Override public void received(final Success success) { myVmServiceReceiverThreadId = Thread.currentThread().getId(); streamListen( VmService.ISOLATE_STREAM_ID, new VmServiceConsumers.SuccessConsumerWrapper() { @Override public void received(final Success success) { getVm( new VmServiceConsumers.VmConsumerWrapper() { @Override public void received(final VM vm) { if (vm.getIsolates().size() == 0) { Logging.getLogger() .logError( "No isolates found after VM start: " + vm.getIsolates().size()); } for (final IsolateRef isolateRef : vm.getIsolates()) { getIsolate( isolateRef.getId(), new VmServiceConsumers.GetIsolateConsumerWrapper() { @Override public void received(final Isolate isolate) { final Event event = isolate.getPauseEvent(); final EventKind eventKind = event.getKind(); // if event is not PauseStart it means that PauseStart event // will follow later and will be handled by listener handleIsolate(isolateRef, eventKind == EventKind.PauseStart); // Handle the case of isolates paused when we connect (this // can come up in remote debugging). if (eventKind == EventKind.PauseBreakpoint || eventKind == EventKind.PauseException || eventKind == EventKind.PauseInterrupted) { myDebugProcess.isolateSuspended(isolateRef); ApplicationManager.getApplication() .executeOnPooledThread( () -> { final ElementList<Breakpoint> breakpoints = eventKind == EventKind.PauseBreakpoint ? event.getPauseBreakpoints() : null; final InstanceRef exception = eventKind == EventKind.PauseException ? event.getException() : null; myVmServiceListener.onIsolatePaused( isolateRef, breakpoints, exception, event.getTopFrame(), event.getAtAsyncSuspension()); }); } } }); } } }); } }); } }); if (myDebugProcess.isRemoteDebug()) { streamListen(VmService.STDOUT_STREAM_ID, VmServiceConsumers.EMPTY_SUCCESS_CONSUMER); streamListen(VmService.STDERR_STREAM_ID, VmServiceConsumers.EMPTY_SUCCESS_CONSUMER); } }