blob: 89d33540048de82c5ba9d498751666af89a40333 [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.codeInspection.utils;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyNamesUtil;
/**
* @author Max Medvedev
*/
public class JavaStylePropertiesUtil {
private static final Logger LOG = Logger.getInstance(JavaStylePropertiesUtil.class);
public static void fixJavaStyleProperty(GrMethodCall call) {
GrExpression invoked = call.getInvokedExpression();
String accessorName = ((GrReferenceExpression)invoked).getReferenceName();
if (isGetterInvocation(call) && invoked instanceof GrReferenceExpression) {
final GrExpression newCall = genRefForGetter(call, accessorName);
call.replaceWithExpression(newCall, true);
}
else if (isSetterInvocation(call) && invoked instanceof GrReferenceExpression) {
final GrStatement newCall = genRefForSetter(call, accessorName);
if(newCall != null) {
call.replaceWithStatement(newCall);
}
}
}
public static boolean isPropertyAccessor(GrMethodCall call) {
return !isInvokedOnMap(call) && (isGetterInvocation(call) || isSetterInvocation(call));
}
@Nullable
private static GrAssignmentExpression genRefForSetter(GrMethodCall call, String accessorName) {
String name = GroovyPropertyUtils.getPropertyNameBySetterName(accessorName);
if(name == null) return null;
GrExpression value = call.getExpressionArguments()[0];
GrReferenceExpression refExpr = (GrReferenceExpression)call.getInvokedExpression();
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject());
final GrAssignmentExpression assignment = (GrAssignmentExpression)factory.createStatementFromText("yyy = xxx", call);
GrReferenceExpression lvalueRef = (GrReferenceExpression)assignment.getLValue();
lvalueRef.setQualifier(refExpr.getQualifier());
lvalueRef.handleElementRenameSimple(name);
assignment.getRValue().replaceWithExpression(value, true);
return assignment;
}
private static GrExpression genRefForGetter(GrMethodCall call, String accessorName) {
String name = GroovyPropertyUtils.getPropertyNameByGetterName(accessorName, true);
GrReferenceExpression refExpr = (GrReferenceExpression)call.getInvokedExpression();
String oldNameStr = refExpr.getReferenceNameElement().getText();
String newRefExpr = StringUtil.trimEnd(refExpr.getText(), oldNameStr) + name;
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(call.getProject());
return factory.createExpressionFromText(newRefExpr, call);
}
private static boolean isInvokedOnMap(GrMethodCall call) {
GrExpression expr = call.getInvokedExpression();
return expr instanceof GrReferenceExpression && ResolveUtil.isKeyOfMap((GrReferenceExpression)expr);
}
private static boolean isSetterInvocation(GrMethodCall call) {
GrExpression expr = call.getInvokedExpression();
if (!(expr instanceof GrReferenceExpression)) return false;
GrReferenceExpression refExpr = (GrReferenceExpression)expr;
PsiMethod method;
if (call instanceof GrApplicationStatement) {
PsiElement element = refExpr.resolve();
if (!(element instanceof PsiMethod) || !GroovyPropertyUtils.isSimplePropertySetter(((PsiMethod)element))) return false;
method = (PsiMethod)element;
}
else {
method = call.resolveMethod();
if (!GroovyPropertyUtils.isSimplePropertySetter(method)) return false;
LOG.assertTrue(method != null);
}
if (!GroovyNamesUtil.isValidReference(GroovyPropertyUtils.getPropertyNameBySetterName(method.getName()),
((GrReferenceExpression)expr).getQualifier() != null,
call.getProject())) {
return false;
}
GrArgumentList args = call.getArgumentList();
if (args == null || args.getExpressionArguments().length != 1 || PsiImplUtil.hasNamedArguments(args)) {
return false;
}
GrAssignmentExpression assignment = genRefForSetter(call, refExpr.getReferenceName());
if(assignment != null) {
GrExpression value = assignment.getLValue();
if (value instanceof GrReferenceExpression &&
call.getManager().areElementsEquivalent(((GrReferenceExpression)value).resolve(), method)) {
return true;
}
}
return false;
}
private static boolean isGetterInvocation(@NotNull GrMethodCall call) {
GrExpression expr = call.getInvokedExpression();
if (!(expr instanceof GrReferenceExpression)) return false;
PsiMethod method = call.resolveMethod();
if (!GroovyPropertyUtils.isSimplePropertyGetter(method)) return false;
LOG.assertTrue(method != null);
if (!GroovyNamesUtil.isValidReference(GroovyPropertyUtils.getPropertyNameByGetterName(method.getName(), true),
((GrReferenceExpression)expr).getQualifier() != null,
call.getProject())) {
return false;
}
GrArgumentList args = call.getArgumentList();
if (args == null || args.getAllArguments().length != 0) {
return false;
}
GrExpression ref = genRefForGetter(call, ((GrReferenceExpression)expr).getReferenceName());
if (ref instanceof GrReferenceExpression) {
PsiElement resolved = ((GrReferenceExpression)ref).resolve();
PsiManager manager = call.getManager();
if (manager.areElementsEquivalent(resolved, method) || areEquivalentAccessors(method, resolved, manager)) {
return true;
}
}
return false;
}
private static boolean areEquivalentAccessors(PsiMethod method, PsiElement resolved, PsiManager manager) {
if (!(resolved instanceof GrAccessorMethod) || !(method instanceof GrAccessorMethod)) {
return false;
}
if (((GrAccessorMethod)resolved).isSetter() != ((GrAccessorMethod)method).isSetter()) return false;
GrField p1 = ((GrAccessorMethod)resolved).getProperty();
GrField p2 = ((GrAccessorMethod)method).getProperty();
return manager.areElementsEquivalent(p1, p2);
}
}