diff --git a/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt b/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt index 306970b4b59..c715237fc08 100644 --- a/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt +++ b/idea/src/org/jetbrains/kotlin/idea/intentions/SpecifyTypeExplicitlyIntention.kt @@ -23,16 +23,15 @@ import com.intellij.psi.PsiDocumentManager import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.idea.caches.resolve.analyze -import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers -import org.jetbrains.kotlin.idea.util.ShortenReferences +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.util.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.types.ErrorUtils -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeUtils -import java.util.* +import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.types.* +import org.jetbrains.kotlin.utils.SmartSet +import org.jetbrains.kotlin.utils.addToStdlib.singletonList public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention(KtCallableDeclaration::class.java, "Specify type explicitly"), LowPriorityAction { override fun isApplicableTo(element: KtCallableDeclaration, caretOffset: Int): Boolean { @@ -65,14 +64,34 @@ public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention() else arrayListOf(exprType) - types.addAll(allSupertypes) + val newArguments = (it.arguments zip it.constructor.parameters).map { + val (arg, param) = it + when { + arg in resolvableArgs -> arg + arg.projectionKind == Variance.OUT_VARIANCE || + param.variance == Variance.OUT_VARIANCE -> TypeProjectionImpl( + arg.projectionKind, + arg.type.approximateWithResolvableType(scope, true) + ) + else -> return@mapArgs null + } + } + object: DelegatingType() { + override fun getDelegate() = it + override fun getArguments() = newArguments + } + } return object : ChooseValueExpression(types, types.first()) { override fun getLookupString(element: KotlinType) = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.renderType(element) override fun getResult(element: KotlinType) = IdeDescriptorRenderers.SOURCE_CODE.renderType(element) @@ -103,7 +122,7 @@ public class SpecifyTypeExplicitlyIntention : SelfTargetingIntention= { object {} } +} \ No newline at end of file diff --git a/idea/testData/intentions/specifyTypeExplicitly/anonymousObject.kt.after b/idea/testData/intentions/specifyTypeExplicitly/anonymousObject.kt.after new file mode 100644 index 00000000000..374168dfb5a --- /dev/null +++ b/idea/testData/intentions/specifyTypeExplicitly/anonymousObject.kt.after @@ -0,0 +1,3 @@ +class A { + private fun foo(): () -> Any = { object {} } +} \ No newline at end of file diff --git a/idea/testData/intentions/specifyTypeExplicitly/localClass.kt b/idea/testData/intentions/specifyTypeExplicitly/localClass.kt new file mode 100644 index 00000000000..a9d9ab11fef --- /dev/null +++ b/idea/testData/intentions/specifyTypeExplicitly/localClass.kt @@ -0,0 +1,6 @@ +class A { + private fun bar() = { + class Local() + Local() + } +} \ No newline at end of file diff --git a/idea/testData/intentions/specifyTypeExplicitly/localClass.kt.after b/idea/testData/intentions/specifyTypeExplicitly/localClass.kt.after new file mode 100644 index 00000000000..7bde653b217 --- /dev/null +++ b/idea/testData/intentions/specifyTypeExplicitly/localClass.kt.after @@ -0,0 +1,6 @@ +class A { + private fun bar(): () -> Any = { + class Local() + Local() + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java index ab9c40aee82..fbcf5e0f511 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/intentions/IntentionTestGenerated.java @@ -7906,6 +7906,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/specifyTypeExplicitly"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); } + @TestMetadata("anonymousObject.kt") + public void testAnonymousObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/anonymousObject.kt"); + doTest(fileName); + } + @TestMetadata("badCaretPosition.kt") public void testBadCaretPosition() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/badCaretPosition.kt"); @@ -7942,6 +7948,12 @@ public class IntentionTestGenerated extends AbstractIntentionTest { doTest(fileName); } + @TestMetadata("localClass.kt") + public void testLocalClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/localClass.kt"); + doTest(fileName); + } + @TestMetadata("loopParameter.kt") public void testLoopParameter() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/intentions/specifyTypeExplicitly/loopParameter.kt");