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);
    }
  }