From 9c15db93d95f5c56c971557a3ac3f412ffa880b5 Mon Sep 17 00:00:00 2001 From: Mikhail Glukhikh Date: Fri, 26 May 2017 17:53:15 +0300 Subject: [PATCH] Inline: more accurate handling of type arguments Partial revert of b8cc7c2ca6cb2e7dad88e3014b4339843fb59907 Soften requirements in remove type arguments intention in this mode So #KT-17622 Fixed Related to KT-17623 --- .../idea/codeInliner/CodeToInlineBuilder.kt | 32 +++++++++++++------ .../DeeperNestedCall2.kt | 6 ++++ .../DeeperNestedCall2.kt.after | 5 +++ .../inline/InlineTestGenerated.java | 6 ++++ 4 files changed, 39 insertions(+), 10 deletions(-) create mode 100644 idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt create mode 100644 idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt.after diff --git a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt index 549bf7d2f31..ab2f7bd7051 100644 --- a/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt +++ b/idea/src/org/jetbrains/kotlin/idea/codeInliner/CodeToInlineBuilder.kt @@ -25,8 +25,6 @@ import org.jetbrains.kotlin.idea.core.asExpression import org.jetbrains.kotlin.idea.imports.importableFqName import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention import org.jetbrains.kotlin.idea.intentions.SpecifyExplicitLambdaSignatureIntention -import org.jetbrains.kotlin.idea.refactoring.addTypeArgumentsIfNeeded -import org.jetbrains.kotlin.idea.refactoring.getQualifiedTypeArgumentList import org.jetbrains.kotlin.idea.references.canBeResolvedViaImport import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.idea.resolve.ResolutionFacade @@ -59,12 +57,15 @@ class CodeToInlineBuilder( analyze: () -> BindingContext, importFqNames: Collection = emptyList() ): CodeToInline { - val bindingContext = analyze() + var bindingContext = analyze() val codeToInline = MutableCodeToInline(mainExpression, statementsBefore.toMutableList(), importFqNames.toMutableSet()) + bindingContext = insertExplicitTypeArguments(codeToInline, bindingContext, analyze) + insertExplicitReceivers(codeToInline, bindingContext) + // NB: we must check in codeToInline, otherwise we get AE from addPostInsertionAction if (mainExpression != null && mainExpression in codeToInline) { val functionLiteralExpression = mainExpression.unpackFunctionLiteral(true) if (functionLiteralExpression != null) { @@ -75,15 +76,8 @@ class CodeToInlineBuilder( } } } - val typeArgumentsForCall = getQualifiedTypeArgumentList(mainExpression, bindingContext) - if (typeArgumentsForCall != null) { - codeToInline.addPostInsertionAction(mainExpression) { inlinedExpression -> - addTypeArgumentsIfNeeded(inlinedExpression, typeArgumentsForCall) - } - } } - return codeToInline.toNonMutable() } @@ -124,6 +118,24 @@ class CodeToInlineBuilder( } } + private fun insertExplicitTypeArguments(codeToInline: MutableCodeToInline, bindingContext: BindingContext, analyze: () -> BindingContext): BindingContext { + val typeArgsToAdd = ArrayList>() + codeToInline.forEachDescendantOfType { + if (InsertExplicitTypeArgumentsIntention.isApplicableTo(it, bindingContext)) { + typeArgsToAdd.add(it to InsertExplicitTypeArgumentsIntention.createTypeArguments(it, bindingContext)!!) + } + } + + if (typeArgsToAdd.isEmpty()) return bindingContext + + for ((callExpr, typeArgs) in typeArgsToAdd) { + callExpr.addAfter(typeArgs, callExpr.calleeExpression) + } + + // reanalyze expression - new usages of type parameters may be added + return analyze() + } + private fun insertExplicitReceivers(codeToInline: MutableCodeToInline, bindingContext: BindingContext) { val receiversToAdd = ArrayList>() diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt new file mode 100644 index 00000000000..6275df9394c --- /dev/null +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt @@ -0,0 +1,6 @@ +fun foo(f: List) {} + +fun f() { + val v : List = ArrayList(listOf()) + foo(v) +} diff --git a/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt.after b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt.after new file mode 100644 index 00000000000..72af716aa1c --- /dev/null +++ b/idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt.after @@ -0,0 +1,5 @@ +fun foo(f: List) {} + +fun f() { + foo(ArrayList(listOf())) +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java index dd982101c63..a069c20fda5 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java @@ -931,6 +931,12 @@ public class InlineTestGenerated extends AbstractInlineTest { doTest(fileName); } + @TestMetadata("DeeperNestedCall2.kt") + public void testDeeperNestedCall2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/DeeperNestedCall2.kt"); + doTest(fileName); + } + @TestMetadata("EnoughDontExplicate.kt") public void testEnoughDontExplicate() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/inline/inlineVariableOrProperty/explicateTypeArgument/EnoughDontExplicate.kt");