Support for A::class and A::class.java in basic completion (but not in smart)

This commit is contained in:
Valentin Kipyatkov
2015-09-30 20:45:36 +03:00
parent ebf649a681
commit ec5d1d3a52
3 changed files with 68 additions and 41 deletions
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.CompletionSorter
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.codeInsight.template.TemplateManager
import com.intellij.patterns.PatternCondition
import com.intellij.patterns.StandardPatterns
@@ -37,6 +38,7 @@ import org.jetbrains.kotlin.idea.completion.smart.SmartCompletion
import org.jetbrains.kotlin.idea.completion.smart.SmartCompletionItemPriority
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil
import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
@@ -230,43 +232,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
collector.addDescriptorElements(referenceVariants)
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
val keyword = lookupElement.getLookupString()
when (keyword) {
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
"this" -> {
if (expression != null) {
collector.addElements(thisExpressionItems(bindingContext, expression, prefix, resolutionFacade).map { it.createLookupElement() })
}
else {
// for completion in secondary constructor delegation call
collector.addElement(lookupElement)
}
}
// if "return" is parsed correctly in the current context - insert it and all return@xxx items
"return" -> {
if (expression != null) {
collector.addElements(returnExpressionItems(bindingContext, expression))
}
}
"break", "continue" -> {
if (expression != null) {
collector.addElements(breakOrContinueExpressionItems(expression, keyword))
}
}
"override" -> {
collector.addElement(lookupElement)
OverridesCompletion(collector, lookupElementFactory).complete(position)
}
else -> collector.addElement(lookupElement)
}
}
completeKeywords()
// getting root packages from scope is very slow so we do this in alternative way
if (isNoQualifierContext() && (descriptorKindFilter?.kindMask ?: 0).and(DescriptorKindFilter.PACKAGES_MASK) != 0) {
@@ -293,7 +259,7 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
collector.advertiseSecondCompletion()
}
addNonImported(completionKind)
completeNonImported()
if (position.getContainingFile() is JetCodeFragment) {
flushToResultSet()
@@ -305,7 +271,66 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
NamedArgumentCompletion.complete(collector, expectedInfos)
}
private fun addNonImported(completionKind: CompletionKind) {
private fun completeKeywords() {
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc
KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
val keyword = lookupElement.getLookupString()
when (keyword) {
// if "this" is parsed correctly in the current context - insert it and all this@xxx items
"this" -> {
if (expression != null) {
collector.addElements(thisExpressionItems(bindingContext, expression, prefix, resolutionFacade).map { it.createLookupElement() })
}
else {
// for completion in secondary constructor delegation call
collector.addElement(lookupElement)
}
}
// if "return" is parsed correctly in the current context - insert it and all return@xxx items
"return" -> {
if (expression != null) {
collector.addElements(returnExpressionItems(bindingContext, expression))
}
}
"break", "continue" -> {
if (expression != null) {
collector.addElements(breakOrContinueExpressionItems(expression, keyword))
}
}
"override" -> {
collector.addElement(lookupElement)
OverridesCompletion(collector, lookupElementFactory).complete(position)
}
"class" -> {
if (callTypeAndReceiver is CallTypeAndReceiver.CALLABLE_REFERENCE) {
if (callTypeAndReceiver.receiver != null) {
collector.addElement(lookupElement)
if (!ProjectStructureUtil.isJsKotlinModule(parameters.originalFile as JetFile)) {
val element = LookupElementBuilder.create(KeywordLookupObject(), "class.java")
.withPresentableText("class")
.withTailText(".java")
.bold()
collector.addElement(element)
}
}
}
else {
collector.addElement(lookupElement)
}
}
else -> collector.addElement(lookupElement)
}
}
}
private fun completeNonImported() {
if (completionKind == CompletionKind.ALL) {
collector.addDescriptorElements(getTopLevelExtensions(), notImported = true)
}
@@ -46,3 +46,5 @@ abstract class AbstractClass
// EXIST: { itemText: "InnerClass", attributes: "bold" }
// ABSENT: WithPrivateConstructor
// ABSENT: AbstractClass
// ABSENT: class
// ABSENT: class.java
@@ -37,8 +37,8 @@ class C {
}
}
/* TODO // EXIST: class */
/* TODO // EXIST: class.java */
// EXIST: { lookupString: "class", itemText: "class", attributes: "bold" }
// EXIST_JAVA_ONLY: { lookupString: "class.java", itemText: "class", tailText: ".java", attributes: "bold" }
// EXIST: { itemText: "memberFunInA", attributes: "bold" }
// EXIST: { itemText: "memberValInA", attributes: "bold" }
// EXIST: { itemText: "InnerInA", attributes: "bold" }