blob: 81403b9a2fba06321b860e84140ac299357b0430 [file] [log] [blame]
/*
* 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.
*/
package org.jetbrains.plugins.groovy.refactoring.changeSignature;
import com.intellij.lang.Language;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.refactoring.changeSignature.JavaChangeInfo;
import com.intellij.refactoring.changeSignature.JavaParameterInfo;
import com.intellij.refactoring.changeSignature.ThrownExceptionInfo;
import com.intellij.refactoring.util.CanonicalTypes;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyLanguage;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* @author Maxim.Medvedev
*/
public class GrChangeInfoImpl implements JavaChangeInfo {
GrMethod method;
final String newName;
@Nullable final CanonicalTypes.Type returnType;
final String visibilityModifier;
final List<GrParameterInfo> parameters;
boolean changeParameters = false;
private boolean myIsParameterTypesChanged = false;
private boolean myIsParameterNamesChanged = false;
private boolean myIsNameChanged = false;
private boolean myIsVisibilityChanged = false;
private boolean myIsReturnTypeChanged = false;
private final boolean myIsRetainVarargs;
private final boolean myIsArrayToVarargs;
private final boolean myIsObtainVarargs;
private final boolean myWasVarargs;
private final String myOldName;
private PsiIdentifier myNewNameIdentifier;
private final PsiExpression[] defaultValues;
private final boolean myDelegate;
private final ThrownExceptionInfo[] myThrownExceptions;
private boolean myExceptionSetChanged;
private boolean myExceptionSetOrOrderChanged;
private final String[] myOldParameterNames;
private final String[] myOldParameterTypes;
public GrChangeInfoImpl(GrMethod method,
@Nullable String visibilityModifier,
@Nullable CanonicalTypes.Type returnType,
String newName,
List<GrParameterInfo> parameters, @Nullable ThrownExceptionInfo[] exceptions, boolean generateDelegate) {
this.method = method;
this.visibilityModifier = visibilityModifier;
this.returnType = returnType;
this.parameters = parameters;
this.newName = newName;
myDelegate = generateDelegate;
myOldName = method.getName();
if (!method.getName().equals(newName)) {
myIsNameChanged = true;
}
myIsVisibilityChanged = visibilityModifier != null && !method.hasModifierProperty(visibilityModifier);
if (!method.isConstructor()) {
PsiType oldReturnType = null;
if (method.getReturnTypeElementGroovy() != null) {
oldReturnType = method.getReturnType();
}
try {
PsiType newReturnType = returnType == null ? null : returnType.getType(method, getMethod().getManager());
if ((oldReturnType == null && newReturnType != null) || (oldReturnType != null && !oldReturnType.equals(newReturnType))) {
myIsReturnTypeChanged = true;
}
}
catch (IncorrectOperationException e) {
myIsReturnTypeChanged = true;
}
}
GrParameter[] params = method.getParameters();
final int oldParameterCount = this.method.getParameters().length;
myOldParameterNames = new String[oldParameterCount];
myOldParameterTypes = new String[oldParameterCount];
for (int i = 0; i < oldParameterCount; i++) {
GrParameter param = params[i];
myOldParameterNames[i] = param.getName();
myOldParameterTypes[i] = param.getType().getCanonicalText();
}
if (oldParameterCount != this.parameters.size()) {
changeParameters = true;
}
else {
for (int i = 0, parametersSize = parameters.size(); i < parametersSize; i++) {
GrParameterInfo parameter = parameters.get(i);
if (parameter.getOldIndex() != i) {
changeParameters = true;
break;
}
if (!params[i].getName().equals(parameter.getName())) {
myIsParameterNamesChanged = true;
}
try {
PsiType type = parameter.createType(method, method.getManager());
PsiType oldType = params[i].getType();
if (!oldType.equals(type)) {
myIsParameterTypesChanged = true;
}
}
catch (IncorrectOperationException e) {
myIsParameterTypesChanged = true;
}
}
}
myWasVarargs = method.isVarArgs();
if (parameters.isEmpty()) {
myIsObtainVarargs = false;
myIsRetainVarargs = false;
myIsArrayToVarargs = false;
}
else {
GrParameterInfo lastNewParam = parameters.get(parameters.size() - 1);
myIsObtainVarargs = lastNewParam.isVarargType();
myIsRetainVarargs = lastNewParam.getOldIndex() >= 0 && myIsObtainVarargs;
if (myIsRetainVarargs) {
final PsiType oldTypeForVararg = params[lastNewParam.getOldIndex()].getType();
myIsArrayToVarargs = (oldTypeForVararg instanceof PsiArrayType && !(oldTypeForVararg instanceof PsiEllipsisType));
}
else {
myIsArrayToVarargs = false;
}
}
if (myIsNameChanged) {
if (StringUtil.isJavaIdentifier(newName)) {
myNewNameIdentifier = JavaPsiFacade.getElementFactory(getMethod().getProject()).createIdentifier(newName);
}
else {
myNewNameIdentifier = getMethod().getNameIdentifier();
}
}
PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
defaultValues = new PsiExpression[parameters.size()];
for (int i = 0; i < parameters.size(); i++) {
JavaParameterInfo info = parameters.get(i);
if (info.getOldIndex() < 0 && !info.isVarargType()) {
if (info.getDefaultValue() == null) continue;
try {
defaultValues[i] = factory.createExpressionFromText(info.getDefaultValue(), method);
}
catch (IncorrectOperationException e) {
// LOG.error(e);
}
}
}
myThrownExceptions = exceptions;
if (exceptions == null) {
myExceptionSetChanged = false;
myExceptionSetOrOrderChanged = false;
}
else {
final PsiClassType[] thrownTypes = method.getThrowsList().getReferencedTypes();
if (thrownTypes.length != myThrownExceptions.length) {
myExceptionSetChanged = true;
myExceptionSetOrOrderChanged = true;
}
else {
myExceptionSetChanged = false;
for (int i = 0; i < myThrownExceptions.length; i++) {
ThrownExceptionInfo info = myThrownExceptions[i];
if (info.getOldIndex() < 0 || !thrownTypes[info.getOldIndex()].equals(info.createType(method, method.getManager()))) {
myExceptionSetChanged = true;
myExceptionSetOrOrderChanged = true;
break;
}
else if (info.getOldIndex() != i) {
myExceptionSetOrOrderChanged = true;
}
}
}
}
}
@Override
@NotNull
public JavaParameterInfo[] getNewParameters() {
return parameters.toArray(new GrParameterInfo[parameters.size()]);
}
@Override
public String getNewVisibility() {
return visibilityModifier;
}
@Override
public boolean isParameterSetOrOrderChanged() {
return changeParameters;
}
@Override
public boolean isParameterTypesChanged() {
return myIsParameterTypesChanged;
}
@Override
public boolean isParameterNamesChanged() {
return myIsParameterNamesChanged;
}
@Override
public boolean isGenerateDelegate() {
return myDelegate;
}
@Override
public boolean isNameChanged() {
return myIsNameChanged;
}
@Override
public boolean isVisibilityChanged() {
return myIsVisibilityChanged;
}
@Override
public boolean isExceptionSetChanged() {
return myExceptionSetChanged;
}
@Override
public boolean isExceptionSetOrOrderChanged() {
return myExceptionSetOrOrderChanged;
}
@Override
public GrMethod getMethod() {
return method;
}
@Override
public boolean isReturnTypeChanged() {
return myIsReturnTypeChanged;
}
@Override
public CanonicalTypes.Type getNewReturnType() {
return returnType;
}
@Override
public String getNewName() {
return newName;
}
@Override
public Language getLanguage() {
return GroovyLanguage.INSTANCE;
}
@Override
@NotNull
public String[] getOldParameterNames() {
return myOldParameterNames;
}
@Override
@NotNull
public String[] getOldParameterTypes() {
return myOldParameterTypes;
}
@Override
public ThrownExceptionInfo[] getNewExceptions() {
return myThrownExceptions;
}
@Override
public boolean isRetainsVarargs() {
return myIsRetainVarargs;
}
@Override
public boolean isObtainsVarags() {
return myIsObtainVarargs;
}
@Override
public boolean isArrayToVarargs() {
return myIsArrayToVarargs;
}
@Override
public PsiIdentifier getNewNameIdentifier() {
return myNewNameIdentifier;
}
@Override
public String getOldName() {
return myOldName;
}
@Override
public boolean wasVararg() {
return myWasVarargs;
}
@Override
public boolean[] toRemoveParm() {
return new boolean[0]; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public PsiExpression getValue(int i, PsiCallExpression callExpression) {
if (defaultValues[i] != null) return defaultValues[i];
return parameters.get(i).getValue(callExpression);
}
@Override
public void updateMethod(PsiMethod psiMethod) {
if (psiMethod instanceof GrMethod) {
method = (GrMethod)psiMethod;
}
}
@Override
public Collection<PsiMethod> getMethodsToPropagateParameters() {
return Collections.emptyList();
}
}