Smart completion: refactored static members processing

This commit is contained in:
Valentin Kipyatkov
2014-04-16 23:12:01 +04:00
parent ad791d0480
commit c53da996c4
@@ -35,7 +35,6 @@ import com.intellij.lang.ASTNode
import org.jetbrains.jet.lang.resolve.scopes.JetScope import org.jetbrains.jet.lang.resolve.scopes.JetScope
import org.jetbrains.jet.plugin.refactoring.JetNameSuggester import org.jetbrains.jet.plugin.refactoring.JetNameSuggester
import org.jetbrains.jet.plugin.refactoring.JetNameValidator import org.jetbrains.jet.plugin.refactoring.JetNameValidator
import com.intellij.openapi.project.Project
class SmartCompletion(val expression: JetSimpleNameExpression, class SmartCompletion(val expression: JetSimpleNameExpression,
val resolveSession: ResolveSessionForBodies, val resolveSession: ResolveSessionForBodies,
@@ -497,97 +496,88 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
expectedTypes: Collection<ExpectedTypeInfo>, expectedTypes: Collection<ExpectedTypeInfo>,
scope: JetScope) { scope: JetScope) {
val memberDescriptors = HashMap<DeclarationDescriptor, MutableList<ExpectedTypeInfo>>() fun processMember(descriptor: DeclarationDescriptor) {
if (descriptor is DeclarationDescriptorWithVisibility && !Visibilities.isVisible(descriptor, scope.getContainingDeclaration())) return
for (expectedType in expectedTypes) { val matchedExpectedTypes = expectedTypes.filter {
fun addMemberDescriptor(descriptor: DeclarationDescriptor) { expectedType ->
val list = memberDescriptors[descriptor] descriptor is CallableDescriptor && descriptor.getReturnType()?.let { it.isSubtypeOf(expectedType.`type`) } ?: false
if (list != null) { || descriptor is ClassDescriptor && descriptor.getKind() == ClassKind.ENUM_ENTRY
list.add(expectedType)
}
else {
if (descriptor is DeclarationDescriptorWithVisibility && !Visibilities.isVisible(descriptor, scope.getContainingDeclaration())) return
val newList = ArrayList<ExpectedTypeInfo>()
newList.add(expectedType)
memberDescriptors[descriptor] = newList
}
} }
if (matchedExpectedTypes.isEmpty()) return
fun isSuitableCallable(descriptor: DeclarationDescriptor) val lookupElement = createStaticMemberLookupElement(descriptor, classDescriptor)
= descriptor is CallableDescriptor && descriptor.getReturnType()?.let { it.isSubtypeOf(expectedType.`type`) } ?: false add(addTailToLookupElement(lookupElement, matchedExpectedTypes))
}
if (classDescriptor is JavaClassDescriptor) { if (classDescriptor is JavaClassDescriptor) {
val pseudoPackage = classDescriptor.getCorrespondingPackageFragment() val pseudoPackage = classDescriptor.getCorrespondingPackageFragment()
if (pseudoPackage != null) { if (pseudoPackage != null) {
pseudoPackage.getMemberScope().getAllDescriptors().filter(::isSuitableCallable).forEach(::addMemberDescriptor) pseudoPackage.getMemberScope().getAllDescriptors().forEach(::processMember)
}
}
val classObject = classDescriptor.getClassObjectDescriptor()
if (classObject != null) {
classObject.getDefaultType().getMemberScope().getAllDescriptors().filter(::isSuitableCallable).forEach(::addMemberDescriptor)
}
if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
classDescriptor.getDefaultType().getMemberScope().getAllDescriptors()
.filter { it is ClassDescriptor && it.getKind() == ClassKind.ENUM_ENTRY }.forEach(::addMemberDescriptor)
} }
} }
for ((descriptor, descriptorExpectedTypes) in memberDescriptors) { val classObject = classDescriptor.getClassObjectDescriptor()
var lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, descriptor) if (classObject != null) {
val qualifierPresentation = classDescriptor.getName().asString() classObject.getDefaultType().getMemberScope().getAllDescriptors().forEach(::processMember)
val lookupString = qualifierPresentation + "." + lookupElement.getLookupString() }
val qualifierText = DescriptorUtils.getFqName(classDescriptor).asString() //TODO: escape keywords
val caretPosition: CaretPosition? if (classDescriptor.getKind() == ClassKind.ENUM_CLASS) {
if (descriptor is FunctionDescriptor) { classDescriptor.getDefaultType().getMemberScope().getAllDescriptors().forEach(::processMember)
caretPosition = if (descriptor.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS }
} }
else {
caretPosition = null
}
lookupElement = object: LookupElementDecorator<LookupElement>(lookupElement) {
override fun getLookupString() = lookupString
override fun renderElement(presentation: LookupElementPresentation) { private fun createStaticMemberLookupElement(memberDescriptor: DeclarationDescriptor, classDescriptor: ClassDescriptor): LookupElement {
getDelegate().renderElement(presentation) val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, memberDescriptor)
val qualifierPresentation = classDescriptor.getName().asString()
val lookupString = qualifierPresentation + "." + lookupElement.getLookupString()
val qualifierText = DescriptorUtils.getFqName(classDescriptor).asString() //TODO: escape keywords
presentation.setItemText(qualifierPresentation + "." + presentation.getItemText()) val caretPosition: CaretPosition?
if (memberDescriptor is FunctionDescriptor) {
caretPosition = if (memberDescriptor.getValueParameters().empty) CaretPosition.AFTER_BRACKETS else CaretPosition.IN_BRACKETS
}
else {
caretPosition = null
}
val tailText = " (" + DescriptorUtils.getFqName(classDescriptor.getContainingDeclaration()) + ")" return object: LookupElementDecorator<LookupElement>(lookupElement) {
if (descriptor is FunctionDescriptor) { override fun getLookupString() = lookupString
presentation.appendTailText(tailText, true)
}
else {
presentation.setTailText(tailText, true)
}
if (presentation.getTypeText().isNullOrEmpty()) { override fun renderElement(presentation: LookupElementPresentation) {
presentation.setTypeText(DescriptorRenderer.TEXT.renderType(classDescriptor.getDefaultType())) getDelegate().renderElement(presentation)
}
presentation.setItemText(qualifierPresentation + "." + presentation.getItemText())
val tailText = " (" + DescriptorUtils.getFqName(classDescriptor.getContainingDeclaration()) + ")"
if (memberDescriptor is FunctionDescriptor) {
presentation.appendTailText(tailText, true)
}
else {
presentation.setTailText(tailText, true)
} }
override fun handleInsert(context: InsertionContext) { if (presentation.getTypeText().isNullOrEmpty()) {
val editor = context.getEditor() presentation.setTypeText(DescriptorRenderer.TEXT.renderType(classDescriptor.getDefaultType()))
val startOffset = context.getStartOffset()
var text = qualifierText + "." + descriptor.getName().asString() //TODO: escape
if (descriptor is FunctionDescriptor) {
text += "()"
//TODO: auto-popup parameter info and other functionality from JetFunctionInsertHandler
}
editor.getDocument().replaceString(startOffset, context.getTailOffset(), text)
val endOffset = startOffset + text.length
editor.getCaretModel().moveToOffset(if (caretPosition == CaretPosition.IN_BRACKETS) endOffset - 1 else endOffset)
shortenReferences(context, startOffset, startOffset + qualifierText.length)
} }
} }
add(addTailToLookupElement(lookupElement, descriptorExpectedTypes)) override fun handleInsert(context: InsertionContext) {
val editor = context.getEditor()
val startOffset = context.getStartOffset()
var text = qualifierText + "." + memberDescriptor.getName().asString() //TODO: escape
if (memberDescriptor is FunctionDescriptor) {
text += "()"
//TODO: auto-popup parameter info and other functionality from JetFunctionInsertHandler
}
editor.getDocument().replaceString(startOffset, context.getTailOffset(), text)
val endOffset = startOffset + text.length
editor.getCaretModel().moveToOffset(if (caretPosition == CaretPosition.IN_BRACKETS) endOffset - 1 else endOffset)
shortenReferences(context, startOffset, startOffset + qualifierText.length)
}
} }
} }