Smart completion: refactored static members processing
This commit is contained in:
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user