adding closure args into the tail of method call while introducing parameter

This commit is contained in:
Maxim.Medvedev
2012-01-25 11:55:39 +04:00
parent 8c1b933f2c
commit 2a80694895
9 changed files with 179 additions and 12 deletions
@@ -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<PsiElement>[] 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);
@@ -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);}
}
@@ -1 +1,16 @@
new A().doSmth({ println "smth" })
/*
* 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" }
@@ -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
}
@@ -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'])
@@ -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<String> list) {
list.each <selection>{
print it
}</selection>
}
}
@@ -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
}
@@ -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)
@@ -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 <selection>{
print it + x
}</selection>
}
}