KT-12447 Don't use CompletionProgressIndicator in Kotlin plugin
#KT-12447 Fixed
This commit is contained in:
+18
-2
@@ -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()
|
||||
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
|
||||
+2
-24
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
+27
-32
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-20
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user