diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java new file mode 100644 index 000000000000..9655fd5e5c55 --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DelegateWithDefaultParamValueIntentionAction.java @@ -0,0 +1,140 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction; +import com.intellij.codeInsight.template.Template; +import com.intellij.codeInsight.template.TemplateBuilderImpl; +import com.intellij.codeInsight.template.impl.TextExpression; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.IconLoader; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.Function; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * User: anna + */ +public class DelegateWithDefaultParamValueIntentionAction extends PsiElementBaseIntentionAction implements Iconable { + public static final Icon REFACTORING_BULB = IconLoader.getIcon("/actions/refactoringBulb.png"); + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) { + final PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); + if (parameter != null) { + final PsiElement declarationScope = parameter.getDeclarationScope(); + if (declarationScope instanceof PsiMethod) { + final PsiMethod method = (PsiMethod)declarationScope; + final PsiClass containingClass = method.getContainingClass(); + if (containingClass != null && !containingClass.isInterface()) { + return containingClass.findMethodBySignature(generateMethodPrototype(method, parameter), false) == null; + } + } + } + return false; + } + + @Override + public Icon getIcon(int flags) { + return REFACTORING_BULB; + } + + private static PsiMethod generateMethodPrototype(PsiMethod method, PsiParameter param) { + final PsiMethod prototype = (PsiMethod)method.copy(); + final PsiCodeBlock body = prototype.getBody(); + if (body != null) { + for (PsiStatement psiStatement : body.getStatements()) { + psiStatement.delete(); + } + } + final int parameterIndex = method.getParameterList().getParameterIndex(param); + prototype.getParameterList().getParameters()[parameterIndex].delete(); + return prototype; + } + + @Override + public void invoke(Project project, Editor editor, PsiElement element) throws IncorrectOperationException { + final PsiParameter parameter = PsiTreeUtil.getParentOfType(element, PsiParameter.class); + final PsiMethod method = (PsiMethod)parameter.getDeclarationScope(); + final PsiMethod prototype = (PsiMethod)method.getContainingClass().addBefore(generateMethodPrototype(method, parameter), method); + + TemplateBuilderImpl builder = new TemplateBuilderImpl(prototype); + + PsiCodeBlock body = prototype.getBody(); + final String callArgs = + "(" + StringUtil.join(method.getParameterList().getParameters(), new Function() { + @Override + public String fun(PsiParameter psiParameter) { + if (psiParameter.equals(parameter)) return "IntelliJIDEARulezzz"; + return psiParameter.getName(); + } + }, ",") + ");"; + final String methodCall; + if (method.getReturnType() == null) { + methodCall = "this"; + } else if (method.getReturnType() != PsiType.VOID) { + methodCall = "return " + method.getName(); + } else { + methodCall = method.getName(); + } + body.add(JavaPsiFacade.getElementFactory(project).createStatementFromText(methodCall + callArgs, method)); + body = (PsiCodeBlock)CodeStyleManager.getInstance(project).reformat(body); + final PsiStatement stmt = body.getStatements()[0]; + PsiExpression expr = null; + if (stmt instanceof PsiReturnStatement) { + expr = ((PsiReturnStatement)stmt).getReturnValue(); + } else if (stmt instanceof PsiExpressionStatement) { + expr = ((PsiExpressionStatement)stmt).getExpression(); + } + if (expr instanceof PsiMethodCallExpression) { + PsiMethodCallExpression methodCallExp = (PsiMethodCallExpression)expr; + RangeMarker rangeMarker = editor.getDocument().createRangeMarker(prototype.getTextRange()); + final PsiExpression exprToBeDefault = + methodCallExp.getArgumentList().getExpressions()[method.getParameterList().getParameterIndex(parameter)]; + builder.replaceElement(exprToBeDefault, new TextExpression("")); + Template template = builder.buildTemplate(); + editor.getCaretModel().moveToOffset(rangeMarker.getStartOffset()); + + PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument()); + editor.getDocument().deleteString(rangeMarker.getStartOffset(), rangeMarker.getEndOffset()); + + rangeMarker.dispose(); + + CreateFromUsageBaseFix.startTemplate(editor, template, project); + } + } + + @NotNull + @Override + public String getText() { + return "Generate delegated method with default parameter value"; + } + + @NotNull + @Override + public String getFamilyName() { + return getText(); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java new file mode 100644 index 000000000000..f37bae2df539 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/after1.java @@ -0,0 +1,9 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + void foo() { + foo(); + } + + void foo(int ii){ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java new file mode 100644 index 000000000000..2ba4de2c87e2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterConstructor.java @@ -0,0 +1,8 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + Test() { + this(); + } + + Test(int ii){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java new file mode 100644 index 000000000000..39c8186309be --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterReturnValue.java @@ -0,0 +1,10 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + int foo() { + return foo(); + } + + int foo(int ii){ + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java new file mode 100644 index 000000000000..76d6ebeb4c0b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterTypeParams.java @@ -0,0 +1,10 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + int foo(boolean... args) { + return foo(, args); + } + + int foo(T ii, boolean... args){ + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java new file mode 100644 index 000000000000..f1645794d65b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/afterVarargs.java @@ -0,0 +1,10 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + int foo(boolean... args) { + return foo(, args); + } + + int foo(int ii, boolean... args){ + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java new file mode 100644 index 000000000000..22b77602b869 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/before1.java @@ -0,0 +1,5 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + void foo(int ii){ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java new file mode 100644 index 000000000000..0d75c3918ed8 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeConstructor.java @@ -0,0 +1,4 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + Test(int ii){} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java new file mode 100644 index 000000000000..0d5ff1b0782f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeExistinMethod.java @@ -0,0 +1,6 @@ +// "Generate delegated method with default parameter value" "false" +class Test { + void foo(){} + void foo(int ii){ + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java new file mode 100644 index 000000000000..a18fdba97688 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeInterface.java @@ -0,0 +1,4 @@ +// "Generate delegated method with default parameter value" "false" +interface Test { + void foo(int ii); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java new file mode 100644 index 000000000000..f77d174ad440 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeReturnValue.java @@ -0,0 +1,6 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + int foo(int ii){ + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java new file mode 100644 index 000000000000..19e77d4724f4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeTypeParams.java @@ -0,0 +1,6 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + int foo(T ii, boolean... args){ + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java new file mode 100644 index 000000000000..865e86d13fd4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue/beforeVarargs.java @@ -0,0 +1,6 @@ +// "Generate delegated method with default parameter value" "true" +class Test { + int foo(int ii, boolean... args){ + return 1; + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java new file mode 100644 index 000000000000..5dc3edf8b84a --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java @@ -0,0 +1,51 @@ +/* + * Copyright 2000-2011 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 com.intellij.codeInsight.daemon.quickFix; + +import com.intellij.codeInsight.template.impl.TemplateManagerImpl; +import com.intellij.codeInsight.template.impl.TemplateState; + +/** + * @author anna + */ +public class DelegateWithDefaultParamValueTest extends LightQuickFixTestCase { + @Override + protected void doAction(String text, boolean actionShouldBeAvailable, String testFullPath, String testName) + throws Exception { + try { + ((TemplateManagerImpl)TemplateManagerImpl.getInstance(getProject())).setTemplateTesting(true); + super.doAction(text, actionShouldBeAvailable, testFullPath, testName); + + if (actionShouldBeAvailable) { + TemplateState state = TemplateManagerImpl.getTemplateState(getEditor()); + assert state != null; + state.gotoEnd(false); + } + } finally { + ((TemplateManagerImpl)TemplateManagerImpl.getInstance(getProject())).setTemplateTesting(false); + } + } + + public void test() throws Exception { + doAllTests(); + + } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/delegateWithDefaultValue"; + } +} diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml index 877f22d23fdc..2a6a319230a6 100644 --- a/platform/platform-resources/src/META-INF/LangExtensions.xml +++ b/platform/platform-resources/src/META-INF/LangExtensions.xml @@ -475,6 +475,11 @@ com.intellij.refactoring.changeSignature.ChangeSignatureDetectorAction + + com.intellij.codeInsight.daemon.impl.quickfix.DelegateWithDefaultParamValueIntentionAction + Declaration + + diff --git a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template new file mode 100644 index 000000000000..97307fd767c3 --- /dev/null +++ b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/after.java.template @@ -0,0 +1,8 @@ +class Test { + void foo(int a) { + foo(a, |); + } + void foo(int a, int b){ + //do smth + } +} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template new file mode 100644 index 000000000000..90e1b2f320b2 --- /dev/null +++ b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/before.java.template @@ -0,0 +1,5 @@ +class Test { + void foo(int a, int b){ + //do smth + } +} \ No newline at end of file diff --git a/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html new file mode 100644 index 000000000000..c476e38684df --- /dev/null +++ b/resources-en/src/intentionDescriptions/DelegateWithDefaultParamValueIntentionAction/description.html @@ -0,0 +1,5 @@ + + +This intention generates method which delegates to the current one setting the selected parameter the default value. + +