Inline: more accurate handling of type arguments

Partial revert of b8cc7c2ca6
Soften requirements in remove type arguments intention in this mode
So #KT-17622 Fixed
Related to KT-17623
This commit is contained in:
Mikhail Glukhikh
2017-05-26 17:53:15 +03:00
parent 38d6c597a3
commit 9c15db93d9
4 changed files with 39 additions and 10 deletions
@@ -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<FqName> = 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<Pair<KtCallExpression, KtTypeArgumentList>>()
codeToInline.forEachDescendantOfType<KtCallExpression> {
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<Pair<KtExpression, KtExpression>>()
@@ -0,0 +1,6 @@
fun foo(f: List<Int>) {}
fun f() {
val v : List<Int> = ArrayList(listOf())
foo(<caret>v)
}
@@ -0,0 +1,5 @@
fun foo(f: List<Int>) {}
fun f() {
foo(ArrayList<Int>(listOf()))
}
@@ -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");