| /* |
| * 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 "); |
| } |
| } |
| } |