From afc3f90fbc2c094a6d6d13c425b86c9171ee2dfc Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Wed, 28 Oct 2015 12:02:59 +0100 Subject: [PATCH] report state message, but not status text on failure (so, we get clear error message on vm connection failed) --- .../jetbrains/debugger/DebugProcessImpl.kt | 65 +++++++------------ .../debugger/ValueNodeAsyncFunction.kt | 10 ++- .../debugger/connection/VmConnection.kt | 14 +++- .../debugger/frame/ExecutionStackImpl.kt | 11 ++-- 4 files changed, 47 insertions(+), 53 deletions(-) diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt index c457fa2ed17d..ae83c33c11b0 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/DebugProcessImpl.kt @@ -21,7 +21,6 @@ import com.intellij.openapi.vfs.VirtualFile import com.intellij.util.Url import com.intellij.util.containers.ContainerUtil import com.intellij.util.io.socketConnection.ConnectionStatus -import com.intellij.util.io.socketConnection.SocketConnectionListener import com.intellij.xdebugger.DefaultDebugProcessHandler import com.intellij.xdebugger.XDebugProcess import com.intellij.xdebugger.XDebugSession @@ -55,28 +54,26 @@ abstract class DebugProcessImpl>(session: XDebugSession, private val _breakpointHandlers: Array> by lazy(LazyThreadSafetyMode.NONE) { createBreakpointHandlers() } init { - connection.addListener(object : SocketConnectionListener { - override fun statusChanged(status: ConnectionStatus) { - when (status) { - ConnectionStatus.DISCONNECTED, ConnectionStatus.DETACHED -> { - if (status == ConnectionStatus.DETACHED) { - if (realProcessHandler != null) { - // here must we must use effective process handler - processHandler.detachProcess() - } + connection.stateChanged { + when (it.status) { + ConnectionStatus.DISCONNECTED, ConnectionStatus.DETACHED -> { + if (it.status == ConnectionStatus.DETACHED) { + if (realProcessHandler != null) { + // here must we must use effective process handler + processHandler.detachProcess() } - getSession().stop() - } - ConnectionStatus.CONNECTION_FAILED -> { - getSession().reportError(status.statusText) - getSession().stop() - } - else -> { - getSession().rebuildViews() } + getSession().stop() + } + ConnectionStatus.CONNECTION_FAILED -> { + getSession().reportError(it.message) + getSession().stop() + } + else -> { + getSession().rebuildViews() } } - }) + } } protected final val realProcessHandler: ProcessHandler? @@ -169,21 +166,15 @@ abstract class DebugProcessImpl>(session: XDebugSession, } else { xSuspendContext.evaluateExpression(condition) - .done(object : ContextDependentAsyncResultConsumer(suspendContext) { - override fun consume(evaluationResult: String, vm: Vm) { - if ("false" == evaluationResult) { - resume() - } - else { - processBreakpointLogExpressionAndSuspend(breakpoint, xSuspendContext, suspendContext) - } + .done(suspendContext) { + if ("false" == it) { + resume() } - }) - .rejected(object : ContextDependentAsyncResultConsumer(suspendContext) { - override fun consume(failure: Throwable, vm: Vm) { + else { processBreakpointLogExpressionAndSuspend(breakpoint, xSuspendContext, suspendContext) } - }) + } + .rejected(suspendContext) { processBreakpointLogExpressionAndSuspend(breakpoint, xSuspendContext, suspendContext) } } } @@ -194,16 +185,8 @@ abstract class DebugProcessImpl>(session: XDebugSession, } else { xSuspendContext.evaluateExpression(logExpression) - .done(object : ContextDependentAsyncResultConsumer(suspendContext) { - override fun consume(logResult: String, vm: Vm) { - breakpointReached(breakpoint, logResult, xSuspendContext) - } - }) - .rejected(object : ContextDependentAsyncResultConsumer(suspendContext) { - override fun consume(logResult: Throwable, vm: Vm) { - breakpointReached(breakpoint, "Failed to evaluate expression: " + logExpression, xSuspendContext) - } - }) + .done(suspendContext) { breakpointReached(breakpoint, it, xSuspendContext) } + .rejected(suspendContext) { breakpointReached(breakpoint, "Failed to evaluate expression: $logExpression", xSuspendContext) } } } diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ValueNodeAsyncFunction.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ValueNodeAsyncFunction.kt index 1411a5d8698f..a396003f27db 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ValueNodeAsyncFunction.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/ValueNodeAsyncFunction.kt @@ -37,7 +37,7 @@ inline fun Promise.done(node: Obsolescent, crossinline handler: (T) -> Un override fun consume(param: T) = handler(param) }) -inline fun Promise.rejected(node: Obsolescent, crossinline handler: (Throwable) -> Unit) = rejected(object : ObsolescentConsumer(node) { +inline fun Promise<*>.rejected(node: Obsolescent, crossinline handler: (Throwable) -> Unit) = rejected(object : ObsolescentConsumer(node) { override fun consume(param: Throwable) = handler(param) }) @@ -45,8 +45,12 @@ abstract class ObsolescentConsumer(private val obsolescent: Obsolescent) : Ob override fun isObsolete() = obsolescent.isObsolete } -inline fun Promise.done(context: SuspendContext, crossinline handler: (result: T, vm: Vm) -> Unit) = done(object : ContextDependentAsyncResultConsumer(context) { - override fun consume(result: T, vm: Vm) = handler(result, vm) +inline fun Promise.done(context: SuspendContext, crossinline handler: (result: T) -> Unit) = done(object : ContextDependentAsyncResultConsumer(context) { + override fun consume(result: T, vm: Vm) = handler(result) +}) + +inline fun Promise<*>.rejected(context: SuspendContext, crossinline handler: (error: Throwable) -> Unit) = rejected(object : ContextDependentAsyncResultConsumer(context) { + override fun consume(result: Throwable, vm: Vm) = handler(result) }) abstract class ContextDependentAsyncResultConsumer(private val context: SuspendContext) : Consumer { diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.kt index 93d6e1c4512d..38874fdb740c 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/connection/VmConnection.kt @@ -19,6 +19,7 @@ import com.intellij.ide.browsers.WebBrowser import com.intellij.openapi.Disposable import com.intellij.openapi.util.Disposer import com.intellij.util.EventDispatcher +import com.intellij.util.containers.ContainerUtil import com.intellij.util.io.socketConnection.ConnectionState import com.intellij.util.io.socketConnection.ConnectionStatus import com.intellij.util.io.socketConnection.SocketConnectionListener @@ -39,7 +40,7 @@ abstract class VmConnection : Disposable { private val stateRef = AtomicReference(ConnectionState(ConnectionStatus.NOT_CONNECTED)) private val dispatcher = EventDispatcher.create(DebugEventListener::class.java) - private val connectionDispatcher = EventDispatcher.create(SocketConnectionListener::class.java) + private val connectionDispatcher = ContainerUtil.createLockFreeCopyOnWriteList<(ConnectionState) -> Unit>() @Volatile var vm: T? = null protected set @@ -68,12 +69,19 @@ abstract class VmConnection : Disposable { if (status == ConnectionStatus.CONNECTION_FAILED) { opened.setError(newState.message) } - connectionDispatcher.multicaster.statusChanged(status) + for (listener in connectionDispatcher) { + listener(newState) + } } } + fun stateChanged(listener: (ConnectionState) -> Unit) { + connectionDispatcher.add(listener) + } + + // backward compatibility, go debugger fun addListener(listener: SocketConnectionListener) { - connectionDispatcher.addListener(listener) + stateChanged { listener.statusChanged(it.status) } } protected val debugEventListener: DebugEventListener diff --git a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/ExecutionStackImpl.kt b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/ExecutionStackImpl.kt index dcbb12d2bdfb..8ace72b04e68 100644 --- a/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/ExecutionStackImpl.kt +++ b/platform/script-debugger/debugger-ui/src/org/jetbrains/debugger/frame/ExecutionStackImpl.kt @@ -38,25 +38,24 @@ internal class ExecutionStackImpl(private val suspendContext: SuspendContext, pr override fun computeStackFrames(firstFrameIndex: Int, container: XExecutionStack.XStackFrameContainer) { val suspendContext = viewSupport.vm!!.suspendContextManager.context ?: return // WipSuspendContextManager set context to null on resume _before_ vm.getDebugListener().resumed() call() (in any case, XFramesView can queue event to EDT), so, IDE state could be outdated compare to VM (our) state - suspendContext.frames - .done(suspendContext) { frames, vm -> - val count = frames.size() - firstFrameIndex + .done(suspendContext) { frames -> + val count = frames.size - firstFrameIndex val result: List if (count < 1) { result = emptyList() } else { result = ArrayList(count) - for (i in firstFrameIndex..frames.size() - 1) { + for (i in firstFrameIndex..frames.size - 1) { if (i == 0) { - result.add(getTopFrame()!!) + result.add(topFrame!!) continue } val frame = frames[i] // if script is null, it is native function (Object.forEach for example), so, skip it - val script = vm.scriptManager.getScript(frame) + val script = suspendContext.valueManager.vm.scriptManager.getScript(frame) if (script != null) { val sourceInfo = viewSupport.getSourceInfo(script, frame) val isInLibraryContent = sourceInfo != null && viewSupport.isInLibraryContent(sourceInfo, script)