diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java index 640d596aaffc..1c2a7fe01dcf 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java @@ -524,7 +524,7 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { final PsiElement tempContainer = anchorStatement.getParent(); - if (!(tempContainer instanceof PsiCodeBlock) && !isLoopOrIf(tempContainer)) { + if (!(tempContainer instanceof PsiCodeBlock) && !isLoopOrIf(tempContainer) && (tempContainer.getParent() instanceof PsiLambdaExpression)) { String message = RefactoringBundle.message("refactoring.is.not.supported.in.the.current.context", REFACTORING_NAME); showErrorMessage(project, editor, message); return false; @@ -913,10 +913,11 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { public static PsiStatement putStatementInLoopBody(PsiStatement declaration, PsiElement container, PsiElement finalAnchorStatement) throws IncorrectOperationException { + final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(container.getProject()).getElementFactory(); if(isLoopOrIf(container)) { PsiStatement loopBody = getLoopBody(container, finalAnchorStatement); PsiStatement loopBodyCopy = loopBody != null ? (PsiStatement) loopBody.copy() : null; - PsiBlockStatement blockStatement = (PsiBlockStatement)JavaPsiFacade.getInstance(container.getProject()).getElementFactory() + PsiBlockStatement blockStatement = (PsiBlockStatement)elementFactory .createStatementFromText("{}", null); blockStatement = (PsiBlockStatement) CodeStyleManager.getInstance(container.getProject()).reformat(blockStatement); final PsiElement prevSibling = loopBody.getPrevSibling(); @@ -931,6 +932,35 @@ public abstract class IntroduceVariableBase extends IntroduceHandlerBase { declaration = (PsiStatement) codeBlock.add(declaration); JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration); if (loopBodyCopy != null) codeBlock.add(loopBodyCopy); + } else if (container instanceof PsiLambdaExpression) { + final PsiLambdaExpression lambdaExpression = (PsiLambdaExpression)container; + final PsiElement lambdaExpressionBody = lambdaExpression.getBody(); + LOG.assertTrue(lambdaExpressionBody != null); + + final PsiLambdaExpression expressionFromText = (PsiLambdaExpression)elementFactory + .createExpressionFromText(lambdaExpression.getParameterList().getText() + " -> {}", lambdaExpression); + PsiCodeBlock newBody = (PsiCodeBlock)expressionFromText.getBody(); + LOG.assertTrue(newBody != null); + newBody.add(declaration); + + final PsiStatement lastBodyStatement; + if (LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression) == PsiType.VOID) { + lastBodyStatement = elementFactory.createStatementFromText("a;", lambdaExpression); + ((PsiExpressionStatement)lastBodyStatement).getExpression().replace(lambdaExpressionBody); + } + else { + lastBodyStatement = elementFactory.createStatementFromText("return a;", lambdaExpression); + final PsiExpression returnValue = ((PsiReturnStatement)lastBodyStatement).getReturnValue(); + LOG.assertTrue(returnValue != null); + returnValue.replace(lambdaExpressionBody); + } + newBody.add(lastBodyStatement); + + final PsiLambdaExpression copy = (PsiLambdaExpression)lambdaExpression.replace(expressionFromText); + newBody = (PsiCodeBlock)copy.getBody(); + LOG.assertTrue(newBody != null); + declaration = newBody.getStatements()[0]; + declaration = (PsiStatement)JavaCodeStyleManager.getInstance(declaration.getProject()).shortenClassReferences(declaration); } return declaration; } diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java index d734719ad376..9a31eceddb7e 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -292,6 +292,7 @@ public class RefactoringUtil { PsiElement parent = place; while (true) { if (parent instanceof PsiStatement) break; + if (parent instanceof PsiExpression && parent.getParent() instanceof PsiLambdaExpression) return parent; parent = parent.getParent(); if (parent == null) return null; } diff --git a/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaValueCompatible.after.java b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaValueCompatible.after.java new file mode 100644 index 000000000000..7e5887fe598c --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaValueCompatible.after.java @@ -0,0 +1,8 @@ +class Foo { + void test() { + Comparable java = o -> { + int c = o.length(); + return c; + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaValueCompatible.java b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaValueCompatible.java new file mode 100644 index 000000000000..247f972d3e00 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaValueCompatible.java @@ -0,0 +1,5 @@ +class Foo { + void test() { + Comparable java = o -> o.length(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaVoidCompatible.after.java b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaVoidCompatible.after.java new file mode 100644 index 000000000000..33cf47d29f4c --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaVoidCompatible.after.java @@ -0,0 +1,8 @@ +class Foo { + void test() { + Runnable java = () -> { + String c = ""; + System.out.println(c); + }; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaVoidCompatible.java b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaVoidCompatible.java new file mode 100644 index 000000000000..1905f6ac7982 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/OneLineLambdaVoidCompatible.java @@ -0,0 +1,5 @@ +class Foo { + void test() { + Runnable java = () -> System.out.println(""); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index c926f13cfdd3..14c47a4a5431 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -371,6 +371,13 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM")); } + public void testOneLineLambdaVoidCompatible() throws Exception { + doTest(new MockIntroduceVariableHandler("c", false, false, false, "java.lang.String")); + } + public void testOneLineLambdaValueCompatible() throws Exception { + doTest(new MockIntroduceVariableHandler("c", false, false, false, "int")); + } + private void doTest(IntroduceVariableBase testMe) throws Exception { @NonNls String baseName = "/refactoring/introduceVariable/" + getTestName(false); configureByFile(baseName + ".java");