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
;
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);
38 regexMethodNames
.add("compile");
39 regexMethodNames
.add("matches");
40 regexMethodNames
.add("replaceFirst");
41 regexMethodNames
.add("replaceAll");
42 regexMethodNames
.add("split");
45 private MethodCallUtils() {}
48 public static String
getMethodName(
49 @NotNull PsiMethodCallExpression expression
) {
50 final PsiReferenceExpression method
= expression
.getMethodExpression();
51 return method
.getReferenceName();
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) {
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
)) {
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
,
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()) {
117 final PsiMethod method
= expression
.resolveMethod();
118 if (method
== null) {
121 if (calledOnClassName
!= null) {
122 final PsiExpression qualifier
=
123 methodExpression
.getQualifierExpression();
124 if (qualifier
!= null) {
125 if (!TypeUtils
.expressionHasTypeOrSubtype(qualifier
,
126 calledOnClassName
)) {
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
)) {
152 final PsiMethod method
= expression
.resolveMethod();
153 if (method
== null) {
156 if (calledOnClassName
!= null) {
157 final PsiExpression qualifier
=
158 methodExpression
.getQualifierExpression();
159 if (qualifier
!= null) {
160 if (!TypeUtils
.expressionHasTypeOrSubtype(qualifier
,
161 calledOnClassName
)) {
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
,
175 final PsiParameterList parameterList
= method
.getParameterList();
176 if (method
.isVarArgs()) {
177 if (types
.length
< parameterList
.getParametersCount() - 1) {
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
)) {
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()) {
194 final PsiType argType
= types
[i
];
195 if (argType
== null) {
198 final PsiType parameterType
= parameters
[i
].getType();
199 final PsiType substitutedParmType
=
200 substitutorForMethod
.substitute(parameterType
);
201 if (!TypeConversionUtil
.isAssignable(substitutedParmType
,
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
)) {
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
,
228 if (types
.length
!= parameterList
.getParametersCount()) {
231 final PsiParameter
[] parameters
= parameterList
.getParameters();
232 for (int i
= 0; i
< types
.length
; i
++) {
233 final PsiType type
= types
[i
];
237 final PsiType parameterType
= parameters
[i
].getType();
238 final PsiType substitutedParameterType
=
239 substitutorForMethod
.substitute(parameterType
);
240 if (!TypeConversionUtil
.isAssignable(substitutedParameterType
,
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
)){
257 final PsiMethod method
= expression
.resolveMethod();
261 final PsiClass containingClass
= method
.getContainingClass();
262 if(containingClass
== null){
265 final String className
= containingClass
.getQualifiedName();
266 return "java.lang.String".equals(className
) ||
267 "java.util.regex.Pattern".equals(className
);