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