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.CompletionResultSet
import com.intellij.codeInsight.completion.CompletionSorter import com.intellij.codeInsight.completion.CompletionSorter
import com.intellij.codeInsight.completion.CompletionType import com.intellij.codeInsight.completion.CompletionType
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
@@ -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.completion.smart.SmartCompletionItemPriority
import org.jetbrains.kotlin.idea.project.ProjectStructureUtil import org.jetbrains.kotlin.idea.project.ProjectStructureUtil
import org.jetbrains.kotlin.idea.stubindex.PackageIndexUtil 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -230,6 +232,46 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
collector.addDescriptorElements(referenceVariants) collector.addDescriptorElements(referenceVariants)
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) {
//TODO: move this code somewhere else?
val packageNames = PackageIndexUtil.getSubPackageFqNames(FqName.ROOT, originalSearchScope, project, prefixMatcher.asNameFilter())
.toMutableSet()
if (!ProjectStructureUtil.isJsKotlinModule(parameters.getOriginalFile() as JetFile)) {
JavaPsiFacade.getInstance(project).findPackage("")?.getSubPackages(originalSearchScope)?.forEach { psiPackage ->
val name = psiPackage.getName()
if (Name.isValidIdentifier(name!!)) {
packageNames.add(FqName(name))
}
}
}
packageNames.forEach { collector.addElement(lookupElementFactory.createLookupElementForPackage(it)) }
}
if (completionKind != CompletionKind.KEYWORDS_ONLY) {
flushToResultSet()
if (!configuration.completeNonImportedDeclarations && isNoQualifierContext()) {
collector.advertiseSecondCompletion()
}
completeNonImported()
if (position.getContainingFile() is JetCodeFragment) {
flushToResultSet()
collector.addDescriptorElements(getRuntimeReceiverTypeReferenceVariants(), withReceiverCast = true)
}
}
}
NamedArgumentCompletion.complete(collector, expectedInfos)
}
private fun completeKeywords() {
val keywordsPrefix = prefix.substringBefore('@') // if there is '@' in the prefix - use shorter prefix to not loose 'this' etc 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 -> KeywordCompletion.complete(expression ?: parameters.getPosition(), keywordsPrefix) { lookupElement ->
val keyword = lookupElement.getLookupString() val keyword = lookupElement.getLookupString()
@@ -264,48 +306,31 @@ class BasicCompletionSession(configuration: CompletionSessionConfiguration,
OverridesCompletion(collector, lookupElementFactory).complete(position) 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) else -> collector.addElement(lookupElement)
} }
} }
// 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) {
//TODO: move this code somewhere else?
val packageNames = PackageIndexUtil.getSubPackageFqNames(FqName.ROOT, originalSearchScope, project, prefixMatcher.asNameFilter())
.toMutableSet()
if (!ProjectStructureUtil.isJsKotlinModule(parameters.getOriginalFile() as JetFile)) {
JavaPsiFacade.getInstance(project).findPackage("")?.getSubPackages(originalSearchScope)?.forEach { psiPackage ->
val name = psiPackage.getName()
if (Name.isValidIdentifier(name!!)) {
packageNames.add(FqName(name))
}
}
} }
packageNames.forEach { collector.addElement(lookupElementFactory.createLookupElementForPackage(it)) } private fun completeNonImported() {
}
if (completionKind != CompletionKind.KEYWORDS_ONLY) {
flushToResultSet()
if (!configuration.completeNonImportedDeclarations && isNoQualifierContext()) {
collector.advertiseSecondCompletion()
}
addNonImported(completionKind)
if (position.getContainingFile() is JetCodeFragment) {
flushToResultSet()
collector.addDescriptorElements(getRuntimeReceiverTypeReferenceVariants(), withReceiverCast = true)
}
}
}
NamedArgumentCompletion.complete(collector, expectedInfos)
}
private fun addNonImported(completionKind: CompletionKind) {
if (completionKind == CompletionKind.ALL) { if (completionKind == CompletionKind.ALL) {
collector.addDescriptorElements(getTopLevelExtensions(), notImported = true) collector.addDescriptorElements(getTopLevelExtensions(), notImported = true)
} }
@@ -46,3 +46,5 @@ abstract class AbstractClass
// EXIST: { itemText: "InnerClass", attributes: "bold" } // EXIST: { itemText: "InnerClass", attributes: "bold" }
// ABSENT: WithPrivateConstructor // ABSENT: WithPrivateConstructor
// ABSENT: AbstractClass // ABSENT: AbstractClass
// ABSENT: class
// ABSENT: class.java
@@ -37,8 +37,8 @@ class C {
} }
} }
/* TODO // EXIST: class */ // EXIST: { lookupString: "class", itemText: "class", attributes: "bold" }
/* TODO // EXIST: class.java */ // EXIST_JAVA_ONLY: { lookupString: "class.java", itemText: "class", tailText: ".java", attributes: "bold" }
// EXIST: { itemText: "memberFunInA", attributes: "bold" } // EXIST: { itemText: "memberFunInA", attributes: "bold" }
// EXIST: { itemText: "memberValInA", attributes: "bold" } // EXIST: { itemText: "memberValInA", attributes: "bold" }
// EXIST: { itemText: "InnerInA", attributes: "bold" } // EXIST: { itemText: "InnerInA", attributes: "bold" }