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.caches.resolve.resolveToCall
|
||||||
import org.jetbrains.kotlin.idea.core.*
|
import org.jetbrains.kotlin.idea.core.*
|
||||||
import org.jetbrains.kotlin.idea.inspections.RedundantUnitExpressionInspection
|
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.intentions.RemoveExplicitTypeArgumentsIntention
|
||||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
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.KotlinType
|
||||||
import org.jetbrains.kotlin.types.isError
|
import org.jetbrains.kotlin.types.isError
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class CodeInliner<TCallElement : KtElement>(
|
class CodeInliner<TCallElement : KtElement>(
|
||||||
private val nameExpression: KtSimpleNameExpression,
|
private val nameExpression: KtSimpleNameExpression,
|
||||||
@@ -175,7 +177,13 @@ class CodeInliner<TCallElement : KtElement>(
|
|||||||
for (parameter in descriptor.valueParameters.asReversed()) {
|
for (parameter in descriptor.valueParameters.asReversed()) {
|
||||||
val argument = argumentForParameter(parameter, descriptor) ?: continue
|
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 parameterName = parameter.name
|
||||||
val usages = codeToInline.collectDescendantsOfType<KtExpression> {
|
val usages = codeToInline.collectDescendantsOfType<KtExpression> {
|
||||||
@@ -191,19 +199,30 @@ class CodeInliner<TCallElement : KtElement>(
|
|||||||
usageArgument?.mark(DEFAULT_PARAMETER_VALUE_KEY)
|
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 (expression.shouldKeepValue(usageCount = usages.size)) {
|
||||||
|
introduceValuesForParameters.add(IntroduceValueForParameter(parameter, expression, argument.expressionType))
|
||||||
if (argument.expression.shouldKeepValue(usageCount = usages.size)) {
|
|
||||||
introduceValuesForParameters.add(IntroduceValueForParameter(parameter, argument.expression, argument.expressionType))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return introduceValuesForParameters
|
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(
|
private data class IntroduceValueForParameter(
|
||||||
val parameter: ValueParameterDescriptor,
|
val parameter: ValueParameterDescriptor,
|
||||||
val value: KtExpression,
|
val value: KtExpression,
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@ fun oldFun(p: List<String>) {
|
|||||||
fun newFun(p1: List<String>, p2: List<String>){}
|
fun newFun(p1: List<String>, p2: List<String>){}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
val p: List<String> = bar()
|
val p = bar<String>()
|
||||||
<caret>newFun(p, p)
|
<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 downParameter(p: GeneOut<SomeFace>) = p
|
||||||
|
|
||||||
fun callDown() {
|
fun callDown() {
|
||||||
// BUG: KT-17402
|
|
||||||
val v2 = <caret>downParameter(downUnder())
|
val v2 = <caret>downParameter(downUnder())
|
||||||
}
|
}
|
||||||
Vendored
+1
-2
@@ -4,6 +4,5 @@ object Empty : GeneOut<Nothing>
|
|||||||
fun <T> downUnder(): GeneOut<T> = Empty
|
fun <T> downUnder(): GeneOut<T> = Empty
|
||||||
|
|
||||||
fun callDown() {
|
fun callDown() {
|
||||||
// BUG: KT-17402
|
val v2 = downUnder<SomeFace>()
|
||||||
val v2 = downUnder()
|
|
||||||
}
|
}
|
||||||
@@ -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
|
if (it.isEmpty()) return@any false
|
||||||
it.length < 10
|
it.length < 10
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
+15
@@ -237,6 +237,11 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
|||||||
runTest("idea/testData/refactoring/inline/function/expressionBody/FunctionalType.kt");
|
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")
|
@TestMetadata("Lambda.kt")
|
||||||
public void testLambda() throws Exception {
|
public void testLambda() throws Exception {
|
||||||
runTest("idea/testData/refactoring/inline/function/expressionBody/Lambda.kt");
|
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");
|
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")
|
@TestMetadata("InnerFunction.kt")
|
||||||
public void testInnerFunction() throws Exception {
|
public void testInnerFunction() throws Exception {
|
||||||
runTest("idea/testData/refactoring/inline/function/returnAtEnd/InnerFunction.kt");
|
runTest("idea/testData/refactoring/inline/function/returnAtEnd/InnerFunction.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user