Bug 577699 - [extract method] Entire lambda body cannot be extracted
- fix ExtractMethodAnalyzer to not invalidate the body of a Lambda
- fix ExtractMethodRefactoring to recognize when it has a return
or call that is replacing a lambda body and not add semi-colon
- also fix ExtractMethodRefactoring to recognize when it is creating
a method from a Block and to unwrap the block to just move over
the statements
- add new tests to ExtractMethodTests1d8
Change-Id: Iacacee7fa582fbcf76ceb9063faf6bf9e764f4b9
Reviewed-on: https://git.eclipse.org/r/c/jdt/eclipse.jdt.ui/+/188710
Tested-by: JDT Bot <jdt-bot@eclipse.org>
Tested-by: Jeff Johnston <jjohnstn@redhat.com>
Reviewed-by: Jeff Johnston <jjohnstn@redhat.com>
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/error_out/A_test804.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/error_out/A_test804.java
index 8e3fe00..dee7cd2 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/error_out/A_test804.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/error_out/A_test804.java
@@ -10,8 +10,6 @@
}
protected void extracted() {
- /*[*/{
- System.out.println("Hello world");
- }/*]*/
+ System.out.println("Hello world");
}
}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_in/A_test328.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_in/A_test328.java
new file mode 100644
index 0000000..900a553
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_in/A_test328.java
@@ -0,0 +1,16 @@
+package lambdaExpression18_in;
+
+@FunctionalInterface
+interface FI {
+ int foo1(int a);
+}
+
+class FI_1 {
+ void fun(int a) {
+ FI i1 = x1-> x1;
+ FI i2 = xxx-> /*]*/{
+ i1.foo1(a);
+ return xxx;
+ }/*[*/;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_in/A_test329.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_in/A_test329.java
new file mode 100644
index 0000000..8cfc43e
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_in/A_test329.java
@@ -0,0 +1,17 @@
+package lambdaExpression18_in;
+
+@FunctionalInterface
+interface FI {
+ void foo1(int a);
+}
+
+class FI_1 {
+ void foo(int a, FI fi) {
+ fi.foo1(a);
+ }
+ void fun(int a) {
+ foo(a, xxx -> /*]*/{
+ System.out.println(a);
+ }/*[*/);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_out/A_test328.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_out/A_test328.java
new file mode 100644
index 0000000..27aeb33
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_out/A_test328.java
@@ -0,0 +1,18 @@
+package lambdaExpression18_in;
+
+@FunctionalInterface
+interface FI {
+ int foo1(int a);
+}
+
+class FI_1 {
+ void fun(int a) {
+ FI i1 = x1-> x1;
+ FI i2 = xxx-> /*]*/extracted(a, i1, xxx)/*[*/;
+ }
+
+ private int extracted(int a, FI i1, int xxx) {
+ i1.foo1(a);
+ return xxx;
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_out/A_test329.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_out/A_test329.java
new file mode 100644
index 0000000..c07d191
--- /dev/null
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/lambdaExpression18_out/A_test329.java
@@ -0,0 +1,18 @@
+package lambdaExpression18_in;
+
+@FunctionalInterface
+interface FI {
+ void foo1(int a);
+}
+
+class FI_1 {
+ void foo(int a, FI fi) {
+ fi.foo1(a);
+ }
+ void fun(int a) {
+ foo(a, xxx -> /*]*/extracted(a)/*[*/);
+ }
+ private void extracted(int a) {
+ System.out.println(a);
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/semicolon_out/A_test402.java b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/semicolon_out/A_test402.java
index 9172545..f57be17 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/semicolon_out/A_test402.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/resources/ExtractMethodWorkSpace/ExtractMethodTests/semicolon_out/A_test402.java
@@ -6,8 +6,6 @@
}
protected void extracted() {
- /*[*/{
- foo();
- }/*]*/
+ foo();
}
}
diff --git a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests1d8.java b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests1d8.java
index 88702f9..b221d98 100644
--- a/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests1d8.java
+++ b/org.eclipse.jdt.ui.tests.refactoring/test cases/org/eclipse/jdt/ui/tests/refactoring/ExtractMethodTests1d8.java
@@ -327,4 +327,14 @@
lambdaExpressionTest(0, Modifier.PRIVATE);
}
+ @Test
+ public void test328() throws Exception {
+ lambdaExpressionTest(0, Modifier.PRIVATE);
+ }
+
+ @Test
+ public void test329() throws Exception {
+ lambdaExpressionTest(0, Modifier.PRIVATE);
+ }
+
}
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java
index 3e091a7..c6d2c27 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodAnalyzer.java
@@ -921,7 +921,7 @@
int bodyExclusiveEnd= bodyStart + body.getLength();
boolean isValidSelection= false;
- if ((body instanceof Block) && (bodyStart < selectionStart && selectionExclusiveEnd <= bodyExclusiveEnd)) {
+ if ((body instanceof Block) && (bodyStart <= selectionStart && selectionExclusiveEnd <= bodyExclusiveEnd)) {
// if selection is inside lambda body's block
isValidSelection= true;
} else if (body instanceof Expression) {
diff --git a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java
index d63540b..d7ae6d5 100644
--- a/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java
+++ b/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ExtractMethodRefactoring.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2020 IBM Corporation and others.
+ * Copyright (c) 2000, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -77,6 +77,7 @@
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.LabeledStatement;
+import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
@@ -1243,9 +1244,25 @@
fAnalyzer.getReturnTypeBinding().equals(fAST.resolveWellKnownType("void")); //$NON-NLS-1$
if (selectedNodes.length == 1) {
if (!isReturnVoid) {
- statements.insertLast(fRewriter.createMoveTarget(selectedNodes[0]), substitute);
+ if (selectedNodes[0] instanceof Block) {
+ Block block= (Block)selectedNodes[0];
+ List<Statement> blockStatements= block.statements();
+ for (Statement blockStatement : blockStatements) {
+ statements.insertLast(fRewriter.createMoveTarget(blockStatement), substitute);
+ }
+ } else {
+ statements.insertLast(fRewriter.createMoveTarget(selectedNodes[0]), substitute);
+ }
}
- fRewriter.replace(selectedNodes[0], replacementNode, substitute);
+ if (selectedNodes[0].getLocationInParent() == LambdaExpression.BODY_PROPERTY) {
+ if (replacementNode instanceof ExpressionStatement) {
+ fRewriter.replace(selectedNodes[0], ((ExpressionStatement)replacementNode).getExpression(), substitute);
+ } else if (replacementNode instanceof ReturnStatement) {
+ fRewriter.replace(selectedNodes[0], ((ReturnStatement)replacementNode).getExpression(), substitute);
+ }
+ } else {
+ fRewriter.replace(selectedNodes[0], replacementNode, substitute);
+ }
} else if (selectedNodes.length > 1) {
if (isReturnVoid) {
fRewriter.remove(selectedNodes[selectedNodes.length - 1], substitute);