From a8549d760611fe1f4338f74009f392a74dbe8a7c Mon Sep 17 00:00:00 2001 From: Max Medvedev Date: Wed, 27 Feb 2013 18:41:07 +0400 Subject: [PATCH] IDEA-98316 Convert to Java: don't wrap access to maps into DGM.putAt/getAt --- plugins/groovy/src/META-INF/plugin.xml | 4 + .../convertToJava/ArgumentListGenerator.java | 11 +- .../convertToJava/ClassItemGeneratorImpl.java | 114 +---------- .../convertToJava/ExpressionGenerator.java | 29 +-- .../convertToJava/GenerationUtil.java | 41 ++-- .../convertToJava/SetterWriter.java | 192 ++++++++++++++++++ .../invocators/CustomMethodInvocator.java | 63 ++++++ .../invocators/MapGetterSetterInvocator.java | 80 ++++++++ .../convertGroovyToJava/file/arrayAccess.java | 4 +- 9 files changed, 386 insertions(+), 152 deletions(-) create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java create mode 100644 plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 02f721375eaa..2b7263145350 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -75,6 +75,8 @@ + + @@ -167,6 +169,8 @@ + + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java index 23222507f71f..046cdde417f8 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ArgumentListGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2013 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. @@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.NullUtils; import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap; @@ -49,10 +50,10 @@ class ArgumentListGenerator { } public void generate(@Nullable GrClosureSignature signature, - GrExpression[] exprs, - GrNamedArgument[] namedArgs, - GrClosableBlock[] clArgs, - GroovyPsiElement context) { + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] clArgs, + @NotNull GroovyPsiElement context) { GrClosureSignatureUtil.ArgInfo[] argInfos = signature == null ? null : GrClosureSignatureUtil.mapParametersToArguments(signature, namedArgs, exprs, clArgs, context, false, false); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java index 97d1caba3cd3..bc6882b5ce85 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClassItemGeneratorImpl.java @@ -37,7 +37,6 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; -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; @@ -384,116 +383,7 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { }, entries); } for (Map.Entry entry : entries) { - PsiMethod setter = entry.getKey(); - if (setter instanceof PsiCompiledElement) setter = (PsiMethod)((PsiCompiledElement)setter).getMirror(); - String name = entry.getValue(); - PsiParameter[] parameters = setter.getParameterList().getParameters(); - PsiParameter parameter = parameters[parameters.length - 1]; - final PsiType parameterType = context.typeProvider.getParameterType(parameter); - - - //type parameters - builder.append("private static "); - if (setter.hasTypeParameters()) { - writeTypeParameters(builder, setter, classNameProvider); - } - - if (parameterType instanceof PsiPrimitiveType) { - builder.append(parameterType.getCanonicalText()).append(' '); - } - else { - if (setter.hasTypeParameters()) { - builder.delete(builder.length()-1, builder.length()); - //builder.removeFromTheEnd(1); - builder.append(", "); - } - else { - builder.append('<'); - } - builder.append("Value"); - if (!parameterType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { - builder.append(" extends "); - writeType(builder, parameterType, psiClass, classNameProvider); - } - builder.append('>'); - builder.append("Value "); - } - builder.append(name); - - final boolean isStatic = setter.hasModifierProperty(PsiModifier.STATIC); - - - final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.project); - - if (!(parameterType instanceof PsiPrimitiveType)) { - parameter = factory.createParameter(parameter.getName(), "Value", null); - } - - //parameters - parameters[parameters.length - 1] = parameter; - PsiParameter[] actual; - if (isStatic) { - actual = parameters; - } - else { - final String typeText; - final PsiClass containingClass = setter.getContainingClass(); - if (containingClass == null) { - if (setter instanceof GrGdkMethod) { - typeText = ((GrGdkMethod)setter).getStaticMethod().getParameterList().getParameters()[0].getType().getCanonicalText(); - } - else { - typeText = CommonClassNames.JAVA_LANG_OBJECT; - } - } - else { - typeText = containingClass.getQualifiedName(); - } - - final GrParameter propOwner = factory.createParameter("propOwner", typeText, null); - - actual = new PsiParameter[parameters.length + 1]; - actual[0] = propOwner; - System.arraycopy(parameters, 0, actual, 1, parameters.length); - } - - - GenerationUtil.writeParameterList(builder, actual, classNameProvider, context); - - - //method body - builder.append("{\n"); - - //arg initialization - context.myUsedVarNames.add("propOwner"); - final GrExpression[] args = new GrExpression[parameters.length]; - for (int i = 0; i < parameters.length; i++) { - args[i] = factory.createExpressionFromText(parameters[i].getName()); - context.myUsedVarNames.add(parameters[i].getName()); - } - GroovyPsiElement place; - if (psiClass instanceof GroovyPsiElement) { - place = (GroovyPsiElement)psiClass; - } - else if (psiClass instanceof GroovyScriptClass) { - place = ((GroovyScriptClass)psiClass).getContainingFile(); - } - else { - LOG.error("wrong class!!!"); - place = null; - } - new ExpressionGenerator(builder, context).invokeMethodOn( - setter, - isStatic ? null : factory.createExpressionFromText("propOwner"), - args, - GrNamedArgument.EMPTY_ARRAY, - GrClosableBlock.EMPTY_ARRAY, - PsiSubstitutor.EMPTY, - place - ); - builder.append(";\n"); - builder.append("return ").append(parameter.getName()).append(";\n"); - builder.append("}\n"); + new SetterWriter(builder, psiClass, entry.getKey(), entry.getValue(), classNameProvider, context).write(); } final String name = context.getRefSetterName(); @@ -503,6 +393,8 @@ public class ClassItemGeneratorImpl implements ClassItemGenerator { } } + + public void writeImplementsList(StringBuilder text, PsiClass typeDefinition) { final Collection implementsTypes = new LinkedHashSet(); Collections.addAll(implementsTypes, typeDefinition.getImplementsListTypes()); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java index 3feab9d73313..62ee427be346 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java @@ -76,6 +76,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames; import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils; import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; +import org.jetbrains.plugins.groovy.refactoring.convertToJava.invocators.CustomMethodInvocator; import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.*; import static org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock.EMPTY_ARRAY; @@ -568,17 +569,16 @@ public class ExpressionGenerator extends Generator { private void writeAssignmentWithSetter(GrExpression qualifier, PsiMethod setter, GrAssignmentExpression assignment) { GrExpression rValue = getRValue(assignment); LOG.assertTrue(rValue != null); - writeAssignmentWithSetter(qualifier, setter, new GrExpression[]{rValue}, GrNamedArgument.EMPTY_ARRAY, EMPTY_ARRAY, PsiSubstitutor.EMPTY, - assignment); + writeAssignmentWithSetter(qualifier, setter, new GrExpression[]{rValue}, GrNamedArgument.EMPTY_ARRAY, EMPTY_ARRAY, PsiSubstitutor.EMPTY, assignment); } private void writeAssignmentWithSetter(@Nullable GrExpression qualifier, - PsiMethod method, - GrExpression[] exprs, - GrNamedArgument[] namedArgs, - GrClosableBlock[] closures, - PsiSubstitutor substitutor, - GrAssignmentExpression assignment) { + @NotNull PsiMethod method, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closures, + @NotNull PsiSubstitutor substitutor, + @NotNull GrAssignmentExpression assignment) { if (PsiUtil.isExpressionUsed(assignment)) { String setterName = context.getSetterName(method, assignment); GrExpression[] args; @@ -1291,14 +1291,15 @@ public class ExpressionGenerator extends Generator { builder.append(']'); } - public void invokeMethodOn(PsiMethod method, + public void invokeMethodOn(@NotNull PsiMethod method, @Nullable GrExpression caller, - GrExpression[] exprs, - GrNamedArgument[] namedArgs, - GrClosableBlock[] closures, - PsiSubstitutor substitutor, - GroovyPsiElement context) { + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closures, + @NotNull PsiSubstitutor substitutor, + @NotNull GroovyPsiElement context) { if (method instanceof GrGdkMethod) { + if (CustomMethodInvocator.invokeMethodOn(this, (GrGdkMethod)method, caller, exprs, namedArgs, closures, substitutor, context)) return; GrExpression[] newArgs = new GrExpression[exprs.length + 1]; System.arraycopy(exprs, 0, newArgs, 1, exprs.length); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java index e067001797bc..1d4982a8189a 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java @@ -153,22 +153,23 @@ public class GenerationUtil { } public static void invokeMethodByName(@Nullable GrExpression caller, - String methodName, - GrExpression[] exprs, - GrNamedArgument[] namedArgs, - GrClosableBlock[] closureArgs, - ExpressionGenerator expressionGenerator, - GroovyPsiElement psiContext) { + @NotNull String methodName, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closureArgs, + @NotNull ExpressionGenerator expressionGenerator, + @NotNull GroovyPsiElement psiContext) { GroovyResolveResult call = resolveMethod(caller, methodName, exprs, namedArgs, closureArgs, psiContext); invokeMethodByResolveResult(caller, call, methodName, exprs, namedArgs, closureArgs, expressionGenerator, psiContext); } + @NotNull public static GroovyResolveResult resolveMethod(@Nullable GrExpression caller, - String methodName, - GrExpression[] exprs, - GrNamedArgument[] namedArgs, - GrClosableBlock[] closureArgs, - GroovyPsiElement psiContext) { + @NotNull String methodName, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closureArgs, + @NotNull GroovyPsiElement psiContext) { GroovyResolveResult call = GroovyResolveResult.EMPTY_RESULT; final PsiType type; @@ -187,13 +188,13 @@ public class GenerationUtil { } public static void invokeMethodByResolveResult(@Nullable GrExpression caller, - GroovyResolveResult resolveResult, - String methodName, - GrExpression[] exprs, - GrNamedArgument[] namedArgs, - GrClosableBlock[] closureArgs, - ExpressionGenerator expressionGenerator, - GroovyPsiElement psiContext) { + @NotNull GroovyResolveResult resolveResult, + @NotNull String methodName, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closureArgs, + @NotNull ExpressionGenerator expressionGenerator, + @NotNull GroovyPsiElement psiContext) { final PsiElement resolved = resolveResult.getElement(); if (resolved instanceof PsiMethod) { final PsiSubstitutor substitutor = resolveResult.getSubstitutor(); @@ -213,8 +214,8 @@ public class GenerationUtil { argumentListGenerator.generate(null, exprs, namedArgs, closureArgs, psiContext); } - static void writeStatement(final StringBuilder codeBlockBuilder, - StringBuilder statementBuilder, + static void writeStatement(@NotNull StringBuilder codeBlockBuilder, + @NotNull StringBuilder statementBuilder, @Nullable GrStatement statement, @Nullable ExpressionContext context) { final PsiElement parent = statement == null ? null : statement.getParent(); diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java new file mode 100644 index 000000000000..9e881bc8963c --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SetterWriter.java @@ -0,0 +1,192 @@ +/* + * Copyright 2000-2013 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; + +import static org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil.writeTypeParameters; +import static org.jetbrains.plugins.groovy.refactoring.convertToJava.TypeWriter.writeType; + +/** + * @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()) { + 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 "); + writeType(myBuffer, parameterType, myClass, myClassNameProvider); + } + myBuffer.append('>'); + myBuffer.append("Value "); + } + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java new file mode 100644 index 000000000000..15d66a717375 --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/CustomMethodInvocator.java @@ -0,0 +1,63 @@ +/* + * Copyright 2000-2013 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.invocators; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiSubstitutor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +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.typedef.members.GrGdkMethod; +import org.jetbrains.plugins.groovy.refactoring.convertToJava.ExpressionGenerator; + +/** + * @author Max Medvedev + */ +public abstract class CustomMethodInvocator { + private static final ExtensionPointName EP_NAME = + ExtensionPointName.create("org.intellij.groovy.convertToJava.customMethodInvocator"); + + protected abstract boolean invoke(@NotNull ExpressionGenerator generator, + @NotNull PsiMethod method, + @Nullable GrExpression caller, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closures, + @NotNull PsiSubstitutor substitutor, + @NotNull GroovyPsiElement context); + + public static boolean invokeMethodOn(@NotNull ExpressionGenerator generator, + @NotNull GrGdkMethod method, + @Nullable GrExpression caller, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closures, + @NotNull PsiSubstitutor substitutor, + @NotNull GroovyPsiElement context) { + final PsiMethod staticMethod = method.getStaticMethod(); + for (CustomMethodInvocator invocator : EP_NAME.getExtensions()) { + if (invocator.invoke(generator, staticMethod, caller, exprs, namedArgs, closures, substitutor, context)) { + return true; + } + } + + return false; + } +} diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java new file mode 100644 index 000000000000..55ab3cb91d4d --- /dev/null +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/invocators/MapGetterSetterInvocator.java @@ -0,0 +1,80 @@ +/* + * Copyright 2000-2013 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.invocators; + +import com.intellij.psi.*; +import com.intellij.psi.util.InheritanceUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; +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.util.GroovyCommonClassNames; +import org.jetbrains.plugins.groovy.refactoring.convertToJava.ExpressionGenerator; +import org.jetbrains.plugins.groovy.refactoring.convertToJava.GenerationUtil; + +/** + * @author Max Medvedev + */ + +public class MapGetterSetterInvocator extends CustomMethodInvocator { + @Override + protected boolean invoke(@NotNull ExpressionGenerator generator, + @NotNull PsiMethod method, + @Nullable GrExpression caller, + @NotNull GrExpression[] exprs, + @NotNull GrNamedArgument[] namedArgs, + @NotNull GrClosableBlock[] closures, + @NotNull PsiSubstitutor substitutor, + @NotNull GroovyPsiElement context) { + if (!method.getName().equals("putAt") && !method.getName().equals("getAt")) return false; + + final PsiClass clazz = method.getContainingClass(); + if (clazz == null) return false; + + final String qname = clazz.getQualifiedName(); + if (!GroovyCommonClassNames.DEFAULT_GROOVY_METHODS.equals(qname)) return false; + + + if (caller == null) return false; + final PsiType type = caller.getType(); + + if (method.getName().equals("getAt")) { + if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { + GenerationUtil.invokeMethodByName(caller, "get", exprs, namedArgs, closures, generator, context); + return true; + } + else if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_LIST)) { + GenerationUtil.invokeMethodByName(caller, "get", exprs, namedArgs, closures, generator, context); + return true; + } + } + else if (method.getName().equals("putAt")) { + if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_MAP)) { + GenerationUtil.invokeMethodByName(caller, "put", exprs, namedArgs, closures, generator, context); + return true; + } + else if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_LIST)) { + GenerationUtil.invokeMethodByName(caller, "set", exprs, namedArgs, closures, generator, context); + return true; + } + } + + + return false; + } +} diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java index 19dfb233d0c9..49fc47dfd3c5 100644 --- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java +++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/arrayAccess.java @@ -18,7 +18,7 @@ java.util.HashMap map = new java.util.HashMa print(putAt0(map, "1", "6")); print(putAt0(map, 2, "7")); -org.codehaus.groovy.runtime.DefaultGroovyMethods.putAt(map, "6", 1); +map.put("6", 1); print(map.get("1")); print(map.get(2)); @@ -45,7 +45,7 @@ public arrayAccess() { super(); } private static Value putAt0(java.util.Map propOwner, K key, Value value) { -org.codehaus.groovy.runtime.DefaultGroovyMethods.putAt(propOwner, key, value); +propOwner.put(key, value); return value; } private static Value putAt1(Foo propOwner, java.lang.String s, java.lang.Integer x, Value value) {