Promise — add onError and onSuccess

Prefix "on" makes method purpose more clear (especially if you are not familiar with "signals" concept).
This commit is contained in:
Vladimir Krivosheev
2018-02-20 14:32:29 +01:00
parent 9adf115a8c
commit ef7e65989e
23 changed files with 218 additions and 347 deletions
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.debugger.actions;
import com.intellij.debugger.engine.DebugProcessImpl;
@@ -65,7 +51,7 @@ public abstract class ArrayAction extends DebuggerAction {
// title = title + " " + label.substring(index);
//}
createNewRenderer(node, renderer, debuggerContext, node.getName())
.done(newRenderer -> setArrayRenderer(newRenderer, node, debuggerContext));
.onSuccess(newRenderer -> setArrayRenderer(newRenderer, node, debuggerContext));
}
@NotNull
@@ -119,7 +105,7 @@ public abstract class ArrayAction extends DebuggerAction {
if (debugProcess != null) {
debugProcess.getManagerThread().schedule(new SuspendContextCommandImpl(debuggerContext.getSuspendContext()) {
@Override
public void contextAction(@NotNull SuspendContextImpl suspendContext) throws Exception {
public void contextAction(@NotNull SuspendContextImpl suspendContext) {
final Renderer lastRenderer = descriptor.getLastRenderer();
if (lastRenderer instanceof ArrayRenderer) {
((JavaValue)container).setRenderer(newRenderer, node);
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.ide
import com.intellij.ide.impl.ProjectUtil.focusProjectWindow
@@ -118,7 +104,7 @@ internal class OpenFileHttpService : RestService() {
}
val promise = openFile(apiRequest, context, request) ?: return null
promise.done { sendStatus(HttpResponseStatus.OK, keepAlive, channel) }
promise.onSuccess { sendStatus(HttpResponseStatus.OK, keepAlive, channel) }
.rejected {
if (it === NOT_FOUND) {
// don't expose file status
@@ -134,7 +120,7 @@ internal class OpenFileHttpService : RestService() {
return null
}
internal fun openFile(request: OpenFileRequest, context: ChannelHandlerContext, httpRequest: HttpRequest?): Promise<Void>? {
internal fun openFile(request: OpenFileRequest, context: ChannelHandlerContext, httpRequest: HttpRequest?): Promise<Void?>? {
val systemIndependentPath = FileUtil.toSystemIndependentName(FileUtil.expandUserHome(request.file!!))
val file = Paths.get(FileUtil.toSystemDependentName(systemIndependentPath))
if (file.isAbsolute) {
@@ -198,7 +184,7 @@ internal class OpenFileRequest {
}
private class OpenFileTask(internal val path: String, internal val request: OpenFileRequest) {
internal val promise = AsyncPromise<Void>()
internal val promise = AsyncPromise<Void?>()
}
private fun navigate(project: Project?, file: VirtualFile, request: OpenFileRequest) {
@@ -251,8 +237,8 @@ private fun openRelativePath(path: String, request: OpenFileRequest): Boolean {
} ?: false
}
private fun openAbsolutePath(file: Path, request: OpenFileRequest): Promise<Void> {
val promise = AsyncPromise<Void>()
private fun openAbsolutePath(file: Path, request: OpenFileRequest): Promise<Void?> {
val promise = AsyncPromise<Void?>()
ApplicationManager.getApplication().invokeLater {
promise.catchError {
val virtualFile = runWriteAction { LocalFileSystem.getInstance().refreshAndFindFileByPath(file.systemIndependentPath) }
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.execution.runners;
import com.intellij.execution.ExecutionException;
@@ -37,7 +23,7 @@ public abstract class AsyncGenericProgramRunner<Settings extends RunnerSettings>
@Nullable Callback callback,
@NotNull RunProfileState state) throws ExecutionException {
prepare(environment, state)
.done(result -> UIUtil.invokeLaterIfNeeded(() -> {
.onSuccess(result -> UIUtil.invokeLaterIfNeeded(() -> {
if (!environment.getProject().isDisposed()) {
startRunProfile(environment, state, callback, result);
}
@@ -35,10 +35,9 @@ import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.concurrency.Promise;
import javax.swing.JTree;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
@@ -207,7 +206,10 @@ class AsyncProjectViewSupport {
}
private void acceptAndUpdate(TreeVisitor visitor, List<TreePath> list, boolean structure) {
if (visitor != null) myAsyncTreeModel.accept(visitor, false).done(path -> update(list, structure));
if (visitor != null) {
myAsyncTreeModel.accept(visitor, false)
.onSuccess(path -> update(list, structure));
}
}
private void updatePresentationsFromRootTo(@NotNull VirtualFile file) {
@@ -238,15 +240,17 @@ class AsyncProjectViewSupport {
void accept(List<TreeVisitor> visitors, Consumer<List<TreePath>> consumer) {
if (visitors != null && !visitors.isEmpty()) {
if (1 == visitors.size()) {
myAsyncTreeModel.accept(visitors.get(0)).done(path -> {
if (path != null) consumer.consume(singletonList(path));
});
myAsyncTreeModel.accept(visitors.get(0))
.onSuccess(path -> {
if (path != null) consumer.consume(singletonList(path));
});
}
else {
List<Promise<TreePath>> promises = visitors.stream().map(visitor -> myAsyncTreeModel.accept(visitor)).collect(toList());
collectResults(promises, true).done(list -> {
if (list != null && !list.isEmpty()) consumer.consume(list);
});
collectResults(promises, true)
.onSuccess(list -> {
if (list != null && !list.isEmpty()) consumer.consume(list);
});
}
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.tree;
import com.intellij.openapi.Disposable;
@@ -36,7 +22,6 @@ import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.IntFunction;
@@ -165,8 +150,8 @@ public final class AsyncTreeModel extends AbstractTreeModel implements Identifia
onValidThread(() -> async.setError("rejected"));
}
else {
promise.rejected(onValidThread(async::setError));
promise.done(onValidThread(path -> resolve(async, path)));
promise.onError(onValidThread(async::setError));
promise.onSuccess(onValidThread(path -> resolve(async, path)));
}
return async;
}
@@ -256,7 +241,9 @@ public final class AsyncTreeModel extends AbstractTreeModel implements Identifia
@Override
protected Collection<Node> getChildren(@NotNull Node node) {
if (node.leaf || !allowLoading) return node.getChildren();
promiseChildren(node).done(parent -> setChildren(parent.getChildren())).rejected(this::setError);
promiseChildren(node)
.onSuccess(parent -> setChildren(parent.getChildren()))
.onError(this::setError);
return null;
}
};
@@ -288,7 +275,7 @@ public final class AsyncTreeModel extends AbstractTreeModel implements Identifia
}
@NotNull
private <T> Consumer<T> onValidThread(Consumer<T> consumer) {
private <T> java.util.function.Consumer<T> onValidThread(Consumer<T> consumer) {
return value -> onValidThread(() -> consumer.consume(value));
}
@@ -36,7 +36,8 @@ class AsyncPromiseTest {
val count = AtomicInteger()
val r = {
promise.done { count.incrementAndGet() }
promise
.onSuccess { count.incrementAndGet() }
}
val s = {
@@ -101,10 +102,10 @@ class AsyncPromiseTest {
val r = {
if (reject) {
promise.rejected { count.incrementAndGet() }
promise.onError { count.incrementAndGet() }
}
else {
promise.done { count.incrementAndGet() }
promise.onSuccess { count.incrementAndGet() }
}
}
@@ -3,7 +3,6 @@ package org.jetbrains.concurrency
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.util.Getter
import com.intellij.util.Consumer
import com.intellij.util.Function
import org.jetbrains.concurrency.Promise.State
import java.util.*
@@ -11,12 +10,13 @@ import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit
import java.util.concurrent.TimeoutException
import java.util.concurrent.atomic.AtomicReference
import java.util.function.Consumer
private val LOG = Logger.getInstance(AsyncPromise::class.java)
private data class PromiseValue<out T>(val result: T? = null, val error: Throwable? = null)
open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
open class AsyncPromise<T : Any?> : Promise<T>, Getter<T>, CancellablePromise<T> {
private val doneRef = AtomicReference<Consumer<in T>?>()
private val rejectedRef = AtomicReference<Consumer<in Throwable>?>()
@@ -31,13 +31,18 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
}
}
override fun done(done: Consumer<in T>): Promise<T> {
override fun onSuccess(done: Consumer<in T>): Promise<T> {
setHandler(doneRef, done, State.FULFILLED)
return this
}
override fun rejected(rejected: Consumer<Throwable>): Promise<T> {
setHandler(rejectedRef, rejected, State.REJECTED)
override fun rejected(rejected: com.intellij.util.Consumer<Throwable>): Promise<T> {
setHandler(rejectedRef, Consumer { rejected.consume(it) }, State.REJECTED)
return this
}
override fun onError(errorHandler: Consumer<Throwable>): Promise<T> {
setHandler(rejectedRef, errorHandler, State.REJECTED)
return this
}
@@ -83,8 +88,8 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
addHandlers(Consumer({
promise.catchError {
handler.`fun`(it)
.done { promise.catchError { promise.setResult(it) } }
.rejected(rejectedHandler)
.onSuccess { promise.catchError { promise.setResult(it) } }
.onError(rejectedHandler)
}
}), rejectedHandler)
return promise
@@ -96,9 +101,10 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
}
val value = valueRef.get()
@Suppress("UNCHECKED_CAST")
when {
value == null -> addHandlers(Consumer({ child.catchError { child.setResult(it) } }), Consumer({ child.setError(it) }))
value.error == null -> child.setResult(value.result)
value.error == null -> child.setResult(value.result as T)
else -> child.setError(value.error)
}
return this
@@ -109,7 +115,7 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
setHandler(rejectedRef, rejected, State.REJECTED)
}
fun setResult(result: T?) {
fun setResult(result: T) {
if (!valueRef.compareAndSet(null, PromiseValue(result = result))) {
return
}
@@ -118,7 +124,7 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
rejectedRef.set(null)
if (done != null && !isObsolete(done)) {
done.consume(result)
done.accept(result)
}
}
@@ -141,14 +147,14 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
LOG.errorIfNotMessage(error)
}
else if (!isObsolete(rejected)) {
rejected.consume(error)
rejected.accept(error)
}
return true
}
override fun processed(processed: Consumer<in T>): Promise<T> {
done(processed)
rejected { processed.consume(null) }
override fun onProcessed(action: Consumer<in T?>): Promise<T> {
onSuccess { action.accept(it) }
onError { action.accept(null) }
return this
}
@@ -223,11 +229,11 @@ open class AsyncPromise<T> : Promise<T>, Getter<T>, CancellablePromise<T> {
}
}
private fun <C_T> callConsumerIfTargeted(targetState: State, newConsumer: Consumer<in C_T>, value: PromiseValue<T>) {
private fun <C_T : Any?> callConsumerIfTargeted(targetState: State, newConsumer: Consumer<in C_T>, value: PromiseValue<T>) {
val currentState = if (value.error == null) State.FULFILLED else State.REJECTED
if (currentState == targetState) {
@Suppress("UNCHECKED_CAST")
newConsumer.consume(if (currentState == State.FULFILLED) value.result as C_T? else value.error as C_T)
newConsumer.accept(if (currentState == State.FULFILLED) value.result as C_T else value.error as C_T)
}
}
@@ -260,7 +266,7 @@ private class CompoundConsumer<T>(c1: Consumer<in T>, c2: Consumer<in T>) : Cons
}
}
override fun consume(t: T) {
override fun accept(t: T) {
val list = synchronized(this) {
val list = consumers
consumers = null
@@ -269,13 +275,13 @@ private class CompoundConsumer<T>(c1: Consumer<in T>, c2: Consumer<in T>) : Cons
for (consumer in list) {
if (!isObsolete(consumer)) {
consumer.consume(t)
consumer.accept(t)
}
}
}
}
internal fun isObsolete(consumer: Consumer<*>?) = consumer is Obsolescent && consumer.isObsolete
internal fun isObsolete(consumer: Any) = consumer is Obsolescent && consumer.isObsolete
inline fun <T> AsyncPromise<*>.catchError(runnable: () -> T): T? {
try {
@@ -2,7 +2,6 @@
package org.jetbrains.concurrency;
import com.intellij.openapi.util.Getter;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -11,6 +10,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;
import static org.jetbrains.concurrency.Promises.rejectedPromise;
import static org.jetbrains.concurrency.Promises.resolvedPromise;
@@ -24,9 +24,9 @@ class DonePromise<T> implements Getter<T>, Promise<T>, Future<T> {
@NotNull
@Override
public Promise<T> done(@NotNull Consumer<? super T> done) {
public Promise<T> onSuccess(@NotNull Consumer<? super T> done) {
if (!AsyncPromiseKt.isObsolete(done)) {
done.consume(result);
done.accept(result);
}
return this;
}
@@ -43,14 +43,14 @@ class DonePromise<T> implements Getter<T>, Promise<T>, Future<T> {
@NotNull
@Override
public Promise<T> processed(@NotNull Consumer<? super T> processed) {
done(processed);
public Promise<T> onProcessed(@NotNull Consumer<? super T> processed) {
onSuccess(processed);
return this;
}
@NotNull
@Override
public Promise<T> rejected(@NotNull Consumer<Throwable> rejected) {
public Promise<T> onError(@NotNull Consumer<Throwable> rejected) {
return this;
}
@@ -71,13 +71,30 @@ public interface Promise<T> {
* Execute passed handler on promise resolve.
*/
@NotNull
Promise<T> done(@NotNull Consumer<? super T> done);
Promise<T> onSuccess(@NotNull java.util.function.Consumer<? super T> done);
/**
* Execute passed handler on promise resolve.
* @deprecated Use {@link #onSuccess(java.util.function.Consumer)}
*/
@NotNull
default Promise<T> done(@NotNull Consumer<? super T> done) {
return onSuccess(it -> done.consume(it));
}
/**
* Execute passed handler on promise reject.
*/
@NotNull
Promise<T> rejected(@NotNull Consumer<Throwable> rejected);
Promise<T> onError(@NotNull java.util.function.Consumer<Throwable> rejected);
/**
* Execute passed handler on promise reject.
*/
@NotNull
default Promise<T> rejected(@NotNull Consumer<Throwable> rejected) {
return onError(it -> rejected.consume(it));
}
/**
* Resolve or reject passed promise as soon as this promise resolved or rejected.
@@ -89,7 +106,15 @@ public interface Promise<T> {
* Execute passed handler on promise resolve (result value will be passed),
* or on promise reject (null as result value will be passed).
*/
Promise<T> processed(@NotNull Consumer<? super T> processed);
Promise<T> onProcessed(@NotNull java.util.function.Consumer<? super T> processed);
/**
* Execute passed handler on promise resolve (result value will be passed),
* or on promise reject (null as result value will be passed).
*/
default Promise<T> processed(@NotNull Consumer<? super T> action) {
return onProcessed(it -> action.consume(it));
}
/**
* Get promise state.
@@ -1,16 +1,16 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.concurrency
import com.intellij.util.Consumer
import com.intellij.util.Function
import java.util.concurrent.Future
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
internal class RejectedPromise<T>(private val error: Throwable) : Promise<T>, Future<T> {
override fun getState() = Promise.State.REJECTED
override fun done(done: Consumer<in T>) = this
override fun onSuccess(done: Consumer<in T>) = this
override fun processed(child: Promise<in T>): Promise<T> {
if (child is AsyncPromise) {
@@ -19,15 +19,15 @@ internal class RejectedPromise<T>(private val error: Throwable) : Promise<T>, Fu
return this
}
override fun rejected(rejected: Consumer<Throwable>): Promise<T> {
if (!isObsolete(rejected)) {
rejected.consume(error)
override fun onError(action: Consumer<Throwable>): Promise<T> {
if (!isObsolete(action)) {
action.accept(error)
}
return this
}
override fun processed(processed: Consumer<in T>): RejectedPromise<T> {
processed.consume(null)
override fun onProcessed(processed: Consumer<in T?>): RejectedPromise<T> {
processed.accept(null)
return this
}
@@ -56,7 +56,7 @@ abstract class ValueNodeAsyncFunction<PARAM, RESULT>(private val node: Obsolesce
override fun isObsolete() = node.isObsolete
}
abstract class ObsolescentConsumer<T>(private val obsolescent: Obsolescent) : Obsolescent, Consumer<T> {
abstract class ObsolescentConsumer<T>(private val obsolescent: Obsolescent) : Obsolescent, java.util.function.Consumer<T> {
override fun isObsolete() = obsolescent.isObsolete
}
@@ -67,20 +67,20 @@ inline fun <T, SUB_RESULT> Promise<T>.then(obsolescent: Obsolescent, crossinline
})
inline fun <T> Promise<T>.done(node: Obsolescent, crossinline handler: (T) -> Unit) = done(object : ObsolescentConsumer<T>(node) {
override fun consume(param: T) = handler(param)
inline fun <T> Promise<T>.onSuccess(node: Obsolescent, crossinline handler: (T) -> Unit) = onSuccess(object : ObsolescentConsumer<T>(node) {
override fun accept(param: T) = handler(param)
})
inline fun Promise<*>.processed(node: Obsolescent, crossinline handler: () -> Unit): Promise<Any?>? {
@Suppress("UNCHECKED_CAST")
return (this as Promise<Any?>)
.processed(object : ObsolescentConsumer<Any?>(node) {
override fun consume(param: Any?) = handler()
.onProcessed(object : ObsolescentConsumer<Any?>(node) {
override fun accept(param: Any?) = handler()
})
}
@Suppress("UNCHECKED_CAST")
inline fun Promise<*>.doneRun(crossinline handler: () -> Unit) = done({ handler() })
inline fun Promise<*>.doneRun(crossinline handler: () -> Unit) = onSuccess { handler() }
@Suppress("UNCHECKED_CAST")
inline fun <T> Promise<*>.thenRun(crossinline handler: () -> T): Promise<T> = (this as Promise<Any?>).then({ handler() })
@@ -94,9 +94,11 @@ inline fun <T, SUB_RESULT> Promise<T>.thenAsync(node: Obsolescent, crossinline h
})
@Suppress("UNCHECKED_CAST")
inline fun <T> Promise<T>.thenAsyncAccept(node: Obsolescent, crossinline handler: (T) -> Promise<*>) = thenAsync(object : ValueNodeAsyncFunction<T, Any?>(node) {
override fun `fun`(param: T) = handler(param) as Promise<Any?>
})
inline fun <T> Promise<T>.thenAsyncAccept(node: Obsolescent, crossinline handler: (T) -> Promise<*>): Promise<Any?> {
return thenAsync(object : ValueNodeAsyncFunction<T, Any?>(node) {
override fun `fun`(param: T) = handler(param) as Promise<Any?>
})
}
inline fun <T> Promise<T>.thenAsyncAccept(crossinline handler: (T) -> Promise<*>) = thenAsync(Function<T, Promise<Any?>> { param ->
@Suppress("UNCHECKED_CAST")
@@ -104,8 +106,8 @@ inline fun <T> Promise<T>.thenAsyncAccept(crossinline handler: (T) -> Promise<*>
})
inline fun Promise<*>.rejected(node: Obsolescent, crossinline handler: (Throwable) -> Unit) = rejected(object : ObsolescentConsumer<Throwable>(node) {
override fun consume(param: Throwable) = handler(param)
inline fun Promise<*>.onError(node: Obsolescent, crossinline handler: (Throwable) -> Unit) = onError(object : ObsolescentConsumer<Throwable>(node) {
override fun accept(param: Throwable) = handler(param)
})
@JvmOverloads
@@ -116,7 +118,7 @@ fun <T> collectResults(promises: List<Promise<T>>, ignoreErrors: Boolean = false
val results: MutableList<T> = if (promises.size == 1) SmartList<T>() else ArrayList(promises.size)
for (promise in promises) {
promise.done { results.add(it) }
promise.onSuccess { results.add(it) }
}
return all(promises, results, ignoreErrors)
}
@@ -125,10 +127,15 @@ fun <T> collectResults(promises: List<Promise<T>>, ignoreErrors: Boolean = false
fun createError(error: String, log: Boolean = false): RuntimeException = MessageError(error, log)
inline fun <T> AsyncPromise<T>.compute(runnable: () -> T) {
val result = catchError(runnable)
if (!isRejected) {
setResult(result)
val result = try {
runnable()
}
catch (e: Throwable) {
setError(e)
return
}
setResult(result)
}
inline fun <T> runAsync(crossinline runnable: () -> T): Promise<T> {
@@ -172,16 +179,17 @@ fun Logger.errorIfNotMessage(e: Throwable): Boolean {
return false
}
fun ActionCallback.toPromise(): Promise<Void> {
val promise = AsyncPromise<Void>()
doWhenDone { promise.setResult(null) }.doWhenRejected { error -> promise.setError(createError(error ?: "Internal error")) }
fun ActionCallback.toPromise(): Promise<Void?> {
val promise = AsyncPromise<Void?>()
doWhenDone { promise.setResult(null) }
.doWhenRejected { error -> promise.setError(createError(error ?: "Internal error")) }
return promise
}
fun all(promises: Collection<Promise<*>>): Promise<*> = if (promises.size == 1) promises.first() else all(promises, null)
@JvmOverloads
fun <T> all(promises: Collection<Promise<*>>, totalResult: T?, ignoreErrors: Boolean = false): Promise<T> {
fun <T: Any?> all(promises: Collection<Promise<*>>, totalResult: T, ignoreErrors: Boolean = false): Promise<T> {
if (promises.isEmpty()) {
@Suppress("UNCHECKED_CAST")
return DONE as Promise<T>
@@ -190,21 +198,21 @@ fun <T> all(promises: Collection<Promise<*>>, totalResult: T?, ignoreErrors: Boo
val totalPromise = AsyncPromise<T>()
val done = CountDownConsumer(promises.size, totalPromise, totalResult)
val rejected = if (ignoreErrors) {
Consumer { done.consume(null) }
Consumer { done.accept(null) }
}
else {
Consumer<Throwable> { totalPromise.setError(it) }
}
for (promise in promises) {
promise.done(done)
promise.onSuccess(done)
promise.rejected(rejected)
}
return totalPromise
}
private class CountDownConsumer<T>(@Volatile private var countDown: Int, private val promise: AsyncPromise<T>, private val totalResult: T?) : Consumer<Any?> {
override fun consume(t: Any?) {
private class CountDownConsumer<T : Any?>(@Volatile private var countDown: Int, private val promise: AsyncPromise<T>, private val totalResult: T) : java.util.function.Consumer<Any?> {
override fun accept(t: Any?) {
if (--countDown == 0) {
promise.setResult(totalResult)
}
@@ -221,11 +229,11 @@ fun <T> any(promises: Collection<Promise<T>>, totalError: String): Promise<T> {
}
val totalPromise = AsyncPromise<T>()
val done = Consumer<T> { result -> totalPromise.setResult(result) }
val rejected = object : Consumer<Throwable> {
val done = java.util.function.Consumer<T> { result -> totalPromise.setResult(result) }
val rejected = object : java.util.function.Consumer<Throwable> {
@Volatile private var toConsume = promises.size
override fun consume(throwable: Throwable) {
override fun accept(throwable: Throwable) {
if (--toConsume <= 0) {
totalPromise.setError(totalError)
}
@@ -233,8 +241,8 @@ fun <T> any(promises: Collection<Promise<T>>, totalError: String): Promise<T> {
}
for (promise in promises) {
promise.done(done)
promise.rejected(rejected)
promise.onSuccess(done)
promise.onError(rejected)
}
return totalPromise
}
@@ -1,28 +1,13 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.util.Consumer
import org.jetbrains.concurrency.Promise
import org.jetbrains.debugger.values.ValueManager
/**
* An object that matches the execution state of the VM while suspended
*/
interface SuspendContext<CALL_FRAME : CallFrame> {
interface SuspendContext<out CALL_FRAME : CallFrame> {
val state: SuspendState
val script: Script?
@@ -60,22 +45,26 @@ interface SuspendContext<CALL_FRAME : CallFrame> {
get() = throw UnsupportedOperationException()
}
abstract class ContextDependentAsyncResultConsumer<T>(private val context: SuspendContext<*>) : Consumer<T> {
override final fun consume(result: T) {
abstract class ContextDependentAsyncResultConsumer<T>(private val context: SuspendContext<*>) : java.util.function.Consumer<T> {
override final fun accept(result: T) {
val vm = context.vm
if (vm.attachStateManager.isAttached && !vm.suspendContextManager.isContextObsolete(context)) {
consume(result, vm)
accept(result, vm)
}
}
protected abstract fun consume(result: T, vm: Vm)
protected abstract fun accept(result: T, vm: Vm)
}
inline fun <T> Promise<T>.done(context: SuspendContext<*>, crossinline handler: (result: T) -> Unit) = done(object : ContextDependentAsyncResultConsumer<T>(context) {
override fun consume(result: T, vm: Vm) = handler(result)
})
inline fun <T> Promise<T>.onSuccess(context: SuspendContext<*>, crossinline handler: (result: T) -> Unit): Promise<T> {
return onSuccess(object : ContextDependentAsyncResultConsumer<T>(context) {
override fun accept(result: T, vm: Vm) = handler(result)
})
}
inline fun Promise<*>.rejected(context: SuspendContext<*>, crossinline handler: (error: Throwable) -> Unit) = rejected(object : ContextDependentAsyncResultConsumer<Throwable>(context) {
override fun consume(result: Throwable, vm: Vm) = handler(result)
})
inline fun Promise<*>.onError(context: SuspendContext<*>, crossinline handler: (error: Throwable) -> Unit): Promise<out Any> {
return onError(object : ContextDependentAsyncResultConsumer<Throwable>(context) {
override fun accept(result: Throwable, vm: Vm) = handler(result)
})
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import org.jetbrains.concurrency.AsyncPromise
@@ -24,7 +10,7 @@ import java.util.concurrent.atomic.AtomicReference
abstract class SuspendContextManagerBase<T : SuspendContextBase<CALL_FRAME>, CALL_FRAME : CallFrame> : SuspendContextManager<CALL_FRAME> {
val contextRef = AtomicReference<T>()
protected val suspendCallback = AtomicReference<AsyncPromise<Void>>()
protected val suspendCallback = AtomicReference<AsyncPromise<Void?>>()
protected abstract val debugListener: DebugEventListener
@@ -46,7 +32,7 @@ abstract class SuspendContextManagerBase<T : SuspendContextBase<CALL_FRAME>, CAL
protected fun dismissContextOnDone(promise: Promise<*>): Promise<*> {
val context = contextOrFail
promise.done { contextDismissed(context) }
promise.onSuccess { contextDismissed(context) }
return promise
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.rpc
import com.intellij.openapi.diagnostic.Logger
@@ -23,7 +9,10 @@ import java.util.concurrent.atomic.AtomicInteger
val LOG = Logger.getInstance(CommandProcessor::class.java)
abstract class CommandProcessor<INCOMING, INCOMING_WITH_SEQ : Any, SUCCESS_RESPONSE>() : CommandSenderBase<SUCCESS_RESPONSE>(), MessageManager.Handler<Request<*>, INCOMING, INCOMING_WITH_SEQ, SUCCESS_RESPONSE>, ResultReader<SUCCESS_RESPONSE>, MessageProcessor {
abstract class CommandProcessor<INCOMING, INCOMING_WITH_SEQ : Any, SUCCESS_RESPONSE : Any?> : CommandSenderBase<SUCCESS_RESPONSE>(),
MessageManager.Handler<Request<*>, INCOMING, INCOMING_WITH_SEQ, SUCCESS_RESPONSE>,
ResultReader<SUCCESS_RESPONSE>,
MessageProcessor {
private val currentSequence = AtomicInteger()
protected val messageManager = MessageManager(this)
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.rpc
import org.jetbrains.concurrency.AsyncPromise
@@ -23,28 +9,28 @@ import org.jetbrains.jsonProtocol.Request
abstract class CommandSenderBase<SUCCESS_RESPONSE> {
protected abstract fun <RESULT> doSend(message: Request<RESULT>, callback: RequestPromise<SUCCESS_RESPONSE, RESULT>)
fun <RESULT> send(message: Request<RESULT>): Promise<RESULT> {
fun <RESULT : Any?> send(message: Request<RESULT>): Promise<RESULT> {
val callback = RequestPromise<SUCCESS_RESPONSE, RESULT>(message.methodName)
doSend(message, callback)
return callback
}
}
class RequestPromise<SUCCESS_RESPONSE, RESULT>(private val methodName: String?) : AsyncPromise<RESULT>(), RequestCallback<SUCCESS_RESPONSE> {
class RequestPromise<SUCCESS_RESPONSE, RESULT : Any?>(private val methodName: String?) : AsyncPromise<RESULT>(), RequestCallback<SUCCESS_RESPONSE> {
override fun onSuccess(response: SUCCESS_RESPONSE?, resultReader: ResultReader<SUCCESS_RESPONSE>?) {
catchError {
val r: Any?
if (resultReader == null || response == null) {
@Suppress("UNCHECKED_CAST")
setResult(response as RESULT?)
r = response
}
else if (methodName == null) {
r = null
}
else {
if (methodName == null) {
setResult(null)
}
else {
setResult(resultReader.readResult(methodName, response))
}
r = resultReader.readResult(methodName, response)
}
UnsafeSetResult.setResult(this, r)
}
}
@@ -0,0 +1,15 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.rpc;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.concurrency.AsyncPromise;
// we cannot fix all WIP types to be nullable for now,
// but don't want to to use explicitly nullable result type for method setResult
class UnsafeSetResult {
static <T> void setResult(@NotNull AsyncPromise<T> promise, @Nullable Object result) {
//noinspection unchecked
promise.setResult((T)result);
}
}
@@ -1,26 +1,12 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.xdebugger.frame.XCompositeNode
import com.intellij.xdebugger.frame.XValueChildrenList
import com.intellij.xdebugger.frame.XValueNode
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.done
import org.jetbrains.concurrency.rejected
import org.jetbrains.concurrency.onError
import org.jetbrains.concurrency.onSuccess
import org.jetbrains.concurrency.resolvedPromise
import org.jetbrains.debugger.values.ObjectValue
import org.jetbrains.debugger.values.Value
@@ -41,10 +27,10 @@ open class BasicDebuggerViewSupport : MemberFilter, DebuggerViewSupport {
override fun computeReceiverVariable(context: VariableContext, callFrame: CallFrame, node: XCompositeNode): Promise<*> {
return callFrame.receiverVariable
.done(node) {
.onSuccess(node) {
node.addChildren(if (it == null) XValueChildrenList.EMPTY else XValueChildrenList.singleton(VariableView(it, context)), true)
}
.rejected(node) {
.onError(node) {
node.addChildren(XValueChildrenList.EMPTY, true)
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.execution.ExecutionResult
@@ -205,7 +191,8 @@ abstract class DebugProcessImpl<C : VmConnection<*>>(session: XDebugSession,
}
override final fun startPausing() {
activeOrMainVm!!.suspendContextManager.suspend().rejected(RejectErrorReporter(session, "Cannot pause"))
activeOrMainVm!!.suspendContextManager.suspend()
.onError(RejectErrorReporter(session, "Cannot pause"))
}
override final fun getCurrentStateMessage() = connection.state.message
@@ -1,25 +1,11 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.xdebugger.frame.XCompositeNode
import com.intellij.xdebugger.frame.XValueChildrenList
import com.intellij.xdebugger.frame.XValueGroup
import org.jetbrains.concurrency.done
import org.jetbrains.concurrency.errorIfNotMessage
import org.jetbrains.concurrency.onSuccess
import org.jetbrains.debugger.values.FunctionValue
import org.jetbrains.rpc.LOG
import java.util.*
@@ -29,7 +15,7 @@ internal class FunctionScopesValueGroup(private val functionValue: FunctionValue
node.setAlreadySorted(true)
functionValue.resolve()
.done(node) {
.onSuccess(node) {
val scopes = it.scopes
if (scopes == null || scopes.size == 0) {
node.addChildren(XValueChildrenList.EMPTY, true)
@@ -1,26 +1,12 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.xdebugger.XDebuggerBundle
import com.intellij.xdebugger.frame.XCompositeNode
import com.intellij.xdebugger.frame.XValueChildrenList
import com.intellij.xdebugger.frame.XValueGroup
import org.jetbrains.concurrency.done
import org.jetbrains.concurrency.rejected
import org.jetbrains.concurrency.onError
import org.jetbrains.concurrency.onSuccess
import org.jetbrains.concurrency.thenAsyncAccept
class ScopeVariablesGroup(val scope: Scope, parentContext: VariableContext, callFrame: CallFrame?) : XValueGroup(scope.createScopeNodeName()) {
@@ -42,13 +28,13 @@ class ScopeVariablesGroup(val scope: Scope, parentContext: VariableContext, call
}
promise
.done(node) {
.onSuccess(node) {
context.memberFilter
.thenAsyncAccept(node) {
if (it.hasNameMappings()) {
it.sourceNameToRaw(RECEIVER_NAME)?.let {
return@thenAsyncAccept callFrame.evaluateContext.evaluate(it)
.done(node) {
.onSuccess(node) {
VariableImpl(RECEIVER_NAME, it.value, null)
node.addChildren(XValueChildrenList.singleton(VariableView(
VariableImpl(RECEIVER_NAME, it.value, null), context)), true)
@@ -58,7 +44,7 @@ class ScopeVariablesGroup(val scope: Scope, parentContext: VariableContext, call
context.viewSupport.computeReceiverVariable(context, callFrame, node)
}
.rejected(node) {
.onError(node) {
context.viewSupport.computeReceiverVariable(context, callFrame, node)
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.icons.AllIcons
@@ -196,7 +182,7 @@ class ExecutionStackView(val suspendContext: SuspendContext<*>,
override fun computeStackFrames(firstFrameIndex: Int, container: XExecutionStack.XStackFrameContainer) {
// 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 ->
.onSuccess(suspendContext) { frames ->
val count = frames.size - firstFrameIndex
val result: List<XStackFrame>
if (count < 1) {
@@ -63,7 +63,7 @@ class VariableView(override val variableName: String, private val variable: Vari
if (variable !is ObjectProperty || variable.getter == null) {
// it is "used" expression (WEB-6779 Debugger/Variables: Automatically show used variables)
evaluateContext.evaluate(variable.name)
.done(node) {
.onSuccess(node) {
if (it.wasThrown) {
setEvaluatedValue(viewSupport.transformErrorOnGetUsedReferenceValue(it.value, null), null, node)
}
@@ -72,7 +72,7 @@ class VariableView(override val variableName: String, private val variable: Vari
computePresentation(it.value, node)
}
}
.rejected(node) { setEvaluatedValue(viewSupport.transformErrorOnGetUsedReferenceValue(null, it.message), it.message, node) }
.onError(node) { setEvaluatedValue(viewSupport.transformErrorOnGetUsedReferenceValue(null, it.message), it.message, node) }
return
}
@@ -90,7 +90,7 @@ class VariableView(override val variableName: String, private val variable: Vari
nonProtoContext = nonProtoContext.parent
}
valueModifier!!.evaluateGet(variable, evaluateContext)
.done(node) {
.onSuccess(node) {
callback.evaluated("")
setEvaluatedValue(it, null, node)
}
@@ -318,9 +318,9 @@ class VariableView(override val variableName: String, private val variable: Vari
override fun computeSourcePosition(navigatable: XNavigatable) {
if (value is FunctionValue) {
(value as FunctionValue).resolve()
.done { function ->
.onSuccess { function ->
vm!!.scriptManager.getScript(function)
.done {
.onSuccess {
navigatable.setSourcePosition(it?.let { viewSupport.getSourceInfo(null, it, function.openParenLine, function.openParenColumn) }?.let {
object : XSourcePositionWrapper(it) {
override fun createNavigatable(project: Project): Navigatable {
@@ -394,12 +394,12 @@ class VariableView(override val variableName: String, private val variable: Vari
val evaluated = AtomicBoolean()
value.fullString
.done {
.onSuccess {
if (!callback.isObsolete && evaluated.compareAndSet(false, true)) {
callback.evaluated(value.valueString!!)
}
}
.rejected { callback.errorOccurred(it.message!!) }
.onError { callback.errorOccurred(it.message!!) }
}
}
@@ -425,8 +425,8 @@ class VariableView(override val variableName: String, private val variable: Vari
}
else {
context.evaluateContext.evaluate("a.length", Collections.singletonMap<String, Any>("a", value), false)
.done(node) { node.setPresentation(icon, null, "Array[${it.value.valueString}]", true) }
.rejected(node) {
.onSuccess(node) { node.setPresentation(icon, null, "Array[${it.value.valueString}]", true) }
.onError(node) {
logger<VariableView>().error("Failed to evaluate array length: $it")
node.setPresentation(icon, null, valueString ?: "Array", true)
}
@@ -1,27 +1,13 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.debugger
import com.intellij.util.Consumer
import com.intellij.xdebugger.XDebugSession
import org.jetbrains.concurrency.errorIfNotMessage
import org.jetbrains.rpc.LOG
import java.util.function.Consumer
class RejectErrorReporter @JvmOverloads constructor(private val session: XDebugSession, private val description: String? = null) : Consumer<Throwable> {
override fun consume(error: Throwable) {
override fun accept(error: Throwable) {
if (LOG.errorIfNotMessage(error)) {
session.reportError("${if (description == null) "" else "$description: "}${error.message}")
}