| /* |
| * Copyright 2000-2014 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /** |
| * created at Sep 17, 2001 |
| * @author Jeka |
| */ |
| package com.intellij.refactoring.changeSignature; |
| |
| import com.intellij.lang.Language; |
| import com.intellij.lang.StdLanguages; |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.Comparing; |
| import com.intellij.openapi.util.text.StringUtil; |
| import com.intellij.psi.*; |
| import com.intellij.refactoring.util.CanonicalTypes; |
| import com.intellij.util.IncorrectOperationException; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.*; |
| |
| import static com.intellij.refactoring.changeSignature.ChangeSignatureUtil.deepTypeEqual; |
| |
| class JavaChangeInfoImpl implements JavaChangeInfo { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.changeSignature.JavaChangeInfoImpl"); |
| |
| @PsiModifier.ModifierConstant |
| final String newVisibility; |
| private PsiMethod method; |
| String oldName; |
| final String oldType; |
| String[] oldParameterNames; |
| String[] oldParameterTypes; |
| final String newName; |
| final CanonicalTypes.Type newReturnType; |
| final ParameterInfoImpl[] newParms; |
| ThrownExceptionInfo[] newExceptions; |
| final boolean[] toRemoveParm; |
| boolean isVisibilityChanged = false; |
| boolean isNameChanged = false; |
| boolean isReturnTypeChanged = false; |
| boolean isParameterSetOrOrderChanged = false; |
| boolean isExceptionSetChanged = false; |
| boolean isExceptionSetOrOrderChanged = false; |
| boolean isParameterNamesChanged = false; |
| boolean isParameterTypesChanged = false; |
| boolean isPropagationEnabled = true; |
| final boolean wasVararg; |
| final boolean retainsVarargs; |
| final boolean obtainsVarags; |
| final boolean arrayToVarargs; |
| PsiIdentifier newNameIdentifier; |
| // PsiType newTypeElement; |
| final PsiExpression[] defaultValues; |
| |
| final boolean isGenerateDelegate; |
| final Set<PsiMethod> propagateParametersMethods; |
| final Set<PsiMethod> propagateExceptionsMethods; |
| |
| /** |
| * @param newExceptions null if not changed |
| */ |
| public JavaChangeInfoImpl(@PsiModifier.ModifierConstant String newVisibility, |
| PsiMethod method, |
| String newName, |
| CanonicalTypes.Type newType, |
| @NotNull ParameterInfoImpl[] newParms, |
| ThrownExceptionInfo[] newExceptions, |
| boolean generateDelegate, |
| Set<PsiMethod> propagateParametersMethods, |
| Set<PsiMethod> propagateExceptionsMethods) { |
| this(newVisibility, method, newName, newType, newParms, newExceptions, generateDelegate, propagateParametersMethods, |
| propagateExceptionsMethods, method.getName()); |
| } |
| |
| /** |
| * @param newExceptions null if not changed |
| * @param oldName |
| */ |
| public JavaChangeInfoImpl(@PsiModifier.ModifierConstant String newVisibility, |
| PsiMethod method, |
| String newName, |
| CanonicalTypes.Type newType, |
| @NotNull ParameterInfoImpl[] newParms, |
| ThrownExceptionInfo[] newExceptions, |
| boolean generateDelegate, |
| Set<PsiMethod> propagateParametersMethods, |
| Set<PsiMethod> propagateExceptionsMethods, |
| String oldName) { |
| this.newVisibility = newVisibility; |
| this.method = method; |
| this.newName = newName; |
| newReturnType = newType; |
| this.newParms = newParms; |
| wasVararg = method.isVarArgs(); |
| |
| this.isGenerateDelegate =generateDelegate; |
| this.propagateExceptionsMethods=propagateExceptionsMethods; |
| this.propagateParametersMethods=propagateParametersMethods; |
| |
| this.oldName = oldName; |
| final PsiManager manager = method.getManager(); |
| if (!method.isConstructor()){ |
| oldType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeElement(method.getReturnType()).getText(); |
| } |
| else{ |
| oldType = null; |
| } |
| fillOldParams(method); |
| |
| isVisibilityChanged = !method.hasModifierProperty(newVisibility); |
| |
| isNameChanged = !newName.equals(this.oldName); |
| |
| if (oldParameterNames.length != newParms.length){ |
| isParameterSetOrOrderChanged = true; |
| } |
| else { |
| for(int i = 0; i < newParms.length; i++){ |
| ParameterInfoImpl parmInfo = newParms[i]; |
| |
| if (i != parmInfo.oldParameterIndex){ |
| isParameterSetOrOrderChanged = true; |
| break; |
| } |
| if (!parmInfo.getName().equals(oldParameterNames[i])){ |
| isParameterNamesChanged = true; |
| } |
| try { |
| if (!parmInfo.getTypeText().equals(oldParameterTypes[i])){ |
| isParameterTypesChanged = true; |
| } |
| } |
| catch (IncorrectOperationException e) { |
| isParameterTypesChanged = true; |
| } |
| } |
| } |
| |
| setupPropagationEnabled(method.getParameterList().getParameters(), newParms); |
| |
| setupExceptions(newExceptions, method); |
| |
| toRemoveParm = new boolean[oldParameterNames.length]; |
| Arrays.fill(toRemoveParm, true); |
| for (ParameterInfoImpl info : newParms) { |
| if (info.oldParameterIndex < 0) continue; |
| toRemoveParm[info.oldParameterIndex] = false; |
| } |
| |
| PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory(); |
| defaultValues = new PsiExpression[newParms.length]; |
| for(int i = 0; i < newParms.length; i++){ |
| ParameterInfoImpl info = newParms[i]; |
| if (info.oldParameterIndex < 0 && !info.isVarargType()){ |
| if (StringUtil.isEmpty(info.defaultValue)) continue; |
| try{ |
| defaultValues[i] = factory.createExpressionFromText(info.defaultValue, method); |
| } |
| catch(IncorrectOperationException e){ |
| LOG.info(e); |
| } |
| } |
| } |
| |
| if (this.newParms.length == 0) { |
| retainsVarargs = false; |
| obtainsVarags = false; |
| arrayToVarargs = false; |
| } |
| else { |
| final ParameterInfoImpl lastNewParm = this.newParms[this.newParms.length - 1]; |
| obtainsVarags = lastNewParm.isVarargType(); |
| retainsVarargs = lastNewParm.oldParameterIndex >= 0 && obtainsVarags; |
| if (retainsVarargs) { |
| arrayToVarargs = oldParameterTypes[lastNewParm.oldParameterIndex].endsWith("[]"); |
| } |
| else { |
| arrayToVarargs = false; |
| } |
| } |
| |
| if (isNameChanged) { |
| newNameIdentifier = factory.createIdentifier(newName); |
| } |
| } |
| |
| protected void fillOldParams(PsiMethod method) { |
| PsiParameter[] parameters = method.getParameterList().getParameters(); |
| oldParameterNames = new String[parameters.length]; |
| oldParameterTypes = new String[parameters.length]; |
| |
| PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory(); |
| for (int i = 0; i < parameters.length; i++) { |
| PsiParameter parameter = parameters[i]; |
| oldParameterNames[i] = parameter.getName(); |
| oldParameterTypes[i] = factory.createTypeElement(parameter.getType()).getText(); |
| } |
| if (!method.isConstructor()){ |
| try { |
| isReturnTypeChanged = !deepTypeEqual(newReturnType.getType(this.method, method.getManager()), this.method.getReturnType()); |
| } |
| catch (IncorrectOperationException e) { |
| isReturnTypeChanged = true; |
| } |
| } |
| } |
| |
| @NotNull |
| public JavaParameterInfo[] getNewParameters() { |
| return newParms; |
| } |
| |
| @PsiModifier.ModifierConstant |
| public String getNewVisibility() { |
| return newVisibility; |
| } |
| |
| public boolean isParameterSetOrOrderChanged() { |
| return isParameterSetOrOrderChanged; |
| } |
| |
| private void setupExceptions(ThrownExceptionInfo[] newExceptions, final PsiMethod method) { |
| if (newExceptions == null) { |
| newExceptions = JavaThrownExceptionInfo.extractExceptions(method); |
| } |
| |
| this.newExceptions = newExceptions; |
| |
| PsiClassType[] types = method.getThrowsList().getReferencedTypes(); |
| isExceptionSetChanged = newExceptions.length != types.length; |
| if (!isExceptionSetChanged) { |
| for (int i = 0; i < newExceptions.length; i++) { |
| try { |
| if (newExceptions[i].getOldIndex() < 0 || !deepTypeEqual(types[i], newExceptions[i].createType(method, method.getManager()))) { |
| isExceptionSetChanged = true; |
| break; |
| } |
| } |
| catch (IncorrectOperationException e) { |
| isExceptionSetChanged = true; |
| } |
| if (newExceptions[i].getOldIndex() != i) isExceptionSetOrOrderChanged = true; |
| } |
| } |
| |
| isExceptionSetOrOrderChanged |= isExceptionSetChanged; |
| } |
| |
| protected void setupPropagationEnabled(final PsiParameter[] parameters, final ParameterInfoImpl[] newParms) { |
| if (parameters.length >= newParms.length) { |
| isPropagationEnabled = false; |
| } |
| else { |
| isPropagationEnabled = !propagateParametersMethods.isEmpty(); |
| for (int i = 0; i < parameters.length; i++) { |
| final ParameterInfoImpl newParm = newParms[i]; |
| if (newParm.oldParameterIndex != i) { |
| isPropagationEnabled = false; |
| break; |
| } |
| } |
| } |
| } |
| |
| public PsiMethod getMethod() { |
| return method; |
| } |
| |
| public CanonicalTypes.Type getNewReturnType() { |
| return newReturnType; |
| } |
| |
| public void updateMethod(PsiMethod method) { |
| this.method = method; |
| } |
| |
| @Override |
| public Collection<PsiMethod> getMethodsToPropagateParameters() { |
| return propagateParametersMethods; |
| } |
| |
| public ParameterInfoImpl[] getCreatedParmsInfoWithoutVarargs() { |
| List<ParameterInfoImpl> result = new ArrayList<ParameterInfoImpl>(); |
| for (ParameterInfoImpl newParm : newParms) { |
| if (newParm.oldParameterIndex < 0 && !newParm.isVarargType()) { |
| result.add(newParm); |
| } |
| } |
| return result.toArray(new ParameterInfoImpl[result.size()]); |
| } |
| |
| @Nullable |
| public PsiExpression getValue(int i, PsiCallExpression expr) throws IncorrectOperationException { |
| if (defaultValues[i] != null) return defaultValues[i]; |
| return newParms[i].getValue(expr); |
| } |
| |
| public boolean isVisibilityChanged() { |
| return isVisibilityChanged; |
| } |
| |
| public boolean isNameChanged() { |
| return isNameChanged; |
| } |
| |
| public boolean isReturnTypeChanged() { |
| return isReturnTypeChanged; |
| } |
| |
| public String getNewName() { |
| return newName; |
| } |
| |
| public Language getLanguage() { |
| return StdLanguages.JAVA; |
| } |
| |
| public boolean isExceptionSetChanged() { |
| return isExceptionSetChanged; |
| } |
| |
| public boolean isExceptionSetOrOrderChanged() { |
| return isExceptionSetOrOrderChanged; |
| } |
| |
| public boolean isParameterNamesChanged() { |
| return isParameterNamesChanged; |
| } |
| |
| public boolean isParameterTypesChanged() { |
| return isParameterTypesChanged; |
| } |
| |
| public boolean isGenerateDelegate() { |
| return isGenerateDelegate; |
| } |
| |
| @NotNull |
| public String[] getOldParameterNames() { |
| return oldParameterNames; |
| } |
| |
| @NotNull |
| public String[] getOldParameterTypes() { |
| return oldParameterTypes; |
| } |
| |
| public ThrownExceptionInfo[] getNewExceptions() { |
| return newExceptions; |
| } |
| |
| public boolean isRetainsVarargs() { |
| return retainsVarargs; |
| } |
| |
| public boolean isObtainsVarags() { |
| return obtainsVarags; |
| } |
| |
| public boolean isArrayToVarargs() { |
| return arrayToVarargs; |
| } |
| |
| public PsiIdentifier getNewNameIdentifier() { |
| return newNameIdentifier; |
| } |
| |
| public String getOldName() { |
| return oldName; |
| } |
| |
| public boolean wasVararg() { |
| return wasVararg; |
| } |
| |
| public boolean[] toRemoveParm() { |
| return toRemoveParm; |
| } |
| |
| protected boolean checkMethodEquality() { |
| return true; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (!(o instanceof JavaChangeInfoImpl)) return false; |
| |
| JavaChangeInfoImpl that = (JavaChangeInfoImpl)o; |
| |
| if (arrayToVarargs != that.arrayToVarargs) return false; |
| if (isExceptionSetChanged != that.isExceptionSetChanged) return false; |
| if (isExceptionSetOrOrderChanged != that.isExceptionSetOrOrderChanged) return false; |
| if (isGenerateDelegate != that.isGenerateDelegate) return false; |
| if (isNameChanged != that.isNameChanged) return false; |
| if (isParameterNamesChanged != that.isParameterNamesChanged) return false; |
| if (isParameterSetOrOrderChanged != that.isParameterSetOrOrderChanged) return false; |
| if (isParameterTypesChanged != that.isParameterTypesChanged) return false; |
| if (isPropagationEnabled != that.isPropagationEnabled) return false; |
| if (isReturnTypeChanged != that.isReturnTypeChanged) return false; |
| if (isVisibilityChanged != that.isVisibilityChanged) return false; |
| if (obtainsVarags != that.obtainsVarags) return false; |
| if (retainsVarargs != that.retainsVarargs) return false; |
| if (wasVararg != that.wasVararg) return false; |
| if (!Arrays.equals(defaultValues, that.defaultValues)) return false; |
| if (checkMethodEquality() && !method.equals(that.method)) return false; |
| if (!Arrays.equals(newExceptions, that.newExceptions)) return false; |
| if (!newName.equals(that.newName)) return false; |
| if (newNameIdentifier != null ? !newNameIdentifier.equals(that.newNameIdentifier) : that.newNameIdentifier != null) return false; |
| if (!Arrays.equals(newParms, that.newParms)) return false; |
| if (newReturnType != null ? that.newReturnType == null || !Comparing.strEqual(newReturnType.getTypeText(), that.newReturnType.getTypeText()) : that.newReturnType != null) return false; |
| if (newVisibility != null ? !newVisibility.equals(that.newVisibility) : that.newVisibility != null) return false; |
| if (!oldName.equals(that.oldName)) return false; |
| if (!Arrays.equals(oldParameterNames, that.oldParameterNames)) return false; |
| if (!Arrays.equals(oldParameterTypes, that.oldParameterTypes)) return false; |
| if (oldType != null ? !oldType.equals(that.oldType): that.oldType != null) return false; |
| if (!propagateExceptionsMethods.equals(that.propagateExceptionsMethods)) return false; |
| if (!propagateParametersMethods.equals(that.propagateParametersMethods)) return false; |
| if (!Arrays.equals(toRemoveParm, that.toRemoveParm)) return false; |
| |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| int result = newVisibility != null ? newVisibility.hashCode() : 0; |
| if (checkMethodEquality()) { |
| result = 31 * result + method.hashCode(); |
| } |
| result = 31 * result + oldName.hashCode(); |
| result = 31 * result +(oldType != null ? oldType.hashCode() : 0); |
| result = 31 * result + Arrays.hashCode(oldParameterNames); |
| result = 31 * result + Arrays.hashCode(oldParameterTypes); |
| result = 31 * result + newName.hashCode(); |
| result = 31 * result + (newReturnType != null ? newReturnType.getTypeText().hashCode() : 0); |
| result = 31 * result + Arrays.hashCode(newParms); |
| result = 31 * result + Arrays.hashCode(newExceptions); |
| result = 31 * result + Arrays.hashCode(toRemoveParm); |
| result = 31 * result + (isVisibilityChanged ? 1 : 0); |
| result = 31 * result + (isNameChanged ? 1 : 0); |
| result = 31 * result + (isReturnTypeChanged ? 1 : 0); |
| result = 31 * result + (isParameterSetOrOrderChanged ? 1 : 0); |
| result = 31 * result + (isExceptionSetChanged ? 1 : 0); |
| result = 31 * result + (isExceptionSetOrOrderChanged ? 1 : 0); |
| result = 31 * result + (isParameterNamesChanged ? 1 : 0); |
| result = 31 * result + (isParameterTypesChanged ? 1 : 0); |
| result = 31 * result + (isPropagationEnabled ? 1 : 0); |
| result = 31 * result + (wasVararg ? 1 : 0); |
| result = 31 * result + (retainsVarargs ? 1 : 0); |
| result = 31 * result + (obtainsVarags ? 1 : 0); |
| result = 31 * result + (arrayToVarargs ? 1 : 0); |
| result = 31 * result + (newNameIdentifier != null ? newNameIdentifier.hashCode() : 0); |
| result = 31 * result + (defaultValues != null ? Arrays.hashCode(defaultValues) : 0); |
| result = 31 * result + (isGenerateDelegate ? 1 : 0); |
| result = 31 * result + propagateParametersMethods.hashCode(); |
| result = 31 * result + propagateExceptionsMethods.hashCode(); |
| return result; |
| } |
| } |