IDEADEV-40452
[fedora-idea.git] / plugins / InspectionGadgets / src / com / siyeh / ig / psiutils / MethodCallUtils.java
blob2c07b7c1830f5a225f184341355fcd7d48499219
1 /*
2 * Copyright 2003-2009 Dave Griffith, Bas Leijdekkers
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.siyeh.ig.psiutils;
18 import com.intellij.psi.*;
19 import com.intellij.psi.search.GlobalSearchScope;
20 import com.intellij.psi.util.TypeConversionUtil;
21 import com.siyeh.HardcodedMethodConstants;
22 import org.jetbrains.annotations.NonNls;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
26 import java.util.HashSet;
27 import java.util.Set;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
31 public class MethodCallUtils {
33 /** @noinspection StaticCollection*/
34 @NonNls private static final Set<String> regexMethodNames =
35 new HashSet<String>(5);
37 static{
38 regexMethodNames.add("compile");
39 regexMethodNames.add("matches");
40 regexMethodNames.add("replaceFirst");
41 regexMethodNames.add("replaceAll");
42 regexMethodNames.add("split");
45 private MethodCallUtils() {}
47 @Nullable
48 public static String getMethodName(
49 @NotNull PsiMethodCallExpression expression) {
50 final PsiReferenceExpression method = expression.getMethodExpression();
51 return method.getReferenceName();
54 @Nullable
55 public static PsiType getTargetType(
56 @NotNull PsiMethodCallExpression expression) {
57 final PsiReferenceExpression method = expression.getMethodExpression();
58 final PsiExpression qualifierExpression =
59 method.getQualifierExpression();
60 if (qualifierExpression == null) {
61 return null;
63 return qualifierExpression.getType();
66 public static boolean isEqualsCall(PsiMethodCallExpression expression) {
67 final PsiReferenceExpression methodExpression =
68 expression.getMethodExpression();
69 final String name = methodExpression.getReferenceName();
70 if (!HardcodedMethodConstants.EQUALS.equals(name)) {
71 return false;
73 final PsiMethod method = expression.resolveMethod();
74 return MethodUtils.isEquals(method);
77 public static boolean isSimpleCallToMethod(
78 @NotNull PsiMethodCallExpression expression,
79 @NonNls @Nullable String calledOnClassName,
80 @Nullable PsiType returnType,
81 @NonNls @Nullable String methodName,
82 @NonNls @Nullable String... parameterTypeStrings) {
83 if (parameterTypeStrings == null) {
84 return isCallToMethod(expression, calledOnClassName, returnType,
85 methodName);
87 final JavaPsiFacade psiFacade =
88 JavaPsiFacade.getInstance(expression.getProject());
89 final PsiElementFactory factory = psiFacade.getElementFactory();
90 final PsiType[] parameterTypes =
91 new PsiType[parameterTypeStrings.length];
92 final GlobalSearchScope scope = expression.getResolveScope();
93 for (int i = 0; i < parameterTypeStrings.length; i++) {
94 final String parameterTypeString = parameterTypeStrings[i];
95 parameterTypes[i] = factory.createTypeByFQClassName(
96 parameterTypeString, scope);
98 return isCallToMethod(expression, calledOnClassName, returnType,
99 methodName, parameterTypes);
102 public static boolean isCallToMethod(
103 @NotNull PsiMethodCallExpression expression,
104 @NonNls @Nullable String calledOnClassName,
105 @Nullable PsiType returnType,
106 @Nullable Pattern methodNamePattern,
107 @Nullable PsiType... parameterTypes) {
108 final PsiReferenceExpression methodExpression =
109 expression.getMethodExpression();
110 if (methodNamePattern != null) {
111 final String referenceName = methodExpression.getReferenceName();
112 final Matcher matcher = methodNamePattern.matcher(referenceName);
113 if (!matcher.matches()) {
114 return false;
117 final PsiMethod method = expression.resolveMethod();
118 if (method == null) {
119 return false;
121 if (calledOnClassName != null) {
122 final PsiExpression qualifier =
123 methodExpression.getQualifierExpression();
124 if (qualifier != null) {
125 if (!TypeUtils.expressionHasTypeOrSubtype(qualifier,
126 calledOnClassName)) {
127 return false;
129 return MethodUtils.methodMatches(method, null, returnType,
130 methodNamePattern, parameterTypes);
133 return MethodUtils.methodMatches(method, calledOnClassName, returnType,
134 methodNamePattern, parameterTypes);
138 public static boolean isCallToMethod(
139 @NotNull PsiMethodCallExpression expression,
140 @NonNls @Nullable String calledOnClassName,
141 @Nullable PsiType returnType,
142 @NonNls @Nullable String methodName,
143 @Nullable PsiType... parameterTypes) {
144 final PsiReferenceExpression methodExpression =
145 expression.getMethodExpression();
146 if (methodName != null) {
147 final String referenceName = methodExpression.getReferenceName();
148 if (!methodName.equals(referenceName)) {
149 return false;
152 final PsiMethod method = expression.resolveMethod();
153 if (method == null) {
154 return false;
156 if (calledOnClassName != null) {
157 final PsiExpression qualifier =
158 methodExpression.getQualifierExpression();
159 if (qualifier != null) {
160 if (!TypeUtils.expressionHasTypeOrSubtype(qualifier,
161 calledOnClassName)) {
162 return false;
164 return MethodUtils.methodMatches(method, null, returnType,
165 methodName, parameterTypes);
168 return MethodUtils.methodMatches(method, calledOnClassName, returnType,
169 methodName, parameterTypes);
172 public static boolean isApplicable(PsiMethod method,
173 PsiSubstitutor substitutorForMethod,
174 PsiType[] types) {
175 final PsiParameterList parameterList = method.getParameterList();
176 if (method.isVarArgs()) {
177 if (types.length < parameterList.getParametersCount() - 1) {
178 return false;
180 final PsiParameter[] parameters = parameterList.getParameters();
181 final PsiParameter lastParameter =
182 parameters[parameters.length - 1];
183 PsiType lastParameterType = lastParameter.getType();
184 if (!(lastParameterType instanceof PsiArrayType)) {
185 return false;
187 lastParameterType = substitutorForMethod.substitute(lastParameterType);
188 if (lastParameter.isVarArgs()) {
189 for (int i = 0; i < parameters.length - 1; i++) {
190 final PsiParameter parm = parameters[i];
191 if (parm.isVarArgs()) {
192 return false;
194 final PsiType argType = types[i];
195 if (argType == null) {
196 return false;
198 final PsiType parameterType = parameters[i].getType();
199 final PsiType substitutedParmType =
200 substitutorForMethod.substitute(parameterType);
201 if (!TypeConversionUtil.isAssignable(substitutedParmType,
202 argType)) {
203 return false;
206 if (types.length == parameters.length) {
207 //call with array as vararg parameter
208 final PsiType lastArgType = types[types.length - 1];
209 if (lastArgType != null && TypeConversionUtil.isAssignable(
210 lastParameterType, lastArgType)) {
211 return true;
214 final PsiArrayType arrayType = (PsiArrayType)lastParameterType;
215 final PsiType componentType = arrayType.getComponentType();
216 for (int i = parameters.length - 1; i < types.length; i++) {
217 final PsiType argType = types[i];
218 if (argType == null ||
219 !TypeConversionUtil.isAssignable(componentType,
220 argType)) {
221 return false;
224 } else {
225 return false;
227 } else {
228 if (types.length != parameterList.getParametersCount()) {
229 return false;
231 final PsiParameter[] parameters = parameterList.getParameters();
232 for (int i = 0; i < types.length; i++) {
233 final PsiType type = types[i];
234 if (type == null) {
235 return false; //?
237 final PsiType parameterType = parameters[i].getType();
238 final PsiType substitutedParameterType =
239 substitutorForMethod.substitute(parameterType);
240 if (!TypeConversionUtil.isAssignable(substitutedParameterType,
241 type)) {
242 return false;
246 return true;
249 public static boolean isCallToRegexMethod(
250 PsiMethodCallExpression expression){
251 final PsiReferenceExpression methodExpression =
252 expression.getMethodExpression();
253 final String name = methodExpression.getReferenceName();
254 if(!regexMethodNames.contains(name)){
255 return false;
257 final PsiMethod method = expression.resolveMethod();
258 if(method == null){
259 return false;
261 final PsiClass containingClass = method.getContainingClass();
262 if(containingClass == null){
263 return false;
265 final String className = containingClass.getQualifiedName();
266 return "java.lang.String".equals(className) ||
267 "java.util.regex.Pattern".equals(className);