Pass data flow info from '::' expressions, fix expected type

This commit is contained in:
Alexander Udalov
2016-06-06 14:31:23 +03:00
parent d8db769823
commit 526a64dc36
6 changed files with 55 additions and 4 deletions
@@ -38,16 +38,20 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsUtil
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.KotlinTypeImpl
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
import javax.inject.Inject
sealed class DoubleColonLHS(val type: KotlinType) {
class Expression(val typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!)
class Expression(typeInfo: KotlinTypeInfo) : DoubleColonLHS(typeInfo.type!!) {
val dataFlowInfo: DataFlowInfo = typeInfo.dataFlowInfo
}
class Type(type: KotlinType, val possiblyBareType: PossiblyBareType) : DoubleColonLHS(type)
}
@@ -82,7 +86,9 @@ class DoubleColonExpressionResolver(
val type = result?.type
if (type != null && !type.isError) {
checkClassLiteral(c, expression, result!!)
return dataFlowAnalyzer.createCheckedTypeInfo(reflectionTypes.getKClassType(Annotations.EMPTY, type), c, expression)
val kClassType = reflectionTypes.getKClassType(Annotations.EMPTY, type)
val dataFlowInfo = (result as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
return dataFlowAnalyzer.checkType(createTypeInfo(kClassType, dataFlowInfo), expression, c)
}
}
@@ -151,7 +157,7 @@ class DoubleColonExpressionResolver(
if (shouldTryResolveLHSAsExpression(doubleColonExpression)) {
val traceForExpr = TemporaryTraceAndCache.create(c, "resolve '::' LHS as expression", expression)
val contextForExpr = c.replaceTraceAndCache(traceForExpr)
val contextForExpr = c.replaceTraceAndCache(traceForExpr).replaceExpectedType(NO_EXPECTED_TYPE)
val typeInfo = expressionTypingServices.getTypeInfo(expression, contextForExpr)
val type = typeInfo.type
@@ -255,7 +261,8 @@ class DoubleColonExpressionResolver(
val (lhs, resolutionResults) = resolveCallableReference(expression, c, ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS)
val result = getCallableReferenceType(expression, lhs, resolutionResults, c)
return dataFlowAnalyzer.createCheckedTypeInfo(result, c, expression)
val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
return dataFlowAnalyzer.checkType(createTypeInfo(result, dataFlowInfo), expression, c)
}
private fun getCallableReferenceType(
@@ -0,0 +1,13 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.reflect.KClass
fun f1(x: String?): String {
x!!::hashCode
return <!DEBUG_INFO_SMARTCAST!>x<!>
}
fun f2(y: String?): String {
val f: KClass<*> = (y ?: return "")::class
return <!DEBUG_INFO_SMARTCAST!>y<!>
}
@@ -0,0 +1,4 @@
package
public fun f1(/*0*/ x: kotlin.String?): kotlin.String
public fun f2(/*0*/ y: kotlin.String?): kotlin.String
@@ -0,0 +1,12 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.reflect.KClass
fun test(s: String) {
val f: () -> Int = s::hashCode
val g: () -> String = s::toString
val h: (Any?) -> Boolean = s::equals
val k: KClass<String> = s::class
val l: KClass<*> = s::class
}
@@ -0,0 +1,3 @@
package
public fun test(/*0*/ s: kotlin.String): kotlin.Unit
@@ -1739,6 +1739,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("dataFlow.kt")
public void testDataFlow() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/dataFlow.kt");
doTest(fileName);
}
@TestMetadata("expectedType.kt")
public void testExpectedType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/expectedType.kt");
doTest(fileName);
}
@TestMetadata("functionCallWithoutArguments.kt")
public void testFunctionCallWithoutArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/functionCallWithoutArguments.kt");