diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java index 3bedee7a826c..ead53e12c190 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2009 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -38,7 +38,6 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyFileType; import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory; -import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList; @@ -47,6 +46,7 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlo import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCall; import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter; import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; @@ -103,19 +103,25 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP final GrClosureSignatureUtil.ArgInfo[] actualArgs = GrClosureSignatureUtil.mapParametersToArguments(signature, argList, callExpression, callExpression.getClosureArguments(), true); + final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(data.getProject()); + if (method != null && IntroduceParameterUtil.isMethodInUsages(data, method, usages)) { - argList.addAfter(GroovyPsiElementFactory.getInstance(data.getProject()).createExpressionFromText(data.getParameterName()), anchor); + argList.addAfter(factory.createExpressionFromText(data.getParameterName()), anchor); } else { - PsiElement initializer = ExpressionConverter - .getExpression(data.getParameterInitializer().getExpression(), GroovyFileType.GROOVY_LANGUAGE, data.getProject()); + final PsiElement _expr = data.getParameterInitializer().getExpression(); + PsiElement initializer = ExpressionConverter.getExpression(_expr, GroovyFileType.GROOVY_LANGUAGE, data.getProject()); LOG.assertTrue(initializer instanceof GrExpression); - GrExpression newArg = (GrExpression)argList.addAfter(initializer, anchor); + GrExpression newArg = addClosureToCall(initializer, argList); + if (newArg == null) { + newArg = (GrExpression)argList.addAfter(initializer, anchor); + } final PsiMethod methodToReplaceIn = data.getMethodToReplaceIn(); new OldReferencesResolver(callExpression, newArg, methodToReplaceIn, data.getReplaceFieldsWithGetters(), initializer, signature, actualArgs, methodToReplaceIn.getParameterList().getParameters()).resolve(); ChangeContextUtil.clearContextInfo(initializer); + GrReferenceAdjuster.shortenReferences(newArg); } if (actualArgs == null) { @@ -124,9 +130,39 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP else { removeParametersFromCall(actualArgs, data.getParametersToRemove()); } + + if (argList.getAllArguments().length == 0 && hasClosureArgs(argList)) { + final GrArgumentList emptyArgList = ((GrMethodCallExpression)factory.createExpressionFromText("foo{}")).getArgumentList(); + LOG.assertTrue(emptyArgList != null); + argList.replace(emptyArgList); + } return false; } + private static boolean hasClosureArgs(GrArgumentList list) { + final PsiElement parent = list.getParent(); + return parent instanceof GrMethodCallExpression && ((GrMethodCallExpression)parent).getClosureArguments().length > 0; + } + + @Nullable + private static GrExpression addClosureToCall(PsiElement initializer, GrArgumentList list) { + if (!(initializer instanceof GrClosableBlock)) return null; + + final PsiElement parent = list.getParent(); + if (!(parent instanceof GrMethodCallExpression)) return null; + + PsiElement anchor; + final GrClosableBlock[] cls = ((GrMethodCallExpression)parent).getClosureArguments(); + if (cls.length > 0) { + anchor = cls[cls.length - 1]; + } + else { + anchor = list; + } + + return (GrExpression)parent.addAfter(initializer, anchor); + } + @Nullable private static GrExpression getLast(GrExpression[] oldArgs) { GrExpression anchor; @@ -233,7 +269,7 @@ public class GroovyIntroduceParameterMethodUsagesProcessor implements IntroduceP final String typeText = forcedType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) ? null : forcedType.getCanonicalText(); GrParameter parameter = factory.createParameter(data.getParameterName(), typeText, method); - parameter.getModifierList().setModifierProperty(GrModifier.FINAL, data.isDeclareFinal()); + parameter.getModifierList().setModifierProperty(PsiModifier.FINAL, data.isDeclareFinal()); final PsiParameter anchorParameter = getAnchorParameter(method); final GrParameterList parameterList = method.getParameterList(); parameter = (GrParameter)parameterList.addAfter(parameter, anchorParameter); diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java index 5ec19fc45edf..446bd52004d4 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2011 JetBrains s.r.o. + * Copyright 2000-2012 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. @@ -45,6 +45,10 @@ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase { return TestUtils.getTestDataPath() + "refactoring/introduceParameterGroovy/" + getTestName(true) + '/'; } + private void doDelegateTest() { + doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, null, true); + } + private boolean doTest(int replaceFieldsWithGetters, boolean removeUnusedParameters, boolean declareFinal) { return doTest(replaceFieldsWithGetters, removeUnusedParameters, declareFinal, null); } @@ -326,7 +330,7 @@ public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase { public void testDelegaterInSuper() {doDelegateTest();} - private void doDelegateTest() { - doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, null, true); - } + public void testClosureArg() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false);} + public void testClosureArgWithEmptyArgList() {doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false);} + } diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closure/ClosureAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closure/ClosureAfter.groovy index 5ec9c955f113..b32c4eff9e8e 100644 --- a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closure/ClosureAfter.groovy +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closure/ClosureAfter.groovy @@ -1 +1,16 @@ -new A().doSmth({ println "smth" }) \ No newline at end of file +/* + * Copyright 2000-2012 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. + */ +new A().doSmth { println "smth" } \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgAfter.groovy new file mode 100644 index 000000000000..b391789e3f78 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgAfter.groovy @@ -0,0 +1,18 @@ +/* + * Copyright 2000-2012 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. + */ +new A().foo(['1', '2']) { + print it +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgBefore.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgBefore.groovy new file mode 100644 index 000000000000..5bb672b1908e --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgBefore.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2000-2012 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. + */ +new A().foo(['1', '2']) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgMyClass.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgMyClass.groovy new file mode 100644 index 000000000000..34edb5a6064a --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArg/ClosureArgMyClass.groovy @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2012 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. + */ +class A { + def foo(List list) { + list.each { + print it + } + } +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListAfter.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListAfter.groovy new file mode 100644 index 000000000000..48f765371321 --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListAfter.groovy @@ -0,0 +1,18 @@ +/* + * Copyright 2000-2012 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. + */ +new A().foo { + print it + 2 +} \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListBefore.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListBefore.groovy new file mode 100644 index 000000000000..0da84ad7ca1f --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListBefore.groovy @@ -0,0 +1,16 @@ +/* + * Copyright 2000-2012 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. + */ +new A().foo(2) \ No newline at end of file diff --git a/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListMyClass.groovy b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListMyClass.groovy new file mode 100644 index 000000000000..c4148481f86e --- /dev/null +++ b/plugins/groovy/testdata/refactoring/introduceParameterGroovy/closureArgWithEmptyArgList/ClosureArgWithEmptyArgListMyClass.groovy @@ -0,0 +1,22 @@ +/* + * Copyright 2000-2012 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. + */ +class A { + def foo(int x) { + [1, 2, 3].each { + print it + x + } + } +} \ No newline at end of file