Smart completion: ExpectedTypeInfo renamed to ExpectedInfo

This commit is contained in:
Valentin Kipyatkov
2014-04-17 13:07:56 +04:00
parent 9609a9fff1
commit 164fb84cbe
7 changed files with 52 additions and 52 deletions
@@ -24,19 +24,19 @@ import java.util.HashSet
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
class ExpectedTypes(val bindingContext: BindingContext, val moduleDescriptor: ModuleDescriptor) {
public fun calculate(expressionWithType: JetExpression): Collection<ExpectedTypeInfo>? {
val expectedTypes = calculateForArgument(expressionWithType)
if (expectedTypes != null) {
return expectedTypes
class ExpectedInfos(val bindingContext: BindingContext, val moduleDescriptor: ModuleDescriptor) {
public fun calculate(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val expectedInfos = calculateForArgument(expressionWithType)
if (expectedInfos != null) {
return expectedInfos
}
else {
val expectedType = bindingContext[BindingContext.EXPECTED_EXPRESSION_TYPE, expressionWithType] ?: return null
return listOf(ExpectedTypeInfo(expectedType, null))
return listOf(ExpectedInfo(expectedType, null))
}
}
private fun calculateForArgument(expressionWithType: JetExpression): Collection<ExpectedTypeInfo>? {
private fun calculateForArgument(expressionWithType: JetExpression): Collection<ExpectedInfo>? {
val argument = expressionWithType.getParent() as? JetValueArgument ?: return null
if (argument.isNamed()) return null //TODO - support named arguments (also do not forget to check for presence of named arguments before)
val argumentList = argument.getParent() as JetValueArgumentList
@@ -74,14 +74,14 @@ class ExpectedTypes(val bindingContext: BindingContext, val moduleDescriptor: Mo
val callResolver = InjectorForMacros(expressionWithType.getProject(), moduleDescriptor).getCallResolver()!!
val results: OverloadResolutionResults<FunctionDescriptor> = callResolver.resolveFunctionCall(callResolutionContext)
val expectedTypes = HashSet<ExpectedTypeInfo>()
val expectedInfos = HashSet<ExpectedInfo>()
for (candidate: ResolvedCall<FunctionDescriptor> in results.getAllCandidates()!!) {
val parameters = candidate.getResultingDescriptor().getValueParameters()
if (parameters.size <= argumentIndex) continue
val parameterDescriptor = parameters[argumentIndex]
val tail = if (argumentIndex == parameters.size - 1) Tail.PARENTHESIS else Tail.COMMA
expectedTypes.add(ExpectedTypeInfo(parameterDescriptor.getType(), tail))
expectedInfos.add(ExpectedInfo(parameterDescriptor.getType(), tail))
}
return expectedTypes
return expectedInfos
}
}
@@ -10,8 +10,8 @@ import org.jetbrains.jet.plugin.refactoring.JetNameSuggester
import com.intellij.openapi.project.Project
class LambdaItems(val project: Project) {
public fun addToCollection(collection: MutableCollection<LookupElement>, functionExpectedTypes: Collection<ExpectedTypeInfo>) {
val distinctTypes = functionExpectedTypes.map { it.`type` }.toSet()
public fun addToCollection(collection: MutableCollection<LookupElement>, functionExpectedInfos: Collection<ExpectedInfo>) {
val distinctTypes = functionExpectedInfos.map { it.`type` }.toSet()
fun createLookupElement(lookupString: String, textBeforeCaret: String, textAfterCaret: String, shortenRefs: Boolean)
= LookupElementBuilder.create(lookupString)
@@ -23,7 +23,7 @@ class LambdaItems(val project: Project) {
val offerNoParametersLambda = singleSignatureLength == 0 || singleSignatureLength == 1
if (offerNoParametersLambda) {
val lookupElement = createLookupElement("{...}", "{ ", " }", shortenRefs = false)
collection.add(addTailToLookupElement(lookupElement, functionExpectedTypes))
collection.add(addTailToLookupElement(lookupElement, functionExpectedInfos))
}
if (singleSignatureLength != 0) {
@@ -53,7 +53,7 @@ class LambdaItems(val project: Project) {
val lookupString = "{ ${wrap(parametersPresentation)} -> ... }"
val lookupElement = createLookupElement(lookupString, "{ ${wrap(parametersText)} -> ", " }", shortenRefs = true)
collection.add(addTailToLookupElement(lookupElement, functionExpectedTypes.filter { it.`type` == functionType }))
collection.add(addTailToLookupElement(lookupElement, functionExpectedInfos.filter { it.`type` == functionType }))
}
}
}
@@ -17,7 +17,7 @@ enum class Tail {
PARENTHESIS
}
data class ExpectedTypeInfo(val `type`: JetType, val tail: Tail?)
data class ExpectedInfo(val `type`: JetType, val tail: Tail?)
class SmartCompletion(val expression: JetSimpleNameExpression,
val resolveSession: ResolveSessionForBodies,
@@ -40,9 +40,9 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
receiver = null
}
val allExpectedTypes = ExpectedTypes(bindingContext, moduleDescriptor).calculate(expressionWithType) ?: return null
val expectedTypes = allExpectedTypes.filter { !it.`type`.isError() }
if (expectedTypes.isEmpty()) return null
val allExpectedInfos = ExpectedInfos(bindingContext, moduleDescriptor).calculate(expressionWithType) ?: return null
val expectedInfos = allExpectedInfos.filter { !it.`type`.isError() }
if (expectedInfos.isEmpty()) return null
val result = ArrayList<LookupElement>()
@@ -50,32 +50,32 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
val itemsToSkip = calcItemsToSkip(expressionWithType)
val functionExpectedTypes = expectedTypes.filter { KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(it.`type`) }
val functionExpectedInfos = expectedInfos.filter { KotlinBuiltIns.getInstance().isExactFunctionOrExtensionFunctionType(it.`type`) }
for (descriptor in referenceVariants) {
if (itemsToSkip.contains(descriptor)) continue
val matchedExpectedTypes = expectedTypes.filter { expectedType ->
typesWithAutoCasts(descriptor).any { it.isSubtypeOf(expectedType.`type`) }
val matchedExpectedInfos = expectedInfos.filter { expectedInfo ->
typesWithAutoCasts(descriptor).any { it.isSubtypeOf(expectedInfo.`type`) }
}
if (matchedExpectedTypes.isNotEmpty()) {
if (matchedExpectedInfos.isNotEmpty()) {
val lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, descriptor)
result.add(addTailToLookupElement(lookupElement, matchedExpectedTypes))
result.add(addTailToLookupElement(lookupElement, matchedExpectedInfos))
}
if (receiver == null) {
toFunctionReferenceLookupElement(descriptor, functionExpectedTypes)?.let { result.add(it) }
toFunctionReferenceLookupElement(descriptor, functionExpectedInfos)?.let { result.add(it) }
}
}
if (receiver == null) {
TypeInstantiationItems(bindingContext, resolveSession).addToCollection(result, expectedTypes)
TypeInstantiationItems(bindingContext, resolveSession).addToCollection(result, expectedInfos)
StaticMembers(bindingContext, resolveSession).addToCollection(result, expectedTypes, expression)
StaticMembers(bindingContext, resolveSession).addToCollection(result, expectedInfos, expression)
ThisItems(bindingContext).addToCollection(result, expressionWithType, expectedTypes)
ThisItems(bindingContext).addToCollection(result, expressionWithType, expectedInfos)
LambdaItems(project).addToCollection(result, functionExpectedTypes)
LambdaItems(project).addToCollection(result, functionExpectedInfos)
}
return result
@@ -104,15 +104,15 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
}
private fun toFunctionReferenceLookupElement(descriptor: DeclarationDescriptor,
functionExpectedTypes: Collection<ExpectedTypeInfo>): LookupElement? {
if (functionExpectedTypes.isEmpty()) return null
functionExpectedInfos: Collection<ExpectedInfo>): LookupElement? {
if (functionExpectedInfos.isEmpty()) return null
fun toLookupElement(descriptor: FunctionDescriptor): LookupElement? {
val functionType = functionType(descriptor)
if (functionType == null) return null
val matchedExpectedTypes = functionExpectedTypes.filter { functionType.isSubtypeOf(it.`type`) }
if (matchedExpectedTypes.isEmpty()) return null
val matchedExpectedInfos = functionExpectedInfos.filter { functionType.isSubtypeOf(it.`type`) }
if (matchedExpectedInfos.isEmpty()) return null
var lookupElement = DescriptorLookupConverter.createLookupElement(resolveSession, bindingContext, descriptor)
val text = "::" + (if (descriptor is ConstructorDescriptor) descriptor.getContainingDeclaration().getName() else descriptor.getName())
@@ -129,7 +129,7 @@ class SmartCompletion(val expression: JetSimpleNameExpression,
}
}
return addTailToLookupElement(lookupElement, matchedExpectedTypes)
return addTailToLookupElement(lookupElement, matchedExpectedInfos)
}
if (descriptor is SimpleFunctionDescriptor) {
@@ -24,14 +24,14 @@ import org.jetbrains.jet.lang.psi.JetExpression
// adds java static members, enum members and members from class object
class StaticMembers(val bindingContext: BindingContext, val resolveSession: ResolveSessionForBodies) {
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedTypes: Collection<ExpectedTypeInfo>, context: JetExpression) {
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedInfos: Collection<ExpectedInfo>, context: JetExpression) {
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, context]
if (scope == null) return
val expectedTypesByClass = expectedTypes.groupBy { TypeUtils.getClassDescriptor(it.`type`) }
for ((classDescriptor, expectedTypesForClass) in expectedTypesByClass) {
val expectedInfosByClass = expectedInfos.groupBy { TypeUtils.getClassDescriptor(it.`type`) }
for ((classDescriptor, expectedInfosForClass) in expectedInfosByClass) {
if (classDescriptor != null && !classDescriptor.getName().isSpecial()) {
addToCollection(collection, classDescriptor, expectedTypesForClass, scope)
addToCollection(collection, classDescriptor, expectedInfosForClass, scope)
}
}
}
@@ -39,21 +39,21 @@ class StaticMembers(val bindingContext: BindingContext, val resolveSession: Reso
private fun addToCollection(
collection: MutableCollection<LookupElement>,
classDescriptor: ClassDescriptor,
expectedTypes: Collection<ExpectedTypeInfo>,
expectedInfos: Collection<ExpectedInfo>,
scope: JetScope) {
fun processMember(descriptor: DeclarationDescriptor) {
if (descriptor is DeclarationDescriptorWithVisibility && !Visibilities.isVisible(descriptor, scope.getContainingDeclaration())) return
val matchedExpectedTypes = expectedTypes.filter {
expectedType ->
descriptor is CallableDescriptor && descriptor.getReturnType()?.let { it.isSubtypeOf(expectedType.`type`) } ?: false
val matchedExpectedInfos = expectedInfos.filter {
expectedInfo ->
descriptor is CallableDescriptor && descriptor.getReturnType()?.let { it.isSubtypeOf(expectedInfo.`type`) } ?: false
|| descriptor is ClassDescriptor && descriptor.getKind() == ClassKind.ENUM_ENTRY
}
if (matchedExpectedTypes.isEmpty()) return
if (matchedExpectedInfos.isEmpty()) return
val lookupElement = createLookupElement(descriptor, classDescriptor)
collection.add(addTailToLookupElement(lookupElement, matchedExpectedTypes))
collection.add(addTailToLookupElement(lookupElement, matchedExpectedInfos))
}
if (classDescriptor is JavaClassDescriptor) {
@@ -19,7 +19,7 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.resolve.BindingContext
class ThisItems(val bindingContext: BindingContext) {
public fun addToCollection(collection: MutableCollection<LookupElement>, context: JetExpression, expectedTypes: Collection<ExpectedTypeInfo>) {
public fun addToCollection(collection: MutableCollection<LookupElement>, context: JetExpression, expectedInfos: Collection<ExpectedInfo>) {
val scope = bindingContext[BindingContext.RESOLUTION_SCOPE, context]
if (scope == null) return
@@ -27,14 +27,14 @@ class ThisItems(val bindingContext: BindingContext) {
for (i in 0..receivers.size - 1) {
val receiver = receivers[i]
val thisType = receiver.getType()
val matchedExpectedTypes = expectedTypes.filter { thisType.isSubtypeOf(it.`type`) }
if (matchedExpectedTypes.notEmpty) {
val matchedExpectedInfos = expectedInfos.filter { thisType.isSubtypeOf(it.`type`) }
if (matchedExpectedInfos.notEmpty) {
//TODO: use this code when KT-4258 fixed
//val expressionText = if (i == 0) "this" else "this@" + (thisQualifierName(receiver, bindingContext) ?: continue)
val qualifier = if (i == 0) null else thisQualifierName(receiver) ?: continue
val expressionText = if (qualifier == null) "this" else "this@" + qualifier
val lookupElement = LookupElementBuilder.create(expressionText).withTypeText(DescriptorRenderer.TEXT.renderType(thisType))
collection.add(addTailToLookupElement(lookupElement, matchedExpectedTypes))
collection.add(addTailToLookupElement(lookupElement, matchedExpectedInfos))
}
}
}
@@ -21,9 +21,9 @@ import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies
class TypeInstantiationItems(val bindingContext: BindingContext, val resolveSession: ResolveSessionForBodies) {
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedTypes: Collection<ExpectedTypeInfo>) {
val expectedTypesGrouped: Map<JetType, List<ExpectedTypeInfo>> = expectedTypes.groupBy { TypeUtils.makeNotNullable(it.`type`) }
for ((jetType, types) in expectedTypesGrouped) {
public fun addToCollection(collection: MutableCollection<LookupElement>, expectedInfos: Collection<ExpectedInfo>) {
val expectedInfosGrouped: Map<JetType, List<ExpectedInfo>> = expectedInfos.groupBy { TypeUtils.makeNotNullable(it.`type`) }
for ((jetType, types) in expectedInfosGrouped) {
val tail = mergeTails(types.map { it.tail })
addToCollection(collection, jetType, tail)
}
@@ -64,8 +64,8 @@ fun addTailToLookupElement(lookupElement: LookupElement, tail: Tail?): LookupEle
}
}
fun addTailToLookupElement(lookupElement: LookupElement, matchedExpectedTypes: Collection<ExpectedTypeInfo>): LookupElement
= addTailToLookupElement(lookupElement, mergeTails(matchedExpectedTypes.map { it.tail }))
fun addTailToLookupElement(lookupElement: LookupElement, matchedExpectedInfos: Collection<ExpectedInfo>): LookupElement
= addTailToLookupElement(lookupElement, mergeTails(matchedExpectedInfos.map { it.tail }))
fun LookupElement.suppressAutoInsertion() = AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(this)