From b9267dc7cf438a6a2f41fcb7c75ce6e67f04aa4f Mon Sep 17 00:00:00 2001 From: "Alexander.Podkhalyuzin" Date: Wed, 23 May 2012 15:58:55 +0400 Subject: [PATCH] Fixed KT-2071: Cannot Introduce Variable from function literal. --- .../jetbrains/jet/lang/psi/JetPsiFactory.java | 7 ++ .../JetRefactoringBundle.properties | 6 +- .../JetInplaceVariableIntroducer.java | 6 +- .../JetIntroduceVariableHandler.java | 70 +++++++++++++++---- .../introduceVariable/FunctionLiteral.kt | 9 +++ .../JetIntroduceVariableTest.java | 4 ++ 6 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 idea/testData/refactoring/introduceVariable/FunctionLiteral.kt diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java index 467123f6b50..18c77085e48 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java @@ -50,6 +50,13 @@ public class JetPsiFactory { return property.getInitializer(); } + public static JetValueArgumentList createCallArguments(Project project, String text) { + JetProperty property = createProperty(project, "val x = foo" + text); + JetExpression initializer = property.getInitializer(); + JetCallExpression callExpression = (JetCallExpression) initializer; + return callExpression.getValueArgumentList(); + } + public static JetTypeReference createType(Project project, String type) { JetProperty property = createProperty(project, "val x : " + type); return property.getPropertyTypeRef(); diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties index aea52d2542a..8c2016d80a4 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/JetRefactoringBundle.properties @@ -1,7 +1,11 @@ cannot.refactor.not.expression=Cannot find an expression to introduce +cannot.refactor.not.expression.to.extract=Cannot find an expression to extract expressions.title=Expressions introduce.variable=Introduce Variable cannot.refactor.no.container=Cannot refactor in this place cannot.refactor.no.expression=Cannot perform refactoring without an expression cannot.refactor.expression.has.unit.type=Cannot introduce expression of unit type -cannot.refactor.namespace.expression=Cannot intoduce namespace reference \ No newline at end of file +cannot.refactor.namespace.expression=Cannot intoduce namespace reference +cannot.extract.method=Cannot find statements to extract +cannot.find.class.to.extract=Cannot find class to extract method +cannot.refactor.expression.should.have.inferred.type=Expression should have inferred type diff --git a/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetInplaceVariableIntroducer.java b/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetInplaceVariableIntroducer.java index 07e2448d692..764d44939a6 100644 --- a/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetInplaceVariableIntroducer.java +++ b/idea/src/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetInplaceVariableIntroducer.java @@ -61,6 +61,7 @@ public class JetInplaceVariableIntroducer extends InplaceVariableIntroducer allOccurrences = findOccurrences(occurrenceContainer, expression); + final List allOccurrences = findOccurrences(occurrenceContainer, expression); + final boolean finalNoTypeInference = noTypeInference; + final boolean finalNeedParentheses = needParentheses; Pass callback = new Pass() { @Override public void pass(OccurrencesChooser.ReplaceChoice replaceChoice) { @@ -147,7 +165,7 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase { final Ref reference = new Ref(); final Runnable introduceRunnable = introduceVariable(project, expression, suggestedNames, allReplaces, commonContainer, commonParent, replaceOccurrence, propertyRef, references, - reference); + reference, finalNoTypeInference, finalNeedParentheses, expressionType); final boolean finalReplaceOccurrence = replaceOccurrence; CommandProcessor.getInstance().executeCommand(project, new Runnable() { @Override @@ -166,7 +184,7 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase { references.toArray(new JetExpression[references.size()]), reference.get(), finalReplaceOccurrence, property, /*todo*/false, /*todo*/false, - expressionType); + expressionType, finalNoTypeInference); variableIntroducer.performInplaceRefactoring(suggestedNamesSet); } } @@ -189,11 +207,18 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase { final PsiElement commonParent, final boolean replaceOccurrence, final Ref propertyRef, final ArrayList references, - final Ref reference) { + final Ref reference, + final boolean noTypeInference, + final boolean needParentheses, + final JetType expressionType) { return new Runnable() { @Override public void run() { - String variableText = "val " + suggestedNames[0] + " = "; + String variableText = "val " + suggestedNames[0]; + if (noTypeInference) { + variableText += ": " + DescriptorRenderer.TEXT.renderType(expressionType); + } + variableText += " = "; if (expression instanceof JetParenthesizedExpression) { JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression)expression; JetExpression innerExpression = parenthesizedExpression.getExpression(); @@ -225,9 +250,15 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase { if (replaceOccurrence && commonContainer != null) { for (JetExpression replace : allReplaces) { boolean isActualExpression = expression == replace; - JetExpression element = - (JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0])); - if (isActualExpression) reference.set(element); + if (!needParentheses && !(replace.getParent() instanceof JetCallExpression)) { + JetExpression element = + (JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0])); + if (isActualExpression) reference.set(element); + } else { + JetValueArgumentList argumentList = JetPsiFactory.createCallArguments(project, "(" + suggestedNames[0] + ")"); + JetValueArgumentList element = (JetValueArgumentList) replace.replace(argumentList); + if (isActualExpression) reference.set(element.getArguments().get(0).getArgumentExpression()); + } } PsiElement oldElement = commonContainer; if (commonContainer instanceof JetWhenEntry) { @@ -322,15 +353,30 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase { for (JetExpression replace : allReplaces) { if (replaceOccurrence && !needBraces) { boolean isActualExpression = expression == replace; - JetExpression element = (JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0])); - references.add(element); - if (isActualExpression) reference.set(element); + + if (!needParentheses && !(replace.getParent() instanceof JetCallExpression)) { + JetExpression element = + (JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0])); + references.add(element); + if (isActualExpression) reference.set(element); + } else { + JetValueArgumentList argumentList = JetPsiFactory.createCallArguments(project, "(" + suggestedNames[0] + ")"); + JetValueArgumentList element = (JetValueArgumentList) replace.replace(argumentList); + JetExpression argumentExpression = element.getArguments().get(0).getArgumentExpression(); + references.add(argumentExpression); + if (isActualExpression) { + reference.set(argumentExpression); + } + } } else if (!needBraces) { replace.delete(); } } propertyRef.set(property); + if (noTypeInference) { + ReferenceToClassesShortening.compactReferenceToClasses(Collections.singletonList(property)); + } } }; } diff --git a/idea/testData/refactoring/introduceVariable/FunctionLiteral.kt b/idea/testData/refactoring/introduceVariable/FunctionLiteral.kt new file mode 100644 index 00000000000..eec79ae40b0 --- /dev/null +++ b/idea/testData/refactoring/introduceVariable/FunctionLiteral.kt @@ -0,0 +1,9 @@ +fun foo(c : Collection){ + c.filter{it; false} +} +/* +fun foo(c : Collection){ + val function: () -> Boolean = {it; false} + c.filter(function) +} +*/ \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableTest.java b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableTest.java index dfb3f896973..e75e211460c 100644 --- a/idea/tests/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/refactoring/introduceVariable/JetIntroduceVariableTest.java @@ -53,6 +53,10 @@ public class JetIntroduceVariableTest extends LightCodeInsightFixtureTestCase { doTest(); } + public void testFunctionLiteral() { + doTest(); + } + public void testIfCondition() { doTest(); }