Inline refactoring: should add explicit type argument for parameters
#KT-17402 Fixed
This commit is contained in:
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
||||
import org.jetbrains.kotlin.idea.core.*
|
||||
import org.jetbrains.kotlin.idea.inspections.RedundantUnitExpressionInspection
|
||||
import org.jetbrains.kotlin.idea.intentions.InsertExplicitTypeArgumentsIntention
|
||||
import org.jetbrains.kotlin.idea.intentions.RemoveExplicitTypeArgumentsIntention
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class CodeInliner<TCallElement : KtElement>(
|
||||
private val nameExpression: KtSimpleNameExpression,
|
||||
@@ -175,7 +177,13 @@ class CodeInliner<TCallElement : KtElement>(
|
||||
for (parameter in descriptor.valueParameters.asReversed()) {
|
||||
val argument = argumentForParameter(parameter, descriptor) ?: continue
|
||||
|
||||
argument.expression.put(PARAMETER_VALUE_KEY, parameter)
|
||||
val expression = argument.expression.apply {
|
||||
if (this is KtCallElement) {
|
||||
insertExplicitTypeArgument()
|
||||
}
|
||||
|
||||
put(PARAMETER_VALUE_KEY, parameter)
|
||||
}
|
||||
|
||||
val parameterName = parameter.name
|
||||
val usages = codeToInline.collectDescendantsOfType<KtExpression> {
|
||||
@@ -191,19 +199,30 @@ class CodeInliner<TCallElement : KtElement>(
|
||||
usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
||||
}
|
||||
|
||||
codeToInline.replaceExpression(it, argument.expression.copied())
|
||||
codeToInline.replaceExpression(it, expression.copied())
|
||||
}
|
||||
|
||||
//TODO: sometimes we need to add explicit type arguments here because we don't have expected type in the new context
|
||||
|
||||
if (argument.expression.shouldKeepValue(usageCount = usages.size)) {
|
||||
introduceValuesForParameters.add(IntroduceValueForParameter(parameter, argument.expression, argument.expressionType))
|
||||
if (expression.shouldKeepValue(usageCount = usages.size)) {
|
||||
introduceValuesForParameters.add(IntroduceValueForParameter(parameter, expression, argument.expressionType))
|
||||
}
|
||||
}
|
||||
|
||||
return introduceValuesForParameters
|
||||
}
|
||||
|
||||
private fun KtCallElement.insertExplicitTypeArgument() {
|
||||
if (InsertExplicitTypeArgumentsIntention.isApplicableTo(this, bindingContext)) {
|
||||
InsertExplicitTypeArgumentsIntention.createTypeArguments(this, bindingContext)?.let { typeArgumentList ->
|
||||
clear(USER_CODE_KEY)
|
||||
for (child in children) {
|
||||
child.safeAs<KtElement>()?.mark(USER_CODE_KEY)
|
||||
}
|
||||
|
||||
addAfter(typeArgumentList, calleeExpression)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private data class IntroduceValueForParameter(
|
||||
val parameter: ValueParameterDescriptor,
|
||||
val value: KtExpression,
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ fun oldFun(p: List<String>) {
|
||||
fun newFun(p1: List<String>, p2: List<String>){}
|
||||
|
||||
fun foo() {
|
||||
val p: List<String> = bar()
|
||||
val p = bar<String>()
|
||||
<caret>newFun(p, p)
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
interface SomeFace
|
||||
interface GeneOut<out T> {}
|
||||
object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
fun downReturn<caret>(): GeneOut<SomeFace> = downUnder()
|
||||
fun callDown() {
|
||||
val v1 = downReturn()
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
interface SomeFace
|
||||
interface GeneOut<out T> {}
|
||||
object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
fun callDown() {
|
||||
val v1 = downUnder<SomeFace>()
|
||||
}
|
||||
-1
@@ -5,6 +5,5 @@ fun <T> downUnder(): GeneOut<T> = Empty
|
||||
fun downParameter(p: GeneOut<SomeFace>) = p
|
||||
|
||||
fun callDown() {
|
||||
// BUG: KT-17402
|
||||
val v2 = <caret>downParameter(downUnder())
|
||||
}
|
||||
Vendored
+1
-2
@@ -4,6 +4,5 @@ object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
|
||||
fun callDown() {
|
||||
// BUG: KT-17402
|
||||
val v2 = downUnder()
|
||||
val v2 = downUnder<SomeFace>()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package test.pack.one
|
||||
|
||||
interface SomeFace
|
||||
interface GeneOut<out T> {}
|
||||
object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
fun downParameter<caret>(p: GeneOut<SomeFace>): GeneOut<SomeFace> {
|
||||
p
|
||||
return p
|
||||
}
|
||||
fun callDown() {
|
||||
val v2 = downParameter(downUnder())
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
package test.pack.one
|
||||
|
||||
interface SomeFace
|
||||
interface GeneOut<out T> {}
|
||||
object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
fun callDown() {
|
||||
val p = downUnder<SomeFace>()
|
||||
p
|
||||
val v2 = p
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
package test.pack.one
|
||||
|
||||
interface SomeFace
|
||||
interface GeneOut<out T> {}
|
||||
object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
fun downParameter(p: GeneOut<SomeFace>): GeneOut<SomeFace> = p
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
package test.pack.one
|
||||
|
||||
interface SomeFace
|
||||
interface GeneOut<out T> {}
|
||||
object Empty : GeneOut<Nothing>
|
||||
fun <T> downUnder(): GeneOut<T> = Empty
|
||||
@@ -0,0 +1,8 @@
|
||||
package adadawwq32q
|
||||
|
||||
import test.pack.one.downParameter
|
||||
import test.pack.one.downUnder
|
||||
|
||||
fun callDown() {
|
||||
val result = downParameter<caret>(downUnder())
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package adadawwq32q
|
||||
|
||||
import test.pack.one.SomeFace
|
||||
import test.pack.one.downUnder
|
||||
|
||||
fun callDown() {
|
||||
val result = downUnder<SomeFace>()
|
||||
}
|
||||
+1
-1
@@ -3,4 +3,4 @@ fun g() {
|
||||
if (it.isEmpty()) return@any false
|
||||
it.length < 10
|
||||
})
|
||||
}
|
||||
}
|
||||
+15
@@ -237,6 +237,11 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
||||
runTest("idea/testData/refactoring/inline/function/expressionBody/FunctionalType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericTypeArgument.kt")
|
||||
public void testGenericTypeArgument() throws Exception {
|
||||
runTest("idea/testData/refactoring/inline/function/expressionBody/GenericTypeArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("Lambda.kt")
|
||||
public void testLambda() throws Exception {
|
||||
runTest("idea/testData/refactoring/inline/function/expressionBody/Lambda.kt");
|
||||
@@ -448,6 +453,16 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
||||
runTest("idea/testData/refactoring/inline/function/returnAtEnd/DefaultParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericTypeArgument.kt")
|
||||
public void testGenericTypeArgument() throws Exception {
|
||||
runTest("idea/testData/refactoring/inline/function/returnAtEnd/GenericTypeArgument.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("GenericTypeArgument2.kt")
|
||||
public void testGenericTypeArgument2() throws Exception {
|
||||
runTest("idea/testData/refactoring/inline/function/returnAtEnd/GenericTypeArgument2.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("InnerFunction.kt")
|
||||
public void testInnerFunction() throws Exception {
|
||||
runTest("idea/testData/refactoring/inline/function/returnAtEnd/InnerFunction.kt");
|
||||
|
||||
Reference in New Issue
Block a user