diff --git a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java index c03cb93bd6de..8fa3337cc412 100644 --- a/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java +++ b/plugins/kotlin/idea/tests/test/org/jetbrains/kotlin/idea/refactoring/introduce/ExtractionTestGenerated.java @@ -2506,6 +2506,11 @@ public abstract class ExtractionTestGenerated extends AbstractExtractionTest { runTest("testData/refactoring/extractFunction/parameters/misc/smartCastInside1.kt"); } + @TestMetadata("smartCastInsideUnqualified.kt") + public void testSmartCastInsideUnqualified() throws Exception { + runTest("testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt"); + } + @TestMetadata("thisInObject.kt") public void testThisInObject() throws Exception { runTest("testData/refactoring/extractFunction/parameters/misc/thisInObject.kt"); diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt new file mode 100644 index 000000000000..ae3e66ef06ff --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt @@ -0,0 +1,7 @@ + +class A(val foo: Set?) { + fun bar(maybeFoo: String) { + if (foo != null && foo.contains(maybeFoo)) println("not null") + } +} +// IGNORE_K1 \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt.after new file mode 100644 index 000000000000..516e0e3eaa2b --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt.after @@ -0,0 +1,10 @@ +class A(val foo: Set?) { + fun bar(maybeFoo: String) { + __dummyTestFun__(maybeFoo) + } + + private fun __dummyTestFun__(maybeFoo: String) { + if (foo != null && foo.contains(maybeFoo)) println("not null") + } +} +// IGNORE_K1 \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/parametersUtil.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/parametersUtil.kt index 960bcf5deb19..181f77582f03 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/parametersUtil.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/parametersUtil.kt @@ -85,7 +85,6 @@ import org.jetbrains.kotlin.psi.psiUtil.isInsideOf import org.jetbrains.kotlin.types.Variance import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.idea.k2.refactoring.introduce.K2SemanticMatcher.isSemanticMatch -import org.jetbrains.kotlin.psi.psiUtil.getQualifiedElementSelector context(KtAnalysisSession) internal fun ExtractionData.inferParametersInfo( @@ -426,27 +425,31 @@ private fun ExtractionData.getBrokenReferencesInfo(body: KtBlockExpression): Lis val parent = newRef.parent val smartCast: KtType? + + fun calculateSmartCastType(target: KtExpression): KtType? { + return analyze(target) { + val cast = target.getSmartCastInfo()?.smartCastType + when { + cast == null -> { + smartCastPossibleRoots.add(target) + null + } + + //same qualified expressions without smartcast are present in the code fragment, + //so smart cast is done inside selection, no need to extract additional parameter + smartCastPossibleRoots.any { it.isSemanticMatch(target) } -> null + else -> cast + } + } + } + val possibleTypes: Set // Qualified property reference: a.b val qualifiedExpression = newRef.getQualifiedExpressionForSelector() if (qualifiedExpression != null) { val smartCastTarget = originalRefExpr.parent as KtExpression - smartCast = analyze(smartCastTarget) { - val cast = smartCastTarget.getSmartCastInfo()?.smartCastType - when { - cast == null -> { - smartCastPossibleRoots.add(smartCastTarget) - null - } - - //same qualified expressions without smartcast are present in the code fragment, - //so smart cast is done inside selection, no need to extract additional parameter - smartCastPossibleRoots.any { it.isSemanticMatch(smartCastTarget) } -> null - else -> cast - } - } - + smartCast = calculateSmartCastType(smartCastTarget) possibleTypes = analyze(smartCastTarget) { smartCastTarget.getExpectedType()?.let { setOf(it) } ?: emptySet() } val (isCompanionObject, bothReceivers) = analyze(smartCastTarget) { val symbol = originalRefExpr.resolveCall()?.singleCallOrNull>()?.partiallyAppliedSymbol @@ -464,7 +467,7 @@ private fun ExtractionData.getBrokenReferencesInfo(body: KtBlockExpression): Lis if (originalResolveResult.descriptor is KtProperty && parent is KtCallExpression && parent.calleeExpression == newRef && parent.getQualifiedExpressionForSelector() != null) { continue } - smartCast = analyze(originalRefExpr) { originalRefExpr.getSmartCastInfo()?.smartCastType } + smartCast = calculateSmartCastType(originalRefExpr) possibleTypes = analyze(originalRefExpr) { originalRefExpr.getExpectedType()?.let { setOf(it) } ?: emptySet() } } diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduceFunction/K2IntroduceFunctionTestGenerated.java b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduceFunction/K2IntroduceFunctionTestGenerated.java index 2e4ef4d44054..96f8c46351ab 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduceFunction/K2IntroduceFunctionTestGenerated.java +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduceFunction/K2IntroduceFunctionTestGenerated.java @@ -1664,6 +1664,11 @@ public abstract class K2IntroduceFunctionTestGenerated extends AbstractK2Introdu runTest("../../idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInside1.kt"); } + @TestMetadata("smartCastInsideUnqualified.kt") + public void testSmartCastInsideUnqualified() throws Exception { + runTest("../../idea/tests/testData/refactoring/extractFunction/parameters/misc/smartCastInsideUnqualified.kt"); + } + @TestMetadata("thisInObject.kt") public void testThisInObject() throws Exception { runTest("../../idea/tests/testData/refactoring/extractFunction/parameters/misc/thisInObject.kt");