Java: Fixed return type when duplicate code is replaced with a call to the extracted method (IDEA-160546)

This commit is contained in:
Pavel Dolgov
2018-06-27 13:25:32 +03:00
parent a823e5ceda
commit abb41a2607
12 changed files with 90 additions and 17 deletions
@@ -21,6 +21,8 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author ven
@@ -39,7 +41,8 @@ public class ConditionalReturnStatementValue implements ReturnValue {
return PsiEquivalenceUtil.areElementsEquivalent(myReturnValue, otherReturnValue);
}
public PsiStatement createReplacement(final PsiMethod extractedMethod, PsiMethodCallExpression methodCallExpression) throws IncorrectOperationException {
@Nullable
public PsiStatement createReplacement(@NotNull final PsiMethod extractedMethod, @NotNull PsiMethodCallExpression methodCallExpression, @Nullable PsiType returnType) throws IncorrectOperationException {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
PsiIfStatement statement;
if (myReturnValue == null) {
@@ -19,6 +19,8 @@ import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author dsl
@@ -39,7 +41,8 @@ public class ExpressionReturnValue implements ReturnValue {
return PsiEquivalenceUtil.areElementsEquivalent(myExpression, ((ExpressionReturnValue)other).myExpression);
}
public PsiStatement createReplacement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression)
@Nullable
public PsiStatement createReplacement(@NotNull final PsiMethod extractedMethod, @NotNull final PsiMethodCallExpression methodCallExpression, @Nullable PsiType returnType)
throws IncorrectOperationException {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
final CodeStyleManager styleManager = CodeStyleManager.getInstance(methodCallExpression.getProject());
@@ -18,6 +18,8 @@ package com.intellij.refactoring.util.duplicates;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author dsl
@@ -38,7 +40,8 @@ public class FieldReturnValue implements ReturnValue {
return myField;
}
public PsiStatement createReplacement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression) throws IncorrectOperationException {
@Nullable
public PsiStatement createReplacement(@NotNull final PsiMethod extractedMethod, @NotNull final PsiMethodCallExpression methodCallExpression, @Nullable PsiType returnType) throws IncorrectOperationException {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
final CodeStyleManager styleManager = CodeStyleManager.getInstance(methodCallExpression.getProject());
@@ -21,12 +21,12 @@ import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class GotoReturnValue implements ReturnValue {
@Nullable
public PsiStatement createReplacement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression) throws
IncorrectOperationException {
public PsiStatement createReplacement(@NotNull final PsiMethod extractedMethod, @NotNull final PsiMethodCallExpression methodCallExpression, @Nullable PsiType returnType) throws IncorrectOperationException {
if (!TypeConversionUtil.isBooleanType(extractedMethod.getReturnType())) return null;
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
final PsiIfStatement statement = (PsiIfStatement)elementFactory.createStatementFromText(getGotoStatement(), null);
@@ -237,7 +237,7 @@ public final class Match {
return element;
}
public PsiElement replaceByStatement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression, final PsiVariable outputVariable) throws IncorrectOperationException {
public PsiElement replaceByStatement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression, final PsiVariable outputVariable, @Nullable PsiType returnType) throws IncorrectOperationException {
PsiStatement statement = null;
if (outputVariable != null) {
ReturnValue returnValue = getOutputVariableValue(outputVariable);
@@ -245,10 +245,10 @@ public final class Match {
returnValue = new FieldReturnValue((PsiField)outputVariable);
}
if (returnValue == null) return null;
statement = returnValue.createReplacement(extractedMethod, methodCallExpression);
statement = returnValue.createReplacement(extractedMethod, methodCallExpression, returnType);
}
else if (getReturnValue() != null) {
statement = getReturnValue().createReplacement(extractedMethod, methodCallExpression);
statement = getReturnValue().createReplacement(extractedMethod, methodCallExpression, returnType);
}
if (statement == null) {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
@@ -271,12 +271,16 @@ public final class Match {
}
public PsiElement replace(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression, PsiVariable outputVariable) throws IncorrectOperationException {
return replace(extractedMethod, methodCallExpression, outputVariable, null);
}
public PsiElement replace(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression, PsiVariable outputVariable, @Nullable PsiType returnType) throws IncorrectOperationException {
declareLocalVariables();
if (getMatchStart() == getMatchEnd() && getMatchStart() instanceof PsiExpression) {
return replaceWithExpression(methodCallExpression);
}
else {
return replaceByStatement(extractedMethod, methodCallExpression, outputVariable);
return replaceByStatement(extractedMethod, methodCallExpression, outputVariable, returnType);
}
}
@@ -18,6 +18,8 @@ package com.intellij.refactoring.util.duplicates;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author dsl
@@ -31,7 +33,8 @@ public class ReturnStatementReturnValue implements ReturnValue {
return other instanceof ReturnStatementReturnValue;
}
public PsiStatement createReplacement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression) throws IncorrectOperationException {
@Nullable
public PsiStatement createReplacement(@NotNull final PsiMethod extractedMethod, @NotNull final PsiMethodCallExpression methodCallExpression,@Nullable PsiType returnType) throws IncorrectOperationException {
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
final CodeStyleManager styleManager = CodeStyleManager.getInstance(methodCallExpression.getProject());
PsiReturnStatement returnStatement = (PsiReturnStatement)elementFactory.createStatementFromText("return x;", null);
@@ -18,7 +18,9 @@ package com.intellij.refactoring.util.duplicates;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.PsiStatement;
import com.intellij.psi.PsiType;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -28,5 +30,5 @@ public interface ReturnValue {
boolean isEquivalent(ReturnValue other);
@Nullable
PsiStatement createReplacement(final PsiMethod extractedMethod, PsiMethodCallExpression methodCallExpression) throws IncorrectOperationException;
PsiStatement createReplacement(@NotNull PsiMethod extractedMethod, @NotNull PsiMethodCallExpression methodCallExpression, @Nullable PsiType returnType) throws IncorrectOperationException;
}
@@ -15,9 +15,13 @@
*/
package com.intellij.refactoring.util.duplicates;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author dsl
@@ -38,14 +42,18 @@ public class VariableReturnValue implements ReturnValue {
return myVariable;
}
public PsiStatement createReplacement(final PsiMethod extractedMethod, final PsiMethodCallExpression methodCallExpression) throws IncorrectOperationException {
@Nullable
public PsiStatement createReplacement(@NotNull final PsiMethod extractedMethod, @NotNull final PsiMethodCallExpression methodCallExpression, @Nullable final PsiType returnType) throws IncorrectOperationException {
final PsiDeclarationStatement statement;
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(methodCallExpression.getProject()).getElementFactory();
final CodeStyleManager styleManager = CodeStyleManager.getInstance(methodCallExpression.getProject());
Project project = methodCallExpression.getProject();
final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory();
final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
JavaCodeStyleManager javaStyleManager = JavaCodeStyleManager.getInstance(project);
PsiType type = returnType != null && returnType.isValid() ? returnType : myVariable.getType();
statement = (PsiDeclarationStatement)styleManager.reformat(
elementFactory.createVariableDeclarationStatement(myVariable.getName(), myVariable.getType(), methodCallExpression)
);
javaStyleManager.shortenClassReferences(
elementFactory.createVariableDeclarationStatement(myVariable.getName(), type, methodCallExpression)));
((PsiVariable)statement.getDeclaredElements()[0]).getModifierList().replace(myVariable.getModifierList());
return statement;
}
@@ -1355,7 +1355,7 @@ public class ExtractMethodProcessor implements MatchProvider {
}
}
List<String> reusedVariables = findReusedVariables(match, myInputVariables, myOutputVariable);
PsiElement replacedMatch = match.replace(myExtractedMethod, methodCallExpression, myOutputVariable);
PsiElement replacedMatch = match.replace(myExtractedMethod, methodCallExpression, myOutputVariable, myReturnType);
PsiElement appendLocation = addNotNullConditionalCheck(match, replacedMatch);
declareReusedVariables(appendLocation, reusedVariables);
@@ -0,0 +1,18 @@
class Test {
public static Integer foo(Integer[] a) {
<selection>
if (a.length != 0) {
int n = a[0] != null ? a[0] : 0;
return n;
}</selection>
return null;
}
public static Integer bar(Integer[] a) {
if (a.length != 0) {
int n = a[0] != null ? a[0] : 0;
return n;
}
return null;
}
}
@@ -0,0 +1,25 @@
import org.jetbrains.annotations.Nullable;
class Test {
public static Integer foo(Integer[] a) {
Integer n = newMethod(a);
if (n != null) return n;
return null;
}
@Nullable
private static Integer newMethod(Integer[] a) {
if (a.length != 0) {
int n = a[0] != null ? a[0] : 0;
return n;
}
return null;
}
public static Integer bar(Integer[] a) {
Integer n = newMethod(a);
if (n != null) return n;
return null;
}
}
@@ -1270,6 +1270,10 @@ public class ExtractMethodTest extends LightCodeInsightTestCase {
doDuplicatesTest();
}
public void testBoxedConditionalReturn() throws Exception {
doDuplicatesTest();
}
public void testBeforeCommentAfterSelectedFragment() throws Exception {
doTest();
}