From 504300662d69326134c3c388b27ae4edb6abb3cb Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 6 Oct 2017 17:39:58 +0700 Subject: [PATCH] IDEA-179382 intention to change return type works when assigning but not when passing a return value as an argument to some different method --- .../impl/analysis/HighlightMethodUtil.java | 1 + .../quickfix/ArgumentFixerActionFactory.java | 3 +- .../impl/quickfix/MethodReturnFixFactory.java | 53 +++++++++++++++++++ .../methodReturn/afterMethodCall.java | 20 +++++++ .../methodReturn/afterMethodCall2.java | 20 +++++++ .../methodReturn/beforeMethodCall.java | 20 +++++++ .../methodReturn/beforeMethodCall2.java | 20 +++++++ .../methodReturn/beforeMethodCallTwice.java | 20 +++++++ 8 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodReturnFixFactory.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall2.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall2.java create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCallTwice.java diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index cba800b85f63..9dae686eeb36 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -856,6 +856,7 @@ public class HighlightMethodUtil { PermuteArgumentsFix.registerFix(highlightInfo, methodCall, methodCandidates, fixRange); AddTypeArgumentsFix.REGISTRAR.registerCastActions(methodCandidates, methodCall, highlightInfo, fixRange); WrapObjectWithOptionalOfNullableFix.REGISTAR.registerCastActions(methodCandidates, methodCall, highlightInfo, fixRange); + MethodReturnFixFactory.INSTANCE.registerCastActions(methodCandidates, methodCall, highlightInfo, fixRange); WrapWithAdapterMethodCallFix.registerCastActions(methodCandidates, methodCall, highlightInfo, fixRange); registerMethodAccessLevelIntentions(methodCandidates, methodCall, list, highlightInfo); registerChangeMethodSignatureFromUsageIntentions(methodCandidates, list, highlightInfo, fixRange); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java index 750017d2d9cf..98e94b933672 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.daemon.impl.quickfix; import com.intellij.codeInsight.daemon.impl.HighlightInfo; +import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.TextRange; @@ -119,5 +120,5 @@ public abstract class ArgumentFixerActionFactory { public abstract boolean areTypesConvertible(@NotNull PsiType exprType, @NotNull PsiType parameterType, @NotNull PsiElement context); - public abstract MethodArgumentFix createFix(PsiExpressionList list, int i, PsiType parameterType); + public abstract IntentionAction createFix(PsiExpressionList list, int i, PsiType parameterType); } \ No newline at end of file diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodReturnFixFactory.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodReturnFixFactory.java new file mode 100644 index 000000000000..10ae1381c348 --- /dev/null +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/MethodReturnFixFactory.java @@ -0,0 +1,53 @@ +// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.codeInsight.daemon.impl.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInsight.intention.QuickFixFactory; +import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.util.PsiUtil; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ObjectUtils; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MethodReturnFixFactory extends ArgumentFixerActionFactory { + public static final ArgumentFixerActionFactory INSTANCE = new MethodReturnFixFactory(); + + private MethodReturnFixFactory() {} + + @Nullable + @Override + protected PsiExpression getModifiedArgument(final PsiExpression expression, final PsiType toType) throws IncorrectOperationException { + PsiMethodCallExpression call = ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(expression), PsiMethodCallExpression.class); + if (call == null) return null; + PsiMethod method = call.resolveMethod(); + if (method == null) return null; + PsiType type = GenericsUtil.getVariableTypeByExpressionType(toType); + + return JavaPsiFacade.getElementFactory(expression.getProject()) + .createExpressionFromText("(" + type.getCanonicalText() + ")null", expression); + } + + @Override + public boolean areTypesConvertible(@NotNull final PsiType exprType, + @NotNull final PsiType parameterType, + @NotNull final PsiElement context) { + return !PsiType.VOID.equals(exprType) && exprType.equalsToText(exprType.getCanonicalText()); + } + + @Override + public IntentionAction createFix(final PsiExpressionList list, final int i, final PsiType toType) { + PsiMethodCallExpression call = + ObjectUtils.tryCast(PsiUtil.skipParenthesizedExprDown(list.getExpressions()[i]), PsiMethodCallExpression.class); + if (call == null) return null; + PsiMethod method = call.resolveMethod(); + if (method == null) return null; + PsiReferenceExpression ref = call.getMethodExpression(); + // Do not suggest to change return type if the same method is used several times in this argument list + // In this case it's unlikely that compilation error will be fixed, and can be confusing + if (!ReferencesSearch.search(method, new LocalSearchScope(list)).forEach(r -> r == ref)) return null; + return QuickFixFactory.getInstance().createMethodReturnFix(method, toType, true); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall.java new file mode 100644 index 000000000000..034eafd7aa03 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall.java @@ -0,0 +1,20 @@ +// "Make 'getNumber' return 'java.lang.String'" "true" +public class Test { + int number; + + public String getNumber() { + return number; + } + + public void consumeString(String s, int s1) { + // Do nothing + } + + public void consumeString(Double s, int s1) { + // Do nothing + } + + public Test() { + consumeString(getNumber(), 1); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall2.java new file mode 100644 index 000000000000..66331e8249f4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/afterMethodCall2.java @@ -0,0 +1,20 @@ +// "Make 'getNumber' return 'double'" "true" +public class Test { + int number; + + public double getNumber() { + return number; + } + + public void consumeString(String s, int s1) { + // Do nothing + } + + public void consumeString(Double s, int s1) { + // Do nothing + } + + public Test() { + consumeString(getNumber(), 1); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall.java new file mode 100644 index 000000000000..bd557e6890c0 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall.java @@ -0,0 +1,20 @@ +// "Make 'getNumber' return 'java.lang.String'" "true" +public class Test { + int number; + + public int getNumber() { + return number; + } + + public void consumeString(String s, int s1) { + // Do nothing + } + + public void consumeString(Double s, int s1) { + // Do nothing + } + + public Test() { + consumeString(getNumber(), 1); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall2.java new file mode 100644 index 000000000000..ad461a61dc03 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCall2.java @@ -0,0 +1,20 @@ +// "Make 'getNumber' return 'double'" "true" +public class Test { + int number; + + public int getNumber() { + return number; + } + + public void consumeString(String s, int s1) { + // Do nothing + } + + public void consumeString(Double s, int s1) { + // Do nothing + } + + public Test() { + consumeString(getNumber(), 1); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCallTwice.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCallTwice.java new file mode 100644 index 000000000000..a9a9143ead42 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn/beforeMethodCallTwice.java @@ -0,0 +1,20 @@ +// "Make 'getNumber' return 'java.lang.String'" "false" +public class Test { + int number; + + public int getNumber() { + return number; + } + + public void consumeString(String s, int s1) { + // Do nothing + } + + public void consumeString(Double s, int s1) { + // Do nothing + } + + public Test() { + consumeString(getNumber(), getNumber()); + } +}