No useless null in return value of ExpectedInfos.calculate

This commit is contained in:
Valentin Kipyatkov
2015-08-06 20:35:40 +03:00
parent e6f5cefce3
commit 2728047acd
5 changed files with 28 additions and 30 deletions
@@ -149,7 +149,7 @@ class ExpectedInfos(
val useHeuristicSignatures: Boolean = true, val useHeuristicSignatures: Boolean = true,
val useOuterCallsExpectedTypeCount: Int = 0 val useOuterCallsExpectedTypeCount: Int = 0
) { ) {
public fun calculate(expressionWithType: JetExpression): Collection<ExpectedInfo>? { public fun calculate(expressionWithType: JetExpression): Collection<ExpectedInfo> {
val expectedInfos = calculateForArgument(expressionWithType) val expectedInfos = calculateForArgument(expressionWithType)
?: calculateForFunctionLiteralArgument(expressionWithType) ?: calculateForFunctionLiteralArgument(expressionWithType)
?: calculateForEqAndAssignment(expressionWithType) ?: calculateForEqAndAssignment(expressionWithType)
@@ -164,7 +164,7 @@ class ExpectedInfos(
?: calculateForLoopRange(expressionWithType) ?: calculateForLoopRange(expressionWithType)
?: calculateForInOperatorArgument(expressionWithType) ?: calculateForInOperatorArgument(expressionWithType)
?: getFromBindingContext(expressionWithType) ?: getFromBindingContext(expressionWithType)
?: return null ?: return emptyList()
return expectedInfos.filterNot { it.fuzzyType?.type?.isError ?: false } return expectedInfos.filterNot { it.fuzzyType?.type?.isError ?: false }
} }
@@ -188,8 +188,8 @@ class ExpectedInfos(
return calculateForArgument(call, argument) return calculateForArgument(call, argument)
} }
public fun calculateForArgument(call: Call, argument: ValueArgument): Collection<ExpectedInfo>? { public fun calculateForArgument(call: Call, argument: ValueArgument): Collection<ExpectedInfo> {
val results = calculateForArgument(call, TypeUtils.NO_EXPECTED_TYPE, argument) ?: return null val results = calculateForArgument(call, TypeUtils.NO_EXPECTED_TYPE, argument)
fun makesSenseToUseOuterCallExpectedType(info: ExpectedInfo): Boolean { fun makesSenseToUseOuterCallExpectedType(info: ExpectedInfo): Boolean {
val data = info.additionalData as ArgumentAdditionalData val data = info.additionalData as ArgumentAdditionalData
@@ -202,21 +202,21 @@ class ExpectedInfos(
val callExpression = (call.callElement as? JetExpression)?.getQualifiedExpressionForSelectorOrThis() ?: return results val callExpression = (call.callElement as? JetExpression)?.getQualifiedExpressionForSelectorOrThis() ?: return results
val expectedFuzzyTypes = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor, useHeuristicSignatures, useOuterCallsExpectedTypeCount - 1) val expectedFuzzyTypes = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor, useHeuristicSignatures, useOuterCallsExpectedTypeCount - 1)
.calculate(callExpression) .calculate(callExpression)
?.map { it.fuzzyType } .map { it.fuzzyType }
?.filterNotNull() ?: return results .filterNotNull()
if (expectedFuzzyTypes.isEmpty() || expectedFuzzyTypes.any { it.freeParameters.isNotEmpty() }) return results if (expectedFuzzyTypes.isEmpty() || expectedFuzzyTypes.any { it.freeParameters.isNotEmpty() }) return results
return expectedFuzzyTypes return expectedFuzzyTypes
.map { it.type } .map { it.type }
.toSet() .toSet()
.flatMap { calculateForArgument(call, it, argument) ?: emptyList() } .flatMap { calculateForArgument(call, it, argument) }
.toSet() .toSet()
} }
return results return results
} }
private fun calculateForArgument(call: Call, callExpectedType: JetType, argument: ValueArgument): Collection<ExpectedInfo>? { private fun calculateForArgument(call: Call, callExpectedType: JetType, argument: ValueArgument): Collection<ExpectedInfo> {
val argumentIndex = call.getValueArguments().indexOf(argument) val argumentIndex = call.getValueArguments().indexOf(argument)
assert(argumentIndex >= 0) { assert(argumentIndex >= 0) {
"Could not find argument '$argument' among arguments of call: $call" "Could not find argument '$argument' among arguments of call: $call"
@@ -236,7 +236,7 @@ class ExpectedInfos(
override fun getFunctionLiteralArguments() = emptyList<FunctionLiteralArgument>() override fun getFunctionLiteralArguments() = emptyList<FunctionLiteralArgument>()
override fun getValueArgumentList() = null override fun getValueArgumentList() = null
} }
val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, call.calleeExpression] ?: return null //TODO: discuss it val resolutionScope = bindingContext[BindingContext.RESOLUTION_SCOPE, call.calleeExpression] ?: return emptyList() //TODO: discuss it
val dataFlowInfo = bindingContext.getDataFlowInfo(call.calleeExpression) val dataFlowInfo = bindingContext.getDataFlowInfo(call.calleeExpression)
val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for completion") val bindingTrace = DelegatingBindingTrace(bindingContext, "Temporary trace for completion")
@@ -371,13 +371,13 @@ class ExpectedInfos(
return when (expressionWithType) { return when (expressionWithType) {
ifExpression.getCondition() -> listOf(ExpectedInfo(KotlinBuiltIns.getInstance().getBooleanType(), null, Tail.RPARENTH)) ifExpression.getCondition() -> listOf(ExpectedInfo(KotlinBuiltIns.getInstance().getBooleanType(), null, Tail.RPARENTH))
ifExpression.getThen() -> calculate(ifExpression)?.map { ExpectedInfo(it.filter, it.expectedName, Tail.ELSE) } ifExpression.getThen() -> calculate(ifExpression).map { ExpectedInfo(it.filter, it.expectedName, Tail.ELSE) }
ifExpression.getElse() -> { ifExpression.getElse() -> {
val ifExpectedInfo = calculate(ifExpression) val ifExpectedInfo = calculate(ifExpression)
val thenType = ifExpression.getThen()?.let { bindingContext.getType(it) } val thenType = ifExpression.getThen()?.let { bindingContext.getType(it) }
if (thenType != null && !thenType.isError()) if (thenType != null && !thenType.isError())
ifExpectedInfo?.filter { it.matchingSubstitutor(thenType) != null } ifExpectedInfo.filter { it.matchingSubstitutor(thenType) != null }
else else
ifExpectedInfo ifExpectedInfo
} }
@@ -395,7 +395,7 @@ class ExpectedInfos(
val leftType = bindingContext.getType(leftExpression) val leftType = bindingContext.getType(leftExpression)
val leftTypeNotNullable = leftType?.makeNotNullable() val leftTypeNotNullable = leftType?.makeNotNullable()
val expectedInfos = calculate(binaryExpression) val expectedInfos = calculate(binaryExpression)
if (expectedInfos != null) { if (expectedInfos.isNotEmpty()) {
return if (leftTypeNotNullable != null) return if (leftTypeNotNullable != null)
expectedInfos.filter { it.matchingSubstitutor(leftTypeNotNullable) != null } expectedInfos.filter { it.matchingSubstitutor(leftTypeNotNullable) != null }
else else
@@ -417,16 +417,16 @@ class ExpectedInfos(
if (functionLiteral != null) { if (functionLiteral != null) {
val literalExpression = functionLiteral.parent as JetFunctionLiteralExpression val literalExpression = functionLiteral.parent as JetFunctionLiteralExpression
return calculate(literalExpression) return calculate(literalExpression)
?.map { it.fuzzyType } .map { it.fuzzyType }
?.filterNotNull() .filterNotNull()
?.filter { KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(it.type) } .filter { KotlinBuiltIns.isExactFunctionOrExtensionFunctionType(it.type) }
?.map { .map {
val returnType = KotlinBuiltIns.getReturnTypeFromFunctionType(it.type) val returnType = KotlinBuiltIns.getReturnTypeFromFunctionType(it.type)
ExpectedInfo(FuzzyType(returnType, it.freeParameters), null, Tail.RBRACE) ExpectedInfo(FuzzyType(returnType, it.freeParameters), null, Tail.RBRACE)
} }
} }
else { else {
return calculate(block)?.map { ExpectedInfo(it.filter, it.expectedName, null) } return calculate(block).map { ExpectedInfo(it.filter, it.expectedName, null) }
} }
} }
@@ -217,7 +217,7 @@ class SmartCompletionInBasicWeigher(private val smartCompletion: SmartCompletion
if ((o as? DeclarationLookupObject)?.descriptor in descriptorsToSkip) return DESCRIPTOR_TO_SKIP_WEIGHT if ((o as? DeclarationLookupObject)?.descriptor in descriptorsToSkip) return DESCRIPTOR_TO_SKIP_WEIGHT
if (expectedInfos == null || expectedInfos.isEmpty()) return NO_MATCH_WEIGHT if (expectedInfos.isEmpty()) return NO_MATCH_WEIGHT
val smartCastCalculator = smartCompletion.smartCastCalculator val smartCastCalculator = smartCompletion.smartCastCalculator
@@ -79,7 +79,7 @@ private fun needExplicitParameterTypes(context: InsertionContext, placeholderRan
val resolutionFacade = file.getResolutionFacade() val resolutionFacade = file.getResolutionFacade()
val bindingContext = resolutionFacade.analyze(expression, BodyResolveMode.PARTIAL) val bindingContext = resolutionFacade.analyze(expression, BodyResolveMode.PARTIAL)
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, resolutionFacade.findModuleDescriptor(file), useHeuristicSignatures = false) val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, resolutionFacade.findModuleDescriptor(file), useHeuristicSignatures = false)
.calculate(expression) ?: return false .calculate(expression)
val functionTypes = expectedInfos val functionTypes = expectedInfos
.map { it.fuzzyType?.type } .map { it.fuzzyType?.type }
.filterNotNull() .filterNotNull()
@@ -63,7 +63,7 @@ class SmartCompletion(
private val receiver = if (expression is JetSimpleNameExpression) expression.getReceiverExpression() else null private val receiver = if (expression is JetSimpleNameExpression) expression.getReceiverExpression() else null
private val expressionWithType = receiver?.parent as? JetExpression ?: expression private val expressionWithType = receiver?.parent as? JetExpression ?: expression
public val expectedInfos: Collection<ExpectedInfo>? = calcExpectedInfos(expressionWithType) public val expectedInfos: Collection<ExpectedInfo> = calcExpectedInfos(expressionWithType)
public val smartCastCalculator: SmartCastCalculator = SmartCastCalculator(bindingContext, moduleDescriptor, expression) public val smartCastCalculator: SmartCastCalculator = SmartCastCalculator(bindingContext, moduleDescriptor, expression)
@@ -113,7 +113,7 @@ class SmartCompletion(
private fun executeInternal(): Result? { private fun executeInternal(): Result? {
val (additionalItems, inheritanceSearcher) = additionalItems() val (additionalItems, inheritanceSearcher) = additionalItems()
if (expectedInfos == null || expectedInfos.isEmpty()) { if (expectedInfos.isEmpty()) {
return Result(null, additionalItems, inheritanceSearcher) return Result(null, additionalItems, inheritanceSearcher)
} }
@@ -147,14 +147,14 @@ class SmartCompletion(
public fun additionalItems(): Pair<Collection<LookupElement>, InheritanceItemsSearcher?> { public fun additionalItems(): Pair<Collection<LookupElement>, InheritanceItemsSearcher?> {
val asTypePositionItems = buildForAsTypePosition() val asTypePositionItems = buildForAsTypePosition()
if (asTypePositionItems != null) { if (asTypePositionItems != null) {
assert(expectedInfos == null) assert(expectedInfos.isEmpty())
return Pair(asTypePositionItems, null) return Pair(asTypePositionItems, null)
} }
val items = ArrayList<LookupElement>() val items = ArrayList<LookupElement>()
val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>() val inheritanceSearchers = ArrayList<InheritanceItemsSearcher>()
if (expectedInfos != null && expectedInfos.isNotEmpty() && receiver == null) { if (expectedInfos.isNotEmpty() && receiver == null) {
TypeInstantiationItems(resolutionFacade, moduleDescriptor, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion) TypeInstantiationItems(resolutionFacade, moduleDescriptor, bindingContext, visibilityFilter, toFromOriginalFileMapper, inheritorSearchScope, lookupElementFactory, forBasicCompletion)
.addTo(items, inheritanceSearchers, expectedInfos) .addTo(items, inheritanceSearchers, expectedInfos)
@@ -198,11 +198,11 @@ class SmartCompletion(
} }
} }
private fun calcExpectedInfos(expression: JetExpression): Collection<ExpectedInfo>? { private fun calcExpectedInfos(expression: JetExpression): Collection<ExpectedInfo> {
if (forBasicCompletion) { if (forBasicCompletion) {
return ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor, useOuterCallsExpectedTypeCount = 0) return ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor, useOuterCallsExpectedTypeCount = 0)
.calculate(expression) .calculate(expression)
?.map { it.copy(tail = null) } .map { it.copy(tail = null) }
} }
// if our expression is initializer of implicitly typed variable - take type of variable from original file (+ the same for function) // if our expression is initializer of implicitly typed variable - take type of variable from original file (+ the same for function)
@@ -222,7 +222,7 @@ class SmartCompletion(
var count = 0 var count = 0
while (true) { while (true) {
val infos = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor, useOuterCallsExpectedTypeCount = count) val infos = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor, useOuterCallsExpectedTypeCount = count)
.calculate(expression) ?: return null .calculate(expression)
if (count == 2 /* use two outer calls maximum */ || infos.none { it.fuzzyType?.isAlmostEverything() ?: false }) return infos if (count == 2 /* use two outer calls maximum */ || infos.none { it.fuzzyType?.isAlmostEverything() ?: false }) return infos
count++ count++
} }
@@ -342,7 +342,7 @@ class SmartCompletion(
?: return null ?: return null
val elementType = binaryExpression.getOperationReference().getReferencedNameElementType() val elementType = binaryExpression.getOperationReference().getReferencedNameElementType()
if (elementType != JetTokens.AS_KEYWORD && elementType != JetTokens.AS_SAFE) return null if (elementType != JetTokens.AS_KEYWORD && elementType != JetTokens.AS_SAFE) return null
val expectedInfos = calcExpectedInfos(binaryExpression) ?: return null val expectedInfos = calcExpectedInfos(binaryExpression)
val expectedInfosGrouped: Map<JetType?, List<ExpectedInfo>> = expectedInfos.groupBy { it.fuzzyType?.type?.makeNotNullable() } val expectedInfosGrouped: Map<JetType?, List<ExpectedInfo>> = expectedInfos.groupBy { it.fuzzyType?.type?.makeNotNullable() }
@@ -106,9 +106,7 @@ class SmartCompletionSession(configuration: CompletionSessionConfiguration, para
val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor) val expectedInfos = ExpectedInfos(bindingContext, resolutionFacade, moduleDescriptor)
.calculateForArgument(dummyCall, dummyArgument) .calculateForArgument(dummyCall, dummyArgument)
if (expectedInfos != null) { collector.addElements(LambdaItems.collect(expectedInfos))
collector.addElements(LambdaItems.collect(expectedInfos))
}
} }
} }
} }