private void processLocatableEvent(final SuspendContextImpl suspendContext, final LocatableEvent event) {
    ThreadReference thread = event.thread();
    //LOG.assertTrue(thread.isSuspended());
    preprocessEvent(suspendContext, thread);

    //we use schedule to allow processing other events during processing this one
    //this is especially necessary if a method is breakpoint condition
    getManagerThread().schedule(new SuspendContextCommandImpl(suspendContext) {
      @Override
      public void contextAction(@NotNull SuspendContextImpl suspendContext) {
        logSuspendContext(suspendContext, "start locatable event processing");
        final SuspendManager suspendManager = getSuspendManager();

        final LocatableEventRequestor requestor = (LocatableEventRequestor)RequestManagerImpl.findRequestor(event.request());

        boolean isDebugLogBreakpoint = requestor instanceof InternalDebugLoggingRequestor dReq && dReq.isDebugLogBreakpoint();

        if (isDebugLogBreakpoint) {
          String firstArgument;
          try {
            firstArgument = suspendContext.getEventThread().frame(0).getArgumentValues().get(0).toString();
          }
          catch (Throwable e) {
            firstArgument = e.getMessage();
          }
          LOG.debug("Debug log breakpoint: " + firstArgument);
          suspendManager.voteResume(suspendContext);
          return;
        }

        ThreadReferenceProxyImpl threadProxy = suspendContext.getThread();
        boolean isEvaluationOnCurrentThread = threadProxy != null && threadProxy.isEvaluating();
        if ((isEvaluationOnCurrentThread || myThreadBlockedMonitor.isInResumeAllMode()) &&
            !(requestor instanceof InstrumentationTracker.InstrumentationMethodBreakpoint) &&
            !DebuggerSession.enableBreakpointsDuringEvaluation()) {
          notifySkippedBreakpointInEvaluation(event, suspendContext);
          // is inside evaluation, so ignore any breakpoints
          logSuspendContext(suspendContext,
                            "Resume because of evaluation: isEvaluationOnCurrentThread = " + isEvaluationOnCurrentThread +
                            ", myThreadBlockedMonitor.isInResumeAllMode() = " + myThreadBlockedMonitor.isInResumeAllMode());
          suspendManager.voteResume(suspendContext);
          return;
        }

        // Skip breakpoints in other threads during suspend-all stepping.
        //
        // Don't try to check breakpoint's condition or evaluate its log expression,
        // because these evaluations may lead to skipping of more important stepping events,
        // see IDEA-336282.
        boolean useThreadFiltering = requestor == null || !requestor.shouldIgnoreThreadFiltering();
        if (!DebuggerSession.filterBreakpointsDuringSteppingUsingDebuggerEngine() && useThreadFiltering) {
          LightOrRealThreadInfo filter = getRequestsManager().getFilterThread();
          if (filter != null) {
            if (myPreparingToSuspendAll || !filter.checkSameThread(thread, suspendContext)) {
              // notify only if the current session is not one with evaluations hidden from the user
              if (!checkContextIsFromImplicitThread(suspendContext)) {
                notifySkippedBreakpoints(event, SkippedBreakpointReason.STEPPING);
              }
              logSuspendContext(suspendContext, "Skip breakpoint because of filter " + filter);
              suspendManager.voteResume(suspendContext);
              return;
            }
          }
        }

        boolean resumePreferred = requestor != null && DebuggerSettings.SUSPEND_NONE.equals(requestor.getSuspendPolicy());
        boolean requestHit = false;
        long startTimeNs = System.nanoTime();
        long endTimeNs = 0;
        try {
          requestHit = (requestor != null) && requestor.processLocatableEvent(this, event);
        }
        catch (final LocatableEventRequestor.EventProcessingException ex) {
          // stop timer here to prevent reporting dialog opened time
          endTimeNs = System.nanoTime();
          if (LOG.isDebugEnabled()) {
            LOG.debug(ex.getMessage());
          }
          final boolean[] considerRequestHit = new boolean[]{true};
          DebuggerInvocationUtil.invokeAndWait(getProject(), () -> {
            final String displayName = requestor instanceof Breakpoint ? ((Breakpoint<?>)requestor).getDisplayName() : requestor.getClass().getSimpleName();
            final String message = JavaDebuggerBundle.message("error.evaluating.breakpoint.condition.or.action", displayName, ex.getMessage());
            considerRequestHit[0] = Messages.showYesNoDialog(getProject(), message, ex.getTitle(), Messages.getQuestionIcon()) == Messages.YES;
          }, ModalityState.nonModal());
          requestHit = considerRequestHit[0];
          resumePreferred = !requestHit;
        }
        catch (VMDisconnectedException e) {
          throw e;
        }
        catch (Exception e) { // catch everything else here to be able to vote
          logError("Error in requestor.processLocatableEvent", e);
        }
        finally {
          if (endTimeNs == 0) {
            endTimeNs = System.nanoTime();
          }
          long timeMs = TimeUnit.NANOSECONDS.toMillis(endTimeNs - startTimeNs);
          if (requestor instanceof Breakpoint<?> breakpoint) {
            DebuggerStatistics.logBreakpointVisit(breakpoint, timeMs);
          }
          if (requestor instanceof OverheadProducer && ((OverheadProducer)requestor).track()) {
            OverheadTimings.add(DebugProcessEvents.this, (OverheadProducer)requestor,
                                requestHit || requestor instanceof StackCapturingLineBreakpoint ? 1 : 0,
                                timeMs);
          }
        }

        if (requestHit && requestor instanceof Breakpoint) {
          // if requestor is a breakpoint and this breakpoint was hit, no matter its suspend policy
          ApplicationManager.getApplication().runReadAction(() -> {
            XDebugSession session = getSession().getXDebugSession();
            if (session != null) {
              XBreakpoint breakpoint = ((Breakpoint)requestor).getXBreakpoint();
              if (breakpoint != null) {
                ((XDebugSessionImpl)session).processDependencies(breakpoint);
              }
            }
          });
        }

        // special check for smart step into with this breakpoint inside the expressions
        EventSet eventSet = suspendContext.getEventSet();
        if (eventSet != null && eventSet.size() > 1) {
          List<StepEvent> stepEvents = ContainerUtil.filterIsInstance(eventSet, StepEvent.class);
          if (!stepEvents.isEmpty()) {
            resumePreferred = resumePreferred ||
                              stepEvents.stream()
                                .map(DebugProcessEvents::getRequestHint)
                                .allMatch(h -> {
                                  if (h != null) {
                                    Integer depth = h.checkCurrentPosition(suspendContext, event.location());
                                    return depth != null && depth != RequestHint.STOP;
                                  }
                                  return false;
                                });
          }
        }

        if (!requestHit || resumePreferred) {
          logSuspendContext(suspendContext,"Resume: requestHit = " + requestHit + ", resumePreferred = " + resumePreferred);
          suspendManager.voteResume(suspendContext);
        }
        else {
          logSuspendContext(suspendContext, "suspend is expected");
          stopWatchingMethodReturn();
          //if (suspendContext.getSuspendPolicy() == EventRequest.SUSPEND_ALL) {
          //  // there could be explicit resume as a result of call to voteSuspend()
          //  // e.g. when breakpoint was considered invalid, in that case the filter will be applied _after_
          //  // resuming and all breakpoints in other threads will be ignored.
          //  // As resume() implicitly cleares the filter, the filter must be always applied _before_ any resume() action happens
          //  myBreakpointManager.applyThreadFilter(DebugProcessEvents.this, event.thread());
          //}

          boolean noStandardSuspendNeeded = specialSuspendProcessing(suspendContext, requestor, suspendManager, thread);
          if (!noStandardSuspendNeeded) {
            suspendManager.voteSuspend(suspendContext);
            showStatusText(DebugProcessEvents.this, event);
          }
        }
      }
    });
  }
private void processLocatableEvent(final SuspendContextImpl suspendContext, final LocatableEvent event)