From e5804ef5c3b1c3640354bf2d966c2c50b5eedd06 Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 11 May 2011 14:57:58 +0200 Subject: [PATCH 01/43] AppCode:Project Model: allow absent fileRef in PBXBuildFile --- .../execution/testframework/sm/runner/SMTestProxy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index 5a896c2db8d1..439d85b628c6 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -15,7 +15,7 @@ */ package com.intellij.execution.testframework.sm.runner; -import com.google.common.collect.Lists; +//import com.google.common.collect.Lists; import com.intellij.execution.Location; import com.intellij.execution.testframework.AbstractTestProxy; import com.intellij.execution.testframework.Filter; @@ -339,7 +339,7 @@ public class SMTestProxy extends AbstractTestProxy { public List collectChildren() { final List allChildren = getChildren(); - final List result = Lists.newArrayList(); + final List result = null;//Lists.newArrayList(); result.addAll(allChildren); From 8f5d93edf8387d3aaecd457eb0b939d488e2ed43 Mon Sep 17 00:00:00 2001 From: Dmitry Trofimov Date: Wed, 11 May 2011 17:13:06 +0400 Subject: [PATCH 02/43] Reverted broken method. (Anton, why did you do that?) --- .../execution/testframework/sm/runner/SMTestProxy.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index 439d85b628c6..5a896c2db8d1 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -15,7 +15,7 @@ */ package com.intellij.execution.testframework.sm.runner; -//import com.google.common.collect.Lists; +import com.google.common.collect.Lists; import com.intellij.execution.Location; import com.intellij.execution.testframework.AbstractTestProxy; import com.intellij.execution.testframework.Filter; @@ -339,7 +339,7 @@ public class SMTestProxy extends AbstractTestProxy { public List collectChildren() { final List allChildren = getChildren(); - final List result = null;//Lists.newArrayList(); + final List result = Lists.newArrayList(); result.addAll(allChildren); From 8a7832e9863fef83f503040349a7fed3946f9865 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Wed, 11 May 2011 17:22:34 +0400 Subject: [PATCH 03/43] tab/escape for live template work in injected fragment --- .../src/com/intellij/openapi/editor/actions/EscapeAction.java | 1 + .../src/com/intellij/openapi/editor/actions/TabAction.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java index 6ffff109d4b5..e6c3422b4bb0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EscapeAction.java @@ -29,6 +29,7 @@ import com.intellij.openapi.editor.actionSystem.EditorActionHandler; public class EscapeAction extends EditorAction { public EscapeAction() { super(new Handler()); + setInjectedContext(true); } private static class Handler extends EditorActionHandler { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java index a590a220f588..26651392f4f7 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java @@ -42,6 +42,7 @@ import com.intellij.openapi.vfs.VirtualFile; public class TabAction extends EditorAction { public TabAction() { super(new Handler()); + setInjectedContext(true); } private static class Handler extends EditorWriteActionHandler { @@ -89,7 +90,7 @@ public class TabAction extends EditorAction { EditorModificationUtil.typeInStringAtCaretHonorBlockSelection(editor, "\t", false); } else { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(spacesToAddCount); for(int i=0; i Date: Wed, 11 May 2011 17:26:45 +0400 Subject: [PATCH 04/43] cleanup --- .../src/com/intellij/codeInsight/hint/EscapeHandler.java | 2 +- .../src/com/intellij/ide/actions/SelectAllAction.java | 7 ++++--- .../openapi/editor/actions/TextComponentEditorAction.java | 1 - 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/EscapeHandler.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/EscapeHandler.java index 8cf30f26a15e..8751f9339ae2 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/EscapeHandler.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/EscapeHandler.java @@ -30,7 +30,7 @@ public class EscapeHandler extends EditorActionHandler { public void execute(Editor editor, DataContext dataContext) { Project project = PlatformDataKeys.PROJECT.getData(dataContext); - if (project == null || !HintManagerImpl.getInstanceImpl().hideHints(HintManagerImpl.HIDE_BY_ESCAPE | HintManagerImpl.HIDE_BY_ANY_KEY, true, false)) { + if (project == null || !HintManagerImpl.getInstanceImpl().hideHints(HintManager.HIDE_BY_ESCAPE | HintManager.HIDE_BY_ANY_KEY, true, false)) { myOriginalHandler.execute(editor, dataContext); } } diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java index 8b2d47a7deb1..684e2fa4c27a 100644 --- a/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java +++ b/platform/platform-impl/src/com/intellij/ide/actions/SelectAllAction.java @@ -16,10 +16,12 @@ package com.intellij.ide.actions; import com.intellij.ide.IdeBundle; -import com.intellij.openapi.actionSystem.*; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.DataContext; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.actionSystem.Presentation; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actions.TextComponentEditorAction; import com.intellij.openapi.project.DumbAware; @@ -27,7 +29,6 @@ import com.intellij.openapi.project.DumbAware; public class SelectAllAction extends TextComponentEditorAction implements DumbAware { public SelectAllAction() { super(new Handler()); - setEnabledInModalContext(true); } private static class Handler extends EditorActionHandler { diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java index ae531890e800..95040714e5e5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java @@ -31,7 +31,6 @@ import javax.swing.text.JTextComponent; public abstract class TextComponentEditorAction extends EditorAction { protected TextComponentEditorAction(final EditorActionHandler defaultHandler) { super(defaultHandler); - setEnabledInModalContext(true); } @Nullable From e08db0b4c372861844dda2759e479649be348fd9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 11 May 2011 16:17:53 +0400 Subject: [PATCH 05/43] helpId && usability --- .../internal/statistic/configurable/StatisticsConfigurable.java | 2 +- .../configurable/StatisticsConfigurationComponent.form | 2 +- .../configurable/StatisticsConfigurationComponent.java | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurable.java b/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurable.java index fde991032105..ecccce03f888 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurable.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurable.java @@ -55,7 +55,7 @@ public class StatisticsConfigurable implements SearchableConfigurable { @Nullable @NonNls public String getHelpTopic() { - return null; + return "preferences.usage.statictics"; } public JComponent createComponent() { diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.form b/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.form index a0f299834ab9..abc0308b4aaf 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.form +++ b/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.form @@ -14,7 +14,7 @@ - + diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.java index d723b8717e61..0d4f1057eb0d 100644 --- a/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/configurable/StatisticsConfigurationComponent.java @@ -16,6 +16,7 @@ package com.intellij.internal.statistic.configurable; import com.intellij.internal.statistic.persistence.UsageStatisticsPersistenceComponent; +import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.ui.ex.MultiLineLabel; import javax.swing.*; @@ -32,6 +33,7 @@ public class StatisticsConfigurationComponent { private JLabel myLabel; public StatisticsConfigurationComponent() { + myTitle.setText("Help improve "+ ApplicationNamesInfo.getInstance().getFullProductName() + " by sending anonymous usage statistics to JetBrains"); myLabel.setText("We're asking your permission to send information about your plugins configuration (what is enabled and what is not)
and feature usage statistics (e.g. how frequently you're using code completion).
This data is anonymous, does not contain any personal information, collected for use only by JetBrains
and will never be transmitted to any third party."); } From dd17c0b2cef3c5e244a1c04427e49c62b438e0d0 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Wed, 11 May 2011 15:46:36 +0200 Subject: [PATCH 06/43] fix tests [r=peter] --- .../src/com/intellij/openapi/extensions/Extensions.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java index 8d32554056e4..475e4eb9a6f4 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java @@ -34,7 +34,7 @@ public class Extensions { public static final ExtensionPointName AREA_LISTENER_EXTENSION_POINT = new ExtensionPointName("com.intellij.arealistener"); private static final Map ourAreaInstance2area = new HashMap(); - private static final ExtensionsAreaImpl ourRootArea = createRootArea(); + private static ExtensionsAreaImpl ourRootArea = createRootArea(); private static final MultiMap ourAreaClass2instances = new MultiMap(); private static final Map ourAreaInstance2class = new HashMap(); private static final Map ourAreaClass2Configuration = new HashMap(); @@ -42,7 +42,6 @@ public class Extensions { private static ExtensionsAreaImpl createRootArea() { ExtensionsAreaImpl rootArea = new ExtensionsAreaImpl(null, null, null, ourLogger); rootArea.registerExtensionPoint(AREA_LISTENER_EXTENSION_POINT.getName(), AreaListener.class.getName()); - ourAreaInstance2area.put(null, rootArea); return rootArea; } @@ -72,7 +71,7 @@ public class Extensions { oldRootArea.notifyAreaReplaced(); Disposer.register(parentDisposable, new Disposable() { public void dispose() { - ourAreaInstance2area.put(null, oldRootArea); + ourRootArea = oldRootArea; newArea.notifyAreaReplaced(); } }); From bd57a1d4fe93812b51a6cc64d4455515d6722d22 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 15:05:57 +0200 Subject: [PATCH 07/43] assertions and a possible fix for EA-27207 - item not in lookup --- .../completion/impl/LiftShorterItemsClassifier.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java index eecb16174ce9..d16d88e4b38e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java @@ -20,6 +20,8 @@ import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; +import gnu.trove.THashSet; +import gnu.trove.TObjectHashingStrategy; import java.util.*; @@ -76,7 +78,7 @@ class LiftShorterItemsClassifier extends Classifier { } private Iterable> liftShorterElements(List source, Set lifted) { - final Set srcSet = new HashSet(source); + final Set srcSet = new THashSet(source, TObjectHashingStrategy.IDENTITY); final Iterable> classified = myNext.classify(source); final Set processed = new HashSet(); @@ -84,6 +86,7 @@ class LiftShorterItemsClassifier extends Classifier { for (List list : classified) { final ArrayList group = new ArrayList(); for (LookupElement element : list) { + assert srcSet.contains(element) : myNext; if (processed.add(element)) { final List prefixes = new SmartList(); for (String string : getAllLookupStrings(element)) { From aa190980998bb1e6db46f7f8e462cf44c8a2918f Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 15:09:29 +0200 Subject: [PATCH 08/43] don't hide the lookup under a change guard (EA-27725) --- .../src/com/intellij/codeInsight/hint/HintManagerImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java index d0a16fcd3c0f..10355f027d52 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java @@ -405,7 +405,9 @@ public class HintManagerImpl extends HintManager implements Disposable { LOG.assertTrue(SwingUtilities.isEventDispatchThread()); List hints = new ArrayList(myHintsStack); for (HintInfo info : hints) { - info.hint.hide(); + if (!info.hint.vetoesHiding()) { + info.hint.hide(); + } } cleanup(); } From 5bcdcc6613cd9396ef47d1f57fe76965d0148acc Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 15:38:32 +0200 Subject: [PATCH 09/43] don't try to create java type from groovy expression text, use resolve to determine if a reference of a class type --- .../GrReferenceExpressionImpl.java | 32 ++----------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java index 3dda83d1a10b..fdeed0cb9b5e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceExpressionImpl.java @@ -491,14 +491,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl { @Nullable public PsiType fun(GrReferenceExpressionImpl refExpr) { From d6c43e4053c48bd5568f8862bf42ca21e02c3dfc Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 15:40:37 +0200 Subject: [PATCH 10/43] reduce visibility --- .../src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java index 8a2318319fbd..12ccc64c8c3b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java @@ -1128,7 +1128,7 @@ public class PsiUtil { return ((GrListOrMap)firstArg).getNamedArguments(); } - public static boolean seemsToBeQualifiedClassName(@Nullable GrExpression qualifier) { + private static boolean seemsToBeQualifiedClassName(@Nullable GrExpression qualifier) { if (qualifier == null) return false; while (qualifier instanceof GrReferenceExpression) { final PsiElement nameElement = ((GrReferenceExpression)qualifier).getReferenceNameElement(); From 57e253d5383cc47aee38fa77d8973ec20e77bdce Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 16:23:13 +0200 Subject: [PATCH 11/43] [^cdr] tolerate empty LazyParseableElements --- .../src/com/intellij/psi/impl/source/tree/AstBufferUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java index d21f7a81da56..d7acb0d738cb 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/AstBufferUtil.java @@ -50,7 +50,7 @@ public class AstBufferUtil { if (composite instanceof LazyParseableElement) { LazyParseableElement lpe = (LazyParseableElement)composite; int lpeResult = lpe.copyTo(buffer, result[0]); - if (lpeResult > 0) { + if (lpeResult >= 0) { result[0] = lpeResult; return; } From 4e3e206038417e2e82cb29d66a9dc459aa03d72e Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 11 May 2011 18:34:42 +0400 Subject: [PATCH 12/43] IDEA-69528 Formatter: Correct processing of right-aligned wide blocks that start new line 1. Alignment on right edge is corrected; 2. Corresponding test is uncommented; --- .../AbstractBlockAlignmentProcessor.java | 7 ++-- .../formatting/AbstractBlockWrapper.java | 34 +-------------- .../formatting/BlockAlignmentProcessor.java | 6 ++- .../formatting/CoreFormatterUtil.java | 30 ++++++++++++++ .../intellij/formatting/FormatProcessor.java | 2 +- .../LeftEdgeAlignmentProcessor.java | 3 +- .../RightEdgeAlignmentProcessor.java | 41 +++++++++++++++++-- 7 files changed, 82 insertions(+), 41 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java index e73e1646d491..f7b999698a4e 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockAlignmentProcessor.java @@ -38,8 +38,7 @@ public abstract class AbstractBlockAlignmentProcessor implements BlockAlignmentP return Result.TARGET_BLOCK_PROCESSED_NOT_ALIGNED; } WhiteSpace whiteSpace = context.targetBlock.getWhiteSpace(); - if (whiteSpace.containsLineFeeds()) { - applyIndentToTheFirstBlockOnLine(indent, context); + if (whiteSpace.containsLineFeeds() && applyIndentToTheFirstBlockOnLine(indent, context)) { return Result.TARGET_BLOCK_ALIGNED; } @@ -118,8 +117,10 @@ public abstract class AbstractBlockAlignmentProcessor implements BlockAlignmentP * * @param alignmentAnchorIndent alignment anchor indent * @param context current processing context + * @return true if desired alignment indent is applied to the current block; + * false otherwise */ - protected abstract void applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context); + protected abstract boolean applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context); /** * Calculates the difference between alignment anchor indent and current target block indent. diff --git a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java index debe73fdb099..6fbbc070b4dc 100644 --- a/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java +++ b/platform/lang-impl/src/com/intellij/formatting/AbstractBlockWrapper.java @@ -134,36 +134,6 @@ public abstract class AbstractBlockWrapper { if (wrap != null) wrap.reset(); } - /** - * Calculates indent for the given block and target start offset according to the given indent options. - * - * @param options indent options to use - * @param block target wrapped block - * @param tokenBlockStartOffset target wrapped block offset - * @return indent to use for the given parameters - */ - private static IndentData getIndent(CodeStyleSettings.IndentOptions options, - AbstractBlockWrapper block, - final int tokenBlockStartOffset) { - final IndentImpl indent = block.getIndent(); - if (indent.getType() == Indent.Type.CONTINUATION) { - return new IndentData(options.CONTINUATION_INDENT_SIZE); - } - if (indent.getType() == Indent.Type.CONTINUATION_WITHOUT_FIRST) { - if (block.getStartOffset() != block.getParent().getStartOffset() && block.getStartOffset() == tokenBlockStartOffset) { - return new IndentData(options.CONTINUATION_INDENT_SIZE); - } - else { - return new IndentData(0); - } - } - if (indent.getType() == Indent.Type.LABEL) return new IndentData(options.LABEL_INDENT_SIZE); - if (indent.getType() == Indent.Type.NONE) return new IndentData(0); - if (indent.getType() == Indent.Type.SPACES) return new IndentData(0, indent.getSpaces()); - return new IndentData(options.INDENT_SIZE); - - } - public IndentData getChildOffset(AbstractBlockWrapper child, CodeStyleSettings.IndentOptions options, int targetBlockStartOffset) { final boolean childStartsNewLine = child.getWhiteSpace().containsLineFeeds(); IndentImpl.Type childIndentType = child.getIndent().getType(); @@ -173,7 +143,7 @@ public abstract class AbstractBlockWrapper { if (childStartsNewLine || (!getWhiteSpace().containsLineFeeds() && RELATIVE_INDENT_TYPES.contains(childIndentType) && indentAlreadyUsedBefore(child))) { - childIndent = getIndent(options, child, targetBlockStartOffset); + childIndent = CoreFormatterUtil.getIndent(options, child, targetBlockStartOffset); } else if (child.getIndent().isEnforceIndentToChildren() && !child.getWhiteSpace().containsLineFeeds()) { // Enforce indent if child doesn't start new line, e.g. prefer the code below: @@ -231,7 +201,7 @@ public abstract class AbstractBlockWrapper { } return anchorBlock.getNumberOfSymbolsBeforeBlock(); } - childIndent = getIndent(options, child, getStartOffset()); + childIndent = CoreFormatterUtil.getIndent(options, child, getStartOffset()); } else { childIndent = new IndentData(0); diff --git a/platform/lang-impl/src/com/intellij/formatting/BlockAlignmentProcessor.java b/platform/lang-impl/src/com/intellij/formatting/BlockAlignmentProcessor.java index f46438928c2d..b245b81a13ff 100644 --- a/platform/lang-impl/src/com/intellij/formatting/BlockAlignmentProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/BlockAlignmentProcessor.java @@ -15,6 +15,7 @@ */ package com.intellij.formatting; +import com.intellij.psi.codeStyle.CodeStyleSettings; import org.jetbrains.annotations.NotNull; import java.util.Map; @@ -64,16 +65,19 @@ public interface BlockAlignmentProcessor { @NotNull public final LeafBlockWrapper targetBlock; @NotNull public final Map> alignmentMappings; @NotNull public final Map> backwardShiftedAlignedBlocks; + @NotNull public final CodeStyleSettings.IndentOptions indentOptions; public Context(@NotNull AlignmentImpl alignment, @NotNull LeafBlockWrapper targetBlock, @NotNull Map> alignmentMappings, - @NotNull Map> backwardShiftedAlignedBlocks) + @NotNull Map> backwardShiftedAlignedBlocks, + @NotNull CodeStyleSettings.IndentOptions indentOptions) { this.alignment = alignment; this.targetBlock = targetBlock; this.alignmentMappings = alignmentMappings; this.backwardShiftedAlignedBlocks = backwardShiftedAlignedBlocks; + this.indentOptions = indentOptions; } } } diff --git a/platform/lang-impl/src/com/intellij/formatting/CoreFormatterUtil.java b/platform/lang-impl/src/com/intellij/formatting/CoreFormatterUtil.java index 1d45e6a0fb31..2909a43f5850 100644 --- a/platform/lang-impl/src/com/intellij/formatting/CoreFormatterUtil.java +++ b/platform/lang-impl/src/com/intellij/formatting/CoreFormatterUtil.java @@ -15,6 +15,7 @@ */ package com.intellij.formatting; +import com.intellij.psi.codeStyle.CodeStyleSettings; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -207,4 +208,33 @@ public class CoreFormatterUtil { return true; } + /** + * Calculates indent for the given block and target start offset according to the given indent options. + * + * @param options indent options to use + * @param block target wrapped block + * @param tokenBlockStartOffset target wrapped block offset + * @return indent to use for the given parameters + */ + public static IndentData getIndent(CodeStyleSettings.IndentOptions options, AbstractBlockWrapper block, + final int tokenBlockStartOffset) + { + final IndentImpl indent = block.getIndent(); + if (indent.getType() == Indent.Type.CONTINUATION) { + return new IndentData(options.CONTINUATION_INDENT_SIZE); + } + if (indent.getType() == Indent.Type.CONTINUATION_WITHOUT_FIRST) { + if (block.getStartOffset() != block.getParent().getStartOffset() && block.getStartOffset() == tokenBlockStartOffset) { + return new IndentData(options.CONTINUATION_INDENT_SIZE); + } + else { + return new IndentData(0); + } + } + if (indent.getType() == Indent.Type.LABEL) return new IndentData(options.LABEL_INDENT_SIZE); + if (indent.getType() == Indent.Type.NONE) return new IndentData(0); + if (indent.getType() == Indent.Type.SPACES) return new IndentData(0, indent.getSpaces()); + return new IndentData(options.INDENT_SIZE); + + } } diff --git a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java index e5799aca2a9e..18ca02120bbf 100644 --- a/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/FormatProcessor.java @@ -599,7 +599,7 @@ class FormatProcessor { } BlockAlignmentProcessor.Context context = new BlockAlignmentProcessor.Context( - alignment, myCurrentBlock, myAlignmentMappings, myBackwardShiftedAlignedBlocks + alignment, myCurrentBlock, myAlignmentMappings, myBackwardShiftedAlignedBlocks, myIndentOption ); BlockAlignmentProcessor.Result result = alignmentProcessor.applyAlignment(context); switch (result) { diff --git a/platform/lang-impl/src/com/intellij/formatting/LeftEdgeAlignmentProcessor.java b/platform/lang-impl/src/com/intellij/formatting/LeftEdgeAlignmentProcessor.java index 86403b27d23e..94f719de1f98 100644 --- a/platform/lang-impl/src/com/intellij/formatting/LeftEdgeAlignmentProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/LeftEdgeAlignmentProcessor.java @@ -56,9 +56,10 @@ public class LeftEdgeAlignmentProcessor extends AbstractBlockAlignmentProcessor } @Override - protected void applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context) { + protected boolean applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context) { WhiteSpace whiteSpace = context.targetBlock.getWhiteSpace(); whiteSpace.setSpaces(alignmentAnchorIndent.getSpaces(), alignmentAnchorIndent.getIndentSpaces()); + return true; } @Override diff --git a/platform/lang-impl/src/com/intellij/formatting/RightEdgeAlignmentProcessor.java b/platform/lang-impl/src/com/intellij/formatting/RightEdgeAlignmentProcessor.java index d3d6d23d110a..210826105dc7 100644 --- a/platform/lang-impl/src/com/intellij/formatting/RightEdgeAlignmentProcessor.java +++ b/platform/lang-impl/src/com/intellij/formatting/RightEdgeAlignmentProcessor.java @@ -52,15 +52,50 @@ public class RightEdgeAlignmentProcessor extends AbstractBlockAlignmentProcessor } @Override - protected void applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context) { + protected boolean applyIndentToTheFirstBlockOnLine(@NotNull IndentData alignmentAnchorIndent, @NotNull Context context) { WhiteSpace whiteSpace = context.targetBlock.getWhiteSpace(); int indentSpaces = alignmentAnchorIndent.getIndentSpaces(); int spaces = alignmentAnchorIndent.getSpaces() - context.targetBlock.getSymbolsAtTheLastLine(); if (spaces < 0) { - indentSpaces = Math.max(0, indentSpaces + spaces); + indentSpaces += spaces; spaces = 0; } - whiteSpace.setSpaces(spaces, indentSpaces); + + if (indentSpaces >= 0) { + whiteSpace.setSpaces(spaces, indentSpaces); + return true; + } + if (whiteSpace.getTotalSpaces() > 0) { + // The general idea is that there is a possible case that particular block that starts new line is much wider than its + // preceding aligned block and its white space is not empty. We may move it to the left then trying to preserve its + // indent. + // + // Example: + // block11 block12 + // test-block-that-has-rather-big-width-and-aligned-to-block12 + // Let's say, the last block has indent '10', hence, the result would be: + // block11 block12 + // test-block-that-has-rather-big-width-and-aligned-to-block12 + CompositeBlockWrapper parent = context.targetBlock.getParent(); + if (parent != null) { + IndentData childOffset = CoreFormatterUtil.getIndent( + context.indentOptions, context.targetBlock, context.targetBlock.getStartOffset() + ); + if (whiteSpace.getTotalSpaces() > childOffset.getTotalSpaces()) { + int leftShift = whiteSpace.getTotalSpaces() - childOffset.getTotalSpaces(); + if (leftShift >= whiteSpace.getSpaces()) { + spaces = 0; + indentSpaces = whiteSpace.getIndentSpaces() - (leftShift - whiteSpace.getSpaces()); + } + else { + spaces = whiteSpace.getSpaces() - leftShift; + indentSpaces = whiteSpace.getIndentSpaces(); + } + } + whiteSpace.setSpaces(spaces, indentSpaces); + } + } + return false; } @Override From 8fbc0fb1951500a6b86ae3d7324691a0a18b3729 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 11 May 2011 16:52:08 +0200 Subject: [PATCH 13/43] IDEA-69478 (Wrong generic type on intention replace for each with iterator for loop) --- ...rEachLoopWithIteratorForLoopIntention.java | 31 +++---------------- 1 file changed, 4 insertions(+), 27 deletions(-) diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java index 78d865875057..d90f47a4a4c2 100644 --- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java +++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -49,19 +49,6 @@ public class ReplaceForEachLoopWithIteratorForLoopIntention extends Intention { if (iteratedValue == null) { return; } - final PsiType type = iteratedValue.getType(); - final PsiType iteratedValueParameterType; - if (type instanceof PsiClassType) { - final PsiClassType classType = (PsiClassType)type; - final PsiType[] parameterTypes = classType.getParameters(); - if (parameterTypes.length == 0) { - iteratedValueParameterType = null; - } else { - iteratedValueParameterType = parameterTypes[0]; - } - } else { - iteratedValueParameterType = null; - } @NonNls final StringBuilder newStatement = new StringBuilder(); final PsiParameter iterationParameter = statement.getIterationParameter(); @@ -71,13 +58,9 @@ public class ReplaceForEachLoopWithIteratorForLoopIntention extends Intention { statement, true); final String typeText = parameterType.getCanonicalText(); newStatement.append("for(java.util.Iterator"); - if (iteratedValueParameterType == null) { - newStatement.append(' '); - } else { - newStatement.append('<'); - newStatement.append(iteratedValueParameterType.getCanonicalText()); - newStatement.append("> "); - } + newStatement.append('<'); + newStatement.append(typeText); + newStatement.append("> "); newStatement.append(iterator); newStatement.append(" = "); if (iteratedValue instanceof PsiTypeCastExpression) { @@ -99,12 +82,6 @@ public class ReplaceForEachLoopWithIteratorForLoopIntention extends Intention { newStatement.append(' '); newStatement.append(iterationParameter.getName()); newStatement.append(" = "); - if (iteratedValueParameterType == null && ! - "java.lang.Object".equals(typeText)) { - newStatement.append('('); - newStatement.append(typeText); - newStatement.append(')'); - } newStatement.append(iterator); newStatement.append(".next();"); final PsiStatement body = statement.getBody(); From ab5d9ae1be7d08d4e717aa13dd9acd186b862194 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 11 May 2011 16:54:42 +0200 Subject: [PATCH 14/43] fix exception --- .../debugger/actions/ObjectMarkupPropertiesDialog.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java b/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java index fe2ac9ee5bf5..655960619a74 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java @@ -40,7 +40,7 @@ public class ObjectMarkupPropertiesDialog extends ValueMarkerPresentationDialogB mySuggestAdditionalMarkup = suggestAdditionalMarkup; myDescriptionLabel.setText("If the value is referenced by a constant field of an abstract class,\n" + "IDEA could additionally mark all values referenced from this class with the names of referencing fields."); - myCbMarkAdditionalFields.setSelected(PropertiesComponent.getInstance().getBoolean(MARK_ALL_REFERENCED_VALUES_KEY, true)); + myCbMarkAdditionalFields.setSelected(suggestAdditionalMarkup && PropertiesComponent.getInstance().getBoolean(MARK_ALL_REFERENCED_VALUES_KEY, true)); init(); } @@ -65,6 +65,6 @@ public class ObjectMarkupPropertiesDialog extends ValueMarkerPresentationDialogB } public boolean isMarkAdditionalFields() { - return myCbMarkAdditionalFields.isSelected(); + return mySuggestAdditionalMarkup && myCbMarkAdditionalFields.isSelected(); } } From abd0479b8932f9131ac55e40e4d4fab3efcc4bb2 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 17:02:52 +0200 Subject: [PATCH 15/43] don't reformat the temporary space inserted during class name completion since this leads to tailOffset range marker invalidation (EA-27020) --- .../completion/JavaCompletionUtil.java | 15 ++++++++++++--- .../source/PostprocessReformattingAspect.java | 2 ++ .../psi/impl/source/codeStyle/CodeEditUtil.java | 11 +++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index b1adde398275..c26ea53d17bb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -22,6 +22,7 @@ import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor; import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler; import com.intellij.codeInsight.guess.GuessManager; import com.intellij.codeInsight.lookup.*; +import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; @@ -44,6 +45,8 @@ import com.intellij.psi.filters.element.ExcludeDeclaredFilter; import com.intellij.psi.filters.element.ExcludeSillyAssignment; import com.intellij.psi.html.HtmlTag; import com.intellij.psi.impl.source.PsiImmediateClassType; +import com.intellij.psi.impl.source.codeStyle.CodeEditUtil; +import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.javadoc.PsiDocToken; import com.intellij.psi.scope.BaseScopeProcessor; import com.intellij.psi.scope.ElementClassFilter; @@ -764,7 +767,7 @@ public class JavaCompletionUtil { assert document != null; document.replaceString(startOffset, endOffset, name); - final RangeMarker toDelete = insertTemporary(startOffset + name.length(), document, "#"); + final RangeMarker toDelete = insertTemporary(startOffset + name.length(), document, " "); PsiDocumentManager.getInstance(project).commitAllDocuments(); @@ -781,9 +784,15 @@ public class JavaCompletionUtil { ? ((PsiImportStaticReferenceElement)ref).bindToTargetClass(psiClass) : ref.bindToElement(psiClass); - RangeMarker marker = document.createRangeMarker(newElement.getTextRange()); + ASTNode newNode = newElement.getNode(); + CodeEditUtil.disablePostponedFormatting(newNode); + ASTNode next = TreeUtil.nextLeaf(newNode); + if (next != null) { + CodeEditUtil.disablePostponedFormatting(next); + } + newElement = CodeInsightUtilBase.forcePsiPostprocessAndRestoreElement(newElement); - newStartOffset = marker.getStartOffset(); + newStartOffset = newElement.getTextRange().getStartOffset(); if (!staticImport && newElement instanceof PsiJavaCodeReferenceElement && diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index b96bcdc8ea63..ac5709d3af2d 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -477,6 +477,8 @@ public class PostprocessReformattingAspect implements PomModelAspect, Disposable protected boolean visitNode(TreeElement element) { if (nodesToProcess.contains(element)) return false; + if (CodeEditUtil.isPostponedFormattingDisabled(element)) return false; + final boolean currentNodeGenerated = CodeEditUtil.isNodeGenerated(element); CodeEditUtil.setNodeGenerated(element, false); if (currentNodeGenerated && !inGeneratedContext) { diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java index a5fc25fa03bc..931f9a6d4abc 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java @@ -45,6 +45,7 @@ public class CodeEditUtil { private static final Key INDENT_INFO = new Key("INDENT_INFO"); private static final Key REFORMAT_BEFORE_KEY = new Key("REFORMAT_BEFORE_KEY"); private static final Key REFORMAT_KEY = new Key("REFORMAT_KEY"); + private static final Key DISABLE_POSTPONED_REFORMAT_KEY = new Key("DISABLE_POSTPONED_REFORMAT_KEY"); private static final ThreadLocal ALLOW_TO_MARK_NODES_TO_REFORMAT = new ThreadLocal() { @Override protected Boolean initialValue() { @@ -444,6 +445,16 @@ public class CodeEditUtil { } } + public static void disablePostponedFormatting(@NotNull final ASTNode node) { + markToReformat(node, false); + markToReformatBefore(node, false); + node.putUserData(DISABLE_POSTPONED_REFORMAT_KEY, true); + } + + public static boolean isPostponedFormattingDisabled(@NotNull final ASTNode node) { + return node.getUserData(DISABLE_POSTPONED_REFORMAT_KEY) != null; + } + /** * We allow to mark particular {@link ASTNode AST nodes} to be reformatted later (e.g. we may want method definition and calls * to be reformatted when we perform 'change method signature' refactoring. Hence, we mark corresponding expressions From f29957241f08586656665524133815509402c460 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 11 May 2011 17:06:26 +0200 Subject: [PATCH 16/43] init checkbox with previous value --- .../intellij/debugger/actions/ObjectMarkupPropertiesDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java b/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java index 655960619a74..cd4aa14b7703 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/ObjectMarkupPropertiesDialog.java @@ -40,7 +40,7 @@ public class ObjectMarkupPropertiesDialog extends ValueMarkerPresentationDialogB mySuggestAdditionalMarkup = suggestAdditionalMarkup; myDescriptionLabel.setText("If the value is referenced by a constant field of an abstract class,\n" + "IDEA could additionally mark all values referenced from this class with the names of referencing fields."); - myCbMarkAdditionalFields.setSelected(suggestAdditionalMarkup && PropertiesComponent.getInstance().getBoolean(MARK_ALL_REFERENCED_VALUES_KEY, true)); + myCbMarkAdditionalFields.setSelected(PropertiesComponent.getInstance().getBoolean(MARK_ALL_REFERENCED_VALUES_KEY, true)); init(); } From 856eabebe9b5bcc5d4b341109f5fd8448bc8e36f Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Wed, 11 May 2011 19:11:38 +0400 Subject: [PATCH 17/43] IDEA-69316 Ctrl+D functionality can be improved by adding selected text after additional line feed. Human-readable name is given to the 'Duplicate Lines' action --- .../platform-resources-en/src/messages/ActionsBundle.properties | 1 + 1 file changed, 1 insertion(+) diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties index 618d12942776..f372113e7992 100644 --- a/platform/platform-resources-en/src/messages/ActionsBundle.properties +++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties @@ -120,6 +120,7 @@ action.EditorKillToWordEnd.text=Kill to Word End action.EditorKillRegion.text=Kill Selected Region action.EditorKillRingSave.text=Save to Kill Ring action.EditorDuplicate.text=Duplicate Line or Block +action.EditorDuplicateLines.text=Duplicate Lines action.EditorSelectWord.text=Select Word at Caret action.EditorUnSelectWord.text=Unselect Word at Caret action.EditorToggleInsertState.text=Toggle Insert/Overwrite From f6369d73d2429ad5c1a425763d2127ad08a81141 Mon Sep 17 00:00:00 2001 From: Alexander Kirillin Date: Wed, 11 May 2011 19:17:31 +0400 Subject: [PATCH 18/43] Temporary fix for AppCode tests --- .../intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index 43c91a765c8c..d63a5e6d5b2f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -66,7 +66,7 @@ import java.util.*; public class VirtualDirectoryImpl extends VirtualFileSystemEntry { private static final VirtualFileSystemEntry NULL_VIRTUAL_FILE = new VirtualFileImpl("*?;%NULL", null, -42); private final NewVirtualFileSystem myFS; - private static final boolean IS_UNIT_TESTS = ApplicationManager.getApplication().isUnitTestMode(); + private static final boolean IS_UNIT_TESTS = false;//ApplicationManager.getApplication().isUnitTestMode(); // guarded by this private Object myChildren; // Either HashMap or VFile[] From 173e6ca3960bd1e59e27bf8a282e866cb6dc01da Mon Sep 17 00:00:00 2001 From: Anton Makeev Date: Wed, 11 May 2011 17:23:57 +0200 Subject: [PATCH 19/43] assertion temporarily disabled --- .../intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java index d63a5e6d5b2f..f25ba1860a17 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java @@ -206,7 +206,7 @@ public class VirtualDirectoryImpl extends VirtualFileSystemEntry { if (!isUnder) { if (!allowed.isEmpty()) { - assert false : "File accessed outside project: " + child +"; project roots: "+new ArrayList(allowed); + //assert false : "File accessed outside project: " + child +"; project roots: "+new ArrayList(allowed); } } } From 93a2771903f159f452fc78e98fb87fd54f4b5f24 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 17:50:43 +0200 Subject: [PATCH 20/43] cleanup the disable-postponed-formatting status --- .../source/PostprocessReformattingAspect.java | 2 ++ .../impl/source/codeStyle/CodeEditUtil.java | 31 +++++++++---------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java index ac5709d3af2d..6a9bc57c8539 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java @@ -509,6 +509,8 @@ public class PostprocessReformattingAspect implements PomModelAspect, Disposable inGeneratedContext = oldGeneratedContext; } }); + + CodeEditUtil.enablePostponedFormattingInTree(node); } } diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java index 931f9a6d4abc..69f5f2136fd1 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeEditUtil.java @@ -29,10 +29,7 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; -import com.intellij.psi.impl.source.tree.Factory; -import com.intellij.psi.impl.source.tree.LeafElement; -import com.intellij.psi.impl.source.tree.TreeElement; -import com.intellij.psi.impl.source.tree.TreeUtil; +import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiUtilBase; @@ -331,12 +328,7 @@ public class CodeEditUtil { } public static void markToReformatBefore(final ASTNode right, boolean value) { - if (value) { - right.putCopyableUserData(REFORMAT_BEFORE_KEY, true); - } - else { - right.putCopyableUserData(REFORMAT_BEFORE_KEY, null); - } + right.putCopyableUserData(REFORMAT_BEFORE_KEY, value ? true : null); } private static int getBlankLines(final String text) { @@ -401,12 +393,7 @@ public class CodeEditUtil { public static void setNodeGenerated(final ASTNode next, final boolean value) { if (next == null) return; - if (value) { - next.putCopyableUserData(GENERATED_FLAG, true); - } - else { - next.putCopyableUserData(GENERATED_FLAG, null); - } + next.putCopyableUserData(GENERATED_FLAG, value ? true : null); } public static void setOldIndentation(final TreeElement treeElement, final int oldIndentation) { @@ -430,7 +417,7 @@ public class CodeEditUtil { * @return true if given node is configured to be reformatted; false otherwise */ public static boolean isMarkedToReformat(final ASTNode node) { - return node.getCopyableUserData(REFORMAT_KEY) != null && ALLOW_NODES_REFORMATTING.get(); + return node.getCopyableUserData(REFORMAT_KEY) != null && isSuspendedNodesReformattingAllowed(); } /** @@ -451,6 +438,16 @@ public class CodeEditUtil { node.putUserData(DISABLE_POSTPONED_REFORMAT_KEY, true); } + public static void enablePostponedFormattingInTree(@NotNull ASTNode root) { + ((TreeElement)root).acceptTree(new RecursiveTreeElementVisitor() { + protected boolean visitNode(TreeElement element) { + element.putUserData(DISABLE_POSTPONED_REFORMAT_KEY, null); + return true; + } + }); + + } + public static boolean isPostponedFormattingDisabled(@NotNull final ASTNode node) { return node.getUserData(DISABLE_POSTPONED_REFORMAT_KEY) != null; } From 88187193f50625abab2e4d38fb03a3f4a11d75e2 Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 18:31:32 +0200 Subject: [PATCH 21/43] don't search for an alias with empty name (EA-25319) --- .../groovy/findUsages/GrAliasedImportedElementSearcher.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java index 5f5e7bbeda39..1cfa50c98c8c 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GrAliasedImportedElementSearcher.java @@ -16,6 +16,7 @@ package org.jetbrains.plugins.groovy.findUsages; import com.intellij.openapi.application.QueryExecutorBase; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.search.*; import com.intellij.psi.search.searches.ReferencesSearch; @@ -42,7 +43,7 @@ public class GrAliasedImportedElementSearcher extends QueryExecutorBase Date: Wed, 11 May 2011 18:01:11 +0200 Subject: [PATCH 22/43] some more diagnostics for failing test --- .../src/com/intellij/openapi/extensions/Extensions.java | 2 +- .../intellij/xdebugger/impl/breakpoints/XBreakpointBase.java | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java index 475e4eb9a6f4..ba6e11113c73 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/Extensions.java @@ -122,7 +122,7 @@ public class Extensions { if (!ourAreaClass2Configuration.containsKey(areaClass)) { throw new IllegalArgumentException("Area class is not registered: " + areaClass); } - if (ourAreaInstance2area.containsKey(areaInstance)) { + if ((areaInstance == null && ourRootArea != null) || ourAreaInstance2area.containsKey(areaInstance)) { throw new IllegalArgumentException("Area already instantiated for: " + areaInstance); } ExtensionsArea parentArea = getArea(parentAreaInstance); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java index ef9e619d0eb3..676d44110f1b 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointBase.java @@ -270,4 +270,9 @@ public class XBreakpointBase, P extends XBreakpointP return new XBreakpointBase>(type, breakpointManager, this); } } + + @Override + public String toString() { + return "XBreakpointBase(type=" + myType + ")"; + } } From 2e8e8ee5db8ef8ebfe5560a418aa62ea52458c3e Mon Sep 17 00:00:00 2001 From: peter Date: Wed, 11 May 2011 18:52:55 +0200 Subject: [PATCH 23/43] [^yole] more diagnostics and a possible fix for EA-26353: the saved lookup element sorting weight mysteriously disappeared --- .../intellij/codeInsight/lookup/ComparingClassifier.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java index 42e363939a57..6f2a0989329a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/ComparingClassifier.java @@ -18,6 +18,8 @@ package com.intellij.codeInsight.lookup; import com.intellij.openapi.application.ApplicationManager; import com.intellij.util.SmartList; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.StripedLockConcurrentHashMap; +import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.util.*; @@ -26,7 +28,7 @@ import java.util.*; * @author peter */ public abstract class ComparingClassifier extends Classifier { - private final Map myWeights = new HashMap(); + private final Map myWeights = new StripedLockConcurrentHashMap(TObjectHashingStrategy.IDENTITY); private final Classifier myNext; private final String myName; @@ -49,7 +51,7 @@ public abstract class ComparingClassifier extends Classifier { for (T t : source) { final Comparable weight = myWeights.get(t); if (weight == null) { - throw new AssertionError(myName + "; " + myWeights.containsKey(t)); + throw new AssertionError(myName + "; " + myWeights.containsKey(t) + "; element=" + t); } List list = map.get(weight); if (list == null) { From efd3c6160a464214dff50eb7c144bd7c785feabd Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 11 May 2011 17:22:41 +0200 Subject: [PATCH 24/43] directly use API from jdk 1.6 --- .../actions/JavaMarkObjectActionHandler.java | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java index 18e54211dc45..5fe4804736bb 100644 --- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java +++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaMarkObjectActionHandler.java @@ -44,7 +44,6 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.awt.*; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.Collections; import java.util.List; import java.util.Map; @@ -205,20 +204,11 @@ public class JavaMarkObjectActionHandler extends MarkObjectActionHandler { } private static List getReferringObjects(ObjectReference value) { - // invoke the following method using Reflection in order to remain compilable on jdk 1.5 - // java.util.List referringObjects(long l); try { - final Method apiMethod = ObjectReference.class.getMethod("referringObjects", long.class); - //noinspection unchecked - return (List)apiMethod.invoke(value, AUTO_MARKUP_REFERRING_OBJECTS_LIMIT); + return value.referringObjects(AUTO_MARKUP_REFERRING_OBJECTS_LIMIT); } - catch (IllegalAccessException e) { - LOG.error(e); // should not happen - } - catch (InvocationTargetException e) { - throw new RuntimeException(e); - } - catch (NoSuchMethodException ignored) { + catch (UnsupportedOperationException e) { + LOG.info(e); } return Collections.emptyList(); } From 5a62c6f74f5b49d75799f290156a3b92885187b4 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Wed, 11 May 2011 20:30:46 +0200 Subject: [PATCH 25/43] use explicit method toExternalForm() instead of toString() invocation when externalizing TextWithImports objects --- .../debugger/engine/evaluation/TextWithImportsImpl.java | 9 ++++++--- .../com/intellij/debugger/impl/DebuggerUtilsImpl.java | 4 ++-- .../debugger/settings/CompoundRendererConfigurable.java | 2 +- .../com/intellij/debugger/ui/breakpoints/Breakpoint.java | 2 +- .../debugger/ui/breakpoints/FilteredRequestor.java | 2 +- .../debugger/engine/evaluation/TextWithImports.java | 9 ++++++++- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java index 87ee0491bfbe..f60ab7f2eaaa 100644 --- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/TextWithImportsImpl.java @@ -23,13 +23,12 @@ import com.intellij.psi.PsiExpressionCodeFragment; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; -public class TextWithImportsImpl implements TextWithImports{ +public final class TextWithImportsImpl implements TextWithImports{ private final CodeFragmentKind myKind; private String myText; private final String myImports; - public TextWithImportsImpl (PsiExpression expression) { myKind = CodeFragmentKind.EXPRESSION; final String text = expression.getText(); @@ -92,9 +91,13 @@ public class TextWithImportsImpl implements TextWithImports{ } public String toString() { + return getText(); + } + + public String toExternalForm() { return "".equals(myImports) ? myText : myText + DebuggerEditorImpl.SEPARATOR + myImports; } - + public int hashCode() { return myText.hashCode(); } diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java index a03cd3b99eac..269799d07624 100644 --- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java +++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsImpl.java @@ -66,7 +66,7 @@ public class DebuggerUtilsImpl extends DebuggerUtilsEx{ public Element writeTextWithImports(TextWithImports text) { Element element = new Element("TextWithImports"); - element.setAttribute("text", text.toString()); + element.setAttribute("text", text.toExternalForm()); element.setAttribute("type", text.getKind() == CodeFragmentKind.EXPRESSION ? "expression" : "code fragment"); return element; } @@ -85,7 +85,7 @@ public class DebuggerUtilsImpl extends DebuggerUtilsEx{ public void writeTextWithImports(Element root, String name, TextWithImports value) { LOG.assertTrue(value.getKind() == CodeFragmentKind.EXPRESSION); - JDOMExternalizerUtil.writeField(root, name, value.toString()); + JDOMExternalizerUtil.writeField(root, name, value.toExternalForm()); } public TextWithImports readTextWithImports(Element root, String name) { diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java index d28dbb4a02ec..df2b69812114 100644 --- a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java +++ b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java @@ -210,7 +210,7 @@ public class CompoundRendererConfigurable implements UnnamedConfigurable{ exprColumn.setCellRenderer(new DefaultTableCellRenderer() { public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { final TextWithImports textWithImports = (TextWithImports)value; - String text = (textWithImports != null)? textWithImports.toString() : ""; + final String text = (textWithImports != null)? textWithImports.getText() : ""; return super.getTableCellRendererComponent(table, text, isSelected, hasFocus, row, column); } }); diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java index 0dafd39824e5..0943b4f3e658 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/Breakpoint.java @@ -260,7 +260,7 @@ public abstract class Breakpoint extends FilteredRequestor implements ClassPrepa public void writeExternal(Element parentNode) throws WriteExternalException { super.writeExternal(parentNode); - JDOMExternalizerUtil.writeField(parentNode, LOG_MESSAGE_OPTION_NAME, getLogMessage().toString()); + JDOMExternalizerUtil.writeField(parentNode, LOG_MESSAGE_OPTION_NAME, getLogMessage().toExternalForm()); } public TextWithImports getLogMessage() { diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java index f402dd47ac58..ce09ba5a67a8 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/FilteredRequestor.java @@ -143,7 +143,7 @@ public abstract class FilteredRequestor implements LocatableEventRequestor, JDOM public void writeExternal(Element parentNode) throws WriteExternalException { DefaultJDOMExternalizer.writeExternal(this, parentNode); - JDOMExternalizerUtil.writeField(parentNode, CONDITION_OPTION_NAME, getCondition().toString()); + JDOMExternalizerUtil.writeField(parentNode, CONDITION_OPTION_NAME, getCondition().toExternalForm()); DebuggerUtilsEx.writeFilters(parentNode, FILTER_OPTION_NAME, myClassFilters); DebuggerUtilsEx.writeFilters(parentNode, EXCLUSION_FILTER_OPTION_NAME, myClassExclusionFilters); DebuggerUtilsEx.writeFilters(parentNode, INSTANCE_ID_OPTION_NAME, InstanceFilter.createClassFilters(myInstanceFilters)); diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java index 1f4b6883b92e..95cf9946c064 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java +++ b/java/debugger/openapi/src/com/intellij/debugger/engine/evaluation/TextWithImports.java @@ -19,8 +19,15 @@ import org.jetbrains.annotations.NotNull; public interface TextWithImports { String getText(); + void setText(String newText); - @NotNull String getImports(); + + @NotNull + String getImports(); + CodeFragmentKind getKind(); + boolean isEmpty(); + + String toExternalForm(); } From de0eaa8ad989cc343c357334cfb58a7e28ddab66 Mon Sep 17 00:00:00 2001 From: Roman Chernyatchik Date: Wed, 11 May 2011 20:58:16 +0400 Subject: [PATCH 26/43] workaround for situation when user launches inspection tool for directory based project, which hasn't been ever opened/imported with IDEA --- .../src/com/intellij/conversion/impl/ConversionContextImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java index bb02cadb6225..7a78fdc6fdc5 100644 --- a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionContextImpl.java @@ -84,7 +84,7 @@ public class ConversionContextImpl implements ConversionContext { myWorkspaceFile = new File(StringUtil.trimEnd(projectPath, ProjectFileType.DOT_DEFAULT_EXTENSION) + WorkspaceFileType.DOT_DEFAULT_EXTENSION); } - myModuleFiles = findModuleFiles(JDomConvertingUtil.loadDocument(modulesFile).getRootElement()); + myModuleFiles = modulesFile.exists() ? findModuleFiles(JDomConvertingUtil.loadDocument(modulesFile).getRootElement()) : new File[0]; } public Set getAllProjectFiles() { From 45040495e717a21949b67a03f8c90dbeff104213 Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 11 May 2011 13:11:38 +0400 Subject: [PATCH 27/43] no usages found --- .../util/xmlb/annotations/Collection.java | 20 ------------------- 1 file changed, 20 deletions(-) delete mode 100644 platform/util/src/com/intellij/util/xmlb/annotations/Collection.java diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/Collection.java b/platform/util/src/com/intellij/util/xmlb/annotations/Collection.java deleted file mode 100644 index 97888bb29ec4..000000000000 --- a/platform/util/src/com/intellij/util/xmlb/annotations/Collection.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2000-2009 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.util.xmlb.annotations; - -public @interface Collection { -} From ab3650db7a259b25bbf62afdf3c9edd95d0909af Mon Sep 17 00:00:00 2001 From: Dmitry Avdeev Date: Wed, 11 May 2011 14:42:13 +0400 Subject: [PATCH 28/43] ElementPatternBean extracted & lazy PsiReferenceProviderBean --- .../completion/WordCompletionTest.java | 2 +- .../intellij/patterns/ElementPatternBean.java | 38 +++++++++++++++ .../intellij/psi/PsiReferenceContributor.java | 3 ++ .../intellij/psi/PsiReferenceProvider.java | 2 + .../psi/PsiReferenceProviderBean.java | 47 +++++++++++-------- .../psi/PsiReferenceContributorImpl.java | 44 ----------------- .../reference/ReferenceProvidersRegistry.java | 47 +++++++++++++++++-- .../src/META-INF/LangExtensions.xml | 2 - 8 files changed, 114 insertions(+), 71 deletions(-) create mode 100644 platform/lang-api/src/com/intellij/patterns/ElementPatternBean.java rename platform/{lang-impl => lang-api}/src/com/intellij/psi/PsiReferenceProviderBean.java (59%) delete mode 100644 platform/lang-impl/src/com/intellij/psi/PsiReferenceContributorImpl.java diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/WordCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/WordCompletionTest.java index 87bbd9b94ad6..1dcef334633d 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/WordCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/WordCompletionTest.java @@ -71,7 +71,7 @@ public class WordCompletionTest extends CompletionTestCase { } }; PsiReferenceRegistrarImpl registrar = - (PsiReferenceRegistrarImpl)ReferenceProvidersRegistry.getInstance().getRegistrar(StdLanguages.JAVA); + ReferenceProvidersRegistry.getInstance().getRegistrar(StdLanguages.JAVA); try { registrar.registerReferenceProvider(PsiLiteralExpression.class, softProvider); registrar.registerReferenceProvider(PsiLiteralExpression.class, hardProvider); diff --git a/platform/lang-api/src/com/intellij/patterns/ElementPatternBean.java b/platform/lang-api/src/com/intellij/patterns/ElementPatternBean.java new file mode 100644 index 000000000000..354524c9e6fc --- /dev/null +++ b/platform/lang-api/src/com/intellij/patterns/ElementPatternBean.java @@ -0,0 +1,38 @@ +/* + * Copyright 2000-2011 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.patterns; + +import com.intellij.patterns.compiler.PatternCompilerFactory; +import com.intellij.psi.PsiElement; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; +import com.intellij.util.xmlb.annotations.Text; +import org.jetbrains.annotations.Nullable; + +@Tag("pattern") +public class ElementPatternBean { + + @Attribute("type") + public String type; + + @Text + public String text; + + @Nullable + public ElementPattern compilePattern() { + return PatternCompilerFactory.getFactory().getPatternCompiler(type).compileElementPattern(text); + } +} diff --git a/platform/lang-api/src/com/intellij/psi/PsiReferenceContributor.java b/platform/lang-api/src/com/intellij/psi/PsiReferenceContributor.java index 04d5e2f79646..55f4f0d1d8aa 100644 --- a/platform/lang-api/src/com/intellij/psi/PsiReferenceContributor.java +++ b/platform/lang-api/src/com/intellij/psi/PsiReferenceContributor.java @@ -15,7 +15,10 @@ import com.intellij.openapi.extensions.ExtensionPointName; * Some elements return them from {@link PsiElement#getReferences()} directly though, but one should not rely on that * behavior since it may be changed in the future. * + * The alternative way to register {@link PsiReferenceProvider} is by using {@link PsiReferenceProviderBean}. + * * @author peter + * @see PsiReferenceProviderBean */ public abstract class PsiReferenceContributor implements Disposable { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.psi.referenceContributor"); diff --git a/platform/lang-api/src/com/intellij/psi/PsiReferenceProvider.java b/platform/lang-api/src/com/intellij/psi/PsiReferenceProvider.java index e6dcea63dc81..799428dbd824 100644 --- a/platform/lang-api/src/com/intellij/psi/PsiReferenceProvider.java +++ b/platform/lang-api/src/com/intellij/psi/PsiReferenceProvider.java @@ -20,6 +20,8 @@ import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NotNull; /** + * Register it via {@link PsiReferenceContributor} or {@link PsiReferenceProviderBean#EP_NAME} + * * @author ik */ public abstract class PsiReferenceProvider { diff --git a/platform/lang-impl/src/com/intellij/psi/PsiReferenceProviderBean.java b/platform/lang-api/src/com/intellij/psi/PsiReferenceProviderBean.java similarity index 59% rename from platform/lang-impl/src/com/intellij/psi/PsiReferenceProviderBean.java rename to platform/lang-api/src/com/intellij/psi/PsiReferenceProviderBean.java index ec4b893043c5..643ff81c622d 100644 --- a/platform/lang-impl/src/com/intellij/psi/PsiReferenceProviderBean.java +++ b/platform/lang-api/src/com/intellij/psi/PsiReferenceProviderBean.java @@ -19,27 +19,41 @@ package com.intellij.psi; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.extensions.AbstractExtensionPointBean; +import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.patterns.ElementPattern; +import com.intellij.patterns.ElementPatternBean; import com.intellij.patterns.StandardPatterns; -import com.intellij.patterns.compiler.PatternCompilerFactory; -import com.intellij.util.xmlb.annotations.*; +import com.intellij.util.NullableFunction; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.xmlb.annotations.AbstractCollection; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Property; +import com.intellij.util.xmlb.annotations.Tag; import org.jetbrains.annotations.Nullable; +/** + * Registers a {@link PsiReferenceProvider} in plugin.xml + */ public class PsiReferenceProviderBean extends AbstractExtensionPointBean { - private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiReferenceProviderBean"); + + public static final ExtensionPointName EP_NAME = + new ExtensionPointName("com.intellij.psi.referenceProvider"); @Attribute("providerClass") public String className; + @Tag("description") public String description; @Property(surroundWithTag = false) @AbstractCollection(surroundWithTag = false) - public Info[] patterns; + public ElementPatternBean[] patterns; public String getDescription() { return description; } + private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiReferenceProviderBean"); + public PsiReferenceProvider instantiate() { try { return (PsiReferenceProvider)instantiate(className, ApplicationManager.getApplication().getPicoContainer()); @@ -50,30 +64,25 @@ public class PsiReferenceProviderBean extends AbstractExtensionPointBean { return null; } + private static final NullableFunction> PATTERN_NULLABLE_FUNCTION = new NullableFunction>() { + @Override + public ElementPattern fun(ElementPatternBean elementPatternBean) { + return elementPatternBean.compilePattern(); + } + }; + @Nullable public ElementPattern createElementPattern() { - final PatternCompilerFactory factory = PatternCompilerFactory.getFactory(); if (patterns.length > 1) { - final ElementPattern[] result = new ElementPattern[this.patterns.length]; - for (int i = 0, len = this.patterns.length; i < len; i++) { - result[i] = factory.getPatternCompiler(patterns[i].type).compileElementPattern(patterns[i].text); - } - return StandardPatterns.or(result); + return StandardPatterns.or(ContainerUtil.mapNotNull(patterns, + PATTERN_NULLABLE_FUNCTION).toArray(new ElementPattern[0])); } else if (patterns.length == 1) { - return factory.getPatternCompiler(patterns[0].type).compileElementPattern(patterns[0].text); + return patterns[0].compilePattern(); } else { LOG.error("At least one pattern should be specified"); return null; } } - - @Tag("pattern") - public static class Info { - @Attribute("type") - public String type; - @Text - public String text; - } } diff --git a/platform/lang-impl/src/com/intellij/psi/PsiReferenceContributorImpl.java b/platform/lang-impl/src/com/intellij/psi/PsiReferenceContributorImpl.java deleted file mode 100644 index c937b32861c9..000000000000 --- a/platform/lang-impl/src/com/intellij/psi/PsiReferenceContributorImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2000-2010 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; - -import com.intellij.openapi.extensions.ExtensionPointName; -import com.intellij.patterns.ElementPattern; - -/** - * @author Gregory.Shrago - */ -public class PsiReferenceContributorImpl extends PsiReferenceContributor { - - public static final ExtensionPointName PSI_REFERENCE_PROVIDERS_EP = - new ExtensionPointName("com.intellij.psi.referenceProvider"); - @Override - public void registerReferenceProviders(PsiReferenceRegistrar registrar) { - for (PsiReferenceProviderBean providerBean : PSI_REFERENCE_PROVIDERS_EP.getExtensions()) { - registerReferenceProvider(registrar, providerBean); - } - } - - private static void registerReferenceProvider(PsiReferenceRegistrar registrar, PsiReferenceProviderBean providerBean) { - final ElementPattern pattern = providerBean.createElementPattern(); - if (pattern != null) { - final PsiReferenceProvider provider = providerBean.instantiate(); - if (provider != null) { - registrar.registerReferenceProvider(pattern, provider); - } - } - } -} diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistry.java b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistry.java index 868ab97bc056..b89a486980e7 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistry.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/resolve/reference/ReferenceProvidersRegistry.java @@ -22,6 +22,7 @@ import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.IndexNotReadyException; import com.intellij.openapi.util.Trinity; +import com.intellij.patterns.ElementPattern; import com.intellij.psi.*; import com.intellij.util.ProcessingContext; import com.intellij.util.SmartList; @@ -52,9 +53,16 @@ public class ReferenceProvidersRegistry { return o2.getThird().compareTo(o1.getThird()); } }; + public final static PsiReferenceProvider NULL_REFERENCE_PROVIDER = new PsiReferenceProvider() { + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + return PsiReference.EMPTY_ARRAY; + } + }; @SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"}) - private final static Map ourRegistrars = new FactoryMap() { + private final Map myRegistrars = new FactoryMap() { @Override protected PsiReferenceRegistrarImpl create(Language language) { PsiReferenceRegistrarImpl registrar = new PsiReferenceRegistrarImpl(); @@ -70,8 +78,36 @@ public class ReferenceProvidersRegistry { return ServiceManager.getService(ReferenceProvidersRegistry.class); } - public PsiReferenceRegistrar getRegistrar(Language language) { - return ourRegistrars.get(language); + public ReferenceProvidersRegistry() { + + PsiReferenceRegistrarImpl registrar = getRegistrar(Language.ANY); + for (final PsiReferenceProviderBean providerBean : PsiReferenceProviderBean.EP_NAME.getExtensions()) { + final ElementPattern pattern = providerBean.createElementPattern(); + if (pattern != null) { + registrar.registerReferenceProvider(pattern, new PsiReferenceProvider() { + + PsiReferenceProvider myProvider; + + @NotNull + @Override + public PsiReference[] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) { + if (myProvider == null) { + + myProvider = providerBean.instantiate(); + if (myProvider == null) { + myProvider = NULL_REFERENCE_PROVIDER; + } + } + return myProvider.getReferencesByElement(element, context); + } + }); + } + } + + } + + public PsiReferenceRegistrarImpl getRegistrar(Language language) { + return myRegistrars.get(language); } @Deprecated @@ -83,10 +119,11 @@ public class ReferenceProvidersRegistry { ProgressManager.checkCanceled(); assert context.isValid() : "Invalid context: " + context; - PsiReferenceRegistrarImpl registrar = ourRegistrars.get(context.getLanguage()); + ReferenceProvidersRegistry registry = getInstance(); + PsiReferenceRegistrarImpl registrar = registry.getRegistrar(context.getLanguage()); SmartList> providers = new SmartList>(); providers.addAll(registrar.getPairsByElement(context, hints)); - providers.addAll(ourRegistrars.get(Language.ANY).getPairsByElement(context, hints)); + providers.addAll(registry.getRegistrar(Language.ANY).getPairsByElement(context, hints)); if (providers.isEmpty()) { return PsiReference.EMPTY_ARRAY; } diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index ac366c2adff5..6a88f3bb4493 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -397,8 +397,6 @@ - - From 32c06226560b18fa6cee9b4b1172bf8f078f8218 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 12 May 2011 10:59:12 +0400 Subject: [PATCH 29/43] fix UI problems when switching LaFs --- .../NavBarRootPaneExtension.java | 83 +++++++++++-------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java index 0fe084574760..4b3b06b72ee2 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarRootPaneExtension.java @@ -25,6 +25,7 @@ import com.intellij.ide.ui.UISettingsListener; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.ex.ComboBoxAction; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.IconLoader; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.wm.IdeRootPaneNorthExtension; @@ -48,6 +49,8 @@ public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension { private NavBarPanel myNavigationBar; private JPanel myRunPanel; private boolean myNavToolbarGroupExist; + private JScrollPane myScrollPane; + private JLabel myCloseIcon; public NavBarRootPaneExtension(Project project) { myProject = project; @@ -122,7 +125,6 @@ public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension { } }; myWrapperPanel.add(buildNavBarPanel(), BorderLayout.CENTER); - myWrapperPanel.putClientProperty("NavBarPanel", myNavigationBar); toggleRunPanel(!UISettings.getInstance().SHOW_MAIN_TOOLBAR); } @@ -185,6 +187,49 @@ public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension { private JComponent buildNavBarPanel() { final JComponent result = new JPanel(new BorderLayout()) { + @Override + public void updateUI() { + super.updateUI(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + removeAll(); + myScrollPane = null; + myCloseIcon = null; + if (myNavigationBar != null && !Disposer.isDisposed(myNavigationBar)) { + Disposer.dispose(myNavigationBar); + } + myNavigationBar = new NavBarPanel(myProject); + myWrapperPanel.putClientProperty("NavBarPanel", myNavigationBar); + myNavigationBar.getModel().setFixedComponent(true); + + myScrollPane = ScrollPaneFactory.createScrollPane(myNavigationBar); + myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); + myScrollPane.setHorizontalScrollBar(null); + myScrollPane.setBorder(null); + + myScrollPane.setOpaque(false); + myScrollPane.getViewport().setOpaque(false); + + setBackground(UIUtil.isUnderGTKLookAndFeel() ? Color.WHITE : UIUtil.getListBackground()); + setOpaque(!UIUtil.isUnderAquaLookAndFeel() || UISettings.getInstance().SHOW_MAIN_TOOLBAR); + setBorder(UIUtil.isUnderAquaLookAndFeel() ? BorderFactory.createEmptyBorder(2, 0, 2, 4) : new NavBarBorder(true, 0)); + myNavigationBar.setBorder(null); + add(myScrollPane, BorderLayout.CENTER); + if (!SystemInfo.isMac) { + myCloseIcon = new JLabel(CROSS_ICON); + myCloseIcon.addMouseListener(new MouseAdapter() { + public void mouseClicked(final MouseEvent e) { + UISettings.getInstance().SHOW_NAVIGATION_BAR = false; + uiSettingsChanged(UISettings.getInstance()); + } + }); + add(myCloseIcon, BorderLayout.EAST); + } + } + }); + } + @Override protected void paintComponent(Graphics g) { if (UIUtil.isUnderAquaLookAndFeel()) { @@ -231,9 +276,9 @@ public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension { final Rectangle r = getBounds(); final Insets insets = getInsets(); int x = insets.left; - - final Component navBar = getComponent(0); - final Component closeLabel = getComponentCount() == 2 ? getComponent(1) : null; + if (myScrollPane == null) return; + final Component navBar = myScrollPane; + final Component closeLabel = myCloseIcon; final Dimension preferredSize = navBar.getPreferredSize(); final Dimension closePreferredSize = closeLabel == null ? new Dimension() : closeLabel.getPreferredSize(); @@ -248,37 +293,7 @@ public class NavBarRootPaneExtension extends IdeRootPaneNorthExtension { } } }; - - result.setBackground(UIUtil.isUnderGTKLookAndFeel() ? Color.WHITE : UIUtil.getListBackground()); - result.setOpaque(!UIUtil.isUnderAquaLookAndFeel() || UISettings.getInstance().SHOW_MAIN_TOOLBAR); - - myNavigationBar = new NavBarPanel(myProject); - myNavigationBar.getModel().setFixedComponent(true); - - JScrollPane scroller = ScrollPaneFactory.createScrollPane(myNavigationBar); - scroller.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER); - scroller.setHorizontalScrollBar(null); - scroller.setBorder(null); - scroller.setOpaque(false); - scroller.getViewport().setOpaque(false); - - result.add(scroller, BorderLayout.CENTER); - - if (!SystemInfo.isMac) { - JLabel closeLabel = new JLabel(CROSS_ICON); - closeLabel.addMouseListener(new MouseAdapter() { - public void mouseClicked(final MouseEvent e) { - UISettings.getInstance().SHOW_NAVIGATION_BAR = false; - uiSettingsChanged(UISettings.getInstance()); - } - }); - result.add(closeLabel, BorderLayout.EAST); - } - - result.setBorder(UIUtil.isUnderAquaLookAndFeel() ? BorderFactory.createEmptyBorder(2, 0, 2, 4) : new NavBarBorder(true, 0)); - myNavigationBar.setBorder(null); - return result; } From 747646b98e1648d376fc4299b6c040f8abf79d25 Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 12 May 2011 11:15:20 +0400 Subject: [PATCH 30/43] fix plugin downloader --- .../openapi/updateSettings/impl/PluginDownloader.java | 2 +- .../util/src/com/intellij/openapi/util/io/FileUtil.java | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java index d8ee30ef372b..a09ec5334bda 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginDownloader.java @@ -208,7 +208,7 @@ public class PluginDownloader { pluginsTemp.mkdirs(); } - File file = FileUtil.createTempFile(pluginsTemp, "plugin", "download", true); + File file = FileUtil.createTempFile(pluginsTemp, "plugin", "download", true, false); int responseCode = connection.getResponseCode(); switch (responseCode) { diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java index 6ea6291bff64..3690ce20398f 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java @@ -354,12 +354,18 @@ public class FileUtil { @NotNull public static File createTempFile(@NonNls final File dir, @NotNull @NonNls String prefix, @NonNls String suffix, final boolean create) throws IOException{ + return createTempFile(dir, prefix, suffix, create, true); + } + + public static File createTempFile(@NonNls final File dir, @NotNull @NonNls String prefix, @NonNls String suffix, final boolean create, boolean removeOnExit) throws IOException { File file = doCreateTempFile(prefix, suffix, dir); file.delete(); if (create) { file.createNewFile(); } - file.deleteOnExit(); + if (removeOnExit) { + file.deleteOnExit(); + } return file; } From c89bda4d6bafbb6722aab907f9065d96dfb1165b Mon Sep 17 00:00:00 2001 From: Konstantin Bulenkov Date: Thu, 12 May 2011 11:37:10 +0400 Subject: [PATCH 31/43] show project on empty frame --- .../src/com/intellij/ide/navigationToolbar/NavBarModel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java index 6aeef1d6dfd9..d7b23d3be7d7 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarModel.java @@ -107,7 +107,7 @@ public class NavBarModel { updateModel(psiElement); } else { - if (UISettings.getInstance().SHOW_NAVIGATION_BAR) return; + if (UISettings.getInstance().SHOW_NAVIGATION_BAR && !myModel.isEmpty()) return; Object moduleOrProject = LangDataKeys.MODULE.getData(dataContext); if (moduleOrProject == null) { From 1aa7241d17ccf2a54d8cca05e79164bb559e0bfe Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 13:06:21 +0400 Subject: [PATCH 32/43] Git: moved stash/shelve classes to git4idea.stash --- .../src/git4idea/checkin/GitPushActiveBranchesDialog.java | 3 +++ .../src/git4idea/checkout/branches/GitCheckoutProcess.java | 2 +- .../src/git4idea/{update => stash}/GitChangesSaver.java | 2 +- .../src/git4idea/{update => stash}/GitShelveChangesSaver.java | 2 +- .../src/git4idea/{update => stash}/GitStashChangesSaver.java | 2 +- .../git4idea/src/git4idea/{update => stash}/GitStashUtils.java | 2 +- plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java | 2 +- plugins/git4idea/src/git4idea/update/GitUpdateProcess.java | 1 + 8 files changed, 10 insertions(+), 6 deletions(-) rename plugins/git4idea/src/git4idea/{update => stash}/GitChangesSaver.java (99%) rename plugins/git4idea/src/git4idea/{update => stash}/GitShelveChangesSaver.java (99%) rename plugins/git4idea/src/git4idea/{update => stash}/GitStashChangesSaver.java (99%) rename plugins/git4idea/src/git4idea/{update => stash}/GitStashUtils.java (99%) diff --git a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java index f6939e289a44..58260620f5f4 100644 --- a/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java +++ b/plugins/git4idea/src/git4idea/checkin/GitPushActiveBranchesDialog.java @@ -51,6 +51,9 @@ import git4idea.commands.*; import git4idea.config.GitVcsSettings; import git4idea.i18n.GitBundle; import git4idea.rebase.GitRebaser; +import git4idea.stash.GitChangesSaver; +import git4idea.stash.GitShelveChangesSaver; +import git4idea.stash.GitStashChangesSaver; import git4idea.ui.GitUIUtil; import git4idea.update.*; import org.jetbrains.annotations.NotNull; diff --git a/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java b/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java index f0616594052a..b228b195f177 100644 --- a/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java +++ b/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java @@ -44,8 +44,8 @@ import git4idea.checkout.branches.GitBranchConfigurations.BranchChanges; import git4idea.checkout.branches.GitBranchConfigurations.ChangeInfo; import git4idea.checkout.branches.GitBranchConfigurations.ChangeListInfo; import git4idea.commands.*; +import git4idea.stash.GitStashUtils; import git4idea.ui.GitUIUtil; -import git4idea.update.GitStashUtils; import org.jetbrains.annotations.Nullable; import java.io.File; diff --git a/plugins/git4idea/src/git4idea/update/GitChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitChangesSaver.java similarity index 99% rename from plugins/git4idea/src/git4idea/update/GitChangesSaver.java rename to plugins/git4idea/src/git4idea/stash/GitChangesSaver.java index cd275d55b89a..69cbdf1c7fb0 100644 --- a/plugins/git4idea/src/git4idea/update/GitChangesSaver.java +++ b/plugins/git4idea/src/git4idea/stash/GitChangesSaver.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.update; +package git4idea.stash; import com.intellij.notification.Notification; import com.intellij.notification.NotificationListener; diff --git a/plugins/git4idea/src/git4idea/update/GitShelveChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java similarity index 99% rename from plugins/git4idea/src/git4idea/update/GitShelveChangesSaver.java rename to plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java index 57000d3eebad..2e37e16df698 100644 --- a/plugins/git4idea/src/git4idea/update/GitShelveChangesSaver.java +++ b/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.update; +package git4idea.stash; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; diff --git a/plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java similarity index 99% rename from plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java rename to plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java index e9b323e94d77..ca8f4120ed40 100644 --- a/plugins/git4idea/src/git4idea/update/GitStashChangesSaver.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.update; +package git4idea.stash; import com.intellij.notification.Notification; import com.intellij.notification.NotificationListener; diff --git a/plugins/git4idea/src/git4idea/update/GitStashUtils.java b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java similarity index 99% rename from plugins/git4idea/src/git4idea/update/GitStashUtils.java rename to plugins/git4idea/src/git4idea/stash/GitStashUtils.java index 2c42bf58ff1c..3bfc731c3109 100644 --- a/plugins/git4idea/src/git4idea/update/GitStashUtils.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package git4idea.update; +package git4idea.stash; import com.intellij.openapi.application.ModalityState; import com.intellij.openapi.diagnostic.Logger; diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java index 36865fd50fdb..820749a286c6 100644 --- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java +++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java @@ -33,7 +33,7 @@ import git4idea.actions.GitShowAllSubmittedFilesAction; import git4idea.commands.*; import git4idea.config.GitVersionSpecialty; import git4idea.i18n.GitBundle; -import git4idea.update.GitStashUtils; +import git4idea.stash.GitStashUtils; import git4idea.validators.GitBranchNameValidator; import org.jetbrains.annotations.NotNull; diff --git a/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java b/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java index 1b5a53be66b2..ab4dba37129d 100644 --- a/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java +++ b/plugins/git4idea/src/git4idea/update/GitUpdateProcess.java @@ -35,6 +35,7 @@ import git4idea.merge.GitMergeConflictResolver; import git4idea.merge.GitMergeUtil; import git4idea.merge.GitMerger; import git4idea.rebase.GitRebaser; +import git4idea.stash.GitChangesSaver; import git4idea.ui.GitUIUtil; import org.jetbrains.annotations.NotNull; From 36f3599debd08550da4d4afcce7631a99a41994d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 13:18:44 +0400 Subject: [PATCH 33/43] Git: move shelving from GitStashUtils to GitShelveUtils --- .../checkout/branches/GitCheckoutProcess.java | 97 ++++----- .../git4idea/stash/GitShelveChangesSaver.java | 4 +- .../src/git4idea/stash/GitShelveUtils.java | 192 ++++++++++++++++++ .../src/git4idea/stash/GitStashUtils.java | 164 --------------- 4 files changed, 243 insertions(+), 214 deletions(-) create mode 100644 plugins/git4idea/src/git4idea/stash/GitShelveUtils.java diff --git a/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java b/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java index b228b195f177..c44a1deeafbb 100644 --- a/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java +++ b/plugins/git4idea/src/git4idea/checkout/branches/GitCheckoutProcess.java @@ -44,7 +44,7 @@ import git4idea.checkout.branches.GitBranchConfigurations.BranchChanges; import git4idea.checkout.branches.GitBranchConfigurations.ChangeInfo; import git4idea.checkout.branches.GitBranchConfigurations.ChangeListInfo; import git4idea.commands.*; -import git4idea.stash.GitStashUtils; +import git4idea.stash.GitShelveUtils; import git4idea.ui.GitUIUtil; import org.jetbrains.annotations.Nullable; @@ -591,52 +591,53 @@ public class GitCheckoutProcess { }; continuation.addExceptionHandler(VcsException.class, exceptionConsumer); final GatheringContinuationContext initContext = new GatheringContinuationContext(); - GitStashUtils.doSystemUnshelve(myProject, shelve, myShelveManager, new Runnable() { - @Override - public void run() { - final HashMap, String> parsedChanges = new HashMap, String>(); - for (ChangeInfo changeInfo : changes.CHANGES) { - String before = changeInfo.BEFORE_PATH; - String after = changeInfo.AFTER_PATH; - parsedChanges.put(Pair.create(before, after), changeInfo.CHANGE_LIST_NAME); - } - try { - HashMap lists = new HashMap(); - final List existedChangeLists = myChangeManager.getChangeLists(); - for (LocalChangeList localChangeList : existedChangeLists) { - lists.put(localChangeList.getName(), localChangeList); - } - LocalChangeList defaultList = myChangeManager.getDefaultChangeList(); - for (ChangeListInfo changeListInfo : changes.CHANGE_LISTS) { - LocalChangeList changeList = lists.get(changeListInfo.NAME); - if (changeList == null) { - changeList = myChangeManager.addChangeList(changeListInfo.NAME, changeListInfo.COMMENT); - lists.put(changeListInfo.NAME, changeList); - } - if (changeListInfo.IS_DEFAULT) { - myChangeManager.setDefaultChangeList(changeList); - } - } - for (Change change : defaultList.getChanges()) { - ContentRevision beforeRevision = change.getBeforeRevision(); - String before = beforeRevision == null ? null : beforeRevision.getFile().getPath(); - ContentRevision afterRevision = change.getAfterRevision(); - String after = afterRevision == null ? null : afterRevision.getFile().getPath(); - Pair key = Pair.create(before, after); - String listName = parsedChanges.get(key); - assert listName != null : "List name should be found: " + key; - if (!listName.equals(defaultList.getName())) { - LocalChangeList changeList = lists.get(listName); - assert changeList != null : "Change List should be found: " + listName; - myChangeManager.moveChangesTo(changeList, new Change[]{change}); - } - } - } - catch (Throwable t) { - exceptionConsumer.consume(new VcsException(t)); - } - } - }, initContext); + GitShelveUtils.doSystemUnshelve(myProject, shelve, myShelveManager, new Runnable() { + @Override + public void run() { + final HashMap, String> parsedChanges = + new HashMap, String>(); + for (ChangeInfo changeInfo : changes.CHANGES) { + String before = changeInfo.BEFORE_PATH; + String after = changeInfo.AFTER_PATH; + parsedChanges.put(Pair.create(before, after), changeInfo.CHANGE_LIST_NAME); + } + try { + HashMap lists = new HashMap(); + final List existedChangeLists = myChangeManager.getChangeLists(); + for (LocalChangeList localChangeList : existedChangeLists) { + lists.put(localChangeList.getName(), localChangeList); + } + LocalChangeList defaultList = myChangeManager.getDefaultChangeList(); + for (ChangeListInfo changeListInfo : changes.CHANGE_LISTS) { + LocalChangeList changeList = lists.get(changeListInfo.NAME); + if (changeList == null) { + changeList = myChangeManager.addChangeList(changeListInfo.NAME, changeListInfo.COMMENT); + lists.put(changeListInfo.NAME, changeList); + } + if (changeListInfo.IS_DEFAULT) { + myChangeManager.setDefaultChangeList(changeList); + } + } + for (Change change : defaultList.getChanges()) { + ContentRevision beforeRevision = change.getBeforeRevision(); + String before = beforeRevision == null ? null : beforeRevision.getFile().getPath(); + ContentRevision afterRevision = change.getAfterRevision(); + String after = afterRevision == null ? null : afterRevision.getFile().getPath(); + Pair key = Pair.create(before, after); + String listName = parsedChanges.get(key); + assert listName != null : "List name should be found: " + key; + if (!listName.equals(defaultList.getName())) { + LocalChangeList changeList = lists.get(listName); + assert changeList != null : "Change List should be found: " + listName; + myChangeManager.moveChangesTo(changeList, new Change[]{change}); + } + } + } + catch (Throwable t) { + exceptionConsumer.consume(new VcsException(t)); + } + } + }, initContext); continuation.run(initContext.getList()); } @@ -742,7 +743,7 @@ public class GitCheckoutProcess { if (progress != null) { progress.setText("Creating shelve: " + description); } - ShelvedChangeList shelved = GitStashUtils.shelveChanges(myProject, myShelveManager, toShelve, description, myExceptions); + ShelvedChangeList shelved = GitShelveUtils.shelveChanges(myProject, myShelveManager, toShelve, description, myExceptions); if (shelved == null) { return null; } diff --git a/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java index 2e37e16df698..0dd56f9d70ab 100644 --- a/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java +++ b/plugins/git4idea/src/git4idea/stash/GitShelveChangesSaver.java @@ -62,7 +62,7 @@ public class GitShelveChangesSaver extends GitChangesSaver { String oldProgressTitle = myProgressIndicator.getText(); myProgressIndicator.setText(GitBundle.getString("update.shelving.changes")); List exceptions = new ArrayList(1); - myShelvedChangeList = GitStashUtils.shelveChanges(myProject, myShelveManager, changes, myStashMessage, exceptions); + myShelvedChangeList = GitShelveUtils.shelveChanges(myProject, myShelveManager, changes, myStashMessage, exceptions); myProgressIndicator.setText(oldProgressTitle); if (!exceptions.isEmpty()) { LOG.info("save " + exceptions, exceptions.get(0)); @@ -77,7 +77,7 @@ public class GitShelveChangesSaver extends GitChangesSaver { String oldProgressTitle = myProgressIndicator.getText(); myProgressIndicator.setText(GitBundle.getString("update.unshelving.changes")); if (myShelvedChangeList != null) { - GitStashUtils.doSystemUnshelve(myProject, myShelvedChangeList, myShelveManager, restoreListsRunnable, context); + GitShelveUtils.doSystemUnshelve(myProject, myShelvedChangeList, myShelveManager, restoreListsRunnable, context); } myProgressIndicator.setText(oldProgressTitle); } diff --git a/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java b/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java new file mode 100644 index 000000000000..6a9f76655236 --- /dev/null +++ b/plugins/git4idea/src/git4idea/stash/GitShelveUtils.java @@ -0,0 +1,192 @@ +/* + * Copyright 2000-2011 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 git4idea.stash; + +import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.progress.AsynchronousExecution; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vcs.AbstractVcsHelper; +import com.intellij.openapi.vcs.FilePath; +import com.intellij.openapi.vcs.FileStatus; +import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.changes.Change; +import com.intellij.openapi.vcs.changes.ChangeListManager; +import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode; +import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; +import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; +import com.intellij.openapi.vcs.changes.shelf.ShelvedBinaryFile; +import com.intellij.openapi.vcs.changes.shelf.ShelvedChange; +import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.continuation.ContinuationContext; +import com.intellij.util.continuation.TaskDescriptor; +import com.intellij.util.continuation.Where; +import com.intellij.vcsUtil.VcsUtil; +import git4idea.GitUtil; +import git4idea.GitVcs; +import git4idea.commands.GitFileUtils; +import git4idea.vfs.GitVFSListener; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.event.ChangeEvent; +import java.io.File; +import java.io.IOException; +import java.util.*; + +/** + * @author Kirill Likhodedov + */ +public class GitShelveUtils { + private static final Logger LOG = Logger.getInstance(GitShelveUtils.class.getName()); + + /** + * Perform system level unshelve operation + * + * @param project the project + * @param shelvedChangeList the shelved change list + * @param shelveManager the shelve manager + * @param restoreListsRunnable + */ + @AsynchronousExecution + public static void doSystemUnshelve(final Project project, + final ShelvedChangeList shelvedChangeList, + final ShelveChangesManager shelveManager, + @NotNull final Runnable restoreListsRunnable, + final @NotNull ContinuationContext context) { + VirtualFile baseDir = project.getBaseDir(); + assert baseDir != null; + final String projectPath = baseDir.getPath() + "/"; + + context.next(new TaskDescriptor("Refreshing files before unshelve", Where.POOLED) { + @Override + public void run(ContinuationContext context) { + LOG.info("doSystemUnshelve "); + // The changes are temporary copied to the first local change list, the next operation will restore them back + // Refresh files that might be affected by unshelve + refreshFilesBeforeUnshelve(shelvedChangeList, projectPath); + + LOG.info("doSystemUnshelve files refreshed. unshelving in AWT thread."); + } + }, new TaskDescriptor("", Where.AWT) { + @Override + public void run(ContinuationContext context) { + GitVFSListener l = GitVcs.getInstance(project).getVFSListener(); + l.setEventsSuppressed(true); + + LOG.info("Unshelving in UI thread. shelvedChangeList: " + shelvedChangeList); + // we pass null as target change list for Patch Applier to do NOTHING with change lists + shelveManager.scheduleUnshelveChangeList(shelvedChangeList, shelvedChangeList.getChanges(), + shelvedChangeList.getBinaryFiles(), null, false, context); + } + }, new TaskDescriptor("", Where.AWT) { + @Override + public void run(ContinuationContext context) { + GitVcs.getInstance(project).getVFSListener().setEventsSuppressed(false); + addFilesAfterUnshelve(project, shelvedChangeList, projectPath, context); + ChangeListManager.getInstance(project).invokeAfterUpdate(new Runnable() { + @Override + public void run() { + restoreListsRunnable.run(); + } + }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, "Restoring changelists", ModalityState.NON_MODAL); + } + }); + } + + public static void addFilesAfterUnshelve(Project project, + ShelvedChangeList shelvedChangeList, + String projectPath, ContinuationContext context) { + Collection paths = new ArrayList(); + for (ShelvedChange c : shelvedChangeList.getChanges()) { + if (c.getBeforePath() == null || !c.getBeforePath().equals(c.getAfterPath()) || c.getFileStatus() == FileStatus.ADDED) { + paths.add(VcsUtil.getFilePath(projectPath + c.getAfterPath())); + } + } + for (ShelvedBinaryFile f : shelvedChangeList.getBinaryFiles()) { + if (f.BEFORE_PATH == null || !f.BEFORE_PATH.equals(f.AFTER_PATH) || f.getFileStatus() == FileStatus.ADDED) { + paths.add(VcsUtil.getFilePath(projectPath + f.AFTER_PATH)); + } + } + final VcsDirtyScopeManager dsm = VcsDirtyScopeManager.getInstance(project); + Map> map = GitUtil.sortGitFilePathsByGitRoot(paths); + for (Map.Entry> e : map.entrySet()) { + try { + GitFileUtils.addPaths(project, e.getKey(), e.getValue()); + dsm.filePathsDirty(e.getValue(), null); + } + catch (VcsException e1) { + if (! context.handleException(e1)) { + AbstractVcsHelper.getInstance(project).showError(e1, "Can not add file to Git"); + LOG.error("Vcs Exception not handled"); + } + } + } + } + + public static void refreshFilesBeforeUnshelve(ShelvedChangeList shelvedChangeList, String projectPath) { + HashSet filesToRefresh = new HashSet(); + for (ShelvedChange c : shelvedChangeList.getChanges()) { + if (c.getBeforePath() != null) { + filesToRefresh.add(new File(projectPath + c.getBeforePath())); + } + if (c.getAfterPath() != null) { + filesToRefresh.add(new File(projectPath + c.getAfterPath())); + } + } + for (ShelvedBinaryFile f : shelvedChangeList.getBinaryFiles()) { + if (f.BEFORE_PATH != null) { + filesToRefresh.add(new File(projectPath + f.BEFORE_PATH)); + } + if (f.AFTER_PATH != null) { + filesToRefresh.add(new File(projectPath + f.BEFORE_PATH)); + } + } + LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh); + } + + /** + * Shelve changes + * + * @param project the context project + * @param shelveManager the shelve manager + * @param changes the changes to process + * @param description the description of for the shelve + * @param exceptions the generated exceptions + * @return created shelved change list or null in case failure + */ + @Nullable + public static ShelvedChangeList shelveChanges(final Project project, final ShelveChangesManager shelveManager, Collection changes, + final String description, + final List exceptions) { + try { + ShelvedChangeList shelve = shelveManager.shelveChanges(changes, description); + project.getMessageBus().syncPublisher(ShelveChangesManager.SHELF_TOPIC).stateChanged(new ChangeEvent(GitStashUtils.class)); + return shelve; + } + catch (IOException e) { + //noinspection ThrowableInstanceNeverThrown + exceptions.add(new VcsException("Shelving changes failed: " + description, e)); + return null; + } + catch (VcsException e) { + exceptions.add(e); + return null; + } + } +} diff --git a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java index 3bfc731c3109..89b3b8ca704c 100644 --- a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java @@ -15,48 +15,20 @@ */ package git4idea.stash; -import com.intellij.openapi.application.ModalityState; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.progress.AsynchronousExecution; import com.intellij.openapi.project.Project; -import com.intellij.openapi.vcs.AbstractVcsHelper; -import com.intellij.openapi.vcs.FilePath; -import com.intellij.openapi.vcs.FileStatus; import com.intellij.openapi.vcs.VcsException; -import com.intellij.openapi.vcs.changes.Change; -import com.intellij.openapi.vcs.changes.ChangeListManager; -import com.intellij.openapi.vcs.changes.InvokeAfterUpdateMode; -import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vcs.changes.shelf.ShelveChangesManager; -import com.intellij.openapi.vcs.changes.shelf.ShelvedBinaryFile; -import com.intellij.openapi.vcs.changes.shelf.ShelvedChange; -import com.intellij.openapi.vcs.changes.shelf.ShelvedChangeList; -import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; -import com.intellij.util.continuation.ContinuationContext; -import com.intellij.util.continuation.TaskDescriptor; -import com.intellij.util.continuation.Where; -import com.intellij.vcsUtil.VcsUtil; -import git4idea.GitUtil; -import git4idea.GitVcs; import git4idea.commands.GitCommand; -import git4idea.commands.GitFileUtils; import git4idea.commands.GitSimpleHandler; import git4idea.commands.StringScanner; import git4idea.config.GitConfigUtil; import git4idea.config.GitVersion; import git4idea.ui.GitUIUtil; import git4idea.ui.StashInfo; -import git4idea.vfs.GitVFSListener; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import javax.swing.event.ChangeEvent; -import java.io.File; -import java.io.IOException; import java.nio.charset.Charset; -import java.util.*; /** * The class contains utilities for creating and removing stashes. @@ -66,7 +38,6 @@ public class GitStashUtils { * The version when quiet stash supported */ private final static GitVersion QUIET_STASH_SUPPORTED = new GitVersion(1, 6, 4, 0); - private static final Logger LOG = Logger.getInstance(GitStashUtils.class.getName()); private GitStashUtils() { } @@ -110,139 +81,4 @@ public class GitStashUtils { consumer.consume(new StashInfo(s.boundedToken(':'), s.boundedToken(':'), s.line().trim())); } } - - /** - * Perform system level unshelve operation - * - * @param project the project - * @param shelvedChangeList the shelved change list - * @param shelveManager the shelve manager - * @param restoreListsRunnable - */ - @AsynchronousExecution - public static void doSystemUnshelve(final Project project, - final ShelvedChangeList shelvedChangeList, - final ShelveChangesManager shelveManager, - @NotNull final Runnable restoreListsRunnable, - final @NotNull ContinuationContext context) { - VirtualFile baseDir = project.getBaseDir(); - assert baseDir != null; - final String projectPath = baseDir.getPath() + "/"; - - context.next(new TaskDescriptor("Refreshing files before unshelve", Where.POOLED) { - @Override - public void run(ContinuationContext context) { - LOG.info("doSystemUnshelve "); - // The changes are temporary copied to the first local change list, the next operation will restore them back - // Refresh files that might be affected by unshelve - refreshFilesBeforeUnshelve(shelvedChangeList, projectPath); - - LOG.info("doSystemUnshelve files refreshed. unshelving in AWT thread."); - } - }, new TaskDescriptor("", Where.AWT) { - @Override - public void run(ContinuationContext context) { - GitVFSListener l = GitVcs.getInstance(project).getVFSListener(); - l.setEventsSuppressed(true); - - LOG.info("Unshelving in UI thread. shelvedChangeList: " + shelvedChangeList); - // we pass null as target change list for Patch Applier to do NOTHING with change lists - shelveManager.scheduleUnshelveChangeList(shelvedChangeList, shelvedChangeList.getChanges(), - shelvedChangeList.getBinaryFiles(), null, false, context); - } - }, new TaskDescriptor("", Where.AWT) { - @Override - public void run(ContinuationContext context) { - GitVcs.getInstance(project).getVFSListener().setEventsSuppressed(false); - addFilesAfterUnshelve(project, shelvedChangeList, projectPath, context); - ChangeListManager.getInstance(project).invokeAfterUpdate(new Runnable() { - @Override - public void run() { - restoreListsRunnable.run(); - } - }, InvokeAfterUpdateMode.BACKGROUND_NOT_CANCELLABLE_NOT_AWT, "Restoring changelists", ModalityState.NON_MODAL); - } - }); - } - - private static void addFilesAfterUnshelve(Project project, - ShelvedChangeList shelvedChangeList, - String projectPath, ContinuationContext context) { - Collection paths = new ArrayList(); - for (ShelvedChange c : shelvedChangeList.getChanges()) { - if (c.getBeforePath() == null || !c.getBeforePath().equals(c.getAfterPath()) || c.getFileStatus() == FileStatus.ADDED) { - paths.add(VcsUtil.getFilePath(projectPath + c.getAfterPath())); - } - } - for (ShelvedBinaryFile f : shelvedChangeList.getBinaryFiles()) { - if (f.BEFORE_PATH == null || !f.BEFORE_PATH.equals(f.AFTER_PATH) || f.getFileStatus() == FileStatus.ADDED) { - paths.add(VcsUtil.getFilePath(projectPath + f.AFTER_PATH)); - } - } - final VcsDirtyScopeManager dsm = VcsDirtyScopeManager.getInstance(project); - Map> map = GitUtil.sortGitFilePathsByGitRoot(paths); - for (Map.Entry> e : map.entrySet()) { - try { - GitFileUtils.addPaths(project, e.getKey(), e.getValue()); - dsm.filePathsDirty(e.getValue(), null); - } - catch (VcsException e1) { - if (! context.handleException(e1)) { - AbstractVcsHelper.getInstance(project).showError(e1, "Can not add file to Git"); - LOG.error("Vcs Exception not handled"); - } - } - } - } - - private static void refreshFilesBeforeUnshelve(ShelvedChangeList shelvedChangeList, String projectPath) { - HashSet filesToRefresh = new HashSet(); - for (ShelvedChange c : shelvedChangeList.getChanges()) { - if (c.getBeforePath() != null) { - filesToRefresh.add(new File(projectPath + c.getBeforePath())); - } - if (c.getAfterPath() != null) { - filesToRefresh.add(new File(projectPath + c.getAfterPath())); - } - } - for (ShelvedBinaryFile f : shelvedChangeList.getBinaryFiles()) { - if (f.BEFORE_PATH != null) { - filesToRefresh.add(new File(projectPath + f.BEFORE_PATH)); - } - if (f.AFTER_PATH != null) { - filesToRefresh.add(new File(projectPath + f.BEFORE_PATH)); - } - } - LocalFileSystem.getInstance().refreshIoFiles(filesToRefresh); - } - - /** - * Shelve changes - * - * @param project the context project - * @param shelveManager the shelve manager - * @param changes the changes to process - * @param description the description of for the shelve - * @param exceptions the generated exceptions - * @return created shelved change list or null in case failure - */ - @Nullable - public static ShelvedChangeList shelveChanges(final Project project, final ShelveChangesManager shelveManager, Collection changes, - final String description, - final List exceptions) { - try { - ShelvedChangeList shelve = shelveManager.shelveChanges(changes, description); - project.getMessageBus().syncPublisher(ShelveChangesManager.SHELF_TOPIC).stateChanged(new ChangeEvent(GitStashUtils.class)); - return shelve; - } - catch (IOException e) { - //noinspection ThrowableInstanceNeverThrown - exceptions.add(new VcsException("Shelving changes failed: " + description, e)); - return null; - } - catch (VcsException e) { - exceptions.add(e); - return null; - } - } } From 015c35b6592995c719faf6a96a4cd2b937a0683d Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 13:20:53 +0400 Subject: [PATCH 34/43] [Git] dead code --- plugins/git4idea/src/git4idea/stash/GitStashUtils.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java index 89b3b8ca704c..e25e764df9f2 100644 --- a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java @@ -23,7 +23,6 @@ import git4idea.commands.GitCommand; import git4idea.commands.GitSimpleHandler; import git4idea.commands.StringScanner; import git4idea.config.GitConfigUtil; -import git4idea.config.GitVersion; import git4idea.ui.GitUIUtil; import git4idea.ui.StashInfo; import org.jetbrains.annotations.NotNull; @@ -34,10 +33,6 @@ import java.nio.charset.Charset; * The class contains utilities for creating and removing stashes. */ public class GitStashUtils { - /** - * The version when quiet stash supported - */ - private final static GitVersion QUIET_STASH_SUPPORTED = new GitVersion(1, 6, 4, 0); private GitStashUtils() { } From ae9c434238d31b6ae7cde7401532ffeb71dbe772 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 17:19:21 +0400 Subject: [PATCH 35/43] [Git] IDEA-51187 Auto-merge on unstash. * dropStash moved to GitStashUtils. * GitUnstashDialog captures conflicts and uses GitMergeConflictResolver. --- .../merge/GitMergeConflictResolver.java | 2 +- .../git4idea/stash/GitStashChangesSaver.java | 18 +---- .../src/git4idea/stash/GitStashUtils.java | 22 ++++++ .../src/git4idea/ui/GitUnstashDialog.java | 78 ++++++++++++++++++- 4 files changed, 98 insertions(+), 22 deletions(-) diff --git a/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java b/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java index faf90fe1c310..834249d06afc 100644 --- a/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java +++ b/plugins/git4idea/src/git4idea/merge/GitMergeConflictResolver.java @@ -42,7 +42,7 @@ import java.util.Collection; public class GitMergeConflictResolver { private static final Logger LOG = Logger.getInstance(GitMergeConflictResolver.class); - private final @NotNull Project myProject; + protected final @NotNull Project myProject; private final boolean myReverseMerge; private final @NotNull String myErrorNotificationTitle; private final @NotNull String myErrorNotificationAdditionalDescription; diff --git a/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java b/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java index ca8f4120ed40..736f9c5a8eef 100644 --- a/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashChangesSaver.java @@ -176,7 +176,7 @@ public class GitStashChangesSaver extends GitChangesSaver { boolean conflictsResolved = new UnstashConflictResolver().merge(Collections.singleton(root)); if (conflictsResolved) { LOG.info("loadRoot " + root + " conflicts resolved, dropping stash"); - dropStash(root); + GitStashUtils.dropStash(myProject, root); } } else { LOG.info("unstash failed " + handler.errors()); @@ -185,22 +185,6 @@ public class GitStashChangesSaver extends GitChangesSaver { } } - // drops stash (after completing conflicting merge during unstashing), shows a warning in case of error - private void dropStash(VirtualFile root) { - final GitSimpleHandler handler = new GitSimpleHandler(myProject, root, GitCommand.STASH); - handler.setNoSSH(true); - handler.addParameters("drop"); - String output = null; - try { - output = handler.run(); - } catch (VcsException e) { - LOG.info("dropStash " + output, e); - GitUIUtil.notifyMessage(myProject, "Couldn't drop stash", - "Couldn't drop stash after resolving conflicts.
Please drop stash manually.", - WARNING, false, handler.errors()); - } - } - // Sort changes from myChangesLists by their git roots. // And use only supplied roots, ignoring changes from other roots. private Map> groupChangesByRoots(Collection rootsToSave) { diff --git a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java index e25e764df9f2..53945b065656 100644 --- a/plugins/git4idea/src/git4idea/stash/GitStashUtils.java +++ b/plugins/git4idea/src/git4idea/stash/GitStashUtils.java @@ -15,6 +15,7 @@ */ package git4idea.stash; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; @@ -29,11 +30,15 @@ import org.jetbrains.annotations.NotNull; import java.nio.charset.Charset; +import static com.intellij.notification.NotificationType.WARNING; + /** * The class contains utilities for creating and removing stashes. */ public class GitStashUtils { + private static final Logger LOG = Logger.getInstance(GitStashUtils.class); + private GitStashUtils() { } @@ -76,4 +81,21 @@ public class GitStashUtils { consumer.consume(new StashInfo(s.boundedToken(':'), s.boundedToken(':'), s.line().trim())); } } + + // drops stash (after completing conflicting merge during unstashing), shows a warning in case of error + public static void dropStash(Project project, VirtualFile root) { + final GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.STASH); + handler.setNoSSH(true); + handler.addParameters("drop"); + String output = null; + try { + output = handler.run(); + } catch (VcsException e) { + LOG.info("dropStash " + output, e); + GitUIUtil.notifyMessage(project, "Couldn't drop stash", + "Couldn't drop stash after resolving conflicts.
Please drop stash manually.", + WARNING, false, handler.errors()); + } + } + } diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java index 820749a286c6..7110aa8c8061 100644 --- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java +++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java @@ -15,6 +15,11 @@ */ package git4idea.ui; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.progress.Task; @@ -23,6 +28,8 @@ import com.intellij.openapi.ui.DialogWrapper; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Key; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.DocumentAdapter; import com.intellij.util.Consumer; @@ -33,19 +40,19 @@ import git4idea.actions.GitShowAllSubmittedFilesAction; import git4idea.commands.*; import git4idea.config.GitVersionSpecialty; import git4idea.i18n.GitBundle; +import git4idea.merge.GitMergeConflictResolver; import git4idea.stash.GitStashUtils; import git4idea.validators.GitBranchNameValidator; import org.jetbrains.annotations.NotNull; import javax.swing.*; import javax.swing.event.DocumentEvent; +import javax.swing.event.HyperlinkEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionListener; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.atomic.AtomicBoolean; /** @@ -102,6 +109,7 @@ public class GitUnstashDialog extends DialogWrapper { */ private final Project myProject; private GitVcs myVcs; + private static final Logger LOG = Logger.getInstance(GitUnstashDialog.class); /** * A constructor @@ -406,10 +414,14 @@ public class GitUnstashDialog extends DialogWrapper { affectedRoots.add(d.getGitRoot()); GitLineHandler h = d.handler(false); final AtomicBoolean needToEscapedBraces = new AtomicBoolean(false); + final AtomicBoolean conflict = new AtomicBoolean(); + h.addLineListener(new GitLineHandlerAdapter() { public void onLineAvailable(String line, Key outputType) { if (line.startsWith("fatal: Needed a single revision")) { needToEscapedBraces.set(true); + } else if (line.contains("Merge conflict")) { + conflict.set(true); } } }); @@ -418,8 +430,66 @@ public class GitUnstashDialog extends DialogWrapper { h = d.handler(true); rc = GitHandlerUtil.doSynchronously(h, GitBundle.getString("unstash.unstashing"), h.printableCommandLine(), false); } - if (rc != 0) { + + if (conflict.get()) { + VirtualFile root = d.getGitRoot(); + boolean conflictsResolved = new UnstashConflictResolver(project, d.getSelectedStash()).merge(Collections.singleton(root)); + if (conflictsResolved) { + LOG.info("loadRoot " + root + " conflicts resolved, dropping stash"); + GitStashUtils.dropStash(project, root); + } + } else if (rc != 0) { GitUIUtil.showOperationErrors(project, h.errors(), h.printableCommandLine()); } } + + private static class UnstashConflictResolver extends GitMergeConflictResolver { + private StashInfo myStashInfo; + + public UnstashConflictResolver(Project project, StashInfo stashInfo) { + super(project, true, new UnstashMergeDialogCustomizer(stashInfo), "Local changes were not restored", ""); + myStashInfo = stashInfo; + } + + @Override + protected void notifyUnresolvedRemain(final Collection roots) { + Notifications.Bus.notify(new Notification(GitVcs.IMPORTANT_ERROR_NOTIFICATION, "Conflicts were not resolved during unstash", + "Unstash is not complete, you have unresolved merges in your working tree
" + + "Resolve conflicts.", + NotificationType.WARNING, new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + if (event.getDescription().equals("resolve")) { + new UnstashConflictResolver(myProject, myStashInfo).justMerge(roots); + } + } + } + })); + } + } + + private static class UnstashMergeDialogCustomizer extends MergeDialogCustomizer { + + private final StashInfo myStashInfo; + + public UnstashMergeDialogCustomizer(StashInfo stashInfo) { + myStashInfo = stashInfo; + } + + @Override + public String getMultipleFileMergeDescription(Collection files) { + return "Conflicts during unstashing " + myStashInfo.getStash() + "\"" + myStashInfo.getMessage() + "\""; + } + + @Override + public String getLeftPanelTitle(VirtualFile file) { + return "Local changes"; + } + + @Override + public String getRightPanelTitle(VirtualFile file, VcsRevisionNumber lastRevisionNumber) { + return "Changes from stash"; + } + } } From 2b3df1d639277f42809ae766aac387963a48c98b Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 18:40:12 +0400 Subject: [PATCH 36/43] [Git] Fixed message in notification. Relates to IDEA-51187. --- plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java index 7110aa8c8061..fe1313da3816 100644 --- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java +++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java @@ -447,7 +447,7 @@ public class GitUnstashDialog extends DialogWrapper { private StashInfo myStashInfo; public UnstashConflictResolver(Project project, StashInfo stashInfo) { - super(project, true, new UnstashMergeDialogCustomizer(stashInfo), "Local changes were not restored", ""); + super(project, true, new UnstashMergeDialogCustomizer(stashInfo), "Unstashed with conflicts", ""); myStashInfo = stashInfo; } From b5d0004b1a8d32afde7de76dbd5c4bd3e7718762 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 20:29:38 +0400 Subject: [PATCH 37/43] [Git] Nullable --- .../git4idea/src/git4idea/commands/GitHandler.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 2f1b90faec3a..dd00d82b163a 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -35,20 +35,14 @@ import git4idea.config.GitVcsSettings; import git4idea.config.GitVersionSpecialty; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.git4idea.ssh.GitSSHHandler; import org.jetbrains.git4idea.ssh.GitSSHService; import java.io.File; import java.io.OutputStream; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.LinkedBlockingQueue; /** @@ -635,7 +629,7 @@ public abstract class GitHandler { return myCommandLine.getCommandLineString().length() > VcsFileUtil.FILE_PATH_LIMIT; } - public void runInCurrentThread(Runnable postStartAction) { + public void runInCurrentThread(@Nullable Runnable postStartAction) { final GitVcs vcs = GitVcs.getInstance(myProject); if (vcs == null) { return; } From 4a8cb65e7f52d0e03657c7306469064aa8f438f8 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 20:30:33 +0400 Subject: [PATCH 38/43] [Git] Store Subject in GitCommit. --- plugins/git4idea/src/git4idea/history/GitHistoryUtils.java | 2 +- .../git4idea/src/git4idea/history/browser/GitCommit.java | 7 +++++++ .../src/git4idea/history/wholeTree/DetailsLoaderImpl.java | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java index 9b9ebca04d64..5760d3b9fd28 100644 --- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java +++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java @@ -502,7 +502,7 @@ public class GitHistoryUtils { final String s = parseRefs(refs, currentRefs, locals, remotes, tags); gitCommit = new GitCommit(AbstractHash.create(record.getShortHash()), new SHAHash(record.getHash()), record.getAuthorName(), record.getCommitterName(), - record.getDate(), record.getFullMessage(), + record.getDate(), record.getSubject(), record.getFullMessage(), new HashSet(Arrays.asList(record.getParentsShortHashes())), record.getFilePaths(root), record.getAuthorEmail(), record.getCommitterEmail(), tags, locals, remotes, diff --git a/plugins/git4idea/src/git4idea/history/browser/GitCommit.java b/plugins/git4idea/src/git4idea/history/browser/GitCommit.java index 71f2af4485c7..8ecc14275459 100644 --- a/plugins/git4idea/src/git4idea/history/browser/GitCommit.java +++ b/plugins/git4idea/src/git4idea/history/browser/GitCommit.java @@ -31,6 +31,7 @@ public class GitCommit { private final SHAHash myHash; private final String myAuthor; private final String myCommitter; + private final String mySubject; private final String myDescription; private final Date myDate; @@ -60,6 +61,7 @@ public class GitCommit { final String author, final String committer, final Date date, + final String subject, final String description, final Set parentsHashes, final List pathsList, @@ -74,6 +76,7 @@ public class GitCommit { myAuthor = author; myCommitter = committer; myDate = date; + mySubject = subject; myDescription = description; myHash = hash; myParentsHashes = parentsHashes; @@ -223,4 +226,8 @@ public class GitCommit { } }); } + + public String getSubject() { + return mySubject; + } } diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/DetailsLoaderImpl.java b/plugins/git4idea/src/git4idea/history/wholeTree/DetailsLoaderImpl.java index 0293f3462cb0..a3fbe82972d1 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/DetailsLoaderImpl.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/DetailsLoaderImpl.java @@ -194,7 +194,7 @@ public class DetailsLoaderImpl implements DetailsLoader { private GitCommit createNotLoadedCommit(AbstractHash shortHash) { final String notKnown = "Can not load"; - return new GitCommit(shortHash, SHAHash.emulate(shortHash), notKnown, notKnown, new Date(0), + return new GitCommit(shortHash, SHAHash.emulate(shortHash), notKnown, notKnown, new Date(0), notKnown, "Can not load details", Collections.emptySet(), Collections.emptyList(), notKnown, notKnown, Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), 0); From 5304e6f6e3ebd3bb5ec9fdf079e957f9c987d468 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 20:31:57 +0400 Subject: [PATCH 39/43] [Git] IDEA-51187 Auto-merge for cherry-pick --- .../src/git4idea/commands/GitFileUtils.java | 9 -- .../history/browser/CherryPicker.java | 5 +- .../history/browser/LowLevelAccess.java | 3 +- .../history/browser/LowLevelAccessImpl.java | 105 +++++++++++++++++- 4 files changed, 105 insertions(+), 17 deletions(-) diff --git a/plugins/git4idea/src/git4idea/commands/GitFileUtils.java b/plugins/git4idea/src/git4idea/commands/GitFileUtils.java index 31d09e596a0a..76f1e4a0ca30 100644 --- a/plugins/git4idea/src/git4idea/commands/GitFileUtils.java +++ b/plugins/git4idea/src/git4idea/commands/GitFileUtils.java @@ -60,15 +60,6 @@ public class GitFileUtils { } } - public static void cherryPick(final Project project, final VirtualFile root, final String hash) throws VcsException { - GitSimpleHandler handler = new GitSimpleHandler(project, root, GitCommand.CHERRY_PICK); - handler.addParameters("-x", "-n", hash); - handler.endOptions(); - //handler.addRelativePaths(new FilePathImpl(root)); - handler.setNoSSH(true); - handler.run(); - } - /** * Delete files * diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index 43c0486ea12a..2146c7ac22c7 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -129,9 +129,8 @@ public class CherryPicker { private void cherryPickStep(CheckinEnvironment ce, int i) { final GitCommit commit = myCommits.get(i); - final SHAHash hash = commit.getHash(); try { - myAccess.cherryPick(hash); + myAccess.cherryPick(commit); } catch (VcsException e) { myExceptions.add(e); @@ -141,7 +140,7 @@ public class CherryPicker { final Collection paths = ChangesUtil.getPaths(changes); String message = ce.getDefaultMessageFor(paths.toArray(new FilePath[paths.size()])); message = (message == null) ? new StringBuilder().append(commit.getDescription()).append("(cherry picked from commit ") - .append(hash.getValue()).append(")").toString() : message; + .append(commit.getShortHash()).append(")").toString() : message; myMessagesInOrder.add(message); myFilesToMove.put(message, paths); diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java index fe88d733ca3f..be147979b3ce 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java @@ -16,7 +16,6 @@ package git4idea.history.browser; import com.intellij.openapi.util.Getter; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.AsynchConsumer; @@ -57,7 +56,7 @@ public interface LowLevelAccess { void loadAllTags(final Collection sink) throws VcsException; - void cherryPick(SHAHash hash) throws VcsException; + void cherryPick(GitCommit hash) throws VcsException; void loadHashesWithParents(final @NotNull Collection startingPoints, @NotNull final Collection filters, final AsynchConsumer consumer, Getter isCanceled, int useMaxCnt) throws VcsException; List getCommitDetails(final Collection commitIds, SymbolicRefs refs) throws VcsException; diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java index b2fe33993ac1..1b88653e0f55 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java @@ -16,24 +16,38 @@ */ package git4idea.history.browser; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Getter; +import com.intellij.openapi.util.Key; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.VcsException; +import com.intellij.openapi.vcs.history.VcsRevisionNumber; +import com.intellij.openapi.vcs.merge.MergeDialogCustomizer; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.AsynchConsumer; import git4idea.GitBranch; +import git4idea.GitRevisionNumber; import git4idea.GitTag; -import git4idea.commands.GitFileUtils; +import git4idea.GitVcs; +import git4idea.commands.GitCommand; +import git4idea.commands.GitLineHandler; +import git4idea.commands.GitLineHandlerAdapter; import git4idea.config.GitConfigUtil; import git4idea.history.GitHistoryUtils; import git4idea.history.wholeTree.CommitHashPlusParents; +import git4idea.merge.GitMergeConflictResolver; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import javax.swing.event.HyperlinkEvent; import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; public class LowLevelAccessImpl implements LowLevelAccess { private final static Logger LOG = Logger.getInstance("#git4idea.history.browser.LowLevelAccessImpl"); @@ -181,7 +195,92 @@ public class LowLevelAccessImpl implements LowLevelAccess { GitTag.listAsStrings(myProject, myRoot, sink, null); } - public void cherryPick(SHAHash hash) throws VcsException { - GitFileUtils.cherryPick(myProject, myRoot, hash.getValue()); + public void cherryPick(GitCommit commit) throws VcsException { + final GitLineHandler handler = new GitLineHandler(myProject, myRoot, GitCommand.CHERRY_PICK); + handler.addParameters("-x", "-n", commit.getHash().getValue()); + handler.endOptions(); + handler.setNoSSH(true); + + final AtomicBoolean conflict = new AtomicBoolean(); + + handler.addLineListener(new GitLineHandlerAdapter() { + public void onLineAvailable(String line, Key outputType) { + if (line.contains("after resolving the conflicts, mark the corrected paths")) { + conflict.set(true); + } + } + }); + handler.runInCurrentThread(null); + + if (conflict.get()) { + new CherryPickConflictResolver(myProject, commit.getShortHash().getString(), commit.getAuthor(), commit.getSubject()).merge(Collections.singleton(myRoot)); + } else { + final List errors = handler.errors(); + if (!errors.isEmpty()) { + throw errors.get(0); + } + } + } + + private static class CherryPickConflictResolver extends GitMergeConflictResolver { + + private String myCommitHash; + private String myCommitAuthor; + private String myCommitMessage; + + public CherryPickConflictResolver(Project project, String commitHash, String commitAuthor, String commitMessage) { + super(project, true, new CherryPickMergeDialogCustomizer(commitHash, commitAuthor, commitMessage), "Cherry-picked with conflicts", ""); + myCommitHash = commitHash; + myCommitAuthor = commitAuthor; + myCommitMessage = commitMessage; + } + + @Override + protected void notifyUnresolvedRemain(final Collection roots) { + Notifications.Bus.notify(new Notification(GitVcs.IMPORTANT_ERROR_NOTIFICATION, "Conflicts were not resolved during cherry-pick", + "Cherry-pick is not complete, you have unresolved merges in your working tree
" + + "Resolve conflicts.", + NotificationType.WARNING, new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + if (event.getDescription().equals("resolve")) { + new CherryPickConflictResolver(myProject, myCommitHash, myCommitAuthor, myCommitMessage).justMerge(roots); + } + } + } + })); + } + } + + private static class CherryPickMergeDialogCustomizer extends MergeDialogCustomizer { + + private String myCommitHash; + private String myCommitAuthor; + private String myCommitMessage; + + public CherryPickMergeDialogCustomizer(String commitHash, String commitAuthor, String commitMessage) { + myCommitHash = commitHash; + myCommitAuthor = commitAuthor; + myCommitMessage = commitMessage; + } + + @Override + public String getMultipleFileMergeDescription(Collection files) { + return "Conflicts during cherry-picking commit " + myCommitHash + " made by " + myCommitAuthor + "
" + + "\"" + myCommitMessage + "\""; + } + + @Override + public String getLeftPanelTitle(VirtualFile file) { + return "Local changes"; + } + + @Override + public String getRightPanelTitle(VirtualFile file, VcsRevisionNumber lastRevisionNumber) { + return "Changes from cherry-pick " + ((GitRevisionNumber)lastRevisionNumber).toShortString() + ""; + } + } + } From 1c2dfda2614a2e9fdcae731667d16c2bf74a7e20 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 20:38:15 +0400 Subject: [PATCH 40/43] [Git] cherryPick returns false if not all conflicts were resolved. --- .../src/git4idea/history/browser/LowLevelAccess.java | 9 ++++++++- .../src/git4idea/history/browser/LowLevelAccessImpl.java | 8 +++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java index be147979b3ce..39959691cf0a 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccess.java @@ -56,7 +56,14 @@ public interface LowLevelAccess { void loadAllTags(final Collection sink) throws VcsException; - void cherryPick(GitCommit hash) throws VcsException; + /** + * Cherry-picks the specified commit. + * Doesn't autocommit - instead puts the changes into a separate changelist. + * In the case of merge conflict provides the Conflict Resolver dialog. + * @return true if all conflicts were resolved or there were no merge conflicts; false if unresolved files remain. + * @throws VcsException + */ + boolean cherryPick(GitCommit hash) throws VcsException; void loadHashesWithParents(final @NotNull Collection startingPoints, @NotNull final Collection filters, final AsynchConsumer consumer, Getter isCanceled, int useMaxCnt) throws VcsException; List getCommitDetails(final Collection commitIds, SymbolicRefs refs) throws VcsException; diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java index 1b88653e0f55..6afd6c8e654b 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java @@ -195,7 +195,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { GitTag.listAsStrings(myProject, myRoot, sink, null); } - public void cherryPick(GitCommit commit) throws VcsException { + public boolean cherryPick(GitCommit commit) throws VcsException { final GitLineHandler handler = new GitLineHandler(myProject, myRoot, GitCommand.CHERRY_PICK); handler.addParameters("-x", "-n", commit.getHash().getValue()); handler.endOptions(); @@ -213,14 +213,16 @@ public class LowLevelAccessImpl implements LowLevelAccess { handler.runInCurrentThread(null); if (conflict.get()) { - new CherryPickConflictResolver(myProject, commit.getShortHash().getString(), commit.getAuthor(), commit.getSubject()).merge(Collections.singleton(myRoot)); + boolean allConflictsResolved = new CherryPickConflictResolver(myProject, commit.getShortHash().getString(), commit.getAuthor(), commit.getSubject()).merge(Collections.singleton(myRoot)); + return allConflictsResolved; } else { final List errors = handler.errors(); if (!errors.isEmpty()) { throw errors.get(0); + } else { // no conflicts, no errors + return true; } } - } private static class CherryPickConflictResolver extends GitMergeConflictResolver { From 30fc60f43c4e2be4c01525eb380c25e22cadad43 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Wed, 11 May 2011 20:49:27 +0400 Subject: [PATCH 41/43] [Git] if not all conflicts resolved, notify. Relates to IDEA-51187 --- .../history/browser/CherryPicker.java | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index 2146c7ac22c7..9ce3a4615a40 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -17,13 +17,13 @@ package git4idea.history.browser; import com.intellij.lifecycle.PeriodicalTasksCloser; import com.intellij.openapi.application.ModalityState; +import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.MessageType; import com.intellij.openapi.vcs.AbstractVcsHelper; import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.*; import com.intellij.openapi.vcs.checkin.CheckinEnvironment; -import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier; import com.intellij.openapi.vfs.LocalFileSystem; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Consumer; @@ -31,6 +31,8 @@ import git4idea.GitVcs; import java.util.*; +import static com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier.showOverChangesView; + public class CherryPicker { private final GitVcs myVcs; private final List myCommits; @@ -41,6 +43,7 @@ public class CherryPicker { private final List myDirtyFiles; private final List myMessagesInOrder; private final Map> myFilesToMove; + private boolean myConflictsExist; public CherryPicker(GitVcs vcs, final List commits, LowLevelAccess access) { myVcs = vcs; @@ -90,15 +93,19 @@ public class CherryPicker { } private void showResults() { - if (myExceptions.isEmpty()) { - VcsBalloonProblemNotifier - .showOverChangesView(myVcs.getProject(), "Successful cherry-pick into working tree, please commit changes", MessageType.INFO); + final Project project = myVcs.getProject(); + if (myExceptions.isEmpty() && !myConflictsExist) { + showOverChangesView(project, "Successful cherry-pick into working tree, please commit changes", MessageType.INFO); } else { - VcsBalloonProblemNotifier.showOverChangesView(myVcs.getProject(), "Errors in cherry-pick", MessageType.ERROR); + if (myExceptions.isEmpty()) { + showOverChangesView(project, "Unresolved conflicts while cherry-picking. Resolve conflicts, then commit changes", MessageType.WARNING); + } else { + showOverChangesView(project, "Errors in cherry-pick", MessageType.ERROR); + } } if ((! myExceptions.isEmpty()) || (! myWarnings.isEmpty())) { myExceptions.addAll(myWarnings); - AbstractVcsHelper.getInstance(myVcs.getProject()).showErrors(myExceptions, "Cherry-pick problems"); + AbstractVcsHelper.getInstance(project).showErrors(myExceptions, "Cherry-pick problems"); } } @@ -130,7 +137,9 @@ public class CherryPicker { private void cherryPickStep(CheckinEnvironment ce, int i) { final GitCommit commit = myCommits.get(i); try { - myAccess.cherryPick(commit); + if (!myAccess.cherryPick(commit)) { + myConflictsExist = true; + } } catch (VcsException e) { myExceptions.add(e); From 3244f117efe7640f0dc4f4bcd0aaef14e016d567 Mon Sep 17 00:00:00 2001 From: "Maxim.Mossienko" Date: Tue, 10 May 2011 21:41:09 +0400 Subject: [PATCH 42/43] IDEA-69459 Flex: show suggestion "Create method" on Alt+Enter for "(A as B).method()" casting --- .../daemon/quickFix/LightQuickFixTestCase.java | 14 ++++++++++---- .../daemon/quickFix/QuickFixTestCase.java | 3 +++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java index e32d3d541523..fb98f7ed9c9b 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java @@ -23,6 +23,7 @@ import com.intellij.lang.Commenter; import com.intellij.lang.LanguageCommenters; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -61,7 +62,7 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase final String relativePath = quickFixTestCase.getBasePath() + "/" + BEFORE_PREFIX + testName; final String testFullPath = quickFixTestCase.getTestDataPath().replace(File.separatorChar, '/') + relativePath; final File testFile = new File(testFullPath); - CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() { + CommandProcessor.getInstance().executeCommand(quickFixTestCase.getProject(), new Runnable() { @Override public void run() { try { @@ -263,17 +264,22 @@ public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase @Override public void configureFromFileText(String name, String contents) throws IOException { - LightCodeInsightTestCase.configureFromFileText(name, contents); + LightQuickFixTestCase.configureFromFileText(name, contents); } @Override public PsiFile getFile() { - return LightCodeInsightTestCase.getFile(); + return LightQuickFixTestCase.getFile(); + } + + @Override + public Project getProject() { + return LightQuickFixTestCase.getProject(); } @Override public void bringRealEditorBack() { - LightCodeInsightTestCase.bringRealEditorBack(); + LightQuickFixTestCase.bringRealEditorBack(); } }); } diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/QuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/QuickFixTestCase.java index 3ea3502a09df..613488732762 100644 --- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/QuickFixTestCase.java +++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/QuickFixTestCase.java @@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.quickFix; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiFile; @@ -57,4 +58,6 @@ public interface QuickFixTestCase { void configureFromFileText(String name, String contents) throws Throwable; PsiFile getFile(); + + Project getProject(); } From 10e89d8a3c2b0c908dab491408afad9d10228198 Mon Sep 17 00:00:00 2001 From: Kirill Likhodedov Date: Thu, 12 May 2011 12:24:55 +0400 Subject: [PATCH 43/43] [Git] Fix merge dialog sides for unstash and cherry-pick. Relates to IDEA-51187 --- .../src/git4idea/history/browser/LowLevelAccessImpl.java | 5 ++--- plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java index 6afd6c8e654b..8d0ef322c0db 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java @@ -32,7 +32,6 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.ArrayUtil; import com.intellij.util.AsynchConsumer; import git4idea.GitBranch; -import git4idea.GitRevisionNumber; import git4idea.GitTag; import git4idea.GitVcs; import git4idea.commands.GitCommand; @@ -232,7 +231,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { private String myCommitMessage; public CherryPickConflictResolver(Project project, String commitHash, String commitAuthor, String commitMessage) { - super(project, true, new CherryPickMergeDialogCustomizer(commitHash, commitAuthor, commitMessage), "Cherry-picked with conflicts", ""); + super(project, false, new CherryPickMergeDialogCustomizer(commitHash, commitAuthor, commitMessage), "Cherry-picked with conflicts", ""); myCommitHash = commitHash; myCommitAuthor = commitAuthor; myCommitMessage = commitMessage; @@ -281,7 +280,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { @Override public String getRightPanelTitle(VirtualFile file, VcsRevisionNumber lastRevisionNumber) { - return "Changes from cherry-pick " + ((GitRevisionNumber)lastRevisionNumber).toShortString() + ""; + return "Changes from cherry-pick " + myCommitHash + ""; } } diff --git a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java index fe1313da3816..ba8d723cdcdc 100644 --- a/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java +++ b/plugins/git4idea/src/git4idea/ui/GitUnstashDialog.java @@ -447,7 +447,7 @@ public class GitUnstashDialog extends DialogWrapper { private StashInfo myStashInfo; public UnstashConflictResolver(Project project, StashInfo stashInfo) { - super(project, true, new UnstashMergeDialogCustomizer(stashInfo), "Unstashed with conflicts", ""); + super(project, false, new UnstashMergeDialogCustomizer(stashInfo), "Unstashed with conflicts", ""); myStashInfo = stashInfo; }