diff --git a/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java b/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java index 08cced8c51c4..0bb24ce60dee 100644 --- a/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java +++ b/java/debugger/impl/src/com/intellij/debugger/codeinsight/JavaWithRuntimeCastSurrounder.java @@ -71,7 +71,7 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder { return null; } - private class SurroundWithCastWorker extends RuntimeTypeEvaluator { + private static class SurroundWithCastWorker extends RuntimeTypeEvaluator { private final Editor myEditor; public SurroundWithCastWorker(Editor editor, PsiExpression expression, DebuggerContextImpl context, final ProgressIndicator indicator) { @@ -80,7 +80,7 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder { } @Override - protected void typeCalculationFinished(@Nullable final PsiClass type) { + protected void typeCalculationFinished(@Nullable final PsiType type) { if (type == null) { return; } @@ -94,9 +94,9 @@ public class JavaWithRuntimeCastSurrounder extends JavaExpressionSurrounder { try { PsiElementFactory factory = JavaPsiFacade.getInstance(myElement.getProject()).getElementFactory(); PsiParenthesizedExpression parenth = - (PsiParenthesizedExpression)factory.createExpressionFromText("((" + type.getQualifiedName() + ")expr)", null); - PsiTypeCastExpression cast = (PsiTypeCastExpression)parenth.getExpression(); - cast.getOperand().replace(myElement); + (PsiParenthesizedExpression)factory.createExpressionFromText("((" + type.getCanonicalText() + ")expr)", null); + //noinspection ConstantConditions + ((PsiTypeCastExpression)parenth.getExpression()).getOperand().replace(myElement); parenth = (PsiParenthesizedExpression)JavaCodeStyleManager.getInstance(project).shortenClassReferences(parenth); PsiExpression expr = (PsiExpression)myElement.replace(parenth); TextRange range = expr.getTextRange(); diff --git a/java/debugger/impl/src/com/intellij/debugger/codeinsight/RuntimeTypeEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/codeinsight/RuntimeTypeEvaluator.java index ecb7556bf2c7..a3bf6ca1db11 100644 --- a/java/debugger/impl/src/com/intellij/debugger/codeinsight/RuntimeTypeEvaluator.java +++ b/java/debugger/impl/src/com/intellij/debugger/codeinsight/RuntimeTypeEvaluator.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. @@ -19,6 +19,7 @@ import com.intellij.debugger.DebuggerBundle; import com.intellij.debugger.DebuggerInvocationUtil; import com.intellij.debugger.EvaluatingComputable; import com.intellij.debugger.engine.ContextUtil; +import com.intellij.debugger.engine.DebuggerUtils; import com.intellij.debugger.engine.evaluation.EvaluateException; import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil; import com.intellij.debugger.engine.evaluation.EvaluationContextImpl; @@ -33,7 +34,6 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.search.GlobalSearchScope; import com.sun.jdi.ClassType; import com.sun.jdi.InterfaceType; import com.sun.jdi.Type; @@ -43,13 +43,13 @@ import org.jetbrains.annotations.Nullable; /** * @author peter */ -public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand { +public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand { public RuntimeTypeEvaluator(@Nullable Editor editor, PsiElement expression, DebuggerContextImpl context, final ProgressIndicator indicator) { super(editor, expression, context, indicator); } public void threadAction() { - PsiClass type = null; + PsiType type = null; try { type = evaluate(); } @@ -62,10 +62,10 @@ public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand() { @@ -82,36 +82,37 @@ public abstract class RuntimeTypeEvaluator extends EditorEvaluationCommand nameRef = new AtomicReference(); + final AtomicReference nameRef = new AtomicReference(); final RuntimeTypeEvaluator worker = new RuntimeTypeEvaluator(null, expression, debuggerContext, ProgressManager.getInstance().getProgressIndicator()) { @Override - protected void typeCalculationFinished(@Nullable PsiClass type) { + protected void typeCalculationFinished(@Nullable PsiType type) { nameRef.set(type); semaphore.up(); } @@ -106,10 +106,7 @@ public class DefaultCodeFragmentFactory extends CodeFragmentFactory { ProgressManager.checkCanceled(); if (semaphore.waitFor(20)) break; } - final PsiClass psiClass = nameRef.get(); - if (psiClass != null) { - return JavaPsiFacade.getElementFactory(project).createType(psiClass); - } + return nameRef.get(); } return null; } diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeExpression.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeExpression.java index fea7faf504f9..73874ef9c0be 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeExpression.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/watch/DebuggerTreeNodeExpression.java @@ -219,16 +219,17 @@ public class DebuggerTreeNodeExpression { Project project = expression.getProject(); - PsiClass type = RuntimeTypeEvaluator.getCastableRuntimeType(project, value); + PsiType type = RuntimeTypeEvaluator.getCastableRuntimeType(project, value); if (type == null) { return expression; } PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project); - String typeName = type.getQualifiedName(); + String typeName = type.getCanonicalText(); try { PsiParenthesizedExpression parenthExpression = (PsiParenthesizedExpression)elementFactory.createExpressionFromText( "((" + typeName + ")expression)", null); + //noinspection ConstantConditions ((PsiTypeCastExpression)parenthExpression.getExpression()).getOperand().replace(expression); Set imports = expression.getUserData(ADDITIONAL_IMPORTS_KEY); if (imports == null) { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ClassRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ClassRenderer.java index af418f3053e8..b950a4b0a328 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ClassRenderer.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ClassRenderer.java @@ -158,16 +158,21 @@ public class ClassRenderer extends NodeRendererImpl{ final ObjectReference objRef = (ObjectReference)value; final ReferenceType refType = objRef.referenceType(); // default ObjectReference processing - final List fields = refType.allFields(); - if (fields.size() > 0) { - for (final Field field : fields) { - if (!shouldDisplay(evaluationContext, objRef, field)) { - continue; + List fields = refType.allFields(); + if (!fields.isEmpty()) { + boolean empty = true; + for (Field field : fields) { + if (shouldDisplay(evaluationContext, objRef, field)) { + children.add(nodeManager.createNode( + createFieldDescriptor(parentDescriptor, nodeDescriptorFactory, objRef, field, evaluationContext), evaluationContext)); + empty = false; } - children.add(nodeManager.createNode(createFieldDescriptor(parentDescriptor, nodeDescriptorFactory, objRef, field, evaluationContext), evaluationContext)); } - if (XDebuggerSettingsManager.getInstance().getDataViewSettings().isSortValues()) { + if (empty) { + children.add(nodeManager.createMessageNode(DebuggerBundle.message("message.node.class.no.fields.to.display"))); + } + else if (XDebuggerSettingsManager.getInstance().getDataViewSettings().isSortValues()) { Collections.sort(children, NodeManagerImpl.getNodeComparator()); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GutterIconTooltipHelper.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GutterIconTooltipHelper.java index de09c0840340..780fd5886003 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GutterIconTooltipHelper.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GutterIconTooltipHelper.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. @@ -36,15 +36,15 @@ public class GutterIconTooltipHelper { private GutterIconTooltipHelper() { } - public static String composeText(@NotNull PsiElement[] elements, String start, final String pattern) { + public static String composeText(@NotNull PsiElement[] elements, @NotNull String start, @NotNull String pattern) { return composeText(Arrays.asList(elements), start, pattern); } - public static String composeText(@NotNull Iterable elements, String start, final String pattern) { + public static String composeText(@NotNull Iterable elements, @NotNull String start, @NotNull String pattern) { return composeText(elements, start, pattern, ""); } - public static String composeText(@NotNull Iterable elements, String start, final String pattern, String postfix) { + public static String composeText(@NotNull Iterable elements, @NotNull String start, @NotNull String pattern, @NotNull String postfix) { @NonNls StringBuilder result = new StringBuilder(); result.append(""); result.append(start); diff --git a/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java b/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java index e9039aba119b..7d5bfda6dfec 100644 --- a/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java +++ b/java/java-analysis-impl/src/com/intellij/psi/impl/FindSuperElementsHelper.java @@ -15,6 +15,8 @@ */ package com.intellij.psi.impl; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.search.searches.ClassInheritorsSearch; import com.intellij.psi.util.MethodSignature; @@ -64,11 +66,12 @@ public class FindSuperElementsHelper { } public static PsiMethod getSiblingInheritedViaSubClass(@NotNull PsiMethod method) { - return getSiblingInheritedViaSubClass(method, createSubClassCache()); + return Pair.getFirst(getSiblingInheritedViaSubClass(method, createSubClassCache())); } - public static PsiMethod getSiblingInheritedViaSubClass(@NotNull final PsiMethod method, - @NotNull Map subClassCache) { + // returns super method, sub class + public static Pair getSiblingInheritedViaSubClass(@NotNull final PsiMethod method, + @NotNull Map subClassCache) { if (!method.hasModifierProperty(PsiModifier.PUBLIC)) return null; if (method.hasModifierProperty(PsiModifier.STATIC)) return null; final PsiClass containingClass = method.getContainingClass(); @@ -77,7 +80,7 @@ public class FindSuperElementsHelper { return null; } final Collection checkedInterfaces = new THashSet(); - final PsiMethod[] result = new PsiMethod[1]; + final Ref> result = Ref.create(); ClassInheritorsSearch.search(containingClass, containingClass.getUseScope(), true, true, false).forEach(new Processor() { @Override public boolean process(PsiClass inheritor) { @@ -107,14 +110,14 @@ public class FindSuperElementsHelper { if (!isOverridden) { continue; } - result[0] = superMethod; + result.set(Pair.create(superMethod, inheritor)); return false; } } return true; } }); - return result[0]; + return result.get(); } @NotNull diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java index f60ba833b1f6..21847f82799c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/JavaLineMarkerProvider.java @@ -184,12 +184,14 @@ public class JavaLineMarkerProvider implements LineMarkerProvider { boolean canHaveSiblingSuper = !method.hasModifierProperty(PsiModifier.ABSTRACT) && !method.hasModifierProperty(PsiModifier.STATIC) && method.hasModifierProperty(PsiModifier.PUBLIC)&& !method.hasModifierProperty(PsiModifier.FINAL)&& !method.hasModifierProperty(PsiModifier.NATIVE); if (!canHaveSiblingSuper) continue; - PsiMethod siblingInheritedViaSubClass = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache); + PsiMethod siblingInheritedViaSubClass = Pair.getFirst(FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, subClassCache)); if (siblingInheritedViaSubClass == null) { continue; } PsiElement range = getMethodRange(method); - LineMarkerInfo info = createSuperMethodLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, Pass.UPDATE_OVERRIDEN_MARKERS); + ArrowUpLineMarkerInfo upInfo = new ArrowUpLineMarkerInfo(range, AllIcons.Gutter.ImplementingMethod, MarkerType.SIBLING_OVERRIDING_METHOD, + Pass.UPDATE_OVERRIDEN_MARKERS); + LineMarkerInfo info = NavigateAction.setNavigateAction(upInfo, "Go to super method", IdeActions.ACTION_GOTO_SUPER); result.add(info); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java index 5de455903a00..604e4db19817 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/MarkerType.java @@ -33,8 +33,10 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbService; import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.impl.FindSuperElementsHelper; +import com.intellij.psi.presentation.java.ClassPresentationUtil; import com.intellij.psi.search.PsiElementProcessor; import com.intellij.psi.search.PsiElementProcessorAdapter; import com.intellij.psi.search.SearchScope; @@ -54,6 +56,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.event.MouseEvent; +import java.text.MessageFormat; import java.util.Arrays; import java.util.Comparator; @@ -119,6 +122,24 @@ public class MarkerType { navigateToOverridingMethod(e, method, method != element.getParent()); } }); + static final MarkerType SIBLING_OVERRIDING_METHOD = new MarkerType("SIBLING_OVERRIDING_METHOD", new NullableFunction() { + @Override + public String fun(PsiElement element) { + PsiElement parent = getParentMethod(element); + if (!(parent instanceof PsiMethod)) return null; + PsiMethod method = (PsiMethod)parent; + + return calculateOverridingSiblingMethodTooltip(method); + } + }, new LineMarkerNavigator() { + @Override + public void browse(MouseEvent e, PsiElement element) { + PsiElement parent = getParentMethod(element); + if (!(parent instanceof PsiMethod)) return; + PsiMethod method = (PsiMethod)parent; + navigateToSiblingOverridingMethod(e, method); + } + }); @Nullable private static String calculateOverridingMethodTooltip(@NotNull PsiMethod method, boolean acceptSelf) { @@ -139,6 +160,22 @@ public class MarkerType { } return composeText(superMethods, "", DaemonBundle.message(key), IdeActions.ACTION_GOTO_SUPER); } + @Nullable + private static String calculateOverridingSiblingMethodTooltip(@NotNull PsiMethod method) { + Pair pair = + FindSuperElementsHelper.getSiblingInheritedViaSubClass(method, FindSuperElementsHelper.createSubClassCache()); + if (pair == null) return null; + PsiMethod superMethod = pair.getFirst(); + PsiClass subClass = pair.getSecond(); + boolean isAbstract = method.hasModifierProperty(PsiModifier.ABSTRACT); + boolean isSuperAbstract = superMethod.hasModifierProperty(PsiModifier.ABSTRACT); + + String postfix = MessageFormat.format(" via sub-class {0}", ClassPresentationUtil.getNameForClass(subClass, false)); + @NonNls String pattern = DaemonBundle.message(isSuperAbstract && !isAbstract ? + "method.implements" : + "method.overrides") + postfix; + return composeText(new PsiElement[]{superMethod}, "", pattern, IdeActions.ACTION_GOTO_SUPER); + } @NotNull private static String composeText(@NotNull PsiElement[] methods, @NotNull String start, @NotNull String pattern, @NotNull String actionId) { @@ -159,6 +196,14 @@ public class MarkerType { DaemonBundle.message("navigation.findUsages.title.super.method", method.getName()), new MethodCellRenderer(showMethodNames)); } + private static void navigateToSiblingOverridingMethod(MouseEvent e, @NotNull PsiMethod method) { + PsiMethod superMethod = FindSuperElementsHelper.getSiblingInheritedViaSubClass(method); + if (superMethod == null) return; + PsiElementListNavigator.openTargets(e, new NavigatablePsiElement[]{superMethod}, + DaemonBundle.message("navigation.title.super.method", method.getName()), + DaemonBundle.message("navigation.findUsages.title.super.method", method.getName()), + new MethodCellRenderer(false)); + } @NotNull private static PsiMethod[] composeSuperMethods(@NotNull PsiMethod method, boolean acceptSelf) { diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java index 336c549861a8..39b44d4adb79 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java @@ -702,9 +702,9 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo ASTNode child = node.getFirstChildNode(); while (child != null) { if (!FormatterUtil.containsWhiteSpacesOnly(child)) { - if (child.getElementType() == JavaElementType.METHOD_CALL_EXPRESSION || child.getElementType() == - JavaElementType - .REFERENCE_EXPRESSION) { + IElementType type = child.getElementType(); + if (type == JavaElementType.METHOD_CALL_EXPRESSION || + type == JavaElementType.REFERENCE_EXPRESSION) { collectNodes(nodes, child); } else { @@ -861,10 +861,15 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo @NotNull final List result, @NotNull ASTNode child, @NotNull final WrappingStrategy wrappingStrategy, - final boolean doAlign) { - final Indent externalIndent = Indent.getNoneIndent(); - final Indent internalIndent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS); - final Indent internalIndentEnforcedToChildren = Indent.getIndent(Indent.Type.CONTINUATION, myIndentSettings.USE_RELATIVE_INDENTS, true); + final boolean doAlign) + { + Indent externalIndent = Indent.getNoneIndent(); + Indent internalIndent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS); + + if (isInsideMethodCallParenthesis(child)) { + internalIndent = Indent.getSmartIndent(Indent.Type.CONTINUATION); + } + AlignmentStrategy alignmentStrategy = AlignmentStrategy.wrap(createAlignment(doAlign, null), JavaTokenType.COMMA); setChildIndent(internalIndent); setChildAlignment(alignmentStrategy.getAlignment(null)); @@ -889,7 +894,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo ASTNode prev = child; boolean afterAnonymousClass = false; - final boolean enforceIndent = shouldEnforceIndentToChildren(); while (child != null) { isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT || child.getElementType() == JavaElementType.EMPTY_EXPRESSION; @@ -898,18 +902,17 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo result.add(createJavaBlock(child, mySettings, myJavaSettings, externalIndent, null, bracketAlignment)); } else if (child.getElementType() == to) { - result.add(createJavaBlock(child, mySettings, myJavaSettings, - isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent, - null, - isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment) - ); + Block block = createJavaBlock(child, mySettings, myJavaSettings, + isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent, + null, + isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment); + result.add(block); return child; } else { final IElementType elementType = child.getElementType(); - Indent indentToUse = enforceIndent ? internalIndentEnforcedToChildren : internalIndent; AlignmentStrategy alignmentStrategyToUse = canUseAnonymousClassAlignment(child) ? anonymousClassStrategy : alignmentStrategy; - processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse); + processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), internalIndent); if (to == null) {//process only one statement return child; } @@ -926,6 +929,15 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return prev; } + private boolean isInsideMethodCallParenthesis(ASTNode child) { + ASTNode currentPredecessor = child.getTreeParent(); + if (currentPredecessor != null) { + currentPredecessor = currentPredecessor.getTreeParent(); + return currentPredecessor != null && currentPredecessor.getElementType() == JavaElementType.METHOD_CALL_EXPRESSION; + } + return false; + } + private static boolean canUseAnonymousClassAlignment(@NotNull ASTNode child) { // The general idea is to handle situations like below: // test(new Runnable() { @@ -967,19 +979,6 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo return true; } - private boolean shouldEnforceIndentToChildren() { - if (myNode.getElementType() != JavaElementType.EXPRESSION_LIST) { - return false; - } - ASTNode parent = myNode.getTreeParent(); - if (parent == null || parent.getElementType() != JavaElementType.METHOD_CALL_EXPRESSION) { - return false; - } - - PsiExpression[] arguments = ((PsiExpressionList)myNode.getPsi()).getExpressions(); - return JavaFormatterUtil.hasMultilineArguments(arguments) && JavaFormatterUtil.isMultilineExceptArguments(arguments); - } - private static boolean isAnonymousClass(@Nullable ASTNode node) { if (node == null || node.getElementType() != JavaElementType.NEW_EXPRESSION) { return false; diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java b/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java index 799027f701b5..e5e3ed668fce 100644 --- a/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java +++ b/java/java-impl/src/com/intellij/psi/formatter/java/ChainMethodCallsBlockBuilder.java @@ -75,8 +75,10 @@ class ChainMethodCallsBlockBuilder { for (int i = 0; i < methodCall.size(); i++) { ChainedCallChunk currentCallChunk = methodCall.get(i); if (isMethodCall(currentCallChunk)) { - if (myWrap == null) myWrap = createCallChunkWrap(i, methodCall); - if (myChainedCallsAlignment == null) myChainedCallsAlignment = createCallChunkAlignment(i, methodCall); + if (myWrap == null) + myWrap = createCallChunkWrap(i, methodCall); + if (myChainedCallsAlignment == null) + myChainedCallsAlignment = createCallChunkAlignment(i, methodCall); } else { myWrap = null; @@ -137,7 +139,7 @@ class ChainMethodCallsBlockBuilder { private boolean isMethodCall(@NotNull ChainedCallChunk callChunk) { List nodes = callChunk.nodes; - return !nodes.isEmpty() && nodes.get(nodes.size() - 1).getElementType() == JavaElementType.EXPRESSION_LIST; + return nodes.size() >= 3 && nodes.get(2).getElementType() == JavaElementType.EXPRESSION_LIST; } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java index 5fc8d7b07da2..f39d316b5bd1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/impl/JavaGotoSuperTest.java @@ -96,7 +96,7 @@ public class JavaGotoSuperTest extends LightDaemonAnalyzerTestCase { assertSame(MarkerType.OVERRIDDEN_METHOD.getNavigationHandler(), iMarker.getNavigationHandler()); LineMarkerInfo aMarker = findMarkerWithElement(markers, aRun.getNameIdentifier()); - assertSame(MarkerType.OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler()); + assertSame(MarkerType.SIBLING_OVERRIDING_METHOD.getNavigationHandler(), aMarker.getNavigationHandler()); } private static LineMarkerInfo findMarkerWithElement(List markers, PsiElement psiMethod) { diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java index dadf7fbf590f..c45fa4cfdbdd 100644 --- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterAlignmentTest.java @@ -48,7 +48,42 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest { " .foo();" ); } + + public void testChainedMethodWithComments() throws Exception { + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true; + doMethodTest("AAAAA.b()\n" + + ".c() // comment after line\n" + + ".d()\n" + + ".e();", + "AAAAA.b()\n" + + " .c() // comment after line\n" + + " .d()\n" + + " .e();"); + } + + public void testChainedMethodWithBlockComment() { + getSettings().ALIGN_MULTILINE_CHAINED_METHODS = true; + doTextTest("class X {\n" + + " public void test() {\n" + + " AAAAAA.b()\n" + + ".c()\n" + + ".d()\n" + + " /* simple block comment */\n" + + ".e();\n" + + " }\n" + + "}", + "class X {\n" + + " public void test() {\n" + + " AAAAAA.b()\n" + + " .c()\n" + + " .d()\n" + + " /* simple block comment */\n" + + " .e();\n" + + " }\n" + + "}"); + } + public void testMultipleMethodAnnotationsCommentedInTheMiddle() throws Exception { getSettings().BLANK_LINES_AFTER_CLASS_HEADER = 1; getSettings().getRootSettings().getIndentOptions(StdFileTypes.JAVA).INDENT_SIZE = 4; @@ -256,7 +291,7 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest { "}" ); } - + public void testAnnotatedAndNonAnnotatedFieldsInColumnsAlignment() { // Inspired by IDEA-60237 @@ -281,10 +316,10 @@ public class JavaFormatterAlignmentTest extends AbstractJavaFormatterTest { "}" ); } - + public void testAlignThrowsKeyword() throws Exception { // Inspired by IDEA-63820 - + getSettings().ALIGN_THROWS_KEYWORD = true; doClassTest( "public void test()\n" + diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterMultilineMethodCallParamsTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterMultilineMethodCallParamsTest.java new file mode 100644 index 000000000000..d80b29c25191 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterMultilineMethodCallParamsTest.java @@ -0,0 +1,106 @@ +/* + * 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.psi.formatter.java; + +public class JavaFormatterMultilineMethodCallParamsTest extends AbstractJavaFormatterTest { + + + public void testChainedMethodInsideCall() { + doMethodTest( + "call(new StringBuilder()\n" + + ".append(\"aaa\")\n" + + ".append(\"bbbb\"));", + "call(new StringBuilder()\n" + + " .append(\"aaa\")\n" + + " .append(\"bbbb\"));" + ); + } + + public void IGNORED_testChainedMethodInsideCall_WithRParenOnNewLine() { + doMethodTest( + "call(new StringBuilder()\n" + + ".append(\"aaa\")\n" + + ".append(\"bbbb\")\n" + + ");", + "call(new StringBuilder()\n" + + " .append(\"aaa\")\n" + + " .append(\"bbbb\")\n" + + ");" + ); + } + + public void testChainedMethodInsideCall_Shifted() { + doMethodTest( + "call(new StringBuilder()\n" + + ".append(\"aaa\")\n" + + ".append(\"bbbb\"),\n" + + "\"aaaa\");", + "call(new StringBuilder()\n" + + " .append(\"aaa\")\n" + + " .append(\"bbbb\"),\n" + + " \"aaaa\");" + ); + } + + public void testChainedMethodInsideCall_Shifted_WithRParentOnNewLine() { + doMethodTest( + "call(new StringBuilder()\n" + + ".append(\"aaa\")\n" + + ".append(\"bbbb\"),\n" + + "\"aaaa\"\n" + + ");", + "call(new StringBuilder()\n" + + " .append(\"aaa\")\n" + + " .append(\"bbbb\"),\n" + + " \"aaaa\"\n" + + ");" + ); + } + + public void testAnonClassAsParameter() { + doMethodTest( + "call(new Runnable() {\n" + + "@Override\n" + + "public void run() {\n" + + "}\n" + + "});", + "call(new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " }\n" + + "});" + ); + } + + public void testAnonClassWithRParent_OnNextLine() { + doMethodTest( + "foo(new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " }\n" + + "}\n" + + ");\n", + "foo(new Runnable() {\n" + + " @Override\n" + + " public void run() {\n" + + " }\n" + + " }\n" + + ");\n" + ); + } + + +} diff --git a/platform/configuration-store-impl/src/ComponentStoreImpl.kt b/platform/configuration-store-impl/src/ComponentStoreImpl.kt index b7fca615e950..dcd128e91820 100644 --- a/platform/configuration-store-impl/src/ComponentStoreImpl.kt +++ b/platform/configuration-store-impl/src/ComponentStoreImpl.kt @@ -33,6 +33,7 @@ import com.intellij.openapi.project.Project import com.intellij.openapi.util import com.intellij.openapi.util.* import com.intellij.openapi.util.Pair +import com.intellij.openapi.util.registry.Registry import com.intellij.openapi.vfs.VirtualFile import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess import com.intellij.util.ArrayUtilRt @@ -240,15 +241,14 @@ abstract class ComponentStoreImpl : IComponentStore { val defaultState = if (stateSpec.defaultStateAsResource) getDefaultState(component, name, stateClass) else null val storageSpecs = getStorageSpecs(component, stateSpec, StateStorageOperation.READ) - val stateStorageChooser = component as? StateStorageChooserEx + val storageChooser = component as? StateStorageChooserEx for (storageSpec in storageSpecs) { - val resolution = if (stateStorageChooser == null) Resolution.DO else stateStorageChooser.getResolution(storageSpec, StateStorageOperation.READ) - if (resolution === Resolution.SKIP) { + if (storageChooser?.getResolution(storageSpec, StateStorageOperation.READ) == Resolution.SKIP) { continue } val storage = storageManager.getStateStorage(storageSpec) - var stateGetter = (storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass) + var stateGetter = if (isUseLoadedStateAsExisting(storageSpec) && Registry.`is`("use.loaded.state.as.existing", false)) (storage as? StorageBaseEx<*>)?.createGetSession(component, name, stateClass) else null var state = if (stateGetter == null) storage.getState(component, name, stateClass, defaultState, reloadData) else stateGetter.getState(defaultState) if (state == null) { if (changedStorages != null && changedStorages.contains(storage)) { @@ -276,6 +276,8 @@ abstract class ComponentStoreImpl : IComponentStore { return name } + protected open fun isUseLoadedStateAsExisting(storageSpec: Storage): Boolean = true + protected open fun getPathMacroManagerForDefaults(): PathMacroManager? = null private fun getDefaultState(component: Any, componentName: String, stateClass: Class): T? { diff --git a/platform/configuration-store-impl/src/DirectoryBasedStorage.kt b/platform/configuration-store-impl/src/DirectoryBasedStorage.kt index c31da745fab6..75b0933332bb 100644 --- a/platform/configuration-store-impl/src/DirectoryBasedStorage.kt +++ b/platform/configuration-store-impl/src/DirectoryBasedStorage.kt @@ -62,7 +62,7 @@ open class DirectoryBasedStorage(private val myPathMacroSubstitutor: TrackingPat } } - override fun getState(storageData: Map, component: Any?, componentName: String) = getCompositeStateAndArchive(storageData, componentName, mySplitter) + override fun getSerializedState(storageData: Map, component: Any?, componentName: String, archive: Boolean) = getCompositeStateAndArchive(storageData, componentName, mySplitter) override fun loadData(): MutableMap { return fromMap(DirectoryStorageUtil.loadFrom(getVirtualFile(), myPathMacroSubstitutor)) @@ -174,7 +174,7 @@ open class DirectoryBasedStorage(private val myPathMacroSubstitutor: TrackingPat writeFile(null, this, file, storeElement, LineSeparator.fromString(if (file.exists()) loadFile(file).second else SystemProperties.getLineSeparator()), false) } catch (e: IOException) { - StateStorageBase.LOG.error(e) + LOG.error(e) } finally { if (element != null) { diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index 5ca7c61f9f6c..f3a5128b3aa6 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -288,6 +288,8 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM } override fun selectDefaultStorages(storages: Array, operation: StateStorageOperation) = selectDefaultStorages(storages, operation, scheme) + + override fun isUseLoadedStateAsExisting(storageSpec: Storage) = storageSpec.file != StoragePathMacros.WORKSPACE_FILE } fun selectDefaultStorages(storages: Array, operation: StateStorageOperation, scheme: StorageScheme): Array { diff --git a/platform/configuration-store-impl/src/StateMap.kt b/platform/configuration-store-impl/src/StateMap.kt index b90b8d5b815f..93a11d6deafa 100644 --- a/platform/configuration-store-impl/src/StateMap.kt +++ b/platform/configuration-store-impl/src/StateMap.kt @@ -122,8 +122,6 @@ class StateMap private constructor(private val names: Array, private val fun isEmpty() = names.isEmpty() - fun getState(key: String) = get(key) as? Element - fun hasState(key: String) = get(key) is Element public fun hasStates(): Boolean { @@ -152,14 +150,19 @@ class StateMap private constructor(private val names: Array, private val } } - public fun getStateAndArchive(key: String): Element? { + fun getStateAndArchive(key: String) = getState(key, true) + + fun getState(key: String, archive: Boolean = false): Element? { val index = Arrays.binarySearch(names, key) if (index < 0) { return null } val state = states.get(index) as? Element ?: return null - return if (states.compareAndSet(index, state, archiveState(state))) state else getStateAndArchive(key) + if (!archive) { + return state + } + return if (states.compareAndSet(index, state, archiveState(state))) state else getState(key, true) } public fun archive(key: String, state: Element?) { diff --git a/platform/configuration-store-impl/src/StorageBaseEx.kt b/platform/configuration-store-impl/src/StorageBaseEx.kt index 94affaa5693e..ffed4fad4cf5 100644 --- a/platform/configuration-store-impl/src/StorageBaseEx.kt +++ b/platform/configuration-store-impl/src/StorageBaseEx.kt @@ -28,22 +28,23 @@ abstract class StorageBaseEx : StateStorageBase() { abstract fun archiveState(storageData: T, componentName: String, serializedState: Element?) } -class StateGetter(private val component: PersistentStateComponent, private val componentName: String, private val storageData: T, private val stateClass: Class, private val storage: StorageBaseEx) { +class StateGetter(private val component: PersistentStateComponent, + private val componentName: String, + private val storageData: T, + private val stateClass: Class, + private val storage: StorageBaseEx) { var serializedState: Element? = null fun getState(mergeInto: S? = null): S? { LOG.assertTrue(serializedState == null) - serializedState = storage.getState(storageData, component, componentName) + serializedState = storage.getSerializedState(storageData, component, componentName, false) if (serializedState != null) { //System.out.println("open $componentName to read state, ${hashCode()} $storage, ${Thread.currentThread()}") } return storage.deserializeState(serializedState, stateClass, mergeInto) } - /** - * nullable - because PersistentStateComponent can return nullable state - */ fun close() { if (serializedState == null) { return diff --git a/platform/configuration-store-impl/src/XmlElementStorage.kt b/platform/configuration-store-impl/src/XmlElementStorage.kt index 67bed1a75dac..8d16a69a9585 100644 --- a/platform/configuration-store-impl/src/XmlElementStorage.kt +++ b/platform/configuration-store-impl/src/XmlElementStorage.kt @@ -37,7 +37,7 @@ abstract class XmlElementStorage protected constructor(protected val fileSpec: S protected abstract fun loadLocalData(): Element? - override final fun getState(storageData: StateMap, component: Any?, componentName: String) = storageData.getState(componentName) + override final fun getSerializedState(storageData: StateMap, component: Any?, componentName: String, archive: Boolean) = storageData.getState(componentName, archive) override fun archiveState(storageData: StateMap, componentName: String, serializedState: Element?) { storageData.archive(componentName, serializedState) diff --git a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt index 5e5c5d89d58d..2120a265f162 100644 --- a/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt +++ b/platform/configuration-store-impl/testSrc/ApplicationStoreTest.kt @@ -110,7 +110,7 @@ class ApplicationStoreTest { } @State(name = "A", storages = arrayOf(Storage(file = "a.xml"))) - private class A : PersistentStateComponent { + private open class A : PersistentStateComponent { data class State(@Attribute var foo: String = "", @Attribute var bar: String = "") var state = State() @@ -144,6 +144,24 @@ class ApplicationStoreTest { assertThat(file).hasContent("\n \n") } + @Test fun `do not apply to workspace storage - do not save if only format is changed`() { + @State(name = "A", storages = arrayOf(Storage(file = StoragePathMacros.WORKSPACE_FILE))) + class AWorkspace : A() + + val oldContent = "" + val file = writeConfig("workspace.xml", oldContent) + val oldModificationTime = file.getLastModifiedTime() + testAppConfig.refreshVfs() + + val component = AWorkspace() + componentStore.initComponent(component, false) + assertThat(component.state).isEqualTo(A.State("old")) + + saveStore() + + assertThat(file).hasContent("\n \n") + } + private fun saveStore() { runInEdtAndWait { componentStore.save(SmartList()) } } @@ -188,7 +206,10 @@ class ApplicationStoreTest { override fun setPath(path: String) { storageManager.addMacro(StoragePathMacros.APP_CONFIG, path) + storageManager.addMacro(StoragePathMacros.WORKSPACE_FILE, "$path/workspace.xml") } + + override fun isUseLoadedStateAsExisting(storageSpec: Storage) = storageSpec.file != StoragePathMacros.WORKSPACE_FILE } abstract class Foo { diff --git a/platform/configuration-store-impl/testSrc/XmlElementStorageTest.kt b/platform/configuration-store-impl/testSrc/XmlElementStorageTest.kt index ad55501e98c5..d31a37ac7e95 100644 --- a/platform/configuration-store-impl/testSrc/XmlElementStorageTest.kt +++ b/platform/configuration-store-impl/testSrc/XmlElementStorageTest.kt @@ -24,7 +24,7 @@ import org.junit.Test class XmlElementStorageTest { @Test fun testGetStateSucceeded() { val storage = MyXmlElementStorage(tag("root", tag("component", attr("name", "test"), tag("foo")))) - val state = storage.getState(this, "test", javaClass(), null, false) + val state = storage.getState(this, "test", javaClass()) assertThat(state).isNotNull() assertThat(state!!.getName()).isEqualTo("component") assertThat(state.getChild("foo")).isNotNull() @@ -32,7 +32,7 @@ class XmlElementStorageTest { @Test fun `get state not succeeded`() { val storage = MyXmlElementStorage(tag("root")) - val state = storage.getState(this, "test", javaClass(), null, false) + val state = storage.getState(this, "test", javaClass()) assertThat(state).isNull() } diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java index 67e3ea3952de..8d12bfe863a9 100644 --- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java +++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java @@ -360,24 +360,28 @@ public class LexerEditorHighlighter implements EditorHighlighter, PrioritizedDoc // Called to determine visual attributes of inserted character prior to starting a write action. // TODO Should be removed when we implement typing without starting write actions. public TextAttributes getAttributes(DocumentImpl document, int offset, char c) { - final int segmentIndex; - try { - segmentIndex = mySegments.findSegmentIndex(offset) - 2; - } - catch (IndexOutOfBoundsException ex) { - throw new IndexOutOfBoundsException(ex.getMessage() + " Lexer: " + myLexer); - } - int startIndex = Math.max(0, segmentIndex); + int startOffset = 0; - int data; - do { - data = mySegments.getSegmentData(startIndex); - if (isInitialState(data)|| startIndex == 0) break; - startIndex--; - } - while (true); + if (mySegments.getSegmentCount() > 0) { + final int segmentIndex; + try { + segmentIndex = mySegments.findSegmentIndex(offset) - 2; + } + catch (IndexOutOfBoundsException ex) { + throw new IndexOutOfBoundsException(ex.getMessage() + " Lexer: " + myLexer); + } + int startIndex = Math.max(0, segmentIndex); - int startOffset = mySegments.getSegmentStart(startIndex); + int data; + do { + data = mySegments.getSegmentData(startIndex); + if (isInitialState(data)|| startIndex == 0) break; + startIndex--; + } + while (true); + + startOffset = mySegments.getSegmentStart(startIndex); + } ImmutableText newText = document.getImmutableText().insert(offset, Character.toString(c)); diff --git a/platform/lang-api/src/com/intellij/formatting/Indent.java b/platform/lang-api/src/com/intellij/formatting/Indent.java index b8cc9fd45ed7..62f80608de91 100644 --- a/platform/lang-api/src/com/intellij/formatting/Indent.java +++ b/platform/lang-api/src/com/intellij/formatting/Indent.java @@ -269,6 +269,10 @@ public abstract class Indent { return myFactory.getIndent(type, spaces, relativeToDirectParent, enforceIndentToChildren); } + public static Indent getSmartIndent(Type type) { + return myFactory.getSmartIndent(type); + } + public static class Type { private final String myName; diff --git a/platform/lang-api/src/com/intellij/formatting/IndentFactory.java b/platform/lang-api/src/com/intellij/formatting/IndentFactory.java index b18949adf2bb..35d2d52d6aa5 100644 --- a/platform/lang-api/src/com/intellij/formatting/IndentFactory.java +++ b/platform/lang-api/src/com/intellij/formatting/IndentFactory.java @@ -34,4 +34,5 @@ interface IndentFactory { Indent getSpaceIndent(final int spaces, boolean relativeToDirectParent); Indent getIndent(@NotNull Indent.Type type, boolean relativeToDirectParent, boolean enforceIndentToChildren); Indent getIndent(@NotNull Indent.Type type, int spaces, boolean relativeToDirectParent, boolean enforceIndentToChildren); + Indent getSmartIndent(@NotNull Indent.Type type); } diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java index b59f14a8a709..61d827693091 100644 --- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java +++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettingsManager.java @@ -61,8 +61,9 @@ public class CommonCodeStyleSettingsManager implements JDOMExternalizable { public CommonCodeStyleSettings getCommonSettings(@Nullable Language lang) { Map commonSettingsMap = getCommonSettingsMap(); CommonCodeStyleSettings settings = commonSettingsMap.get(lang); - if (settings == null && lang != null) { - settings = commonSettingsMap.get(lang.getBaseLanguage()); + while (settings == null && lang != null) { + lang = lang.getBaseLanguage(); + settings = commonSettingsMap.get(lang); } if (settings != null) { return settings; diff --git a/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java b/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java new file mode 100644 index 000000000000..c3d40c6bad40 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/formatting/ExpandableIndent.java @@ -0,0 +1,35 @@ +/* + * 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.formatting; + +public class ExpandableIndent extends IndentImpl { + private boolean myEnforceIndent; + + public ExpandableIndent(Type type) { + super(type, false, 0, false, true); + myEnforceIndent = false; + } + + @Override + public boolean isEnforceIndentToChildren() { + return myEnforceIndent; + } + + void setEnforceIndent(boolean value) { + myEnforceIndent = value; + } + +} diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index 908e098a2c3b..3c1a0851a7f5 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -34,6 +34,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.MultiMap; import com.intellij.util.ui.UIUtil; import gnu.trove.TIntObjectHashMap; import org.jetbrains.annotations.NotNull; @@ -158,6 +159,7 @@ public class FormatProcessor { @NotNull private State myCurrentState; + private MultiMap myExpandableIndents; public FormatProcessor(final FormattingDocumentModel docModel, Block rootBlock, @@ -248,7 +250,11 @@ public class FormatProcessor { public void format(FormattingModel model, boolean sequentially) { if (sequentially) { AdjustWhiteSpacesState adjustState = new AdjustWhiteSpacesState(); - adjustState.setNext(new ApplyChangesState(model)); + ExpandChildrenIndent expandChildrenIndent = new ExpandChildrenIndent(); + ApplyChangesState applyChangesState = new ApplyChangesState(model); + + expandChildrenIndent.setNext(applyChangesState); + adjustState.setNext(expandChildrenIndent); myCurrentState.setNext(adjustState); } else { @@ -284,7 +290,9 @@ public class FormatProcessor { @SuppressWarnings({"WhileLoopSpinsOnField"}) public void formatWithoutRealModifications(boolean sequentially) { - myCurrentState.setNext(new AdjustWhiteSpacesState()); + AdjustWhiteSpacesState adjustSpace = new AdjustWhiteSpacesState(); + adjustSpace.setNext(new ExpandChildrenIndent()); + myCurrentState.setNext(adjustSpace); if (sequentially) { return; @@ -1357,6 +1365,8 @@ public class FormatProcessor { root, model, affectedRanges, mySettings, myDefaultIndentOption, interestingOffset, myProgressCallback ); myWrapper.setCollectAlignmentsInsideFormattingRange(myReformatContext); + + myExpandableIndents = myWrapper.getExpandableIndentsBlocks(); } @Override @@ -1526,24 +1536,24 @@ public class FormatProcessor { } } } - + private static class CaretOffsetUpdater { private final Map myCaretOffsets = new HashMap(); - + private CaretOffsetUpdater(@NotNull Document document) { Editor[] editors = EditorFactory.getInstance().getEditors(document); for (Editor editor : editors) { myCaretOffsets.put(editor, editor.getCaretModel().getOffset()); } } - + private void update(@NotNull List changes) { BulkChangesMerger merger = BulkChangesMerger.INSTANCE; for (Map.Entry entry : myCaretOffsets.entrySet()) { entry.setValue(merger.updateOffset(entry.getValue(), changes)); } } - + private void restoreCaretLocations() { for (Map.Entry entry : myCaretOffsets.entrySet()) { entry.getKey().getCaretModel().moveToOffset(entry.getValue()); @@ -1580,4 +1590,80 @@ public class FormatProcessor { myInterestingOffset = interestingOffset; } } + + private class ExpandChildrenIndent extends State { + private Iterator myIterator; + + public ExpandChildrenIndent() { + super(FormattingStateId.EXPANDING_CHILDREN_INDENTS); + } + + @Override + protected void doIteration() { + if (myIterator == null) { + myIterator = myExpandableIndents.keySet().iterator(); + } + if (!myIterator.hasNext()) { + setDone(true); + return; + } + + final ExpandableIndent indent = myIterator.next(); + Collection blocksToExpandIndent = myExpandableIndents.get(indent); + if (shouldExpand(blocksToExpandIndent)) { + for (AbstractBlockWrapper block : blocksToExpandIndent) { + indent.setEnforceIndent(true); + reindentNewLineChildren(block); + indent.setEnforceIndent(false); + } + } + } + + private boolean shouldExpand(Collection blocksToExpandIndent) { + AbstractBlockWrapper last = null; + for (AbstractBlockWrapper block : blocksToExpandIndent) { + if (block.getWhiteSpace().containsLineFeeds()) { + return true; + } + last = block; + } + + if (last != null) { + AbstractBlockWrapper prev = getPreviousBlock(last); + return prev != null && prev.getWhiteSpace().containsLineFeeds(); + } + + return false; + } + + private AbstractBlockWrapper getPreviousBlock(AbstractBlockWrapper block) { + List children = block.getParent().getChildren(); + int nextBlockIndex = children.indexOf(block) + 1; + if (nextBlockIndex < children.size()) { + return children.get(nextBlockIndex); + } + return null; + } + + private void reindentNewLineChildren(final @NotNull AbstractBlockWrapper block) { + if (block instanceof LeafBlockWrapper) { + WhiteSpace space = block.getWhiteSpace(); + + if (space.containsLineFeeds()) { + myCurrentBlock = (LeafBlockWrapper)block; + adjustIndent(); + } + } + else if (block instanceof CompositeBlockWrapper) { + List children = ((CompositeBlockWrapper)block).getChildren(); + for (AbstractBlockWrapper childBlock : children) { + reindentNewLineChildren(childBlock); + } + } + } + + @Override + protected void prepare() { + } + } } diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java index 3454c507dc7e..f8dbc4ed53f9 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatterImpl.java @@ -818,6 +818,11 @@ public class FormatterImpl extends FormatterEx return getIndent(type, 0, relativeToDirectParent, enforceIndentToChildren); } + @Override + public Indent getSmartIndent(@NotNull Indent.Type type) { + return new ExpandableIndent(type); + } + @Override public Indent getIndent(@NotNull Indent.Type type, int spaces, boolean relativeToDirectParent, boolean enforceIndentToChildren) { return new IndentImpl(type, false, spaces, relativeToDirectParent, enforceIndentToChildren); diff --git a/platform/lang-impl/src/com/intellij/formatting/FormattingStateId.java b/platform/lang-impl/src/com/intellij/formatting/FormattingStateId.java index 5d4aa1c801d2..728cfa4b08eb 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormattingStateId.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormattingStateId.java @@ -46,6 +46,8 @@ public enum FormattingStateId { */ PROCESSING_BLOCKS(1), + EXPANDING_CHILDREN_INDENTS(5), + /** * This element corresponds to formatting phase when all {@link AbstractBlockWrapper wrapped code blocks} are processed and it's * time to apply the changes to the underlying document. diff --git a/platform/lang-impl/src/com/intellij/formatting/IndentInfo.java b/platform/lang-impl/src/com/intellij/formatting/IndentInfo.java index 1b79d6a494ad..168ec6123d6d 100644 --- a/platform/lang-impl/src/com/intellij/formatting/IndentInfo.java +++ b/platform/lang-impl/src/com/intellij/formatting/IndentInfo.java @@ -24,21 +24,39 @@ public class IndentInfo { private final int mySpaces; private final int myIndentSpaces; - private final int myLineFeeds; + private final int myHiddenSpaces; + private final int myLineFeeds; /** @see WhiteSpace#setForceSkipTabulationsUsage(boolean) */ private final boolean myForceSkipTabulationsUsage; private boolean myIndentEmptyLines; // Additional indent on empty lines (before the end of code block) public IndentInfo(final int lineFeeds, final int indentSpaces, final int spaces) { - this(lineFeeds, indentSpaces, spaces, false); + this(lineFeeds, indentSpaces, spaces, 0, false); } - public IndentInfo(final int lineFeeds, final int indentSpaces, final int spaces, final boolean forceSkipTabulationsUsage) { + public IndentInfo(final int lineFeeds, + final int indentSpaces, + final int spaces, + final int hiddenSpaces) + { + this(lineFeeds, indentSpaces, spaces, hiddenSpaces, false); + } + + public IndentInfo(final int lineFeeds, + final int indentSpaces, + final int spaces, + final boolean forceSkipTabulationsUsage) + { + this(lineFeeds, indentSpaces, spaces, 0, forceSkipTabulationsUsage); + } + + public IndentInfo(final int lineFeeds, final int indentSpaces, final int spaces, final int hiddenSpaces, final boolean forceSkipTabulationsUsage) { mySpaces = spaces; myIndentSpaces = indentSpaces; myLineFeeds = lineFeeds; myForceSkipTabulationsUsage = forceSkipTabulationsUsage; + myHiddenSpaces = hiddenSpaces; } public int getSpaces() { diff --git a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java index b8cb7105d410..46045c827735 100644 --- a/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java +++ b/platform/lang-impl/src/com/intellij/formatting/InitialInfoBuilder.java @@ -29,6 +29,8 @@ import com.intellij.psi.formatter.FormattingDocumentModelImpl; import com.intellij.psi.formatter.ReadOnlyBlockInformationProvider; import com.intellij.psi.impl.DebugUtil; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.LinkedMultiMap; +import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.Stack; import gnu.trove.THashMap; import org.jetbrains.annotations.NonNls; @@ -74,6 +76,8 @@ class InitialInfoBuilder { private Set myAlignmentsInsideRangeToModify = ContainerUtil.newHashSet(); private boolean myCollectAlignmentsInsideFormattingRange = false; + private MultiMap myBlocksToForceChildrenIndent = new LinkedMultiMap(); + private InitialInfoBuilder(final Block rootBlock, final FormattingDocumentModel model, @Nullable final FormatTextRanges affectedRanges, @@ -285,6 +289,10 @@ class InitialInfoBuilder { return wrappedRootBlock; } + public MultiMap getExpandableIndentsBlocks() { + return myBlocksToForceChildrenIndent; + } + private void doIteration(@NotNull State state) { List subBlocks = state.parentBlock.getSubBlocks(); final int subBlocksCount = subBlocks.size(); @@ -303,6 +311,7 @@ class InitialInfoBuilder { final AbstractBlockWrapper wrapper = buildFrom( block, childBlockIndex, state.wrappedBlock, state.parentBlockWrap, state.parentBlock, childBlockIsRightBlock ); + registerExpandableIndents(block, wrapper); if (wrapper.getIndent() == null) { wrapper.setIndent((IndentImpl)block.getIndent()); @@ -321,7 +330,14 @@ class InitialInfoBuilder { } } } - + + private void registerExpandableIndents(@NotNull Block block, @NotNull AbstractBlockWrapper wrapper) { + if (block.getIndent() instanceof ExpandableIndent) { + ExpandableIndent indent = (ExpandableIndent)block.getIndent(); + myBlocksToForceChildrenIndent.putValue(indent, wrapper); + } + } + private void setDefaultIndents(final List list) { if (!list.isEmpty()) { for (AbstractBlockWrapper wrapper : list) { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java index 7b07acf493ce..c94202d6f927 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java @@ -25,6 +25,7 @@ import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.components.impl.stores.StateStorageBase; import com.intellij.openapi.components.impl.stores.StateStorageManager; import com.intellij.openapi.components.impl.stores.StorageManagerListener; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.ModuleRootModel; @@ -55,6 +56,8 @@ import java.util.Set; // Boolean - false as not loaded, true as loaded public class ClasspathStorage extends StateStorageBase { + private static final Logger LOG = Logger.getInstance(ClasspathStorage.class); + @NonNls public static final String SPECIAL_STORAGE = "special"; private final ClasspathStorageProvider.ClasspathConverter myConverter; @@ -135,7 +138,7 @@ public class ClasspathStorage extends StateStorageBase { @Nullable @Override - public Element getState(@NotNull Boolean storageData, Object component, @NotNull String componentName) { + public Element getSerializedState(@NotNull Boolean storageData, Object component, @NotNull String componentName, boolean archive) { if (storageData) { return null; } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java index 5a0fc06a21cb..dfd37eae7b9c 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java @@ -29,10 +29,10 @@ import com.intellij.openapi.fileTypes.FileTypeListener; import com.intellij.openapi.fileTypes.FileTypeManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.PushedFilePropertiesUpdater; import com.intellij.openapi.startup.StartupManager; -import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.impl.BulkVirtualFileListenerAdapter; @@ -60,6 +60,30 @@ public class PsiVFSListener extends VirtualFileAdapter { private final Project myProject; private boolean myReportedUnloadedPsiChange; + static { + ApplicationManager.getApplication().getMessageBus().connect().subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { + @Override + public void before(@NotNull List events) { + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + PsiVFSListener listener = project.getComponent(PsiVFSListener.class); + assert listener != null; + new BulkVirtualFileListenerAdapter(listener).before(events); + } + } + + @Override + public void after(@NotNull List events) { + for (Project project : ProjectManager.getInstance().getOpenProjects()) { + PsiVFSListener listener = project.getComponent(PsiVFSListener.class); + assert listener != null; + listener.myReportedUnloadedPsiChange = false; + new BulkVirtualFileListenerAdapter(listener).after(events); + listener.myReportedUnloadedPsiChange = false; + } + } + }); + } + public PsiVFSListener(Project project) { myProject = project; myFileTypeManager = FileTypeManager.getInstance(); @@ -72,20 +96,6 @@ public class PsiVFSListener extends VirtualFileAdapter { StartupManager.getInstance(project).registerPreStartupActivity(new Runnable() { @Override public void run() { - final BulkVirtualFileListenerAdapter adapter = new BulkVirtualFileListenerAdapter(PsiVFSListener.this); - myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() { - @Override - public void before(@NotNull List events) { - adapter.before(events); - } - - @Override - public void after(@NotNull List events) { - myReportedUnloadedPsiChange = false; - adapter.after(events); - myReportedUnloadedPsiChange = false; - } - }); myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new MyModuleRootListener()); myConnection.subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() { @Override @@ -595,11 +605,6 @@ public class PsiVFSListener extends VirtualFileAdapter { true, false); } - // When file is renamed so that extension changes then language dialect might change and thus psiFile should be invalidated - private static boolean languageDialectChanged(final PsiFile newPsiFile, String oldFileName) { - return newPsiFile != null && !FileUtilRt.extensionEquals(oldFileName, FileUtilRt.getExtension(newPsiFile.getName())); - } - private class MyModuleRootListener implements ModuleRootListener { private VirtualFile[] myOldContentRoots = null; private volatile int depthCounter = 0; diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.kt b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.kt index 0223a27d6ce8..5f2d9556f819 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.kt +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageBase.kt @@ -22,22 +22,26 @@ import java.util.concurrent.atomic.AtomicReference public abstract class StateStorageBase : StateStorage { companion object { - protected val LOG: Logger = Logger.getInstance(javaClass>()) + private val LOG: Logger = Logger.getInstance(javaClass>()) } private var mySavingDisabled = false protected val storageDataRef: AtomicReference = AtomicReference() - override fun getState(component: Any?, componentName: String, stateClass: Class, mergeInto: S?, reload: Boolean): S? { - return deserializeState(getState(getStorageData(reload), component, componentName), stateClass, mergeInto) + override final fun getState(component: Any?, componentName: String, stateClass: Class, mergeInto: S?, reload: Boolean): S? { + return getState(component, componentName, stateClass, true, reload, mergeInto) + } + + fun getState(component: Any?, componentName: String, stateClass: Class, archive: Boolean = true, reload: Boolean = false, mergeInto: S? = null): S? { + return deserializeState(getSerializedState(getStorageData(reload), component, componentName, archive), stateClass, mergeInto) } open fun deserializeState(serializedState: Element?, stateClass: Class, mergeInto: S?): S? { return DefaultStateSerializer.deserializeState(serializedState, stateClass, mergeInto) } - abstract fun getState(storageData: T, component: Any?, componentName: String): Element? + abstract fun getSerializedState(storageData: T, component: Any?, componentName: String, archive: Boolean = true): Element? protected abstract fun hasState(storageData: T, componentName: String): Boolean @@ -45,9 +49,7 @@ public abstract class StateStorageBase : StateStorage { return hasState(getStorageData(reloadData), componentName) } - public fun getStorageData(): T { - return getStorageData(false) - } + public fun getStorageData(): T = getStorageData(false) protected fun getStorageData(reload: Boolean): T { val storageData = storageDataRef.get() diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java index 4926fc4b9e2c..38c8290cea6f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/EditorGutterComponentEx.java @@ -52,6 +52,8 @@ public abstract class EditorGutterComponentEx extends JComponent implements Edit public abstract int getLineMarkerAreaOffset(); + public abstract int getIconAreaOffset(); + public abstract int getLineMarkerFreePaintersAreaOffset(); public abstract int getIconsAreaWidth(); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java index 7865d0877b9c..2cca0857a059 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorGutterComponentImpl.java @@ -82,8 +82,9 @@ import java.util.List; class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener, DataProvider { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorGutterComponentImpl"); private static final int START_ICON_AREA_WIDTH = 15; - private static final int FREE_PAINTERS_AREA_WIDTH = 5; - private static final int GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA = 5; + private static final int FREE_PAINTERS_LEFT_AREA_WIDTH = 8; + private static final int FREE_PAINTERS_RIGHT_AREA_WIDTH = 5; + private static final int GAP_BETWEEN_ICONS_AND_RIGHT_FREE_PAINTERS_AREA = 5; private static final int GAP_BETWEEN_ICONS = 3; private static final int GAP_BEFORE_LINE_NUMBERS = 5; private static final int GAP_AFTER_LINE_NUMBERS = 4; @@ -97,7 +98,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private final EditorImpl myEditor; private final FoldingAnchorsOverlayStrategy myAnchorsDisplayStrategy; - private int myLineMarkerAreaWidth = START_ICON_AREA_WIDTH + GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA + FREE_PAINTERS_AREA_WIDTH; private int myIconsAreaWidth = START_ICON_AREA_WIDTH; private int myLineNumberAreaWidth = 0; private int myAdditionalLineNumberAreaWidth = 0; @@ -116,6 +116,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse @Nullable private ActionGroup myCustomGutterPopupGroup; private TIntObjectHashMap myTextFgColors = new TIntObjectHashMap(); private boolean myPaintBackground = true; + private boolean myLeftFreePaintersAreaShown; @SuppressWarnings("unchecked") public EditorGutterComponentImpl(EditorImpl editor) { @@ -629,14 +630,14 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private void updateSizeInner(boolean onLayout) { if (!onLayout) { calcLineNumberAreaWidth(); - calcIconAreaWidth(); + calcLineMarkerAreaWidth(); calcAnnotationsSize(); } calcAnnotationExtraSize(); } private int sizeHash() { - int result = myLineMarkerAreaWidth; + int result = getLineMarkerAreaWidth(); result = 31 * result + myTextAnnotationGuttersSize; result = 31 * result + myTextAnnotationExtraSize; result = 31 * result + getLineNumberAreaWidth(); @@ -682,19 +683,27 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse int width = editorLocationX + editorComponent.getWidth(); if (rightMarginX < width && editorLocationX < width - rightMarginX) { - int centeredSize = (width - rightMarginX - editorLocationX) / 2 - (myLineMarkerAreaWidth + getLineNumberAreaWidth()); + int centeredSize = (width - rightMarginX - editorLocationX) / 2 - (getLineMarkerAreaWidth() + getLineNumberAreaWidth()); myTextAnnotationExtraSize = Math.max(0, centeredSize - myTextAnnotationGuttersSize); } } private TIntObjectHashMap> myLineToGutterRenderers; - private void calcIconAreaWidth() { + private void calcLineMarkerAreaWidth() { myLineToGutterRenderers = new TIntObjectHashMap>(); + myLeftFreePaintersAreaShown = false; processRangeHighlighters(0, myEditor.getDocument().getTextLength(), new RangeHighlighterProcessor() { @Override public void process(@NotNull RangeHighlighter highlighter) { + LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer(); + if (lineMarkerRenderer instanceof LineMarkerRendererEx && + ((LineMarkerRendererEx)lineMarkerRenderer).getPosition() == LineMarkerRendererEx.Position.LEFT && + isLineMarkerVisible(highlighter)) { + myLeftFreePaintersAreaShown = true; + } + GutterMark renderer = highlighter.getGutterIconRenderer(); if (renderer == null) { return; @@ -734,8 +743,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse return true; } }); - - myLineMarkerAreaWidth = myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA + FREE_PAINTERS_AREA_WIDTH; } private boolean isHighlighterVisible(RangeHighlighter highlighter) { @@ -791,28 +798,30 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } private void paintLineMarkerRenderer(RangeHighlighter highlighter, Graphics g) { - Rectangle rectangle = getLineRendererRectangle(highlighter); - - if (rectangle != null) { - final LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer(); - assert lineMarkerRenderer != null; - lineMarkerRenderer.paint(myEditor, g, rectangle); + LineMarkerRenderer lineMarkerRenderer = highlighter.getLineMarkerRenderer(); + if (lineMarkerRenderer != null) { + Rectangle rectangle = getLineRendererRectangle(highlighter); + if (rectangle != null) { + lineMarkerRenderer.paint(myEditor, g, rectangle); + } } } - - @Nullable - private Rectangle getLineRendererRectangle(RangeHighlighter highlighter) { - LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer(); - if (renderer == null) return null; - + + private boolean isLineMarkerVisible(RangeHighlighter highlighter) { int startOffset = highlighter.getStartOffset(); int endOffset = highlighter.getEndOffset(); FoldRegion startFoldRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(startOffset); FoldRegion endFoldRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(endOffset); - if (startFoldRegion != null && endFoldRegion != null && startFoldRegion.equals(endFoldRegion)) { - return null; - } + return startFoldRegion == null || endFoldRegion == null || !startFoldRegion.equals(endFoldRegion); + } + + @Nullable + private Rectangle getLineRendererRectangle(RangeHighlighter highlighter) { + if (!isLineMarkerVisible(highlighter)) return null; + + int startOffset = highlighter.getStartOffset(); + int endOffset = highlighter.getEndOffset(); int startY = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(startOffset)).y; @@ -825,9 +834,13 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse endY += myEditor.getLineHeight(); } + LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer(); + boolean leftPosition = renderer instanceof LineMarkerRendererEx && + ((LineMarkerRendererEx)renderer).getPosition() == LineMarkerRendererEx.Position.LEFT; + int height = endY - startY; - int w = FREE_PAINTERS_AREA_WIDTH; - int x = getLineMarkerFreePaintersAreaOffset() - 1; + int w = leftPosition ? FREE_PAINTERS_LEFT_AREA_WIDTH : FREE_PAINTERS_RIGHT_AREA_WIDTH; + int x = leftPosition ? getLineMarkerAreaOffset() : getLineMarkerFreePaintersAreaOffset() - 1; return new Rectangle(x, startY, w, height); } @@ -845,7 +858,7 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse private void processIconsRow(int line, List row, LineGutterIconRendererProcessor processor) { int middleCount = 0; int middleSize = 0; - int x = getLineMarkerAreaOffset() + 2; + int x = getIconAreaOffset() + 2; final int y = myEditor.logicalPositionToXY(new LogicalPosition(line, 0)).y; for (GutterMark r : row) { @@ -862,9 +875,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - final int leftSize = x - getLineMarkerAreaOffset(); + final int leftSize = x - getIconAreaOffset(); - x = getLineMarkerAreaOffset() + myIconsAreaWidth - 2; // because of 2px LineMarkerRenderers + x = getIconAreaOffset() + myIconsAreaWidth - 2; // because of 2px LineMarkerRenderers for (GutterMark r : row) { if (!checkDumbAware(r, myEditor.getProject())) continue; if (((GutterIconRenderer)r).getAlignment() == GutterIconRenderer.Alignment.RIGHT) { @@ -875,11 +888,11 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } } - int rightSize = myIconsAreaWidth + getLineMarkerAreaOffset() - x + 1; + int rightSize = myIconsAreaWidth + getIconAreaOffset() - x + 1; if (middleCount > 0) { middleSize -= GAP_BETWEEN_ICONS; - x = getLineMarkerAreaOffset() + leftSize + (myIconsAreaWidth - leftSize - rightSize - middleSize) / 2; + x = getIconAreaOffset() + leftSize + (myIconsAreaWidth - leftSize - rightSize - middleSize) / 2; for (GutterMark r : row) { if (!checkDumbAware(r, myEditor.getProject())) continue; if (((GutterIconRenderer)r).getAlignment() == GutterIconRenderer.Alignment.CENTER) { @@ -1121,7 +1134,9 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } public int getLineMarkerAreaWidth() { - return isLineMarkersShown() ? myLineMarkerAreaWidth : 0; + return isLineMarkersShown() ? ((myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0) + + myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_RIGHT_FREE_PAINTERS_AREA + FREE_PAINTERS_RIGHT_AREA_WIDTH) : + 0; } public void setLineNumberAreaWidthFunction(@NotNull TIntFunction calculator) { @@ -1200,9 +1215,14 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse return getAnnotationsAreaOffset() + getAnnotationsAreaWidthEx(); } + @Override + public int getIconAreaOffset() { + return getLineMarkerAreaOffset() + (myLeftFreePaintersAreaShown ? FREE_PAINTERS_LEFT_AREA_WIDTH : 0); + } + @Override public int getLineMarkerFreePaintersAreaOffset() { - return getLineMarkerAreaOffset() + myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_FREE_PAINTERS_AREA; + return getIconAreaOffset() + myIconsAreaWidth + GAP_BETWEEN_ICONS_AND_RIGHT_FREE_PAINTERS_AREA; } @Override @@ -1466,7 +1486,8 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse processRangeHighlighters(firstVisibleOffset, lastVisibleOffset, new RangeHighlighterProcessor() { @Override public void process(@NotNull RangeHighlighter highlighter) { - if (gutterRenderer[0] != null) return; + LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer(); + if (renderer == null || gutterRenderer[0] != null) return; Rectangle rectangle = getLineRendererRectangle(highlighter); if (rectangle == null) return; @@ -1477,7 +1498,6 @@ class EditorGutterComponentImpl extends EditorGutterComponentEx implements Mouse } if (startY < e.getY() && e.getY() <= endY) { - final LineMarkerRenderer renderer = highlighter.getLineMarkerRenderer(); if (renderer instanceof ActiveGutterRenderer && ((ActiveGutterRenderer)renderer).canDoAction(e)) { gutterRenderer[0] = (ActiveGutterRenderer)renderer; } 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 a2ad202a5e87..c44e3ab1817a 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 @@ -2186,7 +2186,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private boolean canPaintImmediately(char c) { return myDocument instanceof DocumentImpl && myHighlighter instanceof LexerEditorHighlighter && - myDocument.getTextLength() > 0 && !mySelectionModel.hasSelection() && areVisualLinesUnique(myCaretModel.getAllCarets()) && !isInplaceRenamerActive() && @@ -2222,8 +2221,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi TextAttributes attributes = ((LexerEditorHighlighter)myHighlighter).getAttributes((DocumentImpl)myDocument, offset, c); int fontType = attributes.getFontType(); - Font font = fontFor(fontType); + FontInfo fontInfo = EditorUtil.fontForChar(c, attributes.getFontType(), this); + Font font = fontInfo.getFont(); + // it's more reliable to query actual font metrics FontMetrics fontMetrics = getFontMetrics(fontType); int charWidth = fontMetrics.charWidth(c); @@ -2318,7 +2319,10 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi Point point = newArea.getLocation(); int ascent = getAscent(); - Font font = fontFor(attributes.getFontType()); + // simplified font selection (based on the first character) + FontInfo fontInfo = EditorUtil.fontForChar(newText.charAt(0), attributes.getFontType(), this); + Font font = fontInfo.getFont(); + Color color = attributes.getForegroundColor() == null ? getForegroundColor() : attributes.getForegroundColor(); EditorUIUtil.setupAntialiasing(g); @@ -2350,11 +2354,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi return color == null ? getBackgroundColor() : color; } - @NotNull - private Font fontFor(int fontType) { - return myScheme.getFont(EditorFontType.values()[fontType]); - } - private static void shift(@NotNull Graphics g, @NotNull Rectangle r, int delta) { g.copyArea(r.x, r.y, r.width, r.height, delta, 0); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/markup/LineMarkerRendererEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/markup/LineMarkerRendererEx.java new file mode 100644 index 000000000000..51f830b56c43 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/editor/markup/LineMarkerRendererEx.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.openapi.editor.markup; + +import com.intellij.openapi.editor.Editor; + +import java.awt.*; + +public interface LineMarkerRendererEx extends LineMarkerRenderer { + enum Position {LEFT, RIGHT} + + /** + * Determines whether line marker should be rendered to the left or to the right of icon area in gutter. + * Corresponding rectangle will be passed to renderer in {@link #paint(Editor, Graphics, Rectangle)} method. + */ + Position getPosition(); +} diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties index b3d50ee9d245..6255b4009dca 100644 --- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties +++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties @@ -30,6 +30,7 @@ progress.reformat.and.optimize.common.command.text=Reformat and Optimize Imports progress.reformat.stage.wrapping.blocks=Preparing... progress.reformat.stage.processing.blocks=Calculating changes... progress.reformat.stage.applying.changes=Storing changes... +progress.reformat.stage.expanding.children.indents=Expanding necessary children indents process.rearrange.code=Rearranging code... process.reformat.code=Reformat Code process.reformat.code.before.commit=Reformat Code Before Commit @@ -520,4 +521,4 @@ dialog.edit.template.checkbox.xsl.text=XSL Text highlight.imported.classes.chooser.title=Choose Imported Classes to Highlight highlight.imported.members.chooser.title=Choose Imported Members to Highlight javadoc.resolved.value=Resolved value\: -javadoc.error.resolving.url=Couldn''t resolve URL {0}

Configuring paths to API docs in project settings might help \ No newline at end of file +javadoc.error.resolving.url=Couldn''t resolve URL {0}

Configuring paths to API docs in project settings might help diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 85efd2301fbd..e68c86255fc1 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -652,6 +652,7 @@ testDiscovery.enabled=false ruby.remote.debugger.supports.catchpoint.removal=true use.read.action.to.init.service=true +use.loaded.state.as.existing=false ide.mac.new.color.picker=false diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SuperTearDownInFinallyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SuperTearDownInFinallyInspection.java index 8bfce245a778..667c1592020c 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SuperTearDownInFinallyInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SuperTearDownInFinallyInspection.java @@ -55,7 +55,7 @@ public class SuperTearDownInFinallyInspection extends BaseInspection { return; } final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiMember.class, PsiLambdaExpression.class); - if (method == null) { + if (method == null || !method.getName().equals("tearDown")) { return; } final PsiClass containingClass = method.getContainingClass(); diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/super_tear_down_in_finally/SuperTearDownInFinally.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/super_tear_down_in_finally/SuperTearDownInFinally.java index 869536184627..0cd7f1f9e1cf 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/super_tear_down_in_finally/SuperTearDownInFinally.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/super_tear_down_in_finally/SuperTearDownInFinally.java @@ -1,17 +1,19 @@ -class SuperTearDownInFinally extends junit.framework.TestCase { +import junit.framework.TestCase; + +class SuperTearDownInFinally extends TestCase { public void tearDown() throws Exception { super.tearDown(); System.out.println(); } } -class NoProblem extends junit.framework.TestCase { +class NoProblem extends TestCase { public void tearDown() throws Exception { super.tearDown(); } } -class CalledInFinally extends junit.framework.TestCase { +class CalledInFinally extends TestCase { public void tearDown() throws Exception { try { @@ -20,4 +22,16 @@ class CalledInFinally extends junit.framework.TestCase { super.tearDown(); } } +} +class SomeTest extends TestCase { + @Override + protected void setUp() throws Exception { + try { + super.setUp(); + } + catch (Throwable t) { + super.tearDown(); // yellow code + } + } + public void test_something() {} } \ No newline at end of file diff --git a/plugins/coverage-common/src/com/intellij/coverage/CoverageLineMarkerRenderer.java b/plugins/coverage-common/src/com/intellij/coverage/CoverageLineMarkerRenderer.java index e25e82570cd9..190c35bf46d3 100644 --- a/plugins/coverage-common/src/com/intellij/coverage/CoverageLineMarkerRenderer.java +++ b/plugins/coverage-common/src/com/intellij/coverage/CoverageLineMarkerRenderer.java @@ -1,5 +1,17 @@ /* - * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved. + * 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.coverage; @@ -25,6 +37,7 @@ import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.EditorGutterComponentEx; import com.intellij.openapi.editor.impl.EditorImpl; import com.intellij.openapi.editor.markup.ActiveGutterRenderer; +import com.intellij.openapi.editor.markup.LineMarkerRendererEx; import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.SearchableConfigurable; @@ -57,7 +70,7 @@ import java.util.TreeMap; /** * @author ven */ -public class CoverageLineMarkerRenderer implements ActiveGutterRenderer { +public class CoverageLineMarkerRenderer implements LineMarkerRendererEx, ActiveGutterRenderer { private static final int THICKNESS = 8; private final TextAttributesKey myKey; private final String myClassName; @@ -97,10 +110,10 @@ public class CoverageLineMarkerRenderer implements ActiveGutterRenderer { if (bgColor != null) { g.setColor(bgColor); } - g.fillRect(0, r.y, THICKNESS, r.height); + g.fillRect(r.x, r.y, r.width, r.height); final LineData lineData = getLineData(editor.xyToLogicalPosition(new Point(0, r.y)).line); if (lineData != null && lineData.isCoveredByOneTest()) { - g.drawImage( ImageLoader.loadFromResource("/gutter/unique.png"), 0, r.y, 8, 8, editor.getComponent()); + g.drawImage( ImageLoader.loadFromResource("/gutter/unique.png"), r.x, r.y, 8, 8, editor.getComponent()); } } @@ -135,7 +148,12 @@ public class CoverageLineMarkerRenderer implements ActiveGutterRenderer { } public boolean canDoAction(final MouseEvent e) { - return e.getX() < THICKNESS; + Component component = e.getComponent(); + if (component instanceof EditorGutterComponentEx) { + EditorGutterComponentEx gutter = (EditorGutterComponentEx)component; + return e.getX() > gutter.getLineMarkerAreaOffset() && e.getX() < gutter.getIconAreaOffset(); + } + return false; } public void doAction(final Editor editor, final MouseEvent e) { @@ -253,6 +271,11 @@ public class CoverageLineMarkerRenderer implements ActiveGutterRenderer { return editor.getColorsScheme().getAttributes(myKey).getErrorStripeColor(); } + @Override + public Position getPosition() { + return Position.LEFT; + } + private class GotoPreviousCoveredLineAction extends BaseGotoCoveredLineAction { public GotoPreviousCoveredLineAction(final Editor editor, final int lineNumber) { diff --git a/plugins/junit/src/META-INF/plugin.xml b/plugins/junit/src/META-INF/plugin.xml index 52e8d652e22f..368745b059a9 100644 --- a/plugins/junit/src/META-INF/plugin.xml +++ b/plugins/junit/src/META-INF/plugin.xml @@ -40,7 +40,7 @@ - + diff --git a/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java index 35ff7804c85e..334f71bae46e 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/AllInDirectoryConfigurationProducer.java @@ -17,6 +17,7 @@ package com.intellij.execution.junit; import com.intellij.execution.actions.ConfigurationContext; +import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.junit2.info.LocationUtil; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; @@ -31,6 +32,14 @@ import org.jetbrains.jps.model.java.JavaSourceRootType; public class AllInDirectoryConfigurationProducer extends JUnitConfigurationProducer { + + protected AllInDirectoryConfigurationProducer(ConfigurationType configurationType) { + super(configurationType); + } + + public AllInDirectoryConfigurationProducer() { + } + @Override protected boolean setupConfigurationFromContext(JUnitConfiguration configuration, ConfigurationContext context, diff --git a/plugins/junit/src/com/intellij/execution/junit/AllInPackageConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/AllInPackageConfigurationProducer.java index 4958c15ee4f2..80af0736c961 100644 --- a/plugins/junit/src/com/intellij/execution/junit/AllInPackageConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/AllInPackageConfigurationProducer.java @@ -18,6 +18,7 @@ package com.intellij.execution.junit; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.ConfigurationFromContext; +import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.junit2.info.LocationUtil; import com.intellij.openapi.util.Ref; import com.intellij.psi.PsiElement; @@ -25,6 +26,14 @@ import com.intellij.psi.PsiPackage; public class AllInPackageConfigurationProducer extends JUnitConfigurationProducer { + + public AllInPackageConfigurationProducer() { + } + + protected AllInPackageConfigurationProducer(ConfigurationType configurationType) { + super(configurationType); + } + @Override protected boolean setupConfigurationFromContext(JUnitConfiguration configuration, ConfigurationContext context, diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java index c1a958d5ce5f..7ea6a5927fc8 100644 --- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java @@ -23,6 +23,7 @@ import com.intellij.execution.RunnerAndConfigurationSettings; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.ConfigurationFromContext; import com.intellij.execution.actions.RunConfigurationProducer; +import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.configurations.RunConfiguration; import com.intellij.execution.junit2.PsiMemberParameterizedLocation; import com.intellij.openapi.module.Module; @@ -36,6 +37,10 @@ public abstract class JUnitConfigurationProducer extends JavaRunConfigurationPro super(JUnitConfigurationType.getInstance()); } + protected JUnitConfigurationProducer(ConfigurationType configurationType) { + super(configurationType); + } + @Override public boolean isPreferredConfiguration(ConfigurationFromContext self, ConfigurationFromContext other) { return !other.isProducedBy(TestMethodConfigurationProducer.class); diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java index ae036f95c83e..43633a89a9e3 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java @@ -21,6 +21,7 @@ import com.intellij.execution.Location; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.ConfigurationFromContext; import com.intellij.execution.actions.RunConfigurationProducer; +import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.junit2.PsiMemberParameterizedLocation; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.Ref; @@ -31,6 +32,13 @@ import com.intellij.psi.PsiMethod; import java.util.List; public class TestClassConfigurationProducer extends JUnitConfigurationProducer { + public TestClassConfigurationProducer() { + } + + protected TestClassConfigurationProducer(ConfigurationType configurationType) { + super(configurationType); + } + @Override protected boolean setupConfigurationFromContext(JUnitConfiguration configuration, ConfigurationContext context, diff --git a/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java index c2e0e3118382..c3dd9654fc33 100644 --- a/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java +++ b/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java @@ -22,6 +22,7 @@ import com.intellij.execution.PsiLocation; import com.intellij.execution.actions.ConfigurationContext; import com.intellij.execution.actions.ConfigurationFromContext; import com.intellij.execution.actions.RunConfigurationProducer; +import com.intellij.execution.configurations.ConfigurationType; import com.intellij.execution.junit2.PsiMemberParameterizedLocation; import com.intellij.execution.junit2.info.MethodLocation; import com.intellij.openapi.module.Module; @@ -35,6 +36,13 @@ import java.util.Iterator; import java.util.List; public class TestMethodConfigurationProducer extends JUnitConfigurationProducer { + public TestMethodConfigurationProducer() { + } + + protected TestMethodConfigurationProducer(ConfigurationType configurationType) { + super(configurationType); + } + @Override protected boolean setupConfigurationFromContext(JUnitConfiguration configuration, ConfigurationContext context, diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java index c769e6c872ca..a66c6d841dcb 100644 --- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java +++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigator.java @@ -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. @@ -92,6 +92,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen myShortcutsManager = shortcutsManager; } + @Override public MavenProjectsNavigatorState getState() { ApplicationManager.getApplication().assertIsDispatchThread(); if (myStructure != null) { @@ -106,6 +107,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen return myState; } + @Override public void loadState(MavenProjectsNavigatorState state) { myState = state; scheduleStructureUpdate(); @@ -183,6 +185,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen listenForProjectsChanges(); if (isUnitTestMode()) return; MavenUtil.runWhenInitialized(myProject, new DumbAwareRunnable() { + @Override public void run() { if (myProject.isDisposed()) return; initToolWindow(); @@ -200,8 +203,10 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen myProjectsManager.addProjectsTreeListener(new MyProjectsListener()); myShortcutsManager.addListener(new MavenShortcutsManager.Listener() { + @Override public void shortcutsUpdated() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateGoals(); } @@ -210,8 +215,10 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen }); myTasksManager.addListener(new MavenTasksManager.Listener() { + @Override public void compileTasksChanged() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateGoals(); } @@ -220,8 +227,10 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen }); RunManagerEx.getInstanceEx(myProject).addRunManagerListener(new RunManagerAdapter() { + @Override public void beforeRunTasksChanged() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateGoals(); } @@ -233,6 +242,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen @Override public void skipTestsChanged() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateGoals(); } @@ -243,6 +253,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen ((RunManagerEx)RunManager.getInstance(myProject)).addRunManagerListener(new RunManagerAdapter() { private void changed() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateRunConfigurations(); } @@ -291,9 +302,11 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen public void stateChanged() { if (myToolWindow.isDisposed()) return; boolean visible = myToolWindow.isVisible(); - if (!visible || visible == wasVisible) return; + if (!visible || wasVisible) { + return; + } scheduleStructureUpdate(); - wasVisible = visible; + wasVisible = true; } }; manager.addToolWindowManagerListener(listener, myProject); @@ -350,6 +363,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen public void selectInTree(final MavenProject project) { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.select(project); } @@ -364,6 +378,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen if (myToolWindow == null) return; MavenUtil.invokeLater(myProject, new Runnable() { + @Override public void run() { if (!myToolWindow.isVisible()) return; @@ -396,6 +411,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen private void scheduleStructureUpdate() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.update(); } @@ -403,10 +419,12 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen } private class MyProjectsListener extends MavenProjectsTree.ListenerAdapter implements MavenProjectsManager.Listener { + @Override public void activated() { scheduleStructureUpdate(); } + @Override public void projectsScheduled() { } @@ -417,6 +435,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen @Override public void projectsIgnoredStateChanged(final List ignored, final List unignored, boolean fromImport) { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateIgnored(ContainerUtil.concat(ignored, unignored)); } @@ -426,6 +445,7 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen @Override public void profilesChanged() { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateProfiles(); } @@ -437,17 +457,20 @@ public class MavenProjectsNavigator extends MavenSimpleProjectComponent implemen scheduleUpdateProjects(MavenUtil.collectFirsts(updated), deleted); } + @Override public void projectResolved(Pair projectWithChanges, NativeMavenProjectHolder nativeMavenProject) { scheduleUpdateProjects(Collections.singletonList(projectWithChanges.first), Collections.emptyList()); } + @Override public void pluginsResolved(MavenProject project) { scheduleUpdateProjects(Collections.singletonList(project), Collections.emptyList()); } private void scheduleUpdateProjects(final List projects, final List deleted) { scheduleStructureRequest(new Runnable() { + @Override public void run() { myStructure.updateProjects(projects, deleted); } diff --git a/plugins/testng/src/META-INF/plugin.xml b/plugins/testng/src/META-INF/plugin.xml index 6f47dd780bad..760f92488ea8 100644 --- a/plugins/testng/src/META-INF/plugin.xml +++ b/plugins/testng/src/META-INF/plugin.xml @@ -57,7 +57,7 @@ groupName="TestNG" enabledByDefault="true" level="ERROR" implementationClass="com.theoryinpractice.testng.inspection.DataProviderReturnTypeInspection"/> - + diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/Painter.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/Painter.java index c2f734e4748d..b0e7b77fa347 100644 --- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/Painter.java +++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/Painter.java @@ -15,6 +15,8 @@ */ package com.intellij.uiDesigner.designSurface; +import com.intellij.ide.ui.UISettings; +import com.intellij.ui.JBColor; import com.intellij.ui.LightColors; import com.intellij.uiDesigner.FormEditingUtil; import com.intellij.uiDesigner.SwingProperties; @@ -457,7 +459,8 @@ public final class Painter { Graphics2D g2d = (Graphics2D)g; g2d.setColor(PlatformColors.BLUE); g2d.fillRect(0, 0, (int)stringBounds.getWidth(), (int)stringBounds.getHeight()); - g2d.setColor(Color.WHITE); + g2d.setColor(JBColor.WHITE); + UISettings.setupAntialiasing(g); g.drawString(tagBuilder.toString(), 0, g.getFontMetrics().getAscent()); } } diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties index 4e8f16a937b5..5cb85518e745 100644 --- a/resources-en/src/messages/DebuggerBundle.properties +++ b/resources-en/src/messages/DebuggerBundle.properties @@ -393,6 +393,7 @@ message.node.all.array.elements.null=All elements in range ({0}, {1}) are null message.node.all.elements.null=All elements are null message.node.empty.array=Empty message.node.class.has.no.fields=Class has no fields +message.node.class.no.fields.to.display=No fields to display message.node.object.collected=Object has been garbage collected during method invocation message.node.thread.running=Thread is running message.node.thread.has.no.frames=Thread has no frames diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml index 88edfb5bd1f3..290e85f5a6fe 100644 --- a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml +++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml @@ -115,7 +115,7 @@ - +