mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-30 10:20:15 +07:00
ExpressionUtils#getQualifierOrThis -> getEffectiveQualifier, nullable now (cannot construct this expression for outer anonymous class)
Fixes EA-140652 - assert: JavaParserUtil.parseFragment
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user