[java-inspections] Redundant cast: do not report if there's a change in compilation errors within the parents

Fixes IDEA-372049 Erroneous RedundantCast inspection on varargs with nested calls
Fixes IDEA-361212 Redundant cast false positive: method call type changes

GitOrigin-RevId: d999fccd9a491445502e48bbab3f0b828ca98f6a
This commit is contained in:
Tagir Valeev
2025-06-16 18:32:39 +02:00
committed by intellij-monorepo-bot
parent 8169859ab9
commit 94f84681ac
7 changed files with 76 additions and 25 deletions

View File

@@ -5,6 +5,8 @@ import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.daemon.impl.analysis.JavaGenericsUtil;
import com.intellij.java.codeserver.core.JavaPsiSwitchUtil;
import com.intellij.java.codeserver.highlighting.JavaErrorCollector;
import com.intellij.java.codeserver.highlighting.errors.JavaCompilationError;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Comparing;
@@ -412,7 +414,7 @@ public final class RedundantCastUtil {
if (operand != null) {
newBranchExpression = (PsiExpression)newBranchExpression.replace(operand);
JavaResolveResult oldResult = oldCall.resolveMethodGenerics();
JavaResolveResult newResult = resolveNewResult(oldCall, newCall);
JavaResolveResult newResult = newCall.resolveMethodGenerics();
if (isSameResolveResult(oldResult, newResult)) {
addToResults((PsiTypeCastExpression)oldBranchExpression);
@@ -499,7 +501,7 @@ public final class RedundantCastUtil {
return;
}
PsiExpression strippedCast = (PsiExpression)newReturnExpression.replace(castOperand);
PsiType newArgType = calculateNewArgType(i, resolveNewResult(oldCall, newCall), parameters);
PsiType newArgType = calculateNewArgType(i, newCall.resolveMethodGenerics(), parameters);
final PsiType functionalInterfaceType = newLambdaExpression.getGroundTargetType(newArgType);
if (originalFunctionalInterfaceType.equals(functionalInterfaceType)) {
final PsiType castExprType = LambdaUtil.performWithTargetType(newLambdaExpression, functionalInterfaceType, () -> strippedCast.getType());
@@ -522,10 +524,14 @@ public final class RedundantCastUtil {
PsiExpression castOperand = ((PsiTypeCastExpression)Objects.requireNonNull(deparenthesizeExpression(newArgs[i]))).getOperand();
if (castOperand == null) return;
newArgs[i] = (PsiExpression)newArgs[i].replace(castOperand);
if (!errorsMatch(newCall, oldCall)) {
newArgs[i].replace(arg);
return;
}
JavaResolveResult oldResult = oldCall.resolveMethodGenerics();
final JavaResolveResult newResult = resolveNewResult(oldCall, newCall);
JavaResolveResult newResult = newCall.resolveMethodGenerics();
PsiMethod oldMethod = (PsiMethod)oldResult.getElement();
LOG.assertTrue(oldMethod != null);
@@ -565,6 +571,20 @@ public final class RedundantCastUtil {
newArgs[i].replace(arg);
}
private static boolean errorsMatch(PsiElement updated, PsiElement original) {
while (!(updated instanceof PsiFile)) {
JavaCompilationError<?, ?> updatedError = JavaErrorCollector.findSingleError(updated);
JavaCompilationError<?, ?> originalError = JavaErrorCollector.findSingleError(original);
if ((updatedError == null) != (originalError == null)) return false;
if (updatedError != null) {
if (updatedError.kind() != originalError.kind()) return false;
}
updated = updated.getParent();
original = original.getParent();
}
return true;
}
private static @Nullable PsiType calculateNewArgType(int i, JavaResolveResult newResult, PsiParameter[] parameters) {
final boolean varargs = newResult instanceof MethodCandidateInfo info && info.isVarargs();
final PsiType parameterType = PsiTypesUtil.getParameterType(parameters, i, varargs);
@@ -576,22 +596,6 @@ public final class RedundantCastUtil {
return newArgType;
}
private static @NotNull JavaResolveResult resolveNewResult(PsiCall oldCall, PsiCall newCall) {
final JavaResolveResult newResult;
if (newCall instanceof PsiEnumConstant) {
// do this manually, because PsiEnumConstantImpl.resolveMethodGenerics() will assert (no containing class for the copy)
final PsiEnumConstant enumConstant = (PsiEnumConstant)oldCall;
PsiClass containingClass = enumConstant.getContainingClass();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(enumConstant.getProject());
final PsiClassType type = facade.getElementFactory().createType(Objects.requireNonNull(containingClass));
newResult = facade.getResolveHelper().resolveConstructor(type, Objects.requireNonNull(newCall.getArgumentList()), enumConstant);
}
else {
newResult = newCall.resolveMethodGenerics();
}
return newResult;
}
private static @Nullable PsiCall copyCallExpression(PsiCall expression, PsiType typeByParent) {
PsiElement encoded = null;
try {