mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
[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:
committed by
intellij-monorepo-bot
parent
8169859ab9
commit
94f84681ac
@@ -425,10 +425,20 @@ final class ExpressionChecker {
|
||||
void checkConstructorCallProblems(@NotNull PsiMethodCallExpression methodCall) {
|
||||
if (!JavaPsiConstructorUtil.isConstructorCall(methodCall)) return;
|
||||
PsiMethod method = PsiTreeUtil.getParentOfType(methodCall, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
|
||||
if (method == null || !method.isConstructor()) {
|
||||
PsiMethod contextMethod =
|
||||
method != null ? method : PsiTreeUtil.getContextOfType(methodCall, PsiMethod.class, true, PsiClass.class, PsiLambdaExpression.class);
|
||||
if (contextMethod == null || !contextMethod.isConstructor()) {
|
||||
myVisitor.report(JavaErrorKinds.CALL_CONSTRUCTOR_ONLY_ALLOWED_IN_CONSTRUCTOR.create(methodCall));
|
||||
return;
|
||||
}
|
||||
if (JavaPsiRecordUtil.isCompactConstructor(contextMethod) || JavaPsiRecordUtil.isExplicitCanonicalConstructor(contextMethod)) {
|
||||
myVisitor.report(JavaErrorKinds.CALL_CONSTRUCTOR_RECORD_IN_CANONICAL.create(methodCall));
|
||||
return;
|
||||
}
|
||||
if (method == null) {
|
||||
// Do not report other errors for detached constructor call, as they are likely non-relevant
|
||||
return;
|
||||
}
|
||||
PsiMethodCallExpression constructorCall = JavaPsiConstructorUtil.findThisOrSuperCallInConstructor(method);
|
||||
if (constructorCall != methodCall) {
|
||||
myVisitor.report(JavaErrorKinds.CALL_CONSTRUCTOR_DUPLICATE.create(methodCall));
|
||||
@@ -439,10 +449,6 @@ final class ExpressionChecker {
|
||||
myVisitor.report(JavaErrorKinds.CALL_CONSTRUCTOR_MUST_BE_TOP_LEVEL_STATEMENT.create(methodCall));
|
||||
return;
|
||||
}
|
||||
if (JavaPsiRecordUtil.isCompactConstructor(method) || JavaPsiRecordUtil.isExplicitCanonicalConstructor(method)) {
|
||||
myVisitor.report(JavaErrorKinds.CALL_CONSTRUCTOR_RECORD_IN_CANONICAL.create(methodCall));
|
||||
return;
|
||||
}
|
||||
PsiStatement prevStatement = PsiTreeUtil.getPrevSiblingOfType(methodCall.getParent(), PsiStatement.class);
|
||||
if (prevStatement != null) {
|
||||
if (!myVisitor.isApplicable(JavaFeature.STATEMENTS_BEFORE_SUPER)) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -91,6 +91,9 @@ public class PsiEnumConstantImpl extends JavaStubPsiElement<PsiFieldStub> implem
|
||||
@Override
|
||||
public PsiClass getContainingClass() {
|
||||
PsiElement parent = getParent();
|
||||
if (parent instanceof DummyHolder) {
|
||||
parent = parent.getContext();
|
||||
}
|
||||
return parent instanceof PsiClass ? (PsiClass)parent : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import java.util.*;
|
||||
|
||||
class Cast {
|
||||
void test(List<Object> list) {
|
||||
assertThat(list, allOf(hasEntry(""), hasEntry((Object) 1)));
|
||||
}
|
||||
|
||||
interface Matcher<T> {
|
||||
}
|
||||
|
||||
private static native <T> void assertThat(T actual, Matcher<? super T> matcher);
|
||||
|
||||
@SafeVarargs
|
||||
private static native <T> Matcher<T> allOf(Matcher<? super T>... matchers);
|
||||
|
||||
static native <K, V> Matcher<List<? extends V>> hasEntry(V value);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
import java.util.function.Function;
|
||||
|
||||
class Use<T> {
|
||||
abstract static class Super<Value> {}
|
||||
|
||||
static class Obj extends Super {
|
||||
static final Obj INSTANCE = new Obj();
|
||||
}
|
||||
|
||||
<R> R test(Function<Super<T>, R> fn) {
|
||||
Obj instance = Obj.INSTANCE;
|
||||
return fn.apply((Super<T>) instance);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ package com.intellij.java.codeInspection;
|
||||
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.redundantCast.RedundantCastInspection;
|
||||
import com.intellij.idea.TestFor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class RedundantCastInspectionLambdaTest extends LightDaemonAnalyzerTestCase {
|
||||
@@ -43,4 +44,7 @@ public class RedundantCastInspectionLambdaTest extends LightDaemonAnalyzerTestCa
|
||||
public void testSameResolveWithConditionalBranches() { doTest(); }
|
||||
public void testIgnoreMessageFormatCall() { doTest(); }
|
||||
public void testClassCastMethodReference() { doTest(); }
|
||||
|
||||
@TestFor(issues = "IDEA-361212")
|
||||
public void testNestedCallRawInheritance() {doTest();}
|
||||
}
|
||||
@@ -88,4 +88,7 @@ public class RedundantCastInspectionTest extends LightJavaCodeInsightFixtureTest
|
||||
|
||||
@TestFor(issues = "IDEA-370995")
|
||||
public void testNoRedundantCastOnGenericFieldAccess() {doTest();}
|
||||
|
||||
@TestFor(issues = "IDEA-372049")
|
||||
public void testNestedCastInVarargs() {doTest();}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user