diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureProcessor.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureProcessor.java index 2b4ca79a6fe..38864e103b0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureProcessor.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureProcessor.java @@ -60,37 +60,15 @@ public class JetChangeSignatureProcessor extends ChangeSignatureProcessorBase { @NotNull @Override protected UsageInfo[] findUsages() { - UsageInfo[] kotlinUsages = super.findUsages(); + List allUsages = new ArrayList(); JavaChangeInfo javaChangeInfo = getChangeInfo().getOrCreateJavaChangeInfo(); - if (javaChangeInfo == null) return kotlinUsages; + if (javaChangeInfo != null) { + UsageInfo[] javaUsages = new JavaChangeSignatureUsageProcessor().findUsages(javaChangeInfo); + allUsages.add(new KotlinWrapperForJavaUsageInfos(javaUsages, getChangeInfo().getMethod())); + } + KotlinPackage.filterIsInstanceTo(super.findUsages(), allUsages, JetUsageInfo.class); - List javaUsages = new ArrayList(); - KotlinPackage.filterNotTo( - new JavaChangeSignatureUsageProcessor().findUsages(javaChangeInfo), - javaUsages, - new Function1() { - @Override - public Boolean invoke(UsageInfo info) { - // Filter overriding declarations since they are already found by our usage processor - return info instanceof OverriderUsageInfo; - } - } - ); - Pair, List> usagesByKotlinProcessor = KotlinPackage.partition( - kotlinUsages, - new Function1() { - @Override - public Boolean invoke(UsageInfo info) { - return info instanceof JetUsageInfo; - } - } - ); - javaUsages.addAll(usagesByKotlinProcessor.getSecond()); - - List allUsages = new ArrayList(); - allUsages.add(new KotlinWrapperForJavaUsageInfos(javaUsages.toArray(new UsageInfo[javaUsages.size()]), getChangeInfo().getMethod())); - allUsages.addAll(usagesByKotlinProcessor.getFirst()); return allUsages.toArray(new UsageInfo[allUsages.size()]); } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java index a88e427749d..c80ab2dd743 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureUsageProcessor.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.codeStyle.JavaCodeStyleManager; +import com.intellij.psi.search.searches.OverridingMethodsSearch; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; @@ -45,6 +46,8 @@ import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.AnalyzerPackage; +import org.jetbrains.kotlin.asJava.AsJavaPackage; +import org.jetbrains.kotlin.asJava.KotlinLightMethod; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.idea.JetFileType; import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage; @@ -91,6 +94,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro else { findSAMUsages(info, result); findConstructorDelegationUsages(info, result); + findKotlinOverrides(info, result); } return result.toArray(new UsageInfo[result.size()]); @@ -334,7 +338,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro JetType samCallType = context.getType(callExpression); if (samCallType == null) continue; - result.add(new DeferredSAMUsage(functionLiteral, functionDescriptor, samCallType)); + result.add(new DeferredJavaMethodOverrideOrSAMUsage(functionLiteral, functionDescriptor, samCallType)); } } @@ -358,6 +362,21 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro ); } + private static void findKotlinOverrides(ChangeInfo changeInfo, Set result) { + PsiElement method = changeInfo.getMethod(); + if (!RefactoringPackage.isTrueJavaMethod(method)) return; + + for (PsiMethod overridingMethod : OverridingMethodsSearch.search((PsiMethod) method)) { + PsiElement unwrappedElement = AsJavaPackage.getNamedUnwrappedElement(overridingMethod); + if (!(unwrappedElement instanceof JetNamedFunction)) continue; + + JetNamedFunction function = (JetNamedFunction) unwrappedElement; + FunctionDescriptor functionDescriptor = (FunctionDescriptor) ResolvePackage.resolveToDescriptor(function); + + result.add(new DeferredJavaMethodOverrideOrSAMUsage(function, functionDescriptor, null)); + } + } + @Override public MultiMap findConflicts(ChangeInfo info, Ref refUsages) { MultiMap result = new MultiMap(); @@ -692,7 +711,7 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro } if (usage instanceof OverriderUsageInfo) { PsiMethod overridingMethod = ((OverriderUsageInfo)usage).getOverridingMethod(); - if (overridingMethod != null) { + if (overridingMethod != null && !(overridingMethod instanceof KotlinLightMethod)) { nullabilityPropagator.processMethod(overridingMethod); } } diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt index 35d6bd10c62..62d67a3afa8 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/changeSignature/usages/JavaMethodDeferredKotlinUsage.kt @@ -22,24 +22,24 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.idea.refactoring.changeSignature.JetChangeInfo import org.jetbrains.kotlin.psi.JetConstructorDelegationCall import org.jetbrains.kotlin.psi.JetFunction -import org.jetbrains.kotlin.psi.JetFunctionLiteral import org.jetbrains.kotlin.types.JetType public abstract class JavaMethodDeferredKotlinUsage(element: T): UsageInfo(element) { abstract fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate } -public class DeferredSAMUsage( - val functionLiteral: JetFunctionLiteral, +public class DeferredJavaMethodOverrideOrSAMUsage( + val function: JetFunction, val functionDescriptor: FunctionDescriptor, - val samCallType: JetType -): JavaMethodDeferredKotlinUsage(functionLiteral) { - override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate { - return object : JavaMethodKotlinUsageWithDelegate(functionLiteral, javaMethodChangeInfo) { + val samCallType: JetType? +): JavaMethodDeferredKotlinUsage(function) { + override fun resolve(javaMethodChangeInfo: JetChangeInfo): JavaMethodKotlinUsageWithDelegate { + return object : JavaMethodKotlinUsageWithDelegate(function, javaMethodChangeInfo) { override val delegateUsage = JetFunctionDefinitionUsage( - functionLiteral, + function, functionDescriptor, - javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction, samCallType + javaMethodChangeInfo.methodDescriptor.originalPrimaryFunction, + samCallType ) } } diff --git a/idea/testData/refactoring/changeSignature/JavaMethodOverridesAfter.1.kt b/idea/testData/refactoring/changeSignature/JavaMethodOverridesAfter.1.kt new file mode 100644 index 00000000000..47368b2fbaa --- /dev/null +++ b/idea/testData/refactoring/changeSignature/JavaMethodOverridesAfter.1.kt @@ -0,0 +1,25 @@ +open class X: A() { + fun foo(x: Int): String? { + return super.foo(1) + } +} + +open class Y: B() { + fun foo(x: Int): String? { + return 0 + } +} + +open class Z: X() { + fun foo(x: Int): String? { + return 0 + } +} + +fun test() { + A().foo(1) + B().foo(1) + X().foo(1) + Y().foo(1) + Z().foo(1) +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/JavaMethodOverridesAfter.java b/idea/testData/refactoring/changeSignature/JavaMethodOverridesAfter.java new file mode 100644 index 00000000000..786a267d29c --- /dev/null +++ b/idea/testData/refactoring/changeSignature/JavaMethodOverridesAfter.java @@ -0,0 +1,25 @@ +import java.lang.Override; +import java.lang.String; + +class A { + String foo(int x) { + return 0; + } +} + +class B extends A { + @Override + String foo(int x) { + return super.foo(x); + } +} + +class Test { + void test() { + new A().foo(1); + new B().foo(1); + new X().foo(1); + new Y().foo(1); + new Z().foo(1); + } +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/JavaMethodOverridesBefore.1.kt b/idea/testData/refactoring/changeSignature/JavaMethodOverridesBefore.1.kt new file mode 100644 index 00000000000..ef92a4ec76d --- /dev/null +++ b/idea/testData/refactoring/changeSignature/JavaMethodOverridesBefore.1.kt @@ -0,0 +1,25 @@ +open class X: A() { + fun foo(s: String): Int { + return super.foo(s) + } +} + +open class Y: B() { + fun foo(s: String): Int { + return 0 + } +} + +open class Z: X() { + fun foo(s: String): Int { + return 0 + } +} + +fun test() { + A().foo("") + B().foo("") + X().foo("") + Y().foo("") + Z().foo("") +} \ No newline at end of file diff --git a/idea/testData/refactoring/changeSignature/JavaMethodOverridesBefore.java b/idea/testData/refactoring/changeSignature/JavaMethodOverridesBefore.java new file mode 100644 index 00000000000..49e00cf60e8 --- /dev/null +++ b/idea/testData/refactoring/changeSignature/JavaMethodOverridesBefore.java @@ -0,0 +1,25 @@ +import java.lang.Override; +import java.lang.String; + +class A { + int foo(String s) { + return 0; + } +} + +class B extends A { + @Override + int foo(String s) { + return super.foo(s); + } +} + +class Test { + void test() { + new A().foo(""); + new B().foo(""); + new X().foo(""); + new Y().foo(""); + new Z().foo(""); + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.java index 81ba967c24c..854d45cda5c 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/changeSignature/JetChangeSignatureTest.java @@ -975,6 +975,26 @@ public class JetChangeSignatureTest extends KotlinCodeInsightTestCase { doTest(changeInfo); } + public void testJavaMethodOverrides() throws Exception { + doJavaTest( + new JavaRefactoringProvider() { + @Nullable + @Override + PsiType getNewReturnType(@NotNull PsiMethod method) { + return PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())); + } + + @NotNull + @Override + ParameterInfoImpl[] getNewParameters(@NotNull PsiMethod method) { + ParameterInfoImpl[] newParameters = super.getNewParameters(method); + newParameters[0] = new ParameterInfoImpl(-1, "x", PsiType.INT, "1"); + return newParameters; + } + } + ); + } + @NotNull @Override protected String getTestDataPath() {