simplify vm attach state management (we cannot use kotlin yet :()
authorVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Mon, 5 Jan 2015 13:56:20 +0000 (14:56 +0100)
committerVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Mon, 5 Jan 2015 13:59:13 +0000 (14:59 +0100)
firefox rdp — step actions

platform/script-debugger/backend/src/org/jetbrains/debugger/Breakpoint.java
platform/script-debugger/backend/src/org/jetbrains/debugger/CallFrameBase.java
platform/script-debugger/backend/src/org/jetbrains/debugger/StandaloneVmHelper.java
platform/script-debugger/backend/src/org/jetbrains/debugger/SuspendContextBase.java
platform/script-debugger/backend/src/org/jetbrains/debugger/SuspendContextManager.java
platform/script-debugger/backend/src/org/jetbrains/debugger/SuspendContextManagerBase.java
platform/script-debugger/backend/src/org/jetbrains/debugger/Vm.java
platform/script-debugger/backend/src/org/jetbrains/debugger/VmBase.java
platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ContextDependentAsyncResultConsumer.java
platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/RemoteVmConnection.java
platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.java

index d77e25824cc6f55a9e049de30a2e59f458dc7ea0..822154b28c488d1154bd64111bf95f968558858c 100755 (executable)
@@ -63,7 +63,9 @@ public abstract class Breakpoint {
    * Be aware! V8 doesn't provide reliable debugger API, so, sometimes actual locations is empty - in this case this methods return "true".
    * V8 debugger doesn't report about resolved breakpoint if it is happened after initial breakpoint set. So, you cannot trust "actual locations".
    */
-  public abstract boolean isActualLineCorrect();
+  public boolean isActualLineCorrect() {
+    return true;
+  }
 
   /**
    * Visitor interface that includes all extensions.
index 2f20df10dd904c68b6b89997d9f6d16959d30b3c..4ee1e3c71d703897da95b191507742bdccc9014d 100644 (file)
@@ -15,13 +15,17 @@ public abstract class CallFrameBase implements CallFrame {
 
   protected NotNullLazyValue<List<Scope>> scopes;
 
+  protected EvaluateContext evaluateContext;
+
   /**
    * You must initialize {@link #scopes} or override {@link #getVariableScopes()}
    */
-  protected CallFrameBase(@Nullable String functionName, int line, int column) {
+  protected CallFrameBase(@Nullable String functionName, int line, int column, @Nullable("init in your constructor") EvaluateContext evaluateContext) {
     this.functionName = functionName;
     this.line = line;
     this.column = column;
+
+    this.evaluateContext = evaluateContext;
   }
 
   @NotNull
@@ -45,4 +49,10 @@ public abstract class CallFrameBase implements CallFrame {
   public int getColumn() {
     return column;
   }
+
+  @NotNull
+  @Override
+  public final EvaluateContext getEvaluateContext() {
+    return evaluateContext;
+  }
 }
\ No newline at end of file
index 0fba70746ad39e87edaa9d52cb46a460e36547bd..82cd52640f67c457d1087922b95258d3bff99465 100644 (file)
@@ -1,19 +1,19 @@
 package org.jetbrains.debugger;
 
-import com.intellij.openapi.util.ActionCallback;
 import com.intellij.util.Consumer;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.concurrency.AsyncPromise;
 import org.jetbrains.concurrency.Promise;
 import org.jetbrains.io.NettyUtil;
 import org.jetbrains.jsonProtocol.Request;
 import org.jetbrains.rpc.MessageProcessor;
 import org.jetbrains.rpc.MessageWriter;
 
-public class StandaloneVmHelper extends MessageWriter {
+public class StandaloneVmHelper extends MessageWriter implements Vm.AttachStateManager {
   private volatile Channel channel;
 
   private final VmEx vm;
@@ -61,15 +61,17 @@ public class StandaloneVmHelper extends MessageWriter {
     }
   }
 
+  @Override
   public boolean isAttached() {
     return channel != null;
   }
 
+  @Override
   @NotNull
-  public ActionCallback detach() {
+  public Promise<Void> detach() {
     final Channel currentChannel = channel;
     if (currentChannel == null) {
-      return ActionCallback.DONE;
+      return Promise.DONE;
     }
 
     vm.getCommandProcessor().cancelWaitingRequests();
@@ -85,7 +87,7 @@ public class StandaloneVmHelper extends MessageWriter {
     Promise<Void> promise = vm.getCommandProcessor().send(disconnectRequest);
     vm.getCommandProcessor().closed();
     channel = null;
-    final ActionCallback subCallback = new ActionCallback();
+    final AsyncPromise<Void> subCallback = new AsyncPromise<Void>();
     promise.processed(new Consumer<Void>() {
       @Override
       public void consume(Void o) {
@@ -94,7 +96,7 @@ public class StandaloneVmHelper extends MessageWriter {
           NettyUtil.closeAndReleaseFactory(currentChannel);
         }
         finally {
-          subCallback.setDone();
+          subCallback.setResult(null);
         }
       }
     });
@@ -102,8 +104,8 @@ public class StandaloneVmHelper extends MessageWriter {
   }
 
   @NotNull
-  protected ActionCallback closeChannel(@NotNull Channel channel) {
+  protected Promise<Void> closeChannel(@NotNull Channel channel) {
     NettyUtil.closeAndReleaseFactory(channel);
-    return ActionCallback.DONE;
+    return Promise.DONE;
   }
 }
\ No newline at end of file
index 0b1f265c3ad70c3368053f359c9d3491eb88b498..c04120f61e9624f24fe0d07fc83a547aec40f5c5 100644 (file)
@@ -1,6 +1,7 @@
 package org.jetbrains.debugger;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
 import org.jetbrains.debugger.values.ValueManager;
 
 public abstract class SuspendContextBase<VALUE_MANAGER extends ValueManager> implements SuspendContext {
@@ -25,4 +26,11 @@ public abstract class SuspendContextBase<VALUE_MANAGER extends ValueManager> imp
   public final VALUE_MANAGER getValueManager() {
     return valueManager;
   }
+
+  @Nullable
+  @Override
+  public Script getScript() {
+    CallFrame topFrame = getTopFrame();
+    return topFrame == null ? null : valueManager.getVm().getScriptManager().getScript(topFrame);
+  }
 }
\ No newline at end of file
index 479774d9c57b0936dde079aa9da8663ceeed9a4c..30e1a7d4c4c1118f361a910fe8fe32ce6cd9865b 100644 (file)
@@ -6,8 +6,7 @@ import org.jetbrains.concurrency.Promise;
 
 public interface SuspendContextManager<CALL_FRAME extends CallFrame> {
   /**
-   * Tries to suspend VM. If successful, {@link DebugEventListener#suspended(SuspendContext)}
-   * will be called.
+   * Tries to suspend VM. If successful, {@link DebugEventListener#suspended(SuspendContext)} will be called.
    */
   @NotNull
   Promise<?> suspend();
@@ -28,6 +27,7 @@ public interface SuspendContextManager<CALL_FRAME extends CallFrame> {
    *  @param stepAction to perform
    * @param stepCount steps to perform (not used if {@code stepAction == CONTINUE})
    */
+  @NotNull
   Promise<Void> continueVm(@NotNull StepAction stepAction, int stepCount);
 
   boolean isRestartFrameSupported();
index ce3b97bd128e1b8a43147bf20b4fca1d59b6c5d6..113594d26acefdb85aed76be74b5bc51f7b75caa 100644 (file)
@@ -1,5 +1,6 @@
 package org.jetbrains.debugger;
 
+import com.intellij.util.Consumer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.jetbrains.concurrency.Promise;
@@ -17,12 +18,34 @@ public abstract class SuspendContextManagerBase<T extends SuspendContextBase, CA
     }
   }
 
-  public final void contextDismissed(@NotNull T context, @NotNull DebugEventListener listener) {
+  // dismiss context on resumed
+  protected final void dismissContext() {
+    T context = getContext();
+    if (context != null) {
+      contextDismissed(context);
+    }
+  }
+
+  @NotNull
+  protected final Promise<Void> dismissContextOnDone(@NotNull Promise<Void> promise) {
+    final T context = getContextOrFail();
+    promise.done(new Consumer<Void>() {
+      @Override
+      public void consume(Void aVoid) {
+        contextDismissed(context);
+      }
+    });
+    return promise;
+  }
+
+  protected abstract DebugEventListener getDebugListener();
+
+  public final void contextDismissed(@NotNull T context) {
     if (!this.context.compareAndSet(context, null)) {
       throw new IllegalStateException("Expected " + context + ", but another suspend context exists");
     }
     context.getValueManager().markObsolete();
-    listener.resumed();
+    getDebugListener().resumed();
   }
 
   @Nullable
index 844692d9a842b58c2caa92bc7efc9d6c43402197..0215a1e61b268511216ab7108bfaaa27380d6765 100644 (file)
@@ -1,14 +1,18 @@
 package org.jetbrains.debugger;
 
-import com.intellij.openapi.util.ActionCallback;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.concurrency.Promise;
 
 public interface Vm {
-  @NotNull
-  ActionCallback detach();
+  interface AttachStateManager {
+    @NotNull
+    Promise<Void> detach();
+
+    boolean isAttached();
+  }
 
-  boolean isAttached();
+  @NotNull
+  AttachStateManager getAttachStateManager();
 
   @NotNull
   ScriptManager getScriptManager();
index b2ebd332c6239b5ccfb1736c3e6453d80b1d00ac..bfd74bf6253c69902abb8adce740804c4e311ca9 100644 (file)
@@ -1,8 +1,9 @@
 package org.jetbrains.debugger;
 
 import org.jetbrains.annotations.NotNull;
+import org.jetbrains.concurrency.Promise;
 
-public abstract class VmBase implements Vm {
+public abstract class VmBase implements Vm, Vm.AttachStateManager {
   private EvaluateContext evaluateContext;
   private final DebugEventListener debugListener;
 
@@ -27,4 +28,21 @@ public abstract class VmBase implements Vm {
   public final DebugEventListener getDebugListener() {
     return debugListener;
   }
+
+  @NotNull
+  @Override
+  public AttachStateManager getAttachStateManager() {
+    return this;
+  }
+
+  @Override
+  public boolean isAttached() {
+    return true;
+  }
+
+  @NotNull
+  @Override
+  public Promise<Void> detach() {
+    return Promise.DONE;
+  }
 }
\ No newline at end of file
index 6082362812561971c48634d9ae90d8f837be0be5..7b1ded850712f5b11d25280be5a8a13752a963b4 100644 (file)
@@ -13,7 +13,7 @@ public abstract class ContextDependentAsyncResultConsumer<T> implements Consumer
   @Override
   public final void consume(T result) {
     Vm vm = context.getValueManager().getVm();
-    if (vm.isAttached() && !vm.getSuspendContextManager().isContextObsolete(context)) {
+    if (vm.getAttachStateManager().isAttached() && !vm.getSuspendContextManager().isContextObsolete(context)) {
       consume(result, vm);
     }
   }
index cd751f15dbdec70b5474ba4dd114629ba692ef34..7ce6844231217f51113ffa55aafa12f8d2de3cb6 100644 (file)
@@ -102,9 +102,10 @@ public abstract class RemoteVmConnection extends VmConnection<Vm> {
     return address.getHostName() + ":" + address.getPort();
   }
 
+  @NotNull
   @Override
-  public ActionCallback detachAndClose() {
-    ActionCallback callback;
+  public Promise<Void> detachAndClose() {
+    Promise<Void> callback;
     try {
       Runnable runnable = connectCancelHandler.getAndSet(null);
       if (runnable != null) {
index f1139acd021fcd6ad575585636cbc5bb7f291e52..9a1b105bd9f8498c3a13786926e472578e07e5a8 100644 (file)
@@ -1,7 +1,6 @@
 package org.jetbrains.debugger.connection;
 
 import com.intellij.openapi.Disposable;
-import com.intellij.openapi.util.ActionCallback;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.util.Consumer;
 import com.intellij.util.EventDispatcher;
@@ -101,17 +100,18 @@ public abstract class VmConnection<T extends Vm> implements Disposable, BrowserC
     vm = null;
   }
 
-  public ActionCallback detachAndClose() {
+  @NotNull
+  public Promise<Void> detachAndClose() {
     opened.setError(Promise.createError("detached and closed"));
 
     Vm currentVm = vm;
-    ActionCallback callback;
+    Promise<Void> callback;
     if (currentVm == null) {
-      callback = new ActionCallback.Done();
+      callback = Promise.DONE;
     }
     else {
       vm = null;
-      callback = currentVm.detach();
+      callback = currentVm.getAttachStateManager().detach();
     }
     close(null, ConnectionStatus.DISCONNECTED);
     return callback;