Bug 565752 - QuickFix is blocked by conditional expression
Quickfix for incorrect return type is blocked by conditional expression
- Add check if expression is part of return statement
- Add test case
Change-Id: Iabbb0b7b33a589243d47e9f91dacbb9bd984835b
diff --git a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/core/manipulation/dom/ASTResolving.java b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/core/manipulation/dom/ASTResolving.java
index 0a8e866..4f73ee4 100644
--- a/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/core/manipulation/dom/ASTResolving.java
+++ b/org.eclipse.jdt.core.manipulation/core extension/org/eclipse/jdt/internal/core/manipulation/dom/ASTResolving.java
@@ -244,13 +244,27 @@
break;
case ASTNode.CONDITIONAL_EXPRESSION:
ConditionalExpression expression= (ConditionalExpression) parent;
- if (node.equals(expression.getExpression())) {
+
+ if (node.getLocationInParent() == ConditionalExpression.EXPRESSION_PROPERTY) {
return parent.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
}
- if (node.equals(expression.getElseExpression())) {
+
+ if (node.getLocationInParent() == ConditionalExpression.THEN_EXPRESSION_PROPERTY
+ && expression.getElseExpression().resolveTypeBinding() != null) {
+ return expression.getElseExpression().resolveTypeBinding();
+ }
+
+ if (node.getLocationInParent() == ConditionalExpression.ELSE_EXPRESSION_PROPERTY
+ && expression.getThenExpression().resolveTypeBinding() != null) {
return expression.getThenExpression().resolveTypeBinding();
}
- return expression.getElseExpression().resolveTypeBinding();
+
+ if (node.getLocationInParent() == ConditionalExpression.THEN_EXPRESSION_PROPERTY
+ || node.getLocationInParent() == ConditionalExpression.ELSE_EXPRESSION_PROPERTY) {
+ return getPossibleReferenceBinding(expression);
+ }
+
+ break;
case ASTNode.POSTFIX_EXPRESSION:
return parent.getAST().resolveWellKnownType("int"); //$NON-NLS-1$
case ASTNode.PREFIX_EXPRESSION:
diff --git a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/ReturnTypeQuickFixTest.java b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/ReturnTypeQuickFixTest.java
index 3ec360d..3211276 100644
--- a/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/ReturnTypeQuickFixTest.java
+++ b/org.eclipse.jdt.ui.tests/ui/org/eclipse/jdt/ui/tests/quickfix/ReturnTypeQuickFixTest.java
@@ -17,6 +17,7 @@
import java.util.ArrayList;
import java.util.Hashtable;
+import java.util.List;
import org.junit.After;
import org.junit.Before;
@@ -45,9 +46,8 @@
import org.eclipse.jdt.internal.ui.JavaPlugin;
public class ReturnTypeQuickFixTest extends QuickFixTest {
-
@Rule
- public ProjectTestSetup projectSetup = new ProjectTestSetup();
+ public ProjectTestSetup projectSetup= new ProjectTestSetup();
private IJavaProject fJProject1;
private IPackageFragmentRoot fSourceFolder;
@@ -810,6 +810,62 @@
}
@Test
+ public void testCorrectReturnStatementInConditional() throws Exception {
+ IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
+ String input= "" //
+ + "package test1;\n" //
+ + "\n" //
+ + "import java.util.Map;\n" //
+ + "\n" //
+ + "public class E {\n" //
+ + " <K1, K2, V> V foo(K1 key1, Map<K1, Map<K2, V>> map) {\n" //
+ + " Map<K2, V> map2 = map.get(key1);\n" //
+ + " return map2 == null ? null : map2.entrySet();\n" //
+ + " }\n" //
+ + "}\n"; //
+ ICompilationUnit cu= pack1.createCompilationUnit("E.java", input, false, null);
+
+ CompilationUnit astRoot= getASTRoot(cu);
+ List<IJavaCompletionProposal> proposals= collectCorrections(cu, astRoot);
+ assertNumberOfProposals(proposals, 2);
+ assertCorrectLabels(proposals);
+
+ ASTRewriteCorrectionProposal proposal= (ASTRewriteCorrectionProposal) proposals.get(0);
+ String preview1= getPreviewContent(proposal);
+
+ String expected1= "" //
+ + "package test1;\n" //
+ + "\n" //
+ + "import java.util.Map;\n" //
+ + "\n" //
+ + "public class E {\n" //
+ + " <K1, K2, V> V foo(K1 key1, Map<K1, Map<K2, V>> map) {\n" //
+ + " Map<K2, V> map2 = map.get(key1);\n" //
+ + " return (V) (map2 == null ? null : map2.entrySet());\n" //
+ + " }\n" //
+ + "}\n"; //
+
+ proposal= (ASTRewriteCorrectionProposal) proposals.get(1);
+ String preview2= getPreviewContent(proposal);
+
+ String expected2= "" //
+ + "package test1;\n" //
+ + "\n" //
+ + "import java.util.Map;\n" //
+ + "import java.util.Map.Entry;\n" //
+ + "import java.util.Set;\n" //
+ + "\n" //
+ + "public class E {\n" //
+ + " <K1, K2, V> Set<Entry<K2, V>> foo(K1 key1, Map<K1, Map<K2, V>> map) {\n" //
+ + " Map<K2, V> map2 = map.get(key1);\n" //
+ + " return map2 == null ? null : map2.entrySet();\n" //
+ + " }\n" //
+ + "}\n"; //
+
+ assertEqualStringsIgnoreOrder(new String[] { preview1, preview2 }, new String[] { expected1, expected2 });
+ }
+
+ @Test
public void testReturnVoid() throws Exception {
IPackageFragment pack1= fSourceFolder.createPackageFragment("test1", false, null);
StringBuffer buf= new StringBuffer();
diff --git a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/TypeMismatchSubProcessor.java b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/TypeMismatchSubProcessor.java
index 99861b6..031301b 100644
--- a/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/TypeMismatchSubProcessor.java
+++ b/org.eclipse.jdt.ui/ui/org/eclipse/jdt/internal/ui/text/correction/TypeMismatchSubProcessor.java
@@ -31,6 +31,7 @@
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
@@ -55,6 +56,9 @@
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.TypeLocation;
+import org.eclipse.jdt.internal.core.manipulation.StubUtility;
+import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
+import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.Bindings;
@@ -76,12 +80,8 @@
import org.eclipse.jdt.internal.ui.text.correction.proposals.ImplementInterfaceProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.LinkedCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.NewVariableCorrectionProposal;
-import org.eclipse.jdt.internal.ui.text.correction.proposals.TypeChangeCorrectionProposal;
import org.eclipse.jdt.internal.ui.text.correction.proposals.OptionalCorrectionProposal;
-
-import org.eclipse.jdt.internal.core.manipulation.StubUtility;
-import org.eclipse.jdt.internal.core.manipulation.dom.ASTResolving;
-import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;
+import org.eclipse.jdt.internal.ui.text.correction.proposals.TypeChangeCorrectionProposal;
import org.eclipse.jdt.internal.ui.viewsupport.BindingLabelProvider;
@@ -198,7 +198,7 @@
boolean nullOrVoid= currBinding == null || "void".equals(currBinding.getName()); //$NON-NLS-1$
// change method return statement to actual type
- if (!nullOrVoid && parentNodeType == ASTNode.RETURN_STATEMENT) {
+ if (!nullOrVoid && isTypeReturned(nodeToCast)) {
BodyDeclaration decl= ASTResolving.findParentBodyDeclaration(selectedNode);
if (decl instanceof MethodDeclaration) {
MethodDeclaration methodDeclaration= (MethodDeclaration) decl;
@@ -262,6 +262,21 @@
}
+ private static boolean isTypeReturned(final Expression nodeToCast) {
+ int parentNodeType= nodeToCast.getParent().getNodeType();
+
+ if (parentNodeType == ASTNode.RETURN_STATEMENT) {
+ return true;
+ }
+
+ if (parentNodeType == ASTNode.PARENTHESIZED_EXPRESSION
+ || parentNodeType == ASTNode.CONDITIONAL_EXPRESSION && (nodeToCast.getLocationInParent() == ConditionalExpression.THEN_EXPRESSION_PROPERTY || nodeToCast.getLocationInParent() == ConditionalExpression.ELSE_EXPRESSION_PROPERTY)) {
+ return isTypeReturned((Expression) nodeToCast.getParent());
+ }
+
+ return false;
+ }
+
public static ITypeBinding boxUnboxPrimitives(ITypeBinding castType, ITypeBinding toCast, AST ast) {
/*
* e.g: