mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[kotlin] k2 extract function context parameters
- extract explicitly used context parameter as context - skip the same typed context parameters used implicitly ^KTIJ-29441 fixed GitOrigin-RevId: 14fb4f0d205d57c184493f083fd720f9e4697f58
This commit is contained in:
committed by
intellij-monorepo-bot
parent
c0a1462c9a
commit
72ba98bc92
+15
@@ -1628,6 +1628,21 @@ public abstract class ExtractionTestGenerated extends AbstractExtractionTest {
|
||||
runTest("testData/refactoring/extractFunction/contextParameters/base.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("explicitParameterUsage.kt")
|
||||
public void testExplicitParameterUsage() throws Exception {
|
||||
runTest("testData/refactoring/extractFunction/contextParameters/explicitParameterUsage.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleParameters.kt")
|
||||
public void testMultipleParameters() throws Exception {
|
||||
runTest("testData/refactoring/extractFunction/contextParameters/multipleParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeRelations.kt")
|
||||
public void testTypeRelations() throws Exception {
|
||||
runTest("testData/refactoring/extractFunction/contextParameters/typeRelations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unnamed.kt")
|
||||
public void testUnnamed() throws Exception {
|
||||
runTest("testData/refactoring/extractFunction/contextParameters/unnamed.kt");
|
||||
|
||||
+2
-2
@@ -14,8 +14,8 @@ class Foo {
|
||||
}
|
||||
}
|
||||
|
||||
private fun string(string: String, string0: String, string1: String): String =
|
||||
string + string0 + string1 + string + this@Foo.toString()
|
||||
private fun string(string: String, string2: String, string3: String): String =
|
||||
string + string2 + string3 + string + this@Foo.toString()
|
||||
}
|
||||
|
||||
private inline fun <T> block(t: T, block: T.() -> Unit) {
|
||||
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// COMPILER_ARGUMENTS: -Xcontext-parameters
|
||||
context(a: String)
|
||||
fun bar(p: Int) {}
|
||||
|
||||
context(a: String, b: Int)
|
||||
fun m() {
|
||||
<selection>bar(b)</selection>
|
||||
}
|
||||
|
||||
// IGNORE_K1
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// COMPILER_ARGUMENTS: -Xcontext-parameters
|
||||
context(a: String)
|
||||
fun bar(p: Int) {}
|
||||
|
||||
context(a: String, b: Int)
|
||||
fun m() {
|
||||
__dummyTestFun__()
|
||||
}
|
||||
|
||||
context(b: Int, a: String) private fun __dummyTestFun__() {
|
||||
bar(b)
|
||||
}
|
||||
|
||||
// IGNORE_K1
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// COMPILER_ARGUMENTS: -Xcontext-parameters
|
||||
context(a: String)
|
||||
fun bar(p: Int) {}
|
||||
|
||||
context(a1: String)
|
||||
fun bar1(p: Int) {}
|
||||
|
||||
context(i: Int)
|
||||
val prop: Int
|
||||
get() = 42
|
||||
|
||||
context(a: String, b: Int)
|
||||
fun m() {
|
||||
<selection>val i = prop
|
||||
bar(i)
|
||||
bar1(i)
|
||||
</selection>
|
||||
}
|
||||
|
||||
// IGNORE_K1
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// COMPILER_ARGUMENTS: -Xcontext-parameters
|
||||
context(a: String)
|
||||
fun bar(p: Int) {}
|
||||
|
||||
context(a1: String)
|
||||
fun bar1(p: Int) {}
|
||||
|
||||
context(i: Int)
|
||||
val prop: Int
|
||||
get() = 42
|
||||
|
||||
context(a: String, b: Int)
|
||||
fun m() {
|
||||
__dummyTestFun__()
|
||||
|
||||
}
|
||||
|
||||
context(i: Int, a: String) private fun __dummyTestFun__() {
|
||||
val i = prop
|
||||
bar(i)
|
||||
bar1(i)
|
||||
}
|
||||
|
||||
// IGNORE_K1
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
// COMPILER_ARGUMENTS: -Xcontext-parameters
|
||||
interface A
|
||||
interface B: A
|
||||
|
||||
context(a: A)
|
||||
fun foo() {}
|
||||
|
||||
context(b: B)
|
||||
fun bar() {}
|
||||
|
||||
context(b: B)
|
||||
fun baz() {
|
||||
<selection>if (b != null) {
|
||||
foo()
|
||||
bar()
|
||||
}</selection>
|
||||
}
|
||||
|
||||
// IGNORE_K1
|
||||
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
// COMPILER_ARGUMENTS: -Xcontext-parameters
|
||||
interface A
|
||||
interface B: A
|
||||
|
||||
context(a: A)
|
||||
fun foo() {}
|
||||
|
||||
context(b: B)
|
||||
fun bar() {}
|
||||
|
||||
context(b: B)
|
||||
fun baz() {
|
||||
__dummyTestFun__()
|
||||
}
|
||||
|
||||
context(b: B) private fun __dummyTestFun__() {
|
||||
if (b != null) {
|
||||
foo()
|
||||
bar()
|
||||
}
|
||||
}
|
||||
|
||||
// IGNORE_K1
|
||||
+3
-3
@@ -6,9 +6,9 @@ fun foo(x: X, y: X) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun __dummyTestFun__(field: Any, field0: Any) {
|
||||
private fun __dummyTestFun__(field: Any, field2: Any) {
|
||||
println(field.hashCode())
|
||||
println(field.hashCode())
|
||||
println(field0.hashCode())
|
||||
println(field2.hashCode())
|
||||
}
|
||||
// IGNORE_K1
|
||||
// IGNORE_K1
|
||||
|
||||
+28
-29
@@ -6,6 +6,7 @@ import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.psi.PsiNamedElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.util.parentOfType
|
||||
import com.intellij.util.text.UniqueNameGenerator
|
||||
import org.jetbrains.kotlin.analysis.api.KaExperimentalApi
|
||||
import org.jetbrains.kotlin.analysis.api.KaImplementationDetail
|
||||
import org.jetbrains.kotlin.analysis.api.KaSession
|
||||
@@ -20,7 +21,6 @@ import org.jetbrains.kotlin.analysis.api.resolution.singleCallOrNull
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.symbol
|
||||
import org.jetbrains.kotlin.analysis.api.components.KaDiagnosticCheckerFilter
|
||||
import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic
|
||||
import org.jetbrains.kotlin.analysis.api.impl.base.components.KaBaseIllegalPsiException
|
||||
import org.jetbrains.kotlin.analysis.api.resolution.KaErrorCallInfo
|
||||
import org.jetbrains.kotlin.analysis.api.signatures.KaCallableSignature
|
||||
import org.jetbrains.kotlin.analysis.api.symbols.*
|
||||
@@ -135,32 +135,22 @@ internal fun ExtractionData.inferParametersInfo(
|
||||
|
||||
}
|
||||
|
||||
val unknownContextParameters = mutableSetOf<KtParameter>()
|
||||
analyze(virtualBlock) {
|
||||
val unknownContextParameters = analyze(virtualBlock) {
|
||||
val parameters = mutableSetOf<KtParameter>()
|
||||
for (referenceExpression in virtualBlock.collectDescendantsOfType<KtReferenceExpression> { it.resolveResult != null }) {
|
||||
val call = referenceExpression.resolveToCall()
|
||||
if (call is KaErrorCallInfo) {
|
||||
val diagnostic = call.diagnostic
|
||||
if (diagnostic is KaFirDiagnostic.NoContextArgument) {
|
||||
unknownContextParameters.addIfNotNull((diagnostic.symbol as? KaContextParameterSymbol)?.psi as? KtParameter)
|
||||
val contextParameterSymbol = diagnostic.symbol as? KaContextParameterSymbol
|
||||
if (contextParameterSymbol != null &&
|
||||
extractedDescriptorToParameter.none { it.value.contextParameter && (it.value.originalDescriptor as? KtParameter)?.returnType?.isSubtypeOf(contextParameterSymbol.returnType) == true }) {
|
||||
parameters.addIfNotNull(contextParameterSymbol.psi as? KtParameter)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unknownContextParameters.forEach {
|
||||
val name = it.name ?: "_"
|
||||
val parameter = MutableParameter(
|
||||
name,
|
||||
it.ownerDeclaration as KtNamedDeclaration,
|
||||
false,
|
||||
it.returnType,
|
||||
targetSibling as KtElement,
|
||||
contextParameter = true
|
||||
)
|
||||
parameter.refCount++
|
||||
parameter.currentName = name
|
||||
info.parameters.add(parameter)
|
||||
parameters.distinctBy { it.returnType }
|
||||
}
|
||||
|
||||
val varNameValidator = KotlinDeclarationNameValidator(
|
||||
@@ -169,7 +159,7 @@ internal fun ExtractionData.inferParametersInfo(
|
||||
KotlinNameSuggestionProvider.ValidatorTarget.PARAMETER
|
||||
)
|
||||
|
||||
val existingParameterNames = hashSetOf<String>()
|
||||
val nameGenerator = UniqueNameGenerator()
|
||||
val generateArguments: (KaType) -> List<KaType> =
|
||||
{ ktType -> (ktType as? KaClassType)?.typeArguments?.mapNotNull { it.type } ?: emptyList() }
|
||||
for ((namedElement, parameter) in extractedDescriptorToParameter) {
|
||||
@@ -197,14 +187,7 @@ internal fun ExtractionData.inferParametersInfo(
|
||||
require(currentName != null || parameter.receiverCandidate)
|
||||
|
||||
if (currentName != null) {
|
||||
if ("$currentName" in existingParameterNames) {
|
||||
var index = 0
|
||||
while ("$currentName$index" in existingParameterNames) {
|
||||
index++
|
||||
}
|
||||
currentName = "$currentName$index"
|
||||
}
|
||||
currentName?.let { existingParameterNames += it }
|
||||
currentName = nameGenerator.generateUniqueName(currentName!!)
|
||||
} else {
|
||||
currentName = "receiver"
|
||||
}
|
||||
@@ -216,6 +199,21 @@ internal fun ExtractionData.inferParametersInfo(
|
||||
}
|
||||
}
|
||||
|
||||
unknownContextParameters.forEach { contextParam ->
|
||||
val name = contextParam.name ?: "_"
|
||||
val parameter = MutableParameter(
|
||||
name,
|
||||
contextParam.ownerDeclaration as KtNamedDeclaration,
|
||||
false,
|
||||
contextParam.returnType,
|
||||
targetSibling as KtElement,
|
||||
contextParameter = true
|
||||
)
|
||||
parameter.refCount++
|
||||
parameter.currentName = name.takeIf { it == "_" } ?: nameGenerator.generateUniqueName(name)
|
||||
info.parameters.add(parameter)
|
||||
}
|
||||
|
||||
for (typeToCheck in info.typeParameters.flatMap { it.collectReferencedTypes() }.map { it.type }) {
|
||||
typeToCheck.processTypeIfExtractable(
|
||||
info.typeParameters,
|
||||
@@ -301,7 +299,8 @@ private fun ExtractionData.registerParameter(
|
||||
receiverToExtract
|
||||
)
|
||||
|
||||
MutableParameter(argumentText, elementToExtract, extractThis, originalType, targetSibling as KtElement, contextParameter = false)
|
||||
val asContextParameter = originalDeclaration is KtParameter && originalDeclaration.isContextParameter
|
||||
MutableParameter(argumentText, elementToExtract, extractThis, originalType, targetSibling as KtElement, contextParameter = asContextParameter)
|
||||
}
|
||||
|
||||
// TODO add type predicate based on called functions https://youtrack.jetbrains.com/issue/KTIJ-29166
|
||||
|
||||
+2
@@ -356,6 +356,7 @@ private fun ExtractableCodeDescriptor.validateTempResult(
|
||||
|
||||
val namedFunction = result.declaration as? KtNamedFunction
|
||||
val valueParameterList = namedFunction?.valueParameterList
|
||||
val contextReceiverList = namedFunction?.contextReceiverList
|
||||
val typeParameterList = namedFunction?.typeParameterList
|
||||
|
||||
fun processReference(currentRefExpr: KtSimpleNameExpression) {
|
||||
@@ -366,6 +367,7 @@ private fun ExtractableCodeDescriptor.validateTempResult(
|
||||
|
||||
val currentDescriptor = currentRefExpr.mainReference.resolve()
|
||||
if (currentDescriptor is KtParameter && currentDescriptor.parent == valueParameterList) return
|
||||
if (currentDescriptor is KtParameter && currentDescriptor.isContextParameter && currentDescriptor.parent == contextReceiverList) return
|
||||
if (currentDescriptor is KtTypeParameter && currentDescriptor.parent == typeParameterList) return
|
||||
if (currentDescriptor is KtProperty && currentDescriptor.isLocal
|
||||
&& parameters.any { it.mirrorVarName == currentDescriptor.name }
|
||||
|
||||
+15
@@ -397,6 +397,21 @@ public abstract class K2IntroduceFunctionTestGenerated extends AbstractK2Introdu
|
||||
runTest("../../idea/tests/testData/refactoring/extractFunction/contextParameters/base.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("explicitParameterUsage.kt")
|
||||
public void testExplicitParameterUsage() throws Exception {
|
||||
runTest("../../idea/tests/testData/refactoring/extractFunction/contextParameters/explicitParameterUsage.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("multipleParameters.kt")
|
||||
public void testMultipleParameters() throws Exception {
|
||||
runTest("../../idea/tests/testData/refactoring/extractFunction/contextParameters/multipleParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("typeRelations.kt")
|
||||
public void testTypeRelations() throws Exception {
|
||||
runTest("../../idea/tests/testData/refactoring/extractFunction/contextParameters/typeRelations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unnamed.kt")
|
||||
public void testUnnamed() throws Exception {
|
||||
runTest("../../idea/tests/testData/refactoring/extractFunction/contextParameters/unnamed.kt");
|
||||
|
||||
Reference in New Issue
Block a user