diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java index 242e157a705b..f7232701bc4c 100644 --- a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java +++ b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java @@ -225,7 +225,7 @@ public class PositionHighlighter { } if (breakpoint instanceof BreakpointWithHighlighter) { - if (((BreakpointWithHighlighter)breakpoint).isVisible()) { + if (((BreakpointWithHighlighter)breakpoint).isVisible() && breakpoint.isValid()) { breakpoint.reload(); final SourcePosition sourcePosition = ((BreakpointWithHighlighter)breakpoint).getSourcePosition(); if (sourcePosition == null || sourcePosition.getLine() != lineIndex) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java index a9f93fdde07b..52e325db6aaf 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java @@ -42,7 +42,7 @@ class CollectionsUtilityMethodsProvider { final PsiType type = parameters.getExpectedType(); final PsiType defaultType = parameters.getDefaultType(); final PsiElement pparent = parent.getParent(); - if (parameters.getInvocationCount() > 1 || + if (parameters.getParameters().getInvocationCount() > 1 || pparent instanceof PsiReturnStatement || pparent instanceof PsiConditionalExpression && pparent.getParent() instanceof PsiReturnStatement) { addCollectionMethod(result, type, defaultType, JAVA_UTIL_LIST, "emptyList", collectionsClass); @@ -50,7 +50,7 @@ class CollectionsUtilityMethodsProvider { addCollectionMethod(result, type, defaultType, JAVA_UTIL_MAP, "emptyMap", collectionsClass); } - if (parameters.getInvocationCount() > 1) { + if (parameters.getParameters().getInvocationCount() > 1) { addCollectionMethod(result, type, defaultType, JAVA_UTIL_LIST, "singletonList", collectionsClass); addCollectionMethod(result, type, defaultType, JAVA_UTIL_SET, "singleton", collectionsClass); addCollectionMethod(result, type, defaultType, JAVA_UTIL_MAP, "singletonMap", collectionsClass); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index fcf92f5c8a61..6157ab88a59a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -220,15 +220,14 @@ public class JavaCompletionContributor extends CompletionContributor { addKeywords(parameters, result); - addAllClasses(parameters, result, position, inheritors); + addAllClasses(parameters, result, inheritors); result.stopHere(); } public static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, - PsiElement position, final InheritorsHolder inheritors) { - if (shouldRunClassNameCompletion(result, position)) { + if (shouldRunClassNameCompletion(result, parameters)) { JavaClassNameCompletionContributor.addAllClasses(parameters, result, new Consumer() { @Override public void consume(LookupElement element) { @@ -314,7 +313,8 @@ public class JavaCompletionContributor extends CompletionContributor { } } - private static boolean shouldRunClassNameCompletion(CompletionResultSet result, PsiElement position) { + private static boolean shouldRunClassNameCompletion(CompletionResultSet result, CompletionParameters parameters) { + PsiElement position = parameters.getPosition(); final PsiElement parent = position.getParent(); if (!(parent instanceof PsiJavaCodeReferenceElement)) return false; if (((PsiJavaCodeReferenceElement)parent).getQualifier() != null) return false; @@ -331,7 +331,7 @@ public class JavaCompletionContributor extends CompletionContributor { return false; } - return StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix()); + return StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix()) || parameters.relaxMatching(); } private static void completeAnnotationAttributeName(CompletionResultSet result, PsiElement insertedElement, diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java index aea4cc222e4c..abc1425bdac8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaDocCompletionContributor.java @@ -103,7 +103,7 @@ public class JavaDocCompletionContributor extends CompletionContributor { result.addElement(item); } - JavaCompletionContributor.addAllClasses(parameters, result, position, new InheritorsHolder(position, result)); + JavaCompletionContributor.addAllClasses(parameters, result, new InheritorsHolder(position, result)); } } }); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionParameters.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionParameters.java index b3aaf854c9bc..9796a359b44c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionParameters.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionParameters.java @@ -15,17 +15,19 @@ */ package com.intellij.codeInsight.completion; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiType; import com.intellij.codeInsight.ExpectedTypeInfo; /** * @author peter */ -public class JavaSmartCompletionParameters extends CompletionParameters{ +public class JavaSmartCompletionParameters { + private final CompletionParameters myParameters; private final ExpectedTypeInfo myExpectedType; public JavaSmartCompletionParameters(CompletionParameters parameters, final ExpectedTypeInfo expectedType) { - super(parameters.getPosition(), parameters.getOriginalFile(), parameters.getCompletionType(), parameters.getOffset(), parameters.getInvocationCount()); + myParameters = parameters; myExpectedType = expectedType; } @@ -36,4 +38,12 @@ public class JavaSmartCompletionParameters extends CompletionParameters{ public PsiType getDefaultType() { return myExpectedType.getDefaultType(); } + + public PsiElement getPosition() { + return myParameters.getPosition(); + } + + public CompletionParameters getParameters() { + return myParameters; + } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 128fdc78843a..fafdeab63df0 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -110,7 +110,7 @@ public class ReferenceExpressionCompletionContributor { final PsiElement element = parameters.getPosition(); if (JavaSmartCompletionContributor.INSIDE_TYPECAST_EXPRESSION.accepts(element)) return; - final int offset = parameters.getOffset(); + final int offset = parameters.getParameters().getOffset(); final PsiReference reference = element.getContainingFile().findReferenceAt(offset); if (reference != null) { final ElementFilter filter = getReferenceFilter(element, false); @@ -118,9 +118,9 @@ public class ReferenceExpressionCompletionContributor { result.consume(item); } - final boolean secondTime = parameters.getInvocationCount() >= 2; + final boolean secondTime = parameters.getParameters().getInvocationCount() >= 2; - for (final LookupElement item : JavaSmartCompletionContributor.completeReference(element, reference, filter, false, parameters)) { + for (final LookupElement item : JavaSmartCompletionContributor.completeReference(element, reference, filter, false, parameters.getParameters())) { addSingleArrayElementAccess(element, item, parameters, result); if (secondTime) { @@ -164,7 +164,7 @@ public class ReferenceExpressionCompletionContributor { public boolean isClassAcceptable(Class hintClass) { return true; } - }), false, parameters); + }), false, parameters.getParameters()); for (LookupElement lookupElement : elements) { if (lookupElement.getObject() instanceof PsiMethod) { final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY); diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java index 10a0aa98a4ff..860af752e6c3 100644 --- a/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java +++ b/java/java-impl/src/com/intellij/codeInspection/ex/GlobalJavaInspectionContextImpl.java @@ -218,6 +218,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext )); final List processors = myDerivedClassesRequests.get(sortedID); + LOG.assertTrue(processors != null, psiClass.getClass().getName()); ClassInheritorsSearch.search(psiClass, searchScope, false) .forEach(createMembersProcessor(processors, scope)); } @@ -229,12 +230,14 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext final List sortedIDs = getSortedIDs(myDerivedMethodsRequests); for (SmartPsiElementPointer sortedID : sortedIDs) { final PsiMethod psiMethod = (PsiMethod)sortedID.getElement(); + if (psiMethod == null) continue; final RefMethod refMethod = (RefMethod)refManager.getReference(psiMethod); context .incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES, refManager.getQualifiedName(refMethod)); final List processors = myDerivedMethodsRequests.get(sortedID); + LOG.assertTrue(processors != null, psiMethod.getClass().getName()); OverridingMethodsSearch.search(psiMethod, searchScope, true) .forEach(createMembersProcessor(processors, scope)); } @@ -249,6 +252,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext if (psiField == null) continue; final List processors = myFieldUsagesRequests.get(sortedID); + LOG.assertTrue(processors != null, psiField.getClass().getName()); context .incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES, refManager.getQualifiedName(refManager.getReference(psiField))); @@ -267,6 +271,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext if (psiClass == null) continue; final List processors = myClassUsagesRequests.get(sortedID); + LOG.assertTrue(processors != null, psiClass.getClass().getName()); context.incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES, ApplicationManager.getApplication().runReadAction( new Computable() { public String compute() { @@ -289,6 +294,7 @@ public class GlobalJavaInspectionContextImpl extends GlobalJavaInspectionContext if (psiMethod == null) continue; final List processors = myMethodUsagesRequests.get(sortedID); + LOG.assertTrue(processors != null, psiMethod.getClass().getName()); context .incrementJobDoneAmount(GlobalInspectionContextImpl.FIND_EXTERNAL_USAGES, refManager.getQualifiedName(refManager.getReference(psiMethod))); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java index a63f7a2a676f..02b38d7eb026 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/InplaceIntroduceParameterPopup.java @@ -187,7 +187,9 @@ class InplaceIntroduceParameterPopup extends IntroduceParameterSettingsUI { final JPanel wrapper = new JPanel(new BorderLayout()); wrapper.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - wrapper.add(myCanBeFinal, BorderLayout.NORTH); + if (myCanBeFinal != null) { + wrapper.add(myCanBeFinal, BorderLayout.NORTH); + } panel.add(wrapper, BorderLayout.SOUTH); return panel; diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java index b8d27999117c..89b5b5b85567 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/IntroduceParameterHandler.java @@ -164,8 +164,9 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R final Introducer introducer = new Introducer(project, expr, localVar, editor); final boolean unitTestMode = ApplicationManager.getApplication().isUnitTestMode(); if (validEnclosingMethods.size() == 1 || unitTestMode) { - if (validEnclosingMethods.get(0).findDeepestSuperMethod() == null || unitTestMode) { - introducer.introduceParameter(method, method); + final PsiMethod methodToIntroduceParameterTo = validEnclosingMethods.get(0); + if (methodToIntroduceParameterTo.findDeepestSuperMethod() == null || unitTestMode) { + introducer.introduceParameter(methodToIntroduceParameterTo, methodToIntroduceParameterTo); return true; } } @@ -176,8 +177,8 @@ public class IntroduceParameterHandler extends IntroduceHandlerBase implements R } private void chooseMethodToIntroduceParameter(final Editor editor, - final List validEnclosingMethods, - final Introducer introducer) { + final List validEnclosingMethods, + final Introducer introducer) { final JPanel panel = new JPanel(new BorderLayout()); final JCheckBox superMethod = new JCheckBox("Use super method of", true); superMethod.setMnemonic('U'); 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 001e566b46c3..2e95f0d34778 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -478,6 +478,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase impleme final VariableInplaceRenamer renamer = new VariableInplaceIntroducer(project, expression, editor, elementToRename, cantChangeFinalModifier, typeSelectorManager.getTypesForAll().length > 1, exprMarker, occurrenceMarkers); + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); renamer.performInplaceRename(false, new LinkedHashSet(Arrays.asList(suggestedName.names))); } } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java index 2a164b4ea3c6..5da76bbd8561 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/VariableInplaceIntroducer.java @@ -235,7 +235,9 @@ public class VariableInplaceIntroducer extends VariableInplaceRenamer { titlePanel.setText(IntroduceVariableBase.REFACTORING_NAME); panel.add(titlePanel, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0)); - panel.add(myCanBeFinal, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + if (myCanBeFinal != null) { + panel.add(myCanBeFinal, new GridBagConstraints(0, 1, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0)); + } panel.add(Box.createVerticalBox(), new GridBagConstraints(0, 2, 1, 1, 1, 1, GridBagConstraints.NORTHWEST, GridBagConstraints.BOTH, new Insets(0,0,0,0), 0,0)); diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java index c8d9ce3ae398..d82b19dd8c87 100644 --- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java +++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionParameters.java @@ -29,9 +29,10 @@ public class CompletionParameters { private final CompletionType myCompletionType; private final int myOffset; private final int myInvocationCount; + private final boolean myRelaxedMatching; protected CompletionParameters(@NotNull final PsiElement position, @NotNull final PsiFile originalFile, - final CompletionType completionType, int offset, final int invocationCount) { + final CompletionType completionType, int offset, final int invocationCount, final boolean relaxedMatching) { assert offset >= position.getTextRange().getStartOffset(); myPosition = position; assert position.isValid(); @@ -39,14 +40,19 @@ public class CompletionParameters { myCompletionType = completionType; myOffset = offset; myInvocationCount = invocationCount; + myRelaxedMatching = relaxedMatching; } public CompletionParameters withType(CompletionType type) { - return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount); + return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myRelaxedMatching); } public CompletionParameters withInvocationCount(int newCount) { - return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount); + return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount, myRelaxedMatching); + } + + public CompletionParameters withRelaxedMatching() { + return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, myInvocationCount, true); } @NotNull @@ -82,4 +88,8 @@ public class CompletionParameters { public int getInvocationCount() { return myInvocationCount; } + + public boolean relaxMatching() { + return myRelaxedMatching; + } } 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 421341b5e3cf..7d003ebd1a4e 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java @@ -53,6 +53,7 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.NameUtil; import com.intellij.psi.impl.PsiFileEx; import com.intellij.psi.impl.source.PostprocessReformattingAspect; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; @@ -291,11 +292,20 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { indicator.duringCompletion(initContext); ProgressManager.checkCanceled(); - data.set(CompletionService.getCompletionService().performCompletion(parameters, new Consumer() { + Consumer consumer = new Consumer() { public void consume(final LookupElement lookupElement) { indicator.addItem(lookupElement); } - })); + }; + LookupElement[] result = CompletionService.getCompletionService().performCompletion(parameters, consumer); + if (NameUtil.isUseMinusculeHumpMatcher() && parameters.getInvocationCount() == 0) { + if (result.length == 0) { + result = CompletionService.getCompletionService().performCompletion(parameters.withRelaxedMatching(), consumer); + } else { + indicator.restartOnEmpty = true; + } + } + data.set(result); } }); } @@ -347,7 +357,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler { LOG.error("wrong text: copy='" + fileCopy.getText() + "'; element='" + insertedElement.getText() + "'; range=" + range); } - return new CompletionParameters(insertedElement, fileCopy.getOriginalFile(), myCompletionType, offset, invocationCount); + return new CompletionParameters(insertedElement, fileCopy.getOriginalFile(), myCompletionType, offset, invocationCount, invocationCount >= 2); } private AutoCompletionDecision shouldAutoComplete( diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java index 5c51cacbda78..e77fad64b7cb 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java @@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.CodeInsightSettings; import com.intellij.codeInsight.completion.impl.CompletionServiceImpl; +import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler; import com.intellij.codeInsight.hint.EditorHintListener; import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.lookup.*; @@ -399,7 +400,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement Disposer.dispose(myQueue); CompletionProgressIndicator currentCompletion = CompletionServiceImpl.getCompletionService().getCurrentCompletion(); - assert currentCompletion == this : currentCompletion + "!=" + this; + LOG.assertTrue(currentCompletion == this, currentCompletion + "!=" + this); CompletionServiceImpl.getCompletionService().setCurrentCompletion(null); CompletionServiceImpl.assertPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class, CompletionPhase.Synchronous.class, CompletionPhase.Restarted.class); @@ -573,6 +574,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } + public boolean restartOnEmpty = false; + public void prefixUpdated() { final CharSequence text = myEditor.getDocument().getCharsSequence(); final int caretOffset = myEditor.getCaretModel().getOffset(); @@ -585,7 +588,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement } } - hideAutopopupIfMeaningless(); + if (hideAutopopupIfMeaningless() && restartOnEmpty) { + CompletionAutoPopupHandler.scheduleAutoPopup(getProject(), myEditor, getParameters().getOriginalFile()); + } updateFocus(); } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java index 2e7378f5117d..70a83f4454e5 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java @@ -28,13 +28,15 @@ public class CamelHumpMatcher extends PrefixMatcher { private NameUtil.Matcher myMatcher; private final boolean myCaseSensitive; private final int currentSetting; + private final boolean myRelaxedMatching; public CamelHumpMatcher(@NotNull final String prefix) { - this(prefix, true); + this(prefix, true, false); } - public CamelHumpMatcher(String prefix, boolean caseSensitive) { + public CamelHumpMatcher(String prefix, boolean caseSensitive, boolean relaxedMatching) { super(prefix); + myRelaxedMatching = relaxedMatching; currentSetting = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE; myCaseSensitive = caseSensitive; } @@ -47,10 +49,11 @@ public class CamelHumpMatcher extends PrefixMatcher { ourLastCompletionCaseSetting = currentSetting; } - NameUtil.Matcher pattern = ourPatternCache.get(myPrefix); + String key = myRelaxedMatching + myPrefix; + NameUtil.Matcher pattern = ourPatternCache.get(key); if (pattern == null) { pattern = createCamelHumpsMatcher(); - ourPatternCache.put(myPrefix, pattern); + ourPatternCache.put(key, pattern); } myMatcher = pattern; } @@ -81,7 +84,7 @@ public class CamelHumpMatcher extends PrefixMatcher { @NotNull public PrefixMatcher cloneWithPrefix(@NotNull final String prefix) { - return new CamelHumpMatcher(prefix); + return new CamelHumpMatcher(prefix, myCaseSensitive, myRelaxedMatching); } private NameUtil.Matcher createCamelHumpsMatcher() { @@ -89,6 +92,10 @@ public class CamelHumpMatcher extends PrefixMatcher { return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true); } + if (myRelaxedMatching) { + return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true); + } + switch (CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE) { case CodeInsightSettings.NONE: return NameUtil.buildCompletionMatcher(myPrefix, 0, true, true); @@ -106,4 +113,8 @@ public class CamelHumpMatcher extends PrefixMatcher { public String toString() { return myPrefix; } + + public boolean isRelaxedMatching() { + return myRelaxedMatching; + } } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java index 99b2bf31a3c5..7b78d815d82d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java @@ -82,7 +82,7 @@ public class CompletionServiceImpl extends CompletionService{ final PsiElement position = parameters.getPosition(); final String prefix = CompletionData.findPrefixStatic(position, parameters.getOffset()); final String textBeforePosition = parameters.getPosition().getContainingFile().getText().substring(0, parameters.getOffset()); - return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix), contributor, defaultSorter(parameters), null); + return new CompletionResultSetImpl(consumer, textBeforePosition, new CamelHumpMatcher(prefix, true, parameters.relaxMatching()), contributor, defaultSorter(parameters), null); } @Override @@ -148,7 +148,8 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull public CompletionResultSet withPrefixMatcher(@NotNull final String prefix) { - return withPrefixMatcher(new CamelHumpMatcher(prefix)); + boolean relaxed = getPrefixMatcher() instanceof CamelHumpMatcher && ((CamelHumpMatcher)getPrefixMatcher()).isRelaxedMatching(); + return withPrefixMatcher(new CamelHumpMatcher(prefix, true, relaxed)); } @NotNull @@ -160,7 +161,8 @@ public class CompletionServiceImpl extends CompletionService{ @NotNull @Override public CompletionResultSet caseInsensitive() { - return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false)); + boolean relaxed = getPrefixMatcher() instanceof CamelHumpMatcher && ((CamelHumpMatcher)getPrefixMatcher()).isRelaxedMatching(); + return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false, relaxed)); } @Override diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java index caf48987b262..207642e11676 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CompletionAutoPopupHandler.java @@ -76,6 +76,11 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { return Result.CONTINUE; } + scheduleAutoPopup(project, editor, file); + return Result.STOP; + } + + public static void scheduleAutoPopup(final Project project, final Editor editor, final PsiFile file) { final boolean isMainEditor = FileEditorManager.getInstance(project).getSelectedTextEditor() == editor; final CompletionPhase.AutoPopupAlarm phase = new CompletionPhase.AutoPopupAlarm(); @@ -95,7 +100,6 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate { } }; AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY); - return Result.STOP; } public static void invokeAutoPopupCompletion(Project project, final Editor editor) { 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 96cc9fd1da61..5a8433feca8c 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 @@ -87,12 +87,12 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { private final Project myProject; private final Editor myEditor; - private int myMinPrefixLength; private int myPreferredItemsCount; private String myInitialPrefix; private LookupArranger myCustomArranger; - private RangeMarker myLookupStartMarker; + private boolean myStableStart; + @NotNull private RangeMarker myLookupStartMarker; private final JList myList = new JBList(new DefaultListModel()); private final LookupCellRenderer myCellRenderer; private Boolean myPositionedAbove = null; @@ -154,6 +154,8 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { myIconPanel.setBackground(Color.LIGHT_GRAY); myIconPanel.add(myProcessIcon); + updateLookupStart(0); + final ListModel model = myList.getModel(); addEmptyItem((DefaultListModel)model); updateListHeight(model); @@ -270,10 +272,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { return myModel.getActionsFor(element); } - public int getMinPrefixLength() { - return myMinPrefixLength; - } - public JList getList() { return myList; } @@ -421,15 +419,17 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } private void checkMinPrefixLengthChanges(Collection items) { + if (myStableStart) return; + if (!myCalculating && !items.isEmpty()) { + myStableStart = true; + } + int minPrefixLength = items.isEmpty() ? 0 : Integer.MAX_VALUE; for (final LookupElement item : items) { minPrefixLength = Math.min(item.getPrefixMatcher().getPrefix().length(), minPrefixLength); } - if (myMinPrefixLength != minPrefixLength) { - myLookupStartMarker = null; - } - myMinPrefixLength = minPrefixLength; + updateLookupStart(minPrefixLength); } private void restoreSelection(@Nullable LookupElement oldSelected, boolean choosePreselectedItem, @Nullable String oldInvariant) { @@ -568,7 +568,7 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { Dimension dim = component.getPreferredSize(); int lookupStart = getLookupStart(); if (lookupStart < 0) { - LOG.error(lookupStart + "; minprefix=" + myMinPrefixLength + "; offset=" + myEditor.getCaretModel().getOffset() + "; element=" + + LOG.error(lookupStart + "; offset=" + myEditor.getCaretModel().getOffset() + "; element=" + getPsiElement()); } @@ -656,12 +656,6 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } public int getLookupStart() { - if (myLookupStartMarker == null) { - final int start = calcLookupStart(); - myLookupStartMarker = myEditor.getDocument().createRangeMarker(start, start); - myLookupStartMarker.setGreedyToLeft(true); - } - return myLookupStartMarker.getStartOffset(); } @@ -816,11 +810,14 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable { } } - private int calcLookupStart() { + private int updateLookupStart(int myMinPrefixLength) { int offset = myEditor.getSelectionModel().hasSelection() ? myEditor.getSelectionModel().getSelectionStart() : myEditor.getCaretModel().getOffset(); - return Math.max(offset - myMinPrefixLength - myAdditionalPrefix.length(), 0); + int start = Math.max(offset - myMinPrefixLength - myAdditionalPrefix.length(), 0); + myLookupStartMarker = myEditor.getDocument().createRangeMarker(start, start); + myLookupStartMarker.setGreedyToLeft(true); + return start; } @Nullable diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java index 0c32cfa102bd..16a9ae0f7ead 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/TypedHandler.java @@ -126,8 +126,11 @@ public class TypedHandler implements TypedActionHandler { @Nullable private static CharFilter.Result getFiltersDecision(char charTyped, LookupImpl lookup) { + LookupElement item = lookup.getCurrentItem(); + int prefixLength = (item == null ? 0 : item.getPrefixMatcher().getPrefix().length()) + lookup.getAdditionalPrefix().length(); + for (final CharFilter extension : getFilters()) { - final CharFilter.Result result = extension.acceptChar(charTyped, lookup.getMinPrefixLength() + lookup.getAdditionalPrefix().length(), lookup); + final CharFilter.Result result = extension.acceptChar(charTyped, prefixLength, lookup); if (result != null) { return result; } diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java index 7240dd7f3e19..0e514acfdd43 100644 --- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java @@ -1568,14 +1568,14 @@ private final class MyVirtualFileListener extends VirtualFileAdapter { // already open if (eachWindow.findFileIndex(newFile) != -1) continue; - closeFile(eachFile, eachWindow); try { newFile.putUserData(EditorWindow.INITIAL_INDEX_KEY, i); - openFile(newFile, eachFile == selected); + openFileImpl2(eachWindow, newFile, eachFile == selected); } finally { newFile.putUserData(EditorWindow.INITIAL_INDEX_KEY, null); } + closeFile(eachFile, eachWindow); } } } diff --git a/platform/util/src/com/intellij/util/containers/IntArrayList.java b/platform/util/src/com/intellij/util/containers/IntArrayList.java index 4e3b07ef52f2..d595a53cc008 100644 --- a/platform/util/src/com/intellij/util/containers/IntArrayList.java +++ b/platform/util/src/com/intellij/util/containers/IntArrayList.java @@ -15,6 +15,8 @@ */ package com.intellij.util.containers; +import java.util.Arrays; + public class IntArrayList implements Cloneable { private int[] myData; private int mySize; @@ -163,4 +165,9 @@ public class IntArrayList implements Cloneable { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + mySize); } } + + @Override + public String toString() { + return Arrays.toString(toArray()); + } } 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 0721d3e3b227..a09bf84e1765 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 @@ -453,7 +453,7 @@ public class GroovyCompletionContributor extends CompletionContributor { } }); - if (StringUtil.isNotEmpty(result.getPrefixMatcher().getPrefix())) { + if (StringUtil.isCapitalized(result.getPrefixMatcher().getPrefix()) || parameters.relaxMatching()) { addAllClasses(parameters, result, inheritors); } } diff --git a/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java b/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java index fae085b71b74..539e29d6c9c9 100644 --- a/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java +++ b/xml/impl/src/com/intellij/lang/xml/XmlUnwrapDescriptor.java @@ -25,15 +25,15 @@ import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.xml.XmlChildRole; import com.intellij.psi.xml.XmlTag; -import com.intellij.util.SmartList; -import java.util.Collections; +import java.util.ArrayList; import java.util.List; public class XmlUnwrapDescriptor implements UnwrapDescriptor { public List> collectUnwrappers(Project project, Editor editor, PsiFile file) { - List> result = new SmartList>(); + List> result = new ArrayList>(); int offset = editor.getCaretModel().getOffset(); PsiElement e1 = file.findElementAt(offset); @@ -49,7 +49,9 @@ public class XmlUnwrapDescriptor implements UnwrapDescriptor { PsiElement tag = PsiTreeUtil.getParentOfType(e1, XmlTag.class); while (tag != null) { - result.add(new Pair(tag, new XmlEnclosingTagUnwrapper())); + if (XmlChildRole.START_TAG_END_FINDER.findChild(tag.getNode()) != null) { // Exclude implicit tags suck as 'jsp:root' + result.add(new Pair(tag, new XmlEnclosingTagUnwrapper())); + } tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class); }