[java] inline super class: allow to inline super calls in "foreign" methods (IDEA-291915)

GitOrigin-RevId: ade765200f9e93ead924225bb8824f54697bd6b4
This commit is contained in:
Anna Kozlova
2022-04-14 09:15:31 +00:00
committed by intellij-monorepo-bot
parent 8f7355621f
commit e2d6fcdffd
11 changed files with 69 additions and 44 deletions
@@ -160,7 +160,7 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
if (element instanceof PsiReferenceExpression &&
((PsiReferenceExpression)element).getQualifierExpression() instanceof PsiSuperExpression &&
PsiTreeUtil.isAncestor(targetClass, element, false) &&
!PushDownConflicts.isSuperCallToBeInlined(member, targetClass, mySuperClass, element)) {
!PushDownConflicts.isSuperCallToBeInlined(member, targetClass, mySuperClass)) {
usages.add(new RemoveQualifierUsageInfo((PsiReferenceExpression)element));
}
}
@@ -1,4 +1,4 @@
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.memberPushDown;
import com.intellij.codeInsight.AnnotationUtil;
@@ -33,7 +33,6 @@ import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -344,18 +343,19 @@ public class JavaPushDownDelegate extends PushDownDelegate<MemberInfo, PsiMember
public void inlineSuperCall(MemberInfoBase<? extends PsiElement> memberInfo, PsiMethod methodBySignature) {
PsiMethod superMethod = (PsiMethod)memberInfo.getMember();
Collection<PsiReference> superReferences =
ReferencesSearch.search(superMethod, new LocalSearchScope(methodBySignature)).findAll();
if (superReferences.size() == 1) {
PsiReference reference = ContainerUtil.getFirstItem(superReferences);
if (reference == null) return;
PsiElement element = reference.getElement();
if (element instanceof PsiReferenceExpression) {
PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
if (superMethod.getBody() != null) {
// No super method body: either native method or compilation error
new InlineMethodProcessor(element.getProject(), superMethod, referenceExpression, null, true)
.inlineMethodCall(referenceExpression);
PsiClass containingClass = methodBySignature.getContainingClass();
if (containingClass != null) {
Collection<PsiReference> superReferences =
ReferencesSearch.search(superMethod, new LocalSearchScope(containingClass)).findAll();
for (PsiReference reference : superReferences) {
PsiElement element = reference.getElement();
if (element instanceof PsiReferenceExpression) {
PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
if (superMethod.getBody() != null) {
// No super method body: either native method or compilation error
new InlineMethodProcessor(element.getProject(), superMethod, referenceExpression, null, true)
.inlineMethodCall(referenceExpression);
}
}
}
}
@@ -1,18 +1,4 @@
/*
* Copyright 2000-2009 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.
*/
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.memberPushDown;
import com.intellij.codeInsight.AnnotationUtil;
@@ -22,7 +8,10 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringConflictsUtil;
@@ -58,10 +47,6 @@ public class PushDownConflicts {
myConflicts = conflicts;
}
public boolean isAnyConflicts() {
return !myConflicts.isEmpty();
}
public MultiMap<PsiElement, String> getConflicts() {
return myConflicts;
}
@@ -157,7 +142,7 @@ public class PushDownConflicts {
if (myConflicts.containsKey(element)) continue;
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
final PsiExpression qualifier = referenceExpression.getQualifierExpression();
if (qualifier instanceof PsiSuperExpression && isSuperCallToBeInlined(member, targetClass, myClass, element)) continue;
if (qualifier instanceof PsiSuperExpression && isSuperCallToBeInlined(member, targetClass, myClass)) continue;
if (qualifier != null) {
final PsiType qualifierType = qualifier.getType();
PsiClass aClass = null;
@@ -238,14 +223,13 @@ public class PushDownConflicts {
public static boolean isSuperCallToBeInlined(PsiMember member,
PsiClass targetClass,
PsiClass sourceClass,
PsiElement referenceOnSuper) {
PsiClass sourceClass) {
if (member instanceof PsiMethod) {
PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(sourceClass, targetClass, PsiSubstitutor.EMPTY);
PsiMethod methodInTarget = MethodSignatureUtil.findMethodBySuperSignature(targetClass,
((PsiMethod)member).getSignature(substitutor),
true);
return methodInTarget != null && PsiTreeUtil.isAncestor(methodInTarget, referenceOnSuper, false);
return methodInTarget != null && targetClass.equals(methodInTarget.getContainingClass());
}
return false;
}
@@ -1,3 +1,3 @@
abstract class Super {
public abstract void method() {}
public abstract void method();
}
@@ -1,6 +1,6 @@
class Test extends Super{
public void context() {
super.method();
method();
}
@Override
@@ -1,3 +1,3 @@
abstract class Super {
public abstract void method() {}
public abstract void method();
}
@@ -1,3 +1,3 @@
abstract class Super {
public abstract void method() {}
public abstract void method();
}
@@ -1,6 +1,6 @@
class Test extends Super{
public void context() {
super.method();
method();
}
@Override
@@ -0,0 +1,20 @@
class Super {
boolean add(Integer key, String value) {
System.out.println("0");
return true;
}
}
class Test {
boolean add(Integer key, String value) {
System.out.println("1");
System.out.println("0");
return true;
}
void assign(Integer key, String value) {
System.out.println("2");
System.out.println("0");
}
}
@@ -0,0 +1,20 @@
class Super {
boolean add(Integer key, String value) {
System.out.println("0");
return true;
}
}
class Test extends Super {
@Override
boolean add(Integer key, String value) {
System.out.println("1");
return super.add(key, value);
}
void assign(Integer key, String value) {
System.out.println("2");
super.add(key, value);
}
}
@@ -76,6 +76,7 @@ public class InlineSuperClassTest extends LightMultiFileTestCase {
public void testSealedGrandParentNonSealedInheritor() { doTest(false, true); }
public void testSealedParentInlineAll() { doTest(); }
public void testMultipleSealedParents() { doTest(false, true); }
public void testMultipleSuperCalls() { doTest(false, true); }
private void doTest() {
doTest(false, false);