blob: 8211ced562df185cd3784f9e4afe1260fbc8fec7 [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.convertToJava;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
/**
* @author Max Medvedev
*/
public class SetterWriter {
private static final Logger LOG = Logger.getInstance(SetterWriter.class);
private final StringBuilder myBuffer;
private final PsiClass myClass;
private final PsiMethod mySetter;
private final String myName;
private final ClassNameProvider myClassNameProvider;
private final ExpressionContext myContext;
public SetterWriter(@NotNull StringBuilder builder,
@NotNull PsiClass psiClass,
@NotNull PsiMethod setter,
@NotNull String name,
@NotNull ClassNameProvider classNameProvider,
@NotNull ExpressionContext context) {
myBuffer = builder;
myClass = psiClass;
myClassNameProvider = classNameProvider;
myContext = context;
myName = name;
if (setter instanceof PsiCompiledElement) setter = (PsiMethod)((PsiCompiledElement)setter).getMirror();
mySetter = setter;
}
public void write() {
final boolean isStatic = mySetter.hasModifierProperty(PsiModifier.STATIC);
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(myContext.project);
PsiParameter[] parameters = mySetter.getParameterList().getParameters();
PsiParameter parameter = parameters[parameters.length - 1];
final PsiType parameterType = myContext.typeProvider.getParameterType(parameter);
myBuffer.append("private static ");
processTypeParameters(parameterType);
myBuffer.append(myName);
if (!(parameterType instanceof PsiPrimitiveType)) {
parameter = factory.createParameter(parameter.getName(), "Value", null);
}
PsiParameter[] actual = inferActualParameters(isStatic, parameters, parameter);
final GroovyPsiElement place = createStubMethod(actual);
GenerationUtil.writeParameterList(myBuffer, actual, myClassNameProvider, myContext);
writeBody(isStatic, parameters, parameter, place);
}
private void writeBody(boolean aStatic,
@NotNull PsiParameter[] parameters,
@NotNull PsiParameter parameter, final GroovyPsiElement place) {
//method body
myBuffer.append("{\n");
//arg initialization
myContext.myUsedVarNames.add("propOwner");
final GrExpression[] args = generateArguments(parameters, place);
new ExpressionGenerator(myBuffer, myContext).invokeMethodOn(
mySetter,
aStatic ? null : GroovyPsiElementFactory.getInstance(myContext.project).createExpressionFromText("propOwner", place),
args,
GrNamedArgument.EMPTY_ARRAY,
GrClosableBlock.EMPTY_ARRAY,
PsiSubstitutor.EMPTY,
place
);
myBuffer.append(";\n");
myBuffer.append("return ").append(parameter.getName()).append(";\n");
myBuffer.append("}\n");
}
@NotNull
private GrExpression[] generateArguments(@NotNull PsiParameter[] parameters, @NotNull GroovyPsiElement place) {
final GrExpression[] args = new GrExpression[parameters.length];
for (int i = 0; i < parameters.length; i++) {
args[i] = GroovyPsiElementFactory.getInstance(myContext.project).createExpressionFromText(parameters[i].getName(), place);
myContext.myUsedVarNames.add(parameters[i].getName());
}
return args;
}
private GroovyPsiElement createStubMethod(@NotNull PsiParameter[] parameters) {
StringBuilder methodText = new StringBuilder("def ").append(myName).append('(');
for (PsiParameter parameter : parameters) {
methodText.append(parameter.getType().getCanonicalText()).append(' ').append(parameter.getName()).append(',');
}
if (parameters.length > 0) methodText.deleteCharAt(methodText.length() - 1);
methodText.append("){}");
return GroovyPsiElementFactory.getInstance(myContext.project).createMethodFromText(methodText.toString(), mySetter);
}
@NotNull
private PsiParameter[] inferActualParameters(boolean aStatic,
@NotNull PsiParameter[] parameters,
@NotNull PsiParameter parameter) {
//parameters
parameters[parameters.length - 1] = parameter;
PsiParameter[] actual;
if (aStatic) {
actual = parameters;
}
else {
final String typeText;
final PsiClass containingClass = mySetter.getContainingClass();
if (containingClass == null) {
if (mySetter instanceof GrGdkMethod) {
typeText = ((GrGdkMethod)mySetter).getStaticMethod().getParameterList().getParameters()[0].getType().getCanonicalText();
}
else {
typeText = CommonClassNames.JAVA_LANG_OBJECT;
}
}
else {
typeText = containingClass.getQualifiedName();
}
final GrParameter propOwner = GroovyPsiElementFactory.getInstance(myContext.project).createParameter("propOwner", typeText, null);
actual = new PsiParameter[parameters.length + 1];
actual[0] = propOwner;
System.arraycopy(parameters, 0, actual, 1, parameters.length);
}
return actual;
}
private void processTypeParameters(PsiType parameterType) {
//type parameters
if (mySetter.hasTypeParameters()) {
GenerationUtil.writeTypeParameters(myBuffer, mySetter, myClassNameProvider);
}
if (parameterType instanceof PsiPrimitiveType) {
myBuffer.append(parameterType.getCanonicalText()).append(' ');
}
else {
if (mySetter.hasTypeParameters()) {
myBuffer.delete(myBuffer.length() - 1, myBuffer.length());
//builder.removeFromTheEnd(1);
myBuffer.append(", ");
}
else {
myBuffer.append('<');
}
myBuffer.append("Value");
if (!parameterType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
myBuffer.append(" extends ");
TypeWriter.writeType(myBuffer, parameterType, myClass, myClassNameProvider);
}
myBuffer.append('>');
myBuffer.append("Value ");
}
}
}