Java: fix inlining of library methods (IDEA-359779)

- only check method body for inaccessible elements
- don't try to optimize imports in method file when method is not modified

GitOrigin-RevId: 27216e8db2306650f638387d6adac6d90099326b
This commit is contained in:
Bas Leijdekkers
2024-10-01 09:31:57 +00:00
committed by intellij-monorepo-bot
parent 834b04f28a
commit c0ca8d8600
2 changed files with 24 additions and 27 deletions
@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.refactoring.inline;
import com.intellij.codeInsight.ChangeContextUtil;
@@ -23,7 +23,6 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.JavaFeature;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.source.javadoc.PsiDocMethodOrFieldRef;
@@ -77,7 +76,6 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
private final Function<PsiReference, InlineTransformer> myTransformerChooser;
private final PsiElementFactory myFactory;
private final JavaCodeStyleManager myJavaCodeStyle;
private final String myDescriptiveName;
private List<CodeBlockSurrounder.SurroundResult> mySurroundResults;
@@ -121,9 +119,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
mySearchForTextOccurrences = searchForTextOccurrences;
myDeleteTheDeclaration = isDeleteTheDeclaration;
PsiManager manager = PsiManager.getInstance(myProject);
myFactory = JavaPsiFacade.getElementFactory(manager.getProject());
myJavaCodeStyle = JavaCodeStyleManager.getInstance(myProject);
myFactory = JavaPsiFacade.getElementFactory(myProject);
myDescriptiveName = DescriptiveNameUtil.getDescriptiveName(myMethod);
}
@@ -229,6 +225,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(
() -> ReadAction.run(() -> {
PsiCodeBlock body = Objects.requireNonNull(myMethod.getBody());
if (!myInlineThisOnly) {
final PsiMethod[] superMethods = myMethod.findSuperMethods();
for (PsiMethod method : superMethods) {
@@ -255,7 +252,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
conflicts.putValue(element, JavaRefactoringBundle.message("inlined.method.will.be.transformed.to.single.return.form"));
}
final String errorMessage = checkUnableToInsertCodeBlock(myMethod.getBody(), element);
final String errorMessage = checkUnableToInsertCodeBlock(body, element);
if (errorMessage != null) {
conflicts.putValue(element, errorMessage);
}
@@ -268,7 +265,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
else if (myReference instanceof PsiMethodReferenceExpression) {
processSideEffectsInMethodReferenceQualifier(conflicts, (PsiMethodReferenceExpression)myReference);
}
addInaccessibleMemberConflicts(myMethod, usagesIn, new ReferencedElementsCollector(), conflicts);
addInaccessibleMemberConflicts(body, usagesIn, new ReferencedElementsCollector(), conflicts);
addInaccessibleSuperCallsConflicts(usagesIn, conflicts);
}),
RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) {
@@ -437,7 +434,7 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
@Override
protected RefactoringEventData getBeforeData() {
final RefactoringEventData data = new RefactoringEventData();
data.addElement(myMethod);
if (myDeleteTheDeclaration) data.addElement(myMethod);
return data;
}
@@ -1,4 +1,4 @@
// 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.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.refactoring.inline;
import com.intellij.JavaTestUtil;
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiMethod;
import com.intellij.refactoring.inline.InlineMethodProcessor;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import java.io.IOException;
@@ -25,16 +26,21 @@ public class InlineLibraryMethodTest extends LightJavaCodeInsightFixtureTestCase
public void testInlineAllInProjectFromLibrary() {
myFixture.addClass("""
package mycompany;
import java.util.*; // unused
public class File {
public static File createTempFile(String pr, String postfix){return createTempFile(pr, postfix, null);}
public static File createTempFile(String pr, String postfix, String base){return new File();}
}""");
@IntrinsicCandidate
public static File createTempFile(String pr, String postfix) { return createTempFile(pr, postfix, null); }
public static File createTempFile(String pr, String postfix, String base) { return new File(); }
}
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.RUNTIME)
@interface IntrinsicCandidate {}""");
@NonNls String fileName = "/refactoring/inlineMethod/" + getTestName(false) + ".java";
myFixture.configureByFile(fileName);
PsiClass fileClass = myFixture.findClass("mycompany.File");
PsiClass libraryClass = myFixture.findClass("mycompany.File");
final PsiFile file = fileClass.getContainingFile();
final PsiFile file = libraryClass.getContainingFile();
WriteCommandAction.runWriteCommandAction(null, () -> {
try {
file.getVirtualFile().setWritable(false);
@@ -44,19 +50,13 @@ public class InlineLibraryMethodTest extends LightJavaCodeInsightFixtureTestCase
}
});
PsiMethod element = null;
PsiMethod[] createTempFiles = fileClass.findMethodsByName("createTempFile", false);
for (PsiMethod createTempFile : createTempFiles) {
if (createTempFile.getParameterList().getParametersCount() == 2) {
element = createTempFile;
break;
}
}
assertNotNull(element);
PsiMethod method = element;
final boolean condition = InlineMethodProcessor.checkBadReturns(method) && !InlineUtil.allUsagesAreTailCalls(method);
PsiMethod[] createTempFiles = libraryClass.findMethodsByName("createTempFile", false);
PsiMethod methodToInline =
ContainerUtil.find(createTempFiles, createTempFile -> createTempFile.getParameterList().getParametersCount() == 2);
assertNotNull(methodToInline);
final boolean condition = InlineMethodProcessor.checkBadReturns(methodToInline) && !InlineUtil.allUsagesAreTailCalls(methodToInline);
assertFalse("Bad returns found", condition);
final InlineMethodProcessor processor = new InlineMethodProcessor(getProject(), method, null, getEditor(), false);
final InlineMethodProcessor processor = new InlineMethodProcessor(getProject(), methodToInline, null, getEditor(), false, false, false, false);
processor.run();
myFixture.checkResultByFile(fileName + ".after");
}