From 61cc498e22479ec1d7de477295842befaf8bb339 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Tue, 2 Nov 2010 16:40:15 +0300 Subject: [PATCH 01/61] IDEA-60613 Groovy: Code Completion for aliased classes instantiation expression inserts braces with wrong offset; SIOOBE at GroovyInsertHandler.handleInsert() --- .../plugins/groovy/lang/completion/GroovyInsertHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java index 15131266f7ea..c78a6cdbf5fa 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java @@ -120,7 +120,7 @@ public class GroovyInsertHandler implements InsertHandler { PsiFile file = PsiDocumentManager.getInstance(clazz.getProject()).getPsiFile(document); PsiElement elementAt = file.findElementAt(context.getStartOffset()); CaretModel caretModel = editor.getCaretModel(); - int offset = context.getStartOffset() + clazz.getName().length(); + int offset = context.getStartOffset() + elementAt.getTextLength(); final String text = document.getText(); final PsiElement parent = elementAt.getParent(); From c2e1ffa967251a39855ec5cbfec49711c96a0e95 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 8 Nov 2010 10:43:32 +0300 Subject: [PATCH 02/61] IDEA-60761 Groovy: Change Signature -> Remove the only parameter Refactoring could add "()" to method calls with omitted parentheses --- .../changeSignature/GrChangeSignatureUsageProcessor.java | 5 ++++- .../refactoring/changeSignature/ChangeSignatureTest.java | 4 ++++ .../refactoring/changeSignature/NoArgInCommandCall.groovy | 5 +++++ .../changeSignature/NoArgInCommandCall_after.groovy | 5 +++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall_after.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 95db68497a57..6e4101bbb752 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -53,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArg import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; @@ -494,7 +495,9 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc anchor = argumentList.addAfter(fromText, anchor); } } - + if (argumentList instanceof GrCommandArgumentList && argumentList.getAllArguments().length == 0) { + argumentList = argumentList.replaceWithArgumentList(factory.createArgumentList()); + } CodeStyleManager.getInstance(argumentList.getProject()).reformat(argumentList); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index f4d84488722e..0d695a9d0e99 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -220,6 +220,10 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { doTest(new SimpleInfo[]{new SimpleInfo(0), new SimpleInfo("a", -1, "1", null, PsiType.INT)}); } + public void testNoArgInCommandCall() { + doTest(new SimpleInfo[0]); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall.groovy new file mode 100644 index 000000000000..03a4c727d8b6 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall.groovy @@ -0,0 +1,5 @@ +def foo(String s) { + +} + +foo "sd" \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall_after.groovy new file mode 100644 index 000000000000..65d9bfeba557 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/NoArgInCommandCall_after.groovy @@ -0,0 +1,5 @@ +def foo() { + +} + +foo() \ No newline at end of file From c42805b0c33003e67871e7c57268e45d03047298 Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 8 Nov 2010 10:44:37 +0300 Subject: [PATCH 03/61] fixed ConfigurablesModifiedTest on Linux --- platform/platform-api/src/com/intellij/ide/ui/UISettings.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java index faf5a650cb18..55588be2125a 100644 --- a/platform/platform-api/src/com/intellij/ide/ui/UISettings.java +++ b/platform/platform-api/src/com/intellij/ide/ui/UISettings.java @@ -147,8 +147,8 @@ public class UISettings implements PersistentStateComponent, Exporta myListenerList.remove(UISettingsListener.class,listener); } - private void setDefaultFontSettings(){ - FONT_FACE = "Dialog"; + private void setDefaultFontSettings() { + FONT_FACE = SystemInfo.isLinux && ApplicationManager.getApplication().isUnitTestMode() ? "Dialog.plain" : "Dialog"; FONT_SIZE = 12; } From 88f44ba2e50c7b0904bc690391016b06611b6841 Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Thu, 4 Nov 2010 19:02:26 +0300 Subject: [PATCH 04/61] Improve support of Grails Domain mapping. --- .../CompleteReferenceExpression.java | 12 ++++++ .../GrReferenceExpressionImpl.java | 42 +++++++++---------- .../ClosureMissingMethodContributor.java | 2 +- 3 files changed, 34 insertions(+), 22 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java index 115e7219e5c9..06e63a6e9a04 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java @@ -36,6 +36,7 @@ import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrThisReferenceExpression; @@ -46,6 +47,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.CompletionProcessor; import org.jetbrains.plugins.groovy.lang.resolve.processors.ResolverProcessor; @@ -176,6 +178,16 @@ public class CompleteReferenceExpression { String[] sameQualifier = getVariantsWithSameQualifier(qualifier, refExpr); if (qualifier == null) { ResolveUtil.treeWalkUp(refExpr, processor, true); + + for (PsiElement e = refExpr.getParent(); e != null; e = e.getParent()) { + if (e instanceof GrClosableBlock) { + ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, (GrClosableBlock)e); + for (ClosureMissingMethodContributor contributor : ClosureMissingMethodContributor.EP_NAME.getExtensions()) { + contributor.processMembers((GrClosableBlock)e, processor, refExpr, state); + } + } + } + qualifier = PsiImplUtil.getRuntimeQualifier(refExpr); if (qualifier != null) { getVariantsFromQualifier(refExpr, processor, qualifier); 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 25ad7d160f29..e08726e617e8 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 @@ -187,6 +187,26 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements return methodResolver.getCandidates(); } + // Search in ClosureMissingMethodContributor + if (!isQualified() && getParent() instanceof GrMethodCall) { + boolean resolve = false; + for (PsiElement e = this.getParent(); !resolve && e != null; e = e.getParent()) { + if (e instanceof GrClosableBlock) { + ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, (GrClosableBlock)e); + for (ClosureMissingMethodContributor contributor : ClosureMissingMethodContributor.EP_NAME.getExtensions()) { + if (!contributor.processMembers((GrClosableBlock)e, methodResolver, this, state)) { + resolve = true; + break; + } + } + } + } + + if (!allVariants && methodResolver.hasApplicableCandidates()) { + return methodResolver.getCandidates(); + } + } + //search for fields inside its class if (!allVariants) { for (GroovyResolveResult candidate : propertyCandidates) { @@ -196,25 +216,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements if (containingClass != null && PsiTreeUtil.isAncestor(containingClass, this, true)) return propertyCandidates; } } - - // Search in ClosureMissingMethodContributor - if (!isQualified() && getParent() instanceof GrMethodCall) { - boolean resolve = false; - for (PsiElement e = this.getParent(); !resolve && e != null; e = e.getParent()) { - if (e instanceof GrClosableBlock) { - for (ClosureMissingMethodContributor contributor : ClosureMissingMethodContributor.EP_NAME.getExtensions()) { - if (!contributor.processMembers((GrClosableBlock)e, methodResolver, this, ResolveState.initial())) { - resolve = true; - break; - } - } - } - } - - if (methodResolver.hasApplicableCandidates()) { - return methodResolver.getCandidates(); - } - } } List allCandidates = new ArrayList(); @@ -577,7 +578,6 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements String name = refExpr.getReferenceName(); if (name == null) return GroovyResolveResult.EMPTY_ARRAY; - Kind kind = refExpr.getKind(); if (incompleteCode) { ResolverProcessor processor = CompletionProcessor.createRefSameNameProcessor(refExpr, name); refExpr.resolveImpl(processor); @@ -585,7 +585,7 @@ public class GrReferenceExpressionImpl extends GrReferenceElementImpl implements if (propertyCandidates.length > 0) return propertyCandidates; } - switch (kind) { + switch (refExpr.getKind()) { case METHOD_OR_PROPERTY: return refExpr.resolveMethodOrProperty(); case TYPE_OR_PROPERTY: diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ClosureMissingMethodContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ClosureMissingMethodContributor.java index 0e5e5d3f27be..27c89f35026b 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ClosureMissingMethodContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/ClosureMissingMethodContributor.java @@ -28,6 +28,6 @@ public abstract class ClosureMissingMethodContributor { public static final ExtensionPointName EP_NAME = ExtensionPointName.create("org.intellij.groovy.closureMissingMethodContributor"); - public abstract boolean processMembers(GrClosableBlock closure, PsiScopeProcessor processor, GrReferenceExpression ref, ResolveState state); + public abstract boolean processMembers(GrClosableBlock closure, PsiScopeProcessor processor, GrReferenceExpression refExpr, ResolveState state); } From 801bd9fb81791833f40bd2e244011643fd69996d Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 8 Nov 2010 12:53:40 +0300 Subject: [PATCH 05/61] IDEA-60753 Groovy: Change Signature -> Remove Parameter Refactoring doesn't remove method arguments before closure inline --- .../GrChangeSignatureUsageProcessor.java | 8 +++++++- .../changeSignature/GrMethodCallUsageInfo.java | 17 +++++++---------- .../changeSignature/ChangeSignatureTest.java | 4 ++++ .../changeSignature/ClosureArgs.groovy | 2 ++ .../changeSignature/ClosureArgs_after.groovy | 2 ++ 5 files changed, 22 insertions(+), 11 deletions(-) create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs.groovy create mode 100644 plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs_after.groovy diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java index 6e4101bbb752..99528fd696c5 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChangeSignatureUsageProcessor.java @@ -53,6 +53,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArg import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression; @@ -68,6 +69,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.refactoring.DefaultGroovyVariableNameValidator; import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; import java.util.List; import java.util.Set; @@ -495,7 +497,11 @@ public class GrChangeSignatureUsageProcessor implements ChangeSignatureUsageProc anchor = argumentList.addAfter(fromText, anchor); } } - if (argumentList instanceof GrCommandArgumentList && argumentList.getAllArguments().length == 0) { + + GrCall call = GroovyRefactoringUtil.getCallExpressionByMethodReference(element); + if (argumentList instanceof GrCommandArgumentList && + argumentList.getAllArguments().length == 0 && + (call == null || call.getClosureArguments().length == 0)) { argumentList = argumentList.replaceWithArgumentList(factory.createArgumentList()); } CodeStyleManager.getInstance(argumentList.getProject()).reformat(argumentList); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java index a5c0ff4b734b..8952db080954 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrMethodCallUsageInfo.java @@ -27,16 +27,12 @@ import com.intellij.refactoring.changeSignature.PossiblyIncorrectUsage; import com.intellij.usageView.UsageInfo; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConstructorCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureSignature; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.types.GrClosureSignatureUtil; -import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; +import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil; /** * @author Maxim.Medvedev @@ -80,13 +76,14 @@ public class GrMethodCallUsageInfo extends UsageInfo implements PossiblyIncorrec GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, mySubstitutor); myToChangeArguments = isToChangeArguments; myToCatchExceptions = isToCatchExceptions; - final GrArgumentList list = PsiUtil.getArgumentsList(element); - if (list == null) { + final GrCall call = GroovyRefactoringUtil.getCallExpressionByMethodReference(element); + if (call == null) { myMapToArguments = GrClosureSignatureUtil.ArgInfo.empty_array(); } else { - myMapToArguments = - GrClosureSignatureUtil.mapParametersToArguments(signature, list); + myMapToArguments = GrClosureSignatureUtil + .mapParametersToArguments(signature, call.getNamedArguments(), call.getExpressionArguments(), call, call.getClosureArguments(), + false); } } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java index 0d695a9d0e99..f9d840c0b18a 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/changeSignature/ChangeSignatureTest.java @@ -224,6 +224,10 @@ public class ChangeSignatureTest extends ChangeSignatureTestCase { doTest(new SimpleInfo[0]); } + public void testClosureArgs() { + doTest(new SimpleInfo[]{new SimpleInfo(0)}); + } + private PsiType createType(String typeText) { return JavaPsiFacade.getElementFactory(getProject()).createTypeByFQClassName(typeText, GlobalSearchScope.allScope(getProject())); } diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs.groovy new file mode 100644 index 000000000000..285e11fed74c --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs.groovy @@ -0,0 +1,2 @@ +def doSmth(int i, Closure c) {} +doSmth(1) { println "smth" } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs_after.groovy b/plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs_after.groovy new file mode 100644 index 000000000000..a537ab9f0a91 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/changeSignature/ClosureArgs_after.groovy @@ -0,0 +1,2 @@ +def doSmth(int i) {} +doSmth(1) \ No newline at end of file From 49cc2c1e933905ad7ce26a4a3dd3ae7279917cee Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 8 Nov 2010 13:01:46 +0300 Subject: [PATCH 06/61] test diagnostics --- .../completion/CodeCompletionHandlerBase.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java index 58fb13216b01..ad4955069902 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -21,6 +21,7 @@ import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer; +import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler; import com.intellij.codeInsight.hint.EditorHintListener; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.lookup.*; @@ -424,6 +425,11 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { final int offset2, final CompletionProgressIndicator indicator, final LookupElement[] items) { + if (CompletionAutoPopupHandler.ourTestingAutopopup) { + System.out.println("CodeCompletionHandlerBase.completionFinished"); + System.out.println("items " + Arrays.asList(items)); + } + if (items.length == 0) { LookupManager.getInstance(indicator.getProject()).hideActiveLookup(); handleEmptyLookup(indicator.getProject(), indicator.getEditor(), indicator.getParameters(), indicator); @@ -436,11 +442,13 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { if (isAutocompleteCommonPrefixOnInvocation() && items.length > 1) { indicator.fillInCommonPrefix(false); } - } else if (decision instanceof AutoCompletionDecision.InsertItem) { + } + else if (decision instanceof AutoCompletionDecision.InsertItem) { final LookupElement item = ((AutoCompletionDecision.InsertItem)decision).getElement(); indicator.closeAndFinish(true); indicator.rememberDocumentState(); - indicator.getOffsetMap().addOffset(CompletionInitializationContext.START_OFFSET, (offset1 - item.getPrefixMatcher().getPrefix().length())); + indicator.getOffsetMap() + .addOffset(CompletionInitializationContext.START_OFFSET, (offset1 - item.getPrefixMatcher().getPrefix().length())); handleSingleItem(offset2, indicator, items, item.getLookupString(), item); // the insert handler may have started a live template with completion From 5d2d24d07d06e7ff14bca335c53b2a9a10591e31 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 8 Nov 2010 13:04:08 +0300 Subject: [PATCH 07/61] IDEA-48674, IDEA-60338 First basic completion shouldn't show generic DefaultGroovyMethods(Object, ...), show them on second one Don't suggest getters/setters for Groovy properties until there's a get/set/is prefix --- .../JavaMethodMergingContributor.java | 6 +- .../plugins/groovy/GroovyBundle.properties | 1 + .../GroovyCompletionConfidence.java | 12 +++ .../GroovyCompletionContributor.java | 65 ++++++++++++-- .../lang/completion/GroovyCompletionUtil.java | 88 ++++++++++++++++--- .../lang/completion/GroovyInsertHandler.java | 6 ++ .../GroovySmartCompletionContributor.java | 8 +- .../GrConstructorInvocationImpl.java | 5 +- .../lang/psi/util/GroovyPropertyUtils.java | 6 +- .../lang/completion/CompletionTestBase.java | 3 +- 10 files changed, 175 insertions(+), 25 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java index 5168a78ca880..513302500f98 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodMergingContributor.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.psi.PsiMethod; +import com.intellij.psi.ResolveResult; import java.util.ArrayList; @@ -39,7 +40,10 @@ public class JavaMethodMergingContributor extends CompletionContributor { LookupElement best = null; final ArrayList allMethods = new ArrayList(); for (LookupElement item : items) { - final Object o = item.getObject(); + Object o = item.getObject(); + if (o instanceof ResolveResult) { + o = ((ResolveResult)o).getElement(); + } if (item.getUserData(LookupItem.FORCE_SHOW_SIGNATURE_ATTR) != null || !(o instanceof PsiMethod)) { return AutoCompletionDecision.SHOW_LOOKUP; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties index 3707d9ade33c..56c1c0c9a0ad 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties @@ -340,3 +340,4 @@ script.file.is.not.groovy.file=Script file is not Groovy file choose.class.to.execute=Choose class to execute class.does.not.exist=Class does not exist class.can't\ be\ executed=Class cannot be executed +invoke.completion.second.time.to.show.skipped.methods=Invoke completion second time to show skipped methods diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionConfidence.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionConfidence.java index 6a047bdb63fe..b00f3dcb37c2 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionConfidence.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionConfidence.java @@ -1,3 +1,15 @@ +/* + * 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 org.jetbrains.plugins.groovy.lang.completion; import com.intellij.codeInsight.completion.CompletionConfidence; diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java index f1837cff9dea..3fe6d901eb38 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionContributor.java @@ -15,6 +15,7 @@ */ package org.jetbrains.plugins.groovy.lang.completion; +import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; @@ -38,6 +39,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.HashMap; import com.intellij.util.containers.hash.HashSet; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.GroovyBundle; import org.jetbrains.plugins.groovy.GroovyIcons; import org.jetbrains.plugins.groovy.lang.completion.handlers.AfterNewClassInsertHandler; import org.jetbrains.plugins.groovy.lang.completion.handlers.ArrayInsertHandler; @@ -54,12 +56,15 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgument import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument; import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConstructorCall; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement; @@ -76,6 +81,7 @@ import java.util.Set; import static com.intellij.patterns.PlatformPatterns.psiElement; import static com.intellij.util.containers.CollectionFactory.hashMap; +import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*; import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipWhitespaces; /** @@ -212,15 +218,57 @@ public class GroovyCompletionContributor extends CompletionContributor { final PsiElement position = parameters.getPosition(); final PsiElement reference = position.getParent(); if (reference instanceof GrReferenceElement) { - final Map staticMembers = hashMap(); + final int invocationCount = parameters.getInvocationCount(); + final boolean secondCompletionInvoked = + CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION ? invocationCount > 0 : invocationCount > 1; + final String prefix = result.getPrefixMatcher().getPrefix(); + final boolean skipAccessors = !secondCompletionInvoked && !prefix.startsWith(GET_PREFIX) && + !prefix.startsWith(SET_PREFIX) && + !prefix.startsWith(IS_PREFIX); + + + result.restartCompletionOnPrefixChange(GET_PREFIX); + result.restartCompletionOnPrefixChange(SET_PREFIX); + result.restartCompletionOnPrefixChange(IS_PREFIX); + final Map staticMembers = hashMap(); ((GrReferenceElement)reference).processVariants(new Consumer() { public void consume(Object element) { final LookupElement lookupElement = element instanceof PsiClass ? GroovyCompletionUtil.createClassLookupItem((PsiClass)element) : GroovyCompletionUtil.getLookupElement(element); - final Object object = lookupElement.getObject(); - if ((object instanceof PsiMethod || object instanceof PsiField) && ((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) { + Object object = lookupElement.getObject(); + PsiSubstitutor substitutor = null; + if (object instanceof GroovyResolveResult) { + substitutor = ((GroovyResolveResult)object).getSubstitutor(); + object = ((GroovyResolveResult)object).getElement(); + } + + + //skip default groovy methods + if (!secondCompletionInvoked && + object instanceof GrGdkMethod && + GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor)) { + showInfo(); + return; + } + + //skip operator methods + if (!secondCompletionInvoked && + object instanceof PsiMethod && + GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName())) { + showInfo(); + return; + } + + //skip accessors if there is no get, set, is prefix + if (skipAccessors && object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) { + showInfo(); + return; + } + + if ((object instanceof PsiMethod || object instanceof PsiField) && + ((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) { if (lookupElement.getLookupString().equals(((PsiMember)object).getName())) { staticMembers.put((PsiModifierListOwner)object, lookupElement); return; @@ -252,7 +300,7 @@ public class GroovyCompletionContributor extends CompletionContributor { }); extend(CompletionType.SMART, AFTER_NEW, new CompletionProvider(false) { - public void addCompletions(@NotNull final CompletionParameters parameters, + protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext matchingContext, @NotNull final CompletionResultSet result) { final PsiElement identifierCopy = parameters.getPosition(); @@ -399,6 +447,11 @@ public class GroovyCompletionContributor extends CompletionContributor { }); } + private static void showInfo() { + CompletionService.getCompletionService() + .setAdvertisementText(GroovyBundle.message("invoke.completion.second.time.to.show.skipped.methods")); + } + private static StaticMemberProcessor completeStaticMembers(PsiElement position) { final StaticMemberProcessor processor = new StaticMemberProcessor(position) { @NotNull diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java index c46b1b737a53..3d4b95240da8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java @@ -18,7 +18,8 @@ package org.jetbrains.plugins.groovy.lang.completion; import com.intellij.codeInsight.CodeInsightUtilBase; import com.intellij.codeInsight.TailType; -import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.completion.AllClassesGetter; +import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.codeInsight.lookup.LookupItem; @@ -28,7 +29,6 @@ import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.highlighter.HighlighterIterator; import com.intellij.openapi.fileEditor.FileDocumentManager; -import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Iconable; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; @@ -36,19 +36,19 @@ import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.impl.light.LightMethodBuilder; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; +import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiFormatUtil; -import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.CollectionFactory; +import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.GroovyIcons; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; @@ -58,9 +58,9 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement; import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClassTypeElement; @@ -71,6 +71,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import java.util.List; +import java.util.Set; import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils.*; @@ -230,9 +231,16 @@ public class GroovyCompletionUtil { } } } - else if (context instanceof GrMethodCallExpression && element instanceof PsiMethod) { - final PsiMethod method = generateMethodInCategory(candidate); - result.add(setupLookupBuilder(method, candidate.getSubstitutor(), LookupElementBuilder.create((PsiNamedElement)element))); + else if (element instanceof PsiMethod) { + final PsiMethod method; + if (ResolveUtil.isInUseScope(candidate)) { + method = generateMethodInCategory(candidate); + } + else { + method = (PsiMethod)element; + } + result.add(setupLookupBuilder(method, candidate.getSubstitutor(), LookupElementBuilder.create(candidate, + ((PsiMethod)element).getName()))); continue; } if (element instanceof PsiClass) { @@ -258,7 +266,7 @@ public class GroovyCompletionUtil { final PsiElement element = resolveResult.getElement(); assert element != null; final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); - LookupElementBuilder builder = LookupElementBuilder.create(element, importedName).setPresentableText(importedName); + LookupElementBuilder builder = LookupElementBuilder.create(resolveResult, importedName).setPresentableText(importedName); return setupLookupBuilder(element, substitutor, builder); } @@ -456,4 +464,64 @@ public class GroovyCompletionUtil { } return TailType.insertChar(editor, offset, ')'); } + + private static final Set COLLECTION_METHOD_NAMES = new HashSet(); + public static final Set OPERATOR_METHOD_NAMES = new HashSet(); + static { + COLLECTION_METHOD_NAMES.add("each"); + COLLECTION_METHOD_NAMES.add("any"); + COLLECTION_METHOD_NAMES.add("every"); + COLLECTION_METHOD_NAMES.add("reverseEach"); + COLLECTION_METHOD_NAMES.add("collect"); + COLLECTION_METHOD_NAMES.add("collectAll"); + COLLECTION_METHOD_NAMES.add("find"); + COLLECTION_METHOD_NAMES.add("findAll"); + COLLECTION_METHOD_NAMES.add("retainAll"); + COLLECTION_METHOD_NAMES.add("removeAll"); + COLLECTION_METHOD_NAMES.add("split"); + COLLECTION_METHOD_NAMES.add("groupBy"); + COLLECTION_METHOD_NAMES.add("groupEntriesBy"); + COLLECTION_METHOD_NAMES.add("findLastIndexOf"); + COLLECTION_METHOD_NAMES.add("findIndexValues"); + COLLECTION_METHOD_NAMES.add("findIndexOf"); + + OPERATOR_METHOD_NAMES.add("plus"); + OPERATOR_METHOD_NAMES.add("minus"); + OPERATOR_METHOD_NAMES.add("multiply"); + OPERATOR_METHOD_NAMES.add("power"); + OPERATOR_METHOD_NAMES.add("div"); + OPERATOR_METHOD_NAMES.add("mod"); + OPERATOR_METHOD_NAMES.add("or"); + OPERATOR_METHOD_NAMES.add("and"); + OPERATOR_METHOD_NAMES.add("xor"); + OPERATOR_METHOD_NAMES.add("next"); + OPERATOR_METHOD_NAMES.add("previous"); + OPERATOR_METHOD_NAMES.add("getAt"); + OPERATOR_METHOD_NAMES.add("putAt"); + OPERATOR_METHOD_NAMES.add("leftShift"); + OPERATOR_METHOD_NAMES.add("rightShift"); + OPERATOR_METHOD_NAMES.add("isCase"); + OPERATOR_METHOD_NAMES.add("bitwiseNegate"); + OPERATOR_METHOD_NAMES.add("negative"); + OPERATOR_METHOD_NAMES.add("positive"); + } + + + + public static boolean skipDefGroovyMethod(GrGdkMethod gdkMethod, PsiSubstitutor substitutor) { + String name = gdkMethod.getStaticMethod().getName(); + + final PsiType baseType = gdkMethod.getStaticMethod().getParameterList().getParameters()[0].getType(); + if (!TypeConversionUtil.erasure(baseType).equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return false; + + final PsiType type = substitutor != null ? substitutor.substitute(baseType) : baseType; + + if (COLLECTION_METHOD_NAMES.contains(name)) { + return !(type instanceof PsiArrayType) && !InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE); + } + if ("with".equals(name)) return false; + + return true; + } + } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java index c78a6cdbf5fa..d37cc837b01f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java @@ -31,6 +31,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression; @@ -53,6 +54,11 @@ public class GroovyInsertHandler implements InsertHandler { public void handleInsert(InsertionContext context, LookupElement item) { @NonNls Object obj = item.getObject(); + + if (obj instanceof GroovyResolveResult) { + obj = ((GroovyResolveResult)obj).getElement(); + } + if (obj instanceof PsiMethod) { PsiMethod method = (PsiMethod)obj; PsiParameter[] parameters = method.getParameterList().getParameters(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java index 26927378888a..6321909f292e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovySmartCompletionContributor.java @@ -41,6 +41,7 @@ import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; @@ -104,9 +105,13 @@ public class GroovySmartCompletionContributor extends CompletionContributor { else { o = variant; } + if (o instanceof PsiElement) { type = getTypeByElement((PsiElement)o, position); } + else if (o instanceof GroovyResolveResult) { + type = getTypeByElement(((GroovyResolveResult)o).getElement(), position); + } else if (o instanceof String) { if ("true".equals(o) || "false".equals(o)) { type = PsiType.BOOLEAN; @@ -115,7 +120,8 @@ public class GroovySmartCompletionContributor extends CompletionContributor { if (type == null) return; for (TypeConstraint info : infos) { if (info.satisfied(type, position.getManager(), GlobalSearchScope.allScope(position.getProject()))) { - final LookupElement lookupElement = GroovyCompletionUtil.getLookupElement(o); + final LookupElement lookupElement = + variant instanceof LookupElement ? (LookupElement)variant : GroovyCompletionUtil.getLookupElement(o); result.addElement(lookupElement); break; } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java index ed86ba86d856..d4a2ca48e021 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java @@ -34,7 +34,7 @@ import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl; import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil; import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrCallImpl; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; -import org.jetbrains.plugins.groovy.lang.resolve.NonCodeMembersContributor; +import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor; /** @@ -90,8 +90,7 @@ public class GrConstructorInvocationImpl extends GrCallImpl implements GrConstru MethodResolverProcessor processor = new MethodResolverProcessor(clazz.getName(), this, true, thisType, argTypes, PsiType.EMPTY_ARRAY, allVariants); clazz.processDeclarations(processor, ResolveState.initial().put(PsiSubstitutor.KEY, substitutor), null, this); - - NonCodeMembersContributor.runContributors(thisType, processor, this, ResolveState.initial()); + ResolveUtil.processNonCodeMethods(thisType, processor, this); return processor.getCandidates(); } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java index b3d4a4ca9332..9d9a89f8cb8f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java @@ -33,9 +33,9 @@ import java.beans.Introspector; * @author ilyas */ public class GroovyPropertyUtils { - private static final String IS_PREFIX = "is"; - private static final String GET_PREFIX = "get"; - private static final String SET_PREFIX = "set"; + public static final String IS_PREFIX = "is"; + public static final String GET_PREFIX = "get"; + public static final String SET_PREFIX = "set"; private GroovyPropertyUtils() { } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/completion/CompletionTestBase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/completion/CompletionTestBase.java index 136fca83e5e0..819bbe6ccc44 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/completion/CompletionTestBase.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/completion/CompletionTestBase.java @@ -9,6 +9,7 @@ import com.intellij.psi.PsiMember; import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.plugins.groovy.CompositeCompletionData; +import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.util.TestUtils; @@ -51,7 +52,7 @@ public abstract class CompletionTestBase extends JavaCodeInsightFixtureTestCase @Override public boolean value(LookupElement lookupElement) { final Object o = lookupElement.getObject(); - return !(o instanceof PsiMember) && !(o instanceof GrVariable); + return !(o instanceof PsiMember) && !(o instanceof GrVariable) && !(o instanceof GroovyResolveResult); } }); } From 58e7cb661ac31badc58155792b8fa5cfb0743992 Mon Sep 17 00:00:00 2001 From: irengrig Date: Mon, 8 Nov 2010 13:22:16 +0300 Subject: [PATCH 08/61] git log: - linked list --- .../history/browser/GitTreeController.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/git4idea/src/git4idea/history/browser/GitTreeController.java b/plugins/git4idea/src/git4idea/history/browser/GitTreeController.java index 23cb9c4a49a4..b15eaf8f061f 100644 --- a/plugins/git4idea/src/git4idea/history/browser/GitTreeController.java +++ b/plugins/git4idea/src/git4idea/history/browser/GitTreeController.java @@ -34,6 +34,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Alarm; import com.intellij.util.Consumer; import com.intellij.util.Processor; +import com.intellij.util.SmartList; import com.intellij.util.containers.SLRUCache; import git4idea.GitVcs; import git4idea.changes.GitChangeUtils; @@ -158,8 +159,8 @@ class GitTreeController implements ManageGitTreeView { private void loadCommitsUsingMemoryAndNativeFilters(final Collection startingPoints, final Pair beforePoint, final Date afterPoint, final Collection filters, final int maxCnt) throws VcsException { assert maxCnt > 0; - final List memoryFilters = new LinkedList(); - final List commandFilters = new LinkedList(); + final List memoryFilters = new SmartList(); + final List commandFilters = new SmartList(); for (ChangesFilter.Filter filter : filters) { final ChangesFilter.CommandParametersFilter commandFilter = filter.getCommandParametersFilter(); if (commandFilter == null) { @@ -319,8 +320,8 @@ class GitTreeController implements ManageGitTreeView { } private void loadTagsNBranches() { - final List branches = new LinkedList(); - final List tags = new LinkedList(); + final List branches = new ArrayList(); + final List tags = new ArrayList(); try { myAccess.loadAllBranches(branches); @@ -381,7 +382,7 @@ class GitTreeController implements ManageGitTreeView { myAlarm.addRequest(new Runnable() { public void run() { // start from beginning - final List> wayList = new LinkedList>(); + final List> wayList = new SmartList>(); while (true) { final Pair startFrom = wayList.isEmpty() ? null : wayList.get(wayList.size() - 1); @@ -438,7 +439,7 @@ class GitTreeController implements ManageGitTreeView { final Application application = ApplicationManager.getApplication(); myAlarm.addRequest(new Runnable() { public void run() { - final List loaded = new LinkedList(); + final List loaded = new ArrayList(); final Set requested = new HashSet(hashes.size()); for (SHAHash hash : hashes) { requested.add(GitChangeUtils.longForSHAHash(hash.getValue())); @@ -483,11 +484,11 @@ class GitTreeController implements ManageGitTreeView { } public List getAllBranchesOrdered() { - return new ArrayList(myBranches.get()); + return Collections.unmodifiableList(myBranches.get()); } public List getAllTagsOrdered() { - return new ArrayList(myTags.get()); + return Collections.unmodifiableList(myTags.get()); } public boolean isInitialized() { @@ -566,7 +567,7 @@ class GitTreeController implements ManageGitTreeView { myLock = new Object(); myStartingPoints = new HashSet(); myFilters = new HashSet(); - myContinuationPoints = new LinkedList>(); + myContinuationPoints = new SmartList>(); } public boolean isDirty() { From 47fe060c9262ade4a3afcf439428eae6df372150 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 8 Nov 2010 14:51:46 +0300 Subject: [PATCH 09/61] clear client properties for popup on disposal - memleak --- .../src/com/intellij/ui/popup/PopupComponent.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java index 94b4bbbdee29..aaa7ebeaf936 100644 --- a/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java +++ b/platform/platform-impl/src/com/intellij/ui/popup/PopupComponent.java @@ -23,6 +23,8 @@ import com.intellij.util.ui.UIUtil; import javax.swing.*; import java.awt.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; public interface PopupComponent { @@ -144,6 +146,14 @@ public interface PopupComponent { public void hide(boolean dispose) { myPopup.hide(); + + Window wnd = getWindow(); + if (wnd instanceof JWindow) { + JRootPane rootPane = ((JWindow)wnd).getRootPane(); + if (rootPane != null) { + ReflectionUtil.resetField(rootPane, "clientProperties"); + } + } } public void show() { From a874564d03ca3d2a85b4837ad7a35dfdb3510f28 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Mon, 8 Nov 2010 14:56:38 +0300 Subject: [PATCH 10/61] Massive LinkedList->ArrayList migration, using short buffer for string parsed from git log (so we don't retain whole 32K log output holding just branch name). --- .../git4idea/src/git4idea/GitReference.java | 2 +- plugins/git4idea/src/git4idea/GitTag.java | 2 +- plugins/git4idea/src/git4idea/GitUtil.java | 2 +- .../git4idea/actions/GitRepositoryAction.java | 7 ++-- .../src/git4idea/changes/GitChangeUtils.java | 2 +- .../changes/GitOutgoingChangesProvider.java | 2 +- .../src/git4idea/commands/GitHandler.java | 2 +- .../src/git4idea/history/GitLogParser.java | 4 +-- .../src/git4idea/history/GitLogRecord.java | 36 +++++++++++-------- .../git4idea/history/GitUsersComponent.java | 4 +-- .../history/browser/ChangesFilter.java | 6 ++-- .../history/browser/CherryPicker.java | 6 ++-- .../history/browser/GitLogHelper.java | 2 +- .../git4idea/history/browser/GitLogTree.java | 6 ++-- .../history/browser/LowLevelAccessImpl.java | 12 +++---- .../src/git4idea/history/browser/Portion.java | 6 ++-- .../history/wholeTree/LoaderImpl.java | 2 +- .../history/wholeTree/TreeSkeletonImpl.java | 2 +- .../src/git4idea/ui/CurrentBranchDialog.java | 4 +-- .../src/git4idea/vfs/GitIgnoreTracker.java | 7 ++-- .../org/jetbrains/git4idea/ssh/SSHConfig.java | 6 ++-- 21 files changed, 67 insertions(+), 55 deletions(-) diff --git a/plugins/git4idea/src/git4idea/GitReference.java b/plugins/git4idea/src/git4idea/GitReference.java index 66b960e655bc..5025d5b23f10 100644 --- a/plugins/git4idea/src/git4idea/GitReference.java +++ b/plugins/git4idea/src/git4idea/GitReference.java @@ -37,7 +37,7 @@ public abstract class GitReference implements Comparable { * @param name the used name */ public GitReference(@NotNull String name) { - myName = name; + myName = new String(name); } /** diff --git a/plugins/git4idea/src/git4idea/GitTag.java b/plugins/git4idea/src/git4idea/GitTag.java index acc607b96661..be875f1af791 100644 --- a/plugins/git4idea/src/git4idea/GitTag.java +++ b/plugins/git4idea/src/git4idea/GitTag.java @@ -76,7 +76,7 @@ public class GitTag extends GitReference { if (line.length() == 0) { continue; } - tags.add(line); + tags.add(new String(line)); } } diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java index b131efa0b8fb..45b6bddfb3c1 100644 --- a/plugins/git4idea/src/git4idea/GitUtil.java +++ b/plugins/git4idea/src/git4idea/GitUtil.java @@ -713,7 +713,7 @@ public class GitUtil { if (file == null || path.length == 0) return null; VirtualFile current = file; - final List backTrace = new LinkedList(); + final List backTrace = new ArrayList(); int idx = path.length - 1; while (current != null) { if (SystemInfo.isFileSystemCaseSensitive ? current.getName().equals(path[idx]) : current.getName().equalsIgnoreCase(path[idx])) { diff --git a/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java b/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java index b48d47c575e3..ff3a683a9c5c 100644 --- a/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java +++ b/plugins/git4idea/src/git4idea/actions/GitRepositoryAction.java @@ -35,7 +35,10 @@ import git4idea.i18n.GitBundle; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; /** * Base class for actions that affect the entire git repository. @@ -45,7 +48,7 @@ public abstract class GitRepositoryAction extends DumbAwareAction { /** * The task delayed until end of the primary action. These tasks happen after repository refresh. */ - final LinkedList myDelayedTasks = new LinkedList(); + final List myDelayedTasks = new ArrayList(); /** * {@inheritDoc} diff --git a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java index 7b88a704648f..a317c3e77027 100644 --- a/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java +++ b/plugins/git4idea/src/git4idea/changes/GitChangeUtils.java @@ -122,7 +122,7 @@ public class GitChangeUtils { } public static Collection parseDiffForPaths(final String rootPath, final StringScanner s) throws VcsException { - final Collection result = new LinkedList(); + final Collection result = new ArrayList(); while (s.hasMoreData()) { if (s.isEol()) { diff --git a/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java b/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java index 81fa4983cf8c..78bb134f20f6 100644 --- a/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java +++ b/plugins/git4idea/src/git4idea/changes/GitOutgoingChangesProvider.java @@ -98,7 +98,7 @@ public class GitOutgoingChangesProvider implements VcsOutgoingChangesProvider result = new ArrayList(revisions); for (Iterator iterator = result.iterator(); iterator.hasNext();) { final U t = iterator.next(); - final LinkedList branches = new LinkedList(); + final List branches = new ArrayList(); // we do not use passed revision convertor since it returns just recent commit on repo final VcsRevisionNumber revision = GitHistoryUtils.getCurrentRevision(myProject, filePatchConvertor.convert(t), null); if (revision == null) continue; // will be true for new files; they are anyway outgoing diff --git a/plugins/git4idea/src/git4idea/commands/GitHandler.java b/plugins/git4idea/src/git4idea/commands/GitHandler.java index 9e39a986c89b..d3f11f0e021b 100644 --- a/plugins/git4idea/src/git4idea/commands/GitHandler.java +++ b/plugins/git4idea/src/git4idea/commands/GitHandler.java @@ -48,7 +48,7 @@ public abstract class GitHandler { protected final GitCommand myCommand; private final HashSet myIgnoredErrorCodes = new HashSet(); // Error codes that are ignored for the handler - private final List myErrors = Collections.synchronizedList(new LinkedList()); + private final List myErrors = Collections.synchronizedList(new ArrayList()); private static final Logger log = Logger.getInstance(GitHandler.class.getName()); final GeneralCommandLine myCommandLine; @SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) diff --git a/plugins/git4idea/src/git4idea/history/GitLogParser.java b/plugins/git4idea/src/git4idea/history/GitLogParser.java index face9e3b0bd6..1d226a19aca2 100644 --- a/plugins/git4idea/src/git4idea/history/GitLogParser.java +++ b/plugins/git4idea/src/git4idea/history/GitLogParser.java @@ -161,10 +161,10 @@ class GitLogParser { line = infoAndPath[0]; if (infoAndPath.length > 1) { // taking the last element, thus avoiding possible blank line - final List nameAndPathSplit = new LinkedList(Arrays.asList(infoAndPath[infoAndPath.length-1].split("[\\s]"))); + final List nameAndPathSplit = new ArrayList(Arrays.asList(infoAndPath[infoAndPath.length - 1].split("[\\s]"))); // not relying that separator is tab => so splitting by any whitespace. // Then removing blank (or whitespace) lines which could appear by this splitting: - for (Iterator it = nameAndPathSplit.iterator(); it.hasNext(); ) { + for (Iterator it = nameAndPathSplit.iterator(); it.hasNext();) { if (it.next().trim().isEmpty()) { it.remove(); } diff --git a/plugins/git4idea/src/git4idea/history/GitLogRecord.java b/plugins/git4idea/src/git4idea/history/GitLogRecord.java index 240ef0318d01..5d2f34aa6199 100644 --- a/plugins/git4idea/src/git4idea/history/GitLogRecord.java +++ b/plugins/git4idea/src/git4idea/history/GitLogRecord.java @@ -70,15 +70,19 @@ class GitLogRecord { return res; } + private String lookup(GitLogParser.GitLogOption key) { + return shortBuffer(myOptions.get(key)); + } + // trivial access methods - String getHash() { return myOptions.get(HASH); } - String getShortHash() { return myOptions.get(SHORT_HASH); } - String getAuthorName() { return myOptions.get(AUTHOR_NAME); } - String getAuthorEmail() { return myOptions.get(AUTHOR_EMAIL); } - String getCommitterName() { return myOptions.get(COMMITTER_NAME); } - String getCommitterEmail() { return myOptions.get(COMMITTER_EMAIL); } - String getSubject() { return myOptions.get(SUBJECT); } - String getBody() { return myOptions.get(BODY); } + String getHash() { return lookup(HASH); } + String getShortHash() { return lookup(SHORT_HASH); } + String getAuthorName() { return lookup(AUTHOR_NAME); } + String getAuthorEmail() { return lookup(AUTHOR_EMAIL); } + String getCommitterName() { return lookup(COMMITTER_NAME); } + String getCommitterEmail() { return lookup(COMMITTER_EMAIL); } + String getSubject() { return lookup(SUBJECT); } + String getBody() { return lookup(BODY); } // access methods with some formatting or conversion @@ -101,11 +105,11 @@ class GitLogRecord { } String[] getParentsShortHashes() { - return myOptions.get(SHORT_PARENTS).split(" "); + return lookup(SHORT_PARENTS).split(" "); } String[] getParentsHashes() { - return myOptions.get(PARENTS).split(" "); + return lookup(PARENTS).split(" "); } /** @@ -117,17 +121,17 @@ class GitLogRecord { Pair, List> getTagsAndBranches(Collection allBranchesSet) { final String decorate = myOptions.get(REF_NAMES); final String[] refNames = parseRefNames(decorate); - final List tags = refNames.length > 0 ? new LinkedList() : Collections.emptyList(); - final List branches = refNames.length > 0 ? new LinkedList() : Collections.emptyList(); + final List tags = refNames.length > 0 ? new ArrayList() : Collections.emptyList(); + final List branches = refNames.length > 0 ? new ArrayList() : Collections.emptyList(); for (String refName : refNames) { if (allBranchesSet.contains(refName)) { // also some gits can return ref name twice (like (HEAD, HEAD), so check we will show it only once) if (!branches.contains(refName)) { - branches.add(refName); + branches.add(shortBuffer(refName)); } } else { if (!tags.contains(refName)) { - tags.add(refName); + tags.add(shortBuffer(refName)); } } } @@ -142,4 +146,8 @@ class GitLogRecord { return refs.split(", "); } + private static String shortBuffer(String raw) { + return new String(raw); + } + } diff --git a/plugins/git4idea/src/git4idea/history/GitUsersComponent.java b/plugins/git4idea/src/git4idea/history/GitUsersComponent.java index 2d02aa2071a3..2411513bc72e 100644 --- a/plugins/git4idea/src/git4idea/history/GitUsersComponent.java +++ b/plugins/git4idea/src/git4idea/history/GitUsersComponent.java @@ -174,7 +174,7 @@ public class GitUsersComponent { private boolean myStartReached; private UsersData() { - myUsers = new LinkedList(); + myUsers = new ArrayList(); final long now = System.currentTimeMillis(); myCloserDate = new UpdatedReference(now); myEarlierDate = new UpdatedReference(now + 1); @@ -327,7 +327,7 @@ public class GitUsersComponent { final long earlierUpdate = in.readLong(); data.setEarlierDate(new UpdatedReference(earlierDate, earlierUpdate)); - final List users = new LinkedList(); + final List users = new ArrayList(); final int size = in.readInt(); for (int i = 0; i < size; i++) { users.add(in.readUTF()); diff --git a/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java b/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java index bd692c40ce6a..3f3cd75ce51b 100644 --- a/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java +++ b/plugins/git4idea/src/git4idea/history/browser/ChangesFilter.java @@ -36,7 +36,7 @@ public class ChangesFilter { private MemoryFilter myResult; protected Merger() { - myFilters = new LinkedList(); + myFilters = new ArrayList(); } protected abstract boolean acceptImpl(MemoryFilter filter); @@ -81,7 +81,7 @@ public class ChangesFilter { final Merger[] mergers = {new UsersMerger()}; if (filters.isEmpty()) return Collections.emptyList(); - final List result = new LinkedList(); + final List result = new ArrayList(); for (Filter filter : filters) { boolean taken = false; for (Merger combiner : mergers) { @@ -361,7 +361,7 @@ public class ChangesFilter { // todo optimization here public boolean addPath(final VirtualFile vf) { final Collection filesWeAlreadyHave = myMap.values(); - final Collection childrenToRemove = new LinkedList(); + final Collection childrenToRemove = new ArrayList(); for (VirtualFile current : filesWeAlreadyHave) { if (current.equals(vf)) return false; // doesnt add exact same if (VfsUtil.isAncestor(vf, current, false)) { diff --git a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java index cf9b6b1c6502..4aa724e8442b 100644 --- a/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java +++ b/plugins/git4idea/src/git4idea/history/browser/CherryPicker.java @@ -51,10 +51,10 @@ public class CherryPicker { myListsCache = listsCache; myAccess = access; - myExceptions = new LinkedList(); - myWarnings = new LinkedList(); + myExceptions = new ArrayList(); + myWarnings = new ArrayList(); - myDirtyFiles = new LinkedList(); + myDirtyFiles = new ArrayList(); myMessagesInOrder = new ArrayList(hashes.size()); myFilesToMove = new HashMap>(); } diff --git a/plugins/git4idea/src/git4idea/history/browser/GitLogHelper.java b/plugins/git4idea/src/git4idea/history/browser/GitLogHelper.java index fa6f1fed1d33..9e88a0b5d346 100644 --- a/plugins/git4idea/src/git4idea/history/browser/GitLogHelper.java +++ b/plugins/git4idea/src/git4idea/history/browser/GitLogHelper.java @@ -30,7 +30,7 @@ public class GitLogHelper { @NotNull public Portion loadPortion(final Collection startingPoints, final Date beforePoint, final Date afterPoint, final Collection filtersIn, int maxCnt, List branches) throws VcsException { - final Collection filters = new LinkedList(filtersIn); + final Collection filters = new ArrayList(filtersIn); if (beforePoint != null) { filters.add(new ChangesFilter.BeforeDate(new Date(beforePoint.getTime() - 1))); } diff --git a/plugins/git4idea/src/git4idea/history/browser/GitLogTree.java b/plugins/git4idea/src/git4idea/history/browser/GitLogTree.java index 7c8491bc0e21..5e53324d1d5a 100644 --- a/plugins/git4idea/src/git4idea/history/browser/GitLogTree.java +++ b/plugins/git4idea/src/git4idea/history/browser/GitLogTree.java @@ -114,7 +114,7 @@ public class GitLogTree implements GitTreeViewI { myMainSplitter.setDividerWidth(3); myFiltersSplitter.setDividerWidth(3); - myInitWaiters = new LinkedList(); + myInitWaiters = new ArrayList(); myCommitsList = new JBList(); myController.init(); } @@ -1547,7 +1547,7 @@ public class GitLogTree implements GitTreeViewI { if (wasEmpty) { myFiltering.addFilter(myFilter); } else { - final List toRemove = new LinkedList(); + final List toRemove = new ArrayList(); for (StructureNode child : getChildren()) { final VirtualFile file = child.getFile(); if (! myFilter.containsFile(file)) { @@ -1657,7 +1657,7 @@ public class GitLogTree implements GitTreeViewI { myText = text; myType = type; myIcon = icon; - myChildren = myAllowsChildren ? new LinkedList() : Collections.emptyList(); + myChildren = myAllowsChildren ? new ArrayList() : Collections.emptyList(); myDescriptor = new PresentableNodeDescriptor(myProject, myParent == null ? null : myParent.getDescriptor()) { @Override public PresentableNodeDescriptor getChildToHighlightAt(int index) { diff --git a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java index 6e19dce17cf1..f2239f97b56c 100644 --- a/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java +++ b/plugins/git4idea/src/git4idea/history/browser/LowLevelAccessImpl.java @@ -50,7 +50,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { @NotNull final Collection endPoints, @NotNull final Collection filters, int useMaxCnt) throws VcsException { - final List parameters = new LinkedList(); + final List parameters = new ArrayList(); if (useMaxCnt > 0) { parameters.add("--max-count=" + useMaxCnt); } @@ -76,7 +76,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { public Runnable loadHashesWithParents(final @NotNull Collection startingPoints, @NotNull final Collection filters, final Consumer consumer) throws VcsException { - final List parameters = new LinkedList(); + final List parameters = new ArrayList(); for (ChangesFilter.Filter filter : filters) { filter.getCommandParametersFilter().applyToCommandLine(parameters); } @@ -101,7 +101,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { public void loadCommits(final Collection startingPoints, final Date beforePoint, final Date afterPoint, final Collection filtersIn, final Consumer consumer, int maxCnt, List branches) throws VcsException { - final Collection filters = new LinkedList(filtersIn); + final Collection filters = new ArrayList(filtersIn); if (beforePoint != null) { filters.add(new ChangesFilter.BeforeDate(new Date(beforePoint.getTime() - 1))); } @@ -136,7 +136,7 @@ public class LowLevelAccessImpl implements LowLevelAccess { @NotNull final Consumer consumer, final Collection branches, int useMaxCnt) throws VcsException { - final List parameters = new LinkedList(); + final List parameters = new ArrayList(); if (useMaxCnt > 0) { parameters.add("--max-count=" + (useMaxCnt + 1)); } @@ -166,14 +166,14 @@ public class LowLevelAccessImpl implements LowLevelAccess { } public Collection getBranchesWithCommit(final SHAHash hash) throws VcsException { - final List result = new LinkedList(); + final List result = new ArrayList(); GitBranch.listAsStrings(myProject, myRoot, false, true, result, hash.getValue()); GitBranch.listAsStrings(myProject, myRoot, true, false, result, hash.getValue()); return result; } public Collection getTagsWithCommit(final SHAHash hash) throws VcsException { - final List result = new LinkedList(); + final List result = new ArrayList(); GitTag.listAsStrings(myProject, myRoot, result, hash.getValue()); return result; } diff --git a/plugins/git4idea/src/git4idea/history/browser/Portion.java b/plugins/git4idea/src/git4idea/history/browser/Portion.java index fc9968f5c764..ed9b0cc46293 100644 --- a/plugins/git4idea/src/git4idea/history/browser/Portion.java +++ b/plugins/git4idea/src/git4idea/history/browser/Portion.java @@ -49,10 +49,10 @@ public class Portion implements AsynchConsumer { myNameToHash = new HashMap(); myHolder = new HashMap(); - myOrdered = new LinkedList(); + myOrdered = new ArrayList(); - myRoots = new LinkedList(); - myLeafs = new LinkedList(); + myRoots = new ArrayList(); + myLeafs = new ArrayList(); myOrphanMap = new MultiMap(); myUsers = new HashSet(); diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/LoaderImpl.java b/plugins/git4idea/src/git4idea/history/wholeTree/LoaderImpl.java index 7d6676d89731..2aa296231365 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/LoaderImpl.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/LoaderImpl.java @@ -160,7 +160,7 @@ public class LoaderImpl implements Loader { myTreeComposite.clearMembers(); - final List endOfTheList = new LinkedList(); + final List endOfTheList = new ArrayList(); final Consumer consumer = createCommitsHolderConsumer(drawHierarchy); final RefreshingCommitsPackConsumer listConsumer = new RefreshingCommitsPackConsumer(current, consumer); diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/TreeSkeletonImpl.java b/plugins/git4idea/src/git4idea/history/wholeTree/TreeSkeletonImpl.java index b3fe3da345f0..b03fe528f40b 100644 --- a/plugins/git4idea/src/git4idea/history/wholeTree/TreeSkeletonImpl.java +++ b/plugins/git4idea/src/git4idea/history/wholeTree/TreeSkeletonImpl.java @@ -44,7 +44,7 @@ public class TreeSkeletonImpl implements TreeSkeleton { assert (size2Power < 16) && (wireEventsIdxSize2Power < 16) && (size2Power > 1) && (wireEventsIdxSize2Power > 1); myList = new BigArray(size2Power); - myWireEvents = new LinkedList(); // todo can use another structure, a list of arrays? + myWireEvents = new ArrayList(); // todo can use another structure, a list of arrays? myWiresIndex = new WiresIndex(wireEventsIdxSize2Power); myAsCommitList = new ReadonlyList() { @Override diff --git a/plugins/git4idea/src/git4idea/ui/CurrentBranchDialog.java b/plugins/git4idea/src/git4idea/ui/CurrentBranchDialog.java index 0a5b1adcb2e2..e779d08fdd02 100644 --- a/plugins/git4idea/src/git4idea/ui/CurrentBranchDialog.java +++ b/plugins/git4idea/src/git4idea/ui/CurrentBranchDialog.java @@ -26,7 +26,7 @@ import git4idea.i18n.GitBundle; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; /** @@ -68,7 +68,7 @@ public class CurrentBranchDialog extends DialogWrapper { /** * The branches to merge */ - private final List myBranches = new LinkedList(); + private final List myBranches = new ArrayList(); /** * The repository tracked for the current branch */ diff --git a/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java b/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java index 8ceb2f769fda..0e3f4ebb2057 100644 --- a/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java +++ b/plugins/git4idea/src/git4idea/vfs/GitIgnoreTracker.java @@ -31,7 +31,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; -import java.util.LinkedList; +import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.Set; @@ -341,10 +342,10 @@ public class GitIgnoreTracker { */ private void checkExcludeFile(VirtualFile file) { String path = file.getPath(); - LinkedList toDirty = null; + List toDirty = null; synchronized (myExcludeFiles) { if (myExcludeFilesPaths.contains(path)) { - toDirty = new LinkedList(); + toDirty = new ArrayList(); for (Map.Entry entry : myExcludeFiles.entrySet()) { if (path.equals(entry.getValue())) { toDirty.add(entry.getKey()); diff --git a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java index 14c4b3b65822..00a065da7114 100644 --- a/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java +++ b/plugins/git4idea/src/org/jetbrains/git4idea/ssh/SSHConfig.java @@ -158,7 +158,7 @@ public class SSHConfig { host.myPort = parseInt(argument); } else if ("PreferredAuthentications".equalsIgnoreCase(keyword)) { - final LinkedList list = parseList(argument); + final List list = parseList(argument); list.retainAll(ALLOWED_METHODS); if (!list.isEmpty()) { host.myPreferredMethods = Collections.unmodifiableList(list); @@ -254,8 +254,8 @@ public class SSHConfig { return "yes".equals(value); } - private static LinkedList parseList(final String arg) { - LinkedList values = new LinkedList(); + private static List parseList(final String arg) { + List values = new ArrayList(); for (String a : arg.split("[ \t,]+")) { if (a.length() == 0) { continue; From 543faae15aabccb3eec68827d58caf5b154f7ca7 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 8 Nov 2010 15:05:26 +0300 Subject: [PATCH 11/61] IDEA-60555 increase a timeout of executing operations on android device --- .../android/src/org/jetbrains/android/util/AndroidUtils.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java b/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java index e722e92751b8..c66569c778c0 100644 --- a/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java +++ b/plugins/android/src/org/jetbrains/android/util/AndroidUtils.java @@ -119,6 +119,8 @@ public class AndroidUtils { public static final String EXT_NATIVE_LIB = "so"; @NonNls public static final String RES_OVERLAY_DIR_NAME = "res-overlay"; + private static final int TIMEOUT = 30000; + private AndroidUtils() { } @@ -345,7 +347,7 @@ public class AndroidUtils { device.executeShellCommand(command, receiver, 0); } else { - device.executeShellCommand(command, receiver); + device.executeShellCommand(command, receiver, TIMEOUT); } if (infinite && !receiver.isCancelled()) { attempt++; From 5350e844208c9cb34ed5629f58bfbf87a6b97b7b Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 8 Nov 2010 15:48:04 +0300 Subject: [PATCH 12/61] IDEA-60543 error indication in project file for AndroidManifest.xml and resource files --- plugins/android/src/META-INF/plugin.xml | 1 + .../AndroidProblemFileHighlightingFilter.java | 51 +++++++++++++++++++ .../resourceManagers/ResourceManager.java | 17 +++++-- 3 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 plugins/android/src/org/jetbrains/android/AndroidProblemFileHighlightingFilter.java diff --git a/plugins/android/src/META-INF/plugin.xml b/plugins/android/src/META-INF/plugin.xml index cf98c409a0bc..d367db87fe0b 100644 --- a/plugins/android/src/META-INF/plugin.xml +++ b/plugins/android/src/META-INF/plugin.xml @@ -137,6 +137,7 @@ + diff --git a/plugins/android/src/org/jetbrains/android/AndroidProblemFileHighlightingFilter.java b/plugins/android/src/org/jetbrains/android/AndroidProblemFileHighlightingFilter.java new file mode 100644 index 000000000000..3711c925ba59 --- /dev/null +++ b/plugins/android/src/org/jetbrains/android/AndroidProblemFileHighlightingFilter.java @@ -0,0 +1,51 @@ +/* + * 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 org.jetbrains.android; + +import com.android.sdklib.SdkConstants; +import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.android.facet.AndroidFacet; +import org.jetbrains.android.resourceManagers.ResourceManager; + +/** + * @author Eugene.Kudelevsky + */ +public class AndroidProblemFileHighlightingFilter implements Condition { + private final Project myProject; + + public AndroidProblemFileHighlightingFilter(Project project) { + myProject = project; + } + + @Override + public boolean value(VirtualFile file) { + if (file.getFileType() != StdFileTypes.XML) { + return false; + } + if (SdkConstants.FN_ANDROID_MANIFEST_XML.equals(file.getName())) { + Module module = ModuleUtil.findModuleForFile(file, myProject); + return module != null && AndroidFacet.getInstance(module) != null; + } + + VirtualFile parent = file.getParent(); + if (parent == null) return false; + parent = parent.getParent(); + if (parent == null) return false; + return ResourceManager.isResourceDirectory(parent, myProject); + } +} diff --git a/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java b/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java index 32ae1e47a73a..2faaaac0478d 100644 --- a/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java +++ b/plugins/android/src/org/jetbrains/android/resourceManagers/ResourceManager.java @@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtil; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; @@ -332,13 +333,21 @@ public abstract class ResourceManager { return dir != null && isResourceDirectory(dir); } + public static boolean isResourceDirectory(VirtualFile dir, Project project) { + Module module = ModuleUtil.findModuleForFile(dir, project); + if (module != null) { + AndroidFacet facet = AndroidFacet.getInstance(module); + return facet != null && facet.getLocalResourceManager().isResourceDir(dir); + } + return false; + } + public static boolean isResourceDirectory(PsiDirectory dir) { // check facet settings VirtualFile vf = dir.getVirtualFile(); - Module module = ModuleUtil.findModuleForPsiElement(dir); - if (module != null) { - AndroidFacet facet = AndroidFacet.getInstance(module); - return facet != null && facet.getLocalResourceManager().isResourceDir(vf); + + if (isResourceDirectory(vf, dir.getProject())) { + return true; } // method can be invoked for system resource dir, so we should check it From 81296b96ce2120dd6c45b40aa8683da325b9263f Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 8 Nov 2010 15:58:25 +0300 Subject: [PATCH 13/61] Test for #IDEA-60920 --- .../refactoring/rename/RenameTest.groovy | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy index a31ee0af7343..a921fe515d4e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy @@ -225,6 +225,31 @@ class A { return newName; } + public void _testRecursivePathRename() { + def file = myFixture.configureByText("SomeBean.groovy", """ +class SomeBean { + + SomeBean someBean + + static { + new SomeBean().someBean.someBean.someBean.someBean.toString() + } +} +""") + myFixture.renameElementAtCaret "b" + + assertEquals """ +class SomeBean { + + SomeBean b + + static { + new SomeBean().b.b.b.b.toString() + } +} +""", file.text + } + public void testDontAutoRenameDynamicallyTypeUsage() throws Exception { myFixture.configureByText "a.groovy", """ class Goo { From 5fdd5ec309369eeabab84798c991ff7175914033 Mon Sep 17 00:00:00 2001 From: Alexey Kudravtsev Date: Mon, 8 Nov 2010 15:30:41 +0300 Subject: [PATCH 14/61] project close in write action --- .../src/com/intellij/ide/impl/ProjectUtil.java | 14 ++++++++++---- .../openapi/project/impl/ProjectImpl.java | 18 ++++++++---------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java index 313b92f74a2d..2580c6aee71d 100644 --- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java +++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java @@ -21,6 +21,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.highlighter.ModuleFileType; import com.intellij.ide.highlighter.ProjectFileType; import com.intellij.ide.highlighter.WorkspaceFileType; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.StorageScheme; import com.intellij.openapi.components.impl.stores.IProjectStore; import com.intellij.openapi.diagnostic.Logger; @@ -31,6 +32,7 @@ import com.intellij.openapi.project.ex.ProjectEx; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.InvalidDataException; import com.intellij.openapi.util.io.FileUtil; @@ -87,10 +89,14 @@ public class ProjectUtil { /** * @param project cannot be null */ - public static boolean closeProject(@NotNull Project project) { - if (!ProjectManagerEx.getInstanceEx().closeProject(project)) return false; - Disposer.dispose(project); - return true; + public static boolean closeProject(@NotNull final Project project) { + return ApplicationManager.getApplication().runWriteAction(new Computable() { + public Boolean compute() { + if (!ProjectManagerEx.getInstanceEx().closeProject(project)) return false; + Disposer.dispose(project); + return true; + } + }); } /** diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java index f2a9a597e533..c473abf4c7d3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java @@ -80,13 +80,8 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { private final AtomicBoolean mySavingInProgress = new AtomicBoolean(false); - @NonNls private static final String PROJECT_LAYER = "project-components"; - public boolean myOptimiseTestLoadSpeed; @NonNls public static final String TEMPLATE_PROJECT_NAME = "Default (Template) Project"; - @NonNls private static final String DEPRECATED_MESSAGE = "Deprecated method usage: {0}.\n" + - "This method will cease to exist in IDEA 7.0 final release.\n" + - "Please contact plugin developers for plugin update."; private final Condition myDisposedCondition = new Condition() { public boolean value(final Object o) { @@ -325,7 +320,11 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { public synchronized void dispose() { ApplicationEx application = ApplicationManagerEx.getApplicationEx(); - assert application.isHeadlessEnvironment() || application.isUnitTestMode() || application.isDispatchThread() || application.isInModalProgressThread(); + assert application.isDispatchThread(); + + // can call dispose only via com.intellij.ide.impl.ProjectUtil.closeProject() + LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || !ProjectManagerEx.getInstanceEx().isProjectOpened(this)); + LOG.assertTrue(!isDisposed()); if (myProjectManagerListener != null) { myManager.removeProjectManagerListener(this, myProjectManagerListener); @@ -472,10 +471,10 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { public static class UnableToSaveProjectNotification extends Notification { private Project myProject; - private String[] myFileNames; + private final String[] myFileNames; private UnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) { - super("Project Settings", "Could not save project!", buildMessage(readOnlyFiles), NotificationType.ERROR, new NotificationListener() { + super("Project Settings", "Could not save project!", buildMessage(), NotificationType.ERROR, new NotificationListener() { @Override public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { final UnableToSaveProjectNotification unableToSaveProjectNotification = (UnableToSaveProjectNotification)notification; @@ -501,7 +500,7 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { return myFileNames; } - private static String buildMessage(final VirtualFile[] readOnlyFiles) { + private static String buildMessage() { final StringBuffer sb = new StringBuffer( "

Unable to save project files. Please ensure project files are writable and you have permissions to modify them."); return sb.append(" Try to save project again.

").toString(); @@ -517,5 +516,4 @@ public class ProjectImpl extends ComponentManagerImpl implements ProjectEx { super.expire(); } } - } From e98abf0f6698d9a4d48763fef51d5c7498d177d6 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Mon, 8 Nov 2010 15:13:46 +0300 Subject: [PATCH 15/61] Doesn't look like we're debugging it anymore --- .../intellij/openapi/extensions/impl/ExtensionsAreaImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java index 5ac0528cc7e5..451a49752c8b 100644 --- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java +++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java @@ -46,7 +46,7 @@ public class ExtensionsAreaImpl implements ExtensionsArea { ourDefaultEPs.put(EPAvailabilityListenerExtension.EXTENSION_POINT_NAME, EPAvailabilityListenerExtension.class.getName()); } - private static final boolean DEBUG_REGISTRATION = true; + private static final boolean DEBUG_REGISTRATION = false; private AreaPicoContainerImpl myPicoContainer; private Throwable myCreationTrace = null; From 6c1f22a7c86fcb339fd82432cecb3972850cf426 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 8 Nov 2010 16:26:19 +0300 Subject: [PATCH 16/61] IDEA-60781 After formatting cursor jumps from indented position to beginning of the line. Caret location is restored if necessary after formatting --- .../codeStyle/CodeStyleManagerImpl.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index a26fe4b5c0f4..d173349a1877 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -24,8 +24,10 @@ import com.intellij.injected.editor.DocumentWindow; import com.intellij.lang.*; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.CaretModel; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; @@ -41,6 +43,7 @@ import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.*; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; +import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.CharTable; import com.intellij.util.IncorrectOperationException; import com.intellij.util.text.CharArrayUtil; @@ -159,6 +162,37 @@ public class CodeStyleManagerImpl extends CodeStyleManager { postProcessText(file, new TextRange(formatFromStart ? 0 : startElement.getTextRange().getStartOffset(), formatToEnd ? file.getTextLength() : endElement.getTextRange().getEndOffset())); } + + Editor editor = PsiUtilBase.findEditor(file); + if (editor == null) { + return; + } + + CaretModel caretModel = editor.getCaretModel(); + String indent = getLineIndent(file, caretModel.getOffset()); + int tabSize = getSettings().getTabSize(file.getFileType()); + int indentColumn = indentWithInVisualColumns(indent, tabSize); + VisualPosition position = caretModel.getVisualPosition(); + if (indentColumn != position.column) { + caretModel.moveToVisualPosition(new VisualPosition(position.line, indentColumn)); + } + } + + private static int indentWithInVisualColumns(String indent, int tabSize) { + if (tabSize <= 1) { + return indent.length(); + } + int result = 0; + for (int i = 0; i < indent.length(); i++) { + char c = indent.charAt(i); + if (c == '\t') { + result += tabSize - result % tabSize; + } + else { + result++; + } + } + return result; } private PsiElement reformatRangeImpl(final PsiElement element, From acecbf7f1c42325c8d7000cf9d4ce52fd1e9501e Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Mon, 8 Nov 2010 16:30:55 +0300 Subject: [PATCH 17/61] Allow editing JavaScript libraries only from Project Structure if possible --- .../LangScriptingContextConfigurable.java | 13 +++++++--- .../ui/ScriptingLibrariesPanel.java | 2 +- .../ui/ScriptingLibrariesPanelStub.form | 26 +++++++++++++++++++ .../ui/ScriptingLibrariesPanelStub.java | 23 ++++++++++++++++ .../ui/ScriptingLibraryPanelBase.java | 0 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.form create mode 100644 platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.java create mode 100644 platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryPanelBase.java diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextConfigurable.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextConfigurable.java index 45f9a6cdcb34..cec9a3a05c46 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextConfigurable.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/LangScriptingContextConfigurable.java @@ -15,6 +15,7 @@ */ package com.intellij.ide.scriptingContext; +import com.intellij.ide.scriptingContext.ui.ScriptingLibrariesPanelStub; import com.intellij.ide.scriptingContext.ui.ScriptingContextsConfigurable; import com.intellij.ide.scriptingContext.ui.ScriptingLibrariesPanel; import com.intellij.openapi.application.ApplicationManager; @@ -30,16 +31,22 @@ import javax.swing.*; * @author Rustam Vishnyakov */ public abstract class LangScriptingContextConfigurable implements Configurable, Configurable.Composite { - private ScriptingLibrariesPanel myPanel; - private ScriptingLibraryManager myLibManager; + private final ScriptingLibrariesPanelStub myPanel; + private final ScriptingLibraryManager myLibManager; private ScriptingContextsConfigurable myContextsConfigurable; + private final String productName = System.getProperty("idea.platform.prefix"); public LangScriptingContextConfigurable(Project project, LangScriptingContextProvider provider) { myLibManager = new ScriptingLibraryManager(project, provider.getLibraryType()); - myPanel = new ScriptingLibrariesPanel(provider, project, myLibManager); + myPanel = useDedicatedLibraryUI() ? new ScriptingLibrariesPanel(provider, project, myLibManager) : new ScriptingLibrariesPanelStub(); myContextsConfigurable = new ScriptingContextsConfigurable(project, provider); } + private boolean useDedicatedLibraryUI() { + //TODO Find a better way to check it + return "WebStorm".equalsIgnoreCase(productName) || "PhpStorm".equalsIgnoreCase(productName); + } + @Nls @Override public String getDisplayName() { diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java index 7ff9a0f8f2bf..c2766e432d5c 100644 --- a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanel.java @@ -32,7 +32,7 @@ import java.awt.event.ActionListener; /** * @author Rustam Vishnyakov */ -public class ScriptingLibrariesPanel { +public class ScriptingLibrariesPanel extends ScriptingLibrariesPanelStub { private JPanel myTopPanel; private JButton myAddLibraryButton; private JButton myRemoveLibraryButton; diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.form b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.form new file mode 100644 index 000000000000..f265e89629f9 --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.form @@ -0,0 +1,26 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.java new file mode 100644 index 000000000000..49e6db0cf74a --- /dev/null +++ b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibrariesPanelStub.java @@ -0,0 +1,23 @@ +package com.intellij.ide.scriptingContext.ui; + +import javax.swing.*; + +/** + * @author Rustam Vishnyakov + */ +public class ScriptingLibrariesPanelStub { + private JPanel myMainPanel; + + public JComponent getPanel() { + return myMainPanel; + } + + + public boolean isModified() { + return false; + } + + public void resetTable() { + // Do nothing + } +} diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryPanelBase.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryPanelBase.java new file mode 100644 index 000000000000..e69de29bb2d1 From 6498c3635919da1a7090c5cec0653634757bfc7a Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 8 Nov 2010 13:52:46 +0300 Subject: [PATCH 18/61] EA-22917 - IAE: HashMap.put --- .../groovy/lang/psi/impl/statements/expressions/TypesUtil.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java index 88c645aacb77..52e210ed22ef 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java @@ -24,6 +24,7 @@ import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.containers.ComparatorUtil; import com.intellij.util.containers.HashMap; +import gnu.trove.THashMap; import gnu.trove.TIntObjectHashMap; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NonNls; @@ -491,7 +492,7 @@ public class TypesUtil { public static PsiSubstitutor composeSubstitutors(PsiSubstitutor s1, PsiSubstitutor s2) { final Map map = s1.getSubstitutionMap(); - Map result = new com.intellij.util.containers.hash.HashMap(map.size()); + Map result = new THashMap(map.size()); for (PsiTypeParameter parameter : map.keySet()) { result.put(parameter, s2.substitute(map.get(parameter))); } From 4c50d2783c8c80bc64de992b209c2cdae9adbddd Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 8 Nov 2010 16:41:14 +0300 Subject: [PATCH 19/61] ChangeSignatureTest fix --- .../plugins/groovy/refactoring/GroovyRefactoringUtil.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java index 206eb18e4c80..27db1788a370 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java @@ -452,11 +452,8 @@ public abstract class GroovyRefactoringUtil { if (ref instanceof GrEnumConstant) return (GrEnumConstant)ref; if (ref instanceof GrConstructorInvocation) return (GrCall)ref; PsiElement parent = ref.getParent(); - if (parent instanceof GrMethodCallExpression) { - return (GrMethodCallExpression)parent; - } - else if (parent instanceof GrNewExpression) { - return (GrNewExpression)parent; + if (parent instanceof GrCall) { + return (GrCall)parent; } else { return null; From 617546c85a7aac6b361102f17e1385fdafb8fa66 Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 8 Nov 2010 16:53:01 +0300 Subject: [PATCH 20/61] IDEA-59209 remove duplicated classes inside "gen" source root only --- .../android/compiler/AndroidAptCompiler.java | 3 ++- .../android/compiler/AndroidCompileUtil.java | 16 +++++++++++----- .../android/compiler/AndroidIdlCompiler.java | 6 +++++- .../compiler/AndroidMavenResourcesCompiler.java | 5 ++++- .../facet/AndroidResourceFilesListener.java | 3 ++- 5 files changed, 24 insertions(+), 9 deletions(-) diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java index 9c3d3705ed13..f54ecf418262 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidAptCompiler.java @@ -124,7 +124,8 @@ public class AndroidAptCompiler implements SourceGeneratingCompiler { return; } String className = FileUtil.getNameWithoutExtension(aptItem.myGeneratedFile); - AndroidCompileUtil.removeDuplicatingClasses(aptItem.myModule, aptItem.myPackage, className, aptItem.myGeneratedFile); + AndroidCompileUtil.removeDuplicatingClasses(aptItem.myModule, aptItem.myPackage, className, aptItem.myGeneratedFile, + aptItem.mySourceRootPath); } }); } diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java index 3d4facc7a179..e1be4068fbff 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidCompileUtil.java @@ -27,9 +27,7 @@ import com.intellij.openapi.compiler.GeneratingCompiler; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ContentEntry; -import com.intellij.openapi.roots.ModifiableRootModel; -import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.roots.*; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.LocalFileSystem; @@ -187,16 +185,24 @@ public class AndroidCompileUtil { // must be invoked in a read action! public static void removeDuplicatingClasses(final Module module, @NotNull final String packageName, @NotNull String className, - @Nullable final File classFile) { + @Nullable final File classFile, String sourceRootPath) { + if (sourceRootPath == null) { + return; + } + VirtualFile sourceRoot = LocalFileSystem.getInstance().findFileByPath(sourceRootPath); + if (sourceRoot == null) { + return; + } final Project project = module.getProject(); final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); final String interfaceQualifiedName = packageName + '.' + className; PsiClass[] classes = facade.findClasses(interfaceQualifiedName, GlobalSearchScope.moduleScope(module)); + final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); for (PsiClass c : classes) { PsiFile psiFile = c.getContainingFile(); if (className.equals(FileUtil.getNameWithoutExtension(psiFile.getName()))) { VirtualFile virtualFile = psiFile.getVirtualFile(); - if (virtualFile != null) { + if (virtualFile != null && projectFileIndex.getSourceRootForFile(virtualFile) == sourceRoot) { final String path = virtualFile.getPath(); File f = new File(path); if (!f.equals(classFile) && f.exists()) { diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java index 38486a4395d7..e20427b2ae53 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidIdlCompiler.java @@ -114,6 +114,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler { final IAndroidTarget myAndroidTarget; final File myGeneratedFile; final String myPackageName; + final String mySourceRootPath; public IdlGenerationItem(@NotNull Module module, @NotNull VirtualFile file, @@ -126,6 +127,7 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler { myTestSource = testSource; myAndroidTarget = androidTarget; myPackageName = packageName; + mySourceRootPath = sourceRootPath; myGeneratedFile = new File(sourceRootPath, packageName.replace('.', File.separatorChar) + File.separator + file.getNameWithoutExtension() + ".java"); } @@ -222,7 +224,9 @@ public class AndroidIdlCompiler implements SourceGeneratingCompiler { public void run() { if (idlItem.myModule.getProject().isDisposed()) return; String className = FileUtil.getNameWithoutExtension(idlItem.myGeneratedFile); - AndroidCompileUtil.removeDuplicatingClasses(idlItem.myModule, idlItem.myPackageName, className, idlItem.myGeneratedFile); + AndroidCompileUtil.removeDuplicatingClasses(idlItem.myModule, idlItem.myPackageName, className, + idlItem.myGeneratedFile.exists() ? idlItem.myGeneratedFile : null, + idlItem.mySourceRootPath); } }); } diff --git a/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java b/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java index 38b7f9dfeeba..e5eb49cd9069 100644 --- a/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java +++ b/plugins/android/src/org/jetbrains/android/compiler/AndroidMavenResourcesCompiler.java @@ -106,7 +106,8 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { ApplicationManager.getApplication().runReadAction(new Runnable() { public void run() { String className = FileUtil.getNameWithoutExtension(genItem.myGeneratedFile); - AndroidCompileUtil.removeDuplicatingClasses(genItem.myModule, genItem.myPackage, className, genItem.myGeneratedFile); + AndroidCompileUtil.removeDuplicatingClasses(genItem.myModule, genItem.myPackage, className, genItem.myGeneratedFile, + genItem.mySourceRootPath); } }); } @@ -132,12 +133,14 @@ public class AndroidMavenResourcesCompiler implements SourceGeneratingCompiler { final Module myModule; final String myPackage; final File myGeneratedFile; + final String mySourceRootPath; private MyGenerationItem(@NotNull Module module, @NotNull String aPackage, @NotNull String sourceRootPath) { myModule = module; myPackage = aPackage; myGeneratedFile = new File(sourceRootPath, aPackage.replace('.', File.separatorChar) + File.separator + AndroidUtils.R_JAVA_FILENAME); + mySourceRootPath = sourceRootPath; } @Nullable diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidResourceFilesListener.java b/plugins/android/src/org/jetbrains/android/facet/AndroidResourceFilesListener.java index 63c8133334e0..bbb49e855a69 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidResourceFilesListener.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidResourceFilesListener.java @@ -142,7 +142,8 @@ class AndroidResourceFilesListener extends VirtualFileAdapter { Manifest manifest = myFacet.getManifest(); String aPackage = manifest != null ? manifest.getPackage().getValue() : null; if (myCachedPackage != null && !myCachedPackage.equals(aPackage)) { - AndroidCompileUtil.removeDuplicatingClasses(myModule, myCachedPackage, AndroidUtils.R_CLASS_NAME, null); + String aptGenDirPath = myFacet.getAptGenSourceRootPath(); + AndroidCompileUtil.removeDuplicatingClasses(myModule, myCachedPackage, AndroidUtils.R_CLASS_NAME, null, aptGenDirPath); } myCachedPackage = aPackage; myFacet.getLocalResourceManager().invalidateAttributeDefinitions(); From f60f03cfd39643d5f048dd91ed144ed08a7d5371 Mon Sep 17 00:00:00 2001 From: Maxim Medvedev Date: Mon, 8 Nov 2010 17:12:24 +0300 Subject: [PATCH 21/61] EA-22846 - assert: ProblemDescriptorImpl. --- .../assignment/GroovyAssignabilityCheckInspection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java index e917a26af11b..ed59e67214f7 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyAssignabilityCheckInspection.java @@ -268,7 +268,7 @@ public class GroovyAssignabilityCheckInspection extends BaseInspection { private void highlightInapplicableMethodUsage(GroovyResolveResult methodResolveResult, PsiElement place, PsiMethod method, PsiType[] argumentTypes) { PsiElement elementToHighlight = PsiUtil.getArgumentsList(place); - if (elementToHighlight == null) { + if (elementToHighlight == null || elementToHighlight.getTextRange().getLength() == 0) { elementToHighlight = place; } From df8995a4ef1fc91556065c935ba5e19f8aa12cc7 Mon Sep 17 00:00:00 2001 From: anna Date: Tue, 2 Nov 2010 19:12:27 +0300 Subject: [PATCH 22/61] hide Alt-Ins all java templates - they are already included in create Java class --- .../src/com/intellij/ide/actions/CreateClassAction.java | 2 +- .../ide/fileTemplates/JavaCreateFromTemplateHandler.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/java/java-impl/src/com/intellij/ide/actions/CreateClassAction.java b/java/java-impl/src/com/intellij/ide/actions/CreateClassAction.java index 6fc85e123636..6a480246a5dd 100644 --- a/java/java-impl/src/com/intellij/ide/actions/CreateClassAction.java +++ b/java/java-impl/src/com/intellij/ide/actions/CreateClassAction.java @@ -59,7 +59,7 @@ public class CreateClassAction extends JavaCreateTemplateInPackageAction Date: Tue, 2 Nov 2010 20:38:48 +0300 Subject: [PATCH 23/61] disable accept new name for vars which are not inplace renamable --- .../changeSignature/JavaChangeSignatureDetector.java | 8 ++++---- .../refactoring/changeSignature/RenameChangeInfo.java | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java index 25b48d6a5744..e75f55b43919 100644 --- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java +++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDetector.java @@ -17,6 +17,7 @@ package com.intellij.refactoring.changeSignature; import com.intellij.lang.Language; import com.intellij.lang.StdLanguages; +import com.intellij.lang.java.JavaRefactoringSupportProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.Result; import com.intellij.openapi.command.CommandProcessor; @@ -30,7 +31,6 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.BaseRefactoringProcessor; import com.intellij.refactoring.RefactoringBundle; -import com.intellij.refactoring.rename.RenameProcessor; import com.intellij.refactoring.util.CanonicalTypes; import com.intellij.usageView.UsageInfo; import com.intellij.usageView.UsageViewUtil; @@ -118,9 +118,9 @@ public class JavaChangeSignatureDetector implements LanguageChangeSignatureDetec return changeInfo; } } else { - final PsiLocalVariable localVariable = PsiTreeUtil.getParentOfType(element, PsiLocalVariable.class); - if (localVariable != null) { - return new RenameChangeInfo(localVariable, changeInfo) { + final PsiVariable variable = PsiTreeUtil.getParentOfType(element, PsiVariable.class); + if (variable != null && JavaRefactoringSupportProvider.mayRenameInplace(variable, element)) { + return new RenameChangeInfo(variable, changeInfo) { @Override public Language getLanguage() { return StdLanguages.JAVA; diff --git a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/RenameChangeInfo.java b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/RenameChangeInfo.java index 082fb4374d67..6639872e6a03 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/changeSignature/RenameChangeInfo.java +++ b/platform/lang-impl/src/com/intellij/refactoring/changeSignature/RenameChangeInfo.java @@ -13,7 +13,6 @@ package com.intellij.refactoring.changeSignature; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.rename.RenameProcessor; @@ -100,7 +99,7 @@ public abstract class RenameChangeInfo implements ChangeInfo { element.setName(myOldName); } }); - new RenameProcessor(element.getProject(), element, name, true, true).run(); + new RenameProcessor(element.getProject(), element, name, false, false).run(); } } From b5c9f110141cecacb55e1b745e283e1936017916 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 3 Nov 2010 13:26:03 +0300 Subject: [PATCH 24/61] forbid to move method from library as soon as possible --- .../move/moveInstanceMethod/MoveInstanceMethodHandler.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java index ed51d5326147..2ed4042a8f97 100644 --- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java @@ -75,7 +75,9 @@ public class MoveInstanceMethodHandler implements RefactoringActionHandler { if (elements.length != 1 || !(elements[0] instanceof PsiMethod)) return; final PsiMethod method = (PsiMethod)elements[0]; String message = null; - if (method.isConstructor()) { + if (!method.getManager().isInProject(method)) { + message = "Move method is not supported for non-project methods"; + } else if (method.isConstructor()) { message = RefactoringBundle.message("move.method.is.not.supported.for.constructors"); } else if (PsiUtil.typeParametersIterator(method.getContainingClass()).hasNext() && TypeParametersSearcher.hasTypeParameters(method)) { From b0d4c4f26c76d10b6259e9b5dfda340bd3a5ff31 Mon Sep 17 00:00:00 2001 From: anna Date: Wed, 3 Nov 2010 13:42:02 +0300 Subject: [PATCH 25/61] sort source roots in eclipse --- .../src/com/intellij/openapi/roots/impl/ContentEntryImpl.java | 2 +- .../org/jetbrains/idea/eclipse/config/EclipseModuleManager.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java index f7260d85a6c6..4f3aa9cd05ec 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java @@ -44,7 +44,7 @@ public class ContentEntryImpl extends RootModelComponentBase implements ContentE private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.SimpleContentEntryImpl"); private final VirtualFilePointer myRoot; @NonNls public static final String ELEMENT_NAME = "content"; - private final LinkedHashSet mySourceFolders = new LinkedHashSet(); + private final TreeSet mySourceFolders = new TreeSet(ContentFolderComparator.INSTANCE); private final TreeSet myExcludeFolders = new TreeSet(ContentFolderComparator.INSTANCE); private final TreeSet myExcludedOutputFolders = new TreeSet(ContentFolderComparator.INSTANCE); @NonNls public static final String URL_ATTRIBUTE = "url"; diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java index 27067213a990..8b7ed5b6ba98 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManager.java @@ -126,6 +126,7 @@ public class EclipseModuleManager implements PersistentStateComponent{ public void setForceConfigureJDK() { myForceConfigureJDK = true; + myExpectedModuleSourcePlace++; } public void registerEclipseLibUrl(String url) { From c288da64dfd55db473532ab3af84595baa1ff1d6 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 17:15:04 +0300 Subject: [PATCH 26/61] Ctrl-Alt-V Ctrl-Alt-V to reassign expression to existing variable --- .../IntroduceVariableBase.java | 30 ++- .../ReassignVariableUtil.java | 188 ++++++++++++++++++ .../codeInsight/template/Expression.java | 5 + .../codeInsight/template/Template.java | 10 +- .../template/TemplateBuilderImpl.java | 17 +- .../template/impl/TemplateImpl.java | 12 +- .../template/impl/TemplateState.java | 9 +- .../codeInsight/template/impl/Variable.java | 11 +- .../inplace/VariableInplaceRenamer.java | 20 +- 9 files changed, 276 insertions(+), 26 deletions(-) create mode 100644 java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 1440f58bcd64..2801ef9574c3 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -27,8 +27,8 @@ import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.codeInsight.completion.JavaCompletionUtil; import com.intellij.codeInsight.highlighting.HighlightManager; import com.intellij.codeInsight.lookup.LookupManager; +import com.intellij.codeInsight.template.TemplateBuilderImpl; import com.intellij.featureStatistics.FeatureUsageTracker; -import com.intellij.ide.DataManager; import com.intellij.ide.util.PropertiesComponent; import com.intellij.lang.LanguageRefactoringSupport; import com.intellij.lang.refactoring.RefactoringSupportProvider; @@ -39,13 +39,10 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; -import com.intellij.openapi.editor.markup.TextAttributes; +import com.intellij.openapi.editor.markup.*; import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Pass; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.*; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.wm.WindowManager; import com.intellij.psi.*; @@ -55,7 +52,6 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.*; import com.intellij.refactoring.introduceField.ElementToWorkOn; -import com.intellij.refactoring.rename.inplace.VariableInplaceRenameHandler; import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer; import com.intellij.refactoring.ui.TypeSelectorManagerImpl; import com.intellij.refactoring.util.CommonRefactoringUtil; @@ -65,7 +61,6 @@ import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.refactoring.util.occurences.ExpressionOccurenceManager; import com.intellij.refactoring.util.occurences.NotInSuperCallOccurenceFilter; import com.intellij.util.Consumer; -import com.intellij.util.Function; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.*; import org.jetbrains.annotations.NonNls; @@ -73,6 +68,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.List; public abstract class IntroduceVariableBase extends IntroduceHandlerBase implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.introduceVariable.IntroduceVariableBase"); @@ -367,6 +363,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme } if (expr == null) { + if (ReassignVariableUtil.reassign(editor)) return false; String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message("selected.block.should.represent.an.expression")); showErrorMessage(project, editor, message); return false; @@ -475,11 +472,21 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme public void run() { ApplicationManager.getApplication().runWriteAction(runnable); if (isInplaceAvailableOnDataContext) { - PsiVariable elementToRename = variable.get().getElement(); + final PsiVariable elementToRename = variable.get().getElement(); if (elementToRename != null) { editor.getCaretModel().moveToOffset(elementToRename.getTextOffset()); - new VariableInplaceRenamer(elementToRename, editor) - .performInplaceRename(false, new LinkedHashSet(Arrays.asList(suggestedName.names)), new Consumer(){ + final PsiDeclarationStatement declarationStatement = PsiTreeUtil.getParentOfType(elementToRename, PsiDeclarationStatement.class); + editor.putUserData(ReassignVariableUtil.DECLARATION_KEY, declarationStatement); + final VariableInplaceRenamer renamer = new VariableInplaceRenamer(elementToRename, editor){ + @Override + protected void addAdditionalVariables(TemplateBuilderImpl builder) { + builder.replaceElement(elementToRename.getTypeElement(), "Variable_Type", ReassignVariableUtil + .createExpression(typeSelectorManager), false, true); + } + }; + renamer.setAdvertisementText( + ReassignVariableUtil.getAdvertisementText(editor, declarationStatement, elementToRename.getType())); + renamer.performInplaceRename(false, new LinkedHashSet(Arrays.asList(suggestedName.names)), new Consumer() { @Override public void consume(Boolean apply) { if (apply) { @@ -492,6 +499,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme } editor.getCaretModel().moveToOffset(startOffset); } + editor.putUserData(ReassignVariableUtil.DECLARATION_KEY, null); exprMarker.dispose(); } }); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java new file mode 100644 index 000000000000..2eec696a185d --- /dev/null +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java @@ -0,0 +1,188 @@ +/* + * 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.refactoring.introduceVariable; + +import com.intellij.codeInsight.lookup.LookupElement; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.codeInsight.template.Expression; +import com.intellij.codeInsight.template.ExpressionContext; +import com.intellij.codeInsight.template.TextResult; +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; +import com.intellij.ide.ui.ListCellRendererWrapper; +import com.intellij.openapi.actionSystem.ActionManager; +import com.intellij.openapi.actionSystem.Shortcut; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.VisualPosition; +import com.intellij.openapi.keymap.Keymap; +import com.intellij.openapi.keymap.KeymapManager; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.util.Key; +import com.intellij.psi.*; +import com.intellij.psi.scope.processor.VariablesProcessor; +import com.intellij.psi.scope.util.PsiScopesUtil; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.refactoring.rename.inplace.VariableInplaceRenamer; +import com.intellij.refactoring.ui.TypeSelectorManager; +import com.intellij.refactoring.ui.TypeSelectorManagerImpl; +import com.intellij.ui.awt.RelativePoint; +import com.intellij.ui.components.JBList; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; + +/** + * User: anna + * Date: 11/8/10 + */ +public class ReassignVariableUtil { + static final Key DECLARATION_KEY = Key.create("var.type"); + + static boolean reassign(final Editor editor) { + final PsiDeclarationStatement declaration = editor.getUserData(DECLARATION_KEY); + final PsiType type = getVariableType(declaration); + if (type != null) { + VariablesProcessor proc = findVariablesOfType(editor, declaration, type); + if (proc.size() > 0) { + + if (proc.size() == 1) { + replaceWithAssignment(declaration, proc.getResult(0), editor); + return true; + } + + final DefaultListModel model = new DefaultListModel(); + for (int i = 0; i < proc.size(); i++) { + model.addElement(proc.getResult(i)); + } + final JList list = new JBList(model); + list.setCellRenderer(new ListCellRendererWrapper(new DefaultListCellRenderer()) { + @Override + public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) { + if (value instanceof PsiVariable) { + setText(((PsiVariable)value).getName()); + setIcon(((PsiVariable)value).getIcon(0)); + } + } + }); + + + final VisualPosition visualPosition = editor.getCaretModel().getVisualPosition(); + final Point point = editor.visualPositionToXY(new VisualPosition(visualPosition.line + 1, visualPosition.column)); + JBPopupFactory.getInstance().createListPopupBuilder(list) + .setTitle("Choose variable to reassign") + .setRequestFocus(true) + .setItemChoosenCallback(new Runnable() { + public void run() { + replaceWithAssignment(declaration, (PsiVariable)list.getSelectedValue(), editor); + } + }).createPopup().show(new RelativePoint(editor.getContentComponent(), point)); + } + + return true; + } + return false; + } + + @Nullable + private static PsiType getVariableType(@Nullable PsiDeclarationStatement declaration) { + if (declaration != null) { + final PsiElement[] declaredElements = declaration.getDeclaredElements(); + if (declaredElements.length > 0 && declaredElements[0] instanceof PsiVariable) { + return ((PsiVariable)declaredElements[0]).getType(); + } + } + return null; + } + + private static VariablesProcessor findVariablesOfType(Editor editor, final PsiDeclarationStatement declaration, final PsiType type) { + VariablesProcessor proc = new VariablesProcessor(false) { + @Override + protected boolean check(PsiVariable var, ResolveState state) { + for (PsiElement element : declaration.getDeclaredElements()) { + if (element == var) return false; + } + return TypeConversionUtil.isAssignable(var.getType(), type); + } + }; + PsiElement scope = editor.getUserData(DECLARATION_KEY); + while (scope != null) { + if (scope instanceof PsiFile || scope instanceof PsiMethod || scope instanceof PsiClassInitializer) break; + scope = scope.getParent(); + } + if (scope == null) return proc; + PsiScopesUtil.treeWalkUp(proc, declaration, scope); + return proc; + } + + static void replaceWithAssignment(final PsiDeclarationStatement declaration, final PsiVariable variable, Editor editor) { + final PsiVariable var = (PsiVariable)declaration.getDeclaredElements()[0]; + final PsiExpression initializer = var.getInitializer(); + new WriteCommandAction(declaration.getProject()) { + @Override + protected void run(Result result) throws Throwable { + //would generate red code for final variables + declaration.replace(JavaPsiFacade.getElementFactory(variable.getProject()) + .createStatementFromText(variable.getName() + " = " + initializer.getText() + ";", declaration)); + } + }.execute(); + finishTemplate(editor); + } + + private static void finishTemplate(Editor editor) { + final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor); + final VariableInplaceRenamer renamer = editor.getUserData(VariableInplaceRenamer.INPLACE_RENAMER); + if (templateState != null && renamer != null) { + templateState.gotoEnd(true); + editor.putUserData(VariableInplaceRenamer.INPLACE_RENAMER, null); + } + } + + static Expression createExpression(final TypeSelectorManagerImpl typeSelectorManager) { + final PsiType[] types = typeSelectorManager.getTypesForAll(); + return new Expression() { + @Override + public com.intellij.codeInsight.template.Result calculateResult(ExpressionContext context) { + return new TextResult(typeSelectorManager.getDefaultType().getPresentableText()); + } + + @Override + public com.intellij.codeInsight.template.Result calculateQuickResult(ExpressionContext context) { + return new TextResult(typeSelectorManager.getDefaultType().getPresentableText()); + } + + @Override + public LookupElement[] calculateLookupItems(ExpressionContext context) { + LookupElement[] result = new LookupElement[types.length]; + for (int i = 0, typesLength = types.length; i < typesLength; i++) { + result[i] = LookupElementBuilder.create(types[i].getPresentableText()); + } + return result; + } + }; + } + + static String getAdvertisementText(Editor editor, PsiDeclarationStatement declaration, PsiType type) { + final VariablesProcessor processor = findVariablesOfType(editor, declaration, type); + if (processor.size() > 0) { + final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); + final Shortcut[] shortcuts = keymap.getShortcuts("IntroduceVariable"); + if (shortcuts.length > 0) { + return "Press " + shortcuts[0] + " to reassign existing variable"; + } + } + return "Press Shift Tab to change type"; + } +} diff --git a/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java b/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java index da8e040c4c07..a5205581a1c2 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java +++ b/platform/lang-api/src/com/intellij/codeInsight/template/Expression.java @@ -29,5 +29,10 @@ public abstract class Expression { @Nullable public abstract LookupElement[] calculateLookupItems(ExpressionContext context); + + @Nullable + public String getAdvertisingText() { + return null; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java b/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java index a5a6a0c0b4e9..0da41ec1cb35 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/Template.java @@ -29,7 +29,15 @@ public abstract class Template { } public abstract Variable addVariable(Expression expression, boolean isAlwaysStopAt); - public abstract Variable addVariable(@NonNls String name, Expression expression, Expression defaultValueExpression, boolean isAlwaysStopAt); + public Variable addVariable(@NonNls String name, Expression expression, Expression defaultValueExpression, boolean isAlwaysStopAt) { + return addVariable(name, expression, defaultValueExpression, isAlwaysStopAt, false); + } + + public abstract Variable addVariable(@NonNls String name, + Expression expression, + Expression defaultValueExpression, + boolean isAlwaysStopAt, + boolean skipOnStart); public abstract Variable addVariable(@NonNls String name, @NonNls String expression, @NonNls String defaultValueExpression, boolean isAlwaysStopAt); public abstract void addEndVariable(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java index 10f375414b46..25d5744b9672 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java @@ -46,6 +46,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { private final Map myExpressions = new HashMap(); private final Map myVariableExpressions = new HashMap(); private final Map myAlwaysStopAtMap = new HashMap(); + private final Map mySkipOnStartMap = new HashMap(); private final Map myVariableNamesMap = new HashMap(); private final Set myElements = new TreeSet(RangeMarker.BY_START_OFFSET); @@ -79,10 +80,7 @@ public class TemplateBuilderImpl implements TemplateBuilder { } public void replaceElement(PsiElement element, String varName, Expression expression, boolean alwaysStopAt) { - final RangeMarker key = wrapElement(element); - myAlwaysStopAtMap.put(key, alwaysStopAt ? Boolean.TRUE : Boolean.FALSE); - myVariableNamesMap.put(key, varName); - replaceElement(key, expression); + replaceElement(element, varName, expression, alwaysStopAt, false); } public void replaceElement(PsiReference ref, String varName, Expression expression, boolean alwaysStopAt) { @@ -201,7 +199,8 @@ public class TemplateBuilderImpl implements TemplateBuilder { : myVariableNamesMap.get(element); if (expression != null) { - template.addVariable(variableName, expression, expression, alwaysStopAt); + final Boolean skipOnStart = mySkipOnStartMap.get(element); + template.addVariable(variableName, expression, expression, alwaysStopAt, skipOnStart != null && skipOnStart.booleanValue()); } else { template.addVariableSegment(variableName); @@ -258,4 +257,12 @@ public class TemplateBuilderImpl implements TemplateBuilder { TemplateManager.getInstance(myFile.getProject()).startTemplate(editor, template); } + + public void replaceElement(PsiElement element, String varName, Expression expression, boolean alwaysStopAt, boolean skipOnStart) { + final RangeMarker key = wrapElement(element); + myAlwaysStopAtMap.put(key, alwaysStopAt ? Boolean.TRUE : Boolean.FALSE); + myVariableNamesMap.put(key, varName); + mySkipOnStartMap.put(key, Boolean.valueOf(skipOnStart)); + replaceElement(key, expression); + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java index 725cca18d565..a1a9f3bf567c 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateImpl.java @@ -139,12 +139,16 @@ public class TemplateImpl extends Template implements SchemeElement { return addVariable("__Variable" + myVariables.size(), expression, isAlwaysStopAt); } - public Variable addVariable(String name, Expression expression, Expression defaultValueExpression, boolean isAlwaysStopAt) { + public Variable addVariable(String name, + Expression expression, + Expression defaultValueExpression, + boolean isAlwaysStopAt, + boolean skipOnStart) { if (mySegments != null) { Segment segment = new Segment(name, myTemplateText.length()); mySegments.add(segment); } - Variable variable = new Variable(name, expression, defaultValueExpression, isAlwaysStopAt); + Variable variable = new Variable(name, expression, defaultValueExpression, isAlwaysStopAt, skipOnStart); myVariables.add(variable); return variable; } @@ -442,6 +446,10 @@ public class TemplateImpl extends Template implements SchemeElement { } } + public boolean skipOnStart(int i) { + return myVariables.get(i).skipOnStart(); + } + private static class Segment { public String name; public int offset; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java index 18cbd431517d..6b15a24fdf6a 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateState.java @@ -473,7 +473,7 @@ public class TemplateState implements Disposable { itemSelected(lookupItems[0], psiFile, currentSegmentNumber, ' ', lookupItems); } else { - runLookup(currentSegmentNumber, lookupItems, psiFile); + runLookup(currentSegmentNumber, lookupItems, expressionNode.getAdvertisingText(), psiFile); } } else { @@ -486,12 +486,14 @@ public class TemplateState implements Disposable { focusCurrentHighlighter(true); } - private void runLookup(final int currentSegmentNumber, final LookupElement[] lookupItems, final PsiFile psiFile) { + private void runLookup(final int currentSegmentNumber, final LookupElement[] lookupItems, String advertisingText, final PsiFile psiFile) { if (myEditor == null) return; final LookupManager lookupManager = LookupManager.getInstance(myProject); final Lookup lookup = lookupManager.showLookup(myEditor, lookupItems); + ((LookupImpl)lookup).setAdvertisementText(advertisingText); + ((LookupImpl)lookup).refreshUi(); ourLookupShown = true; lookup.addLookupListener(new LookupAdapter() { public void lookupCanceled(LookupEvent event) { @@ -864,6 +866,9 @@ public class TemplateState implements Disposable { } int segmentNumber = myTemplate.getVariableSegmentNumber(variableName); if (segmentNumber < 0) return false; + if (myCurrentVariableNumber == -1) { + if (myTemplate.skipOnStart(currentVariableNumber)) return false; + } int start = mySegments.getSegmentStart(segmentNumber); ExpressionContext context = createExpressionContext(start); Result result = expression.calculateResult(context); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/Variable.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/Variable.java index 6144d980a4b3..0b6d067ccde5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/Variable.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/Variable.java @@ -27,12 +27,14 @@ public class Variable implements Cloneable { private String myDefaultValueString; private Expression myDefaultValueExpression; + private boolean mySkipOnStart; - public Variable(String name, Expression expression, Expression defaultValueExpression, boolean alwaysStopAt) { + public Variable(String name, Expression expression, Expression defaultValueExpression, boolean alwaysStopAt, boolean skipOnStart) { myName = name; myExpression = expression; myDefaultValueExpression = defaultValueExpression; myAlwaysStopAt = alwaysStopAt; + mySkipOnStart = skipOnStart; } public Variable(String name, String expression, String defaultValueString, boolean alwaysStopAt) { @@ -40,6 +42,7 @@ public class Variable implements Cloneable { myExpressionString = expression; myDefaultValueString = defaultValueString; myAlwaysStopAt = alwaysStopAt; + mySkipOnStart = false; } public String getExpressionString() { @@ -103,6 +106,7 @@ public class Variable implements Cloneable { final Variable variable = (Variable) o; if (myAlwaysStopAt != variable.myAlwaysStopAt) return false; + if (mySkipOnStart != variable.mySkipOnStart) return false; if (myDefaultValueString != null ? !myDefaultValueString.equals(variable.myDefaultValueString) : variable.myDefaultValueString != null) return false; if (myExpressionString != null ? !myExpressionString.equals(variable.myExpressionString) : variable.myExpressionString != null) return false; if (myName != null ? !myName.equals(variable.myName) : variable.myName != null) return false; @@ -114,8 +118,13 @@ public class Variable implements Cloneable { int result; result = (myName != null ? myName.hashCode() : 0); result = 29 * result + (myAlwaysStopAt ? 1 : 0); + result = 29 * result + (mySkipOnStart ? 1 : 0); result = 29 * result + (myExpressionString != null ? myExpressionString.hashCode() : 0); result = 29 * result + (myDefaultValueString != null ? myDefaultValueString.hashCode() : 0); return result; } + + public boolean skipOnStart() { + return mySkipOnStart; + } } diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java index f03ed1b19187..234f3e81b646 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/VariableInplaceRenamer.java @@ -31,7 +31,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.command.CommandProcessor; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.editor.RangeMarker; import com.intellij.openapi.editor.colors.EditorColors; import com.intellij.openapi.editor.colors.EditorColorsManager; import com.intellij.openapi.editor.markup.RangeHighlighter; @@ -39,7 +38,6 @@ import com.intellij.openapi.editor.markup.TextAttributes; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.vfs.VirtualFile; @@ -60,7 +58,6 @@ import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.refactoring.util.TextOccurrencesUtil; import com.intellij.usageView.UsageInfo; import com.intellij.util.Consumer; -import com.intellij.util.Function; import com.intellij.util.PairProcessor; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.Stack; @@ -89,6 +86,12 @@ public class VariableInplaceRenamer { private final Editor myEditor; private final Project myProject; + public void setAdvertisementText(String advertisementText) { + myAdvertisementText = advertisementText; + } + + private String myAdvertisementText; + private static final Stack ourRenamersStack = new Stack(); public VariableInplaceRenamer(@NotNull PsiNamedElement elementToRename, Editor editor) { @@ -178,7 +181,8 @@ public class VariableInplaceRenamer { for (PsiReference ref : refs) { addVariable(ref, selectedElement, builder, offset, nameSuggestions); } - + addAdditionalVariables(builder); + final PsiElement scope1 = scope; final int renameOffset = myElementToRename.getTextOffset(); CommandProcessor.getInstance().executeCommand(myProject, new Runnable() { @@ -260,6 +264,9 @@ public class VariableInplaceRenamer { return true; } + protected void addAdditionalVariables(TemplateBuilderImpl builder) { + } + protected void addReferenceAtCaret(Collection refs) { PsiFile myEditorFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument()); // Note, that myEditorFile can be different from myElement.getContainingFile() e.g. in injections: myElement declaration in one @@ -459,5 +466,10 @@ public class VariableInplaceRenamer { public Result calculateResult(ExpressionContext context) { return new TextResult(myName); } + + @Override + public String getAdvertisingText() { + return myAdvertisementText; + } } } From f391453d328c2d894e192a82132cdc984ffa0a50 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Mon, 8 Nov 2010 15:11:57 +0300 Subject: [PATCH 27/61] diagnostics for AIOOBE in NameUtil matching --- platform/util/src/com/intellij/psi/codeStyle/NameUtil.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java index a4e1e31e47e3..9c7bda8404b2 100644 --- a/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java +++ b/platform/util/src/com/intellij/psi/codeStyle/NameUtil.java @@ -415,7 +415,12 @@ public class NameUtil { return false; } - return myMatcher.matches(name, myPattern); + try { + return myMatcher.matches(name, myPattern); + } + catch (ArrayIndexOutOfBoundsException e) { + throw new RuntimeException("Name=" + name + "; pattern=" + myPattern.getPattern() , e); + } } private static String preparePattern(String pattern) { From 217ece149ba78de6ddbedd91249a790233ad8126 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Mon, 8 Nov 2010 16:56:45 +0300 Subject: [PATCH 28/61] IDEA-58858 Regression: Incorrect behavior on method name autocomplete if the next statement has a cast --- .../codeInsight/completion/JavaCompletionUtil.java | 8 ++++++++ ...colonAfterExistingParenthesesEspeciallyIfItsACast.java | 5 +++++ ...fterExistingParenthesesEspeciallyIfItsACast_after.java | 5 +++++ .../codeInsight/completion/NormalCompletionTest.groovy | 2 ++ 4 files changed, 20 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast_after.java 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 fd8e72df578e..f0588fb2a53c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -922,6 +922,14 @@ public class JavaCompletionUtil { // Invoke parameters popup AutoPopupController.getInstance(file.getProject()).autoPopupParameterInfo(editor, overloadsMatter ? null : (PsiElement)item.getObject()); } + + if (tailType == TailType.SEMICOLON) { + PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments(); + if (psiElement().beforeLeaf(psiElement().withText(".")).accepts(file.findElementAt(context.getTailOffset() - 1))) { + return; + } + } + if (tailType == TailType.SMART_COMPLETION || needLeftParenth && needRightParenth) { tailType.processTail(editor, context.getTailOffset()); } diff --git a/java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast.java b/java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast.java new file mode 100644 index 000000000000..8f7b35e3ff22 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast.java @@ -0,0 +1,5 @@ +public class Beda { + { + System.out.printl ((String)"a").subSequence(); + } +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast_after.java b/java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast_after.java new file mode 100644 index 000000000000..25802dce5c1b --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/NoSemicolonAfterExistingParenthesesEspeciallyIfItsACast_after.java @@ -0,0 +1,5 @@ +public class Beda { + { + System.out.println ((String)"a").subSequence(); + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 2e3607a7a4b0..b8ebfd0ea1db 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -596,6 +596,8 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { doTest(); } + public void testNoSemicolonAfterExistingParenthesesEspeciallyIfItsACast() throws Throwable { doTest(); } + public void testCaseTailType() throws Throwable { doTest(); } def doPrimitiveTypeTest() { From 1fec75c35a898ba6a7108b72c972922d61d51047 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Mon, 8 Nov 2010 17:55:05 +0300 Subject: [PATCH 29/61] suggest the just appeared type variables when writing a method return type (IDEA-60681) --- .../completion/JavaCompletionData.java | 17 +++++++++++++++++ .../normal/ReturningTypeVariable.java | 3 +++ .../normal/ReturningTypeVariable2.java | 3 +++ .../normal/ReturningTypeVariable2_after.java | 3 +++ .../normal/ReturningTypeVariable3.java | 3 +++ .../normal/ReturningTypeVariable3_after.java | 3 +++ .../normal/ReturningTypeVariable_after.java | 3 +++ .../completion/NormalCompletionTest.groovy | 3 +++ .../intellij/patterns/TreeElementPattern.java | 14 ++++++++++++++ 9 files changed, 52 insertions(+) create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2_after.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3_after.java create mode 100644 java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable_after.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java index d6f982f22825..45a7965df590 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionData.java @@ -37,6 +37,7 @@ import com.intellij.psi.jsp.JspElementType; import com.intellij.psi.scope.ElementClassFilter; import com.intellij.psi.templateLanguages.OuterLanguageElement; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ProcessingContext; import org.jetbrains.annotations.NonNls; import static com.intellij.patterns.PsiJavaPatterns.*; @@ -598,6 +599,22 @@ public class JavaCompletionData extends JavaAwareCompletionData{ } } + final ProcessingContext context = new ProcessingContext(); + if (psiElement().afterLeaf( + psiElement().withText(">").withParent( + psiElement(PsiTypeParameterList.class).withParent(PsiErrorElement.class).save("typeParameterList"))).accepts(position, context)) { + final PsiTypeParameterList list = (PsiTypeParameterList)context.get("typeParameterList"); + PsiElement current = list.getParent().getParent(); + if (current instanceof PsiField) { + current = current.getParent(); + } + if (current instanceof PsiClass) { + for (PsiTypeParameter typeParameter : list.getTypeParameters()) { + result.addElement(new JavaPsiClassReferenceElement(typeParameter)); + } + } + } + } private static LookupElement createKeyword(PsiElement position, String keyword) { diff --git a/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable.java b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable.java new file mode 100644 index 000000000000..49ee189e13f2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable.java @@ -0,0 +1,3 @@ +public class Beda { + public Tooo +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2.java b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2.java new file mode 100644 index 000000000000..9dd705997abc --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2.java @@ -0,0 +1,3 @@ +public class Beda { + public Tooo x +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2_after.java b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2_after.java new file mode 100644 index 000000000000..4f846ea53dd7 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable2_after.java @@ -0,0 +1,3 @@ +public class Beda { + public Toooo x +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3.java b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3.java new file mode 100644 index 000000000000..675ce20a630d --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3.java @@ -0,0 +1,3 @@ +public class Beda { + public Tooo a() +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3_after.java b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3_after.java new file mode 100644 index 000000000000..c382a57c858a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable3_after.java @@ -0,0 +1,3 @@ +public class Beda { + public Toooo a() +} diff --git a/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable_after.java b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable_after.java new file mode 100644 index 000000000000..99044b6b2616 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ReturningTypeVariable_after.java @@ -0,0 +1,3 @@ +public class Beda { + public Toooo +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index b8ebfd0ea1db..30f7cdb853d1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -597,6 +597,9 @@ public class NormalCompletionTest extends LightFixtureCompletionTestCase { } public void testNoSemicolonAfterExistingParenthesesEspeciallyIfItsACast() throws Throwable { doTest(); } + public void testReturningTypeVariable() throws Throwable { doTest(); } + public void testReturningTypeVariable2() throws Throwable { doTest(); } + public void testReturningTypeVariable3() throws Throwable { doTest(); } public void testCaseTailType() throws Throwable { doTest(); } diff --git a/platform/platform-api/src/com/intellij/patterns/TreeElementPattern.java b/platform/platform-api/src/com/intellij/patterns/TreeElementPattern.java index c4fb4a387d62..1eda3eef4ec1 100644 --- a/platform/platform-api/src/com/intellij/patterns/TreeElementPattern.java +++ b/platform/platform-api/src/com/intellij/patterns/TreeElementPattern.java @@ -173,4 +173,18 @@ public abstract class TreeElementPattern pattern) { + return with(new PatternCondition("afterSibling") { + @Override + public boolean accepts(@NotNull T t, ProcessingContext context) { + final ParentType parent = getParent(t); + if (parent == null) return false; + final ParentType[] children = getChildren(parent); + final int i = Arrays.asList(children).indexOf(t); + if (i <= 0) return false; + return pattern.accepts(children[i - 1], context); + } + }); + } } From 87b635ba86ff554e9354862a317f8633c7ccac68 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Mon, 8 Nov 2010 17:56:33 +0300 Subject: [PATCH 30/61] more reliable GDSL script execution --- .../jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java index 9737415a4445..72386f54f859 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java @@ -237,9 +237,8 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { final long stamp = vfile.getModificationStamp(); final GroovyDslExecutor cached = getCachedExecutor(vfile, stamp); if (cached == null) { - if (scheduleParsing(queue, project, vfile, stamp, psiFile.getText())) { - count++; - } + scheduleParsing(queue, project, vfile, stamp, psiFile.getText()); + count++; } else { result.add(new GroovyDslScript(project, vfile, cached)); @@ -281,7 +280,7 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { } } - private static boolean scheduleParsing(final LinkedBlockingQueue> queue, + private static void scheduleParsing(final LinkedBlockingQueue> queue, final Project project, final VirtualFile vfile, final long stamp, @@ -319,10 +318,8 @@ public class GroovyDslFileIndex extends ScalarIndexExtension { if (isNewRequest) { ourPool.execute(parseScript); //todo bring back multithreading when Groovy team fixes http://jira.codehaus.org/browse/GROOVY-4292 //ApplicationManager.getApplication().executeOnPooledThread(parseScript); - return true; } } - return false; } private static volatile boolean stopGdsl = false; From 632af16797117af1dd3b08c2d805e831fd9678af Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 8 Nov 2010 16:27:17 +0300 Subject: [PATCH 31/61] IDEA-57673 --- .../lang/java/parser/DeclarationParser.java | 23 +++++++++++------ .../declarations/ConstructorBrackets.txt | 25 +++++++++++++++++++ .../parser/partial/DeclarationParserTest.java | 2 ++ 3 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-partial/declarations/ConstructorBrackets.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 8739aa717f49..ff9d1da681b8 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -291,7 +291,7 @@ public class DeclarationParser { declaration.rollbackTo(); return null; } - return parseMethodFromLeftParenth(builder, declaration, false); + return parseMethodFromLeftParenth(builder, declaration, false, true); } idPos.drop(); } @@ -345,7 +345,7 @@ public class DeclarationParser { if (typeParams == null) { emptyElement(type, JavaElementType.TYPE_PARAMETER_LIST); } - return parseMethodFromLeftParenth(builder, declaration, (context == Context.ANNOTATION_INTERFACE)); + return parseMethodFromLeftParenth(builder, declaration, (context == Context.ANNOTATION_INTERFACE), false); } } @@ -396,10 +396,17 @@ public class DeclarationParser { } private static PsiBuilder.Marker parseMethodFromLeftParenth(final PsiBuilder builder, final PsiBuilder.Marker declaration, - final boolean anno) { + final boolean anno, final boolean constructor) { parseParameterList(builder); - eatBrackets(builder); + if (constructor && builder.getTokenType() == JavaTokenType.LBRACKET) { + final PsiBuilder.Marker marker = builder.mark(); + eatBrackets(builder, false); + marker.error(JavaErrorMessages.message("expected.semicolon")); + } + else { + eatBrackets(builder, true); + } if (areTypeAnnotationsSupported(builder)) { final PsiBuilder.Marker receiver = builder.mark(); @@ -551,7 +558,7 @@ public class DeclarationParser { } if (expect(builder, JavaTokenType.IDENTIFIER)) { - eatBrackets(builder); + eatBrackets(builder, true); done(param, JavaElementType.PARAMETER); return param; } @@ -586,7 +593,7 @@ public class DeclarationParser { while (true) { shouldRollback = true; - if (!eatBrackets(builder)) { + if (!eatBrackets(builder, true)) { unclosed = true; } @@ -648,10 +655,10 @@ public class DeclarationParser { return declaration; } - private static boolean eatBrackets(final PsiBuilder builder) { + private static boolean eatBrackets(final PsiBuilder builder, final boolean withError) { while (expect(builder, JavaTokenType.LBRACKET)) { if (!expect(builder, JavaTokenType.RBRACKET)) { - error(builder, JavaErrorMessages.message("expected.rbracket")); + if (withError) error(builder, JavaErrorMessages.message("expected.rbracket")); return false; } } diff --git a/java/java-tests/testData/psi/parser-partial/declarations/ConstructorBrackets.txt b/java/java-tests/testData/psi/parser-partial/declarations/ConstructorBrackets.txt new file mode 100644 index 000000000000..69837ce54785 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/declarations/ConstructorBrackets.txt @@ -0,0 +1,25 @@ +PsiJavaFile:ConstructorBrackets.java + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiMethod:A + PsiModifierList: + + PsiTypeParameterList + + PsiIdentifier:A('A') + PsiParameterList:() + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiErrorElement:';' expected + PsiJavaToken:LBRACKET('[') + PsiJavaToken:RBRACKET(']') + PsiReferenceList + + PsiWhiteSpace(' ') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java index bbb58b422675..0638d948b230 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/DeclarationParserTest.java @@ -89,6 +89,8 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testUnclosed3() { doParserTest("{ void f(int a }", false, false); } public void testUnclosed4() { doParserTest("{ void f(int a,, }", false, false); } public void testUnclosed5() { doParserTest("{ void f(int a,); }", false, false); } + public void testConstructorBrackets() { doParserTest("{ A() [] { } }", false, false); } + public void testGenericMethod() { doParserTest("{ public static test();\n" + " void test1();\n" + " String test2(); }", false, false); } From 8ba3c2533f498c45e5c37144898aa7979a2479a4 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 8 Nov 2010 18:04:27 +0300 Subject: [PATCH 32/61] IDEA-21530 (restart IDEA in Linux) --- bin/nix/idea.sh | 5 ++++- .../application/impl/ApplicationImpl.java | 21 ++++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/bin/nix/idea.sh b/bin/nix/idea.sh index 07d8e1f03b15..941b392455aa 100644 --- a/bin/nix/idea.sh +++ b/bin/nix/idea.sh @@ -101,4 +101,7 @@ LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH export LD_LIBRARY_PATH cd "$IDEA_BIN_HOME" -exec $IDEA_JDK/bin/java $JVM_ARGS $IDEA_MAIN_CLASS_NAME $* +while true ; do + $IDEA_JDK/bin/java $JVM_ARGS -Djb.restart.code=88 $IDEA_MAIN_CLASS_NAME $* + test $? -ne 88 && break +done diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java index baac4465d04c..238ad166919c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java @@ -104,6 +104,9 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application private boolean myDoNotSave = false; private volatile boolean myDisposeInProgress = false; + private int myRestartCode = 0; + private volatile int myExitCode = 0; + private final AtomicBoolean mySaveSettingsIsInProgress = new AtomicBoolean(false); @SuppressWarnings({"UseOfArchaicSystemPropertyAccessors"}) private static final int ourDumpThreadsOnLongWriteActionWaiting = Integer.getInteger( System.getProperty("dump.threads.on.long.write.action.waiting"), 0); @@ -226,6 +229,14 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application } }); } + + final String s = System.getProperty("jb.restart.code"); + if (s != null) { + try { + myRestartCode = Integer.parseInt(s); + } catch (NumberFormatException ignore) { + } + } } private void registerShutdownHook() { @@ -678,7 +689,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application if (!canExit()) return; - if (disposeSelf()) System.exit(0); + if (disposeSelf()) System.exit(myExitCode); } }; @@ -1146,7 +1157,7 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application } public boolean isRestartCapable() { - return SystemInfo.isWindows || SystemInfo.isMacOSSnowLeopard; + return SystemInfo.isWindows || SystemInfo.isMacOSSnowLeopard || myRestartCode > 0; } public void restart() { @@ -1156,8 +1167,12 @@ public class ApplicationImpl extends ComponentManagerImpl implements Application else if (SystemInfo.isMacOSSnowLeopard) { MacRestarter.restart(); } + else if (myRestartCode > 0) { + myExitCode = myRestartCode; + exit(true); + } else { - exit(); + exit(true); } } From 2fb68882bfcefc33d11ea2b9c7acef3facad85f5 Mon Sep 17 00:00:00 2001 From: "Rustam.Vishnyakov" Date: Mon, 8 Nov 2010 18:12:31 +0300 Subject: [PATCH 33/61] Removing accidentally added file --- .../ide/scriptingContext/ui/ScriptingLibraryPanelBase.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryPanelBase.java diff --git a/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryPanelBase.java b/platform/lang-impl/src/com/intellij/ide/scriptingContext/ui/ScriptingLibraryPanelBase.java deleted file mode 100644 index e69de29bb2d1..000000000000 From 77540b993d40b23b0625b5e7ef2c9f845fd2a12b Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Mon, 8 Nov 2010 18:11:24 +0300 Subject: [PATCH 34/61] IDEA-60781 After formatting cursor jumps from indented position to beginning of the line. Added examination of return result of method marked by @Nullable --- .../psi/impl/source/codeStyle/CodeStyleManagerImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index d173349a1877..4e4d1813e0f6 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -170,6 +170,9 @@ public class CodeStyleManagerImpl extends CodeStyleManager { CaretModel caretModel = editor.getCaretModel(); String indent = getLineIndent(file, caretModel.getOffset()); + if (indent == null) { + return; + } int tabSize = getSettings().getTabSize(file.getFileType()); int indentColumn = indentWithInVisualColumns(indent, tabSize); VisualPosition position = caretModel.getVisualPosition(); From 1671bb9f622d3ac27277c49925145b523151bd95 Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Mon, 8 Nov 2010 18:20:36 +0300 Subject: [PATCH 35/61] IDEA-60669 Native Mac restarter crash --- .../src/com/intellij/openapi/application/impl/MacRestarter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java index 19d0c3bec596..10bf5ffa82a4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/MacRestarter.java @@ -44,7 +44,7 @@ public class MacRestarter { try { final String executablePath = Foundation.toStringViaUTF8(stringURL); final URL url = new URL(executablePath); - final String path = url.getPath(); + final String path = url.getPath().replace("%20", " "); if (path.contains(".app")) { final int appIndex = path.indexOf(".app"); final String appPath = path.substring(0, appIndex + 4); From e6ae8e36e9dbc4cfc12b6c0621533f5f1e564a50 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 17:41:32 +0300 Subject: [PATCH 36/61] copy files/dirs: focus on name --- .../intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java index ad35dd2be9b8..9f642f8b7d80 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java +++ b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesDialog.java @@ -120,7 +120,7 @@ class CopyFilesOrDirectoriesDialog extends DialogWrapper{ } public JComponent getPreferredFocusedComponent() { - return myShowDirectoryField ? myTargetDirectoryField.getChildComponent() : myNewNameField; + return myNewNameField; } protected JComponent createCenterPanel() { From b2f6c859f301a2f1f5d355ddf137a5df40d1da22 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 17:46:27 +0300 Subject: [PATCH 37/61] typo --- .../platform-resources-en/src/messages/IdeBundle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties index 32276921d6a3..0bad426867c8 100644 --- a/platform/platform-resources-en/src/messages/IdeBundle.properties +++ b/platform/platform-resources-en/src/messages/IdeBundle.properties @@ -848,7 +848,7 @@ label.implements.method.of_interfaces=implements methods of the following classe element.method=method element.of.interface=of interface element.of.class=of class -prompt.do.you.want.to.action_verb.the.method.from_class=Do you want to {0} the base {1,choice,1#method|2#methods}? +prompt.do.you.want.to.action_verb.the.method.from_class=Do you want {0} the base {1,choice,1#method|2#methods}? jar.no.java.modules.in.project.error=There are no Java modules found in the project.\nOnly Java modules can be jarred. jar.build.progress=Building jar {0}... jar.build.error.title=Error Creating Jar From eed35c8ed197a420f4a2168f1bdc5eb0cbe5f0b7 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 18:27:15 +0300 Subject: [PATCH 38/61] do not skip empty lines in copyrights --- .../src/com/maddyhome/idea/copyright/util/FileTypeUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java b/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java index fa52f2fd258a..f9559579f0fa 100644 --- a/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java +++ b/plugins/copyright/src/com/maddyhome/idea/copyright/util/FileTypeUtil.java @@ -162,7 +162,6 @@ public class FileTypeUtil { line = StringUtil.trimStart(StringUtil.trimStart(line.trim(), pre.toString()), open); line = StringUtil.trimEnd(line, close); - if (line.isEmpty()) continue; preview.append(leader).append(pre); int len = 0; if (pre.length() > 0 && line.length() > 0) From 9eac765bcdaadb8da36eccb4c5b5d1e3a918790d Mon Sep 17 00:00:00 2001 From: Sergey Evdokimov Date: Mon, 8 Nov 2010 18:48:24 +0300 Subject: [PATCH 39/61] Test for #IDEA-60927 --- .../refactoring/rename/RenameTest.groovy | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy index a921fe515d4e..c758b8d07696 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy @@ -186,7 +186,31 @@ class A { }""" } - + public void _testRenameFieldWithNonstandardName() { + def file = myFixture.configureByText("a.groovy", """ +class SomeBean { + String xXx = "field" + public String getxXx() { + return "method" + } + public static void main(String[] args) { + println(new SomeBean().xXx) + } +} +""") + myFixture.renameElementAtCaret "xXx777" + assertEquals """ +class SomeBean { + String xXx777 = "field" + public String getxXx777() { + return "method" + } + public static void main(String[] args) { + println(new SomeBean().xXx777) + } +} +""", file.text + } public void doTest() throws Throwable { final String testFile = getTestName(true).replace('$', '/') + ".test"; From 8c868505a3f175c2d9267c85c0fb41c476e4c191 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 8 Nov 2010 19:20:48 +0300 Subject: [PATCH 40/61] navbar location, focus and plainting fixes --- .../ide/navigationToolbar/NavBarPanel.java | 9 ++++---- .../src/com/intellij/ide/IdeEventQueue.java | 22 +++++++++++++++++++ .../wm/impl/ToolWindowManagerImpl.java | 18 +++++++++++---- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java index af4979d6bcfb..bc4b12ebf655 100644 --- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java +++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java @@ -103,7 +103,7 @@ public class NavBarPanel extends OpaquePanel.List implements DataProvider, Popup private LightweightHint myHint = null; private ListPopupImpl myNodePopup = null; - private Container myHintContainer; + private JComponent myHintContainer; private Component myContextComponent; private Runnable myRunWhenListRebuilt; @@ -1041,7 +1041,8 @@ public class NavBarPanel extends OpaquePanel.List implements DataProvider, Popup final AsyncResult result = new AsyncResult(); if (myHintContainer != null) { final Point p = AbstractPopup.getCenterOf(myHintContainer, this); - p.y -= myHintContainer.getHeight() / 4; + p.y -= myHintContainer.getVisibleRect().height / 4; + result.setDone(RelativePoint.fromScreen(p)); } else { @@ -1114,8 +1115,8 @@ public class NavBarPanel extends OpaquePanel.List implements DataProvider, Popup boolean selected = myModel.getSelectedIndex() == myIndex; - setPaintFocusBorder(selected); - setFocusBorderAroundIcon(true); + setPaintFocusBorder(!focused && selected); + setFocusBorderAroundIcon(false); setBackground(selected && focused ? UIUtil.getListSelectionBackground() diff --git a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java index b5efa1e0163a..65e04b9340a6 100644 --- a/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java +++ b/platform/platform-impl/src/com/intellij/ide/IdeEventQueue.java @@ -39,6 +39,7 @@ import com.intellij.util.Alarm; import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -48,6 +49,7 @@ import java.awt.event.*; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.*; @@ -569,6 +571,26 @@ public class IdeEventQueue extends EventQueue { if (!mouseEventsAhead) { Window showingWindow = mgr.getActiveWindow(); + if (showingWindow == null) { + Method getNativeFocusOwner = ReflectionUtil.getDeclaredMethod(KeyboardFocusManager.class, "getNativeFocusOwner"); + if (getNativeFocusOwner != null) { + getNativeFocusOwner.setAccessible(true); + try { + Object owner = getNativeFocusOwner.invoke(mgr); + if (owner instanceof Component) { + Component nativeFocusOwner = (Component)owner; + if (nativeFocusOwner instanceof Window) { + showingWindow = (Window)nativeFocusOwner; + } else { + showingWindow = SwingUtilities.getWindowAncestor(nativeFocusOwner); + } + } + } + catch (Exception e1) { + LOG.debug(e1); + } + } + } if (showingWindow != null) { final IdeFocusManager fm = IdeFocusManager.findInstanceByComponent(showingWindow); Runnable requestDefaultFocus = new Runnable() { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java index 273f62fea55f..adf6866eacf3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java @@ -496,19 +496,29 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements } private void activateEditorComponent(final boolean forced) { + activateEditorComponent(forced, false); + } + private void activateEditorComponent(final boolean forced, boolean now) { if (LOG.isDebugEnabled()) { LOG.debug("enter: activateEditorComponent()"); } ApplicationManager.getApplication().assertIsDispatchThread(); - getFocusManager().doWhenFocusSettlesDown(new Runnable() { + Runnable runnable = new Runnable() { @Override public void run() { final ArrayList commandList = new ArrayList(); activateEditorComponentImpl(getSplittersFromFocus(), commandList, forced); execute(commandList); } - }); + }; + + if (now) { + runnable.run(); + } else { + getFocusManager().doWhenFocusSettlesDown(runnable); + + } } private EditorsSplitters getSplittersFromFocus() { @@ -2035,10 +2045,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements if (ModalityState.NON_MODAL.equals(ModalityState.current())) { final String activeId = getActiveToolWindowId(); if (myEditorComponentActive || activeId == null || getToolWindow(activeId) == null) { - activateEditorComponent(forced); + activateEditorComponent(forced, true); } else { - activateToolWindow(activeId, forced, false); + activateToolWindow(activeId, forced, true); } } return new ActionCallback.Done(); From fa53d89041ac7eba2b7c1dadf65f61197f63b850 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Mon, 8 Nov 2010 19:16:36 +0300 Subject: [PATCH 41/61] lookup progress which doesn't lead to size jumping --- .../codeInsight/lookup/impl/LookupImpl.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java index 55cdba73dde1..c3d1ec195f9e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupImpl.java @@ -97,6 +97,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { private boolean myFocused = true; private String myAdditionalPrefix = ""; private final AsyncProcessIcon myProcessIcon = new AsyncProcessIcon("Completion progress"); + private final JPanel myIconPanel = new JPanel(new BorderLayout()); private volatile boolean myCalculating; private final JLabel myAdComponent; private volatile String myAdText; @@ -112,7 +113,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { myProject = project; myEditor = editor; - myProcessIcon.setVisible(false); + myIconPanel.setVisible(false); myCellRenderer = new LookupCellRenderer(this); myList.setCellRenderer(myCellRenderer); @@ -127,14 +128,13 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { getComponent().add(scrollPane, BorderLayout.NORTH); scrollPane.setBorder(null); - JPanel bottomPanel = new JPanel(new BorderLayout()); - - bottomPanel.add(myProcessIcon, BorderLayout.EAST); myAdComponent = HintUtil.createAdComponent(null); - bottomPanel.add(myAdComponent, BorderLayout.CENTER); - getComponent().add(bottomPanel, BorderLayout.SOUTH); + getComponent().add(myAdComponent, BorderLayout.SOUTH); getComponent().setBorder(new BegPopupMenuBorder()); + myIconPanel.setBackground(Color.LIGHT_GRAY); + myIconPanel.add(myProcessIcon); + final ListModel model = myList.getModel(); addEmptyItem((DefaultListModel)model); updateListHeight(model); @@ -164,7 +164,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { public void setCalculating(final boolean calculating) { myCalculating = calculating; - myProcessIcon.setVisible(calculating); + myIconPanel.setVisible(calculating); if (calculating) { myProcessIcon.resume(); } else { @@ -306,11 +306,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { updateListHeight(model); - myAdComponent.setPreferredSize(null); myAdComponent.setText(myAdText); - if (myAdText != null) { - myAdComponent.setPreferredSize(new Dimension(myAdComponent.getPreferredSize().width, myProcessIcon.getPreferredSize().height)); - } if (hasItems) { myList.setFixedCellWidth(Math.max(myLookupTextWidth + myCellRenderer.getIconIndent(), myAdComponent.getPreferredSize().width)); @@ -584,6 +580,8 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl(); hintManager.showEditorHint(this, myEditor, p, HintManagerImpl.HIDE_BY_ESCAPE | HintManagerImpl.UPDATE_BY_SCROLLING, 0, false); + getComponent().getRootPane().getLayeredPane().add(myIconPanel, 42, 0); + myShownStamp = System.currentTimeMillis(); } @@ -976,6 +974,9 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { Point point = calculatePosition(); updateBounds(point.x,point.y); + final Dimension size = myProcessIcon.getPreferredSize(); + myIconPanel.setBounds(getComponent().getRootPane().getLayeredPane().getWidth() - size.width, 0, size.width, size.height); + HintManagerImpl.adjustEditorHintPosition(this, myEditor, point); } } From 487b0edba89ca90a08a14d099eb22dca6622dd38 Mon Sep 17 00:00:00 2001 From: "peter.gromov" Date: Mon, 8 Nov 2010 19:22:50 +0300 Subject: [PATCH 42/61] more interruptibility in class name completion --- .../impl/search/AllClassesSearchExecutor.java | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java b/java/java-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java index 817c937cf562..e2fcbcec8acd 100644 --- a/java/java-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java +++ b/java/java-impl/src/com/intellij/psi/impl/search/AllClassesSearchExecutor.java @@ -20,6 +20,7 @@ package com.intellij.psi.impl.search; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.util.Computable; import com.intellij.psi.*; @@ -32,8 +33,10 @@ import com.intellij.util.Processor; import com.intellij.util.QueryExecutor; import org.jetbrains.annotations.NotNull; -import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; import java.util.Comparator; +import java.util.List; public class AllClassesSearchExecutor implements QueryExecutor { public boolean execute(@NotNull final AllClassesSearch.SearchParameters queryParameters, @NotNull final Processor consumer) { @@ -61,16 +64,34 @@ public class AllClassesSearchExecutor implements QueryExecutor() { + + final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); + if (indicator != null) { + indicator.checkCanceled(); + } + + List sorted = new ArrayList(names.length); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (parameters.nameMatches(name)) { + sorted.add(name); + } + if (indicator != null && i % 512 == 0) { + indicator.checkCanceled(); + } + } + + if (indicator != null) { + indicator.checkCanceled(); + } + + Collections.sort(sorted, new Comparator() { public int compare(final String o1, final String o2) { return o1.compareToIgnoreCase(o2); } }); - for (final String name : names) { - if (!parameters.nameMatches(name)) continue; - + for (final String name : sorted) { ProgressManager.checkCanceled(); final PsiClass[] classes = ApplicationManager.getApplication().runReadAction(new Computable() { public PsiClass[] compute() { From ab1944d3cd10d17b8bef302f925d507e1c391860 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 8 Nov 2010 19:39:30 +0300 Subject: [PATCH 43/61] editor framgent tooltip rolled back to be non-balloon --- .../com/intellij/codeInsight/hint/EditorFragmentComponent.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/EditorFragmentComponent.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/EditorFragmentComponent.java index 9745fe537891..353aac65b256 100644 --- a/platform/platform-impl/src/com/intellij/codeInsight/hint/EditorFragmentComponent.java +++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/EditorFragmentComponent.java @@ -24,6 +24,7 @@ import com.intellij.openapi.editor.colors.EditorColorsScheme; import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.editor.ex.FoldingModelEx; import com.intellij.openapi.util.TextRange; +import com.intellij.ui.HintHint; import com.intellij.ui.LightweightHint; import com.intellij.ui.ScreenUtil; import org.jetbrains.annotations.Nullable; @@ -152,7 +153,7 @@ public class EditorFragmentComponent extends JPanel { Point p = new Point(x, y); LightweightHint hint = new MyComponentHint(fragmentComponent); - HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, p, (hideByAnyKey ? HintManagerImpl.HIDE_BY_ANY_KEY : 0) | HintManagerImpl.HIDE_BY_TEXT_CHANGE, 0, false); + HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, p, (hideByAnyKey ? HintManagerImpl.HIDE_BY_ANY_KEY : 0) | HintManagerImpl.HIDE_BY_TEXT_CHANGE, 0, false, new HintHint(editor, p)); return hint; } From a795a7e5659e1a093fd9d5619169c3ee9d47927b Mon Sep 17 00:00:00 2001 From: Alexey Pegov Date: Mon, 8 Nov 2010 20:04:08 +0300 Subject: [PATCH 44/61] IDEA-60931 Tabs color goes away on restart --- .../src/com/intellij/ui/tabs/FileColorManagerImpl.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java index 839af348ada3..2f6866f58737 100644 --- a/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/ui/tabs/FileColorManagerImpl.java @@ -188,6 +188,8 @@ public class FileColorManagerImpl extends FileColorManager implements Persistent @Nullable public Color getFileColor(@NotNull final PsiFile file) { + initSharedConfigurations(); + final String colorName = myModel.getColor(file); return colorName == null ? null : getColor(colorName); } From 2d98b6c538c5e4ce6ded0a7f81926bf8fb526f2f Mon Sep 17 00:00:00 2001 From: Eugene Kudelevsky Date: Mon, 8 Nov 2010 20:27:28 +0300 Subject: [PATCH 45/61] clean up --- .../src/org/jetbrains/android/facet/AndroidFacetEditorTab.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java index 8040b125acf8..d1bef6b08245 100644 --- a/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java +++ b/plugins/android/src/org/jetbrains/android/facet/AndroidFacetEditorTab.java @@ -455,7 +455,7 @@ public class AndroidFacetEditorTab extends FacetEditorTab { myConfiguration.ASSETS_FOLDER_RELATIVE_PATH = '/' + getAndCheckRelativePath(absAssetsPath, false); String absApkPath = (String)myApkPathCombo.getComboBox().getEditor().getItem(); - if (absResPath.length() == 0) { + if (absApkPath.length() == 0) { myConfiguration.APK_PATH = ""; } else { From e4cb6a0eed1c8f8fee290446b003971dc1a6398b Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 19:20:57 +0300 Subject: [PATCH 46/61] dispose configurables after show --- .../src/com/intellij/ide/ui/search/TraverseUIStarter.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java b/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java index 4f4fb0b1ed0b..c8959d4836cf 100644 --- a/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java +++ b/platform/lang-impl/src/com/intellij/ide/ui/search/TraverseUIStarter.java @@ -27,6 +27,7 @@ import com.intellij.openapi.application.ex.ApplicationEx; import com.intellij.openapi.keymap.impl.ui.KeymapConfigurable; import com.intellij.openapi.options.SearchableConfigurable; import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.JDOMUtil; import org.jdom.Document; import org.jdom.Element; @@ -98,6 +99,7 @@ public class TraverseUIStarter implements ApplicationStarter { processCodeStyleConfigurable((CodeStyleSchemesConfigurable)configurable, configurableElement); } root.addContent(configurableElement); + configurable.disposeUIResources(); } JDOMUtil.writeDocument(new Document(root), OUTPUT_PATH, "\n"); From a623497e60c72060fb9794b640563e97d7b73489 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 20:23:09 +0300 Subject: [PATCH 47/61] revert to prevent .iml changes --- .../src/com/intellij/openapi/roots/impl/ContentEntryImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java index 4f3aa9cd05ec..f7260d85a6c6 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ContentEntryImpl.java @@ -44,7 +44,7 @@ public class ContentEntryImpl extends RootModelComponentBase implements ContentE private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.SimpleContentEntryImpl"); private final VirtualFilePointer myRoot; @NonNls public static final String ELEMENT_NAME = "content"; - private final TreeSet mySourceFolders = new TreeSet(ContentFolderComparator.INSTANCE); + private final LinkedHashSet mySourceFolders = new LinkedHashSet(); private final TreeSet myExcludeFolders = new TreeSet(ContentFolderComparator.INSTANCE); private final TreeSet myExcludedOutputFolders = new TreeSet(ContentFolderComparator.INSTANCE); @NonNls public static final String URL_ATTRIBUTE = "url"; From fbf39dca255fc548e1ebdb8eaacc43ad40fa258b Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 20:24:16 +0300 Subject: [PATCH 48/61] .iml changes --- plugins/git4idea/git4idea.iml | 2 +- plugins/hg4idea/hg4idea.iml | 2 +- plugins/properties/properties.iml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/git4idea/git4idea.iml b/plugins/git4idea/git4idea.iml index 2079f73db038..aabff7b1f236 100644 --- a/plugins/git4idea/git4idea.iml +++ b/plugins/git4idea/git4idea.iml @@ -4,9 +4,9 @@ + - diff --git a/plugins/hg4idea/hg4idea.iml b/plugins/hg4idea/hg4idea.iml index 1c036a8a3851..383f5ce51cbe 100644 --- a/plugins/hg4idea/hg4idea.iml +++ b/plugins/hg4idea/hg4idea.iml @@ -3,8 +3,8 @@ - + diff --git a/plugins/properties/properties.iml b/plugins/properties/properties.iml index cec4a8781319..2aaee73917cc 100644 --- a/plugins/properties/properties.iml +++ b/plugins/properties/properties.iml @@ -3,8 +3,8 @@ - + From 110b31053641763cf7e77a6a837248f7b9a55698 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 8 Nov 2010 20:36:30 +0300 Subject: [PATCH 49/61] table header font AA. mousewheel font size handler. WI-3862 Query results table cells should be scaled with the font size. --- .../src/com/intellij/ui/table/JBTable.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/platform/platform-api/src/com/intellij/ui/table/JBTable.java b/platform/platform-api/src/com/intellij/ui/table/JBTable.java index bda2de982314..ad5dd5b426c1 100644 --- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java +++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java @@ -89,6 +89,19 @@ public class JBTable extends JTable implements ComponentWithEmptyText, Component boolean marker = Patches.SUN_BUG_ID_4503845; // Don't remove. It's a marker for find usages } + @Override + protected JTableHeader createDefaultTableHeader() { + return new JTableHeader(columnModel) { + @Override + public void paint(Graphics g) { + if (myEnableAntialiasing) { + UISettings.setupAntialiasing(g); + } + super.paint(g); + } + }; + } + public boolean isEmpty() { return getRowCount() == 0; } From f7c661302b508ad7e62f121731c63978da77ee96 Mon Sep 17 00:00:00 2001 From: Kirill Kalishev Date: Mon, 8 Nov 2010 21:14:28 +0300 Subject: [PATCH 50/61] change marker tooltip rolled back to be non-balloon --- .../com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java index 53d50e986dc3..d6a019e047a4 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ex/LineStatusTrackerDrawing.java @@ -41,6 +41,7 @@ import com.intellij.openapi.vcs.actions.ShowNextChangeMarkerAction; import com.intellij.openapi.vcs.actions.ShowPrevChangeMarkerAction; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.ui.ColoredSideBorder; +import com.intellij.ui.HintHint; import com.intellij.ui.HintListener; import com.intellij.ui.LightweightHint; import com.intellij.util.ui.UIUtil; @@ -208,7 +209,7 @@ public class LineStatusTrackerDrawing { HintManagerImpl.getInstanceImpl().showEditorHint(lightweightHint, editor, point, HintManagerImpl.HIDE_BY_ANY_KEY | HintManagerImpl.HIDE_BY_TEXT_CHANGE | HintManagerImpl.HIDE_BY_OTHER_HINT | HintManagerImpl.HIDE_BY_SCROLLING, - -1, false); + -1, false, new HintHint(editor, point)); } private static String getFileName(final Document document) { From 5f484eea21a2bfd602629cb14c839dba8fd089d6 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 21:21:14 +0300 Subject: [PATCH 51/61] type text fixed --- .../introduceVariable/IntroduceVariableBase.java | 5 +++-- .../introduceVariable/ReassignVariableUtil.java | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 2801ef9574c3..bbed1f676aa0 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -480,8 +480,9 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme final VariableInplaceRenamer renamer = new VariableInplaceRenamer(elementToRename, editor){ @Override protected void addAdditionalVariables(TemplateBuilderImpl builder) { - builder.replaceElement(elementToRename.getTypeElement(), "Variable_Type", ReassignVariableUtil - .createExpression(typeSelectorManager), false, true); + final PsiTypeElement typeElement = elementToRename.getTypeElement(); + builder.replaceElement(typeElement, "Variable_Type", ReassignVariableUtil + .createExpression(typeSelectorManager, typeElement.getText()), false, true); } }; renamer.setAdvertisementText( diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java index 2eec696a185d..e0d2aa29f2e7 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java @@ -150,24 +150,24 @@ public class ReassignVariableUtil { } } - static Expression createExpression(final TypeSelectorManagerImpl typeSelectorManager) { + static Expression createExpression(final TypeSelectorManagerImpl typeSelectorManager, final String defaultText) { final PsiType[] types = typeSelectorManager.getTypesForAll(); return new Expression() { @Override public com.intellij.codeInsight.template.Result calculateResult(ExpressionContext context) { - return new TextResult(typeSelectorManager.getDefaultType().getPresentableText()); + return new TextResult(defaultText); } @Override public com.intellij.codeInsight.template.Result calculateQuickResult(ExpressionContext context) { - return new TextResult(typeSelectorManager.getDefaultType().getPresentableText()); + return new TextResult(defaultText); } @Override public LookupElement[] calculateLookupItems(ExpressionContext context) { LookupElement[] result = new LookupElement[types.length]; for (int i = 0, typesLength = types.length; i < typesLength; i++) { - result[i] = LookupElementBuilder.create(types[i].getPresentableText()); + result[i] = LookupElementBuilder.create(types[i], types[i].getPresentableText()); } return result; } From 09ff5078dc7d6a65126abf1361a76c9478ebcca1 Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 8 Nov 2010 21:28:34 +0300 Subject: [PATCH 52/61] suggest shift tab when there is another type to suggest --- .../refactoring/introduceVariable/IntroduceVariableBase.java | 2 +- .../refactoring/introduceVariable/ReassignVariableUtil.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index bbed1f676aa0..b5dc13ba4f83 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -486,7 +486,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme } }; renamer.setAdvertisementText( - ReassignVariableUtil.getAdvertisementText(editor, declarationStatement, elementToRename.getType())); + ReassignVariableUtil.getAdvertisementText(editor, declarationStatement, elementToRename.getType(), typeSelectorManager.getTypesForAll())); renamer.performInplaceRename(false, new LinkedHashSet(Arrays.asList(suggestedName.names)), new Consumer() { @Override public void consume(Boolean apply) { diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java index e0d2aa29f2e7..9e76662587ed 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/ReassignVariableUtil.java @@ -174,7 +174,8 @@ public class ReassignVariableUtil { }; } - static String getAdvertisementText(Editor editor, PsiDeclarationStatement declaration, PsiType type) { + @Nullable + static String getAdvertisementText(Editor editor, PsiDeclarationStatement declaration, PsiType type, PsiType[] typesForAll) { final VariablesProcessor processor = findVariablesOfType(editor, declaration, type); if (processor.size() > 0) { final Keymap keymap = KeymapManager.getInstance().getActiveKeymap(); @@ -183,6 +184,6 @@ public class ReassignVariableUtil { return "Press " + shortcuts[0] + " to reassign existing variable"; } } - return "Press Shift Tab to change type"; + return typesForAll.length > 1 ? "Press Shift Tab to change type" : null; } } From 1991d544cc107ad3128547f8def1e636dac95bfa Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 8 Nov 2010 18:40:34 +0300 Subject: [PATCH 53/61] Missed test data added --- plugins/ant/tests/data/psi/Dirname_u.txt | 57 ++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 plugins/ant/tests/data/psi/Dirname_u.txt diff --git a/plugins/ant/tests/data/psi/Dirname_u.txt b/plugins/ant/tests/data/psi/Dirname_u.txt new file mode 100644 index 000000000000..ea49effbd1e5 --- /dev/null +++ b/plugins/ant/tests/data/psi/Dirname_u.txt @@ -0,0 +1,57 @@ +XmlFile:Dirname.ant + PsiElement(XML_DOCUMENT) + PsiElement(XML_PROLOG) + + XmlTag:project + XmlToken:XML_START_TAG_START('<') + XmlToken:XML_NAME('project') + PsiWhiteSpace(' ') + PsiElement(XML_ATTRIBUTE) + XmlToken:XML_NAME('default') + XmlToken:XML_EQ('=') + PsiElement(XML_ATTRIBUTE_VALUE) + XmlToken:XML_ATTRIBUTE_VALUE_START_DELIMITER('"') + XmlToken:XML_ATTRIBUTE_VALUE_TOKEN('A') + XmlToken:XML_ATTRIBUTE_VALUE_END_DELIMITER('"') + XmlToken:XML_TAG_END('>') + XmlText + PsiWhiteSpace('\n ') + XmlTag:dirname + XmlToken:XML_START_TAG_START('<') + XmlToken:XML_NAME('dirname') + PsiWhiteSpace(' ') + PsiElement(XML_ATTRIBUTE) + XmlToken:XML_NAME('property') + XmlToken:XML_EQ('=') + PsiElement(XML_ATTRIBUTE_VALUE) + XmlToken:XML_ATTRIBUTE_VALUE_START_DELIMITER('"') + XmlToken:XML_ATTRIBUTE_VALUE_TOKEN('prop') + XmlToken:XML_ATTRIBUTE_VALUE_END_DELIMITER('"') + PsiWhiteSpace(' ') + PsiElement(XML_ATTRIBUTE) + XmlToken:XML_NAME('file') + XmlToken:XML_EQ('=') + PsiElement(XML_ATTRIBUTE_VALUE) + XmlToken:XML_ATTRIBUTE_VALUE_START_DELIMITER('"') + XmlToken:XML_ATTRIBUTE_VALUE_TOKEN('${ant.file}') + XmlToken:XML_ATTRIBUTE_VALUE_END_DELIMITER('"') + XmlToken:XML_EMPTY_ELEMENT_END('/>') + XmlText + PsiWhiteSpace('\n ') + XmlTag:target + XmlToken:XML_START_TAG_START('<') + XmlToken:XML_NAME('target') + PsiWhiteSpace(' ') + PsiElement(XML_ATTRIBUTE) + XmlToken:XML_NAME('name') + XmlToken:XML_EQ('=') + PsiElement(XML_ATTRIBUTE_VALUE) + XmlToken:XML_ATTRIBUTE_VALUE_START_DELIMITER('"') + XmlToken:XML_ATTRIBUTE_VALUE_TOKEN('A') + XmlToken:XML_ATTRIBUTE_VALUE_END_DELIMITER('"') + XmlToken:XML_EMPTY_ELEMENT_END('/>') + XmlText + PsiWhiteSpace('\n') + XmlToken:XML_END_TAG_START('') \ No newline at end of file From cb1db6171b604c8d917843e9159be65b365fea84 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 8 Nov 2010 21:06:30 +0300 Subject: [PATCH 54/61] IDEA-57674 (parameterized explicit constructor call) --- .../lang/java/parser/ExpressionParser.java | 36 +++++++++++++------ .../PinesInReferenceExpression2.txt | 17 +++++++++ .../parser/partial/ExpressionParserTest.java | 1 + 3 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression2.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index ac329b05bfea..a7d00b29c069 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -59,6 +59,7 @@ public class ExpressionParser { private static final TokenSet ARGS_LIST_END = TokenSet.create(JavaTokenType.RPARENTH, JavaTokenType.RBRACE, JavaTokenType.RBRACKET); private static final TokenSet ARGS_LIST_CONTINUE = TokenSet.create( JavaTokenType.IDENTIFIER, TokenType.BAD_CHARACTER, JavaTokenType.COMMA, JavaTokenType.INTEGER_LITERAL, JavaTokenType.STRING_LITERAL); + private static final TokenSet CONSTRUCTOR_CALL = TokenSet.create(JavaTokenType.THIS_KEYWORD, JavaTokenType.SUPER_KEYWORD); private ExpressionParser() { } @@ -553,18 +554,33 @@ public class ExpressionParser { beforeAnnotation.drop(); } - if (tokenType == JavaTokenType.THIS_KEYWORD) { - final PsiBuilder.Marker expr = builder.mark(); - builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST); - builder.advanceLexer(); - expr.done(builder.getTokenType() != JavaTokenType.LPARENTH ? JavaElementType.THIS_EXPRESSION : JavaElementType.REFERENCE_EXPRESSION); - return expr; + PsiBuilder.Marker expr = null; + if (tokenType == JavaTokenType.LT) { + expr = builder.mark(); + + if (!ReferenceParser.parseReferenceParameterList(builder, false, false)) { + expr.rollbackTo(); + return null; + } + + tokenType = builder.getTokenType(); + if (!CONSTRUCTOR_CALL.contains(tokenType)) { + expr.rollbackTo(); + return null; + } } - if (tokenType == JavaTokenType.SUPER_KEYWORD) { - final PsiBuilder.Marker expr = builder.mark(); - builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST); + + if (CONSTRUCTOR_CALL.contains(tokenType)) { + if (expr == null) { + expr = builder.mark(); + builder.mark().done(JavaElementType.REFERENCE_PARAMETER_LIST); + } builder.advanceLexer(); - expr.done(builder.getTokenType() != JavaTokenType.LPARENTH ? JavaElementType.SUPER_EXPRESSION : JavaElementType.REFERENCE_EXPRESSION); + expr.done(builder.getTokenType() == JavaTokenType.LPARENTH + ? JavaElementType.REFERENCE_EXPRESSION + : tokenType == JavaTokenType.THIS_KEYWORD + ? JavaElementType.THIS_EXPRESSION + : JavaElementType.SUPER_EXPRESSION); return expr; } if (tokenType == JavaTokenType.NEW_KEYWORD) { diff --git a/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression2.txt b/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression2.txt new file mode 100644 index 000000000000..52b37d3ab61b --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/expressions/PinesInReferenceExpression2.txt @@ -0,0 +1,17 @@ +PsiJavaFile:PinesInReferenceExpression2.java + PsiMethodCallExpression:super(null) + PsiReferenceExpression:super + PsiReferenceParameterList + PsiJavaToken:LT('<') + PsiTypeElement:String + PsiJavaCodeReferenceElement:String + PsiIdentifier:String('String') + PsiReferenceParameterList + + PsiJavaToken:GT('>') + PsiKeyword:super('super') + PsiExpressionList + PsiJavaToken:LPARENTH('(') + PsiLiteralExpression:null + PsiJavaToken:NULL_KEYWORD('null') + PsiJavaToken:RPARENTH(')') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java index c5fb275f7855..6b294d9083fc 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/ExpressionParserTest.java @@ -92,6 +92,7 @@ public class ExpressionParserTest extends JavaParsingTestCase { public void testPinesInReferenceExpression0() { doParserTest("Collections.sort(null)"); } public void testPinesInReferenceExpression1() { doParserTest("this.sort(null)"); } + public void testPinesInReferenceExpression2() { doParserTest("super(null)"); } public void testGE0() { doParserTest("x >>>= 8 >> 2"); } public void testGE1() { doParserTest("x >= 2"); } From 0c39d517a5d959941f51e98350612963cc8ca405 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Mon, 8 Nov 2010 21:40:48 +0300 Subject: [PATCH 55/61] IDEA-56188 (trailing comma in annotation value array initializer) --- .../lang/java/parser/DeclarationParser.java | 4 +++- .../annotations/ExtraCommaInList.txt | 21 +++++++++++++++++++ .../parser/partial/AnnotationParserTest.java | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/psi/parser-partial/annotations/ExtraCommaInList.txt diff --git a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index ff9d1da681b8..47b60ef7d599 100644 --- a/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -817,7 +817,9 @@ public class DeclarationParser { break; } else if (expect(builder, JavaTokenType.COMMA)) { - parseAnnotationValue(builder); + if (builder.getTokenType() != JavaTokenType.RBRACE) { + parseAnnotationValue(builder); + } } else { error(builder, JavaErrorMessages.message("expected.rbrace")); diff --git a/java/java-tests/testData/psi/parser-partial/annotations/ExtraCommaInList.txt b/java/java-tests/testData/psi/parser-partial/annotations/ExtraCommaInList.txt new file mode 100644 index 000000000000..c58fc1971df5 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/annotations/ExtraCommaInList.txt @@ -0,0 +1,21 @@ +PsiJavaFile:ExtraCommaInList.java + PsiAnnotation + PsiJavaToken:AT('@') + PsiJavaCodeReferenceElement:Anno + PsiIdentifier:Anno('Anno') + PsiReferenceParameterList + + PsiAnnotationParameterList + PsiJavaToken:LPARENTH('(') + PsiNameValuePair + PsiArrayInitializerMemberValue:{0, 1,} + PsiJavaToken:LBRACE('{') + PsiLiteralExpression:0 + PsiJavaToken:INTEGER_LITERAL('0') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiLiteralExpression:1 + PsiJavaToken:INTEGER_LITERAL('1') + PsiJavaToken:COMMA(',') + PsiJavaToken:RBRACE('}') + PsiJavaToken:RPARENTH(')') diff --git a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java index 6cad51311ea7..e0a38e2a58dd 100644 --- a/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/lang/java/parser/partial/AnnotationParserTest.java @@ -33,6 +33,7 @@ public class AnnotationParserTest extends JavaParsingTestCase { public void testArray() { doParserTest("@Endorsers({\"Children\", \"Unscrupulous dentists\"})"); } public void testNested() { doParserTest("@Author(@Name(first=\"Eugene\", second=\"Wampirchik\"))"); } public void testQualifiedAnnotation() { doParserTest("@org.jetbrains.annotations.Nullable"); } + public void testExtraCommaInList() { doParserTest("@Anno({0, 1,})"); } public void testParameterizedAnnotation () { doParserTest("@Nullable"); } public void testFirstNameMissed() { doParserTest("@Anno(value1, param2=value2)"); } From 6df7ba3e8e9937b03f6178830f2996d0c277a1cd Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 8 Nov 2010 19:55:24 +0100 Subject: [PATCH 56/61] more accurate "unnecessary 'this' qualifier" inspection, less code --- .../ConstantIfStatementInspection.java | 104 ++------ .../ig/psiutils/VariableSearchUtils.java | 231 +++--------------- .../ig/style/UnnecessaryThisInspection.java | 51 +++- .../UnnecessaryThisInspection.java | 16 ++ .../style/unnecessary_this/expected.xml | 8 + .../style/UnnecessaryThisInspectionTest.java | 3 +- 6 files changed, 110 insertions(+), 303 deletions(-) diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java index 159382a39c89..840feb65f3ac 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 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. @@ -26,33 +26,36 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.psiutils.BoolUtils; +import com.siyeh.ig.psiutils.VariableSearchUtils; import org.jetbrains.annotations.NotNull; -import java.util.HashSet; -import java.util.Set; - public class ConstantIfStatementInspection extends BaseInspection { + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message( "constant.if.statement.display.name"); } + @Override public boolean isEnabledByDefault() { return true; } + @Override @NotNull protected String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "constant.if.statement.problem.descriptor"); } + @Override public BaseInspectionVisitor buildVisitor() { return new ConstantIfStatementVisitor(); } + @Override public InspectionGadgetsFix buildFix(Object... infos) { //if (PsiUtil.isInJspFile(location)) { // return null; @@ -103,7 +106,8 @@ public class ConstantIfStatementInspection extends BaseInspection { final PsiCodeBlock block = ((PsiBlockStatement)branch).getCodeBlock(); final boolean hasConflicts = - containsConflictingDeclarations(block, parentBlock); + VariableSearchUtils.containsConflictingDeclarations( + block, parentBlock); if (hasConflicts) { final String elseText = branch.getText(); replaceStatement(statement, elseText); @@ -112,9 +116,12 @@ public class ConstantIfStatementInspection extends BaseInspection { final PsiStatement[] statements = block.getStatements(); if (statements.length > 0) { assert containingElement != null; - final PsiElement added = containingElement.addRangeBefore(statements[0], statements[statements.length - 1], statement); + final PsiElement added = + containingElement.addRangeBefore(statements[0], + statements[statements.length - 1], statement); final Project project = statement.getProject(); - final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project); + final CodeStyleManager codeStyleManager = + CodeStyleManager.getInstance(project); codeStyleManager.reformat(added); } statement.delete(); @@ -124,43 +131,6 @@ public class ConstantIfStatementInspection extends BaseInspection { replaceStatement(statement, elseText); } } - - private static boolean containsConflictingDeclarations( - PsiCodeBlock block, PsiCodeBlock parentBlock) { - final PsiStatement[] statements = block.getStatements(); - final Set declaredVars = new HashSet(); - for (final PsiStatement statement : statements) { - if (statement instanceof PsiDeclarationStatement) { - final PsiDeclarationStatement declaration = - (PsiDeclarationStatement)statement; - final PsiElement[] vars = declaration.getDeclaredElements(); - for (PsiElement var : vars) { - if (var instanceof PsiLocalVariable) { - declaredVars.add(var); - } - } - } - } - for (Object declaredVar : declaredVars) { - final PsiLocalVariable variable = - (PsiLocalVariable)declaredVar; - final String variableName = variable.getName(); - if (conflictingDeclarationExists(variableName, parentBlock, - block)) { - return true; - } - } - return false; - } - - private static boolean conflictingDeclarationExists( - String name, PsiCodeBlock parentBlock, - PsiCodeBlock exceptBlock) { - final ConflictingDeclarationVisitor visitor = - new ConflictingDeclarationVisitor(name, exceptBlock); - parentBlock.accept(visitor); - return visitor.hasConflictingDeclaration(); - } } private static class ConstantIfStatementVisitor @@ -181,50 +151,4 @@ public class ConstantIfStatementInspection extends BaseInspection { } } } - - private static class ConflictingDeclarationVisitor - extends JavaRecursiveElementVisitor { - - private final String variableName; - private final PsiCodeBlock exceptBlock; - private boolean hasConflictingDeclaration = false; - - ConflictingDeclarationVisitor(String variableName, - PsiCodeBlock exceptBlock) { - super(); - this.variableName = variableName; - this.exceptBlock = exceptBlock; - } - - @Override public void visitElement(@NotNull PsiElement element) { - if (!hasConflictingDeclaration) { - super.visitElement(element); - } - } - - @Override public void visitCodeBlock(PsiCodeBlock block) { - if (hasConflictingDeclaration) { - return; - } - if (block.equals(exceptBlock)) { - return; - } - super.visitCodeBlock(block); - } - - @Override public void visitVariable(PsiVariable variable) { - if (hasConflictingDeclaration) { - return; - } - super.visitVariable(variable); - final String name = variable.getName(); - if (name != null && name.equals(variableName)) { - hasConflictingDeclaration = true; - } - } - - public boolean hasConflictingDeclaration() { - return hasConflictingDeclaration; - } - } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableSearchUtils.java b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableSearchUtils.java index a1ba06ec29ee..987c86b287d4 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableSearchUtils.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/psiutils/VariableSearchUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 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. @@ -15,226 +15,55 @@ */ package com.siyeh.ig.psiutils; +import com.intellij.openapi.project.Project; import com.intellij.psi.*; -import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; -import java.util.Set; public class VariableSearchUtils { private VariableSearchUtils() {} - public static boolean existsLocalOrParameter(@NotNull String variableName, - @Nullable PsiElement context) { - if (context == null) { - return false; - } - if (existsParameter(variableName, context)) { - return true; - } - if (existsLocal(variableName, context)) { - return true; - } - if (existsCatchSectionLocal(variableName, context)) { - return true; - } - if (existsForLoopLocal(variableName, context)) { - return true; - } - return existsForeachLoopLocal(variableName, context); - } - - private static boolean existsParameter(@NotNull String variableName, - PsiElement context) { - PsiMethod ancestor = - PsiTreeUtil.getParentOfType(context, PsiMethod.class); - while (ancestor != null) { - final PsiParameterList parameterList = ancestor.getParameterList(); - final PsiParameter[] parameters = parameterList.getParameters(); - for (final PsiParameter parameter : parameters) { - final String parameterName = parameter.getName(); - if (variableName.equals(parameterName)) { - return true; - } - } - ancestor = PsiTreeUtil.getParentOfType(ancestor, PsiMethod.class); - } - return false; - } - - private static boolean existsLocal(@NotNull String variableName, - PsiElement context) { - PsiCodeBlock ancestor = - PsiTreeUtil.getParentOfType(context, PsiCodeBlock.class); - while (ancestor != null) { - final PsiStatement[] statements = ancestor.getStatements(); - for (final PsiStatement statement : statements) { - if (statement instanceof PsiDeclarationStatement) { - final PsiDeclarationStatement declarationStatement = - (PsiDeclarationStatement) statement; - final PsiElement[] elements = - declarationStatement.getDeclaredElements(); - for (PsiElement element : elements) { - if (!(element instanceof PsiLocalVariable)) { - continue; - } - final PsiLocalVariable localVariable = - (PsiLocalVariable) element; - final String localVariableName = - localVariable.getName(); - if(variableName.equals(localVariableName)) { - return true; - } - } - } - } - ancestor = - PsiTreeUtil.getParentOfType(ancestor, PsiCodeBlock.class); - } - return false; - } - - private static boolean existsCatchSectionLocal(@NotNull String variableName, - PsiElement context) { - PsiCatchSection catchSectionAncestor = - PsiTreeUtil.getParentOfType(context, PsiCatchSection.class); - while (catchSectionAncestor != null) { - final PsiParameter parameter = - catchSectionAncestor.getParameter(); - if (parameter != null) { - final String parameterName = parameter.getName(); - if (variableName.equals(parameterName)) { - return true; - } - } - catchSectionAncestor = - PsiTreeUtil.getParentOfType(catchSectionAncestor, - PsiCatchSection.class); - } - return false; - } - - private static boolean existsForLoopLocal(@NotNull String variableName, - PsiElement context) { - PsiForStatement forLoopAncestor = - PsiTreeUtil.getParentOfType(context, PsiForStatement.class); - while (forLoopAncestor != null) { - final PsiStatement initialization = - forLoopAncestor.getInitialization(); - if (initialization instanceof PsiDeclarationStatement) { - final PsiDeclarationStatement declarationStatement = - (PsiDeclarationStatement) initialization; - final PsiElement[] elements = - declarationStatement.getDeclaredElements(); - for (PsiElement element : elements) { - final PsiLocalVariable localVariable = - (PsiLocalVariable) element; - final String localVariableName = localVariable.getName(); - if (variableName.equals(localVariableName)) { - return true; - } - } - } - forLoopAncestor = PsiTreeUtil.getParentOfType(forLoopAncestor, - PsiForStatement.class); - } - return false; - } - - private static boolean existsForeachLoopLocal(@NotNull String variableName, - PsiElement context) { - PsiForeachStatement forLoopAncestor = - PsiTreeUtil.getParentOfType(context, PsiForeachStatement.class); - while (forLoopAncestor != null) { - final PsiParameter parameter = - forLoopAncestor.getIterationParameter(); - final String parameterName = parameter.getName(); - if (variableName.equals(parameterName)) { - return true; - } - forLoopAncestor = PsiTreeUtil.getParentOfType(forLoopAncestor, - PsiForeachStatement.class); - } - return false; + public static boolean variableNameResolvesToTarget( + @NotNull String variableName, @NotNull PsiVariable target, + @NotNull PsiElement context) { + + final Project project = context.getProject(); + final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = psiFacade.getResolveHelper(); + final PsiVariable variable = + resolveHelper.resolveAccessibleReferencedVariable( + variableName, context); + return target.equals(variable); } public static boolean containsConflictingDeclarations( - PsiCodeBlock block, PsiCodeBlock parentBlock){ + PsiCodeBlock block, PsiCodeBlock parentBlock) { final PsiStatement[] statements = block.getStatements(); - final Set variableNames = new HashSet(); - for(final PsiStatement statement : statements){ + final Project project = block.getProject(); + final JavaPsiFacade facade = JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = facade.getResolveHelper(); + for (final PsiStatement statement : statements) { if (!(statement instanceof PsiDeclarationStatement)) { continue; } final PsiDeclarationStatement declaration = - (PsiDeclarationStatement) statement; - final PsiElement[] declaredElements = + (PsiDeclarationStatement)statement; + final PsiElement[] variables = declaration.getDeclaredElements(); - for(PsiElement declaredElement : declaredElements){ - if (!(declaredElement instanceof PsiLocalVariable)) { + for (PsiElement variable : variables) { + if (!(variable instanceof PsiLocalVariable)) { continue; } - final PsiLocalVariable variable = - (PsiLocalVariable)declaredElement; - final String variableName = variable.getName(); - if (variableName == null) { - continue; + final PsiLocalVariable localVariable = + (PsiLocalVariable) variable; + final PsiVariable target = + resolveHelper.resolveAccessibleReferencedVariable( + localVariable.getName(), parentBlock); + if (target != null) { + return true; } - variableNames.add(variableName); } } - final ConflictingDeclarationVisitor visitor = - new ConflictingDeclarationVisitor(variableNames, block); - parentBlock.accept(visitor); - return visitor.hasConflictingDeclaration(); - } - - private static class ConflictingDeclarationVisitor - extends JavaRecursiveElementVisitor{ - - private final Set variableNames; - private final PsiCodeBlock exceptBlock; - private boolean hasConflictingDeclaration = false; - - ConflictingDeclarationVisitor(@NotNull Set variableNames, - PsiCodeBlock exceptBlock){ - this.variableNames = variableNames; - this.exceptBlock = exceptBlock; - } - - @Override public void visitElement(@NotNull PsiElement element){ - if (hasConflictingDeclaration) { - return; - } - super.visitElement(element); - } - - @Override public void visitCodeBlock(PsiCodeBlock block){ - if(hasConflictingDeclaration){ - return; - } - if(block.equals(exceptBlock)){ - return; - } - super.visitCodeBlock(block); - } - - @Override public void visitVariable(@NotNull PsiVariable variable){ - if(hasConflictingDeclaration){ - return; - } - super.visitVariable(variable); - final String name = variable.getName(); - if(variableNames.contains(name)){ - hasConflictingDeclaration = true; - } - } - - public boolean hasConflictingDeclaration(){ - return hasConflictingDeclaration; - } + return false; } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryThisInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryThisInspection.java index 2dd7625f998f..0c9cf1d6a04a 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryThisInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnnecessaryThisInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers + * Copyright 2003-2010 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. @@ -18,6 +18,7 @@ package com.siyeh.ig.style; import com.intellij.codeInspection.ProblemDescriptor; import com.intellij.openapi.project.Project; import com.intellij.psi.*; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.siyeh.InspectionGadgetsBundle; import com.siyeh.ig.BaseInspection; @@ -29,17 +30,20 @@ import org.jetbrains.annotations.NotNull; public class UnnecessaryThisInspection extends BaseInspection { + @Override @NotNull public String getDisplayName() { return InspectionGadgetsBundle.message("unnecessary.this.display.name"); } + @Override @NotNull protected String buildErrorString(Object... infos) { return InspectionGadgetsBundle.message( "unnecessary.this.problem.descriptor"); } + @Override public InspectionGadgetsFix buildFix(Object... infos) { return new UnnecessaryThisFix(); } @@ -66,6 +70,7 @@ public class UnnecessaryThisInspection extends BaseInspection { } } + @Override public BaseInspectionVisitor buildVisitor() { return new UnnecessaryThisVisitor(); } @@ -103,8 +108,13 @@ public class UnnecessaryThisInspection extends BaseInspection { registerError(qualifierExpression); return; } - if (VariableSearchUtils.existsLocalOrParameter(referenceName, - expression)) { + final PsiElement target = expression.resolve(); + if (!(target instanceof PsiVariable)) { + return; + } + final PsiVariable variable = (PsiVariable) target; + if (!VariableSearchUtils.variableNameResolvesToTarget( + referenceName, variable, expression)) { return; } registerError(thisExpression); @@ -124,24 +134,43 @@ public class UnnecessaryThisInspection extends BaseInspection { final String methodName = calledMethod.getName(); PsiClass parentClass = ClassUtils.getContainingClass(expression); + final Project project = expression.getProject(); + final JavaPsiFacade psiFacade = + JavaPsiFacade.getInstance(project); + final PsiResolveHelper resolveHelper = + psiFacade.getResolveHelper(); while (parentClass != null) { if (qualifierName.equals(parentClass.getName())) { registerError(thisExpression); } - //resolve will point to any _accessible_ method with the same name final PsiMethod[] methods = - parentClass.findMethodsByName(methodName, - true); - //todo: filter only accessible methods - if (methods.length > 0) { - return; + parentClass.findMethodsByName(methodName, true); + for (PsiMethod method : methods) { + final PsiClass containingClass = + method.getContainingClass(); + if (resolveHelper.isAccessible(method, + expression, containingClass)) { + if (method.hasModifierProperty( + PsiModifier.PRIVATE) && + !PsiTreeUtil.isAncestor(containingClass, + expression, true)) { + continue; + } + return; + } + } parentClass = ClassUtils.getContainingClass(parentClass); } } else { - if (VariableSearchUtils.existsLocalOrParameter(referenceName, - expression)) { + final PsiElement target = expression.resolve(); + if (!(target instanceof PsiVariable)) { + return; + } + final PsiVariable variable = (PsiVariable) target; + if (!VariableSearchUtils.variableNameResolvesToTarget( + referenceName, variable, expression)) { return; } PsiClass parentClass = diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/UnnecessaryThisInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/UnnecessaryThisInspection.java index 4552710b662c..4edef3d03e70 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/UnnecessaryThisInspection.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/UnnecessaryThisInspection.java @@ -53,4 +53,20 @@ public class UnnecessaryThisInspection throwable.printStackTrace(); } } + + public void foo(String s) {} + + class D{ + + private void foo(String s) {} + } + class C extends D { + + class Box { + + void bar() { + UnnecessaryThisInspection.this.foo(""); + } + } + } } diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/expected.xml index 7491a3413bde..d620f795222c 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/expected.xml +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessary_this/expected.xml @@ -14,4 +14,12 @@ Unnecessary 'this' qualifier <code>this</code> is unnecessary in this context #loc + + + UnnecessaryThisInspection.java + 68 + Unnecessary 'this' qualifier + <code>UnnecessaryThisInspection.this</code> is unnecessary in this context #loc + + \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryThisInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryThisInspectionTest.java index 04c361bf5325..5e36cc3bd064 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryThisInspectionTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessaryThisInspectionTest.java @@ -5,6 +5,7 @@ import com.IGInspectionTestCase; public class UnnecessaryThisInspectionTest extends IGInspectionTestCase { public void test() throws Exception { - doTest("com/siyeh/igtest/style/unnecessary_this", new UnnecessaryThisInspection()); + doTest("com/siyeh/igtest/style/unnecessary_this", + new UnnecessaryThisInspection()); } } \ No newline at end of file From b25bd94e5a861ffdea7cc9971b42932ad9719fa0 Mon Sep 17 00:00:00 2001 From: Maxim Shafirov Date: Mon, 8 Nov 2010 21:54:17 +0300 Subject: [PATCH 57/61] Having a directory in initial startup costs >5megs in ClasspathCache resource map filled with results of recursive symlinks walking in JWS plugin. --- build/conf/mac/Contents/Info.plist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/conf/mac/Contents/Info.plist b/build/conf/mac/Contents/Info.plist index 5ac4640b0767..25e799c35539 100644 --- a/build/conf/mac/Contents/Info.plist +++ b/build/conf/mac/Contents/Info.plist @@ -42,7 +42,7 @@ Java ClassPath - $APP_PACKAGE/lib/bootstrap.jar:$APP_PACKAGE/lib/extensions.jar:$APP_PACKAGE/lib/util.jar:$APP_PACKAGE/lib/jdom.jar:$APP_PACKAGE/lib/log4j.jar:/System/Library/Java + $APP_PACKAGE/lib/bootstrap.jar:$APP_PACKAGE/lib/extensions.jar:$APP_PACKAGE/lib/util.jar:$APP_PACKAGE/lib/jdom.jar:$APP_PACKAGE/lib/log4j.jar JVMVersion @@jdk_req@@ From 4b6cbf3185c74e6502ec64c7d95f611eaafa0bc6 Mon Sep 17 00:00:00 2001 From: Gregory Shrago Date: Mon, 8 Nov 2010 21:31:43 +0300 Subject: [PATCH 58/61] extract method --- .../com/intellij/openapi/editor/impl/EditorImpl.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index c30a0970c3a8..33a40608216c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -5173,6 +5173,12 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi info.put("caret", visual.getLine() + ":" + visual.getColumn()); } + public static boolean isChangeFontSize(MouseWheelEvent e) { + return SystemInfo.isMac + ? !e.isControlDown() && e.isMetaDown() && !e.isAltDown() && !e.isShiftDown() + : e.isControlDown() && !e.isMetaDown() && !e.isAltDown() && !e.isShiftDown(); + } + private class MyScrollPane extends JBScrollPane { @@ -5182,10 +5188,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi protected void processMouseWheelEvent(MouseWheelEvent e) { if (mySettings.isWheelFontChangeEnabled()) { - boolean changeFontSize = SystemInfo.isMac - ? !e.isControlDown() && e.isMetaDown() && !e.isAltDown() && !e.isShiftDown() - : e.isControlDown() && !e.isMetaDown() && !e.isAltDown() && !e.isShiftDown(); - if (changeFontSize) { + if (isChangeFontSize(e)) { setFontSize(myScheme.getEditorFontSize() + e.getWheelRotation()); return; } From 8b758ade5dd2918bcb8fea2f099cd147312f7190 Mon Sep 17 00:00:00 2001 From: nik Date: Mon, 8 Nov 2010 17:58:05 +0300 Subject: [PATCH 59/61] 'navigate' and 'fix' actions implemented for new project structure errors --- .../ui/configuration/ConfigurationError.java | 4 +- .../ConfigurationErrorsComponent.java | 25 +++--- .../ui/configuration/ProjectConfigurable.java | 2 +- .../ProjectStructureConfigurable.java | 20 ++++- .../artifacts/ArtifactProblemDescription.java | 10 +-- .../artifacts/ArtifactProblemsHolderImpl.java | 6 +- .../libraryEditor/LibraryRootsComponent.java | 10 ++- .../projectRoot/LibraryConfigurable.java | 6 ++ .../daemon/ConfigurationErrorQuickFix.java | 30 +++++++ .../LibraryProjectStructureElement.java | 80 ++++++++++++++++++- .../daemon/ModuleProjectStructureElement.java | 14 +++- .../daemon/ProjectConfigurationProblem.java | 71 ++++++++++++++++ .../daemon/ProjectConfigurationProblems.java | 16 +--- .../ProjectStructureProblemDescription.java | 26 +++++- .../ProjectStructureProblemsHolder.java | 6 +- .../ProjectStructureProblemsHolderImpl.java | 12 ++- .../roots/impl/libraries/LibraryEx.java | 6 +- .../roots/impl/libraries/LibraryImpl.java | 11 ++- 18 files changed, 297 insertions(+), 58 deletions(-) create mode 100644 java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ConfigurationErrorQuickFix.java create mode 100644 java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblem.java diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationError.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationError.java index fdd29a300176..66a8de47a85a 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationError.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ConfigurationError.java @@ -17,6 +17,8 @@ package com.intellij.openapi.roots.ui.configuration; import org.jetbrains.annotations.NotNull; +import javax.swing.*; + /** * User: spLeaner */ @@ -65,7 +67,7 @@ public abstract class ConfigurationError implements Comparable implements D } @Override - public void fix() { + public void fix(JComponent contextComponent) { } @Override diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java index f7a6784e2e3d..fac45969b2a7 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ProjectStructureConfigurable.java @@ -364,6 +364,10 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se return navigateTo(place, requestFocus); } + public Place createModulePlace(@NotNull Module module) { + return createPlaceFor(myModulesConfig).putPath(ModuleStructureConfigurable.TREE_OBJECT, module); + } + public ActionCallback select(@Nullable final Facet facetToSelect, final boolean requestFocus) { Place place = createPlaceFor(myModulesConfig); if (facetToSelect != null) { @@ -379,17 +383,27 @@ public class ProjectStructureConfigurable extends BaseConfigurable implements Se } public ActionCallback selectProjectOrGlobalLibrary(@NotNull Library library, boolean requestFocus) { - Place place = createPlaceFor(getConfigurableFor(library)); - place.putPath(BaseStructureConfigurable.TREE_NAME, library.getName()); + Place place = createProjectOrGlobalLibraryPlace(library); return navigateTo(place, requestFocus); } + public Place createProjectOrGlobalLibraryPlace(Library library) { + Place place = createPlaceFor(getConfigurableFor(library)); + place.putPath(BaseStructureConfigurable.TREE_NAME, library.getName()); + return place; + } + public ActionCallback select(@Nullable Artifact artifact, boolean requestFocus) { + Place place = createArtifactPlace(artifact); + return navigateTo(place, requestFocus); + } + + public Place createArtifactPlace(Artifact artifact) { Place place = createPlaceFor(myArtifactsStructureConfigurable); if (artifact != null) { place.putPath(BaseStructureConfigurable.TREE_NAME, artifact.getName()); } - return navigateTo(place, requestFocus); + return place; } public ActionCallback select(@NotNull LibraryOrderEntry libraryOrderEntry, final boolean requestFocus) { diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemDescription.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemDescription.java index 8595333d1d6f..20317b52c8d1 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemDescription.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemDescription.java @@ -15,9 +15,11 @@ */ package com.intellij.openapi.roots.ui.configuration.artifacts; +import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ConfigurationErrorQuickFix; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription; import com.intellij.packaging.elements.PackagingElement; import com.intellij.packaging.ui.ArtifactProblemQuickFix; +import com.intellij.ui.navigation.Place; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -31,15 +33,11 @@ public class ArtifactProblemDescription extends ProjectStructureProblemDescripti private List myQuickFixes; private List> myPathToPlace; - public ArtifactProblemDescription(@NotNull String message, @NotNull Severity severity) { - this(message, severity, null, Collections.emptyList()); - } - public ArtifactProblemDescription(@NotNull String message, @NotNull Severity severity, @Nullable List> pathToPlace, - @NotNull List quickFixes) { - super(message, severity); + @NotNull List quickFixes, @NotNull Place place) { + super(message, null, severity, place, Collections.emptyList()); myPathToPlace = pathToPlace; myQuickFixes = quickFixes; } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemsHolderImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemsHolderImpl.java index 4cca595a799c..380260c8885f 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemsHolderImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactProblemsHolderImpl.java @@ -15,12 +15,14 @@ */ package com.intellij.openapi.roots.ui.configuration.artifacts; +import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemDescription; import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureProblemsHolder; import com.intellij.packaging.elements.PackagingElement; import com.intellij.packaging.impl.ui.ArtifactProblemsHolderBase; import com.intellij.packaging.ui.ArtifactEditorContext; import com.intellij.packaging.ui.ArtifactProblemQuickFix; +import com.intellij.ui.navigation.Place; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,7 +46,9 @@ public class ArtifactProblemsHolderImpl extends ArtifactProblemsHolderBase { private void registerProblem(@NotNull String message, @Nullable List> pathToPlace, final ProjectStructureProblemDescription.Severity severity, @NotNull ArtifactProblemQuickFix... quickFixes) { - myProblemsHolder.registerProblem(new ArtifactProblemDescription(message, severity, pathToPlace, Arrays.asList(quickFixes))); + final ArtifactEditorContext context = getContext(); + final Place place = ProjectStructureConfigurable.getInstance(context.getProject()).createArtifactPlace(context.getArtifact()); + myProblemsHolder.registerProblem(new ArtifactProblemDescription(message, severity, pathToPlace, Arrays.asList(quickFixes), place)); } public void registerWarning(@NotNull String message, diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java index 3f95273100f7..1f7b946148da 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java @@ -256,6 +256,12 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } } + public void updateRootsTree() { + if (myTreeBuilder != null) { + myTreeBuilder.queueUpdate(); + } + } + private class AttachItemAction implements ActionListener { private VirtualFile myLastChosen = null; private final AttachRootButtonDescriptor myDescriptor; @@ -328,7 +334,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent } }); updateProperties(); - myTreeBuilder.updateFromRoot(); + myTreeBuilder.queueUpdate(); } return filesToAttach; } @@ -368,7 +374,7 @@ public class LibraryRootsComponent implements Disposable, LibraryEditorComponent protected void librariesChanged(boolean putFocusIntoTree) { updateProperties(); - myTreeBuilder.updateFromRoot(); + myTreeBuilder.queueUpdate(); if (putFocusIntoTree) { myTree.requestFocus(); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibraryConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibraryConfigurable.java index f98a4eed68d0..d3b7fa5e27e2 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibraryConfigurable.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/LibraryConfigurable.java @@ -171,4 +171,10 @@ public class LibraryConfigurable extends ProjectStructureElementConfigurable invalidClasses = library.getInvalidRootUrls(OrderRootType.CLASSES); + if (!invalidClasses.isEmpty()) { + final String description = createInvalidRootsDescription(invalidClasses, libraryName); + problemsHolder.registerError(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName), description, createPlace(), + new RemoveInvalidRootsQuickFix(Collections.singletonMap(OrderRootType.CLASSES, invalidClasses), library)); } - else if (!library.allPathsValid(JavadocOrderRootType.getInstance()) || !library.allPathsValid(OrderRootType.SOURCES)) { - problemsHolder.registerWarning(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName)); + final List invalidJavadocs = library.getInvalidRootUrls(JavadocOrderRootType.getInstance()); + final List invalidSources = library.getInvalidRootUrls(OrderRootType.SOURCES); + if (!invalidJavadocs.isEmpty() || !invalidSources.isEmpty()) { + final Map> invalidRoots = new HashMap>(); + invalidRoots.put(OrderRootType.SOURCES, invalidSources); + invalidRoots.put(JavadocOrderRootType.getInstance(), invalidJavadocs); + final String description = createInvalidRootsDescription(ContainerUtil.concat(invalidJavadocs, invalidSources), libraryName); + problemsHolder.registerWarning(ProjectBundle.message("project.roots.tooltip.library.misconfigured", libraryName), description, createPlace(), + new RemoveInvalidRootsQuickFix(invalidRoots, library)); } } + private static String createInvalidRootsDescription(List invalidClasses, String libraryName) { + StringBuilder buffer = new StringBuilder(); + buffer.append(""); + buffer.append("Library '").append(libraryName).append("' has broken paths:"); + for (String url : invalidClasses) { + buffer.append("
  "); + buffer.append(VfsUtil.urlToPath(url)); + } + buffer.append(""); + return buffer.toString(); + } + + @NotNull + private Place createPlace() { + return ProjectStructureConfigurable.getInstance(myContext.getProject()).createProjectOrGlobalLibraryPlace(myLibrary); + } + @Override public List getUsagesInElement() { return Collections.emptyList(); @@ -84,4 +121,39 @@ public class LibraryProjectStructureElement extends ProjectStructureElement { final LibraryTable libraryTable = myLibrary.getTable(); return libraryTable != null && LibraryTablesRegistrar.PROJECT_LEVEL.equals(libraryTable.getTableLevel()); } + + private class RemoveInvalidRootsQuickFix extends ConfigurationErrorQuickFix { + private final Map> myInvalidRoots; + private final Library myLibrary; + + public RemoveInvalidRootsQuickFix(Map> invalidRoots, Library library) { + super("Remove invalid roots"); + myInvalidRoots = invalidRoots; + myLibrary = library; + } + + @Override + public void performFix() { + final LibraryTable.ModifiableModel libraryTable = myContext.getModifiableLibraryTable(myLibrary.getTable()); + if (libraryTable instanceof LibrariesModifiableModel) { + for (OrderRootType rootType : myInvalidRoots.keySet()) { + for (String invalidRoot : myInvalidRoots.get(rootType)) { + final ExistingLibraryEditor libraryEditor = ((LibrariesModifiableModel)libraryTable).getLibraryEditor(myLibrary); + libraryEditor.removeRoot(invalidRoot, rootType); + } + } + myContext.getDaemonAnalyzer().queueUpdate(LibraryProjectStructureElement.this); + final ProjectStructureConfigurable structureConfigurable = ProjectStructureConfigurable.getInstance(myContext.getProject()); + structureConfigurable.navigateTo(createPlace(), true).doWhenDone(new Runnable() { + @Override + public void run() { + final NamedConfigurable configurable = structureConfigurable.getConfigurableFor(myLibrary).getSelectedConfugurable(); + if (configurable instanceof LibraryConfigurable) { + ((LibraryConfigurable)configurable).updateComponent(); + } + } + }); + } + } + } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java index 52832d69a6a8..a457a840cbd5 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ModuleProjectStructureElement.java @@ -7,7 +7,9 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.ui.configuration.ModuleEditor; +import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; +import com.intellij.ui.navigation.Place; import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; @@ -39,7 +41,7 @@ public class ModuleProjectStructureElement extends ProjectStructureElement { for (Module each : all) { if (each != myModule && myContext.getRealName(each).equals(myContext.getRealName(myModule))) { - problemsHolder.registerError(ProjectBundle.message("project.roots.module.duplicate.name.message")); + problemsHolder.registerError(ProjectBundle.message("project.roots.module.duplicate.name.message"), null, createPlace(), null); break; } } @@ -50,9 +52,11 @@ public class ModuleProjectStructureElement extends ProjectStructureElement { for (OrderEntry entry : entries) { if (!entry.isValid()){ if (entry instanceof JdkOrderEntry && ((JdkOrderEntry)entry).getJdkName() == null) { - problemsHolder.registerError(ProjectBundle.message("project.roots.module.jdk.problem.message")); + problemsHolder.registerError(ProjectBundle.message("project.roots.module.jdk.problem.message"), null, createPlace(), null); } else { - problemsHolder.registerError(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName())); + problemsHolder.registerError(ProjectBundle.message("project.roots.library.problem.message", entry.getPresentableName()), null, + createPlace(), + null); } } //todo[nik] highlight libraries with invalid paths in ClasspathEditor @@ -70,6 +74,10 @@ public class ModuleProjectStructureElement extends ProjectStructureElement { } } + private Place createPlace() { + return ProjectStructureConfigurable.getInstance(myContext.getProject()).createModulePlace(myModule); + } + @Override public List getUsagesInElement() { final List usages = new ArrayList(); diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblem.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblem.java new file mode 100644 index 000000000000..500b7460a792 --- /dev/null +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblem.java @@ -0,0 +1,71 @@ +/* + * 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.openapi.roots.ui.configuration.projectRoot.daemon; + +import com.intellij.openapi.roots.ui.configuration.ConfigurationError; +import com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurable; +import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext; +import com.intellij.openapi.ui.popup.JBPopupFactory; +import com.intellij.openapi.ui.popup.PopupStep; +import com.intellij.openapi.ui.popup.util.BaseListPopupStep; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.util.List; + +/** +* @author nik +*/ +class ProjectConfigurationProblem extends ConfigurationError { + private final StructureConfigurableContext myContext; + private final ProjectStructureProblemDescription myDescription; + + public ProjectConfigurationProblem(StructureConfigurableContext context, ProjectStructureProblemDescription description) { + super(description.getMessage(), description.getDescription() != null ? description.getDescription() : description.getMessage()); + myContext = context; + myDescription = description; + } + + @Override + public void navigate() { + ProjectStructureConfigurable.getInstance(myContext.getProject()).navigateTo(myDescription.getPlace(), true); + } + + @Override + public boolean canBeFixed() { + return !myDescription.getFixes().isEmpty(); + } + + @Override + public void fix(JComponent contextComponent) { + final List fixes = myDescription.getFixes(); + if (fixes.size() == 1) { + fixes.get(0).performFix(); + } + else { + JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep(null, fixes) { + @NotNull + @Override + public String getTextFor(ConfigurationErrorQuickFix value) { + return value.getActionName(); + } + + @Override + public PopupStep onChosen(ConfigurationErrorQuickFix selectedValue, boolean finalChoice) { + selectedValue.performFix(); + return FINAL_CHOICE; + } + }).showUnderneathOf(contextComponent); + } + } +} diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblems.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblems.java index bae70d3391ca..049fe43a80e6 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblems.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectConfigurationProblems.java @@ -67,7 +67,7 @@ public class ProjectConfigurationProblems { final List descriptions = problemsHolder.getProblemDescriptions(); if (descriptions != null) { for (ProjectStructureProblemDescription description : descriptions) { - final ProjectConfigurationProblem error = new ProjectConfigurationProblem(description); + final ProjectConfigurationProblem error = new ProjectConfigurationProblem(myContext, description); myErrors.put(element, error); ConfigurationErrors.Bus.addError(error, myContext.getProject()); } @@ -81,18 +81,4 @@ public class ProjectConfigurationProblems { ConfigurationErrors.Bus.removeError(error, myContext.getProject()); } } - - private static class ProjectConfigurationProblem extends ConfigurationError { - public ProjectConfigurationProblem(ProjectStructureProblemDescription description) { - super(description.getMessage(), description.getMessage()); - } - - @Override - public void navigate() { - } - - @Override - public void fix() { - } - } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemDescription.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemDescription.java index 6dd988ad3f19..d4b125dc58fb 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemDescription.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemDescription.java @@ -15,27 +15,51 @@ */ package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon; +import com.intellij.ui.navigation.Place; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; /** * @author nik */ public class ProjectStructureProblemDescription { private final String myMessage; + private final String myDescription; private final Severity mySeverity; + private final Place myPlace; + private final List myFixes; - public ProjectStructureProblemDescription(@NotNull String message, @NotNull Severity severity) { + public ProjectStructureProblemDescription(@NotNull String message, @Nullable String description, @NotNull Severity severity, @NotNull Place place, + @NotNull List fixes) { myMessage = message; + myDescription = description; mySeverity = severity; + myPlace = place; + myFixes = fixes; } public String getMessage() { return myMessage; } + @Nullable + public String getDescription() { + return myDescription; + } + + public List getFixes() { + return myFixes; + } + public Severity getSeverity() { return mySeverity; } + public Place getPlace() { + return myPlace; + } + public enum Severity { ERROR, WARNING } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolder.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolder.java index 9094b4ac654c..411451abfdcc 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolder.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolder.java @@ -15,15 +15,17 @@ */ package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon; +import com.intellij.ui.navigation.Place; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author nik */ public interface ProjectStructureProblemsHolder { - void registerError(@NotNull String message); + void registerError(@NotNull String message, @Nullable String description, @NotNull Place place, @Nullable ConfigurationErrorQuickFix fix); - void registerWarning(@NotNull String message); + void registerWarning(@NotNull String message, @Nullable String description, @NotNull Place place, @Nullable ConfigurationErrorQuickFix fix); void registerProblem(@NotNull ProjectStructureProblemDescription description); } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolderImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolderImpl.java index 82cb561b8fd8..ea515d43263f 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolderImpl.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/daemon/ProjectStructureProblemsHolderImpl.java @@ -1,10 +1,12 @@ package com.intellij.openapi.roots.ui.configuration.projectRoot.daemon; +import com.intellij.ui.navigation.Place; import com.intellij.util.SmartList; import com.intellij.util.StringBuilderSpinAllocator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.List; /** @@ -13,12 +15,14 @@ import java.util.List; public class ProjectStructureProblemsHolderImpl implements ProjectStructureProblemsHolder { private List myProblemDescriptions; - public void registerError(@NotNull String message) { - registerProblem(new ProjectStructureProblemDescription(message, ProjectStructureProblemDescription.Severity.ERROR)); + public void registerError(@NotNull String message, String description, @NotNull Place place, @Nullable ConfigurationErrorQuickFix fix) { + final List fixes = fix != null ? Collections.singletonList(fix) : Collections.emptyList(); + registerProblem(new ProjectStructureProblemDescription(message, description, ProjectStructureProblemDescription.Severity.ERROR, place, fixes)); } - public void registerWarning(@NotNull String message) { - registerProblem(new ProjectStructureProblemDescription(message, ProjectStructureProblemDescription.Severity.WARNING)); + public void registerWarning(@NotNull String message, String description, @NotNull Place place, @Nullable ConfigurationErrorQuickFix fix) { + final List fixes = Collections.singletonList(fix); + registerProblem(new ProjectStructureProblemDescription(message, description, ProjectStructureProblemDescription.Severity.WARNING, place, fixes)); } public void registerProblem(final @NotNull ProjectStructureProblemDescription description) { diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java index 839ee0b2b79e..54ac21a3ffd3 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryEx.java @@ -22,13 +22,15 @@ import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.libraries.LibraryProperties; import com.intellij.openapi.roots.libraries.LibraryType; +import java.util.List; + /** * @author dsl */ public interface LibraryEx extends Library { Library cloneLibrary(RootModelImpl rootModel); - boolean allPathsValid(OrderRootType type); + List getInvalidRootUrls(OrderRootType type); boolean isDisposed(); @@ -37,8 +39,6 @@ public interface LibraryEx extends Library { LibraryProperties getProperties(); interface ModifiableModelEx extends ModifiableModel { - boolean allPathsValid(OrderRootType type); - void setProperties(LibraryProperties properties); LibraryProperties getProperties(); diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java index d3e6aa18ffad..5af2d67121e0 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/libraries/LibraryImpl.java @@ -39,6 +39,7 @@ import com.intellij.openapi.vfs.pointers.VirtualFilePointerContainer; import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager; import com.intellij.util.ArrayUtil; import com.intellij.util.ReflectionUtil; +import com.intellij.util.SmartList; import com.intellij.util.containers.HashMap; import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; @@ -204,14 +205,18 @@ public class LibraryImpl implements LibraryEx.ModifiableModelEx, LibraryEx { return clone; } - public boolean allPathsValid(OrderRootType type) { + public List getInvalidRootUrls(OrderRootType type) { final List pointers = myRoots.get(type).getList(); + List invalidPaths = null; for (VirtualFilePointer pointer : pointers) { if (!pointer.isValid()) { - return false; + if (invalidPaths == null) { + invalidPaths = new SmartList(); + } + invalidPaths.add(pointer.getUrl()); } } - return true; + return invalidPaths != null ? invalidPaths : Collections.emptyList(); } @Override From a65019d5de4e96a5225aff394f327525734fc8e6 Mon Sep 17 00:00:00 2001 From: Denis Zhdanov Date: Tue, 9 Nov 2010 11:27:40 +0300 Subject: [PATCH 60/61] IDEA-60781 After formatting cursor jumps from indented position to beginning of the line. Restricted caret position restoring only for the use-cases when caret is located at the line that contains only white spaces --- .../codeStyle/CodeStyleManagerImpl.java | 34 ++++++++++++++++--- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java index 4e4d1813e0f6..e3db5036e4cb 100644 --- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java @@ -146,6 +146,32 @@ public class CodeStyleManagerImpl extends CodeStyleManager { LOG.error("end=" + start + "; end=" + file); } + Editor editor = PsiUtilBase.findEditor(file); + + // There is a possible case that cursor is located at the end of the line that contains only white spaces. For example: + // public void foo() { + // + // } + // Formatter removes such white spaces, i.e. keeps only line feed symbol. But we want to preserve caret position then. + // So, we check if it should be preserved and restore it after formatting if necessary + boolean fixCaretPosition = false; + if (editor != null) { + int caretOffset = editor.getCaretModel().getOffset(); + Document document = editor.getDocument(); + CharSequence text = document.getCharsSequence(); + int caretLine = document.getLineNumber(Math.max(Math.min(caretOffset, document.getTextLength() - 1), 0)); + int lineStartOffset = document.getLineStartOffset(caretLine); + fixCaretPosition = true; + for (int i = caretOffset; i>= lineStartOffset; i--) { + char c = text.charAt(i); + if (c != ' ' && c != '\t' && c != '\n') { + fixCaretPosition = false; + break; + } + } + } + + boolean formatFromStart = startOffset == 0; boolean formatToEnd = endOffset == file.getTextLength(); @@ -163,25 +189,23 @@ public class CodeStyleManagerImpl extends CodeStyleManager { formatToEnd ? file.getTextLength() : endElement.getTextRange().getEndOffset())); } - Editor editor = PsiUtilBase.findEditor(file); - if (editor == null) { + if (!fixCaretPosition) { return; } - CaretModel caretModel = editor.getCaretModel(); String indent = getLineIndent(file, caretModel.getOffset()); if (indent == null) { return; } int tabSize = getSettings().getTabSize(file.getFileType()); - int indentColumn = indentWithInVisualColumns(indent, tabSize); + int indentColumn = indentInVisualColumns(indent, tabSize); VisualPosition position = caretModel.getVisualPosition(); if (indentColumn != position.column) { caretModel.moveToVisualPosition(new VisualPosition(position.line, indentColumn)); } } - private static int indentWithInVisualColumns(String indent, int tabSize) { + private static int indentInVisualColumns(String indent, int tabSize) { if (tabSize <= 1) { return indent.length(); } From 851329b79e7ebb0a95044c2d5a8f870b454735ee Mon Sep 17 00:00:00 2001 From: nik Date: Tue, 9 Nov 2010 11:32:42 +0300 Subject: [PATCH 61/61] xdebugger api: support for multiline error messages and error messages with hyperlinks --- .../xdebugger/frame/XCompositeNode.java | 8 ++++ .../frame/XDebuggerTreeNodeHyperlink.java} | 11 +++-- .../xdebugger/impl/ui/tree/XDebuggerTree.java | 5 ++- .../impl/ui/tree/XDebuggerTreeRenderer.java | 4 +- .../impl/ui/tree/nodes/MessageTreeNode.java | 45 ++++++++++++------- .../impl/ui/tree/nodes/XDebuggerTreeNode.java | 3 +- .../ui/tree/nodes/XValueContainerNode.java | 14 +++++- .../impl/ui/tree/nodes/XValueNodeImpl.java | 9 ++-- 8 files changed, 68 insertions(+), 31 deletions(-) rename platform/{xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerNodeLink.java => xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java} (76%) diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XCompositeNode.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XCompositeNode.java index badc500ae727..b2a550d36647 100644 --- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XCompositeNode.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XCompositeNode.java @@ -17,6 +17,7 @@ package com.intellij.xdebugger.frame; import com.intellij.xdebugger.Obsolescent; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -47,4 +48,11 @@ public interface XCompositeNode extends Obsolescent { * @param errorMessage message describing the error */ void setErrorMessage(@NotNull String errorMessage); + + /** + * Indicates that an error occurs + * @param errorMessage message describing the error + * @param link describes a hyperlink which will be appended to the error message + */ + void setErrorMessage(@NotNull String errorMessage, @Nullable XDebuggerTreeNodeHyperlink link); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerNodeLink.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java similarity index 76% rename from platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerNodeLink.java rename to platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java index ea93a8ad7b99..b7689ae65d5f 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerNodeLink.java +++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java @@ -13,20 +13,25 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.xdebugger.impl.ui.tree.nodes; +package com.intellij.xdebugger.frame; + +import org.jetbrains.annotations.NotNull; import java.awt.event.MouseEvent; /** + * Describes a hyperlink inside a debugger node + * * @author nik */ -public abstract class XDebuggerNodeLink { +public abstract class XDebuggerTreeNodeHyperlink { private String myLinkText; - protected XDebuggerNodeLink(String linkText) { + protected XDebuggerTreeNodeHyperlink(@NotNull String linkText) { myLinkText = linkText; } + @NotNull public String getLinkText() { return myLinkText; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java index d002d1f2da1a..425aec3cb0a2 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java @@ -28,6 +28,7 @@ import com.intellij.util.containers.Convertor; import com.intellij.xdebugger.XDebugSession; import com.intellij.xdebugger.XSourcePosition; import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.ui.tree.nodes.*; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -78,8 +79,8 @@ public class XDebuggerTree extends DnDAwareTree implements DataProvider { new TreeLinkMouseListener(new XDebuggerTreeRenderer()) { @Override protected void handleTagClick(Object tag, MouseEvent event) { - if (tag instanceof XDebuggerNodeLink) { - ((XDebuggerNodeLink)tag).onClick(event); + if (tag instanceof XDebuggerTreeNodeHyperlink) { + ((XDebuggerTreeNodeHyperlink)tag).onClick(event); } } }.install(this); diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java index 06f901c7f4c7..a7a20094c15c 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTreeRenderer.java @@ -17,7 +17,7 @@ package com.intellij.xdebugger.impl.ui.tree; import com.intellij.ui.ColoredTreeCellRenderer; import com.intellij.ui.SimpleTextAttributes; -import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerNodeLink; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.ui.tree.nodes.XDebuggerTreeNode; import javax.swing.*; @@ -35,7 +35,7 @@ class XDebuggerTreeRenderer extends ColoredTreeCellRenderer { final boolean hasFocus) { XDebuggerTreeNode node = (XDebuggerTreeNode)value; node.getText().appendToComponent(this); - final XDebuggerNodeLink link = node.getLink(); + final XDebuggerTreeNodeHyperlink link = node.getLink(); if (link != null) { append(link.getLinkText(), SimpleTextAttributes.LINK_ATTRIBUTES, link); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java index e3c70553dcb4..ec47fecf023d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java @@ -15,8 +15,11 @@ */ package com.intellij.xdebugger.impl.ui.tree.nodes; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.SimpleTextAttributes; +import com.intellij.util.ui.EmptyIcon; import com.intellij.xdebugger.XDebuggerBundle; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; @@ -24,6 +27,7 @@ import org.jetbrains.annotations.Nullable; import javax.swing.*; import javax.swing.tree.TreeNode; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -31,17 +35,25 @@ import java.util.List; * @author nik */ public class MessageTreeNode extends XDebuggerTreeNode { + private static final EmptyIcon EMPTY_ICON = new EmptyIcon(XDebuggerUIConstants.ERROR_MESSAGE_ICON); private boolean myEllipsis; + private XDebuggerTreeNodeHyperlink myLink; private MessageTreeNode(XDebuggerTree tree, final XDebuggerTreeNode parent, final String message, final SimpleTextAttributes attributes, @Nullable Icon icon) { - this(tree, parent, message, attributes, icon, false); + this(tree, parent, message, attributes, icon, null); } - private MessageTreeNode(XDebuggerTree tree, final XDebuggerTreeNode parent, final String message, final SimpleTextAttributes attributes, @Nullable Icon icon, - final boolean ellipsis) { + private MessageTreeNode(XDebuggerTree tree, final XDebuggerTreeNode parent, final String message, final SimpleTextAttributes attributes, + @Nullable Icon icon, final XDebuggerTreeNodeHyperlink link) { + this(tree, parent, message, attributes, icon, false, link); + } + + private MessageTreeNode(XDebuggerTree tree, final XDebuggerTreeNode parent, final String message, final SimpleTextAttributes attributes, + @Nullable Icon icon, final boolean ellipsis, final XDebuggerTreeNodeHyperlink link) { super(tree, parent, true); myEllipsis = ellipsis; + myLink = link; setIcon(icon); myText.append(message, attributes); } @@ -51,11 +63,6 @@ public class MessageTreeNode extends XDebuggerTreeNode { myEllipsis = false; } - private MessageTreeNode(XDebuggerTree tree, XDebuggerTreeNode parent, String infoMessage, String errorMessage) { - super(tree, parent, true); - myEllipsis = false; - } - protected List getChildren() { return Collections.emptyList(); } @@ -64,6 +71,11 @@ public class MessageTreeNode extends XDebuggerTreeNode { return myEllipsis; } + @Override + public XDebuggerTreeNodeHyperlink getLink() { + return myLink; + } + public List getLoadedChildren() { return null; } @@ -74,7 +86,7 @@ public class MessageTreeNode extends XDebuggerTreeNode { public static MessageTreeNode createEllipsisNode(XDebuggerTree tree, XDebuggerTreeNode parent, final int remaining) { String message = remaining == -1 ? "..." : XDebuggerBundle.message("node.text.ellipsis.0.more.nodes.double.click.to.show", remaining); - return new MessageTreeNode(tree, parent, message, SimpleTextAttributes.REGULAR_ATTRIBUTES, null, true); + return new MessageTreeNode(tree, parent, message, SimpleTextAttributes.REGULAR_ATTRIBUTES, null, true, null); } public static MessageTreeNode createMessageNode(XDebuggerTree tree, XDebuggerTreeNode parent, String message, @Nullable Icon icon) { @@ -85,16 +97,19 @@ public class MessageTreeNode extends XDebuggerTreeNode { return new MessageTreeNode(tree, parent, XDebuggerUIConstants.COLLECTING_DATA_MESSAGE, XDebuggerUIConstants.COLLECTING_DATA_HIGHLIGHT_ATTRIBUTES, null); } - public static MessageTreeNode createEvaluatingMessage(XDebuggerTree tree, final XDebuggerTreeNode parent, final String message) { - return new MessageTreeNode(tree, parent, message, XDebuggerUIConstants.EVALUATING_EXPRESSION_HIGHLIGHT_ATTRIBUTES, null); - } - public static MessageTreeNode createEvaluatingMessage(XDebuggerTree tree, final XDebuggerTreeNode parent) { return new MessageTreeNode(tree, parent, XDebuggerUIConstants.EVALUATING_EXPRESSION_MESSAGE, XDebuggerUIConstants.EVALUATING_EXPRESSION_HIGHLIGHT_ATTRIBUTES, null); } - public static MessageTreeNode createErrorMessage(XDebuggerTree tree, final XDebuggerTreeNode parent, @NotNull String errorMessage) { - return new MessageTreeNode(tree, parent, errorMessage, XDebuggerUIConstants.ERROR_MESSAGE_ATTRIBUTES, XDebuggerUIConstants.ERROR_MESSAGE_ICON); + public static List createErrorMessages(XDebuggerTree tree, final XDebuggerTreeNode parent, @NotNull String errorMessage, + XDebuggerTreeNodeHyperlink link) { + List messages = new ArrayList(1); + final List lines = StringUtil.split(errorMessage, "\n"); + for (int i = 0; i < lines.size(); i++) { + final Icon icon = i == 0 ? XDebuggerUIConstants.ERROR_MESSAGE_ICON : EMPTY_ICON; + messages.add(new MessageTreeNode(tree, parent, lines.get(i), XDebuggerUIConstants.ERROR_MESSAGE_ATTRIBUTES, icon, i == 0 ? link : null)); + } + return messages; } public static MessageTreeNode createInfoMessage(XDebuggerTree tree, final XDebuggerTreeNode parent, @NotNull String message) { diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java index 78019ab2d30d..31985506f5a6 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java @@ -17,6 +17,7 @@ package com.intellij.xdebugger.impl.ui.tree.nodes; import com.intellij.ui.SimpleColoredText; import com.intellij.util.enumeration.EmptyEnumeration; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -87,7 +88,7 @@ public abstract class XDebuggerTreeNode implements TreeNode { } @Nullable - public XDebuggerNodeLink getLink() { + public XDebuggerTreeNodeHyperlink getLink() { return null; } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java index 03fa75102232..2faa7711094d 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueContainerNode.java @@ -16,6 +16,7 @@ package com.intellij.xdebugger.impl.ui.tree.nodes; import com.intellij.xdebugger.frame.XCompositeNode; +import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink; import com.intellij.xdebugger.frame.XValue; import com.intellij.xdebugger.frame.XValueContainer; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; @@ -110,20 +111,29 @@ public abstract class XValueContainerNode messages) { myCachedAllChildren = null; final int[] indices = getNodesIndices(myMessageChildren); final TreeNode[] nodes = getChildNodes(indices); myMessageChildren = Collections.emptyList(); fireNodesRemoved(indices, nodes); - myMessageChildren = Collections.singletonList(messageNode); + myMessageChildren = messages; myCachedAllChildren = null; fireNodesInserted(myMessageChildren); } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java index 7a85c146fb19..1aa1934598e6 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java @@ -19,10 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.text.StringUtil; import com.intellij.ui.SimpleTextAttributes; import com.intellij.util.StringBuilderSpinAllocator; -import com.intellij.xdebugger.frame.XCompositeNode; -import com.intellij.xdebugger.frame.XFullValueEvaluator; -import com.intellij.xdebugger.frame.XValue; -import com.intellij.xdebugger.frame.XValueNode; +import com.intellij.xdebugger.frame.*; import com.intellij.xdebugger.impl.ui.DebuggerUIUtil; import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants; import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree; @@ -117,9 +114,9 @@ public class XValueNodeImpl extends XValueContainerNode implements XValu @Override - public XDebuggerNodeLink getLink() { + public XDebuggerTreeNodeHyperlink getLink() { if (myFullValueEvaluator != null) { - return new XDebuggerNodeLink(myFullValueEvaluator.getLinkText()) { + return new XDebuggerTreeNodeHyperlink(myFullValueEvaluator.getLinkText()) { @Override public void onClick(MouseEvent event) { DebuggerUIUtil.showValuePopup(myFullValueEvaluator, event, myTree.getProject());