From b27ed90ff31533d7289367f85e6f5a7de4253158 Mon Sep 17 00:00:00 2001 From: Jaebaek Seo Date: Tue, 30 Jul 2024 21:24:35 +0200 Subject: [PATCH] Add renderAnnotations to ExtractableCodeDescriptor The existing `ExtractFunctionDescriptorModifier::modifyDescriptor(..)` that allows us to update the extraction descriptor returns `ExtractableCodeDescriptor`. We have some cases like compose editor of Android Studio that needs to change the behavior of the extraction by updating the annotation rendering. The current annotation rendering has a limitation that the rendered annotations must be from the annotations of the container class. However, in the following example the lambda argument must have `@Composable` annotation after extraction even though its container function does not have it: ``` @Composable fun myWidget(context: @Composable () -> Unit) {} fun containerFunction() { myWidget { // This lambda argument is composable! print(true) } } ``` Since we cannot handle the above case i.e., adding `@Composable` to the extracted function for the lambda argument, this commit allows us to use the rendered annotations instead of class Ids for `ExtractableCodeDescriptor`. ^KTIJ-30695 Signed-off-by: Anna Kozlova GitOrigin-RevId: e4f2039882092544b67896f4f06a91ffee05d6d8 --- .../composableFunction.kt | 10 +++ .../composableFunction.kt.after | 15 +++++ .../composableLambda.kt | 14 ++++ .../composableLambda.kt.after | 19 ++++++ .../ExtractableCodeDescriptor.kt | 45 ++----------- .../ui/KotlinFirExtractFunctionDialog.java | 2 +- .../ExtractionDataAnalyzer.kt | 67 +++++++------------ ...FunctionWithExtractFunctionModifierTest.kt | 54 +++++++++++++++ ...hExtractFunctionModifierTestGenerated.java | 42 ++++++++++++ .../GenerateK2RefactoringsTests.kt | 4 ++ 10 files changed, 191 insertions(+), 81 deletions(-) create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt.after create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt create mode 100644 plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt.after create mode 100644 plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/AbstractK2IntroduceFunctionWithExtractFunctionModifierTest.kt create mode 100644 plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/K2IntroduceFunctionWithExtractFunctionModifierTestGenerated.java diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt new file mode 100644 index 000000000000..b9adc138d082 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt @@ -0,0 +1,10 @@ +package com.example + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER, + AnnotationTarget.VALUE_PARAMETER) +annotation class MyComposable + +@MyComposable +fun sourceFunction() { + print(true) +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt.after new file mode 100644 index 000000000000..bb40c35e55b3 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt.after @@ -0,0 +1,15 @@ +package com.example + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER, + AnnotationTarget.VALUE_PARAMETER) +annotation class MyComposable + +@MyComposable +fun sourceFunction() { + __dummyTestFun__() +} + +@MyComposable +private fun __dummyTestFun__() { + print(true) +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt new file mode 100644 index 000000000000..44753b831bcf --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt @@ -0,0 +1,14 @@ +package com.example + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER, + AnnotationTarget.VALUE_PARAMETER) +annotation class MyComposable + +@MyComposable +fun myWidget(context: @MyComposable () -> Unit) {} + +fun setContent() { + myWidget { + print(true) + } +} \ No newline at end of file diff --git a/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt.after b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt.after new file mode 100644 index 000000000000..644db3da6650 --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt.after @@ -0,0 +1,19 @@ +package com.example + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE_PARAMETER, + AnnotationTarget.VALUE_PARAMETER) +annotation class MyComposable + +@MyComposable +fun myWidget(context: @MyComposable () -> Unit) {} + +fun setContent() { + myWidget { + __dummyTestFun__() + } +} + +@MyComposable +private fun __dummyTestFun__() { + print(true) +} diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ExtractableCodeDescriptor.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ExtractableCodeDescriptor.kt index bcff4638b20d..be6dd3d4a86d 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ExtractableCodeDescriptor.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ExtractableCodeDescriptor.kt @@ -3,30 +3,14 @@ package org.jetbrains.kotlin.idea.k2.refactoring.extractFunction import com.intellij.psi.PsiElement import com.intellij.util.containers.MultiMap -import org.jetbrains.kotlin.analysis.api.KaExperimentalApi -import org.jetbrains.kotlin.analysis.api.KaSession import org.jetbrains.kotlin.analysis.api.analyze -import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotated -import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotation -import org.jetbrains.kotlin.analysis.api.renderer.base.annotations.KaRendererAnnotationsFilter -import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KaDeclarationRendererForSource import org.jetbrains.kotlin.analysis.api.types.KaType -import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ControlFlow -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.DuplicateInfo -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ExtractableCodeDescriptorWithConflictsResult -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.IExtractableCodeDescriptor -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.IExtractableCodeDescriptorWithConflicts -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.IReplacement -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.TypeParameter +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* import org.jetbrains.kotlin.lexer.KtKeywordToken import org.jetbrains.kotlin.lexer.KtModifierKeywordToken -import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtElement -import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType data class ExtractableCodeDescriptor( val context: KtElement, @@ -41,7 +25,7 @@ data class ExtractableCodeDescriptor( override val returnType: KaType, override val modifiers: List = emptyList(), override val optInMarkers: List = emptyList(), - val annotationClassIds: Set = emptySet() + val renderedAnnotations: List = emptyList(), ) : IExtractableCodeDescriptor { override val name: String get() = suggestedNames.firstOrNull() ?: "" @@ -51,28 +35,11 @@ data class ExtractableCodeDescriptor( override fun isUnitReturnType(): Boolean = isUnitReturn - @OptIn(KaExperimentalApi::class) override val annotationsText: String - get() { - if (annotationClassIds.isEmpty()) return "" - val container = extractionData.commonParent.getStrictParentOfType() ?: return "" - return analyze(container) { - val filteredRenderer = KaDeclarationRendererForSource.WITH_QUALIFIED_NAMES.annotationRenderer.with { - annotationFilter = annotationFilter.and(object : KaRendererAnnotationsFilter { - override fun filter( - analysisSession: KaSession, - annotation: KaAnnotation, - owner: KaAnnotated - ): Boolean { - return annotation.classId in annotationClassIds - } - }) - - } - val printer = PrettyPrinter() - filteredRenderer.renderAnnotations(useSiteSession, container.symbol, printer) - printer.toString() + "\n" - } + get() = if (renderedAnnotations.isEmpty()) { + "" + } else { + renderedAnnotations.joinToString(separator = "\n", postfix = "\n") } } diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ui/KotlinFirExtractFunctionDialog.java b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ui/KotlinFirExtractFunctionDialog.java index 29ea05373e79..befdb215c3a5 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ui/KotlinFirExtractFunctionDialog.java +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/extractFunction/ui/KotlinFirExtractFunctionDialog.java @@ -303,6 +303,6 @@ public class KotlinFirExtractFunctionDialog extends DialogWrapper { returnType, originalDescriptor.getModifiers(), originalDescriptor.getOptInMarkers(), - originalDescriptor.getAnnotationClassIds()); + originalDescriptor.getRenderedAnnotations()); } } diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/extractionEngine/ExtractionDataAnalyzer.kt b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/extractionEngine/ExtractionDataAnalyzer.kt index e44e7fe43d91..974d452ad173 100644 --- a/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/extractionEngine/ExtractionDataAnalyzer.kt +++ b/plugins/kotlin/refactorings/kotlin.refactorings.k2/src/org/jetbrains/kotlin/idea/k2/refactoring/introduce/extractionEngine/ExtractionDataAnalyzer.kt @@ -9,63 +9,30 @@ import com.intellij.psi.util.descendantsOfType import com.intellij.refactoring.util.RefactoringUIUtil import com.intellij.util.containers.MultiMap import org.jetbrains.kotlin.analysis.api.* -import org.jetbrains.kotlin.analysis.api.annotations.* +import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotation +import org.jetbrains.kotlin.analysis.api.annotations.KaAnnotationValue import org.jetbrains.kotlin.analysis.api.components.KaDataFlowExitPointSnapshot import org.jetbrains.kotlin.analysis.api.components.KaDiagnosticCheckerFilter import org.jetbrains.kotlin.analysis.api.fir.diagnostics.KaFirDiagnostic import org.jetbrains.kotlin.analysis.api.projectStructure.KaDanglingFileResolutionMode +import org.jetbrains.kotlin.analysis.api.renderer.declarations.impl.KaDeclarationRendererForSource import org.jetbrains.kotlin.analysis.api.symbols.KaCallableSymbol import org.jetbrains.kotlin.analysis.api.symbols.markers.KaAnnotatedSymbol import org.jetbrains.kotlin.analysis.api.types.KaClassType import org.jetbrains.kotlin.analysis.api.types.KaType +import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter import org.jetbrains.kotlin.idea.base.resources.KotlinBundle import org.jetbrains.kotlin.idea.base.util.names.FqNames import org.jetbrains.kotlin.idea.base.util.names.FqNames.OptInFqNames.isRequiresOptInFqName -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractFunctionDescriptorModifier -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractableCodeDescriptor -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractableCodeDescriptorWithConflicts -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractionData -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractionGeneratorConfiguration -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractionResult -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.MutableParameter -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.inferParametersInfo -import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.targetKey -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.AbstractExtractionDataAnalyzer -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ControlFlow -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ExtractionGeneratorOptions -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ExtractionTarget -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.IExtractableCodeDescriptor -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.IExtractionData -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.IReplacement -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.OutputDescriptor -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ParametersInfo -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.ResolveResult -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.TypeDescriptor -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.TypeParameter -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.getDefaultVisibility -import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.resolveResult +import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.* +import org.jetbrains.kotlin.idea.refactoring.introduce.extractionEngine.* import org.jetbrains.kotlin.idea.references.ReadWriteAccessChecker import org.jetbrains.kotlin.idea.references.mainReference import org.jetbrains.kotlin.lexer.KtModifierKeywordToken import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtBreakExpression -import org.jetbrains.kotlin.psi.KtContinueExpression -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtProperty -import org.jetbrains.kotlin.psi.KtReferenceExpression -import org.jetbrains.kotlin.psi.KtReturnExpression -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtThisExpression -import org.jetbrains.kotlin.psi.KtTreeVisitorVoid -import org.jetbrains.kotlin.psi.KtTypeParameter -import org.jetbrains.kotlin.psi.KtUserType +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType internal class ExtractionDataAnalyzer(private val extractionData: ExtractionData) : @@ -222,7 +189,7 @@ internal class ExtractionDataAnalyzer(private val extractionData: ExtractionData returnType = returnType, modifiers = emptyList(), optInMarkers = experimentalMarkers.optInMarkers, - annotationClassIds = experimentalMarkers.propagatingMarkerClassIds + renderedAnnotations = getRenderedAnnotations(experimentalMarkers.propagatingMarkerClassIds) ) val config = ExtractionGeneratorConfiguration( descriptor, @@ -248,6 +215,24 @@ internal class ExtractionDataAnalyzer(private val extractionData: ExtractionData } return descriptor } + + @OptIn(KaExperimentalApi::class) + private fun getRenderedAnnotations(annotationClassIds: Set): List { + if (annotationClassIds.isEmpty()) return emptyList() + val container = extractionData.commonParent.getStrictParentOfType() ?: return emptyList() + return analyze(container) { + val owner = container.symbol + val renderer = KaDeclarationRendererForSource.WITH_QUALIFIED_NAMES.annotationRenderer + owner.annotations.filter { it.classId in annotationClassIds }.map { annotation -> + val printer = PrettyPrinter() + printer.append('@') + renderer.annotationUseSiteTargetRenderer.renderUseSiteTarget(useSiteSession, annotation, owner, renderer, printer) + renderer.annotationsQualifiedNameRenderer.renderQualifier(useSiteSession, annotation, owner, renderer, printer) + printer.append('\n') + printer.toString() + } + } + } } private data class ExperimentalMarkers( diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/AbstractK2IntroduceFunctionWithExtractFunctionModifierTest.kt b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/AbstractK2IntroduceFunctionWithExtractFunctionModifierTest.kt new file mode 100644 index 000000000000..e0fe52f48748 --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/AbstractK2IntroduceFunctionWithExtractFunctionModifierTest.kt @@ -0,0 +1,54 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package org.jetbrains.kotlin.idea.k2.refactoring.introduce + +import com.intellij.psi.util.parentOfType +import org.jetbrains.kotlin.analysis.api.analyze +import org.jetbrains.kotlin.analysis.api.resolution.singleFunctionCallOrNull +import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractFunctionDescriptorModifier +import org.jetbrains.kotlin.idea.k2.refactoring.extractFunction.ExtractableCodeDescriptor +import org.jetbrains.kotlin.idea.util.findAnnotation +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtAnnotated +import org.jetbrains.kotlin.psi.KtCallExpression +import org.jetbrains.kotlin.psi.KtLambdaArgument + +private val MY_COMPOSABLE_CLASS_ID = ClassId(FqName("com.example"), FqName("MyComposable"), false) + +abstract class AbstractK2IntroduceFunctionWithExtractFunctionModifierTest: AbstractK2IntroduceFunctionTest() { + override fun setUp() { + super.setUp() + ExtractFunctionDescriptorModifier.EP_NAME.point.registerExtension( + MyComposeExtractFunctionDescriptorModifier(), testRootDisposable + ) + } +} + +private class MyComposeExtractFunctionDescriptorModifier : ExtractFunctionDescriptorModifier { + private fun KtLambdaArgument.isComposable(): Boolean { + val callExpression = parent as KtCallExpression + val lambdaExpression = getLambdaExpression() ?: return false + analyze(callExpression) { + val call = callExpression.resolveToCall()?.singleFunctionCallOrNull() ?: return false + val parameterTypeForLambda = call.argumentMapping[lambdaExpression]?.returnType ?: return false + return parameterTypeForLambda.annotations.classIds.any { it == MY_COMPOSABLE_CLASS_ID } + } + } + + override fun modifyDescriptor(descriptor: ExtractableCodeDescriptor): ExtractableCodeDescriptor { + val sourceFunction = descriptor.extractionData.targetSibling + if (sourceFunction is KtAnnotated) { + sourceFunction.findAnnotation(MY_COMPOSABLE_CLASS_ID)?.let { + return descriptor.copy( + renderedAnnotations = descriptor.renderedAnnotations + "@${MY_COMPOSABLE_CLASS_ID.asFqNameString()}" + ) + } + } + val outsideLambda = descriptor.extractionData.commonParent.parentOfType(true) ?: return descriptor + return if (outsideLambda.isComposable()) { + descriptor.copy(renderedAnnotations = descriptor.renderedAnnotations + "@${MY_COMPOSABLE_CLASS_ID.asFqNameString()}") + } else { + descriptor + } + } +} \ No newline at end of file diff --git a/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/K2IntroduceFunctionWithExtractFunctionModifierTestGenerated.java b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/K2IntroduceFunctionWithExtractFunctionModifierTestGenerated.java new file mode 100644 index 000000000000..607f4eb3c66a --- /dev/null +++ b/plugins/kotlin/refactorings/kotlin.refactorings.tests.k2/test/org/jetbrains/kotlin/idea/k2/refactoring/introduce/K2IntroduceFunctionWithExtractFunctionModifierTestGenerated.java @@ -0,0 +1,42 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. + +package org.jetbrains.kotlin.idea.k2.refactoring.introduce; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.idea.base.plugin.KotlinPluginMode; +import org.jetbrains.kotlin.idea.base.test.TestRoot; +import org.jetbrains.kotlin.idea.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.idea.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +/** + * This class is generated by {@link org.jetbrains.kotlin.testGenerator.generator.TestGenerator}. + * DO NOT MODIFY MANUALLY. + */ +@SuppressWarnings("all") +@TestRoot("refactorings/kotlin.refactorings.tests.k2") +@TestDataPath("$CONTENT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +@TestMetadata("../../idea/tests/testData/refactoring/extractFunctionModifier") +public class K2IntroduceFunctionWithExtractFunctionModifierTestGenerated extends AbstractK2IntroduceFunctionWithExtractFunctionModifierTest { + @java.lang.Override + @org.jetbrains.annotations.NotNull + public final KotlinPluginMode getPluginMode() { + return KotlinPluginMode.K2; + } + + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doExtractFunctionTest, this, testDataFilePath); + } + + @TestMetadata("composableFunction.kt") + public void testComposableFunction() throws Exception { + runTest("../../idea/tests/testData/refactoring/extractFunctionModifier/composableFunction.kt"); + } + + @TestMetadata("composableLambda.kt") + public void testComposableLambda() throws Exception { + runTest("../../idea/tests/testData/refactoring/extractFunctionModifier/composableLambda.kt"); + } +} diff --git a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt index aef9c571e759..b1daa23d6940 100644 --- a/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt +++ b/plugins/kotlin/util/test-generator-fir/test/org/jetbrains/kotlin/fir/testGenerator/GenerateK2RefactoringsTests.kt @@ -82,6 +82,10 @@ internal fun MutableTWorkspace.generateK2RefactoringsTests() { model("refactoring/extractFunction", pattern = Patterns.KT_OR_KTS, testMethodName = "doExtractFunctionTest") } + testClass { + model("refactoring/extractFunctionModifier", pattern = Patterns.KT_OR_KTS, testMethodName = "doExtractFunctionTest") + } + testClass { model("refactoring/extractFunctionInplace") }