Extraction Engine: Respect smart casts applied to "this" references

#KT-7447
This commit is contained in:
Alexey Sedunov
2015-04-14 18:05:46 +03:00
parent aa0930ea60
commit d036edb5c6
6 changed files with 105 additions and 5 deletions
@@ -69,8 +69,10 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
import org.jetbrains.kotlin.resolve.calls.CallTransformer
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.scopes.JetScopeUtils
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ThisReceiver
import org.jetbrains.kotlin.types.*
@@ -642,13 +644,27 @@ private fun ExtractionData.inferParametersInfo(
val extractParameter = extractThis || extractLocalVar
if (extractParameter) {
val parameterType = when {
receiverToExtract.exists() -> receiverToExtract.getType()
else -> bindingContext[BindingContext.SMARTCAST, originalRef]
?: bindingContext[BindingContext.EXPRESSION_TYPE, originalRef]
?: DEFAULT_PARAMETER_TYPE
val parameterExpression = when {
receiverToExtract is ExpressionReceiver -> receiverToExtract.getExpression()
receiverToExtract.exists() -> null
else -> (originalRef.getParent() as? JetThisExpression) ?: originalRef
}
val parameterType = when {
parameterExpression != null -> bindingContext[BindingContext.SMARTCAST, parameterExpression]
?: bindingContext[BindingContext.EXPRESSION_TYPE, parameterExpression]
?: if (receiverToExtract.exists()) receiverToExtract.getType() else null
receiverToExtract is ThisReceiver -> {
val calleeExpression = resolvedCall!!.getCall().getCalleeExpression()
bindingContext[BindingContext.EXPRESSION_DATA_FLOW_INFO, calleeExpression]?.let { dataFlowInfo ->
val possibleTypes = dataFlowInfo.getPossibleTypes(DataFlowValueFactory.createDataFlowValue(receiverToExtract))
CommonSupertypes.commonSupertype(possibleTypes)
} ?: receiverToExtract.getType()
}
receiverToExtract.exists() -> receiverToExtract.getType()
else -> null
} ?: DEFAULT_PARAMETER_TYPE
val parameter = extractedDescriptorToParameter.getOrPut(descriptorToExtract) {
val argumentText =
if (hasThisReceiver && extractThis) {
@@ -0,0 +1,17 @@
// SUGGESTED_NAMES: i, getB
// PARAM_DESCRIPTOR: internal fun A.ext(): kotlin.Unit defined in root package
// PARAM_TYPES: B
fun main(args: Array<String>) {
val a: A = B()
a.ext()
}
fun A.ext() {
if (this !is B) return
val b = <selection>this.foo()</selection>
}
open class A
class B: A() {
fun foo() = 1
}
@@ -0,0 +1,19 @@
// SUGGESTED_NAMES: i, getB
// PARAM_DESCRIPTOR: internal fun A.ext(): kotlin.Unit defined in root package
// PARAM_TYPES: B
fun main(args: Array<String>) {
val a: A = B()
a.ext()
}
fun A.ext() {
if (this !is B) return
val b = i()
}
private fun B.i() = this.foo()
open class A
class B: A() {
fun foo() = 1
}
@@ -0,0 +1,17 @@
// SUGGESTED_NAMES: i, getB
// PARAM_DESCRIPTOR: internal fun A.ext(): kotlin.Unit defined in root package
// PARAM_TYPES: B
fun main(args: Array<String>) {
val a: A = B()
a.ext()
}
fun A.ext() {
if (this !is B) return
val b = <selection>foo()</selection>
}
open class A
class B: A() {
fun foo() = 1
}
@@ -0,0 +1,19 @@
// SUGGESTED_NAMES: i, getB
// PARAM_DESCRIPTOR: internal fun A.ext(): kotlin.Unit defined in root package
// PARAM_TYPES: B
fun main(args: Array<String>) {
val a: A = B()
a.ext()
}
fun A.ext() {
if (this !is B) return
val b = i()
}
private fun B.i() = foo()
open class A
class B: A() {
fun foo() = 1
}
@@ -1643,6 +1643,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
doExtractFunctionTest(fileName);
}
@TestMetadata("explicitThisWithSmartCast.kt")
public void testExplicitThisWithSmartCast() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/extractThis/explicitThisWithSmartCast.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("implicitAndExplicitLabeledThisInMember.kt")
public void testImplicitAndExplicitLabeledThisInMember() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/extractThis/implicitAndExplicitLabeledThisInMember.kt");
@@ -1667,6 +1673,12 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest {
doExtractFunctionTest(fileName);
}
@TestMetadata("implicitThisWithSmartCast.kt")
public void testImplicitThisWithSmartCast() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/extractThis/implicitThisWithSmartCast.kt");
doExtractFunctionTest(fileName);
}
@TestMetadata("qualifiedThisAsArgument.kt")
public void testQualifiedThisAsArgument() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/extractFunction/parameters/extractThis/qualifiedThisAsArgument.kt");