IDEA-146276 Memory leak in AsyncResult.REJECTED
authorVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Fri, 30 Oct 2015 12:23:15 +0000 (13:23 +0100)
committerVladimir Krivosheev <vladimir.krivosheev@jetbrains.com>
Fri, 30 Oct 2015 12:29:30 +0000 (13:29 +0100)
13 files changed:
platform/core-api/src/com/intellij/openapi/util/AsyncResult.java
platform/core-api/src/com/intellij/openapi/util/CollectingAsyncResult.java
platform/lang-impl/src/com/intellij/ide/structureView/newStructureView/StructureViewComponent.java
platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/TestEditorManagerImpl.java
platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java
platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeUi.java
platform/platform-api/src/com/intellij/util/ui/update/LazyUiDisposable.java
platform/platform-impl/src/com/intellij/openapi/ui/playback/util/ProjectPlaybackCall.java
platform/platform-tests/testSrc/com/intellij/ide/util/treeView/TreeUiTest.java
platform/structure-view-api/src/com/intellij/ide/util/treeView/AbstractTreeStructure.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java
platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java

index 2d0a4a834fe070fe810fde3e9a7e9bdfa1425f59..8c7a536b541fb086ed4971828ad95aa7f434d21f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -28,9 +28,6 @@ import java.util.List;
 public class AsyncResult<T> extends ActionCallback {
   private static final Logger LOG = Logger.getInstance(AsyncResult.class);
 
-  private static final AsyncResult REJECTED = new Rejected();
-  private static final AsyncResult DONE_LIST = new Done<Object>(Collections.EMPTY_LIST);
-
   protected T myResult;
 
   public AsyncResult() {
@@ -68,7 +65,12 @@ public class AsyncResult<T> extends ActionCallback {
     return subResult;
   }
 
+  @SuppressWarnings("unused")
   @NotNull
+  @Deprecated
+  /**
+   * @deprecated Don't use AsyncResult - use Promise instead.
+   */
   public ActionCallback subCallback(@NotNull Consumer<T> doneHandler) {
     ActionCallback subCallback = new ActionCallback();
     doWhenDone(new SubCallbackDoneCallback<T>(subCallback, doneHandler)).notifyWhenRejected(subCallback);
@@ -101,21 +103,6 @@ public class AsyncResult<T> extends ActionCallback {
     return this;
   }
 
-  @NotNull
-  @Deprecated
-  /**
-   * @deprecated Use {@link #doWhenRejected(com.intellij.util.Consumer)} (to remove in IDEA 16)
-   */
-  public AsyncResult<T> doWhenRejected(@SuppressWarnings("deprecation") @NotNull final Handler<T> handler) {
-    doWhenRejected(new Runnable() {
-      @Override
-      public void run() {
-        handler.run(myResult);
-      }
-    });
-    return this;
-  }
-
   @NotNull
   public AsyncResult<T> doWhenRejected(@NotNull final PairConsumer<T, String> consumer) {
     doWhenRejected(new Runnable() {
@@ -168,12 +155,20 @@ public class AsyncResult<T> extends ActionCallback {
     void run(T t);
   }
 
+  @Deprecated
+  /**
+   * @deprecated Don't use AsyncResult - use Promise instead.
+   */
   public static class Done<T> extends AsyncResult<T> {
     public Done(T value) {
       setDone(value);
     }
   }
 
+  @Deprecated
+  /**
+   * @deprecated Don't use AsyncResult - use Promise instead.
+   */
   public static class Rejected<T> extends AsyncResult<T> {
     public Rejected() {
       setRejected();
@@ -185,12 +180,20 @@ public class AsyncResult<T> extends ActionCallback {
   }
 
   @NotNull
+  @Deprecated
+  /**
+   * @deprecated Don't use AsyncResult - use Promise instead.
+   */
   public static <R> AsyncResult<R> rejected() {
-    //noinspection unchecked
-    return REJECTED;
+    //noinspection unchecked,deprecation
+    return new Rejected();
   }
 
   @NotNull
+  @Deprecated
+  /**
+   * @deprecated Don't use AsyncResult - use Promise instead.
+   */
   public static <R> AsyncResult<R> rejected(@NotNull String errorMessage) {
     AsyncResult<R> result = new AsyncResult<R>();
     result.reject(errorMessage);
@@ -203,9 +206,13 @@ public class AsyncResult<T> extends ActionCallback {
   }
 
   @NotNull
+  @Deprecated
+  /**
+   * @deprecated Don't use AsyncResult - use Promise instead.
+   */
   public static <R extends List> AsyncResult<R> doneList() {
     //noinspection unchecked
-    return DONE_LIST;
+    return done((R)Collections.emptyList());
   }
 
   // we don't use inner class, avoid memory leak, we don't want to hold this result while dependent is computing
index 3d22b169d224b0cac0bde4f9a35b9c53557545dd..4829bdb6d0fb0d5e23277c412a2e04281f8589ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * 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.
@@ -22,8 +22,10 @@ import org.jetbrains.annotations.NotNull;
 import java.util.ArrayList;
 import java.util.List;
 
+@SuppressWarnings("unused")
+@Deprecated
 /**
- * Please note - rejected results are not collected.
+ * @deprecated Don't use AsyncResult - use Promise instead.
  */
 public final class CollectingAsyncResult<T> {
   private final List<AsyncResult<T>> asyncResults = new SmartList<AsyncResult<T>>();
index 9619043e859d723e5e1bef93dd1f564045ada01c..0eec66ec69889c6c18fe4b8251b3ce48cfcfab51 100644 (file)
@@ -458,10 +458,10 @@ public class StructureViewComponent extends SimpleToolWindowPanel implements Tre
   }
 
   public AsyncResult<AbstractTreeNode> expandPathToElement(Object element) {
-    if (myAbstractTreeBuilder == null) return new AsyncResult.Rejected<AbstractTreeNode>();
+    if (myAbstractTreeBuilder == null) return AsyncResult.rejected();
 
     ArrayList<AbstractTreeNode> pathToElement = getPathToElement(element);
-    if (pathToElement.isEmpty()) return new AsyncResult.Rejected<AbstractTreeNode>();
+    if (pathToElement.isEmpty()) return AsyncResult.rejected();
 
     final AsyncResult<AbstractTreeNode> result = new AsyncResult<AbstractTreeNode>();
     final AbstractTreeNode toExpand = pathToElement.get(pathToElement.size() - 1);
index 5fcfcaaf5de92c587a83530b74c7779914beb4ef..22dc0a0f78236c53831350caa47ed8b220285939 100644 (file)
@@ -255,7 +255,7 @@ public class TestEditorManagerImpl extends FileEditorManagerEx implements Projec
   @NotNull
   @Override
   public AsyncResult<EditorWindow> getActiveWindow() {
-    return new AsyncResult.Done<EditorWindow>(null);
+    return AsyncResult.done(null);
   }
 
   @Override
index 21b2c64821b56c68b0746f3f3d8a79c8a736eb75..861893622541bd34c23c05900c032d3164cb267f 100644 (file)
@@ -531,10 +531,10 @@ public class AbstractTreeBuilder implements Disposable {
 
   @NotNull
   public AsyncResult<Object> revalidateElement(Object element) {
-    if (isDisposed()) return new AsyncResult.Rejected<Object>();
+    if (isDisposed()) return AsyncResult.rejected();
 
     AbstractTreeStructure structure = getTreeStructure();
-    if (structure == null) return new AsyncResult.Rejected<Object>();
+    if (structure == null) return AsyncResult.rejected();
 
     return structure.revalidateElement(element);
   }
index 85b0f1b19ac0a9575be100f05fb18b6603df7881..440305c85adb762d372503a223211f7255cdd4d9 100644 (file)
@@ -2988,7 +2988,7 @@ public class AbstractTreeUi {
   }
 
   @NotNull
-  private Promise<Void> processExistingNode(@NotNull final DefaultMutableTreeNode childNode,
+  private Promise<?> processExistingNode(@NotNull final DefaultMutableTreeNode childNode,
                                              final NodeDescriptor childDescriptor,
                                              @NotNull final DefaultMutableTreeNode parentNode,
                                              @NotNull final MutualMap<Object, Integer> elementToIndexMap,
index 8d5b392c2e1e8aca97388bdc878070197a358449..eb0dbc7ec49908cf21972a8e10a96798e40127f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,11 +23,12 @@ import com.intellij.openapi.actionSystem.DataKey;
 import com.intellij.openapi.actionSystem.PlatformDataKeys;
 import com.intellij.openapi.application.ApplicationManager;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.AsyncResult;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.util.Consumer;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.concurrency.Promise;
 
 import javax.swing.*;
 
@@ -55,16 +56,17 @@ public abstract class LazyUiDisposable<T extends Disposable> implements Activata
     if (myWasEverShown) return;
 
     try {
-      findParentDisposable().doWhenDone(new Consumer<Disposable>() {
-        public void consume(Disposable parent) {
-          Project project = null;
-          if (ApplicationManager.getApplication() != null) {
-            project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
+      findParentDisposable()
+        .done(new Consumer<Disposable>() {
+          public void consume(Disposable parent) {
+            Project project = null;
+            if (ApplicationManager.getApplication() != null) {
+              project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext());
+            }
+            initialize(parent, myChild, project);
+            Disposer.register(parent, myChild);
           }
-          initialize(parent, myChild, project);
-          Disposer.register(parent, myChild);
-        }
-      });
+        });
     }
     finally {
       myWasEverShown = true;
@@ -77,24 +79,25 @@ public abstract class LazyUiDisposable<T extends Disposable> implements Activata
   protected abstract void initialize(@NotNull Disposable parent, @NotNull T child, @Nullable Project project);
 
   @NotNull
-  private AsyncResult<Disposable> findParentDisposable() {
+  private Promise<Disposable> findParentDisposable() {
     return findDisposable(myParent, PlatformDataKeys.UI_DISPOSABLE);
   }
 
-
-  private static AsyncResult<Disposable> findDisposable(Disposable defaultValue, final DataKey<? extends Disposable> key) {
+  private static Promise<Disposable> findDisposable(Disposable defaultValue, final DataKey<? extends Disposable> key) {
     if (defaultValue == null) {
       if (ApplicationManager.getApplication() != null) {
-        final AsyncResult<Disposable> result = new AsyncResult<Disposable>();
-        DataManager.getInstance().getDataContextFromFocus().doWhenDone(new Consumer<DataContext>() {
-          public void consume(DataContext context) {
-            Disposable disposable = key.getData(context);
-            if (disposable == null) {
-              disposable = Disposer.get("ui");
+        final AsyncPromise<Disposable> result = new AsyncPromise<Disposable>();
+        DataManager.getInstance().getDataContextFromFocus()
+          .doWhenDone(new Consumer<DataContext>() {
+            @Override
+            public void consume(DataContext context) {
+              Disposable disposable = key.getData(context);
+              if (disposable == null) {
+                disposable = Disposer.get("ui");
+              }
+              result.setResult(disposable);
             }
-            result.setDone(disposable);
-          }
-        });
+          });
         return result;
       }
       else {
@@ -102,8 +105,7 @@ public abstract class LazyUiDisposable<T extends Disposable> implements Activata
       }
     }
     else {
-      return new AsyncResult.Done<Disposable>(defaultValue);
+      return Promise.resolve(defaultValue);
     }
   }
-
-}
+}
\ No newline at end of file
index c7fe9d23fefac86ddd8688195d03a704a8e8230c..7b5ae6007263abdf33a08964af89dd6f239d0090 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -32,14 +32,14 @@ public class ProjectPlaybackCall {
     try {
       File parentDir = FileUtil.createTempDirectory("funcTest", "");
       File sourceDir = context.getPathMacro().resolveFile(path, context.getBaseDir());
-      
+
       context.message("Cloning project: " + sourceDir.getAbsolutePath(), context.getCurrentLine());
       FileUtil.copyDir(sourceDir, parentDir);
       File projectDir = new File(parentDir, sourceDir.getName());
       return openProject(context, projectDir.getAbsolutePath());
     }
     catch (IOException e) {
-      return new AsyncResult.Rejected<String>("Cannot create temp directory for clone");
+      return AsyncResult.rejected("Cannot create temp directory for clone");
     }
   }
 
index 99959d3a7d7440935bc2967798cbfff0d3db1445..baf38451130dab54b209578e7a8f626dd52af89b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * 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.
@@ -2117,10 +2117,10 @@ public class TreeUiTest extends AbstractTreeBuilderTest {
       @Override
       public AsyncResult<Object> revalidate(NodeElement element) {
         if (element == actionSystem) {
-          return new AsyncResult.Done<Object>(newActionSystem);
+          return AsyncResult.done(newActionSystem);
         }
         else if (element == fabrique) {
-          return new AsyncResult.Done<Object>(newFabrique);
+          return AsyncResult.done(newFabrique);
         }
         return null;
       }
index 262ab06fc625dc67450df2bff6d63d1b2aaeb637..2ef543ea28ab63654fed585a7aee7574abbbe50c 100644 (file)
@@ -73,6 +73,6 @@ public abstract class AbstractTreeStructure {
   }
 
   public AsyncResult<Object> revalidateElement(Object element) {
-    return new AsyncResult.Done<Object>(element);
+    return AsyncResult.done(element);
   }
 }
\ No newline at end of file
index 19a17516efd4b78ed9d0bec2f0f38e5fd762e6de..206c746800735ae1f06869ea6ce903b3bdc68cb2 100644 (file)
@@ -37,7 +37,6 @@ import com.intellij.openapi.fileTypes.StdFileTypes;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.ui.popup.PopupStep;
 import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.AsyncResult;
 import com.intellij.openapi.util.Computable;
 import com.intellij.openapi.util.TextRange;
 import com.intellij.openapi.util.text.StringUtil;
@@ -73,6 +72,9 @@ import com.intellij.xdebugger.ui.DebuggerColors;
 import gnu.trove.THashMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.concurrency.AsyncPromise;
+import org.jetbrains.concurrency.Promise;
+import org.jetbrains.concurrency.PromiseKt;
 
 import javax.swing.*;
 import javax.swing.event.ListSelectionEvent;
@@ -137,14 +139,14 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
   }
 
   @NotNull
-  public static <P extends XBreakpointProperties> AsyncResult<XLineBreakpoint> toggleAndReturnLineBreakpoint(@NotNull final Project project,
-                                                                                                             @NotNull final XLineBreakpointType<P> type,
-                                                                                                             @NotNull final XSourcePosition position,
-                                                                                                             final boolean temporary,
-                                                                                                             @Nullable final Editor editor) {
-    return new WriteAction<AsyncResult<XLineBreakpoint>>() {
+  public static <P extends XBreakpointProperties> Promise<XLineBreakpoint> toggleAndReturnLineBreakpoint(@NotNull final Project project,
+                                                                                                         @NotNull final XLineBreakpointType<P> type,
+                                                                                                         @NotNull final XSourcePosition position,
+                                                                                                         final boolean temporary,
+                                                                                                         @Nullable final Editor editor) {
+    return new WriteAction<Promise<XLineBreakpoint>>() {
       @Override
-      protected void run(@NotNull Result<AsyncResult<XLineBreakpoint>> result) throws Throwable {
+      protected void run(@NotNull Result<Promise<XLineBreakpoint>> result) throws Throwable {
         final VirtualFile file = position.getFile();
         final int line = position.getLine();
         final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
@@ -157,7 +159,7 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
           if (!variants.isEmpty() && editor != null) {
             RelativePoint relativePoint = DebuggerUIUtil.getPositionForPopup(editor, line);
             if (variants.size() > 1 && relativePoint != null) {
-              final AsyncResult<XLineBreakpoint> res = new AsyncResult<XLineBreakpoint>();
+              final AsyncPromise<XLineBreakpoint> res = new AsyncPromise<XLineBreakpoint>();
               class MySelectionListener implements ListSelectionListener {
                 RangeHighlighter myHighlighter = null;
 
@@ -233,7 +235,7 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
                       @Override
                       public void run() {
                         P properties = (P)selectedValue.createProperties();
-                        res.setDone(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary));
+                        res.setResult(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary));
                       }
                     });
                     return FINAL_CHOICE;
@@ -252,17 +254,17 @@ public class XDebuggerUtilImpl extends XDebuggerUtil {
             }
             else {
               P properties = variants.get(0).createProperties();
-              result.setResult(AsyncResult.done(
-                (XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)));
+              result.setResult(
+                Promise.resolve((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)));
               return;
             }
           }
           P properties = type.createBreakpointProperties(file, line);
-          result.setResult(AsyncResult
-                             .done((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)));
+          result.setResult(
+            Promise.resolve((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)));
           return;
         }
-        result.setResult(AsyncResult.<XLineBreakpoint>rejected());
+        result.setResult(PromiseKt.<XLineBreakpoint>rejectedPromise());
       }
     }.execute().getResultObject();
   }
index 7b49b34dc05f0ba4ae4a754759a984215d715cde..6217a8c90352b99ab386ae03d7d02bea40a9a73c 100644 (file)
@@ -22,7 +22,6 @@ import com.intellij.openapi.editor.Editor;
 import com.intellij.openapi.editor.FoldRegion;
 import com.intellij.openapi.editor.markup.GutterIconRenderer;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.AsyncResult;
 import com.intellij.openapi.util.Pair;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -38,6 +37,8 @@ import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider;
 import org.jetbrains.annotations.NonNls;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
+import org.jetbrains.concurrency.Promise;
+import org.jetbrains.concurrency.PromiseKt;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -135,11 +136,11 @@ public class XBreakpointUtil {
    * - if folded, checks if line breakpoints could be toggled inside folded text
    */
   @NotNull
-  public static AsyncResult<XLineBreakpoint> toggleLineBreakpoint(@NotNull Project project,
-                                                                  @NotNull XSourcePosition position,
-                                                                  @Nullable Editor editor,
-                                                                  boolean temporary,
-                                                                  boolean moveCarret) {
+  public static Promise<XLineBreakpoint> toggleLineBreakpoint(@NotNull Project project,
+                                                              @NotNull XSourcePosition position,
+                                                              @Nullable Editor editor,
+                                                              boolean temporary,
+                                                              boolean moveCarret) {
     int lineStart = position.getLine();
     VirtualFile file = position.getFile();
     // for folded text check each line and find out type with the biggest priority
@@ -153,7 +154,7 @@ public class XBreakpointUtil {
 
     final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
     XLineBreakpointType<?>[] lineTypes = XDebuggerUtil.getInstance().getLineBreakpointTypes();
-    XLineBreakpointType typeWinner = null;
+    XLineBreakpointType<?> typeWinner = null;
     int lineWinner = -1;
     for (int line = lineStart; line <= linesEnd; line++) {
       int maxPriority = 0;
@@ -179,8 +180,7 @@ public class XBreakpointUtil {
     if (typeWinner != null) {
       XSourcePosition winPosition = (lineStart == lineWinner) ? position : XSourcePositionImpl.create(file, lineWinner);
       if (winPosition != null) {
-        AsyncResult<XLineBreakpoint> res =
-          XDebuggerUtilImpl.toggleAndReturnLineBreakpoint(project, typeWinner, winPosition, temporary, editor);
+        Promise<XLineBreakpoint> res = XDebuggerUtilImpl.toggleAndReturnLineBreakpoint(project, typeWinner, winPosition, temporary, editor);
 
         if (editor != null && lineStart != lineWinner) {
           int offset = editor.getDocument().getLineStartOffset(lineWinner);
@@ -193,6 +193,6 @@ public class XBreakpointUtil {
       }
     }
 
-    return AsyncResult.rejected();
+    return PromiseKt.rejectedPromise();
   }
 }
index 8210e45f17da59be13b2e0eb5b7536ee133eb222..be948d3cf975ed8f870faeebe3761a166284fa78 100644 (file)
@@ -39,7 +39,6 @@ import com.intellij.openapi.fileEditor.TextEditor;
 import com.intellij.openapi.project.DumbAwareRunnable;
 import com.intellij.openapi.project.Project;
 import com.intellij.openapi.startup.StartupManager;
-import com.intellij.openapi.util.AsyncResult;
 import com.intellij.openapi.util.Disposer;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.vfs.VirtualFile;
@@ -301,25 +300,27 @@ public class XLineBreakpointManager {
                 if (!myProject.isDisposed() && myProject.isInitialized() && file.isValid()) {
                   ActionManagerEx.getInstanceEx().fireBeforeActionPerformed(IdeActions.ACTION_TOGGLE_LINE_BREAKPOINT, e.getMouseEvent());
 
-                  AsyncResult<XLineBreakpoint> result = XBreakpointUtil.toggleLineBreakpoint(
-                    myProject, XSourcePositionImpl.create(file, line), editor, mouseEvent.isAltDown(), false);
-                  result.doWhenDone(new Consumer<XLineBreakpoint>() {
-                    @Override
-                    public void consume(XLineBreakpoint breakpoint) {
-                      if (!mouseEvent.isAltDown() && mouseEvent.isShiftDown() && breakpoint != null) {
-                        breakpoint.setSuspendPolicy(SuspendPolicy.NONE);
-                        String selection = editor.getSelectionModel().getSelectedText();
-                        if (selection != null) {
-                          breakpoint.setLogExpression(selection);
+                  XBreakpointUtil
+                    .toggleLineBreakpoint(myProject, XSourcePositionImpl.create(file, line), editor, mouseEvent.isAltDown(), false)
+                    .done(new Consumer<XLineBreakpoint>() {
+                      @Override
+                      public void consume(XLineBreakpoint breakpoint) {
+                        if (!mouseEvent.isAltDown() && mouseEvent.isShiftDown() && breakpoint != null) {
+                          breakpoint.setSuspendPolicy(SuspendPolicy.NONE);
+                          String selection = editor.getSelectionModel().getSelectedText();
+                          if (selection != null) {
+                            breakpoint.setLogExpression(selection);
+                          }
+                          else {
+                            breakpoint.setLogMessage(true);
+                          }
+                          // edit breakpoint
+                          DebuggerUIUtil
+                            .showXBreakpointEditorBalloon(myProject, mouseEvent.getPoint(), ((EditorEx)editor).getGutterComponentEx(),
+                                                          false, breakpoint);
                         }
-                        else {
-                          breakpoint.setLogMessage(true);
-                        }
-                        // edit breakpoint
-                        DebuggerUIUtil.showXBreakpointEditorBalloon(myProject, mouseEvent.getPoint(), ((EditorEx)editor).getGutterComponentEx(), false, breakpoint);
                       }
-                    }
-                  });
+                    });
                 }
               }
             });