ability to change name of method to any string constant. Detection of incorrect usages
[idea/community.git] / plugins / groovy / src / org / jetbrains / plugins / groovy / refactoring / changeSignature / GrChangeInfoImpl.java
1 /*
2  * Copyright 2000-2010 JetBrains s.r.o.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.jetbrains.plugins.groovy.refactoring.changeSignature;
17
18 import com.intellij.lang.Language;
19 import com.intellij.openapi.util.text.StringUtil;
20 import com.intellij.psi.*;
21 import com.intellij.refactoring.changeSignature.JavaChangeInfo;
22 import com.intellij.refactoring.changeSignature.JavaParameterInfo;
23 import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
24 import com.intellij.refactoring.util.CanonicalTypes;
25 import com.intellij.util.IncorrectOperationException;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
28 import org.jetbrains.plugins.groovy.GroovyFileType;
29 import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
30 import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
31
32 import java.util.List;
33
34 /**
35  * @author Maxim.Medvedev
36  */
37 class GrChangeInfoImpl implements JavaChangeInfo {
38   GrMethod method;
39   final String newName;
40   @Nullable final CanonicalTypes.Type returnType;
41   final String visibilityModifier;
42   final List<GrParameterInfo> parameters;
43   boolean changeParameters = false;
44   private boolean myIsParameterTypesChanged = false;
45   private boolean myIsParameterNamesChanged = false;
46   private boolean myIsNameChanged = false;
47   private boolean myIsVisibilityChanged = false;
48   private boolean myIsReturnTypeChanged = false;
49   private boolean myIsRetainVarargs;
50   private boolean myIsArrayToVarargs;
51   private boolean myIsObtainVarargs;
52   private boolean myWasVarargs;
53   private String myOldName;
54   private PsiIdentifier myNewNameIdentifier;
55   private PsiExpression[] defaultValues;
56   private boolean myDelegate;
57   private ThrownExceptionInfo[] myThrownExceptions;
58   private boolean myExceptionSetChanged;
59   private boolean myExceptionSetOrOrderChanged;
60   private String[] myOldParameterNames;
61   private String[] myOldParameterTypes;
62
63   public GrChangeInfoImpl(GrMethod method,
64                           String visibilityModifier,
65                           @Nullable CanonicalTypes.Type returnType,
66                           String newName,
67                           List<GrParameterInfo> parameters, ThrownExceptionInfo[] exceptions, boolean generateDelegate) {
68     this.method = method;
69     this.visibilityModifier = visibilityModifier;
70     this.returnType = returnType;
71     this.parameters = parameters;
72     this.newName = newName;
73     myDelegate = generateDelegate;
74     myOldName = method.getName();
75
76     if (!method.getName().equals(newName)) {
77       myIsNameChanged = true;
78     }
79
80     myIsVisibilityChanged = !method.hasModifierProperty(visibilityModifier);
81
82     if (!method.isConstructor()) {
83       PsiType oldReturnType = null;
84       if (method.getReturnTypeElementGroovy() != null) {
85         oldReturnType = method.getReturnType();
86       }
87       try {
88         PsiType newReturnType = returnType == null ? null : returnType.getType(method, getMethod().getManager());
89         if ((oldReturnType == null && newReturnType != null) || (oldReturnType != null && !oldReturnType.equals(newReturnType))) {
90           myIsReturnTypeChanged = true;
91         }
92       }
93       catch (IncorrectOperationException e) {
94         myIsReturnTypeChanged = true;
95       }
96     }
97
98     GrParameter[] params = method.getParameters();
99     final int oldParameterCount = this.method.getParameters().length;
100     myOldParameterNames=new String[oldParameterCount];
101     myOldParameterTypes=new String[oldParameterCount];
102
103     for (int i = 0; i < oldParameterCount; i++) {
104       GrParameter param = params[i];
105       myOldParameterNames[i] = param.getName();
106       myOldParameterTypes[i] = param.getType().getCanonicalText();
107     }
108
109     if (oldParameterCount != this.parameters.size()) {
110       changeParameters = true;
111     }
112     else {
113       for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
114         GrParameterInfo parameter = parameters.get(i);
115         if (parameter.getOldIndex() != i) {
116           changeParameters = true;
117           break;
118         }
119         if (!params[i].getName().equals(parameter.getName())) {
120           myIsParameterNamesChanged = true;
121         }
122         try {
123           PsiType type = parameter.createType(method, method.getManager());
124           PsiType oldType = params[i].getType();
125           if (!oldType.equals(type)) {
126             myIsParameterTypesChanged = true;
127           }
128         }
129         catch (IncorrectOperationException e) {
130           myIsParameterTypesChanged = true;
131         }
132       }
133     }
134
135     myWasVarargs = method.isVarArgs();
136     if (parameters.size() == 0) {
137       myIsObtainVarargs = false;
138       myIsRetainVarargs = false;
139       myIsArrayToVarargs = false;
140     }
141     else {
142       GrParameterInfo lastNewParam = parameters.get(parameters.size() - 1);
143       myIsObtainVarargs = lastNewParam.isVarargType();
144       myIsRetainVarargs = lastNewParam.getOldIndex() >= 0 && myIsObtainVarargs;
145       if (myIsRetainVarargs) {
146         final PsiType oldTypeForVararg = params[lastNewParam.getOldIndex()].getType();
147         myIsArrayToVarargs = (oldTypeForVararg instanceof PsiArrayType && !(oldTypeForVararg instanceof PsiEllipsisType));
148       }
149       else {
150         myIsArrayToVarargs = false;
151       }
152     }
153
154     if (myIsNameChanged) {
155       if (StringUtil.isJavaIdentifier(newName)) {
156         myNewNameIdentifier = JavaPsiFacade.getElementFactory(getMethod().getProject()).createIdentifier(newName);
157       } else {
158         myNewNameIdentifier = getMethod().getNameIdentifier();
159       }
160     }
161
162     PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
163     defaultValues = new PsiExpression[parameters.size()];
164     for (int i = 0; i < parameters.size(); i++) {
165       JavaParameterInfo info = parameters.get(i);
166       if (info.getOldIndex() < 0 && !info.isVarargType()) {
167         if (info.getDefaultValue() == null) continue;
168         try {
169           defaultValues[i] = factory.createExpressionFromText(info.getDefaultValue(), method);
170         }
171         catch (IncorrectOperationException e) {
172 //          LOG.error(e);
173         }
174       }
175     }
176
177     myThrownExceptions = exceptions;
178     final PsiClassType[] thrownTypes = method.getThrowsList().getReferencedTypes();
179     if (thrownTypes.length != myThrownExceptions.length) {
180       myExceptionSetChanged = true;
181       myExceptionSetOrOrderChanged = true;
182     }
183     else {
184       myExceptionSetChanged = false;
185       for (int i = 0; i < myThrownExceptions.length; i++) {
186         ThrownExceptionInfo info = myThrownExceptions[i];
187         if (info.getOldIndex() < 0) {
188           myExceptionSetChanged = true;
189           myExceptionSetOrOrderChanged = true;
190           break;
191         }
192         else if (info.getOldIndex() != i) {
193           myExceptionSetOrOrderChanged = true;
194         }
195       }
196     }
197   }
198
199   @NotNull
200   public JavaParameterInfo[] getNewParameters() {
201     return parameters.toArray(new GrParameterInfo[parameters.size()]);
202   }
203
204   @Modifier
205   public String getNewVisibility() {
206     return visibilityModifier;
207   }
208
209   public boolean isParameterSetOrOrderChanged() {
210     return changeParameters;
211   }
212
213   public boolean isParameterTypesChanged() {
214     return myIsParameterTypesChanged;
215   }
216
217   public boolean isParameterNamesChanged() {
218     return myIsParameterNamesChanged;
219   }
220
221   public boolean isGenerateDelegate() {
222     return myDelegate;
223   }
224
225   public boolean isNameChanged() {
226     return myIsNameChanged;
227   }
228
229   public boolean isVisibilityChanged() {
230     return myIsVisibilityChanged;
231   }
232
233   public boolean isExceptionSetChanged() {
234     return myExceptionSetChanged;
235   }
236
237   public boolean isExceptionSetOrOrderChanged() {
238     return myExceptionSetOrOrderChanged;
239   }
240
241   public GrMethod getMethod() {
242     return method;
243   }
244
245   public boolean isReturnTypeChanged() {
246     return myIsReturnTypeChanged;
247   }
248
249   public CanonicalTypes.Type getNewReturnType() {
250     return returnType;
251   }
252
253   public String getNewName() {
254     return newName;
255   }
256
257   public Language getLanguage() {
258     return GroovyFileType.GROOVY_LANGUAGE;
259   }
260
261   @NotNull
262   public String[] getOldParameterNames() {
263     return myOldParameterNames;
264   }
265
266   @NotNull
267   public String[] getOldParameterTypes() {
268     return myOldParameterTypes;
269   }
270
271   public ThrownExceptionInfo[] getNewExceptions() {
272     return myThrownExceptions;
273   }
274
275   public boolean isRetainsVarargs() {
276     return myIsRetainVarargs;
277   }
278
279   public boolean isObtainsVarags() {
280     return myIsObtainVarargs;
281   }
282
283   public boolean isArrayToVarargs() {
284     return myIsArrayToVarargs;
285   }
286
287   public PsiIdentifier getNewNameIdentifier() {
288     return myNewNameIdentifier;
289   }
290
291   public String getOldName() {
292     return myOldName;
293   }
294
295   public boolean wasVararg() {
296     return myWasVarargs;
297   }
298
299   public boolean[] toRemoveParm() {
300     return new boolean[0];  //To change body of implemented methods use File | Settings | File Templates.
301   }
302
303   public PsiExpression getValue(int i, PsiCallExpression callExpression) {
304     if (defaultValues[i] != null) return defaultValues[i];
305     return parameters.get(i).getValue(callExpression);
306   }
307
308   public void updateMethod(PsiMethod psiMethod) {
309     if (psiMethod instanceof GrMethod) {
310       method = (GrMethod)psiMethod;
311     }
312   }
313 }