diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt index bd118395895..1f05b7ea316 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/createFromUsage/callableBuilder/typeUtils.kt @@ -21,11 +21,9 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.scopes.JetScope -import java.util.LinkedHashSet import org.jetbrains.kotlin.resolve.BindingContext import com.intellij.refactoring.psi.SearchUtils import org.jetbrains.kotlin.idea.references.JetSimpleNameReference -import java.util.HashSet import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.checker.JetTypeChecker @@ -43,6 +41,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getNonStrictParentOfType import org.jetbrains.kotlin.resolve.descriptorUtil.resolveTopLevelClass import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.calls.callUtil.* +import org.jetbrains.kotlin.resolve.calls.smartcasts.* +import java.util.* private fun JetType.contains(inner: JetType): Boolean { return JetTypeChecker.DEFAULT.equalTypes(this, inner) || getArguments().any { inner in it.getType() } @@ -107,7 +107,9 @@ fun JetExpression.guessTypes( // if we know the actual type of the expression val theType1 = context[BindingContext.EXPRESSION_TYPE, this] if (theType1 != null) { - return array(theType1) + val dataFlowInfo = context[BindingContext.EXPRESSION_DATA_FLOW_INFO, this] + val possibleTypes = dataFlowInfo?.getPossibleTypes(DataFlowValueFactory.createDataFlowValue(this, theType1, context)) + return if (possibleTypes != null && possibleTypes.isNotEmpty()) possibleTypes.copyToArray() else array(theType1) } // expression has an expected type diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/afterSmartCastWithIs.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/afterSmartCastWithIs.kt new file mode 100644 index 00000000000..d5e7e25aa5b --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/afterSmartCastWithIs.kt @@ -0,0 +1,9 @@ +// "Create function 'foo'" "true" + +fun test(o: Any) { + if (o is String) foo(o) +} + +fun foo(o: String) { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/afterSmartCastWithNullCheck.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/afterSmartCastWithNullCheck.kt new file mode 100644 index 00000000000..1c16dad0e87 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/afterSmartCastWithNullCheck.kt @@ -0,0 +1,10 @@ +// "Create function 'foo'" "true" + +fun test(s: String?) { + if (s == null) return + foo(s) +} + +fun foo(s: String) { + throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates. +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithIs.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithIs.kt new file mode 100644 index 00000000000..c3f365b926f --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithIs.kt @@ -0,0 +1,5 @@ +// "Create function 'foo'" "true" + +fun test(o: Any) { + if (o is String) foo(o) +} diff --git a/idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithNullCheck.kt b/idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithNullCheck.kt new file mode 100644 index 00000000000..b04274d3e39 --- /dev/null +++ b/idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithNullCheck.kt @@ -0,0 +1,6 @@ +// "Create function 'foo'" "true" + +fun test(s: String?) { + if (s == null) return + foo(s) +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index a4413c7beee..f476df52092 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -1794,6 +1794,18 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest(fileName); } + @TestMetadata("beforeSmartCastWithIs.kt") + public void testSmartCastWithIs() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithIs.kt"); + doTest(fileName); + } + + @TestMetadata("beforeSmartCastWithNullCheck.kt") + public void testSmartCastWithNullCheck() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeSmartCastWithNullCheck.kt"); + doTest(fileName); + } + @TestMetadata("beforeThisInClass.kt") public void testThisInClass() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeThisInClass.kt");