diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt index e2dc3404171..ffa0295904e 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/BasicCompletionSession.kt @@ -23,8 +23,7 @@ import com.intellij.codeInsight.lookup.LookupElementBuilder import com.intellij.codeInsight.template.TemplateManager import com.intellij.patterns.PatternCondition import com.intellij.patterns.StandardPatterns -import com.intellij.psi.JavaPsiFacade -import com.intellij.psi.PsiClass +import com.intellij.psi.* import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.ProcessingContext import org.jetbrains.kotlin.descriptors.ClassDescriptor @@ -119,11 +118,28 @@ class BasicCompletionSession( lookupElement.putUserData(LookupCancelWatcher.AUTO_POPUP_AT, position.startOffset) lookupElement } + + if (isInFunctionLiteralStart(position)) { + collector.addLookupElementPostProcessor { lookupElement -> + lookupElement.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit) + lookupElement + } + } } completionKind.doComplete() } + private fun isInFunctionLiteralStart(position: PsiElement): Boolean { + var prev = position.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment } + if (prev?.node?.elementType == KtTokens.LPAR) { + prev = prev?.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment } + } + if (prev?.node?.elementType != KtTokens.LBRACE) return false + val functionLiteral = prev!!.parent as? KtFunctionLiteral ?: return false + return functionLiteral.lBrace == prev + } + override fun createSorter(): CompletionSorter { var sorter = super.createSorter() diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt index c756fc6a0e2..65b7c93f816 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/CompletionUtils.kt @@ -16,12 +16,9 @@ package org.jetbrains.kotlin.idea.completion -import com.intellij.codeInsight.completion.CompletionProgressIndicator -import com.intellij.codeInsight.completion.CompletionService import com.intellij.codeInsight.completion.InsertionContext import com.intellij.codeInsight.completion.PrefixMatcher import com.intellij.codeInsight.lookup.* -import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.openapi.util.Key import com.intellij.patterns.ElementPattern import com.intellij.patterns.StandardPatterns @@ -107,17 +104,6 @@ fun LookupElement.keepOldArgumentListOnTab(): LookupElement { return this } -fun rethrowWithCancelIndicator(exception: ProcessCanceledException): ProcessCanceledException { - val indicator = CompletionService.getCompletionService().currentCompletion as CompletionProgressIndicator - - // Force cancel to avoid deadlock in CompletionThreading.delegateWeighing() - if (!indicator.isCanceled) { - indicator.cancel() - } - - return exception -} - fun PrefixMatcher.asNameFilter(): (Name) -> Boolean { return { name -> !name.isSpecial && prefixMatches(name.identifier) } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionCharFilter.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionCharFilter.kt index 40747763c09..0106d8775d9 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionCharFilter.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionCharFilter.kt @@ -16,19 +16,11 @@ package org.jetbrains.kotlin.idea.completion -import com.intellij.codeInsight.completion.CompletionProgressIndicator import com.intellij.codeInsight.completion.CompletionService import com.intellij.codeInsight.lookup.CharFilter -import com.intellij.codeInsight.lookup.CharFilter.Result import com.intellij.codeInsight.lookup.Lookup import com.intellij.openapi.util.Key -import com.intellij.psi.PsiComment -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiWhiteSpace -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtFile -import org.jetbrains.kotlin.psi.KtFunctionLiteral -import org.jetbrains.kotlin.psi.psiUtil.prevLeaf class KotlinCompletionCharFilter() : CharFilter() { companion object { @@ -43,10 +35,7 @@ class KotlinCompletionCharFilter() : CharFilter() { override fun acceptChar(c : Char, prefixLength : Int, lookup : Lookup) : Result? { if (lookup.psiFile !is KtFile) return null if (!lookup.isCompletion) return null - // it does not work in tests, so we use other way -// val isAutopopup = CompletionService.getCompletionService().getCurrentCompletion().isAutopopupCompletion() - val completionParameters = (CompletionService.getCompletionService().currentCompletion as CompletionProgressIndicator).parameters - val isAutopopup = completionParameters.invocationCount == 0 + val isAutopopup = CompletionService.getCompletionService().currentCompletion!!.isAutopopupCompletion if (Character.isJavaIdentifierPart(c) || c == '@') { return CharFilter.Result.ADD_TO_PREFIX @@ -55,8 +44,7 @@ class KotlinCompletionCharFilter() : CharFilter() { val currentItem = lookup.currentItem // do not accept items by special chars in some special positions such as in the very beginning of function literal where name of the first parameter can be - if (isAutopopup && !lookup.isSelectionTouched - && (currentItem?.getUserData(SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING) != null || isInFunctionLiteralStart(completionParameters.position))) { + if (isAutopopup && !lookup.isSelectionTouched && currentItem?.getUserData(SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING) != null) { return Result.HIDE_LOOKUP } @@ -94,14 +82,4 @@ class KotlinCompletionCharFilter() : CharFilter() { else -> CharFilter.Result.HIDE_LOOKUP } } - - private fun isInFunctionLiteralStart(position: PsiElement): Boolean { - var prev = position.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment } - if (prev?.node?.elementType == KtTokens.LPAR) { - prev = prev?.prevLeaf { it !is PsiWhiteSpace && it !is PsiComment } - } - if (prev?.node?.elementType != KtTokens.LBRACE) return false - val functionLiteral = prev!!.parent as? KtFunctionLiteral ?: return false - return functionLiteral.lBrace == prev - } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt index 1d1e779efb0..fec4f405888 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/KotlinCompletionContributor.kt @@ -284,44 +284,39 @@ class KotlinCompletionContributor : CompletionContributor() { } } - try { - result.restartCompletionWhenNothingMatches() + result.restartCompletionWhenNothingMatches() - val configuration = CompletionSessionConfiguration(parameters) - if (parameters.completionType == CompletionType.BASIC) { - val session = BasicCompletionSession(configuration, parameters, toFromOriginalFileMapper, result) + val configuration = CompletionSessionConfiguration(parameters) + if (parameters.completionType == CompletionType.BASIC) { + val session = BasicCompletionSession(configuration, parameters, toFromOriginalFileMapper, result) - addPostProcessor(session) + addPostProcessor(session) - if (parameters.isAutoPopup && session.shouldDisableAutoPopup()) { - result.stopHere() - return - } - - val somethingAdded = session.complete() - if (!somethingAdded && parameters.invocationCount < 2) { - // Rerun completion if nothing was found - val newConfiguration = CompletionSessionConfiguration( - useBetterPrefixMatcherForNonImportedClasses = false, - completeNonAccessibleDeclarations = false, - filterOutJavaGettersAndSetters = false, - completeJavaClassesNotToBeUsed = false, - completeStaticMembers = parameters.invocationCount > 0 - ) - - val newSession = BasicCompletionSession(newConfiguration, parameters, toFromOriginalFileMapper, result) - addPostProcessor(newSession) - newSession.complete() - } + if (parameters.isAutoPopup && session.shouldDisableAutoPopup()) { + result.stopHere() + return } - else { - val session = SmartCompletionSession(configuration, parameters, toFromOriginalFileMapper, result) - addPostProcessor(session) - session.complete() + + val somethingAdded = session.complete() + if (!somethingAdded && parameters.invocationCount < 2) { + // Rerun completion if nothing was found + val newConfiguration = CompletionSessionConfiguration( + useBetterPrefixMatcherForNonImportedClasses = false, + completeNonAccessibleDeclarations = false, + filterOutJavaGettersAndSetters = false, + completeJavaClassesNotToBeUsed = false, + completeStaticMembers = parameters.invocationCount > 0 + ) + + val newSession = BasicCompletionSession(newConfiguration, parameters, toFromOriginalFileMapper, result) + addPostProcessor(newSession) + newSession.complete() } } - catch (e: ProcessCanceledException) { - throw rethrowWithCancelIndicator(e) + else { + val session = SmartCompletionSession(configuration, parameters, toFromOriginalFileMapper, result) + addPostProcessor(session) + session.complete() } } diff --git a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt index c2a59061899..e490caeab4a 100644 --- a/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt +++ b/idea/idea-completion/src/org/jetbrains/kotlin/idea/completion/PackageDirectiveCompletion.kt @@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.completion import com.intellij.codeInsight.completion.CompletionParameters import com.intellij.codeInsight.completion.CompletionResultSet import com.intellij.codeInsight.completion.PlainPrefixMatcher -import com.intellij.openapi.progress.ProcessCanceledException import com.intellij.patterns.PlatformPatterns import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.util.CallType @@ -44,29 +43,24 @@ object PackageDirectiveCompletion { val expression = file.findElementAt(parameters.offset)?.parent as? KtSimpleNameExpression ?: return false - try { - val prefixLength = parameters.offset - expression.textOffset - val prefix = expression.text!! - val prefixMatcher = PlainPrefixMatcher(prefix.substring(0, prefixLength)) - val result = result.withPrefixMatcher(prefixMatcher) + val prefixLength = parameters.offset - expression.textOffset + val prefix = expression.text!! + val prefixMatcher = PlainPrefixMatcher(prefix.substring(0, prefixLength)) + val result = result.withPrefixMatcher(prefixMatcher) - val resolutionFacade = expression.getResolutionFacade() + val resolutionFacade = expression.getResolutionFacade() - val packageMemberScope = resolutionFacade.moduleDescriptor.getPackage(file.packageFqName.parent()).memberScope + val packageMemberScope = resolutionFacade.moduleDescriptor.getPackage(file.packageFqName.parent()).memberScope - val variants = packageMemberScope.getContributedDescriptors(DescriptorKindFilter.PACKAGES, prefixMatcher.asNameFilter()) - val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.PACKAGE_DIRECTIVE, expectedInfosCalculator = { emptyList() })) - for (variant in variants) { - val lookupElement = lookupElementFactory.createLookupElement(variant) - if (!lookupElement.lookupString.contains(DUMMY_IDENTIFIER)) { - result.addElement(lookupElement) - } + val variants = packageMemberScope.getContributedDescriptors(DescriptorKindFilter.PACKAGES, prefixMatcher.asNameFilter()) + val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.PACKAGE_DIRECTIVE, expectedInfosCalculator = { emptyList() })) + for (variant in variants) { + val lookupElement = lookupElementFactory.createLookupElement(variant) + if (!lookupElement.lookupString.contains(DUMMY_IDENTIFIER)) { + result.addElement(lookupElement) } + } - return true - } - catch (e: ProcessCanceledException) { - throw rethrowWithCancelIndicator(e) - } + return true } }