diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java index 20ba3dad8dbc..543f17ed3581 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XLineBreakpointType.java @@ -1,17 +1,5 @@ /* - * 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-2017 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.xdebugger.breakpoints; @@ -30,6 +18,7 @@ import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.concurrency.Promise; import javax.swing.*; import java.util.Collections; @@ -136,6 +125,11 @@ public abstract class XLineBreakpointType

exten return Collections.emptyList(); } + @NotNull + public Promise> computeVariantsAsync(@NotNull Project project, @NotNull XSourcePosition position) { + return Promise.resolve(computeVariants(project, position)); + } + public abstract class XLineBreakpointVariant { public abstract String getText(); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java index 87e41cd604c7..00495185a9fa 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java @@ -9,10 +9,7 @@ import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ReadAction; -import com.intellij.openapi.application.Result; -import com.intellij.openapi.application.WriteAction; +import com.intellij.openapi.application.*; import com.intellij.openapi.editor.Caret; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -35,6 +32,7 @@ import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.ui.GuiUtils; import com.intellij.ui.SimpleColoredText; import com.intellij.ui.awt.RelativePoint; import com.intellij.ui.popup.list.ListPopupImpl; @@ -145,145 +143,154 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { final boolean temporary, @Nullable final Editor editor, boolean canRemove) { - return new WriteAction>() { - @Override - protected void run(@NotNull Result> result) throws Throwable { - final VirtualFile file = position.getFile(); - final int line = position.getLine(); - final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); - XLineBreakpoint

breakpoint = breakpointManager.findBreakpointAtLine(type, file, line); - if (breakpoint != null) { - if (!temporary && canRemove) { - breakpointManager.removeBreakpoint(breakpoint); - } - } - else { - List.XLineBreakpointVariant> variants = type.computeVariants(project, position); - if (!variants.isEmpty() && editor != null) { - RelativePoint relativePoint = DebuggerUIUtil.getPositionForPopup(editor, line); - if (variants.size() > 1 && relativePoint != null) { - final AsyncPromise res = new AsyncPromise<>(); - class MySelectionListener implements ListSelectionListener { - RangeHighlighter myHighlighter = null; - - @Override - public void valueChanged(ListSelectionEvent e) { - if (!e.getValueIsAdjusting()) { - updateHighlighter(((JList)e.getSource()).getSelectedValue()); - } - } - - public void initialSet(Object value) { - if (myHighlighter == null) { - updateHighlighter(value); - } - } - - void updateHighlighter(Object value) { - clearHighlighter(); - if (value instanceof XLineBreakpointType.XLineBreakpointVariant) { - TextRange range = ((XLineBreakpointType.XLineBreakpointVariant)value).getHighlightRange(); - TextRange lineRange = DocumentUtil.getLineTextRange(editor.getDocument(), line); - if (range != null) { - range = range.intersection(lineRange); - } - else { - range = lineRange; - } - if (range != null && !range.isEmpty()) { - EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); - TextAttributes attributes = scheme.getAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES); - myHighlighter = editor.getMarkupModel().addRangeHighlighter( - range.getStartOffset(), range.getEndOffset(), DebuggerColors.BREAKPOINT_HIGHLIGHTER_LAYER, attributes, - HighlighterTargetArea.EXACT_RANGE); - } - } - } - - private void clearHighlighter() { - if (myHighlighter != null) { - myHighlighter.dispose(); - } - } - } - - // calculate default item - int caretOffset = editor.getCaretModel().getOffset(); - XLineBreakpointType

.XLineBreakpointVariant defaultVariant = null; - for (XLineBreakpointType

.XLineBreakpointVariant variant : variants) { - TextRange range = variant.getHighlightRange(); - if (range != null && range.contains(caretOffset)) { - //noinspection ConstantConditions - if (defaultVariant == null || defaultVariant.getHighlightRange().getLength() > range.getLength()) { - defaultVariant = variant; - } - } - } - final int defaultIndex = defaultVariant != null ? variants.indexOf(defaultVariant) : 0; - - final MySelectionListener selectionListener = new MySelectionListener(); - ListPopupImpl popup = new ListPopupImpl( - new BaseListPopupStep("Set Breakpoint", variants) { - @NotNull - @Override - public String getTextFor(XLineBreakpointType.XLineBreakpointVariant value) { - return value.getText(); - } - - @Override - public Icon getIconFor(XLineBreakpointType.XLineBreakpointVariant value) { - return value.getIcon(); - } - - @Override - public void canceled() { - selectionListener.clearHighlighter(); - } - - @Override - public PopupStep onChosen(final XLineBreakpointType.XLineBreakpointVariant selectedValue, boolean finalChoice) { - selectionListener.clearHighlighter(); - WriteAction.run(() -> { - P properties = (P)selectedValue.createProperties(); - res.setResult(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); - }); - return FINAL_CHOICE; - } - - @Override - public int getDefaultOptionIndex() { - return defaultIndex; - } - }) { - @Override - protected void afterShow() { - super.afterShow(); - selectionListener.initialSet(getList().getSelectedValue()); - } - }; - DebuggerUIUtil.registerExtraHandleShortcuts(popup, IdeActions.ACTION_TOGGLE_LINE_BREAKPOINT); - popup.setAdText(DebuggerUIUtil.getSelectionShortcutsAdText(IdeActions.ACTION_TOGGLE_LINE_BREAKPOINT)); - - popup.addListSelectionListener(selectionListener); - popup.show(relativePoint); - result.setResult(res); - return; - } - else { - P properties = variants.get(0).createProperties(); - result.setResult( - Promise.resolve(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); - return; - } - } - P properties = type.createBreakpointProperties(file, line); - result.setResult( - Promise.resolve(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); + final VirtualFile file = position.getFile(); + final int line = position.getLine(); + final XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); + XLineBreakpoint

breakpoint = breakpointManager.findBreakpointAtLine(type, file, line); + if (breakpoint != null) { + if (!temporary && canRemove) { + WriteAction.run(() -> breakpointManager.removeBreakpoint(breakpoint)); + } + } + else { + Promise.XLineBreakpointVariant>> variantsPromise = type.computeVariantsAsync(project, position); + final AsyncPromise res = new AsyncPromise<>(); + variantsPromise.done(variants -> GuiUtils.invokeLaterIfNeeded(() -> { + XLineBreakpoint

alreadyAddedBreakpoint = breakpointManager.findBreakpointAtLine(type, file, line); + if (alreadyAddedBreakpoint != null) { return; } - result.setResult(rejectedPromise()); - } - }.execute().getResultObject(); + if (!variants.isEmpty() && editor != null) { + RelativePoint relativePoint = DebuggerUIUtil.getPositionForPopup(editor, line); + if (variants.size() > 1 && relativePoint != null) { + class MySelectionListener implements ListSelectionListener { + RangeHighlighter myHighlighter = null; + + @Override + public void valueChanged(ListSelectionEvent e) { + if (!e.getValueIsAdjusting()) { + updateHighlighter(((JList)e.getSource()).getSelectedValue()); + } + } + + public void initialSet(Object value) { + if (myHighlighter == null) { + updateHighlighter(value); + } + } + + void updateHighlighter(Object value) { + clearHighlighter(); + if (value instanceof XLineBreakpointType.XLineBreakpointVariant) { + TextRange range = ((XLineBreakpointType.XLineBreakpointVariant)value).getHighlightRange(); + TextRange lineRange = DocumentUtil.getLineTextRange(editor.getDocument(), line); + if (range != null) { + range = range.intersection(lineRange); + } + else { + range = lineRange; + } + if (range != null && !range.isEmpty()) { + EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme(); + TextAttributes attributes = scheme.getAttributes(DebuggerColors.BREAKPOINT_ATTRIBUTES); + myHighlighter = editor.getMarkupModel().addRangeHighlighter( + range.getStartOffset(), range.getEndOffset(), DebuggerColors.BREAKPOINT_HIGHLIGHTER_LAYER, attributes, + HighlighterTargetArea.EXACT_RANGE); + } + } + } + + private void clearHighlighter() { + if (myHighlighter != null) { + myHighlighter.dispose(); + } + } + } + + // calculate default item + int caretOffset = editor.getCaretModel().getOffset(); + XLineBreakpointType

.XLineBreakpointVariant defaultVariant = null; + for (XLineBreakpointType

.XLineBreakpointVariant variant : variants) { + TextRange range = variant.getHighlightRange(); + if (range != null && range.contains(caretOffset)) { + //noinspection ConstantConditions + if (defaultVariant == null || defaultVariant.getHighlightRange().getLength() > range.getLength()) { + defaultVariant = variant; + } + } + } + final int defaultIndex = defaultVariant != null ? variants.indexOf(defaultVariant) : 0; + + final MySelectionListener selectionListener = new MySelectionListener(); + ListPopupImpl popup = new ListPopupImpl( + new BaseListPopupStep("Set Breakpoint", variants) { + @NotNull + @Override + public String getTextFor(XLineBreakpointType.XLineBreakpointVariant value) { + return value.getText(); + } + + @Override + public Icon getIconFor(XLineBreakpointType.XLineBreakpointVariant value) { + return value.getIcon(); + } + + @Override + public void canceled() { + selectionListener.clearHighlighter(); + res.cancel(); + } + + @Override + public PopupStep onChosen(final XLineBreakpointType.XLineBreakpointVariant selectedValue, boolean finalChoice) { + selectionListener.clearHighlighter(); + P properties = (P)selectedValue.createProperties(); + insertBreakpoint(properties, res, breakpointManager, file, line, type, temporary); + return FINAL_CHOICE; + } + + @Override + public int getDefaultOptionIndex() { + return defaultIndex; + } + }) { + @Override + protected void afterShow() { + super.afterShow(); + selectionListener.initialSet(getList().getSelectedValue()); + } + }; + DebuggerUIUtil.registerExtraHandleShortcuts(popup, IdeActions.ACTION_TOGGLE_LINE_BREAKPOINT); + popup.setAdText(DebuggerUIUtil.getSelectionShortcutsAdText(IdeActions.ACTION_TOGGLE_LINE_BREAKPOINT)); + + popup.addListSelectionListener(selectionListener); + popup.show(relativePoint); + return; + } + else { + P properties = variants.get(0).createProperties(); + insertBreakpoint(properties, res, breakpointManager, file, line, type, temporary); + return; + } + } + P properties = type.createBreakpointProperties(file, line); + insertBreakpoint(properties, res, breakpointManager, file, line, type, temporary); + }, ModalityState.defaultModalityState())) + .rejected(error -> ApplicationManager.getApplication().invokeLater(() -> res.setError(error))); + + return res; + } + return rejectedPromise(); + } + + private static

void insertBreakpoint(P properties, + AsyncPromise res, + XBreakpointManager breakpointManager, + VirtualFile file, + int line, + XLineBreakpointType

type, + Boolean temporary) { + WriteAction.run(() -> res.setResult(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary))); } @Override