[java-inspections] ReplaceWithConstantValueFix: substitute parameter types when necessary

Fixes IDEA-276811 Replace-with-null refactoring is incorrect when generics are involved

GitOrigin-RevId: 5783d19c4c5458ecb3c1e97ed11ff1d78a756793
This commit is contained in:
Tagir Valeev
2022-04-07 13:40:25 +07:00
committed by intellij-monorepo-bot
parent 83e613fa2f
commit 5f0fd1d8e1
5 changed files with 63 additions and 6 deletions

View File

@@ -20,11 +20,9 @@ import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.java.analysis.JavaAnalysisBundle;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpressionList;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.*;
import com.intellij.refactoring.extractMethod.ExtractMethodUtil;
import com.intellij.util.ObjectUtils;
import com.siyeh.ig.psiutils.CommentTracker;
import org.jetbrains.annotations.NotNull;
@@ -61,12 +59,18 @@ public class ReplaceWithConstantValueFix implements LocalQuickFix {
problemElement.getParent().getParent() instanceof PsiMethodCallExpression ?
(PsiMethodCallExpression)problemElement.getParent().getParent() :
null;
PsiMethod targetMethod = call == null ? null : call.resolveMethod();
PsiMethod targetMethod = null;
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
if (call != null) {
JavaResolveResult result = call.resolveMethodGenerics();
substitutor = result.getSubstitutor();
targetMethod = ObjectUtils.tryCast(result.getElement(), PsiMethod.class);
}
new CommentTracker().replaceAndRestoreComments(problemElement, myReplacementText);
if (targetMethod != null) {
ExtractMethodUtil.addCastsToEnsureResolveTarget(targetMethod, call);
ExtractMethodUtil.addCastsToEnsureResolveTarget(targetMethod, substitutor, call);
}
}
}

View File

@@ -96,6 +96,13 @@ public final class ExtractMethodUtil {
public static void addCastsToEnsureResolveTarget(@NotNull final PsiMethod oldTarget, @NotNull final PsiMethodCallExpression call)
throws IncorrectOperationException {
addCastsToEnsureResolveTarget(oldTarget, PsiSubstitutor.EMPTY, call);
}
public static void addCastsToEnsureResolveTarget(@NotNull final PsiMethod oldTarget,
@NotNull PsiSubstitutor oldSubstitutor,
@NotNull final PsiMethodCallExpression call)
throws IncorrectOperationException {
final PsiMethod newTarget = call.resolveMethod();
final PsiManager manager = oldTarget.getManager();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(manager.getProject());
@@ -107,6 +114,7 @@ public final class ExtractMethodUtil {
for (int i = 0; i < args.length; i++) {
PsiExpression arg = args[i];
PsiType paramType = i < oldParameters.length ? oldParameters[i].getType() : oldParameters[oldParameters.length - 1].getType();
paramType = oldSubstitutor.substitute(paramType);
final PsiTypeCastExpression cast = (PsiTypeCastExpression)factory.createExpressionFromText("(a)b", null);
final PsiTypeElement typeElement = cast.getCastType();
assert typeElement != null;

View File

@@ -0,0 +1,9 @@
// "Replace with 'null'" "true"
import java.util.stream.*;
class Test {
public static void method() {
Object obj = null;
Stream<Object> stream = Stream.of((Object) null);
}
}

View File

@@ -0,0 +1,9 @@
// "Replace with 'null'" "true"
import java.util.stream.*;
class Test {
public static void method() {
Object obj = null;
Stream<Object> stream = Stream.of(<caret>obj);
}
}

View File

@@ -0,0 +1,27 @@
// 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.
package com.intellij.java.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
import com.intellij.testFramework.LightProjectDescriptor;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
public class ReplaceWithConstantValueFixTest extends LightQuickFixParameterizedTestCase {
@Override
protected LocalInspectionTool @NotNull [] configureLocalInspectionTools() {
return new LocalInspectionTool[]{new DataFlowInspection()};
}
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return LightJavaCodeInsightFixtureTestCase.JAVA_17;
}
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/replaceWithConstantValue";
}
}