diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index 72329e551a56..399082d491c6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -498,6 +498,7 @@ public class HighlightMethodUtil { AddTypeArgumentsFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, highlightInfo, fixRange); registerMethodAccessLevelIntentions(methodCandidates, methodCall, list, highlightInfo); ChangeMethodSignatureFromUsageFix.registerIntentions(methodCandidates, list, highlightInfo, fixRange); + RemoveRedundantArgumentsFix.registerIntentions(methodCandidates, list, highlightInfo, fixRange); ConvertDoubleToFloatFix.registerIntentions(methodCandidates, list, highlightInfo, fixRange); WrapExpressionFix.registerWrapAction(methodCandidates, list.getExpressions(), highlightInfo); ChangeParameterClassFix.registerQuickFixActions(methodCall, list, highlightInfo); diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantArgumentsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantArgumentsFix.java new file mode 100644 index 000000000000..7802df0ff50d --- /dev/null +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/RemoveRedundantArgumentsFix.java @@ -0,0 +1,132 @@ +/* + * 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. + */ +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.CodeInsightUtilBase; +import com.intellij.codeInsight.daemon.QuickFixBundle; +import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil; +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +/** + * @author Danila Ponomarenko + */ +public class RemoveRedundantArgumentsFix implements IntentionAction { + private final PsiMethod myTargetMethod; + private final PsiExpression[] myArguments; + private final PsiSubstitutor mySubstitutor; + + public RemoveRedundantArgumentsFix(@NotNull PsiMethod targetMethod, + @NotNull PsiExpression[] arguments, + @NotNull PsiSubstitutor substitutor) { + myTargetMethod = targetMethod; + myArguments = arguments; + mySubstitutor = substitutor; + } + + @NotNull + @Override + public String getText() { + return QuickFixBundle.message("remove.redundant.arguments.text", HighlightUtil.formatMethod(myTargetMethod)); + } + + @NotNull + @Override + public String getFamilyName() { + return QuickFixBundle.message("remove.redundant.arguments.family"); + } + + @Override + public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { + if (!myTargetMethod.isValid() || myTargetMethod.getContainingClass() == null) return false; + for (PsiExpression expression : myArguments) { + if (!expression.isValid()) return false; + } + if (!mySubstitutor.isValid()) return false; + + return findRedundantArgument(myArguments, myTargetMethod.getParameterList().getParameters(), mySubstitutor) != null; + } + + @Nullable + private static PsiExpression[] findRedundantArgument(@NotNull PsiExpression[] arguments, + @NotNull PsiParameter[] parameters, + @NotNull PsiSubstitutor substitutor) { + if (arguments.length <= parameters.length) return null; + + for (int i = 0; i < parameters.length; i++) { + final PsiExpression argument = arguments[i]; + final PsiParameter parameter = parameters[i]; + + final PsiType argumentType = argument.getType(); + if (argumentType == null) return null; + final PsiType parameterType = substitutor.substitute(parameter.getType()); + + if (!TypeConversionUtil.isAssignable(parameterType, argumentType)) { + return null; + } + } + + return Arrays.copyOfRange(arguments, parameters.length, arguments.length); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + if (!CodeInsightUtilBase.prepareFileForWrite(file)) return; + final PsiExpression[] redundantArguments = findRedundantArgument(myArguments, myTargetMethod.getParameterList().getParameters(), mySubstitutor); + if (redundantArguments != null) { + for (PsiExpression argument : redundantArguments) { + argument.delete(); + } + } + } + + @Override + public boolean startInWriteAction() { + return true; + } + + public static void registerIntentions(@NotNull JavaResolveResult[] candidates, + @NotNull PsiExpressionList arguments, + @NotNull HighlightInfo highlightInfo, + TextRange fixRange) { + for (JavaResolveResult candidate : candidates) { + registerIntention(arguments, highlightInfo, fixRange, candidate, arguments); + } + } + + private static void registerIntention(@NotNull PsiExpressionList arguments, + @NotNull HighlightInfo highlightInfo, + TextRange fixRange, + @NotNull JavaResolveResult candidate, + @NotNull PsiElement context) { + if (!candidate.isStaticsScopeCorrect()) return; + PsiMethod method = (PsiMethod)candidate.getElement(); + PsiSubstitutor substitutor = candidate.getSubstitutor(); + if (method != null && context.getManager().isInProject(method)) { + QuickFixAction.registerQuickFixAction(highlightInfo, fixRange, new RemoveRedundantArgumentsFix(method, arguments.getExpressions(), substitutor)); + } + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterBoxed.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterBoxed.java new file mode 100644 index 000000000000..147015b41c73 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterBoxed.java @@ -0,0 +1,9 @@ +// "Remove redundant arguments to match 'method(int, Integer)'" "true" +class A { + public A() { + method(new Integer(5), 5); + } + + private void method(int i, Integer i2) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterGeneric.java new file mode 100644 index 000000000000..75331d9786fb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterGeneric.java @@ -0,0 +1,9 @@ +// "Remove redundant arguments to match 'method(int, T)'" "true" +class A { + public A() { + method(5, new Exception()); + } + + private void method(int i, T t) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterSimple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterSimple.java new file mode 100644 index 000000000000..a5977febd94e --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/afterSimple.java @@ -0,0 +1,9 @@ +// "Remove redundant arguments to match 'method(int, String)'" "true" +class A { + public A() { + method(5, ""); + } + + private void method(int s, String s2) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeBoxed.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeBoxed.java new file mode 100644 index 000000000000..118b2acccecb --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeBoxed.java @@ -0,0 +1,9 @@ +// "Remove redundant arguments to match 'method(int, Integer)'" "true" +class A { + public A() { + method(new Integer(5), 5, "", new String()); + } + + private void method(int i, Integer i2) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeGeneric.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeGeneric.java new file mode 100644 index 000000000000..c648eaaf6b18 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeGeneric.java @@ -0,0 +1,9 @@ +// "Remove redundant arguments to match 'method(int, T)'" "true" +class A { + public A() { + method(5, new Exception(), new Exception(), "", 3); + } + + private void method(int i, T t) { + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeSimple.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeSimple.java new file mode 100644 index 000000000000..854fc6ee0d72 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument/beforeSimple.java @@ -0,0 +1,9 @@ +// "Remove redundant arguments to match 'method(int, String)'" "true" +class A { + public A() { + method(5, "", 10); + } + + private void method(int s, String s2) { + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java new file mode 100644 index 000000000000..2930d5d42571 --- /dev/null +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java @@ -0,0 +1,12 @@ +package com.intellij.codeInsight.daemon.quickFix; + +public class RemoveRedundantArgumentTest extends LightQuickFixTestCase { + + public void test() throws Exception { doAllTests(); } + + @Override + protected String getBasePath() { + return "/codeInsight/daemonCodeAnalyzer/quickFix/removeRedundantArgument"; + } + +} diff --git a/resources-en/src/messages/QuickFixBundle.properties b/resources-en/src/messages/QuickFixBundle.properties index aec410a7e2b3..bd107e9cb0db 100644 --- a/resources-en/src/messages/QuickFixBundle.properties +++ b/resources-en/src/messages/QuickFixBundle.properties @@ -263,4 +263,7 @@ convert.to.string.family=Fix Character Literal convert.to.string.text=Convert to String Literal initialize.final.field.in.constructor.name=Initialize in constructor -initialize.final.field.in.constructor.choose.dialog.title=Choose constructors to add initialization to \ No newline at end of file +initialize.final.field.in.constructor.choose.dialog.title=Choose constructors to add initialization to + +remove.redundant.arguments.text=Remove redundant arguments to call ''{0}'' +remove.redundant.arguments.family=Remove redundant arguments \ No newline at end of file