ExpressionUtils#getQualifierOrThis -> getEffectiveQualifier, nullable now (cannot construct this expression for outer anonymous class)

Fixes EA-140652 - assert: JavaParserUtil.parseFragment
This commit is contained in:
Tagir Valeev
2019-04-18 13:03:27 +07:00
parent cd1bfec129
commit 9e1982a819
27 changed files with 217 additions and 83 deletions

View File

@@ -251,7 +251,7 @@ public class JavaMethodContractUtil {
ContractReturnValue returnValue = getNonFailingReturnValue(contracts);
if (returnValue == null) return null;
if (returnValue.equals(ContractReturnValue.returnThis())) {
return ExpressionUtils.getQualifierOrThis(call.getMethodExpression());
return ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
}
if (returnValue instanceof ContractReturnValue.ParameterReturnValue) {
int number = ((ContractReturnValue.ParameterReturnValue)returnValue).getParameterNumber();

View File

@@ -55,7 +55,13 @@ public class MutationSignature {
StreamEx<PsiExpression> elements =
IntStreamEx.range(Math.min(myParameters.length, MethodCallUtils.isVarArgCall(call) ? args.length - 1 : args.length))
.filter(idx -> myParameters[idx]).elements(args);
return myThis ? elements.prepend(ExpressionUtils.getQualifierOrThis(call.getMethodExpression())) : elements;
if (myThis) {
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
if (qualifier != null) {
return elements.prepend(qualifier);
}
}
return elements;
}
/**

View File

@@ -235,8 +235,9 @@ public abstract class DeprecationInspectionBase extends LocalInspectionTool {
PsiExpression qualifierExpression = call.getMethodExpression().getQualifierExpression();
qualifierText = qualifierExpression == null ? "" : qualifierExpression.getText() + ".";
PsiType qualifierType = ExpressionUtils.getQualifierOrThis(call.getMethodExpression()).getType();
PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
if (qualifier == null) return false;
PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifier.getType());
if (qualifierClass == null) return false;
PsiClass suggestedClass = suggestedReplacement.getContainingClass();
if (suggestedClass == null || !InheritanceUtil.isInheritorOrSelf(qualifierClass, suggestedClass, true)) return false;

View File

@@ -154,8 +154,11 @@ public class OptionalIsPresentInspection extends AbstractBaseJavaLocalInspection
PsiMethodCallExpression call = (PsiMethodCallExpression)element;
if (!call.getArgumentList().isEmpty()) return false;
PsiReferenceExpression methodExpression = call.getMethodExpression();
return "get".equals(methodExpression.getReferenceName()) &&
areElementsEquivalent(ExpressionUtils.getQualifierOrThis(methodExpression), optionalRef);
if ("get".equals(methodExpression.getReferenceName())) {
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(methodExpression);
return qualifier != null && areElementsEquivalent(qualifier, optionalRef);
}
return false;
}
@NotNull

View File

@@ -103,7 +103,7 @@ public class OverwrittenKeyInspection extends AbstractBaseJavaLocalInspectionToo
PsiExpression arg = call.getArgumentList().getExpressions()[0];
Object key = getKey(arg);
if (key == null) return statement;
PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getQualifierOrThis(call.getMethodExpression()));
PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getEffectiveQualifier(call.getMethodExpression()));
if (qualifier == null) return statement;
PsiVariable qualifierVar =
qualifier instanceof PsiReferenceExpression ? tryCast(((PsiReferenceExpression)qualifier).resolve(), PsiVariable.class) : null;
@@ -116,7 +116,7 @@ public class OverwrittenKeyInspection extends AbstractBaseJavaLocalInspectionToo
PsiMethodCallExpression nextCall = tryCast(nextStatement.getExpression(), PsiMethodCallExpression.class);
if (!myMatcher.test(nextCall)) break;
PsiExpression nextQualifier =
PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getQualifierOrThis(nextCall.getMethodExpression()));
PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getEffectiveQualifier(nextCall.getMethodExpression()));
if (nextQualifier == null || !PsiEquivalenceUtil.areElementsEquivalent(qualifier, nextQualifier)) break;
if (qualifierVar != null && VariableAccessUtils.variableIsUsed(qualifierVar, nextCall.getArgumentList())) break;
PsiExpression nextArg = nextCall.getArgumentList().getExpressions()[0];

View File

@@ -469,7 +469,7 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
public PsiElement simplify(PsiMethodCallExpression streamMethodCall) {
PsiMethodCallExpression collectionStreamCall = getQualifierMethodCall(streamMethodCall);
if (collectionStreamCall == null) return null;
PsiExpression collectionExpression = collectionStreamCall.getMethodExpression().getQualifierExpression();
PsiExpression collectionExpression = ExpressionUtils.getEffectiveQualifier(collectionStreamCall.getMethodExpression());
if (collectionExpression == null) return null;
collectionStreamCall.replace(collectionExpression);
ExpressionUtils.bindCallTo(streamMethodCall, myReplacementMethod);
@@ -479,6 +479,7 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
static CallHandler<CallChainSimplification> handler() {
return CallHandler.of(STREAM_FOR_EACH, call -> {
PsiMethodCallExpression qualifierCall = getQualifierMethodCall(call);
if (qualifierCall == null || ExpressionUtils.getEffectiveQualifier(qualifierCall.getMethodExpression()) == null) return null;
if (COLLECTION_STREAM.test(qualifierCall)) {
return new ReplaceForEachMethodFix(call.getMethodExpression().getReferenceName(), FOR_EACH_METHOD, true);
}
@@ -1803,7 +1804,8 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
argList = StreamEx.of(args, 1, args.length - 1).map(ct::text).joining();
}
else if (COLLECTION_STREAM.matches(qualifier)) {
PsiExpression collection = ExpressionUtils.getQualifierOrThis(qualifier.getMethodExpression());
PsiExpression collection = ExpressionUtils.getEffectiveQualifier(qualifier.getMethodExpression());
if (collection == null) return null;
argList = ct.text(collection);
}
else {
@@ -1821,7 +1823,8 @@ public class SimplifyStreamApiCallChainsInspection extends AbstractBaseJavaLocal
if (extractDelimiter(call) == null) return null;
PsiMethodCallExpression qualifier = getQualifierMethodCall(call);
if (qualifier == null) return null;
if (ARRAYS_STREAM.matches(qualifier) || COLLECTION_STREAM.matches(qualifier)) {
if (ARRAYS_STREAM.matches(qualifier) ||
(COLLECTION_STREAM.matches(qualifier) && ExpressionUtils.getEffectiveQualifier(qualifier.getMethodExpression()) != null)) {
PsiType elementType = StreamApiUtil.getStreamElementType(qualifier.getType());
if (InheritanceUtil.isInheritor(elementType, "java.lang.CharSequence")) {
return new JoiningStringsFix();

View File

@@ -146,13 +146,13 @@ public class UseBulkOperationInspection extends AbstractBaseJavaLocalInspectionT
PsiMethodCallExpression parentCall = (PsiMethodCallExpression)parent;
PsiExpression parentQualifier = PsiUtil.skipParenthesizedExprDown(parentCall.getMethodExpression().getQualifierExpression());
if (MethodCallUtils.isCallToMethod(parentCall, CommonClassNames.JAVA_LANG_ITERABLE, null, "forEach", new PsiType[]{null})) {
return ExpressionUtils.getQualifierOrThis(parentCall.getMethodExpression());
return ExpressionUtils.getEffectiveQualifier(parentCall.getMethodExpression());
}
if (MethodCallUtils.isCallToMethod(parentCall, CommonClassNames.JAVA_UTIL_STREAM_STREAM, null, FOR_EACH_METHOD, new PsiType[]{null}) &&
parentQualifier instanceof PsiMethodCallExpression) {
PsiMethodCallExpression grandParentCall = (PsiMethodCallExpression)parentQualifier;
if (MethodCallUtils.isCallToMethod(grandParentCall, CommonClassNames.JAVA_UTIL_COLLECTION, null, "stream", PsiType.EMPTY_ARRAY)) {
return ExpressionUtils.getQualifierOrThis(grandParentCall.getMethodExpression());
return ExpressionUtils.getEffectiveQualifier(grandParentCall.getMethodExpression());
}
PsiExpression[] grandParentArgs = grandParentCall.getArgumentList().getExpressions();
if (grandParentArgs.length == 1) {
@@ -200,7 +200,7 @@ public class UseBulkOperationInspection extends AbstractBaseJavaLocalInspectionT
private void register(@NotNull PsiExpression iterable,
@NotNull BulkMethodInfo info,
@NotNull PsiReferenceExpression methodExpression) {
PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getQualifierOrThis(methodExpression));
PsiExpression qualifier = PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getEffectiveQualifier(methodExpression));
if (qualifier instanceof PsiThisExpression) {
PsiMethod method = PsiTreeUtil.getParentOfType(iterable, PsiMethod.class);
// Likely we are inside of the bulk method implementation
@@ -250,7 +250,8 @@ public class UseBulkOperationInspection extends AbstractBaseJavaLocalInspectionT
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getStartElement();
if (!(element instanceof PsiReferenceExpression)) return;
PsiExpression qualifier = ExpressionUtils.getQualifierOrThis((PsiReferenceExpression)element);
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier((PsiReferenceExpression)element);
if (qualifier == null) return;
PsiExpression iterable;
if (element instanceof PsiMethodReferenceExpression) {
iterable = findIterableForFunction((PsiFunctionalExpression)element);

View File

@@ -83,7 +83,8 @@ abstract class SourceOperation extends Operation {
return fn == null ? null : new IterateSource(args[0], fn);
}
if (name.equals("stream") && args.length == 0 &&
InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_COLLECTION)) {
InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_COLLECTION) &&
ExpressionUtils.getEffectiveQualifier(call.getMethodExpression()) != null) {
return new ForEachSource(call.getMethodExpression().getQualifierExpression());
}
if (name.equals("stream") && args.length == 1 &&
@@ -148,7 +149,8 @@ abstract class SourceOperation extends Operation {
@Override
public String wrap(StreamVariable outVar, String code, StreamToLoopReplacementContext context) {
PsiExpression iterationParameter = myQualifier == null ? ExpressionUtils
.getQualifierOrThis(((PsiMethodCallExpression)context.createExpression("stream()")).getMethodExpression()) : myQualifier;
.getEffectiveQualifier(((PsiMethodCallExpression)context.createExpression("stream()")).getMethodExpression()) : myQualifier;
assert iterationParameter != null; // Checked at construction site that effective qualifier is available
String iterationParameterText = iterationParameter.getText() + (myEntrySet ? ".entrySet()" : "");
return context.getLoopLabel() + "for(" + outVar.getDeclaration() + ": " + iterationParameterText + ") {" + code + "}\n";
}

View File

@@ -1,7 +1,6 @@
// "Replace Stream API chain with loop" "true"
// "Fix all 'Stream API call chain can be replaced with loop' problems in file" "true"
import java.util.Arrays;
import java.util.List;
import java.util.*;
public class Main {
private static void test(List<String> list) {
@@ -15,4 +14,29 @@ public class Main {
public static void main(String[] args) {
test(Arrays.asList("a", "b", "xyz"));
}
void testLocal() {
class X extends ArrayList<String> {
class Y {
void test() {
for (String s : X.this) {
System.out.println(s);
}
}
}
}
}
void testAnonymous() {
new ArrayList<String>() {
class Y {
void test() {
for (Iterator<String> it = stream().iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}
}
}
};
}
}

View File

@@ -1,7 +1,6 @@
// "Replace Stream API chain with loop" "true"
// "Fix all 'Stream API call chain can be replaced with loop' problems in file" "true"
import java.util.Arrays;
import java.util.List;
import java.util.*;
public class Main {
private static void test(List<String> list) {
@@ -11,4 +10,24 @@ public class Main {
public static void main(String[] args) {
test(Arrays.asList("a", "b", "xyz"));
}
void testLocal() {
class X extends ArrayList<String> {
class Y {
void test() {
stream().forEach(System.out::println);
}
}
}
}
void testAnonymous() {
new ArrayList<String>() {
class Y {
void test() {
stream().forEach(System.out::println);
}
}
};
}
}

View File

@@ -0,0 +1,17 @@
// "Replace 'stream().forEach()' with 'forEach()' (may change semantics)" "true"
import java.util.ArrayList;
class Test {
void foo() {
class X extends ArrayList<String> {
class Y {
{
X.this.forEach(System.out::println);
}
void forEach(Object obj) {}
}
}
}
}

View File

@@ -0,0 +1,18 @@
// "Replace 'stream().forEach()' with 'forEach()' (may change semantics)" "false"
import java.util.ArrayList;
class Test {
void foo() {
new ArrayList<String>() {
class Y {
{
// Impossible to qualify forEach() call
stream().fo<caret>rEach(System.out::println);
}
void forEach(Object obj) {}
}
}
}
}

View File

@@ -0,0 +1,17 @@
// "Replace 'stream().forEach()' with 'forEach()' (may change semantics)" "true"
import java.util.ArrayList;
class Test {
void foo() {
class X extends ArrayList<String> {
class Y {
{
stream().fo<caret>rEach(System.out::println);
}
void forEach(Object obj) {}
}
}
}
}

View File

@@ -53,8 +53,8 @@ public class InstanceofThisInspection extends BaseInspection {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression call) {
if (OBJECT_GET_CLASS.test(call)) {
PsiExpression qualifier = ExpressionUtils.getQualifierOrThis(call.getMethodExpression());
if (StreamEx.of(ExpressionUtils.nonStructuralChildren(qualifier)).select(PsiThisExpression.class)
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
if (qualifier != null && StreamEx.of(ExpressionUtils.nonStructuralChildren(qualifier)).select(PsiThisExpression.class)
.anyMatch(thisExpression -> thisExpression.getQualifier() == null)) {
PsiExpression compared = ExpressionUtils.getExpressionComparedTo(call);
if (compared instanceof PsiClassObjectAccessExpression) {

View File

@@ -56,7 +56,7 @@ abstract class BaseEqualsVisitor extends BaseInspectionVisitor {
final PsiExpression expression1;
final PsiExpression expression2;
if (OBJECT_EQUALS.test(expression)) {
expression1 = PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getQualifierOrThis(expression.getMethodExpression()));
expression1 = PsiUtil.skipParenthesizedExprDown(ExpressionUtils.getEffectiveQualifier(expression.getMethodExpression()));
expression2 = PsiUtil.skipParenthesizedExprDown(arguments[0]);
}
else if (STATIC_EQUALS.test(expression)) {

View File

@@ -17,10 +17,7 @@ package com.siyeh.ig.fixes;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiReferenceExpression;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.InspectionGadgetsBundle;
@@ -75,7 +72,8 @@ public class AddThisQualifierFix extends InspectionGadgetsFix {
if (expression.getQualifierExpression() != null) {
return;
}
final PsiExpression thisQualifier = ExpressionUtils.getQualifierOrThis(expression);
final PsiExpression thisQualifier = ExpressionUtils.getEffectiveQualifier(expression);
if (!(thisQualifier instanceof PsiThisExpression)) return;
CommentTracker commentTracker = new CommentTracker();
@NonNls final String newExpression = commentTracker.text(thisQualifier) + "." + commentTracker.text(expression);
PsiReplacementUtil.replaceExpressionAndShorten(expression, newExpression, commentTracker);

View File

@@ -283,7 +283,8 @@ public class ManualArrayToCollectionCopyInspection extends BaseInspection {
final PsiExpression expression = PsiUtil.skipParenthesizedExprDown(((PsiExpressionStatement)body).getExpression());
if (!(expression instanceof PsiMethodCallExpression)) return null;
final PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
return ExpressionUtils.getQualifierOrThis(call.getMethodExpression()).getText();
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
return qualifier != null ? qualifier.getText() : null;
}
@Nullable

View File

@@ -259,10 +259,10 @@ public class StringConcatenationInLoopsInspection extends BaseInspection {
PsiExpression otherQualifier = other.getQualifierExpression();
if (qualifier == null && otherQualifier == null) return true;
if (qualifier == null && ref.resolve() instanceof PsiField) {
qualifier = ExpressionUtils.getQualifierOrThis(ref);
qualifier = ExpressionUtils.getEffectiveQualifier(ref);
}
if (otherQualifier == null && other.resolve() instanceof PsiField) {
otherQualifier = ExpressionUtils.getQualifierOrThis(other);
otherQualifier = ExpressionUtils.getEffectiveQualifier(other);
}
if (qualifier == null || otherQualifier == null) return false;
if (qualifier instanceof PsiReferenceExpression) {

View File

@@ -276,15 +276,15 @@ public class CollectionUtils {
if (sizeQualifier == null) return false;
sizeQualifier = getBaseCollection(sizeQualifier);
collection = getBaseCollection(collection);
return PsiEquivalenceUtil.areElementsEquivalent(sizeQualifier, collection);
return sizeQualifier != null && collection != null && PsiEquivalenceUtil.areElementsEquivalent(sizeQualifier, collection);
}
private static @NotNull PsiExpression getBaseCollection(@NotNull PsiExpression derivedCollection) {
private static @Nullable PsiExpression getBaseCollection(@NotNull PsiExpression derivedCollection) {
while(true) {
PsiMethodCallExpression derivedCall =
ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(derivedCollection), PsiMethodCallExpression.class);
if (DERIVED_COLLECTION.test(derivedCall)) {
derivedCollection = ExpressionUtils.getQualifierOrThis(derivedCall.getMethodExpression());
derivedCollection = ExpressionUtils.getEffectiveQualifier(derivedCall.getMethodExpression());
}
else {
return derivedCollection;

View File

@@ -15,7 +15,6 @@ import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.ig.callMatcher.CallMatcher;
@@ -917,41 +916,48 @@ public class ExpressionUtils {
}
/**
* Returns a qualifier for reference or creates a corresponding {@link PsiThisExpression} statement if
* a qualifier is null
* Returns an effective qualifier for a reference. If qualifier is not specified, then tries to construct it
* e.g. creating a corresponding {@link PsiThisExpression}.
*
* @param ref a reference expression to get a qualifier from
* @return a qualifier or created (non-physical) {@link PsiThisExpression}.
* @param ref a reference expression to get an effective qualifier for
* @return a qualifier or created (non-physical) {@link PsiThisExpression}.
* May return null if reference points to local or member of anonymous class referred from inner class
*/
@NotNull
public static PsiExpression getQualifierOrThis(@NotNull PsiReferenceExpression ref) {
@Nullable
public static PsiExpression getEffectiveQualifier(@NotNull PsiReferenceExpression ref) {
PsiExpression qualifier = ref.getQualifierExpression();
if (qualifier != null) return qualifier;
PsiElementFactory factory = JavaPsiFacade.getElementFactory(ref.getProject());
PsiMember member = tryCast(ref.resolve(), PsiMember.class);
if (member != null) {
PsiClass memberClass = member.getContainingClass();
if (memberClass != null) {
PsiClass containingClass = ClassUtils.getContainingClass(ref);
if (containingClass == null) {
containingClass = PsiTreeUtil.getContextOfType(ref, PsiClass.class);
}
if (!InheritanceUtil.isInheritorOrSelf(containingClass, memberClass, true)) {
if (member == null) {
// Reference resolves to non-member: probably variable/parameter/etc.
return null;
}
PsiClass memberClass = member.getContainingClass();
if (memberClass != null) {
PsiClass containingClass = ClassUtils.getContainingClass(ref);
if (containingClass == null) {
containingClass = PsiTreeUtil.getContextOfType(ref, PsiClass.class);
}
if (containingClass != null && member.hasModifierProperty(PsiModifier.STATIC)) {
return factory.createReferenceExpression(containingClass);
}
if (!InheritanceUtil.isInheritorOrSelf(containingClass, memberClass, true)) {
containingClass = ClassUtils.getContainingClass(containingClass);
while (containingClass != null && !InheritanceUtil.isInheritorOrSelf(containingClass, memberClass, true)) {
containingClass = ClassUtils.getContainingClass(containingClass);
while (containingClass != null && !InheritanceUtil.isInheritorOrSelf(containingClass, memberClass, true)) {
containingClass = ClassUtils.getContainingClass(containingClass);
}
if (containingClass != null) {
String thisQualifier = containingClass.getQualifiedName();
if (thisQualifier == null) {
if (PsiUtil.isLocalClass(containingClass)) {
thisQualifier = containingClass.getName();
} else {
throw new IncorrectOperationException("Anonymous surrounding class");
}
}
if (containingClass != null) {
String thisQualifier = containingClass.getQualifiedName();
if (thisQualifier == null) {
if (PsiUtil.isLocalClass(containingClass)) {
thisQualifier = containingClass.getName();
} else {
// Cannot qualify anonymous class
return null;
}
return factory.createExpressionFromText(thisQualifier + "." + PsiKeyword.THIS, ref);
}
return factory.createExpressionFromText(thisQualifier + "." + PsiKeyword.THIS, ref);
}
}
}

View File

@@ -93,7 +93,10 @@ public abstract class IndexedContainer {
if (expression instanceof PsiMethodCallExpression) {
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
if (ListIndexedContainer.isSizeCall(call)) {
return new ListIndexedContainer(ExpressionUtils.getQualifierOrThis(call.getMethodExpression()));
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
if (qualifier != null) {
return new ListIndexedContainer(qualifier);
}
}
}
return null;
@@ -148,7 +151,7 @@ public abstract class IndexedContainer {
@Override
public boolean isGetMethodReference(PsiMethodReferenceExpression methodReference) {
if (!"get".equals(methodReference.getReferenceName())) return false;
if (!isQualifierEquivalent(ExpressionUtils.getQualifierOrThis(methodReference))) return false;
if (!isQualifierEquivalent(ExpressionUtils.getEffectiveQualifier(methodReference))) return false;
PsiMethod method = ObjectUtils.tryCast(methodReference.resolve(), PsiMethod.class);
return method != null && MethodUtils.methodMatches(method, CommonClassNames.JAVA_UTIL_LIST, null, "get", PsiType.INT);
}
@@ -173,7 +176,7 @@ public abstract class IndexedContainer {
PsiMethodCallExpression call = ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(expression), PsiMethodCallExpression.class);
if (call == null) return null;
PsiExpression[] args = call.getArgumentList().getExpressions();
if (args.length == 1 && isGetCall(call) && isQualifierEquivalent(ExpressionUtils.getQualifierOrThis(call.getMethodExpression()))) {
if (args.length == 1 && isGetCall(call) && isQualifierEquivalent(ExpressionUtils.getEffectiveQualifier(call.getMethodExpression()))) {
return args[0];
}
return null;

View File

@@ -80,7 +80,12 @@ public class UnnecessaryToStringCallInspection extends BaseInspection implements
ObjectUtils.tryCast(descriptor.getPsiElement().getParent().getParent(), PsiMethodCallExpression.class);
if (!isRedundantToString(call)) return;
final PsiReferenceExpression methodExpression = call.getMethodExpression();
final PsiExpression qualifier = ExpressionUtils.getQualifierOrThis(methodExpression);
final PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(methodExpression);
if (qualifier == null) {
// Should not happen normally as toString() should always resolve to the innermost class
// Probably may happen only if SDK is broken (e.g. no java.lang.Object found)
return;
}
new CommentTracker().replaceAndRestoreComments(call, qualifier);
}
}
@@ -98,8 +103,9 @@ public class UnnecessaryToStringCallInspection extends BaseInspection implements
final PsiReferenceExpression methodExpression = call.getMethodExpression();
PsiElement referenceNameElement = methodExpression.getReferenceNameElement();
if (referenceNameElement == null) return;
registerError(referenceNameElement, ProblemHighlightType.LIKE_UNUSED_SYMBOL,
ExpressionUtils.getQualifierOrThis(methodExpression).getText());
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(methodExpression);
if (qualifier == null) return;
registerError(referenceNameElement, ProblemHighlightType.LIKE_UNUSED_SYMBOL, qualifier.getText());
}
}
@@ -109,8 +115,8 @@ public class UnnecessaryToStringCallInspection extends BaseInspection implements
PsiReferenceExpression methodExpression = call.getMethodExpression();
@NonNls final String referenceName = methodExpression.getReferenceName();
if (!"toString".equals(referenceName) || !call.getArgumentList().isEmpty()) return false;
final PsiExpression qualifier = ExpressionUtils.getQualifierOrThis(methodExpression);
if (qualifier.getType() instanceof PsiArrayType) {
final PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(methodExpression);
if (qualifier == null || qualifier.getType() instanceof PsiArrayType) {
// do not warn on nonsensical code
return false;
}

View File

@@ -26,7 +26,8 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import static com.intellij.util.ObjectUtils.tryCast;
import static com.siyeh.ig.psiutils.ParenthesesUtils.*;
import static com.siyeh.ig.psiutils.ParenthesesUtils.getParentSkipParentheses;
import static com.siyeh.ig.psiutils.ParenthesesUtils.stripParentheses;
public class ForCanBeForeachInspection extends BaseInspection {
@SuppressWarnings("PublicField")
@@ -237,8 +238,8 @@ public class ForCanBeForeachInspection extends BaseInspection {
if (!HardcodedMethodConstants.ITERATOR.equals(initialCallName) && !"listIterator".equals(initialCallName)) {
return null;
}
final PsiExpression qualifier = ExpressionUtils.getQualifierOrThis(initialMethodExpression);
if (qualifier instanceof PsiSuperExpression) {
final PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(initialMethodExpression);
if (qualifier == null || qualifier instanceof PsiSuperExpression) {
return null;
}
final PsiType qualifierType = qualifier.getType();
@@ -609,7 +610,13 @@ public class ForCanBeForeachInspection extends BaseInspection {
qualifier = ((PsiReferenceExpression)qualifier).getQualifierExpression();
}
final PsiVariable target = resolveHelper.resolveReferencedVariable(text, context);
return variable != target ? ExpressionUtils.getQualifierOrThis(reference).getText() + "." + text : text;
if (variable != target) {
PsiExpression effectiveQualifier = ExpressionUtils.getEffectiveQualifier(reference);
if (effectiveQualifier != null) {
return effectiveQualifier.getText() + "." + text;
}
}
return text;
}
private static class IteratorNextVisitor extends JavaRecursiveElementWalkingVisitor {
@@ -931,7 +938,7 @@ public class ForCanBeForeachInspection extends BaseInspection {
return;
}
final PsiReferenceExpression listLengthExpression = methodCallExpression.getMethodExpression();
final PsiExpression qualifier = stripParentheses(ExpressionUtils.getQualifierOrThis(listLengthExpression));
final PsiExpression qualifier = stripParentheses(ExpressionUtils.getEffectiveQualifier(listLengthExpression));
if (qualifier == null) {
return;
}
@@ -1071,7 +1078,7 @@ public class ForCanBeForeachInspection extends BaseInspection {
return;
}
final PsiReferenceExpression methodExpression = initializer.getMethodExpression();
final PsiExpression collection = stripParentheses(ExpressionUtils.getQualifierOrThis(methodExpression));
final PsiExpression collection = stripParentheses(ExpressionUtils.getEffectiveQualifier(methodExpression));
if (collection == null) {
return;
}

View File

@@ -120,7 +120,7 @@ public class WhileCanBeForeachInspection extends BaseInspection {
return;
}
final PsiReferenceExpression methodExpression = initializer.getMethodExpression();
final PsiExpression collection = ParenthesesUtils.stripParentheses(ExpressionUtils.getQualifierOrThis(methodExpression));
final PsiExpression collection = ParenthesesUtils.stripParentheses(ExpressionUtils.getEffectiveQualifier(methodExpression));
if (collection == null) {
return;
}

View File

@@ -278,7 +278,8 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiMethodCallExpression call = PsiTreeUtil.getNonStrictParentOfType(descriptor.getStartElement(), PsiMethodCallExpression.class);
if (call == null) return;
PsiExpression qualifier = ExpressionUtils.getQualifierOrThis(call.getMethodExpression());
PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
if (qualifier == null) return;
CommentTracker ct = new CommentTracker();
switch (myFixType) {
case REPLACE_WITH_QUALIFIER: {

View File

@@ -55,7 +55,7 @@ public class FlipCommutativeMethodCallIntention extends MutablyNamedIntention {
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression argument = argumentList.getExpressions()[0];
final PsiReferenceExpression methodExpression = expression.getMethodExpression();
final PsiExpression qualifier = ExpressionUtils.getQualifierOrThis(methodExpression);
final PsiExpression qualifier = ExpressionUtils.getEffectiveQualifier(methodExpression);
final PsiExpression strippedQualifier = ParenthesesUtils.stripParentheses(qualifier);
final PsiExpression strippedArgument = ParenthesesUtils.stripParentheses(argument);
if (strippedQualifier == null || strippedArgument == null) {

View File

@@ -57,8 +57,9 @@ public class FlipSetterCallIntention extends Intention {
if (!(argument instanceof PsiMethodCallExpression)) return;
final PsiMethodCallExpression call2 = (PsiMethodCallExpression)argument;
final PsiExpression qualifierExpression1 = ExpressionUtils.getQualifierOrThis(call.getMethodExpression());
final PsiExpression qualifierExpression2 = ExpressionUtils.getQualifierOrThis(call2.getMethodExpression());
final PsiExpression qualifierExpression1 = ExpressionUtils.getEffectiveQualifier(call.getMethodExpression());
final PsiExpression qualifierExpression2 = ExpressionUtils.getEffectiveQualifier(call2.getMethodExpression());
if (qualifierExpression1 == null || qualifierExpression2 == null) return;
final PsiMethod setter = call.resolveMethod();
final PsiMethod getter = call2.resolveMethod();
final PsiMethod get = PropertyUtil.getReversePropertyMethod(setter);