EA-33054 - IOE: PsiJavaParserFacadeImpl.createExpressionFromText
[idea/community.git] / java / java-impl / src / com / intellij / refactoring / changeSignature / JavaChangeInfoImpl.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
17 /**
18  * created at Sep 17, 2001
19  * @author Jeka
20  */
21 package com.intellij.refactoring.changeSignature;
22
23 import com.intellij.lang.Language;
24 import com.intellij.lang.StdLanguages;
25 import com.intellij.openapi.diagnostic.Logger;
26 import com.intellij.openapi.util.Comparing;
27 import com.intellij.openapi.util.text.StringUtil;
28 import com.intellij.psi.*;
29 import com.intellij.refactoring.util.CanonicalTypes;
30 import com.intellij.util.IncorrectOperationException;
31 import org.jetbrains.annotations.NotNull;
32 import org.jetbrains.annotations.Nullable;
33
34 import java.util.*;
35
36 class JavaChangeInfoImpl implements JavaChangeInfo {
37   private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeInfoImpl");
38
39   @PsiModifier.ModifierConstant
40   final String newVisibility;
41   private PsiMethod method;
42   String oldName;
43   final String oldType;
44   String[] oldParameterNames;
45   String[] oldParameterTypes;
46   final String newName;
47   final CanonicalTypes.Type newReturnType;
48   final ParameterInfoImpl[] newParms;
49   ThrownExceptionInfo[] newExceptions;
50   final boolean[] toRemoveParm;
51   boolean isVisibilityChanged = false;
52   boolean isNameChanged = false;
53   boolean isReturnTypeChanged = false;
54   boolean isParameterSetOrOrderChanged = false;
55   boolean isExceptionSetChanged = false;
56   boolean isExceptionSetOrOrderChanged = false;
57   boolean isParameterNamesChanged = false;
58   boolean isParameterTypesChanged = false;
59   boolean isPropagationEnabled = true;
60   final boolean wasVararg;
61   final boolean retainsVarargs;
62   final boolean obtainsVarags;
63   final boolean arrayToVarargs;
64   PsiIdentifier newNameIdentifier;
65 //  PsiType newTypeElement;
66   final PsiExpression[] defaultValues;
67
68   final boolean isGenerateDelegate;
69   final Set<PsiMethod> propagateParametersMethods;
70   final Set<PsiMethod> propagateExceptionsMethods;
71
72   /**
73    * @param newExceptions null if not changed
74    */
75   public JavaChangeInfoImpl(@PsiModifier.ModifierConstant String newVisibility,
76                     PsiMethod method,
77                     String newName,
78                     CanonicalTypes.Type newType,
79                     @NotNull ParameterInfoImpl[] newParms,
80                     ThrownExceptionInfo[] newExceptions,
81                     boolean generateDelegate,
82                     Set<PsiMethod> propagateParametersMethods,
83                     Set<PsiMethod> propagateExceptionsMethods) {
84     this(newVisibility, method, newName, newType, newParms, newExceptions, generateDelegate, propagateParametersMethods,
85          propagateExceptionsMethods, method.getName());
86   }
87
88   /**
89    * @param newExceptions null if not changed
90    * @param oldName
91    */
92   public JavaChangeInfoImpl(@PsiModifier.ModifierConstant String newVisibility,
93                             PsiMethod method,
94                             String newName,
95                             CanonicalTypes.Type newType,
96                             @NotNull ParameterInfoImpl[] newParms,
97                             ThrownExceptionInfo[] newExceptions,
98                             boolean generateDelegate,
99                             Set<PsiMethod> propagateParametersMethods,
100                             Set<PsiMethod> propagateExceptionsMethods,
101                             String oldName) {
102     this.newVisibility = newVisibility;
103     this.method = method;
104     this.newName = newName;
105     newReturnType = newType;
106     this.newParms = newParms;
107     wasVararg = method.isVarArgs();
108
109     this.isGenerateDelegate =generateDelegate;
110     this.propagateExceptionsMethods=propagateExceptionsMethods;
111     this.propagateParametersMethods=propagateParametersMethods;
112
113     this.oldName = oldName;
114     final PsiManager manager = method.getManager();
115     if (!method.isConstructor()){
116       oldType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeElement(method.getReturnType()).getText();
117     }
118     else{
119       oldType = null;
120     }
121     fillOldParams(method);
122
123     isVisibilityChanged = !method.hasModifierProperty(newVisibility);
124
125     isNameChanged = !newName.equals(this.oldName);
126
127     if (oldParameterNames.length != newParms.length){
128       isParameterSetOrOrderChanged = true;
129     }
130     else {
131       for(int i = 0; i < newParms.length; i++){
132         ParameterInfoImpl parmInfo = newParms[i];
133
134         if (i != parmInfo.oldParameterIndex){
135           isParameterSetOrOrderChanged = true;
136           break;
137         }
138         if (!parmInfo.getName().equals(oldParameterNames[i])){
139           isParameterNamesChanged = true;
140         }
141         try {
142           if (!parmInfo.getTypeText().equals(oldParameterTypes[i])){
143             isParameterTypesChanged = true;
144           }
145         }
146         catch (IncorrectOperationException e) {
147           isParameterTypesChanged = true;
148         }
149       }
150     }
151
152     setupPropagationEnabled(method.getParameterList().getParameters(), newParms);
153
154     setupExceptions(newExceptions, method);
155
156     toRemoveParm = new boolean[oldParameterNames.length];
157     Arrays.fill(toRemoveParm, true);
158     for (ParameterInfoImpl info : newParms) {
159       if (info.oldParameterIndex < 0) continue;
160       toRemoveParm[info.oldParameterIndex] = false;
161     }
162
163     PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
164     defaultValues = new PsiExpression[newParms.length];
165     for(int i = 0; i < newParms.length; i++){
166       ParameterInfoImpl info = newParms[i];
167       if (info.oldParameterIndex < 0 && !info.isVarargType()){
168         if (StringUtil.isEmpty(info.defaultValue)) continue;
169         try{
170           defaultValues[i] = factory.createExpressionFromText(info.defaultValue, method);
171         }
172         catch(IncorrectOperationException e){
173           LOG.info(e);
174         }
175       }
176     }
177
178     if (this.newParms.length == 0) {
179       retainsVarargs = false;
180       obtainsVarags = false;
181       arrayToVarargs = false;
182     }
183     else {
184       final ParameterInfoImpl lastNewParm = this.newParms[this.newParms.length - 1];
185       obtainsVarags = lastNewParm.isVarargType();
186       retainsVarargs = lastNewParm.oldParameterIndex >= 0 && obtainsVarags;
187       if (retainsVarargs) {
188         arrayToVarargs = oldParameterTypes[lastNewParm.oldParameterIndex].endsWith("[]");
189       }
190       else {
191         arrayToVarargs = false;
192       }
193     }
194
195     if (isNameChanged) {
196       newNameIdentifier = factory.createIdentifier(newName);
197     }
198
199   }
200
201   protected void fillOldParams(PsiMethod method) {
202     PsiParameter[] parameters = method.getParameterList().getParameters();
203     oldParameterNames = new String[parameters.length];
204     oldParameterTypes = new String[parameters.length];
205     for(int i = 0; i < parameters.length; i++){
206       PsiParameter parameter = parameters[i];
207       oldParameterNames[i] = parameter.getName();
208       oldParameterTypes[i] =
209         JavaPsiFacade.getInstance(parameter.getProject()).getElementFactory().createTypeElement(parameter.getType()).getText();
210     }
211     if (!method.isConstructor()){
212       try {
213         isReturnTypeChanged = !newReturnType.getType(this.method, method.getManager()).equals(this.method.getReturnType());
214       }
215       catch (IncorrectOperationException e) {
216         isReturnTypeChanged = true;
217       }
218     }
219   }
220
221   @NotNull
222   public JavaParameterInfo[] getNewParameters() {
223     return newParms;
224   }
225
226   @PsiModifier.ModifierConstant
227   public String getNewVisibility() {
228     return newVisibility;
229   }
230
231   public boolean isParameterSetOrOrderChanged() {
232     return isParameterSetOrOrderChanged;
233   }
234
235   private void setupExceptions(ThrownExceptionInfo[] newExceptions, final PsiMethod method) {
236     if (newExceptions == null) newExceptions = JavaThrownExceptionInfo.extractExceptions(method);
237
238     this.newExceptions = newExceptions;
239
240     PsiClassType[] types = method.getThrowsList().getReferencedTypes();
241     isExceptionSetChanged = newExceptions.length != types.length;
242     if (!isExceptionSetChanged) {
243       for (int i = 0; i < newExceptions.length; i++) {
244         try {
245           if (newExceptions[i].getOldIndex() < 0 || !types[i].equals(newExceptions[i].createType(method, method.getManager()))) {
246             isExceptionSetChanged = true;
247             break;
248           }
249         }
250         catch (IncorrectOperationException e) {
251           isExceptionSetChanged = true;
252         }
253         if (newExceptions[i].getOldIndex() != i) isExceptionSetOrOrderChanged = true;
254       }
255     }
256
257     isExceptionSetOrOrderChanged |= isExceptionSetChanged;
258   }
259
260   protected void setupPropagationEnabled(final PsiParameter[] parameters, final ParameterInfoImpl[] newParms) {
261     if (parameters.length >= newParms.length) {
262       isPropagationEnabled = false;
263     }
264     else {
265       for (int i = 0; i < parameters.length; i++) {
266         final ParameterInfoImpl newParm = newParms[i];
267         if (newParm.oldParameterIndex != i) {
268           isPropagationEnabled = false;
269           break;
270         }
271       }
272     }
273   }
274
275   public PsiMethod getMethod() {
276     return method;
277   }
278
279   public CanonicalTypes.Type getNewReturnType() {
280     return newReturnType;
281   }
282
283   public void updateMethod(PsiMethod method) {
284     this.method = method;
285   }
286
287   @Override
288   public Collection<PsiMethod> getMethodsToPropagateParameters() {
289     return propagateParametersMethods;
290   }
291
292   public ParameterInfoImpl[] getCreatedParmsInfoWithoutVarargs() {
293     List<ParameterInfoImpl> result = new ArrayList<ParameterInfoImpl>();
294     for (ParameterInfoImpl newParm : newParms) {
295       if (newParm.oldParameterIndex < 0 && !newParm.isVarargType()) {
296         result.add(newParm);
297       }
298     }
299     return result.toArray(new ParameterInfoImpl[result.size()]);
300   }
301
302   @Nullable
303   public PsiExpression getValue(int i, PsiCallExpression expr) throws IncorrectOperationException {
304     if (defaultValues[i] != null) return defaultValues[i];
305     return newParms[i].getValue(expr);
306   }
307
308   public boolean isVisibilityChanged() {
309     return isVisibilityChanged;
310   }
311
312   public boolean isNameChanged() {
313     return isNameChanged;
314   }
315
316   public boolean isReturnTypeChanged() {
317     return isReturnTypeChanged;
318   }
319
320   public String getNewName() {
321     return newName;
322   }
323
324   public Language getLanguage() {
325     return StdLanguages.JAVA;
326   }
327
328   public boolean isExceptionSetChanged() {
329     return isExceptionSetChanged;
330   }
331
332   public boolean isExceptionSetOrOrderChanged() {
333     return isExceptionSetOrOrderChanged;
334   }
335
336   public boolean isParameterNamesChanged() {
337     return isParameterNamesChanged;
338   }
339
340   public boolean isParameterTypesChanged() {
341     return isParameterTypesChanged;
342   }
343
344   public boolean isGenerateDelegate() {
345     return isGenerateDelegate;
346   }
347
348   @NotNull
349   public String[] getOldParameterNames() {
350     return oldParameterNames;
351   }
352
353   @NotNull
354   public String[] getOldParameterTypes() {
355     return oldParameterTypes;
356   }
357
358   public ThrownExceptionInfo[] getNewExceptions() {
359     return newExceptions;
360   }
361
362   public boolean isRetainsVarargs() {
363     return retainsVarargs;
364   }
365
366   public boolean isObtainsVarags() {
367     return obtainsVarags;
368   }
369
370   public boolean isArrayToVarargs() {
371     return arrayToVarargs;
372   }
373
374   public PsiIdentifier getNewNameIdentifier() {
375     return newNameIdentifier;
376   }
377
378   public String getOldName() {
379     return oldName;
380   }
381
382   public boolean wasVararg() {
383     return wasVararg;
384   }
385
386   public boolean[] toRemoveParm() {
387     return toRemoveParm;
388   }
389
390   protected boolean checkMethodEquality() {
391     return true;
392   }
393
394   @Override
395   public boolean equals(Object o) {
396     if (this == o) return true;
397     if (!(o instanceof JavaChangeInfoImpl)) return false;
398
399     JavaChangeInfoImpl that = (JavaChangeInfoImpl)o;
400
401     if (arrayToVarargs != that.arrayToVarargs) return false;
402     if (isExceptionSetChanged != that.isExceptionSetChanged) return false;
403     if (isExceptionSetOrOrderChanged != that.isExceptionSetOrOrderChanged) return false;
404     if (isGenerateDelegate != that.isGenerateDelegate) return false;
405     if (isNameChanged != that.isNameChanged) return false;
406     if (isParameterNamesChanged != that.isParameterNamesChanged) return false;
407     if (isParameterSetOrOrderChanged != that.isParameterSetOrOrderChanged) return false;
408     if (isParameterTypesChanged != that.isParameterTypesChanged) return false;
409     if (isPropagationEnabled != that.isPropagationEnabled) return false;
410     if (isReturnTypeChanged != that.isReturnTypeChanged) return false;
411     if (isVisibilityChanged != that.isVisibilityChanged) return false;
412     if (obtainsVarags != that.obtainsVarags) return false;
413     if (retainsVarargs != that.retainsVarargs) return false;
414     if (wasVararg != that.wasVararg) return false;
415     if (!Arrays.equals(defaultValues, that.defaultValues)) return false;
416     if (checkMethodEquality() && !method.equals(that.method)) return false;
417     if (!Arrays.equals(newExceptions, that.newExceptions)) return false;
418     if (!newName.equals(that.newName)) return false;
419     if (newNameIdentifier != null ? !newNameIdentifier.equals(that.newNameIdentifier) : that.newNameIdentifier != null) return false;
420     if (!Arrays.equals(newParms, that.newParms)) return false;
421     if (newReturnType != null ? that.newReturnType == null || !Comparing.strEqual(newReturnType.getTypeText(), that.newReturnType.getTypeText()) : that.newReturnType != null) return false;
422     if (newVisibility != null ? !newVisibility.equals(that.newVisibility) : that.newVisibility != null) return false;
423     if (!oldName.equals(that.oldName)) return false;
424     if (!Arrays.equals(oldParameterNames, that.oldParameterNames)) return false;
425     if (!Arrays.equals(oldParameterTypes, that.oldParameterTypes)) return false;
426     if (oldType != null ? !oldType.equals(that.oldType): that.oldType != null) return false;
427     if (!propagateExceptionsMethods.equals(that.propagateExceptionsMethods)) return false;
428     if (!propagateParametersMethods.equals(that.propagateParametersMethods)) return false;
429     if (!Arrays.equals(toRemoveParm, that.toRemoveParm)) return false;
430
431     return true;
432   }
433
434   @Override
435   public int hashCode() {
436     int result = newVisibility != null ? newVisibility.hashCode() : 0;
437     if (checkMethodEquality()) {
438       result = 31 * result + method.hashCode();
439     }
440     result = 31 * result + oldName.hashCode();
441     result = 31 * result +(oldType != null ? oldType.hashCode() : 0);
442     result = 31 * result + Arrays.hashCode(oldParameterNames);
443     result = 31 * result + Arrays.hashCode(oldParameterTypes);
444     result = 31 * result + newName.hashCode();
445     result = 31 * result + (newReturnType != null ? newReturnType.getTypeText().hashCode() : 0);
446     result = 31 * result + Arrays.hashCode(newParms);
447     result = 31 * result + Arrays.hashCode(newExceptions);
448     result = 31 * result + Arrays.hashCode(toRemoveParm);
449     result = 31 * result + (isVisibilityChanged ? 1 : 0);
450     result = 31 * result + (isNameChanged ? 1 : 0);
451     result = 31 * result + (isReturnTypeChanged ? 1 : 0);
452     result = 31 * result + (isParameterSetOrOrderChanged ? 1 : 0);
453     result = 31 * result + (isExceptionSetChanged ? 1 : 0);
454     result = 31 * result + (isExceptionSetOrOrderChanged ? 1 : 0);
455     result = 31 * result + (isParameterNamesChanged ? 1 : 0);
456     result = 31 * result + (isParameterTypesChanged ? 1 : 0);
457     result = 31 * result + (isPropagationEnabled ? 1 : 0);
458     result = 31 * result + (wasVararg ? 1 : 0);
459     result = 31 * result + (retainsVarargs ? 1 : 0);
460     result = 31 * result + (obtainsVarags ? 1 : 0);
461     result = 31 * result + (arrayToVarargs ? 1 : 0);
462     result = 31 * result + (newNameIdentifier != null ? newNameIdentifier.hashCode() : 0);
463     result = 31 * result + (defaultValues != null ? Arrays.hashCode(defaultValues) : 0);
464     result = 31 * result + (isGenerateDelegate ? 1 : 0);
465     result = 31 * result + propagateParametersMethods.hashCode();
466     result = 31 * result + propagateExceptionsMethods.hashCode();
467     return result;
468   }
469 }