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.codeInsight.template.TemplateManager
|
||||||
import com.intellij.patterns.PatternCondition
|
import com.intellij.patterns.PatternCondition
|
||||||
import com.intellij.patterns.StandardPatterns
|
import com.intellij.patterns.StandardPatterns
|
||||||
import com.intellij.psi.JavaPsiFacade
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.PsiClass
|
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
import com.intellij.util.ProcessingContext
|
import com.intellij.util.ProcessingContext
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
@@ -119,11 +118,28 @@ class BasicCompletionSession(
|
|||||||
lookupElement.putUserData(LookupCancelWatcher.AUTO_POPUP_AT, position.startOffset)
|
lookupElement.putUserData(LookupCancelWatcher.AUTO_POPUP_AT, position.startOffset)
|
||||||
lookupElement
|
lookupElement
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isInFunctionLiteralStart(position)) {
|
||||||
|
collector.addLookupElementPostProcessor { lookupElement ->
|
||||||
|
lookupElement.putUserData(KotlinCompletionCharFilter.SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING, Unit)
|
||||||
|
lookupElement
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
completionKind.doComplete()
|
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 {
|
override fun createSorter(): CompletionSorter {
|
||||||
var sorter = super.createSorter()
|
var sorter = super.createSorter()
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.completion
|
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.InsertionContext
|
||||||
import com.intellij.codeInsight.completion.PrefixMatcher
|
import com.intellij.codeInsight.completion.PrefixMatcher
|
||||||
import com.intellij.codeInsight.lookup.*
|
import com.intellij.codeInsight.lookup.*
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
|
||||||
import com.intellij.openapi.util.Key
|
import com.intellij.openapi.util.Key
|
||||||
import com.intellij.patterns.ElementPattern
|
import com.intellij.patterns.ElementPattern
|
||||||
import com.intellij.patterns.StandardPatterns
|
import com.intellij.patterns.StandardPatterns
|
||||||
@@ -107,17 +104,6 @@ fun LookupElement.keepOldArgumentListOnTab(): LookupElement {
|
|||||||
return this
|
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 {
|
fun PrefixMatcher.asNameFilter(): (Name) -> Boolean {
|
||||||
return { name -> !name.isSpecial && prefixMatches(name.identifier) }
|
return { name -> !name.isSpecial && prefixMatches(name.identifier) }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-24
@@ -16,19 +16,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.completion
|
package org.jetbrains.kotlin.idea.completion
|
||||||
|
|
||||||
import com.intellij.codeInsight.completion.CompletionProgressIndicator
|
|
||||||
import com.intellij.codeInsight.completion.CompletionService
|
import com.intellij.codeInsight.completion.CompletionService
|
||||||
import com.intellij.codeInsight.lookup.CharFilter
|
import com.intellij.codeInsight.lookup.CharFilter
|
||||||
import com.intellij.codeInsight.lookup.CharFilter.Result
|
|
||||||
import com.intellij.codeInsight.lookup.Lookup
|
import com.intellij.codeInsight.lookup.Lookup
|
||||||
import com.intellij.openapi.util.Key
|
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.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtFunctionLiteral
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.prevLeaf
|
|
||||||
|
|
||||||
class KotlinCompletionCharFilter() : CharFilter() {
|
class KotlinCompletionCharFilter() : CharFilter() {
|
||||||
companion object {
|
companion object {
|
||||||
@@ -43,10 +35,7 @@ class KotlinCompletionCharFilter() : CharFilter() {
|
|||||||
override fun acceptChar(c : Char, prefixLength : Int, lookup : Lookup) : Result? {
|
override fun acceptChar(c : Char, prefixLength : Int, lookup : Lookup) : Result? {
|
||||||
if (lookup.psiFile !is KtFile) return null
|
if (lookup.psiFile !is KtFile) return null
|
||||||
if (!lookup.isCompletion) return null
|
if (!lookup.isCompletion) return null
|
||||||
// it does not work in tests, so we use other way
|
val isAutopopup = CompletionService.getCompletionService().currentCompletion!!.isAutopopupCompletion
|
||||||
// val isAutopopup = CompletionService.getCompletionService().getCurrentCompletion().isAutopopupCompletion()
|
|
||||||
val completionParameters = (CompletionService.getCompletionService().currentCompletion as CompletionProgressIndicator).parameters
|
|
||||||
val isAutopopup = completionParameters.invocationCount == 0
|
|
||||||
|
|
||||||
if (Character.isJavaIdentifierPart(c) || c == '@') {
|
if (Character.isJavaIdentifierPart(c) || c == '@') {
|
||||||
return CharFilter.Result.ADD_TO_PREFIX
|
return CharFilter.Result.ADD_TO_PREFIX
|
||||||
@@ -55,8 +44,7 @@ class KotlinCompletionCharFilter() : CharFilter() {
|
|||||||
val currentItem = lookup.currentItem
|
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
|
// 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
|
if (isAutopopup && !lookup.isSelectionTouched && currentItem?.getUserData(SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING) != null) {
|
||||||
&& (currentItem?.getUserData(SUPPRESS_ITEM_SELECTION_BY_CHARS_ON_TYPING) != null || isInFunctionLiteralStart(completionParameters.position))) {
|
|
||||||
return Result.HIDE_LOOKUP
|
return Result.HIDE_LOOKUP
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,14 +82,4 @@ class KotlinCompletionCharFilter() : CharFilter() {
|
|||||||
else -> CharFilter.Result.HIDE_LOOKUP
|
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)
|
val configuration = CompletionSessionConfiguration(parameters)
|
||||||
if (parameters.completionType == CompletionType.BASIC) {
|
if (parameters.completionType == CompletionType.BASIC) {
|
||||||
val session = BasicCompletionSession(configuration, parameters, toFromOriginalFileMapper, result)
|
val session = BasicCompletionSession(configuration, parameters, toFromOriginalFileMapper, result)
|
||||||
|
|
||||||
addPostProcessor(session)
|
addPostProcessor(session)
|
||||||
|
|
||||||
if (parameters.isAutoPopup && session.shouldDisableAutoPopup()) {
|
if (parameters.isAutoPopup && session.shouldDisableAutoPopup()) {
|
||||||
result.stopHere()
|
result.stopHere()
|
||||||
return
|
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()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
val session = SmartCompletionSession(configuration, parameters, toFromOriginalFileMapper, result)
|
val somethingAdded = session.complete()
|
||||||
addPostProcessor(session)
|
if (!somethingAdded && parameters.invocationCount < 2) {
|
||||||
session.complete()
|
// 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) {
|
else {
|
||||||
throw rethrowWithCancelIndicator(e)
|
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.CompletionParameters
|
||||||
import com.intellij.codeInsight.completion.CompletionResultSet
|
import com.intellij.codeInsight.completion.CompletionResultSet
|
||||||
import com.intellij.codeInsight.completion.PlainPrefixMatcher
|
import com.intellij.codeInsight.completion.PlainPrefixMatcher
|
||||||
import com.intellij.openapi.progress.ProcessCanceledException
|
|
||||||
import com.intellij.patterns.PlatformPatterns
|
import com.intellij.patterns.PlatformPatterns
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.util.CallType
|
import org.jetbrains.kotlin.idea.util.CallType
|
||||||
@@ -44,29 +43,24 @@ object PackageDirectiveCompletion {
|
|||||||
|
|
||||||
val expression = file.findElementAt(parameters.offset)?.parent as? KtSimpleNameExpression ?: return false
|
val expression = file.findElementAt(parameters.offset)?.parent as? KtSimpleNameExpression ?: return false
|
||||||
|
|
||||||
try {
|
val prefixLength = parameters.offset - expression.textOffset
|
||||||
val prefixLength = parameters.offset - expression.textOffset
|
val prefix = expression.text!!
|
||||||
val prefix = expression.text!!
|
val prefixMatcher = PlainPrefixMatcher(prefix.substring(0, prefixLength))
|
||||||
val prefixMatcher = PlainPrefixMatcher(prefix.substring(0, prefixLength))
|
val result = result.withPrefixMatcher(prefixMatcher)
|
||||||
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 variants = packageMemberScope.getContributedDescriptors(DescriptorKindFilter.PACKAGES, prefixMatcher.asNameFilter())
|
||||||
val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.PACKAGE_DIRECTIVE, expectedInfosCalculator = { emptyList() }))
|
val lookupElementFactory = BasicLookupElementFactory(resolutionFacade.project, InsertHandlerProvider(callType = CallType.PACKAGE_DIRECTIVE, expectedInfosCalculator = { emptyList() }))
|
||||||
for (variant in variants) {
|
for (variant in variants) {
|
||||||
val lookupElement = lookupElementFactory.createLookupElement(variant)
|
val lookupElement = lookupElementFactory.createLookupElement(variant)
|
||||||
if (!lookupElement.lookupString.contains(DUMMY_IDENTIFIER)) {
|
if (!lookupElement.lookupString.contains(DUMMY_IDENTIFIER)) {
|
||||||
result.addElement(lookupElement)
|
result.addElement(lookupElement)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
|
||||||
catch (e: ProcessCanceledException) {
|
|
||||||
throw rethrowWithCancelIndicator(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user