Fixed KT-2071: Cannot Introduce Variable from function literal.
This commit is contained in:
@@ -50,6 +50,13 @@ public class JetPsiFactory {
|
|||||||
return property.getInitializer();
|
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) {
|
public static JetTypeReference createType(Project project, String type) {
|
||||||
JetProperty property = createProperty(project, "val x : " + type);
|
JetProperty property = createProperty(project, "val x : " + type);
|
||||||
return property.getPropertyTypeRef();
|
return property.getPropertyTypeRef();
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
cannot.refactor.not.expression=Cannot find an expression to introduce
|
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
|
expressions.title=Expressions
|
||||||
introduce.variable=Introduce Variable
|
introduce.variable=Introduce Variable
|
||||||
cannot.refactor.no.container=Cannot refactor in this place
|
cannot.refactor.no.container=Cannot refactor in this place
|
||||||
cannot.refactor.no.expression=Cannot perform refactoring without an expression
|
cannot.refactor.no.expression=Cannot perform refactoring without an expression
|
||||||
cannot.refactor.expression.has.unit.type=Cannot introduce expression of unit type
|
cannot.refactor.expression.has.unit.type=Cannot introduce expression of unit type
|
||||||
cannot.refactor.namespace.expression=Cannot intoduce namespace reference
|
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
|
||||||
|
|||||||
+4
-2
@@ -61,6 +61,7 @@ public class JetInplaceVariableIntroducer extends InplaceVariableIntroducer<JetE
|
|||||||
private final boolean isVar;
|
private final boolean isVar;
|
||||||
private final boolean myDoNotChangeVar;
|
private final boolean myDoNotChangeVar;
|
||||||
@Nullable private final JetType myExprType;
|
@Nullable private final JetType myExprType;
|
||||||
|
private final boolean noTypeInference;
|
||||||
private JCheckBox myVarCheckbox;
|
private JCheckBox myVarCheckbox;
|
||||||
private JCheckBox myExprTypeCheckbox;
|
private JCheckBox myExprTypeCheckbox;
|
||||||
|
|
||||||
@@ -68,13 +69,14 @@ public class JetInplaceVariableIntroducer extends InplaceVariableIntroducer<JetE
|
|||||||
String title, JetExpression[] occurrences,
|
String title, JetExpression[] occurrences,
|
||||||
@Nullable JetExpression expr, boolean replaceOccurrence,
|
@Nullable JetExpression expr, boolean replaceOccurrence,
|
||||||
JetProperty property, boolean isVar, boolean doNotChangeVar,
|
JetProperty property, boolean isVar, boolean doNotChangeVar,
|
||||||
@Nullable JetType exprType) {
|
@Nullable JetType exprType, boolean noTypeInference) {
|
||||||
super(elementToRename, editor, project, title, occurrences, expr);
|
super(elementToRename, editor, project, title, occurrences, expr);
|
||||||
this.myReplaceOccurrence = replaceOccurrence;
|
this.myReplaceOccurrence = replaceOccurrence;
|
||||||
myProperty = property;
|
myProperty = property;
|
||||||
this.isVar = isVar;
|
this.isVar = isVar;
|
||||||
myDoNotChangeVar = doNotChangeVar;
|
myDoNotChangeVar = doNotChangeVar;
|
||||||
myExprType = exprType;
|
myExprType = exprType;
|
||||||
|
this.noTypeInference = noTypeInference;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -99,7 +101,7 @@ public class JetInplaceVariableIntroducer extends InplaceVariableIntroducer<JetE
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (myExprType != null) {
|
if (myExprType != null && !noTypeInference) {
|
||||||
myExprTypeCheckbox = new NonFocusableCheckBox("Specify type explicitly");
|
myExprTypeCheckbox = new NonFocusableCheckBox("Specify type explicitly");
|
||||||
myExprTypeCheckbox.setSelected(false);
|
myExprTypeCheckbox.setSelected(false);
|
||||||
myExprTypeCheckbox.setMnemonic('t');
|
myExprTypeCheckbox.setMnemonic('t');
|
||||||
|
|||||||
+58
-12
@@ -43,8 +43,10 @@ import org.jetbrains.jet.lang.types.NamespaceType;
|
|||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||||
import org.jetbrains.jet.lexer.JetTokens;
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
import org.jetbrains.jet.plugin.codeInsight.ReferenceToClassesShortening;
|
||||||
import org.jetbrains.jet.plugin.project.AnalyzeSingleFileUtil;
|
import org.jetbrains.jet.plugin.project.AnalyzeSingleFileUtil;
|
||||||
import org.jetbrains.jet.plugin.refactoring.*;
|
import org.jetbrains.jet.plugin.refactoring.*;
|
||||||
|
import org.jetbrains.jet.resolve.DescriptorRenderer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -81,6 +83,8 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
_expression = (JetExpression)_expression.getParent();
|
_expression = (JetExpression)_expression.getParent();
|
||||||
}
|
}
|
||||||
final JetExpression expression = _expression;
|
final JetExpression expression = _expression;
|
||||||
|
boolean noTypeInference = false;
|
||||||
|
boolean needParentheses = false;
|
||||||
if (expression.getParent() instanceof JetQualifiedExpression) {
|
if (expression.getParent() instanceof JetQualifiedExpression) {
|
||||||
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression)expression.getParent();
|
JetQualifiedExpression qualifiedExpression = (JetQualifiedExpression)expression.getParent();
|
||||||
if (qualifiedExpression.getReceiverExpression() != expression) {
|
if (qualifiedExpression.getReceiverExpression() != expression) {
|
||||||
@@ -88,9 +92,17 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (expression.getParent() instanceof JetCallElement || expression instanceof JetStatementExpression) {
|
else if (expression instanceof JetStatementExpression) {
|
||||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.no.expression"));
|
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.no.expression"));
|
||||||
return;
|
return;
|
||||||
|
} else if (expression.getParent() instanceof JetCallElement) {
|
||||||
|
if (expression instanceof JetFunctionLiteralExpression) {
|
||||||
|
noTypeInference = true;
|
||||||
|
needParentheses = true;
|
||||||
|
} else {
|
||||||
|
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.no.expression"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (expression.getParent() instanceof JetOperationExpression) {
|
else if (expression.getParent() instanceof JetOperationExpression) {
|
||||||
JetOperationExpression operationExpression = (JetOperationExpression)expression.getParent();
|
JetOperationExpression operationExpression = (JetOperationExpression)expression.getParent();
|
||||||
@@ -110,6 +122,10 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.expression.has.unit.type"));
|
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.expression.has.unit.type"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (expressionType == null && noTypeInference) {
|
||||||
|
showErrorHint(project, editor, JetRefactoringBundle.message("cannot.refactor.expression.should.have.inferred.type"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
final PsiElement container = getContainer(expression);
|
final PsiElement container = getContainer(expression);
|
||||||
final PsiElement occurrenceContainer = getOccurrenceContainer(expression);
|
final PsiElement occurrenceContainer = getOccurrenceContainer(expression);
|
||||||
if (container == null) {
|
if (container == null) {
|
||||||
@@ -119,7 +135,9 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
final boolean isInplaceAvailableOnDataContext =
|
final boolean isInplaceAvailableOnDataContext =
|
||||||
editor.getSettings().isVariableInplaceRenameEnabled() &&
|
editor.getSettings().isVariableInplaceRenameEnabled() &&
|
||||||
!ApplicationManager.getApplication().isUnitTestMode();
|
!ApplicationManager.getApplication().isUnitTestMode();
|
||||||
final ArrayList<JetExpression> allOccurrences = findOccurrences(occurrenceContainer, expression);
|
final List<JetExpression> allOccurrences = findOccurrences(occurrenceContainer, expression);
|
||||||
|
final boolean finalNoTypeInference = noTypeInference;
|
||||||
|
final boolean finalNeedParentheses = needParentheses;
|
||||||
Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
|
Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
|
||||||
@Override
|
@Override
|
||||||
public void pass(OccurrencesChooser.ReplaceChoice replaceChoice) {
|
public void pass(OccurrencesChooser.ReplaceChoice replaceChoice) {
|
||||||
@@ -147,7 +165,7 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
final Ref<JetExpression> reference = new Ref<JetExpression>();
|
final Ref<JetExpression> reference = new Ref<JetExpression>();
|
||||||
final Runnable introduceRunnable = introduceVariable(project, expression, suggestedNames, allReplaces, commonContainer,
|
final Runnable introduceRunnable = introduceVariable(project, expression, suggestedNames, allReplaces, commonContainer,
|
||||||
commonParent, replaceOccurrence, propertyRef, references,
|
commonParent, replaceOccurrence, propertyRef, references,
|
||||||
reference);
|
reference, finalNoTypeInference, finalNeedParentheses, expressionType);
|
||||||
final boolean finalReplaceOccurrence = replaceOccurrence;
|
final boolean finalReplaceOccurrence = replaceOccurrence;
|
||||||
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -166,7 +184,7 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
references.toArray(new JetExpression[references.size()]),
|
references.toArray(new JetExpression[references.size()]),
|
||||||
reference.get(), finalReplaceOccurrence,
|
reference.get(), finalReplaceOccurrence,
|
||||||
property, /*todo*/false, /*todo*/false,
|
property, /*todo*/false, /*todo*/false,
|
||||||
expressionType);
|
expressionType, finalNoTypeInference);
|
||||||
variableIntroducer.performInplaceRefactoring(suggestedNamesSet);
|
variableIntroducer.performInplaceRefactoring(suggestedNamesSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,11 +207,18 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
final PsiElement commonParent, final boolean replaceOccurrence,
|
final PsiElement commonParent, final boolean replaceOccurrence,
|
||||||
final Ref<JetProperty> propertyRef,
|
final Ref<JetProperty> propertyRef,
|
||||||
final ArrayList<JetExpression> references,
|
final ArrayList<JetExpression> references,
|
||||||
final Ref<JetExpression> reference) {
|
final Ref<JetExpression> reference,
|
||||||
|
final boolean noTypeInference,
|
||||||
|
final boolean needParentheses,
|
||||||
|
final JetType expressionType) {
|
||||||
return new Runnable() {
|
return new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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) {
|
if (expression instanceof JetParenthesizedExpression) {
|
||||||
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression)expression;
|
JetParenthesizedExpression parenthesizedExpression = (JetParenthesizedExpression)expression;
|
||||||
JetExpression innerExpression = parenthesizedExpression.getExpression();
|
JetExpression innerExpression = parenthesizedExpression.getExpression();
|
||||||
@@ -225,9 +250,15 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
if (replaceOccurrence && commonContainer != null) {
|
if (replaceOccurrence && commonContainer != null) {
|
||||||
for (JetExpression replace : allReplaces) {
|
for (JetExpression replace : allReplaces) {
|
||||||
boolean isActualExpression = expression == replace;
|
boolean isActualExpression = expression == replace;
|
||||||
JetExpression element =
|
if (!needParentheses && !(replace.getParent() instanceof JetCallExpression)) {
|
||||||
(JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0]));
|
JetExpression element =
|
||||||
if (isActualExpression) reference.set(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;
|
PsiElement oldElement = commonContainer;
|
||||||
if (commonContainer instanceof JetWhenEntry) {
|
if (commonContainer instanceof JetWhenEntry) {
|
||||||
@@ -322,15 +353,30 @@ public class JetIntroduceVariableHandler extends JetIntroduceHandlerBase {
|
|||||||
for (JetExpression replace : allReplaces) {
|
for (JetExpression replace : allReplaces) {
|
||||||
if (replaceOccurrence && !needBraces) {
|
if (replaceOccurrence && !needBraces) {
|
||||||
boolean isActualExpression = expression == replace;
|
boolean isActualExpression = expression == replace;
|
||||||
JetExpression element = (JetExpression)replace.replace(JetPsiFactory.createExpression(project, suggestedNames[0]));
|
|
||||||
references.add(element);
|
if (!needParentheses && !(replace.getParent() instanceof JetCallExpression)) {
|
||||||
if (isActualExpression) reference.set(element);
|
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) {
|
else if (!needBraces) {
|
||||||
replace.delete();
|
replace.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
propertyRef.set(property);
|
propertyRef.set(property);
|
||||||
|
if (noTypeInference) {
|
||||||
|
ReferenceToClassesShortening.compactReferenceToClasses(Collections.singletonList(property));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
fun foo(c : Collection<String>){
|
||||||
|
c.filter<selection>{it; false}</selection>
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
fun foo(c : Collection<String>){
|
||||||
|
val function: () -> Boolean = {it; false}
|
||||||
|
c.filter(function)
|
||||||
|
}
|
||||||
|
*/
|
||||||
+4
@@ -53,6 +53,10 @@ public class JetIntroduceVariableTest extends LightCodeInsightFixtureTestCase {
|
|||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testFunctionLiteral() {
|
||||||
|
doTest();
|
||||||
|
}
|
||||||
|
|
||||||
public void testIfCondition() {
|
public void testIfCondition() {
|
||||||
doTest();
|
doTest();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user