ConstructorUtil created and used

RefactoringChangeUtil methods are replaced with ConstructorUtil; manual constructor call search replaced
This commit is contained in:
Tagir Valeev
2018-03-29 17:49:36 +07:00
parent 43b765aac7
commit 574c7421f3
28 changed files with 195 additions and 286 deletions
@@ -41,7 +41,7 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ConstructorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -821,16 +821,8 @@ public class HighlightClassUtil {
PsiMethod[] constructors = aClass.getConstructors();
if (constructors.length == 0) return false;
for (PsiMethod constructor : constructors) {
PsiCodeBlock body = constructor.getBody();
if (body == null) return false;
PsiStatement[] statements = body.getStatements();
if (statements.length == 0) return false;
PsiStatement firstStatement = statements[0];
if (!(firstStatement instanceof PsiExpressionStatement)) return false;
PsiExpression expression = ((PsiExpressionStatement)firstStatement).getExpression();
if (!RefactoringChangeUtil.isSuperOrThisMethodCall(expression)) return false;
PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
if (PsiKeyword.THIS.equals(methodCallExpression.getMethodExpression().getReferenceName())) continue;
PsiMethodCallExpression methodCallExpression = ConstructorUtil.findThisOrSuperCallInConstructor(constructor);
if (!ConstructorUtil.isSuperConstructorCall(methodCallExpression)) continue;
PsiReferenceExpression referenceExpression = methodCallExpression.getMethodExpression();
PsiExpression qualifierExpression = PsiUtil.skipParenthesizedExprDown(referenceExpression.getQualifierExpression());
//If the class instance creation expression is qualified, then the immediately
@@ -885,7 +877,7 @@ public class HighlightClassUtil {
@Nullable
static HighlightInfo checkSuperQualifierType(@NotNull Project project, @NotNull PsiMethodCallExpression superCall) {
if (!RefactoringChangeUtil.isSuperMethodCall(superCall)) return null;
if (!ConstructorUtil.isSuperConstructorCall(superCall)) return null;
PsiMethod ctr = PsiTreeUtil.getParentOfType(superCall, PsiMethod.class, true, PsiMember.class);
if (ctr == null) return null;
final PsiClass aClass = ctr.getContainingClass();
@@ -27,8 +27,8 @@ import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.ui.ColorUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.MostlySingularMultiMap;
@@ -1318,7 +1318,7 @@ public class HighlightMethodUtil {
@Nullable
static HighlightInfo checkConstructorCallMustBeFirstStatement(@NotNull PsiMethodCallExpression methodCall) {
if (!RefactoringChangeUtil.isSuperOrThisMethodCall(methodCall)) return null;
if (!ConstructorUtil.isConstructorCall(methodCall)) return null;
PsiElement codeBlock = methodCall.getParent().getParent();
if (codeBlock instanceof PsiCodeBlock
&& codeBlock.getParent() instanceof PsiMethod
@@ -1358,14 +1358,7 @@ public class HighlightMethodUtil {
PsiCodeBlock body = constructor.getBody();
if (body == null) return null;
// check whether constructor call super(...) or this(...)
PsiElement element = new PsiMatcherImpl(body)
.firstChild(PsiMatchers.hasClass(PsiExpressionStatement.class))
.firstChild(PsiMatchers.hasClass(PsiMethodCallExpression.class))
.firstChild(PsiMatchers.hasClass(PsiReferenceExpression.class))
.firstChild(PsiMatchers.hasClass(PsiKeyword.class))
.getElement();
if (element != null) return null;
if (ConstructorUtil.findThisOrSuperCallInConstructor(constructor) != null) return null;
TextRange textRange = HighlightNamesUtil.getMethodDeclarationTextRange(constructor);
PsiClassType[] handledExceptions = constructor.getThrowsList().getReferencedTypes();
HighlightInfo info = HighlightClassUtil.checkBaseClassDefaultConstructorProblem(aClass, refCountHolder, resolveHelper, textRange, handledExceptions);
@@ -44,6 +44,7 @@ import com.intellij.psi.util.*;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashSet;
@@ -2055,7 +2056,7 @@ public class HighlightUtil extends HighlightUtilBase {
type = qualifier instanceof PsiExpression ? ((PsiExpression)qualifier).getType() : null;
referencedClass = PsiUtil.resolveClassInType(type);
boolean isSuperCall = RefactoringChangeUtil.isSuperMethodCall(expression.getParent());
boolean isSuperCall = ConstructorUtil.isSuperConstructorCall(expression.getParent());
if (resolved == null && isSuperCall) {
if (qualifier instanceof PsiReferenceExpression) {
resolved = ((PsiReferenceExpression)qualifier).resolve();
@@ -2150,7 +2151,7 @@ public class HighlightUtil extends HighlightUtilBase {
PsiElement element = expression.getParent();
while (element != null) {
// check if expression inside super()/this() call
if (RefactoringChangeUtil.isSuperOrThisMethodCall(element)) {
if (ConstructorUtil.isConstructorCall(element)) {
PsiElement parentClass = new PsiMatcherImpl(element)
.parent(PsiMatchers.hasClass(PsiExpressionStatement.class))
.parent(PsiMatchers.hasClass(PsiCodeBlock.class))
@@ -2242,29 +2243,14 @@ public class HighlightUtil extends HighlightUtilBase {
return createMemberReferencedError(aClass.getName() + ".this", range);
}
for (PsiMethod constructor : constructors) {
if (!isSuperCalledInConstructor(constructor)) {
PsiMethodCallExpression call = ConstructorUtil.findThisOrSuperCallInConstructor(constructor);
if (!ConstructorUtil.isSuperConstructorCall(call)) {
return createMemberReferencedError(aClass.getName() + ".this", HighlightNamesUtil.getMethodDeclarationTextRange(constructor));
}
}
return null;
}
private static boolean isSuperCalledInConstructor(@NotNull final PsiMethod constructor) {
final PsiCodeBlock body = constructor.getBody();
if (body == null) return false;
final PsiStatement[] statements = body.getStatements();
if (statements.length == 0) return false;
final PsiStatement statement = statements[0];
final PsiElement element = new PsiMatcherImpl(statement)
.dot(PsiMatchers.hasClass(PsiExpressionStatement.class))
.firstChild(PsiMatchers.hasClass(PsiMethodCallExpression.class))
.firstChild(PsiMatchers.hasClass(PsiReferenceExpression.class))
.firstChild(PsiMatchers.hasClass(PsiKeyword.class))
.dot(PsiMatchers.hasText(PsiKeyword.SUPER))
.getElement();
return element != null;
}
private static boolean thisOrSuperReference(@Nullable PsiExpression qualifierExpression, @NotNull PsiClass aClass) {
if (qualifierExpression == null) return true;
PsiJavaCodeReferenceElement qualifier;
@@ -20,7 +20,11 @@ import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -155,22 +159,8 @@ public class JavaHighlightUtil {
static void visitConstructorChain(@NotNull PsiMethod entry, @NotNull ConstructorVisitorInfo info) {
PsiMethod constructor = entry;
while (true) {
final PsiCodeBlock body = constructor.getBody();
if (body == null) return;
final PsiStatement[] statements = body.getStatements();
if (statements.length == 0) return;
final PsiStatement statement = statements[0];
final PsiElement element = new PsiMatcherImpl(statement)
.dot(PsiMatchers.hasClass(PsiExpressionStatement.class))
.firstChild(PsiMatchers.hasClass(PsiMethodCallExpression.class))
.firstChild(PsiMatchers.hasClass(PsiReferenceExpression.class))
.firstChild(PsiMatchers.hasClass(PsiKeyword.class))
.dot(PsiMatchers.hasText(PsiKeyword.THIS))
.parent(null)
.parent(null)
.getElement();
if (element == null) return;
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)element;
PsiMethodCallExpression methodCall = ConstructorUtil.findThisOrSuperCallInConstructor(constructor);
if (!ConstructorUtil.isChainedConstructorCall(methodCall)) return;
PsiMethod method = methodCall.resolveMethod();
if (method == null) return;
if (info.visitedConstructors != null && info.visitedConstructors.contains(method)) {
@@ -19,8 +19,8 @@ import com.intellij.openapi.progress.ProgressManager;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiSuperMethodUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.Processor;
import com.intellij.util.containers.MultiMap;
@@ -43,7 +43,7 @@ public class FindSuperElementsHelper {
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod) element;
if (method.isConstructor()) {
PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method);
PsiMethod constructorInSuper = ConstructorUtil.findConstructorInSuper(method);
if (constructorInSuper != null) {
return new PsiMethod[]{constructorInSuper};
}
@@ -34,9 +34,9 @@ import com.intellij.psi.search.PsiShortNamesCache;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import com.siyeh.ig.psiutils.ExpressionUtils;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -946,7 +946,7 @@ public class ExpectedTypesProvider {
return ExpectedTypeInfo.EMPTY_ARRAY;
}
PsiMethod toExclude = ExpressionUtils.isConstructorInvocation(argumentList.getParent())
PsiMethod toExclude = ConstructorUtil.isConstructorCall(argumentList.getParent())
? PsiTreeUtil.getParentOfType(argument, PsiMethod.class) : null;
PsiResolveHelper helper = JavaPsiFacade.getInstance(myExpr.getProject()).getResolveHelper();
@@ -22,7 +22,7 @@ import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.intellij.util.ConstructorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,7 +43,7 @@ class CheckInitialized implements ElementFilter {
}
static boolean isInsideConstructorCall(@NotNull PsiElement position) {
return ExpressionUtils.isConstructorInvocation(PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class)) &&
return ConstructorUtil.isConstructorCall(PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class)) &&
!JavaKeywordCompletion.AFTER_DOT.accepts(position);
}
@@ -30,12 +30,12 @@ import com.intellij.psi.impl.source.tree.java.PsiEmptyExpressionImpl;
import com.intellij.psi.util.PsiSuperMethodUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.Consumer;
import com.intellij.util.PlatformIcons;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CharArrayUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -131,8 +131,8 @@ class SameSignatureCallParametersProvider extends CompletionProvider<CompletionP
results = new JavaResolveResult[]{expression.resolveMethodGenerics()};
}
PsiMethod toExclude = ExpressionUtils.isConstructorInvocation(expression) ? PsiTreeUtil.getParentOfType(expression, PsiMethod.class)
: null;
PsiMethod toExclude = ConstructorUtil.isConstructorCall(expression) ? PsiTreeUtil.getParentOfType(expression, PsiMethod.class)
: null;
for (final JavaResolveResult candidate : results) {
final PsiElement element = candidate.getElement();
@@ -17,10 +17,10 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ConstructorUtil;
/**
* @author yole
@@ -71,24 +71,13 @@ public class CreateInnerClassFromNewFix extends CreateClassFromNewFix {
}
private static boolean isInThisOrSuperCall(PsiNewExpression newExpression) {
boolean inFirstConstructorLine = false;
final PsiExpressionStatement expressionStatement = PsiTreeUtil.getParentOfType(newExpression, PsiExpressionStatement.class);
if (expressionStatement != null) {
final PsiExpression expression = expressionStatement.getExpression();
if (expression instanceof PsiMethodCallExpression) {
final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expression).getMethodExpression();
final PsiElement resolve = methodExpression.resolve();
if (resolve instanceof PsiMethod && ((PsiMethod)resolve).isConstructor()) {
final PsiElement referenceNameElement = methodExpression.getReferenceNameElement();
if (referenceNameElement != null) {
if (Comparing.strEqual(referenceNameElement.getText(), PsiKeyword.THIS) ||
Comparing.strEqual(referenceNameElement.getText(), PsiKeyword.SUPER)) {
inFirstConstructorLine = true;
}
}
}
if (ConstructorUtil.isConstructorCall(expression)) {
return true;
}
}
return inFirstConstructorLine;
return false;
}
}
@@ -27,8 +27,8 @@ import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -148,9 +148,7 @@ public abstract class BaseMoveInitializerToMethodAction extends PsiElementBaseIn
private static boolean isSuperOrThisMethodCall(@NotNull PsiStatement statement) {
if (statement instanceof PsiExpressionStatement) {
final PsiElement expression = ((PsiExpressionStatement)statement).getExpression();
if (RefactoringChangeUtil.isSuperOrThisMethodCall(expression)) {
return true;
}
return ConstructorUtil.isConstructorCall(expression);
}
return false;
}
@@ -44,6 +44,7 @@ import com.intellij.refactoring.util.*;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.MultiMap;
import com.siyeh.ig.psiutils.CommentTracker;
@@ -1524,14 +1525,14 @@ public class InlineMethodProcessor extends BaseRefactoringProcessor {
@Deprecated
public static String checkCalledInSuperOrThisExpr(PsiCodeBlock methodBody, final PsiElement element) {
return checkUnableToInsertCodeBlock(methodBody, element,
expr -> RefactoringChangeUtil.isSuperOrThisMethodCall(expr) && expr.getMethodExpression() != element)
expr -> ConstructorUtil.isConstructorCall(expr) && expr.getMethodExpression() != element)
? "Inline cannot be applied to multiline method in constructor call"
: null;
}
public static String checkUnableToInsertCodeBlock(PsiCodeBlock methodBody, final PsiElement element) {
if (checkUnableToInsertCodeBlock(methodBody, element,
expr -> RefactoringChangeUtil.isSuperOrThisMethodCall(expr) && expr.getMethodExpression() != element)) {
expr -> ConstructorUtil.isConstructorCall(expr) && expr.getMethodExpression() != element)) {
return "Inline cannot be applied to multiline method in constructor call";
}
return checkUnableToInsertCodeBlock(methodBody, element,
@@ -38,6 +38,7 @@ import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
@@ -315,20 +316,11 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor
@Nullable
private PsiElement findAnchorForLocalVariableDeclaration(PsiCodeBlock body) {
PsiElement anchor = body.getLBrace();
if (myMethod.isConstructor()) {
final PsiStatement[] statements = body.getStatements();
if (statements.length > 0 && statements[0] instanceof PsiExpressionStatement) {
final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
if (expression instanceof PsiMethodCallExpression) {
final String referenceName = ((PsiMethodCallExpression)expression).getMethodExpression().getReferenceName();
if (PsiKeyword.SUPER.equals(referenceName) || PsiKeyword.THIS.equals(referenceName)) {
anchor = statements[0];
}
}
}
PsiMethodCallExpression call = ConstructorUtil.findThisOrSuperCallInConstructor(myMethod);
if (call != null) {
return call.getParent();
}
return anchor;
return body.getLBrace();
}
private static class LocalReplacementUsageInfo extends UsageInfo {
@@ -39,6 +39,7 @@ import com.intellij.refactoring.util.classMembers.MemberInfoStorage;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
@@ -170,23 +171,12 @@ public class InlineSuperClassRefactoringProcessor extends FixableUsagesRefactori
final PsiMethod[] superConstructors = mySuperClass.getConstructors();
for (PsiMethod constructor : targetClass.getConstructors()) {
final PsiCodeBlock constrBody = constructor.getBody();
if (constrBody != null) {
final PsiStatement[] statements = constrBody.getStatements();
if (statements.length > 0) {
final PsiStatement firstConstrStatement = statements[0];
if (firstConstrStatement instanceof PsiExpressionStatement) {
final PsiExpression expression = ((PsiExpressionStatement)firstConstrStatement).getExpression();
if (expression instanceof PsiMethodCallExpression) {
final PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expression).getMethodExpression();
if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
final PsiMethod superConstructor = ((PsiMethodCallExpression)expression).resolveMethod();
if (superConstructor != null && superConstructor.getBody() != null) {
usages.add(new InlineSuperCallUsageInfo((PsiMethodCallExpression)expression));
continue;
}
}
}
}
PsiMethodCallExpression call = ConstructorUtil.findThisOrSuperCallInConstructor(constructor);
if (ConstructorUtil.isSuperConstructorCall(call)) {
final PsiMethod superConstructor = call.resolveMethod();
if (superConstructor != null && superConstructor.getBody() != null) {
usages.add(new InlineSuperCallUsageInfo(call));
continue;
}
}
@@ -44,13 +44,13 @@ import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.changeSignature.inCallers.AbstractJavaMemberCallerChooser;
import com.intellij.refactoring.safeDelete.usageInfo.*;
import com.intellij.refactoring.util.ConflictsUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.refactoring.util.RefactoringMessageUtil;
import com.intellij.refactoring.util.RefactoringUIUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewUtil;
import com.intellij.usages.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
@@ -615,12 +615,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
if (statements.length == 0) continue;
if (statements.length == 1 && statements[0] instanceof PsiExpressionStatement) {
final PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
if (expression instanceof PsiMethodCallExpression) {
PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)expression).getMethodExpression();
if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
continue;
}
}
if (ConstructorUtil.isSuperConstructorCall(expression)) continue;
}
}
}
@@ -978,7 +973,7 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
if (safeDeleteDelegate != null) {
safeDeleteDelegate.createUsageInfoForParameter(reference, usages, parameter, method);
}
if (!parameter.isVarArgs() && !RefactoringChangeUtil.isSuperMethodCall(element.getParent())) {
if (!parameter.isVarArgs() && !ConstructorUtil.isSuperConstructorCall(element.getParent())) {
final PsiParameter paramInCaller = SafeDeleteJavaCallerChooser.isTheOnlyOneParameterUsage(element.getParent(), parameterIndex, method);
if (paramInCaller != null) {
final PsiMethod callerMethod = (PsiMethod)paramInCaller.getDeclarationScope();
@@ -1000,11 +995,10 @@ public class JavaSafeDeleteProcessor extends SafeDeleteProcessorDelegateBase {
boolean isSafeDelete = false;
if (element.getParent().getParent() instanceof PsiMethodCallExpression) {
PsiMethodCallExpression call = (PsiMethodCallExpression)element.getParent().getParent();
PsiReferenceExpression methodExpression = call.getMethodExpression();
if (methodExpression.getText().equals(PsiKeyword.SUPER)) {
if (ConstructorUtil.isSuperConstructorCall(call)) {
isSafeDelete = true;
}
else if (methodExpression.getQualifierExpression() instanceof PsiSuperExpression) {
else if (call.getMethodExpression().getQualifierExpression() instanceof PsiSuperExpression) {
final PsiMethod superMethod = call.resolveMethod();
if (superMethod != null && MethodSignatureUtil.isSuperMethod(superMethod, method)) {
isSafeDelete = true;
@@ -20,58 +20,17 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class PsiSuperMethodUtil {
private PsiSuperMethodUtil() {}
public static PsiMethod findConstructorInSuper(PsiMethod constructor) {
return findConstructorInSuper(constructor, new HashSet<>());
}
public static PsiMethod findConstructorInSuper(PsiMethod constructor, Set<PsiMethod> visited) {
if (visited.contains(constructor)) return null;
visited.add(constructor);
final PsiCodeBlock body = constructor.getBody();
if (body != null) {
PsiStatement[] statements = body.getStatements();
if (statements.length > 0) {
PsiElement firstChild = statements[0].getFirstChild();
if (firstChild instanceof PsiMethodCallExpression) {
PsiReferenceExpression methodExpr = ((PsiMethodCallExpression)firstChild).getMethodExpression();
@NonNls final String text = methodExpr.getText();
if (text.equals("super")) {
PsiElement superConstructor = methodExpr.resolve();
if (superConstructor instanceof PsiMethod) {
return (PsiMethod)superConstructor;
}
} else if (text.equals("this")) {
final PsiElement resolved = methodExpr.resolve();
if (resolved instanceof PsiMethod) {
return findConstructorInSuper((PsiMethod)resolved, visited);
}
return null;
}
}
}
}
PsiClass containingClass = constructor.getContainingClass();
if (containingClass != null) {
PsiClass superClass = containingClass.getSuperClass();
if (superClass != null) {
MethodSignature defConstructor = MethodSignatureUtil.createMethodSignature(superClass.getName(), PsiType.EMPTY_ARRAY,
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, true);
return MethodSignatureUtil.findMethodBySignature(superClass, defConstructor, false);
}
}
return null;
}
public static boolean isSuperMethod(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
HierarchicalMethodSignature signature = method.getHierarchicalMethodSignature();
for (HierarchicalMethodSignature supsig : signature.getSuperSignatures()) {
@@ -21,6 +21,7 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -28,23 +29,6 @@ import org.jetbrains.annotations.Nullable;
public class RefactoringChangeUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.util.ChangeUtil");
@Nullable
private static String getMethodExpressionName(@Nullable PsiElement element) {
if (!(element instanceof PsiMethodCallExpression)) return null;
PsiReferenceExpression methodExpression = ((PsiMethodCallExpression)element).getMethodExpression();
return methodExpression.getReferenceName();
}
public static boolean isSuperOrThisMethodCall(@Nullable PsiElement element) {
String name = getMethodExpressionName(element);
return PsiKeyword.SUPER.equals(name) || PsiKeyword.THIS.equals(name);
}
public static boolean isSuperMethodCall(@Nullable PsiElement element) {
String name = getMethodExpressionName(element);
return PsiKeyword.SUPER.equals(name);
}
public static PsiType getTypeByExpression(PsiExpression expr) {
PsiType type = expr != null ? expr.getType() : null;
if (type == null) {
@@ -76,7 +60,7 @@ public class RefactoringChangeUtil {
PsiManager manager = referenceExpression.getManager();
PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(referenceExpression, PsiMethodCallExpression.class, true);
while (methodCallExpression != null) {
if (isSuperOrThisMethodCall(methodCallExpression)) {
if (ConstructorUtil.isConstructorCall(methodCallExpression)) {
return referenceExpression;
}
methodCallExpression = PsiTreeUtil.getParentOfType(methodCallExpression, PsiMethodCallExpression.class, true);
@@ -0,0 +1,104 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.util;
import com.intellij.psi.*;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
public class ConstructorUtil {
/**
* Finds call to another constructor within this constructor (either chained or super)
* @param constructor constructor to search in
* @return found this/super constructor method call or null if not found or supplied method is null or not a constructor
*/
@Contract("null -> null")
@Nullable
public static PsiMethodCallExpression findThisOrSuperCallInConstructor(@Nullable PsiMethod constructor) {
if (constructor == null || !constructor.isConstructor()) return null;
PsiCodeBlock body = constructor.getBody();
if (body == null) return null;
PsiElement bodyElement = body.getFirstBodyElement();
while (bodyElement != null && !(bodyElement instanceof PsiStatement)) {
bodyElement = bodyElement.getNextSibling();
}
if (!(bodyElement instanceof PsiExpressionStatement)) return null;
PsiMethodCallExpression call =
ObjectUtils.tryCast(((PsiExpressionStatement)bodyElement).getExpression(), PsiMethodCallExpression.class);
if (isConstructorCall(call)) return call;
return null;
}
/**
* Returns true if given element is a chained constructor call
* @param call element to check
* @return true if given element is a chained constructor call
*/
@Contract("null -> false")
public static boolean isChainedConstructorCall(@Nullable PsiElement call) {
if (!(call instanceof PsiMethodCallExpression)) return false;
PsiElement child = ((PsiMethodCallExpression)call).getMethodExpression().getReferenceNameElement();
return child instanceof PsiKeyword && child.textMatches(PsiKeyword.THIS);
}
/**
* Returns true if given element is a super constructor call
* @param call element to check
* @return true if given element is a super constructor call
*/
@Contract("null -> false")
public static boolean isSuperConstructorCall(@Nullable PsiElement call) {
if (!(call instanceof PsiMethodCallExpression)) return false;
PsiElement child = ((PsiMethodCallExpression)call).getMethodExpression().getReferenceNameElement();
return child instanceof PsiKeyword && child.textMatches(PsiKeyword.SUPER);
}
/**
* Returns true if given element is chained or super constructor call
* @param call element to check
* @return true if given element is chained or super constructor call
*/
@Contract("null -> false")
public static boolean isConstructorCall(@Nullable PsiElement call) {
if (!(call instanceof PsiMethodCallExpression)) return false;
PsiElement child = ((PsiMethodCallExpression)call).getMethodExpression().getReferenceNameElement();
return child instanceof PsiKeyword && (child.textMatches(PsiKeyword.SUPER) || child.textMatches(PsiKeyword.THIS));
}
public static PsiMethod findConstructorInSuper(PsiMethod constructor) {
return findConstructorInSuper(constructor, new HashSet<>());
}
private static PsiMethod findConstructorInSuper(PsiMethod constructor, Set<PsiMethod> visited) {
if (visited.contains(constructor)) return null;
visited.add(constructor);
PsiMethodCallExpression call = findThisOrSuperCallInConstructor(constructor);
if (isSuperConstructorCall(call)) {
PsiMethod superConstructor = call.resolveMethod();
if (superConstructor != null) {
return superConstructor;
}
} else if (isChainedConstructorCall(call)) {
PsiMethod chainedConstructor = call.resolveMethod();
if (chainedConstructor != null) {
return findConstructorInSuper(chainedConstructor, visited);
}
return null;
}
PsiClass containingClass = constructor.getContainingClass();
if (containingClass != null) {
PsiClass superClass = containingClass.getSuperClass();
if (superClass != null && superClass.getName() != null) {
MethodSignature defConstructor = MethodSignatureUtil.createMethodSignature(superClass.getName(), PsiType.EMPTY_ARRAY,
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY, true);
return MethodSignatureUtil.findMethodBySignature(superClass, defConstructor, false);
}
}
return null;
}
}
@@ -18,7 +18,7 @@ package com.siyeh.ig.psiutils;
import com.intellij.codeInsight.ExceptionUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ConstructorUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -228,8 +228,10 @@ public class ExceptionUtils {
} else {
final PsiMethodCallExpression methodCallExpression =
PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class, PsiClass.class);
if (RefactoringChangeUtil.isSuperOrThisMethodCall(methodCallExpression)) {
return true;
if (ConstructorUtil.isConstructorCall(methodCallExpression)) {
PsiMethod ctor = methodCallExpression.resolveMethod();
return ctor != null &&
com.intellij.psi.util.InheritanceUtil.isInheritor(ctor.getContainingClass(), CommonClassNames.JAVA_LANG_THROWABLE);
}
}
return false;
@@ -505,19 +505,6 @@ public class ExpressionUtils {
}
public static boolean isConstructorInvocation(PsiElement element) {
if (!(element instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression methodCallExpression =
(PsiMethodCallExpression)element;
final PsiReferenceExpression methodExpression =
methodCallExpression.getMethodExpression();
final String callName = methodExpression.getReferenceName();
return PsiKeyword.THIS.equals(callName) ||
PsiKeyword.SUPER.equals(callName);
}
public static boolean hasType(@Nullable PsiExpression expression, @NonNls @NotNull String typeName) {
if (expression == null) {
return false;
@@ -22,7 +22,7 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ConstructorUtil;
import com.siyeh.HardcodedMethodConstants;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@@ -424,7 +424,7 @@ public class MethodCallUtils {
// we've already seen this method -> circular call chain
return false;
}
final PsiMethodCallExpression call = MethodUtils.findSuperOrThisCall(method);
final PsiMethodCallExpression call = ConstructorUtil.findThisOrSuperCallInConstructor(method);
if (call == null) {
return false;
}
@@ -440,7 +440,7 @@ public class MethodCallUtils {
if (method == null) {
return false;
}
if (RefactoringChangeUtil.isSuperMethodCall(call) && (!superMustBeLibrary || method instanceof PsiCompiledElement)) {
if (ConstructorUtil.isSuperConstructorCall(call) && (!superMustBeLibrary || method instanceof PsiCompiledElement)) {
return true;
}
parameter = method.getParameterList().getParameters()[index];
@@ -8,9 +8,11 @@ import com.intellij.psi.*;
import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.siyeh.HardcodedMethodConstants;
@@ -323,14 +325,7 @@ public class MethodUtils {
}
else if (statement instanceof PsiExpressionStatement) {
final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)statement;
final PsiExpression expression = expressionStatement.getExpression();
if (!(expression instanceof PsiMethodCallExpression)) {
return false;
}
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
if (!PsiKeyword.SUPER.equals(methodExpression.getText())) {
// constructor super call
if (!ConstructorUtil.isSuperConstructorCall(expressionStatement.getExpression())) {
return false;
}
}
@@ -402,22 +397,6 @@ public class MethodUtils {
return AnnotationUtil.equal(list1.getAnnotations(), list2.getAnnotations());
}
public static PsiMethodCallExpression findSuperOrThisCall(PsiMethod constructor) {
if (constructor == null || !constructor.isConstructor()) {
return null;
}
final PsiStatement firstStatement = PsiTreeUtil.getChildOfType(constructor.getBody(), PsiStatement.class);
if (!(firstStatement instanceof PsiExpressionStatement)) {
return null;
}
final PsiExpressionStatement expressionStatement = (PsiExpressionStatement)firstStatement;
final PsiExpression expression = expressionStatement.getExpression();
if (!RefactoringChangeUtil.isSuperOrThisMethodCall(expression)) {
return null;
}
return (PsiMethodCallExpression)expression;
}
/**
* Find a specific method by base class method and known specific type of the object
*
@@ -17,10 +17,10 @@ package com.siyeh.ig.style;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ConstructorUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
@@ -70,7 +70,7 @@ public class ChainedMethodCallInspectionBase extends BaseInspection {
final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class);
if (expressionList != null) {
final PsiElement parent = expressionList.getParent();
if (ExpressionUtils.isConstructorInvocation(parent)) {
if (ConstructorUtil.isConstructorCall(parent)) {
return;
}
}
@@ -21,12 +21,12 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ConstructorUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -144,7 +144,7 @@ public class ImplicitCallToSuperInspection extends BaseInspection {
(PsiExpressionStatement)statement;
final PsiExpression expression =
expressionStatement.getExpression();
return ExpressionUtils.isConstructorInvocation(expression);
return ConstructorUtil.isConstructorCall(expression);
}
}
}
@@ -20,10 +20,10 @@ import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ConstructorUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
@@ -105,7 +105,7 @@ public class NestedMethodCallInspectionBase extends BaseInspection {
if (!(grandParent instanceof PsiCallExpression)) {
return;
}
if (ExpressionUtils.isConstructorInvocation(grandParent)) {
if (ConstructorUtil.isConstructorCall(grandParent)) {
//ignore nested method calls at the start of a constructor,
//where they can't be extracted
return;
@@ -5,7 +5,7 @@ import com.intellij.psi.*;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtilRt;
import com.siyeh.InspectionGadgetsBundle;
@@ -107,7 +107,7 @@ public class CopyConstructorMissesFieldInspection extends BaseInspection {
assignedFields.add((PsiField)variable);
}
}
else if (RefactoringChangeUtil.isSuperOrThisMethodCall(element)) {
else if (ConstructorUtil.isConstructorCall(element)) {
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
for (PsiExpression argument : methodCallExpression.getArgumentList().getExpressions()) {
argument = ParenthesesUtils.stripParentheses(argument);
@@ -25,12 +25,16 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.ConstructorUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.*;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -286,7 +290,7 @@ public class ConditionalExpressionInspection extends BaseInspection {
final PsiMethodCallExpression methodCallExpression =
PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true,
PsiLambdaExpression.class, PsiStatement.class, PsiMember.class);
return ExpressionUtils.isConstructorInvocation(methodCallExpression);
return ConstructorUtil.isConstructorCall(methodCallExpression);
}
}
}
@@ -23,8 +23,8 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiSuperMethodUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ConstructorUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -117,7 +117,7 @@ public class GroovyGotoSuperHandler extends GotoTargetHandler implements Languag
@NotNull
private static PsiMethod[] getSupers(PsiMethod method) {
if (method.isConstructor()) {
PsiMethod constructorInSuper = PsiSuperMethodUtil.findConstructorInSuper(method);
PsiMethod constructorInSuper = ConstructorUtil.findConstructorInSuper(method);
if (constructorInSuper != null) {
return new PsiMethod[]{constructorInSuper};
}
@@ -27,12 +27,12 @@ import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.refactoring.introduceField.IntroduceConstantHandler;
import com.intellij.refactoring.util.RefactoringChangeUtil;
import com.intellij.ui.AddDeleteListPanel;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.FieldPanel;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.util.containers.ContainerUtil;
import com.siyeh.ig.psiutils.ExceptionUtils;
import gnu.trove.THashSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -561,7 +561,7 @@ public class I18nInspection extends AbstractBaseJavaLocalInspectionTool implemen
if (ignoreForAssertStatements && isArgOfAssertStatement(expression)) {
return false;
}
if (ignoreForExceptionConstructors && isArgOfExceptionConstructor(expression)) {
if (ignoreForExceptionConstructors && ExceptionUtils.isExceptionArgument(expression)) {
return false;
}
if (ignoreForEnumConstants && isArgOfEnumConstant(expression)) {
@@ -872,41 +872,6 @@ public class I18nInspection extends AbstractBaseJavaLocalInspectionTool implemen
return junitAssert != null && !containingClass.isInheritor(junitAssert, true);
}
private static boolean isArgOfExceptionConstructor(PsiExpression expression) {
final PsiElement parent = PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class, PsiClass.class);
if (!(parent instanceof PsiExpressionList)) {
return false;
}
final PsiElement grandparent = parent.getParent();
final PsiClass aClass;
if (RefactoringChangeUtil.isSuperOrThisMethodCall(grandparent)) {
final PsiMethod method = ((PsiMethodCallExpression)grandparent).resolveMethod();
if (method != null) {
aClass = method.getContainingClass();
} else {
return false;
}
} else {
if (!(grandparent instanceof PsiNewExpression)) {
return false;
}
final PsiJavaCodeReferenceElement reference = ((PsiNewExpression)grandparent).getClassReference();
if (reference == null) {
return false;
}
final PsiElement referent = reference.resolve();
if (!(referent instanceof PsiClass)) {
return false;
}
aClass = (PsiClass)referent;
}
final Project project = expression.getProject();
final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
final PsiClass throwable = JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_THROWABLE, scope);
return throwable != null && aClass.isInheritor(throwable, true);
}
private static boolean isArgOfSpecifiedExceptionConstructor(PsiExpression expression, String[] specifiedExceptions) {
if (specifiedExceptions.length == 0) return false;