mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-inspection] IDEA-347245 Do not report 'Redundant local variable' when inlining would require a cast
GitOrigin-RevId: 3735bc589a2998c7117d9c9bee62831945869ede
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f6672246e7
commit
b3efd6516e
@@ -469,14 +469,13 @@ public final class InstanceOfUtils {
|
||||
PsiElement block = PsiUtil.getVariableCodeBlock(variable, null);
|
||||
if (block == null) return false;
|
||||
for (PsiReferenceExpression reference : VariableAccessUtils.getVariableReferences(variable, block)) {
|
||||
if (!isVariableTypeChangeSafeForReference(cast, castType, reference)) return false;
|
||||
if (PsiTreeUtil.isAncestor(cast, reference, true)) continue;
|
||||
if (!isVariableTypeChangeSafeForReference(castType, reference)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isVariableTypeChangeSafeForReference(@NotNull PsiTypeCastExpression cast,
|
||||
@NotNull PsiType targetType,
|
||||
@NotNull PsiReferenceExpression reference) {
|
||||
static boolean isVariableTypeChangeSafeForReference(@NotNull PsiType targetType, @NotNull PsiReferenceExpression reference) {
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(reference.getParent());
|
||||
if (PsiUtil.isAccessedForWriting(reference)) {
|
||||
PsiAssignmentExpression assignmentExpression = tryCast(parent, PsiAssignmentExpression.class);
|
||||
@@ -496,11 +495,11 @@ public final class InstanceOfUtils {
|
||||
// Could be always false instanceof which will become compilation error after fix
|
||||
return TypeConversionUtil.areTypesConvertible(targetType, checkType);
|
||||
}
|
||||
if (parent instanceof PsiTypeCastExpression parentCast && parent != cast) {
|
||||
if (parent instanceof PsiTypeCastExpression parentCast) {
|
||||
PsiTypeElement castTypeElement = parentCast.getCastType();
|
||||
if (castTypeElement == null) return false;
|
||||
PsiType castType = castTypeElement.getType();
|
||||
// Another cast could become invalid due to this change
|
||||
// Another replacement could become invalid due to this change
|
||||
return TypeConversionUtil.areTypesConvertible(targetType, castType);
|
||||
}
|
||||
// Some method call can be mis-resolved after update, check this
|
||||
@@ -513,16 +512,18 @@ public final class InstanceOfUtils {
|
||||
PsiTreeUtil.releaseMark(reference, mark);
|
||||
PsiElement refCopy = PsiTreeUtil.releaseMark(callCopy, mark);
|
||||
if (refCopy == null) return false;
|
||||
PsiTypeCastExpression insertedCast = (PsiTypeCastExpression)refCopy.replace(cast);
|
||||
Objects.requireNonNull(insertedCast.getCastType())
|
||||
.replace(JavaPsiFacade.getElementFactory(call.getProject()).createTypeElement(targetType));
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(call.getProject());
|
||||
PsiTypeCastExpression insertedCast = (PsiTypeCastExpression)refCopy.replace(
|
||||
factory.createExpressionFromText("(a)"+reference.getReferenceName(), refCopy));
|
||||
Objects.requireNonNull(insertedCast.getCastType()).replace(factory.createTypeElement(targetType));
|
||||
return callCopy.resolveMethod() == method;
|
||||
}
|
||||
if (parent instanceof PsiReferenceExpression && parent.getParent() instanceof PsiMethodCallExpression call) {
|
||||
PsiMethod method = call.resolveMethod();
|
||||
if (method == null) return false;
|
||||
// private method cannot be called on a subtype qualifier
|
||||
return !method.hasModifierProperty(PsiModifier.PRIVATE);
|
||||
if (parent instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolve = ((PsiReferenceExpression)parent).resolve();
|
||||
// private member cannot be accessed on a subtype qualifier
|
||||
if (resolve instanceof PsiMember member && member.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.pom.java.JavaFeature;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
@@ -493,8 +492,7 @@ public final class VariableAccessUtils {
|
||||
final PsiType variableType = variable.getType();
|
||||
final PsiType initializationType = initialization.getType();
|
||||
final boolean sameType = Comparing.equal(variableType, initializationType);
|
||||
for (PsiReference ref : ReferencesSearch.search(variable, new LocalSearchScope(containingScope))) {
|
||||
final PsiElement refElement = ref.getElement();
|
||||
for (PsiReferenceExpression refElement : getVariableReferences(variable)) {
|
||||
if (finalVariableIntroduction || canCaptureThis) {
|
||||
final PsiElement element = PsiTreeUtil.getParentOfType(refElement, PsiClass.class, PsiLambdaExpression.class);
|
||||
if (element != null && PsiTreeUtil.isAncestor(containingScope, element, true)) {
|
||||
@@ -506,15 +504,8 @@ public final class VariableAccessUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sameType) {
|
||||
final PsiElement parent = refElement.getParent();
|
||||
if (parent instanceof PsiReferenceExpression) {
|
||||
final PsiElement resolve = ((PsiReferenceExpression)parent).resolve();
|
||||
if (resolve instanceof PsiMember &&
|
||||
((PsiMember)resolve).hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!sameType && !InstanceOfUtils.isVariableTypeChangeSafeForReference(initializationType, refElement)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
class Base {
|
||||
{
|
||||
Descendant descendant = new Descendant();
|
||||
consume((Base) descendant);
|
||||
}
|
||||
|
||||
private static void consume(Base value) {}
|
||||
private static void consume(Descendant value) {}
|
||||
}
|
||||
class Descendant extends Base {}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
class Scratch {
|
||||
public static void main(String... arguments) {
|
||||
String <warning descr="Local variable 's' is redundant">s</warning> = arguments[0];
|
||||
Object o = s;
|
||||
use(o);
|
||||
}
|
||||
|
||||
private static void use(Object objectionable) {
|
||||
System.out.println("Objection!");
|
||||
}
|
||||
|
||||
private static void use(String s) {
|
||||
System.out.println("Strings are like ropes. Threads are like fibers");
|
||||
}
|
||||
}
|
||||
+2
@@ -11,6 +11,8 @@ public class UnnecessaryLocalVariableInspectionTest extends LightJavaInspectionT
|
||||
}
|
||||
|
||||
public void testUnnecessaryLocalVariable() { doTest(); }
|
||||
|
||||
public void testCastNecessary() { doTest(); }
|
||||
|
||||
public void testTree() { doTest(); }
|
||||
|
||||
|
||||
@@ -19,6 +19,6 @@ public class InlineVariableFixTest extends IGQuickFixesTestCase {
|
||||
public void testSingleResourceVar() { doTest(); }
|
||||
public void testCastNeeded() { doTest(); }
|
||||
public void testArrayInitializer() { doTest(); }
|
||||
public void testCastForOverloads() { doTest(); }
|
||||
public void testCastForOverloads() { assertQuickfixNotAvailable(); }
|
||||
public void testComment() { doTest(); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user