[java-refactoring] IDEA-71792 Support inlining of abstract methods having one implementation

GitOrigin-RevId: 00491acff53aff96705a866e0d799dfe22873d23
This commit is contained in:
Tagir Valeev
2024-10-10 16:22:04 +02:00
committed by intellij-monorepo-bot
parent ce73510eb1
commit 09bd11efd8
12 changed files with 284 additions and 116 deletions

View File

@@ -7,7 +7,9 @@ import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.java.refactoring.JavaRefactoringBundle;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
@@ -15,14 +17,19 @@ import com.intellij.openapi.util.NlsContexts;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.Collections;
import java.util.function.Supplier;
@@ -52,6 +59,10 @@ public final class InlineMethodHandler extends JavaInlineActionHandler {
public static void performInline(Project project, Editor editor, PsiMethod method, boolean allowInlineThisOnly) {
PsiReference reference = editor != null ? TargetElementUtil.findReference(editor, editor.getCaretModel().getOffset()) : null;
if (reference != null && reference.isReferenceTo(method) && method.hasModifierProperty(PsiModifier.ABSTRACT)) {
if (tryInlineAbstractMethodImplementation(project, editor, method, reference)) return;
}
PsiCodeBlock methodBody = method.getBody();
Supplier<PsiCodeBlock> specialization = InlineMethodSpecialization.forReference(reference);
if (specialization != null) {
@@ -139,7 +150,7 @@ public final class InlineMethodHandler extends JavaInlineActionHandler {
if (reference != null) {
final PsiElement referenceElement = reference.getElement();
if (referenceElement.getLanguage() == JavaLanguage.INSTANCE &&
if (referenceElement.getLanguage() == JavaLanguage.INSTANCE &&
!(referenceElement instanceof PsiJavaCodeReferenceElement)) {
reference = null;
}
@@ -157,8 +168,34 @@ public final class InlineMethodHandler extends JavaInlineActionHandler {
}
}
private static boolean tryInlineAbstractMethodImplementation(@NotNull Project project,
@NotNull Editor editor,
@NotNull PsiMethod method,
@NotNull PsiReference reference) {
PsiMethod realMethod = ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> ReadAction.nonBlocking(() -> {
Collection<PsiMethod> methods =
OverridingMethodsSearch.search(method).filtering(m -> !m.hasModifierProperty(PsiModifier.ABSTRACT))
.findAll();
return ContainerUtil.getOnlyItem(methods);
}).executeSynchronously(),
JavaRefactoringBundle.message("dialog.title.resolving.method.implementation"), true, project);
if (realMethod == null || realMethod.getBody() == null) return false;
String message = JavaRefactoringBundle.message("dialog.message.confirmation.to.process.only.implementation",
PsiFormatUtil.formatMethod(realMethod, PsiSubstitutor.EMPTY,
PsiFormatUtilBase.SHOW_NAME |
PsiFormatUtilBase.SHOW_CONTAINING_CLASS, 0));
int answer = Messages.showYesNoDialog(project, message, getRefactoringName(), Messages.getQuestionIcon());
if (answer == Messages.NO) return true;
InlineMethodProcessor processor = new InlineMethodProcessor(project, realMethod, reference, editor, true, false, false, true);
processor.setPrepareSuccessfulSwingThreadCallback(() -> {});
processor.run();
return true;
}
public static boolean checkRecursive(PsiMethod method) {
return checkCalls(method.getBody(), method);
PsiCodeBlock body = method.getBody();
return body != null && checkCalls(body, method);
}
private static boolean checkCalls(PsiElement scope, PsiMethod method) {
@@ -179,15 +216,10 @@ public final class InlineMethodHandler extends JavaInlineActionHandler {
}
public static boolean isThisReference(PsiReference reference) {
if (reference != null) {
final PsiElement referenceElement = reference.getElement();
if (referenceElement instanceof PsiJavaCodeReferenceElement &&
referenceElement.getParent() instanceof PsiMethodCallExpression &&
"this".equals(((PsiJavaCodeReferenceElement)referenceElement).getReferenceName())) {
return true;
}
}
return false;
return reference != null &&
reference.getElement() instanceof PsiJavaCodeReferenceElement codeRef &&
codeRef.getParent() instanceof PsiMethodCallExpression &&
"this".equals(codeRef.getReferenceName());
}
@Override

View File

@@ -10,10 +10,7 @@ import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.ObjectUtils;
@@ -21,10 +18,11 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
/**
* A helper class to perform the parameter substitution during the Inline method refactoring.
* A helper class to perform the parameter substitution during the Inline method refactoring.
* It helps to declare parameters as locals, passing arguments from the call site and then tries to inline the parameters when possible.
*/
class InlineMethodHelper {
@@ -60,23 +58,41 @@ class InlineMethodHelper {
@NotNull
private PsiSubstitutor createSubstitutor() {
JavaResolveResult resolveResult = myCall.resolveMethodGenerics();
if (myMethod.isPhysical()) {
// Could be specialized
LOG.assertTrue(myManager.areElementsEquivalent(resolveResult.getElement(), myMethod));
}
if (resolveResult.getSubstitutor() != PsiSubstitutor.EMPTY) {
PsiSubstitutor origSubstitutor = resolveResult.getSubstitutor();
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
if (substitutor != PsiSubstitutor.EMPTY) {
if (myMethod.isPhysical()) { // Could be specialized, thus non-physical, see InlineMethodSpecialization
PsiMethod calledMethod = ObjectUtils.tryCast(resolveResult.getElement(), PsiMethod.class);
if (calledMethod != null && !myManager.areElementsEquivalent(calledMethod, myMethod)) {
// Could be an implementation method
PsiSubstitutor superSubstitutor =
TypeConversionUtil.getSuperClassSubstitutor(Objects.requireNonNull(calledMethod.getContainingClass()),
Objects.requireNonNull(myMethod.getContainingClass()),
PsiSubstitutor.EMPTY);
PsiSubstitutor superMethodSubstitutor = MethodSignatureUtil.getSuperMethodSignatureSubstitutor(
myMethod.getHierarchicalMethodSignature(), calledMethod.getHierarchicalMethodSignature());
if (superMethodSubstitutor != null) {
superSubstitutor = superSubstitutor.putAll(superMethodSubstitutor);
}
for (Map.Entry<PsiTypeParameter, PsiType> entry : superSubstitutor.getSubstitutionMap().entrySet()) {
PsiTypeParameter parameter = entry.getKey();
PsiType type = entry.getValue();
if (type instanceof PsiClassType classType && classType.resolve() instanceof PsiTypeParameter typeParameter) {
substitutor = substitutor.put(typeParameter, origSubstitutor.substitute(parameter));
}
}
origSubstitutor = substitutor;
}
}
Iterator<PsiTypeParameter> oldTypeParameters = PsiUtil.typeParametersIterator(myMethod);
Iterator<PsiTypeParameter> newTypeParameters = PsiUtil.typeParametersIterator(myMethodCopy);
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
while (newTypeParameters.hasNext()) {
final PsiTypeParameter newTypeParameter = newTypeParameters.next();
final PsiTypeParameter oldTypeParameter = oldTypeParameters.next();
substitutor = substitutor.put(newTypeParameter, resolveResult.getSubstitutor().substitute(oldTypeParameter));
substitutor = substitutor.put(newTypeParameter, origSubstitutor.substitute(oldTypeParameter));
}
return substitutor;
}
return PsiSubstitutor.EMPTY;
return substitutor;
}
PsiLocalVariable @NotNull [] declareParameters() {

View File

@@ -0,0 +1,18 @@
import java.util.List;
public class InlineSingleImplementation {
interface MyIface<T> {
void mySimpleMethod();
}
static class MyIfaceImpl<E extends CharSequence> implements MyIface<E> {
@Override
public void mySimpleMethod() {
System.out.println("Impl");
}
}
void test(MyIface<String> iface) {
iface.<caret>mySimpleMethod();
}
}

View File

@@ -0,0 +1,16 @@
public class InlineSingleImplementation {
interface MyIface<T> {
void mySimpleMethod();
}
static class MyIfaceImpl<E extends CharSequence> implements MyIface<E> {
@Override
public void mySimpleMethod() {
System.out.println("Impl");
}
}
void test(MyIface<String> iface) {
System.out.println("Impl");
}
}

View File

@@ -0,0 +1,19 @@
import java.util.List;
public class InlineSingleImplementation {
interface MyIface<T> {
void myUseGenericMethod(T t);
}
static class MyIfaceImpl<E extends CharSequence> implements MyIface<E> {
@Override
public void myUseGenericMethod(E e) {
E e1 = e;
System.out.println("Impl: " + e);
}
}
void test(MyIface<String> iface) {
iface.<caret>myUseGenericMethod("hello");
}
}

View File

@@ -0,0 +1,18 @@
public class InlineSingleImplementation {
interface MyIface<T> {
void myUseGenericMethod(T t);
}
static class MyIfaceImpl<E extends CharSequence> implements MyIface<E> {
@Override
public void myUseGenericMethod(E e) {
E e1 = e;
System.out.println("Impl: " + e);
}
}
void test(MyIface<String> iface) {
String e1 = "hello";
System.out.println("Impl: " + "hello");
}
}

View File

@@ -0,0 +1,22 @@
import java.util.List;
public class InlineSingleImplementation {
interface MyIface<T> {
<M> M myGenericMethod(M m, T t);
}
static class MyIfaceImpl<E extends CharSequence> implements MyIface<E> {
@Override
public <M1> M1 myGenericMethod(M1 m, E e) {
M1 m1 = m;
E e1 = e;
if (m == null) return null;
System.out.println("Impl: " + m1 + " : " + e);
return m;
}
}
void test(MyIface<String> iface) {
int x = iface.<caret>myGenericMethod(123, "hello");
}
}

View File

@@ -0,0 +1,27 @@
public class InlineSingleImplementation {
interface MyIface<T> {
<M> M myGenericMethod(M m, T t);
}
static class MyIfaceImpl<E extends CharSequence> implements MyIface<E> {
@Override
public <M1> M1 myGenericMethod(M1 m, E e) {
M1 m1 = m;
E e1 = e;
if (m == null) return null;
System.out.println("Impl: " + m1 + " : " + e);
return m;
}
}
void test(MyIface<String> iface) {
Integer result = null;
Integer m1 = 123;
String e1 = "hello";
if ((Integer) 123 != null) {
System.out.println("Impl: " + m1 + " : " + "hello");
result = 123;
}
int x = result;
}
}

View File

@@ -10,7 +10,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.refactoring.MockInlineMethodOptions;
import com.intellij.refactoring.inline.InlineMethodProcessor;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.testFramework.LightProjectDescriptor;
@@ -67,8 +66,7 @@ public class InlineMethodMultifileTest extends LightFixtureCompletionTestCase {
final boolean condition = InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method);
assertFalse("Bad returns found", condition);
new InlineMethodProcessor(getProject(), method, null, getEditor(), new MockInlineMethodOptions().isInlineThisOnly())
.run();
new InlineMethodProcessor(getProject(), method, null, getEditor(), false).run();
Path expectedPath = myDescriptor.getAfterPath().resolve("src/org/jetbrains/" + getTestName(true));
VirtualFile rootAfter = LocalFileSystem.getInstance().findFileByNioFile(expectedPath);

View File

@@ -4,15 +4,19 @@ package com.intellij.java.refactoring.inline;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtil;
import com.intellij.java.refactoring.LightRefactoringTestCase;
import com.intellij.lang.refactoring.InlineActionHandler;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.TestDialog;
import com.intellij.openapi.ui.TestDialogManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.MockInlineMethodOptions;
import com.intellij.refactoring.inline.InlineMethodHandler;
import com.intellij.refactoring.inline.InlineMethodProcessor;
import com.intellij.refactoring.inline.InlineOptions;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -49,7 +53,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
}
public void testSideEffect() { doTest(); }
public void testParamAsAutocloseableRef() { doTest(); }
public void testInlineWithTry() { doTest(); }
@@ -94,7 +98,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testSCR31093() { doTest(); }
public void testSCR37742() { doTest(); }
public void testChainingConstructor() { doTest(); }
public void testChainingConstructor1() {
@@ -121,7 +125,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testEnumConstructor() { doTest(); }
public void testEnumConstantConstructorParameter() { // IDEADEV-26133
doTest();
doTest();
}
public void testEnumConstantConstructorParameterComplex() { // IDEADEV-26133
@@ -180,7 +184,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testRawSubstitution() {
doTest();
}
public void testSubstitution() {
doTest();
}
@@ -200,7 +204,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testSuperMethodInAnonymousClass() {
doTest();
}
public void testInlineAnonymousClassWithPrivateMethodInside() {
doTest();
}
@@ -236,27 +240,27 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testNotAStatement2() {
doTest();
}
public void testNotAStatement3() {
doTest();
}
public void testNotAStatement4() {
doTest();
}
public void testForContinue() {
doTest();
}
public void testSingleReturn1() {
doTestAssertBadReturn();
}
public void testSingleReturn1NotFinal() {
doTestAssertBadReturn();
}
public void testSingleReturn2() {
doTestAssertBadReturn();
}
@@ -269,7 +273,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testMethodReferenceInsideMethodCall() {
doTest();
}
public void testVolatilePassed() {
doTest();
}
@@ -287,7 +291,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
doTest();
fail("Conflict was not detected");
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
catch (BaseRefactoringProcessor.ConflictsInTestsException | CommonRefactoringUtil.RefactoringErrorHintException e) {
assertEquals(conflict, e.getMessage());
}
}
@@ -315,7 +319,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testOneLineLambdaVoidCompatibleOneLine() {
doTestInlineThisOnly();
}
public void testOneLineLambdaValueCompatibleOneLine() {
doTestInlineThisOnly();
}
@@ -329,7 +333,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
}
public void testNonCodeUsage() {
doTest(true);
doTestNonCode();
}
public void testMethodInsideChangeIfStatement() {
@@ -442,7 +446,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testPrivateFieldInSuperClassInSameFile() {
doTest();
}
public void testWidenArgument() {
doTest();
}
@@ -490,7 +494,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testNotTailCallInsideIf() {
doTestAssertBadReturn();
}
public void testConvertToSingleReturnWithFinished() {
doTestAssertBadReturn();
}
@@ -502,7 +506,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testUnusedResult() {
doTest();
}
public void testReuseResultVar() {
doTest();
}
@@ -510,23 +514,23 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testSpecializeClassGetName() {
doTest();
}
public void testSpecializeEnumName() {
doTest();
}
public void testSpecializeEnumValueOf() {
doTest();
}
public void testBooleanModelSimple() {
doTestAssertBadReturn();
}
public void testBooleanModelMultiReturns() {
doTestAssertBadReturn();
}
public void testBooleanModelIfElse() {
doTestAssertBadReturn();
}
@@ -542,11 +546,11 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testBooleanModelFinalCondition() {
doTestAssertBadReturn();
}
public void testInvertMethod() {
doTest();
}
public void testUnusedParameter() {
doTest();
}
@@ -554,19 +558,19 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testEnumStaticMethod() {
doTest();
}
public void testTypeParameterMethodRefArgument() {
doTest();
}
public void testIgnoreReturnValue() {
doTest();
}
public void testSingleReturnComplexQualifier() {
doTestAssertBadReturn();
}
public void testAnonymousCall() { doTest(); }
public void testInSwitchExpression() { doTest(); }
public void testInSwitchExpressionYield() { doTest(); }
@@ -579,15 +583,30 @@ public class InlineMethodTest extends LightRefactoringTestCase {
public void testTernaryBranchCollapsible() { doTest(); }
public void testNewWithSideEffect() { doTest(); }
public void testSplitIfAndCollapseBack() { doTest(); }
public void testThisVariableName() { doTest(); }
public void testRenameLocalClass() { doTest(); }
public void testRenameLocalClassDoubleConflict() { doTest(); }
public void testInlineSingleImplementation() {
TestDialogManager.setTestDialog(TestDialog.YES, getTestRootDisposable());
doTest();
}
public void testInlineSingleImplementationGenericClass() {
TestDialogManager.setTestDialog(TestDialog.YES, getTestRootDisposable());
doTest();
}
public void testInlineSingleImplementationGenericMethod() {
TestDialogManager.setTestDialog(TestDialog.YES, getTestRootDisposable());
BaseRefactoringProcessor.ConflictsInTestsException.withIgnoredConflicts(() -> doTest());
}
@Override
protected Sdk getProjectJDK() {
return getTestName(false).contains("Src") ? IdeaTestUtil.getMockJdk17() : super.getProjectJDK();
@@ -595,12 +614,7 @@ public class InlineMethodTest extends LightRefactoringTestCase {
private void doTestInlineThisOnly() {
@NonNls String fileName = configure();
performAction(new MockInlineMethodOptions(){
@Override
public boolean isInlineThisOnly() {
return true;
}
}, false, false);
performAction(true, false);
checkResultByFile(fileName + ".after");
}
@@ -608,16 +622,29 @@ public class InlineMethodTest extends LightRefactoringTestCase {
doTest(false);
}
private void doTest(final boolean nonCode) {
private void doTest(boolean assertBadReturn) {
String fileName = configure();
InlineActionHandler handler = ContainerUtil.find(InlineActionHandler.EP_NAME.getExtensionList(), ep -> ep instanceof InlineMethodHandler);
assertNotNull(handler);
PsiMethod method = findMethod();
final boolean condition = InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method);
if (assertBadReturn) {
assertTrue("Bad returns not found", condition);
} else {
assertFalse("Bad returns found", condition);
}
handler.inlineElement(getProject(), getEditor(), method);
checkResultByFile(fileName + ".after");
}
private void doTestNonCode() {
@NonNls String fileName = configure();
performAction(nonCode);
performAction(false, true);
checkResultByFile(fileName + ".after");
}
private void doTestAssertBadReturn() {
@NonNls String fileName = configure();
BaseRefactoringProcessor.ConflictsInTestsException.withIgnoredConflicts(() -> performAction(new MockInlineMethodOptions(), false, true));
checkResultByFile(fileName + ".after");
BaseRefactoringProcessor.ConflictsInTestsException.withIgnoredConflicts(() -> doTest(true));
}
@NotNull
@@ -627,32 +654,25 @@ public class InlineMethodTest extends LightRefactoringTestCase {
return fileName;
}
private void performAction(final boolean nonCode) {
performAction(new MockInlineMethodOptions(), nonCode, false);
private void performAction(final boolean inlineThisOnly, final boolean nonCode) {
final PsiReference ref = getFile().findReferenceAt(getEditor().getCaretModel().getOffset());
PsiReferenceExpression refExpr = ref instanceof PsiReferenceExpression ? (PsiReferenceExpression)ref : null;
PsiMethod method = findMethod();
final boolean condition = InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method);
assertFalse("Bad returns found", condition);
final InlineMethodProcessor processor =
new InlineMethodProcessor(getProject(), method, refExpr, getEditor(), inlineThisOnly, nonCode, nonCode, true);
processor.run();
}
private void performAction(final InlineOptions options, final boolean nonCode, final boolean assertBadReturn) {
private PsiMethod findMethod() {
PsiElement element = TargetElementUtil
.findTargetElement(getEditor(), TargetElementUtil.ELEMENT_NAME_ACCEPTED | TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED);
final PsiReference ref = getFile().findReferenceAt(getEditor().getCaretModel().getOffset());
if (ref instanceof PsiJavaCodeReferenceElement) {
final PsiElement parent = ((PsiJavaCodeReferenceElement)ref).getParent();
if (parent instanceof PsiNewExpression) {
element = ((PsiNewExpression)parent).resolveConstructor();
}
if (ref instanceof PsiJavaCodeReferenceElement codeRef && codeRef.getParent() instanceof PsiNewExpression newExpression) {
element = newExpression.resolveConstructor();
}
PsiReferenceExpression refExpr = ref instanceof PsiReferenceExpression ? (PsiReferenceExpression)ref : null;
assertTrue(element instanceof PsiMethod);
PsiMethod method = (PsiMethod)element.getNavigationElement();
final boolean condition = InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method);
if (assertBadReturn) {
assertTrue("Bad returns not found", condition);
} else {
assertFalse("Bad returns found", condition);
}
final InlineMethodProcessor processor =
new InlineMethodProcessor(getProject(), method, refExpr, getEditor(), options.isInlineThisOnly(), nonCode, nonCode,
!options.isKeepTheDeclaration());
processor.run();
return (PsiMethod)element;
}
}

View File

@@ -822,4 +822,6 @@ introduce.variable.message.cannot.extract.in.implicit.class=Cannot extract in im
tooltip.cannot.inline.pattern.variable=Cannot inline pattern variable
inline.popup.highlight=Highlight {0} conflicting {0, choice, 1#write|2#writes}
inline.popup.ignore.conflicts=Ignore writes and continue
inline.warning.variables.used.in.initializer.are.updated=Unsafe Inline: Variables Used in Initializer Are Updated
inline.warning.variables.used.in.initializer.are.updated=Unsafe Inline: Variables Used in Initializer Are Updated
dialog.title.resolving.method.implementation=Resolving Method Implementation
dialog.message.confirmation.to.process.only.implementation=An implementation of abstract method is found:<br><br><b>{0}</b><br><br>Do you want to inline this implementation?

View File

@@ -1,20 +0,0 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.refactoring;
import com.intellij.refactoring.inline.InlineOptions;
public class MockInlineMethodOptions implements InlineOptions {
@Override
public boolean isInlineThisOnly() {
return false;
}
@Override
public void close(int exitCode) {
}
@Override
public boolean isPreviewUsages() {
return false;
}
}