diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java b/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java index f17787b67de6..52665815abb2 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/CompoundPositionManager.java @@ -79,6 +79,7 @@ public class CompoundPositionManager extends PositionManagerEx implements MultiR return defaultValue; } + @Nullable @Override public SourcePosition getSourcePosition(final Location location) { if (location == null) return null; diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java index 43b131c92c25..2ed9b5283ada 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java @@ -20,6 +20,7 @@ import com.intellij.debugger.NoDataException; import com.intellij.debugger.PositionManager; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.evaluation.EvaluateException; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.debugger.jdi.VirtualMachineProxyImpl; import com.intellij.debugger.requests.ClassPrepareRequestor; import com.intellij.execution.filters.LineNumbersMapping; @@ -122,6 +123,7 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio }); } + @Nullable public SourcePosition getSourcePosition(final Location location) throws NoDataException { DebuggerManagerThreadImpl.assertIsManagerThread(); if(location == null) { @@ -254,51 +256,17 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio PsiFile file = original.getFile(); int line = original.getLine(); if (LambdaMethodFilter.isLambdaName(myExpectedMethodName) && myLambdaOrdinal > -1) { + List lambdas = DebuggerUtilsEx.collectLambdas(original, false); + Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); if (document == null || line >= document.getLineCount()) { return original; } - PsiElement element = original.getElementAt(); - TextRange lineRange = new TextRange(document.getLineStartOffset(line), document.getLineEndOffset(line)); - do { - PsiElement parent = element.getParent(); - if (parent == null || (parent.getTextOffset() < lineRange.getStartOffset())) { - break; - } - element = parent; - } - while(true); - final List lambdas = new ArrayList(3); - final PsiElementVisitor lambdaCollector = new JavaRecursiveElementVisitor() { - @Override - public void visitLambdaExpression(PsiLambdaExpression expression) { - super.visitLambdaExpression(expression); - lambdas.add(expression); - } - }; - element.accept(lambdaCollector); - // add initial lambda if we're inside already - NavigatablePsiElement method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiLambdaExpression.class); - if (method instanceof PsiLambdaExpression) { - lambdas.add((PsiLambdaExpression)method); - } - for (PsiElement sibling = getNextElement(element); sibling != null; sibling = getNextElement(sibling)) { - if (!lineRange.intersects(sibling.getTextRange())) { - break; - } - sibling.accept(lambdaCollector); - } if (myLambdaOrdinal < lambdas.size()) { - PsiElement body = lambdas.get(myLambdaOrdinal).getBody(); - if (body instanceof PsiCodeBlock) { - for (PsiStatement statement : ((PsiCodeBlock)body).getStatements()) { - if (lineRange.intersects(statement.getTextRange())) { - body = statement; - break; - } - } + PsiElement firstElem = DebuggerUtilsEx.getFirstElementOnTheLine(lambdas.get(myLambdaOrdinal), document, line); + if (firstElem != null) { + return SourcePosition.createFromElement(firstElem); } - return SourcePosition.createFromElement(body); } } else { @@ -316,14 +284,6 @@ public class PositionManagerImpl implements PositionManager, MultiRequestPositio }); } - private static PsiElement getNextElement(PsiElement element) { - PsiElement sibling = element.getNextSibling(); - if (sibling != null) return sibling; - element = element.getParent(); - if (element != null) return getNextElement(element); - return null; - } - @Nullable @Override public RangeHighlighter createHighlighter(Document document, Project project, TextAttributes attributes) { diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextRunnable.java b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextRunnable.java index 6df6a1463d71..671bd9813bb9 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextRunnable.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/SuspendContextRunnable.java @@ -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. @@ -15,8 +15,6 @@ */ package com.intellij.debugger.engine; -import com.intellij.debugger.engine.SuspendContextImpl; - public interface SuspendContextRunnable { void run(SuspendContextImpl suspendContext) throws Exception; } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java index 6d908e1c7476..359f61fdf403 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java @@ -58,6 +58,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.pom.Navigatable; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.ui.classFilter.ClassFilter; import com.intellij.ui.content.Content; import com.intellij.unscramble.ThreadDumpPanel; @@ -779,4 +780,85 @@ public abstract class DebuggerUtilsEx extends DebuggerUtils { res.append(location.method().name()); return res.toString(); } + + private static PsiElement getNextElement(PsiElement element) { + PsiElement sibling = element.getNextSibling(); + if (sibling != null) return sibling; + element = element.getParent(); + if (element != null) return getNextElement(element); + return null; + } + + public static List collectLambdas(SourcePosition position, final boolean onlyOnTheLine) { + ApplicationManager.getApplication().assertReadAccessAllowed(); + PsiFile file = position.getFile(); + int line = position.getLine(); + Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + if (document == null || line >= document.getLineCount()) { + return Collections.emptyList(); + } + PsiElement element = position.getElementAt(); + final TextRange lineRange = new TextRange(document.getLineStartOffset(line), document.getLineEndOffset(line)); + do { + PsiElement parent = element.getParent(); + if (parent == null || (parent.getTextOffset() < lineRange.getStartOffset())) { + break; + } + element = parent; + } + while(true); + + final List lambdas = new ArrayList(3); + final PsiElementVisitor lambdaCollector = new JavaRecursiveElementVisitor() { + @Override + public void visitLambdaExpression(PsiLambdaExpression expression) { + super.visitLambdaExpression(expression); + if (!onlyOnTheLine || lineRange.intersects(expression.getTextRange())) { + lambdas.add(expression); + } + } + }; + element.accept(lambdaCollector); + // add initial lambda if we're inside already + NavigatablePsiElement method = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiLambdaExpression.class); + if (method instanceof PsiLambdaExpression) { + lambdas.add((PsiLambdaExpression)method); + } + for (PsiElement sibling = getNextElement(element); sibling != null; sibling = getNextElement(sibling)) { + if (!lineRange.intersects(sibling.getTextRange())) { + break; + } + sibling.accept(lambdaCollector); + } + return lambdas; + } + + @Nullable + public static PsiElement getFirstElementOnTheLine(PsiLambdaExpression lambda, Document document, int line) { + ApplicationManager.getApplication().assertReadAccessAllowed(); + TextRange lineRange = new TextRange(document.getLineStartOffset(line), document.getLineEndOffset(line)); + if (!lineRange.intersects(lambda.getTextRange())) return null; + PsiElement body = lambda.getBody(); + if (body instanceof PsiCodeBlock) { + for (PsiStatement statement : ((PsiCodeBlock)body).getStatements()) { + if (lineRange.intersects(statement.getTextRange())) { + return statement; + } + } + } + return body; + } + + public static boolean inTheSameMethod(@NotNull SourcePosition pos1, @NotNull SourcePosition pos2) { + ApplicationManager.getApplication().assertReadAccessAllowed(); + PsiElement elem1 = pos1.getElementAt(); + PsiElement elem2 = pos2.getElementAt(); + if (elem1 == null) return elem2 == null; + if (elem2 != null) { + NavigatablePsiElement expectedMethod = PsiTreeUtil.getParentOfType(elem1, PsiMethod.class, PsiLambdaExpression.class); + NavigatablePsiElement currentMethod = PsiTreeUtil.getParentOfType(elem2, PsiMethod.class, PsiLambdaExpression.class); + return Comparing.equal(expectedMethod, currentMethod); + } + return false; + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java index a3c442fb410b..ff1b10d1d8d6 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaLineBreakpointType.java @@ -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. @@ -17,26 +17,39 @@ package com.intellij.debugger.ui.breakpoints; import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.HelpID; -import com.intellij.icons.AllIcons; +import com.intellij.debugger.SourcePosition; +import com.intellij.debugger.impl.DebuggerUtilsEx; +import com.intellij.openapi.editor.Document; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.SmartList; import com.intellij.xdebugger.XDebuggerUtil; +import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; +import com.intellij.xdebugger.impl.XSourcePositionImpl; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointVariant; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointVariantsProvider; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties; import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties; import javax.swing.*; +import java.util.Collections; import java.util.List; /** * Base class for java line-connected exceptions (line, method, field) * @author egor */ -public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase implements JavaBreakpointType { +public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase + implements JavaBreakpointType, XLineBreakpointVariantsProvider { public JavaLineBreakpointType() { super("java-line", DebuggerBundle.message("line.breakpoints.tab.title")); } @@ -58,13 +71,13 @@ public class JavaLineBreakpointType extends JavaLineBreakpointTypeBase computeLineBreakpointVariants(@NotNull Project project, @NotNull XSourcePosition position) { + PsiFile file = PsiManager.getInstance(project).findFile(position.getFile()); + if (file == null) { + return Collections.emptyList(); + } + + SourcePosition pos = SourcePosition.createFromLine(file, position.getLine()); + List lambdas = DebuggerUtilsEx.collectLambdas(pos, true); + if (lambdas.isEmpty()) { + return Collections.emptyList(); + } + + NavigatablePsiElement startMethod = PsiTreeUtil.getParentOfType(pos.getElementAt(), PsiMethod.class, PsiLambdaExpression.class); + //noinspection SuspiciousMethodCalls + if (lambdas.contains(startMethod) && lambdas.size() == 1) { + return Collections.emptyList(); + } + + Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); + if (document == null) { + return Collections.emptyList(); + } + + List res = new SmartList(); + res.add(new JavaBreakpointVariant(position)); //all + + if (startMethod instanceof PsiMethod) { + res.add(new ExactJavaBreakpointVariant(position, startMethod)); // base method + } + + for (PsiLambdaExpression lambda : lambdas) { //lambdas + PsiElement firstElem = DebuggerUtilsEx.getFirstElementOnTheLine(lambda, document, position.getLine()); + res.add(new ExactJavaBreakpointVariant(XSourcePositionImpl.createByElement(firstElem), lambda)); + } + + return res; + } + + class JavaBreakpointVariant extends XLineBreakpointVariant { + protected final XSourcePosition mySourcePosition; + + private JavaBreakpointVariant(XSourcePosition position) { + mySourcePosition = position; + } + + @Override + public String getText() { + return "All"; + } + + @Override + public Icon getIcon() { + return null; + } + + @Override + public TextRange getHighlightRange() { + return null; + } + + @Override + public JavaLineBreakpointProperties createProperties() { + return createBreakpointProperties(mySourcePosition.getFile(), + mySourcePosition.getLine()); + } + } + + private class ExactJavaBreakpointVariant extends JavaBreakpointVariant { + private final PsiElement myElement; + + public ExactJavaBreakpointVariant(XSourcePosition position, PsiElement element) { + super(position); + myElement = element; + } + + @Override + public Icon getIcon() { + return myElement.getIcon(0); + } + + @Override + public String getText() { + return StringUtil.shortenTextWithEllipsis(myElement.getText(), 100, 0); + } + + @Override + public TextRange getHighlightRange() { + return myElement.getTextRange(); + } + + @Override + public JavaLineBreakpointProperties createProperties() { + JavaLineBreakpointProperties properties = super.createProperties(); + properties.setOffset(mySourcePosition.getOffset()); + return properties; + } + } } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java index c322f67641d2..8cf083f49710 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/LineBreakpoint.java @@ -62,6 +62,7 @@ import com.sun.jdi.request.BreakpointRequest; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.debugger.breakpoints.properties.JavaLineBreakpointProperties; import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes; import javax.swing.*; @@ -198,12 +199,30 @@ public class LineBreakpoint extends BreakpointWithHighlighter { return false; } - protected boolean acceptLocation(DebugProcessImpl debugProcess, ReferenceType classType, Location loc) { + protected boolean acceptLocation(final DebugProcessImpl debugProcess, ReferenceType classType, final Location loc) { Method method = loc.method(); if (DebuggerUtils.isSynthetic(method)) { return false; } - return !(method.isConstructor() && loc.codeIndex() == 0 && isAnonymousClass(classType)); + boolean res = !(method.isConstructor() && loc.codeIndex() == 0 && isAnonymousClass(classType)); + if (!res) return false; + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + public Boolean compute() { + if (getProperties() instanceof JavaLineBreakpointProperties) { + Integer offset = ((JavaLineBreakpointProperties)getProperties()).getOffset(); + if (offset == null) return true; + PsiFile file = getPsiFile(); + if (file != null) { + SourcePosition exactPosition = SourcePosition.createFromOffset(file, offset); + SourcePosition position = debugProcess.getPositionManager().getSourcePosition(loc); + if (position == null) return false; + return DebuggerUtilsEx.inTheSameMethod(exactPosition, position); + } + } + return true; + } + }); } private boolean isInScopeOf(DebugProcessImpl debugProcess, String className) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java index 52af16623eb7..e30d0f866fbe 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/RunToCursorBreakpoint.java @@ -17,17 +17,18 @@ package com.intellij.debugger.ui.breakpoints; import com.intellij.debugger.SourcePosition; import com.intellij.debugger.engine.DebugProcessImpl; +import com.intellij.debugger.impl.DebuggerUtilsEx; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Computable; -import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; import com.intellij.xdebugger.XSourcePosition; import com.sun.jdi.Location; import com.sun.jdi.ReferenceType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties; /** * @author Eugene Zhuravlev @@ -114,6 +115,11 @@ public class RunToCursorBreakpoint extends LineBreakpoint { return true; } + @Override + protected JavaBreakpointProperties getProperties() { + return null; + } + @Override protected boolean isMuted(@NotNull final DebugProcessImpl debugProcess) { return false; // always enabled @@ -125,19 +131,9 @@ public class RunToCursorBreakpoint extends LineBreakpoint { return ApplicationManager.getApplication().runReadAction(new Computable() { @Override public Boolean compute() { - PsiElement expectedElement = myCustomPosition.getElementAt(); - if (expectedElement != null) { - SourcePosition position = debugProcess.getPositionManager().getSourcePosition(loc); - if (position != null) { - PsiElement currentElement = position.getElementAt(); - if (currentElement != null) { - NavigatablePsiElement expectedMethod = PsiTreeUtil.getParentOfType(expectedElement, PsiMethod.class, PsiLambdaExpression.class); - NavigatablePsiElement currentMethod = PsiTreeUtil.getParentOfType(currentElement, PsiMethod.class, PsiLambdaExpression.class); - return Comparing.equal(expectedMethod, currentMethod); - } - } - } - return true; + SourcePosition position = debugProcess.getPositionManager().getSourcePosition(loc); + if (position == null) return false; + return DebuggerUtilsEx.inTheSameMethod(myCustomPosition, position); } }); } diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java index 9a892346ac04..1ddf268f5895 100644 --- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java +++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/properties/JavaLineBreakpointProperties.java @@ -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. @@ -15,8 +15,20 @@ */ package org.jetbrains.java.debugger.breakpoints.properties; +import com.intellij.util.xmlb.annotations.OptionTag; + /** * @author egor */ public class JavaLineBreakpointProperties extends JavaBreakpointProperties { + private Integer myOffset = null; + + @OptionTag("offset") + public Integer getOffset() { + return myOffset; + } + + public void setOffset(Integer offset) { + myOffset = offset; + } } diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index 831a5fc3c4ae..1b748b7691e6 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -312,7 +312,7 @@ public abstract class SourcePosition implements Navigatable{ } @Nullable - public static SourcePosition createFromElement(PsiElement element) { + public static SourcePosition createFromElement(@NotNull PsiElement element) { ApplicationManager.getApplication().assertReadAccessAllowed(); PsiElement navigationElement = element.getNavigationElement(); final SmartPsiElementPointer pointer = diff --git a/java/execution/impl/src/com/intellij/execution/application/ApplicationRunLineMarkerProvider.java b/java/execution/impl/src/com/intellij/execution/application/ApplicationRunLineMarkerProvider.java index b161cbec1885..fe21ddd71d80 100644 --- a/java/execution/impl/src/com/intellij/execution/application/ApplicationRunLineMarkerProvider.java +++ b/java/execution/impl/src/com/intellij/execution/application/ApplicationRunLineMarkerProvider.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.daemon.LineMarkerProvider; import com.intellij.execution.lineMarker.RunLineMarkerInfo; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiIdentifier; import com.intellij.psi.PsiMethod; import com.intellij.psi.util.PsiMethodUtil; import org.jetbrains.annotations.NotNull; @@ -35,11 +36,14 @@ public class ApplicationRunLineMarkerProvider implements LineMarkerProvider { @Nullable @Override - public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement element) { - if (element instanceof PsiClass && PsiMethodUtil.findMainInClass((PsiClass)element) != null) - return new RunLineMarkerInfo(element, ApplicationConfigurationType.getInstance().getIcon(), null); - if (element instanceof PsiMethod && "main".equals(((PsiMethod)element).getName()) && PsiMethodUtil.isMainMethod((PsiMethod)element)) - return new RunLineMarkerInfo(element, ApplicationConfigurationType.getInstance().getIcon(), null); + public LineMarkerInfo getLineMarkerInfo(@NotNull PsiElement e) { + if (e instanceof PsiIdentifier) { + PsiElement element = e.getParent(); + if (element instanceof PsiClass && PsiMethodUtil.findMainInClass((PsiClass)element) != null) + return new RunLineMarkerInfo(element, ApplicationConfigurationType.getInstance().getIcon(), null); + if (element instanceof PsiMethod && "main".equals(((PsiMethod)element).getName()) && PsiMethodUtil.isMainMethod((PsiMethod)element)) + return new RunLineMarkerInfo(element, ApplicationConfigurationType.getInstance().getIcon(), null); + } return null; } diff --git a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java index 615ed5c65193..e1ab9ff4e3cf 100644 --- a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java +++ b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java @@ -138,6 +138,7 @@ public abstract class ExecutionWithDebuggerToolsTestCase extends ExecutionTestCa } catch (AssertionError e) { addException(e); + paused(suspendContext); } if (myScriptRunnables.isEmpty()) { diff --git a/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java b/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java index b79781923d04..6c1163cb27bb 100644 --- a/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java +++ b/platform/built-in-server/src/org/jetbrains/builtInWebServer/BuiltInWebBrowserUrlProvider.java @@ -59,7 +59,7 @@ public class BuiltInWebBrowserUrlProvider extends WebBrowserUrlProvider implemen } public static boolean compareAuthority(@Nullable String currentAuthority) { - if (currentAuthority == null) { + if (StringUtil.isEmpty(currentAuthority)) { return false; } diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java index 54dc3d9b73cc..0567e18f1153 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java @@ -418,7 +418,7 @@ public class VfsUtilCore { return prefix + ":///" + suffix; } } - else if (url.charAt(index + 3) == '/' && SystemInfoRt.isWindows && url.regionMatches(0, StandardFileSystems.FILE_PROTOCOL_PREFIX, 0, StandardFileSystems.FILE_PROTOCOL_PREFIX.length())) { + else if (SystemInfoRt.isWindows && (index + 3) < url.length() && url.charAt(index + 3) == '/' && url.regionMatches(0, StandardFileSystems.FILE_PROTOCOL_PREFIX, 0, StandardFileSystems.FILE_PROTOCOL_PREFIX.length())) { // file:///C:/test/file.js -> file://C:/test/file.js for (int i = index + 4; i < url.length(); i++) { char c = url.charAt(i); diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java index a1cb7b8c23f3..9d097a5dabfb 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConfigurationSettingsEditorWrapper.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package com.intellij.execution.impl; import com.intellij.execution.BeforeRunTask; @@ -44,8 +43,9 @@ import java.util.List; */ public class ConfigurationSettingsEditorWrapper extends SettingsEditor implements BeforeRunStepsPanel.StepsBeforeRunListener { - public static DataKey CONFIGURATION_EDITOR_KEY = DataKey.create("ConfigurationSettingsEditor"); + public static final DataKey CONFIGURATION_EDITOR_KEY = DataKey.create("ConfigurationSettingsEditor"); @NonNls private static final String EXPAND_PROPERTY_KEY = "ExpandBeforeRunStepsPanel"; + private JPanel myComponentPlace; private JPanel myWholePanel; @@ -79,6 +79,7 @@ public class ConfigurationSettingsEditorWrapper extends SettingsEditor { private static final Map ourProjectIcons = new HashMap(); + private static Icon ourSmallAppIcon; public static RecentProjectsManagerBase getInstanceEx() { return (RecentProjectsManagerBase)RecentProjectsManager.getInstance(); @@ -215,6 +219,11 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im @NotNull public static Icon createIcon(File file) { final BufferedImage image = loadAndScaleImage(file); + return toRetinaAwareIcon(image); + } + + @NotNull + protected static Icon toRetinaAwareIcon(final BufferedImage image) { return new Icon() { @Override public void paintIcon(Component c, Graphics g, int x, int y) { @@ -245,10 +254,9 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im private static BufferedImage loadAndScaleImage(File file) { try { Image img = ImageLoader.loadFromUrl(file.toURL()); - return Scalr.resize(ImageUtil.toBufferedImage(img), Scalr.Method.ULTRA_QUALITY, UIUtil.isRetina() ? 32 : JBUI.scale(16), null); + return Scalr.resize(ImageUtil.toBufferedImage(img), Scalr.Method.ULTRA_QUALITY, UIUtil.isRetina() ? 32 : JBUI.scale(16)); } - catch (MalformedURLException e) { - e.printStackTrace(); + catch (MalformedURLException e) {// } return null; } @@ -267,8 +275,32 @@ public abstract class RecentProjectsManagerBase extends RecentProjectsManager im } } + return getSmallApplicationIcon(); + } - return AllIcons.Nodes.IdeaProject; + protected static Icon getSmallApplicationIcon() { + if (ourSmallAppIcon == null) { + try { + Icon appIcon = IconLoader.findIcon(ApplicationInfoEx.getInstanceEx().getIconUrl()); + + if (appIcon != null) { + if (appIcon.getIconWidth() == JBUI.scale(16) && appIcon.getIconHeight() == JBUI.scale(16)) { + ourSmallAppIcon = appIcon; + } else { + BufferedImage image = ImageUtil.toBufferedImage(IconUtil.toImage(appIcon)); + image = Scalr.resize(image, Scalr.Method.ULTRA_QUALITY, UIUtil.isRetina() ? 32 : JBUI.scale(16)); + ourSmallAppIcon = toRetinaAwareIcon(image); + } + } + } + catch (Exception e) {// + } + if (ourSmallAppIcon == null) { + ourSmallAppIcon = EmptyIcon.ICON_16; + } + } + + return ourSmallAppIcon; } private Set getDuplicateProjectNames(Set openedPaths, Set recentPaths) { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 89a698ae45a8..e9507352a6a5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -1236,13 +1236,16 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi if (line == 0 && myPrefixText != null) { px -= myPrefixWidthInPixels; } + if (px < 0) { + px = 0; + } int textLength = myDocument.getTextLength(); LogicalPosition logicalPosition = visualToLogicalPosition(new VisualPosition(line, 0)); int offset = logicalPositionToOffset(logicalPosition); int plainSpaceSize = EditorUtil.getSpaceWidth(Font.PLAIN, this); - if (offset >= textLength) return new VisualPosition(line, EditorUtil.columnsNumber(p.x, plainSpaceSize)); + if (offset >= textLength) return new VisualPosition(line, EditorUtil.columnsNumber(px, plainSpaceSize)); // There is a possible case that starting logical line is split by soft-wraps and it's part after the split should be drawn. // We mark that we're under such circumstances then. @@ -1260,7 +1263,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi + "to offset %d (end offset). State: %s", p, line, line, 0, logicalPosition, offset, line + 1, 0, endLogicalPosition, endOffset, dumpState() )); - return new VisualPosition(line, EditorUtil.columnsNumber(p.x, plainSpaceSize)); + return new VisualPosition(line, EditorUtil.columnsNumber(px, plainSpaceSize)); } IterationState state = new IterationState(this, offset, endOffset, false); diff --git a/platform/platform-impl/src/com/intellij/util/UrlImpl.java b/platform/platform-impl/src/com/intellij/util/UrlImpl.java index ee2340db5a89..023865164405 100644 --- a/platform/platform-impl/src/com/intellij/util/UrlImpl.java +++ b/platform/platform-impl/src/com/intellij/util/UrlImpl.java @@ -33,7 +33,7 @@ public final class UrlImpl implements Url { private String externalForm; private UrlImpl withoutParameters; - public UrlImpl(@Nullable String path) { + public UrlImpl(@NotNull String path) { this(null, null, path, null); } @@ -43,8 +43,8 @@ public final class UrlImpl implements Url { public UrlImpl(@Nullable String scheme, @Nullable String authority, @Nullable String path, @Nullable String parameters) { this.scheme = scheme; - this.authority = StringUtil.nullize(authority); - this.path = StringUtil.isEmpty(path) ? "/" : path; + this.authority = authority; + this.path = StringUtil.isEmpty(path) && !StringUtil.isEmpty(authority) ? "/" : StringUtil.notNullize(path); this.parameters = StringUtil.nullize(parameters); } @@ -85,11 +85,11 @@ public final class UrlImpl implements Url { StringBuilder builder = new StringBuilder(); if (scheme != null) { builder.append(scheme); - if (authority != null || isInLocalFileSystem()) { - builder.append(URLUtil.SCHEME_SEPARATOR); + if (authority == null) { + builder.append(':'); } else { - builder.append(':'); + builder.append(URLUtil.SCHEME_SEPARATOR); } if (authority != null) { @@ -111,7 +111,7 @@ public final class UrlImpl implements Url { } // relative path - special url, encoding is not required - // authority is null in case of URI or file URL + // authority is null in case of URI if ((path.charAt(0) != '/' || authority == null) && !isInLocalFileSystem()) { return toDecodedForm(); } diff --git a/platform/platform-impl/src/com/intellij/util/Urls.java b/platform/platform-impl/src/com/intellij/util/Urls.java index abe4c5ae75b2..0deb412f3f1e 100644 --- a/platform/platform-impl/src/com/intellij/util/Urls.java +++ b/platform/platform-impl/src/com/intellij/util/Urls.java @@ -141,15 +141,21 @@ public final class Urls { } String authority = StringUtil.nullize(matcher.group(3)); - String path = StringUtil.nullize(matcher.group(4)); - if (path != null) { - path = FileUtil.toCanonicalUriPath(path); + boolean hasUrlSeparator = !StringUtil.isEmpty(matcher.group(2)); + if (authority == null) { + if (hasUrlSeparator) { + authority = ""; + } + } + else if (StandardFileSystems.FILE_PROTOCOL.equals(scheme) || !hasUrlSeparator) { + path = path == null ? authority : (authority + path); + authority = hasUrlSeparator ? "" : null; } - if (authority != null && (StandardFileSystems.FILE_PROTOCOL.equals(scheme) || StringUtil.isEmpty(matcher.group(2)))) { - path = path == null ? authority : (authority + path); - authority = null; + // canonicalize only if authority is not empty or file url - we should not canonicalize URL with unknown scheme (webpack:///./modules/flux-orion-plugin/fluxPlugin.ts) + if (path != null && (!StringUtil.isEmpty(authority) || StandardFileSystems.FILE_PROTOCOL.equals(scheme))) { + path = FileUtil.toCanonicalUriPath(path); } return new UrlImpl(scheme, authority, path, matcher.group(5)); } 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 cc2ba00f239f..cb93462706f6 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java @@ -18,6 +18,7 @@ package com.intellij.xdebugger.impl; import com.intellij.lang.Language; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.application.WriteAction; import com.intellij.openapi.editor.Caret; @@ -28,12 +29,19 @@ import com.intellij.openapi.fileEditor.FileEditorManager; import com.intellij.openapi.fileEditor.OpenFileDescriptor; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.popup.JBPopupFactory; +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.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.*; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.ui.awt.RelativePoint; import com.intellij.util.Processor; +import com.intellij.util.SmartList; import com.intellij.xdebugger.*; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.breakpoints.ui.XBreakpointGroupingRule; @@ -45,6 +53,8 @@ import com.intellij.xdebugger.frame.XSuspendContext; import com.intellij.xdebugger.frame.XValueContainer; import com.intellij.xdebugger.impl.breakpoints.XBreakpointUtil; import com.intellij.xdebugger.impl.breakpoints.XExpressionImpl; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointVariant; +import com.intellij.xdebugger.impl.breakpoints.XLineBreakpointVariantsProvider; import com.intellij.xdebugger.impl.breakpoints.ui.grouping.XBreakpointFileGroupingRule; import com.intellij.xdebugger.impl.evaluate.quick.common.ValueLookupManager; import com.intellij.xdebugger.impl.settings.XDebuggerSettingsManager; @@ -54,6 +64,7 @@ import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.*; import java.util.*; /** @@ -107,28 +118,76 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { @NotNull final VirtualFile file, final int line, final boolean temporary) { - toggleAndReturnLineBreakpoint(project, type, file, line, temporary); + XSourcePositionImpl position = XSourcePositionImpl.create(file, line); + if (position != null) { + toggleAndReturnLineBreakpoint(project, type, position, temporary, null); + } } - public static

XLineBreakpoint toggleAndReturnLineBreakpoint(@NotNull final Project project, + @NotNull + public static

AsyncResult toggleAndReturnLineBreakpoint(@NotNull final Project project, @NotNull final XLineBreakpointType

type, - @NotNull final VirtualFile file, - final int line, - final boolean temporary) { - return new WriteAction() { + @NotNull final XSourcePosition position, + final boolean temporary, + final RelativePoint relativePoint) { + return ApplicationManager.getApplication().runWriteAction(new Computable>() { @Override - protected void run(@NotNull final Result result) { - XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager(); + public AsyncResult compute() { + 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) { breakpointManager.removeBreakpoint(breakpoint); } else { + if (type instanceof XLineBreakpointVariantsProvider) { + final XLineBreakpointVariantsProvider provider = + (XLineBreakpointVariantsProvider)type; + List variants = provider.computeLineBreakpointVariants(project, position); + if (!variants.isEmpty()) { + if (variants.size() > 1 && relativePoint != null) { + final AsyncResult res = new AsyncResult(); + JBPopupFactory.getInstance().createListPopup( + new BaseListPopupStep("Create breakpoint for", variants) { + @NotNull + @Override + public String getTextFor(XLineBreakpointVariant value) { + return value.getText(); + } + + @Override + public Icon getIconFor(XLineBreakpointVariant value) { + return value.getIcon(); + } + + @Override + public PopupStep onChosen(final XLineBreakpointVariant selectedValue, boolean finalChoice) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + P properties = (P)selectedValue.createProperties(); + res.setDone(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); + } + }); + return FINAL_CHOICE; + } + }).show(relativePoint); + return res; + } + else { + P properties = (P)variants.get(0).createProperties(); + return AsyncResult.done( + (XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); + } + } + } P properties = type.createBreakpointProperties(file, line); - result.setResult(breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); + return AsyncResult.done((XLineBreakpoint)breakpointManager.addLineBreakpoint(type, file.getUrl(), line, properties, temporary)); } + return AsyncResult.rejected(); } - }.execute().getResultObject(); + }); } @Override @@ -199,13 +258,10 @@ public class XDebuggerUtilImpl extends XDebuggerUtil { return Collections.emptyList(); } - final Document document = editor.getDocument(); - VirtualFile file = FileDocumentManager.getInstance().getFile(document); - Collection res = new ArrayList(); - List carets = editor.getCaretModel().getAllCarets(); - for (Caret caret : carets) { - int line = caret.getLogicalPosition().line; - XSourcePositionImpl position = XSourcePositionImpl.create(file, line); + VirtualFile file = FileDocumentManager.getInstance().getFile(editor.getDocument()); + List res = new SmartList(); + for (Caret caret : editor.getCaretModel().getAllCarets()) { + XSourcePositionImpl position = XSourcePositionImpl.createByOffset(file, caret.getOffset()); if (position != null) { res.add(position); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java index 78462bbee293..b9a8beafed14 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/handlers/XToggleLineBreakpointActionHandler.java @@ -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. @@ -65,7 +65,7 @@ public class XToggleLineBreakpointActionHandler extends DebuggerActionHandler { Set processedLines = new HashSet(); for (XSourcePosition position : XDebuggerUtilImpl.getAllCaretsPositions(project, event.getDataContext())) { if (processedLines.add(position.getLine())) { - XBreakpointUtil.toggleLineBreakpoint(project, position.getFile(), editor, position.getLine(), myTemporary, true); + XBreakpointUtil.toggleLineBreakpoint(project, position, editor, myTemporary, true); } } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java index 7bfc31989e3b..d5280fc94e6e 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointUtil.java @@ -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. @@ -22,16 +22,20 @@ 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; import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.XDebuggerUtil; +import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.breakpoints.*; import com.intellij.xdebugger.impl.DebuggerSupport; import com.intellij.xdebugger.impl.XDebuggerUtilImpl; +import com.intellij.xdebugger.impl.XSourcePositionImpl; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem; import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointPanelProvider; +import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -130,12 +134,14 @@ public class XBreakpointUtil { * - unfolds folded block on the line * - if folded, checks if line breakpoints could be toggled inside folded text */ - public static XLineBreakpoint toggleLineBreakpoint(Project project, - VirtualFile file, - Editor editor, - int lineStart, + @NotNull + public static AsyncResult 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 int linesEnd = lineStart; if (editor != null) { @@ -147,7 +153,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; @@ -170,18 +176,22 @@ public class XBreakpointUtil { } if (typeWinner != null) { - XLineBreakpoint res = XDebuggerUtilImpl.toggleAndReturnLineBreakpoint(project, typeWinner, file, lineWinner, temporary); + XSourcePosition winPosition = (lineStart == lineWinner) ? position : XSourcePositionImpl.create(file, lineWinner); + if (winPosition != null) { + AsyncResult res = XDebuggerUtilImpl.toggleAndReturnLineBreakpoint(project, typeWinner, winPosition, temporary, + DebuggerUIUtil.calcPopupLocation(editor, lineWinner)); - if (editor != null && lineStart != lineWinner) { - int offset = editor.getDocument().getLineStartOffset(lineWinner); - ExpandRegionAction.expandRegionAtOffset(project, editor, offset); - if (moveCarret) { - editor.getCaretModel().moveToOffset(offset); + if (editor != null && lineStart != lineWinner) { + int offset = editor.getDocument().getLineStartOffset(lineWinner); + ExpandRegionAction.expandRegionAtOffset(project, editor, offset); + if (moveCarret) { + editor.getCaretModel().moveToOffset(offset); + } } + return res; } - return res; } - return null; + return AsyncResult.rejected(); } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java index acf896a8d357..626b22e068f0 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java @@ -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. @@ -38,6 +38,7 @@ 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; @@ -45,6 +46,7 @@ import com.intellij.openapi.vfs.VirtualFileEvent; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.openapi.vfs.VirtualFileUrlChangeAdapter; import com.intellij.psi.PsiDocumentManager; +import com.intellij.util.Consumer; import com.intellij.util.SmartList; import com.intellij.util.containers.BidirectionalMap; import com.intellij.util.ui.update.MergingUpdateQueue; @@ -53,6 +55,7 @@ import com.intellij.xdebugger.XDebuggerManager; import com.intellij.xdebugger.breakpoints.SuspendPolicy; import com.intellij.xdebugger.breakpoints.XBreakpoint; import com.intellij.xdebugger.breakpoints.XLineBreakpoint; +import com.intellij.xdebugger.impl.XSourcePositionImpl; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import gnu.trove.TIntHashSet; import org.jetbrains.annotations.NotNull; @@ -297,20 +300,25 @@ public class XLineBreakpointManager { if (!myProject.isDisposed() && myProject.isInitialized() && file.isValid()) { ActionManagerEx.getInstanceEx().fireBeforeActionPerformed("ToggleLineBreakpoint", e.getMouseEvent()); - XLineBreakpoint breakpoint = - XBreakpointUtil.toggleLineBreakpoint(myProject, file, editor, line, mouseEvent.isAltDown(), false); - if (!mouseEvent.isAltDown() && mouseEvent.isShiftDown() && breakpoint != null) { - breakpoint.setSuspendPolicy(SuspendPolicy.NONE); - String selection = editor.getSelectionModel().getSelectedText(); - if (selection != null) { - breakpoint.setLogExpression(selection); + AsyncResult result = XBreakpointUtil.toggleLineBreakpoint( + myProject, XSourcePositionImpl.create(file, line), editor, mouseEvent.isAltDown(), false); + result.doWhenDone(new Consumer() { + @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); - } + }); } } }); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointVariant.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointVariant.java new file mode 100644 index 000000000000..18b4db2b6891 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointVariant.java @@ -0,0 +1,34 @@ +/* + * 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. + */ +package com.intellij.xdebugger.impl.breakpoints; + +import com.intellij.openapi.util.TextRange; +import com.intellij.xdebugger.breakpoints.XBreakpointProperties; + +import javax.swing.*; + +/** + * @author egor + */ +public abstract class XLineBreakpointVariant

{ + public abstract String getText(); + + public abstract Icon getIcon(); + + public abstract TextRange getHighlightRange(); + + public abstract P createProperties(); +} diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointVariantsProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointVariantsProvider.java new file mode 100644 index 000000000000..9861ef0f8a29 --- /dev/null +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointVariantsProvider.java @@ -0,0 +1,30 @@ +/* + * 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. + */ +package com.intellij.xdebugger.impl.breakpoints; + +import com.intellij.openapi.project.Project; +import com.intellij.xdebugger.XSourcePosition; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author egor + */ +public interface XLineBreakpointVariantsProvider { + @NotNull + List computeLineBreakpointVariants(@NotNull Project project, @NotNull XSourcePosition position); +} diff --git a/plugins/devkit/src/testAssistant/NavigateToTestDataAction.java b/plugins/devkit/src/testAssistant/NavigateToTestDataAction.java index 91b903e9bbdb..c325da519163 100644 --- a/plugins/devkit/src/testAssistant/NavigateToTestDataAction.java +++ b/plugins/devkit/src/testAssistant/NavigateToTestDataAction.java @@ -65,7 +65,7 @@ public class NavigateToTestDataAction extends AnAction implements TestTreeViewAc } @Nullable - public static List findTestDataFiles(@NotNull DataContext context) { + static List findTestDataFiles(@NotNull DataContext context) { final PsiMethod method = findTargetMethod(context); if (method == null) { return null; diff --git a/plugins/devkit/src/testAssistant/NavigateToTestDataActionGroup.java b/plugins/devkit/src/testAssistant/NavigateToTestDataActionGroup.java deleted file mode 100644 index 795832f78cc8..000000000000 --- a/plugins/devkit/src/testAssistant/NavigateToTestDataActionGroup.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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. - */ -package org.jetbrains.idea.devkit.testAssistant; - -import com.intellij.openapi.actionSystem.ActionGroup; -import com.intellij.openapi.actionSystem.AnAction; -import com.intellij.openapi.actionSystem.AnActionEvent; -import com.intellij.openapi.fileTypes.FileTypeManager; -import com.intellij.psi.PsiMethod; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.List; - -public class NavigateToTestDataActionGroup extends ActionGroup { - private final PsiMethod myMethod; - - public NavigateToTestDataActionGroup(PsiMethod method) { - myMethod = method; - } - - @NotNull - @Override - public AnAction[] getChildren(@Nullable AnActionEvent e) { - List names = TestDataNavigationHandler.getFileNames(myMethod); - if (names == null || names.isEmpty()) return new AnAction[0]; - return ContainerUtil.map2Array(names, AnAction.class, new Function() { - @Override - public AnAction fun(String s) { - return new GotoTestDataAction(s, myMethod.getProject(), FileTypeManager.getInstance().getFileTypeByFileName(s).getIcon()); - } - }); - } -} diff --git a/plugins/devkit/src/testAssistant/TestDataLineMarkerProvider.java b/plugins/devkit/src/testAssistant/TestDataLineMarkerProvider.java index 017d5b95a6a2..f0dcc8e2202a 100644 --- a/plugins/devkit/src/testAssistant/TestDataLineMarkerProvider.java +++ b/plugins/devkit/src/testAssistant/TestDataLineMarkerProvider.java @@ -18,6 +18,7 @@ package org.jetbrains.idea.devkit.testAssistant; import com.intellij.codeInsight.AnnotationUtil; import com.intellij.execution.lineMarker.RunLineMarkerContributor; import com.intellij.icons.AllIcons; +import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnAction; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectFileIndex; @@ -39,9 +40,11 @@ public class TestDataLineMarkerProvider extends RunLineMarkerContributor { public static final String CONTENT_ROOT_VARIABLE = "$CONTENT_ROOT"; public static final String PROJECT_ROOT_VARIABLE = "$PROJECT_ROOT"; - public AnAction getAdditionalAction(@NotNull PsiElement element) { + public AnAction getAdditionalAction(@NotNull PsiElement e) { - if (!(element instanceof PsiMethod) && + PsiElement element = e.getParent(); + if (!(e instanceof PsiIdentifier) || + !(element instanceof PsiMethod) && !(element instanceof PsiClass)) { return null; } @@ -55,8 +58,7 @@ public class TestDataLineMarkerProvider extends RunLineMarkerContributor { return null; } if (element instanceof PsiMethod) { - final PsiMethod method = (PsiMethod)element; - return new NavigateToTestDataActionGroup(method); + return ActionManager.getInstance().getAction("TestData.Navigate"); } else { final PsiClass psiClass = (PsiClass)element; final String basePath = getTestDataBasePath(psiClass); diff --git a/python/edu/interactive-learning-python/interactive-learning-python.iml b/python/edu/interactive-learning-python/interactive-learning-python.iml index e92551376fe3..1d2fc6ad288e 100644 --- a/python/edu/interactive-learning-python/interactive-learning-python.iml +++ b/python/edu/interactive-learning-python/interactive-learning-python.iml @@ -5,7 +5,7 @@ - + @@ -15,16 +15,8 @@ - - - - - - - - - + \ No newline at end of file diff --git a/python/edu/interactive-learning-python/tests/JsonParserTest.java b/python/edu/interactive-learning-python/tests/JsonParserTest.java index 5cba837b2bcf..42ac11d1eb37 100644 --- a/python/edu/interactive-learning-python/tests/JsonParserTest.java +++ b/python/edu/interactive-learning-python/tests/JsonParserTest.java @@ -1,3 +1,5 @@ +package com.jetbrains.edu.learning; + import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -33,6 +35,6 @@ public class JsonParserTest extends TestCase { assertEquals(myCourse.getLessons().get(1).getTaskList().size(), 1); } protected String getTestDataPath() { - return PythonHelpersLocator.getPythonCommunityPath() + "/edu/learn-python/testData"; + return PythonHelpersLocator.getPythonCommunityPath() + "/edu/interactive-learning-python/testData"; } } diff --git a/python/edu/interactive-learning-python/tests/StudyDocumentListenerTest.java b/python/edu/interactive-learning-python/tests/StudyDocumentListenerTest.java index dc6c2a496dab..996536f4bf7b 100644 --- a/python/edu/interactive-learning-python/tests/StudyDocumentListenerTest.java +++ b/python/edu/interactive-learning-python/tests/StudyDocumentListenerTest.java @@ -1,3 +1,5 @@ +package com.jetbrains.edu.learning; + import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Document; diff --git a/python/edu/interactive-learning-python/tests/StudyTestCase.java b/python/edu/interactive-learning-python/tests/StudyTestCase.java index 39bc30c165eb..c822fb869073 100644 --- a/python/edu/interactive-learning-python/tests/StudyTestCase.java +++ b/python/edu/interactive-learning-python/tests/StudyTestCase.java @@ -1,3 +1,5 @@ +package com.jetbrains.edu.learning; + import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.UsefulTestCase; import com.intellij.testFramework.fixtures.CodeInsightTestFixture; diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java index 43de59f09bad..1722e67aedfa 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/StudyTaskManager.java @@ -1,12 +1,6 @@ package com.jetbrains.edu.learning; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.StorageScheme; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.module.ModuleServiceManager; +import com.intellij.openapi.components.*; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.Project; import com.intellij.ui.JBColor; @@ -31,9 +25,9 @@ import java.util.Map; @State( name = "StudySettings", storages = { + @Storage(file = StoragePathMacros.PROJECT_FILE), @Storage( - id = "others", - file = "$PROJECT_CONFIG_DIR$/study_project.xml", + file = StoragePathMacros.PROJECT_CONFIG_DIR + "/study_project.xml", scheme = StorageScheme.DIRECTORY_BASED )} ) @@ -176,8 +170,6 @@ public class StudyTaskManager implements PersistentStateComponent