introduce variable from one line lambda transforms body to code block (IDEA-91122)

This commit is contained in:
Anna Kozlova
2012-09-06 19:10:15 +04:00
parent 3ee8a858bd
commit a8ea5d4deb
7 changed files with 66 additions and 2 deletions
@@ -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;
}
@@ -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;
}
@@ -0,0 +1,8 @@
class Foo {
void test() {
Comparable<String> java = o -> {
int c = o.length();
return c;
};
}
}
@@ -0,0 +1,5 @@
class Foo {
void test() {
Comparable<String> java = o -> <selection>o.length()</selection>;
}
}
@@ -0,0 +1,8 @@
class Foo {
void test() {
Runnable java = () -> {
String c = "";
System.out.println(c);
};
}
}
@@ -0,0 +1,5 @@
class Foo {
void test() {
Runnable java = () -> System.out.println(<selection>""</selection>);
}
}
@@ -371,6 +371,13 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM<java.lang.String>"));
}
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");