diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index ada6da94f66..cdaf580a565 100644 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -626,6 +626,7 @@ fun main(args: Array) { model("refactoring/introduceProperty", extension = "kt", testMethod = "doIntroducePropertyTest") model("refactoring/introduceParameter", extension = "kt", testMethod = "doIntroduceSimpleParameterTest") model("refactoring/introduceLambdaParameter", extension = "kt", testMethod = "doIntroduceLambdaParameterTest") + model("refactoring/introduceJavaParameter", extension = "java", testMethod = "doIntroduceJavaParameterTest") } testClass(javaClass()) { diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt index 32a111c298c..dcf9b46ac5e 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/declarationsSearch/overridersSearch.kt @@ -43,7 +43,7 @@ fun PsiElement.isOverridableElement(): Boolean = when (this) { else -> false } -public fun HierarchySearchRequest.searchOverriders(): Query { +public fun HierarchySearchRequest<*>.searchOverriders(): Query { val psiMethods = originalElement.toLightMethods() if (psiMethods.isEmpty()) return EmptyQuery.getEmptyQuery() diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index cd9abd0d912..8f707c98222 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -262,6 +262,8 @@ language="jet" /> + diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeInfo.kt index 341dec68967..8c30a4425b3 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeInfo.kt @@ -46,7 +46,7 @@ public class JetChangeInfo( val methodDescriptor: JetMethodDescriptor, private var name: String = methodDescriptor.getName(), val newReturnType: JetType? = methodDescriptor.baseDescriptor.getReturnType(), - var newReturnTypeText: String = newReturnType?.let { IdeDescriptorRenderers.SOURCE_CODE.renderType(it) } ?: "", + var newReturnTypeText: String = methodDescriptor.renderOriginalReturnType(), var newVisibility: Visibility = methodDescriptor.getVisibility(), parameterInfos: List = methodDescriptor.getParameters(), receiver: JetParameterInfo? = methodDescriptor.receiver, diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt new file mode 100644 index 00000000000..af7d537c521 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/introduce/introduceParameter/KotlinIntroduceParameterMethodUsageProcessor.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.refactoring.introduce.introduceParameter + +import com.intellij.lang.java.JavaLanguage +import com.intellij.openapi.util.Ref +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiExpression +import com.intellij.psi.PsiMethod +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.refactoring.introduceParameter.IntroduceParameterData +import com.intellij.refactoring.introduceParameter.IntroduceParameterMethodUsagesProcessor +import com.intellij.usageView.UsageInfo +import com.intellij.util.ArrayUtil +import com.intellij.util.containers.MultiMap +import gnu.trove.TIntArrayList +import org.jetbrains.kotlin.asJava.KotlinLightMethod +import org.jetbrains.kotlin.asJava.unwrapped +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.idea.JetFileType +import org.jetbrains.kotlin.idea.caches.resolve.getJavaMethodDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.core.refactoring.j2k +import org.jetbrains.kotlin.idea.j2k.IdeaResolverForConverter +import org.jetbrains.kotlin.idea.j2k.J2kPostProcessor +import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo +import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeSignatureData +import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetParameterInfo +import org.jetbrains.kotlin.idea.refactoring.changeSignature.originalBaseFunctionDescriptor +import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.* +import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchRequest +import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers +import org.jetbrains.kotlin.j2k.ConverterSettings +import org.jetbrains.kotlin.j2k.IdeaReferenceSearcher +import org.jetbrains.kotlin.j2k.JavaToKotlinConverter +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch +import org.jetbrains.kotlin.types.JetType +import java.util.Arrays +import java.util.Collections +import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders + +public class KotlinIntroduceParameterMethodUsageProcessor : IntroduceParameterMethodUsagesProcessor { + override fun isMethodUsage(usage: UsageInfo): Boolean = (usage.getElement() as? JetElement)?.let { + it.getParentOfTypeAndBranch(true) { getCalleeExpression() } != null + } ?: false + + override fun findConflicts(data: IntroduceParameterData, usages: Array, conflicts: MultiMap) { + + } + + private fun createChangeInfo(data: IntroduceParameterData, method: PsiElement): JetChangeInfo? { + val psiMethodDescriptor = when (method) { + is JetFunction -> method.resolveToDescriptor() as? FunctionDescriptor + is PsiMethod -> method.getJavaMethodDescriptor() + else -> null + } ?: return null + val changeSignatureData = JetChangeSignatureData(psiMethodDescriptor, method, Collections.singletonList(psiMethodDescriptor)) + val changeInfo = JetChangeInfo(methodDescriptor = changeSignatureData, context = method) + + data.getParametersToRemove().toNativeArray().toList().sortDescending().forEach { changeInfo.removeParameter(it) } + + // Temporarily assume that the new parameter is of Any type. Actual type is substituted during the signature update phase + val defaultValueForCall = (data.getParameterInitializer().getExpression()!! as? PsiExpression)?.let { it.j2k(it) } + changeInfo.addParameter(JetParameterInfo(functionDescriptor = psiMethodDescriptor, + name = data.getParameterName(), + type = KotlinBuiltIns.getInstance().getAnyType(), + defaultValueForCall = defaultValueForCall)) + return changeInfo + } + + override fun processChangeMethodSignature(data: IntroduceParameterData, usage: UsageInfo, usages: Array): Boolean { + val element = usage.getElement() as? JetFunction ?: return true + + val changeInfo = createChangeInfo(data, element) ?: return true + // Java method is already updated at this point + val addedParameterType = data.getMethodToReplaceIn().getJavaMethodDescriptor().getValueParameters().last().getType() + changeInfo.getNewParameters().last().currentTypeText = IdeDescriptorRenderers.SOURCE_CODE.renderType(addedParameterType) + + val scope = element.getUseScope().let { + if (it is GlobalSearchScope) GlobalSearchScope.getScopeRestrictedByFileTypes(it, JetFileType.INSTANCE) else it + } + val kotlinFunctions = HierarchySearchRequest(element, scope) + .searchOverriders() + .map { it.unwrapped } + .filterIsInstance() + return (kotlinFunctions + element).all { + JetFunctionDefinitionUsage(it, changeInfo.originalBaseFunctionDescriptor, null, null).processUsage(changeInfo, it) + } + } + + override fun processChangeMethodUsage(data: IntroduceParameterData, usage: UsageInfo, usages: Array): Boolean { + val psiMethod = data.getMethodToReplaceIn() + val changeInfo = createChangeInfo(data, psiMethod) ?: return true + val refElement = usage.getElement() as? JetReferenceExpression ?: return true + val callElement = refElement.getParentOfTypeAndBranch(true) { getCalleeExpression() } ?: return true + val delegateUsage = if (callElement is JetConstructorDelegationCall) { + [suppress("CAST_NEVER_SUCCEEDS")] + (JetConstructorDelegationCallUsage(callElement, changeInfo) as JetUsageInfo) + } + else { + JetFunctionCallUsage(callElement, changeInfo.methodDescriptor.originalPrimaryFunction) + } + return delegateUsage.processUsage(changeInfo, callElement) + } + + override fun processAddSuperCall(data: IntroduceParameterData, usage: UsageInfo, usages: Array): Boolean = true + + override fun processAddDefaultConstructor(data: IntroduceParameterData, usage: UsageInfo, usages: Array): Boolean = true +} diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethod.1.kt b/idea/testData/refactoring/introduceJavaParameter/javaMethod.1.kt new file mode 100644 index 00000000000..d36f2f75d5d --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethod.1.kt @@ -0,0 +1,3 @@ +fun test() { + val x = J().foo(1, 2, 3) +} diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethod.1.kt.after b/idea/testData/refactoring/introduceJavaParameter/javaMethod.1.kt.after new file mode 100644 index 00000000000..7045ae896c5 --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethod.1.kt.after @@ -0,0 +1,3 @@ +fun test() { + val x = J().foo(3, A(a + b)) +} diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethod.java b/idea/testData/refactoring/introduceJavaParameter/javaMethod.java new file mode 100644 index 00000000000..13830460f36 --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethod.java @@ -0,0 +1,19 @@ +class A { + int x; + + A(int x) { + this.x = x; + } +} + +class J { + int foo(int a, int b, int c) { + return new A(a + b).x * c + } +} + +class Test { + void test() { + new J().foo(1, 2, 3); + } +} diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethod.java.after b/idea/testData/refactoring/introduceJavaParameter/javaMethod.java.after new file mode 100644 index 00000000000..73ff92431c2 --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethod.java.after @@ -0,0 +1,19 @@ +class A { + int x; + + A(int x) { + this.x = x; + } +} + +class J { + int foo(int c, A a1) { + return a1.x * c + } +} + +class Test { + void test() { + new J().foo(3, new A(1 + 2)); + } +} diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.1.kt b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.1.kt new file mode 100644 index 00000000000..aa3fe2b6031 --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.1.kt @@ -0,0 +1,12 @@ +fun test() { + J().foo(1, 2, 3) + K().foo(1, 2, 3) +} + +abstract class K0 { + abstract fun foo(a: Int, b: Int, c: Int): Int +} + +open class K: K0() { + override fun foo(a: Int, b: Int, c: Int) = a + b + c +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.1.kt.after b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.1.kt.after new file mode 100644 index 00000000000..a7f79a410bd --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.1.kt.after @@ -0,0 +1,12 @@ +fun test() { + J().foo(3, A(a + b)) + K().foo(3, A(a + b)) +} + +abstract class K0 { + abstract fun foo(c: Int, a1: A?): Int +} + +open class K: K0() { + override fun foo(c: Int, a1: A?) = a + b + c +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java new file mode 100644 index 00000000000..e92209a18d6 --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java @@ -0,0 +1,26 @@ +// APPLY_TO_SUPER +class A { + int x; + + A(int x) { + this.x = x; + } +} + +interface T { + int foo(int a, int b, int c); +} + +class J extends K implements T { + @Override + public int foo(int a, int b, int c) { + return new A(a + b).x * c; + } +} + +class Test { + void test() { + new J().foo(1, 2, 3); + new K().foo(1, 2, 3); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java.after b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java.after new file mode 100644 index 00000000000..b1d0ef6917d --- /dev/null +++ b/idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java.after @@ -0,0 +1,26 @@ +// APPLY_TO_SUPER +class A { + int x; + + A(int x) { + this.x = x; + } +} + +interface T { + int foo(int a, int b, int c); +} + +class J extends K implements T { + @Override + public int foo(int c, A a1) { + return a1.x * c; + } +} + +class Test { + void test() { + new J().foo(3, new A(1 + 2)); + new K().foo(3, new A(1 + 2)); + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt index c9b0aeece4e..90c5618e759 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractJetExtractionTest.kt @@ -16,11 +16,23 @@ package org.jetbrains.kotlin.idea.refactoring.introduce +import com.intellij.codeInsight.CodeInsightUtil +import com.intellij.codeInsight.completion.JavaCompletionUtil import com.intellij.ide.DataManager import com.intellij.openapi.editor.Editor import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.FileUtil +import com.intellij.psi.PsiFile +import com.intellij.psi.PsiJavaFile +import com.intellij.psi.codeStyle.JavaCodeStyleManager +import com.intellij.psi.codeStyle.VariableKind import com.intellij.refactoring.BaseRefactoringProcessor.ConflictsInTestsException +import com.intellij.refactoring.IntroduceParameterRefactoring +import com.intellij.refactoring.introduceField.ElementToWorkOn +import com.intellij.refactoring.introduceParameter.AbstractJavaInplaceIntroducer +import com.intellij.refactoring.introduceParameter.IntroduceParameterProcessor +import com.intellij.refactoring.introduceParameter.Util +import com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase import org.jetbrains.kotlin.idea.refactoring.JetRefactoringUtil @@ -52,6 +64,8 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe protected fun doIntroduceVariableTest(path: String) { doTest(path) { file -> + file as JetFile + KotlinIntroduceVariableHandler().invoke( fixture.getProject(), fixture.getEditor(), @@ -111,9 +125,85 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe protected fun doIntroduceLambdaParameterTest(path: String) { doIntroduceParameterTest(path, true) } - + + protected fun doIntroduceJavaParameterTest(path: String) { + // Copied from com.intellij.refactoring.IntroduceParameterTest.perform() + doTest(path, true) { file -> + file as PsiJavaFile + + var elementToWorkOn: ElementToWorkOn? = null + ElementToWorkOn.processElementToWorkOn( + getEditor(), + file, + "Introduce parameter", + null, + getProject(), + object : ElementToWorkOn.ElementsProcessor { + override fun accept(e: ElementToWorkOn): Boolean { + return true + } + + override fun pass(e: ElementToWorkOn?) { + if (e != null) { + elementToWorkOn = e + } + } + }) + + val expr = elementToWorkOn!!.getExpression() + val localVar = elementToWorkOn!!.getLocalVariable() + + val context = expr ?: localVar + val method = Util.getContainingMethod(context) ?: throw AssertionError("No containing method found") + + val applyToSuper = InTextDirectivesUtils.isDirectiveDefined(file.getText(), "// APPLY_TO_SUPER") + val methodToSearchFor = if (applyToSuper) method.findDeepestSuperMethods()[0] else method + + val (initializer, occurrences) = + if (expr == null) { + localVar.getInitializer()!! to CodeInsightUtil.findReferenceExpressions(method, localVar) + } + else { + expr to ExpressionOccurrenceManager(expr, method, null).findExpressionOccurrences() + } + val type = initializer.getType() + + val parametersToRemove = Util.findParametersToRemove(method, initializer, occurrences) + + val codeStyleManager = JavaCodeStyleManager.getInstance(getProject()) + val info = codeStyleManager.suggestUniqueVariableName( + codeStyleManager.suggestVariableName(VariableKind.PARAMETER, localVar?.getName(), initializer, type), + expr, + true + ) + val suggestedNames = AbstractJavaInplaceIntroducer.appendUnresolvedExprName( + JavaCompletionUtil.completeVariableNameForRefactoring(codeStyleManager, type, VariableKind.LOCAL_VARIABLE, info), + initializer + ) + + IntroduceParameterProcessor(getProject(), + method, + methodToSearchFor, + initializer, + expr, + localVar, + true, + suggestedNames.first(), + true, + IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, + false, + false, + null, + parametersToRemove).run() + + getEditor().getSelectionModel().removeSelection() + } + } + protected fun doIntroducePropertyTest(path: String) { doTest(path) { file -> + file as JetFile + val extractionTarget = propertyTargets.single { it.name == InTextDirectivesUtils.findStringWithPrefixes(file.getText(), "// EXTRACTION_TARGET: ") } @@ -144,6 +234,8 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe protected fun doExtractFunctionTest(path: String) { doTest(path) { file -> + file as JetFile + val explicitPreviousSibling = file.findElementByComment("// SIBLING:") val fileText = file.getText() ?: "" val expectedNames = InTextDirectivesUtils.findListWithPrefixes(fileText, "// SUGGESTED_NAMES: ") @@ -206,7 +298,7 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe } } - protected fun doTest(path: String, action: (JetFile) -> Unit) { + protected fun doTest(path: String, checkAdditionalAfterdata: Boolean = false, action: (PsiFile) -> Unit) { val mainFile = File(path) val afterFile = File("$path.after") val conflictFile = File("$path.conflicts") @@ -215,13 +307,11 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe val mainFileName = mainFile.getName() val mainFileBaseName = FileUtil.getNameWithoutExtension(mainFileName) - mainFile.getParentFile() - .listFiles { file, name -> - name != mainFileName && name.startsWith("$mainFileBaseName.") && (name.endsWith(".kt") || name.endsWith(".java")) - }.forEach { - fixture.configureByFile(it.getName()) - } - val file = fixture.configureByFile(mainFileName) as JetFile + val extraFiles = mainFile.getParentFile().listFiles { file, name -> + name != mainFileName && name.startsWith("$mainFileBaseName.") && (name.endsWith(".kt") || name.endsWith(".java")) + } + val extraFilesToPsi = extraFiles.toMap { fixture.configureByFile(it.getName()) } + val file = fixture.configureByFile(mainFileName) val addKotlinRuntime = InTextDirectivesUtils.findStringWithPrefixes(file.getText(), "// WITH_RUNTIME") != null if (addKotlinRuntime) { @@ -233,6 +323,12 @@ public abstract class AbstractJetExtractionTest() : JetLightCodeInsightFixtureTe assert(!conflictFile.exists()) { "Conflict file $conflictFile should not exist" } JetTestUtils.assertEqualsToFile(afterFile, file.getText()!!) + + if (checkAdditionalAfterdata) { + for ((extraPsiFile, extraFile) in extraFilesToPsi) { + JetTestUtils.assertEqualsToFile(File("${extraFile.getPath()}.after"), extraPsiFile.getText()) + } + } } catch(e: Exception) { val message = if (e is ConflictsInTestsException) e.getMessages().sort().joinToString(" ") else e.getMessage() diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java index 82ca85ba46f..7bb2e2f0bd1 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/JetExtractionTestGenerated.java @@ -2521,4 +2521,25 @@ public class JetExtractionTestGenerated extends AbstractJetExtractionTest { doIntroduceLambdaParameterTest(fileName); } } + + @TestMetadata("idea/testData/refactoring/introduceJavaParameter") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class IntroduceJavaParameter extends AbstractJetExtractionTest { + public void testAllFilesPresentInIntroduceJavaParameter() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/refactoring/introduceJavaParameter"), Pattern.compile("^(.+)\\.java$"), true); + } + + @TestMetadata("javaMethod.java") + public void testJavaMethod() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceJavaParameter/javaMethod.java"); + doIntroduceJavaParameterTest(fileName); + } + + @TestMetadata("javaMethodOverridingKotlinFunctionWithUsages.java") + public void testJavaMethodOverridingKotlinFunctionWithUsages() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/introduceJavaParameter/javaMethodOverridingKotlinFunctionWithUsages.java"); + doIntroduceJavaParameterTest(fileName); + } + } }