Supported vals initialized after.

#KT-2637 in progress
This commit is contained in:
Evgeny Gerashchenko
2013-07-09 19:13:37 +04:00
parent 72ed74ab9a
commit c22f54055e
11 changed files with 131 additions and 13 deletions
@@ -1,5 +1,6 @@
package org.jetbrains.jet.plugin.refactoring.inline;
import com.google.common.collect.Sets;
import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.lang.Language;
import com.intellij.lang.refactoring.InlineActionHandler;
@@ -18,11 +19,14 @@ import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.RefactoringMessageDialog;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lexer.JetTokens;
import org.jetbrains.jet.plugin.JetLanguage;
import java.util.Collection;
import java.util.Set;
public class KotlinInlineLocalHandler extends InlineActionHandler {
@Override
@@ -36,7 +40,7 @@ public class KotlinInlineLocalHandler extends InlineActionHandler {
return false;
}
JetProperty property = (JetProperty) element;
return property.getInitializer() != null && !property.isVar();
return !property.isVar();
}
@Override
@@ -44,10 +48,40 @@ public class KotlinInlineLocalHandler extends InlineActionHandler {
final JetProperty val = (JetProperty) element;
String name = val.getName();
final JetExpression initializer = val.getInitializer();
assert initializer != null : element.getText();
JetExpression initializerInDeclaration = val.getInitializer();
final Collection<PsiReference> references = ReferencesSearch.search(val, GlobalSearchScope.allScope(project), false).findAll();
final Set<PsiElement> assignments = Sets.newHashSet();
for (PsiReference ref : references) {
PsiElement refElement = ref.getElement();
PsiElement parent = refElement.getParent();
if (parent instanceof JetBinaryExpression &&
((JetBinaryExpression) parent).getOperationToken() == JetTokens.EQ &&
((JetBinaryExpression) parent).getLeft() == refElement) {
assignments.add(parent);
}
}
final JetExpression initializer;
if (initializerInDeclaration != null) {
initializer = initializerInDeclaration;
}
else {
if (assignments.size() == 1) {
initializer = ((JetBinaryExpression) assignments.iterator().next()).getRight();
}
else {
initializer = null;
}
if (initializer == null) {
String key = assignments.isEmpty() ? "variable.has.no.initializer" : "variable.has.no.dominating.definition";
String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, name));
CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("inline.variable.title"), HelpID.INLINE_VARIABLE);
return;
}
}
PsiReference[] referencesArray = references.toArray(references.toArray(new PsiReference[references.size()]));
if (editor != null && !ApplicationManager.getApplication().isUnitTestMode()) {
@@ -80,6 +114,10 @@ public class KotlinInlineLocalHandler extends InlineActionHandler {
public void run() {
for (PsiReference reference : references) {
PsiElement referenceElement = reference.getElement();
if (assignments.contains(referenceElement.getParent())) {
continue;
}
if (referenceElement.getParent() instanceof JetSimpleNameStringTemplateEntry &&
!(initializer instanceof JetSimpleNameExpression)) {
referenceElement.getParent().replace(JetPsiFactory.createBlockStringTemplateEntry(project, initializer));
@@ -89,6 +127,10 @@ public class KotlinInlineLocalHandler extends InlineActionHandler {
}
}
for (PsiElement assignment : assignments) {
assignment.delete();
}
val.delete();
}
});
@@ -0,0 +1,12 @@
// ERROR: Cannot perform refactoring.\nCannot find a single definition to inline.
fun f() {
val v: Int
if (true) {
v = 239
}
else {
v = 30
}
println(<caret>v)
}
@@ -0,0 +1,5 @@
fun f() {
val v: Int
v = 239
println(<caret>v)
}
@@ -0,0 +1,3 @@
fun f() {
println(239)
}
@@ -0,0 +1,8 @@
fun f() {
val v: Int
try {
v = 239
} finally {
}
println(<caret>v)
}
@@ -0,0 +1,6 @@
fun f() {
try {
} finally {
}
println(239)
}
@@ -0,0 +1,4 @@
fun f() {
val v = 239
vv = <caret>v
}
@@ -0,0 +1,3 @@
fun f() {
vv = 239
}
@@ -1,3 +1,5 @@
// ERROR: Cannot perform refactoring.\nVariable v has no initializer.
fun f() {
val v: Int
println(<caret>v)
@@ -4,11 +4,14 @@ import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.InTextDirectivesUtils;
import java.io.File;
import java.io.IOException;
import java.util.List;
import static com.intellij.codeInsight.TargetElementUtilBase.ELEMENT_NAME_ACCEPTED;
import static com.intellij.codeInsight.TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED;
@@ -25,17 +28,27 @@ public abstract class AbstractInlineTest extends LightCodeInsightFixtureTestCase
TargetElementUtilBase.findTargetElement(myFixture.getEditor(), ELEMENT_NAME_ACCEPTED | REFERENCED_ELEMENT_ACCEPTED);
final KotlinInlineLocalHandler handler = new KotlinInlineLocalHandler();
assertEquals(afterFileExists, handler.canInlineElement(targetElement));
if (!afterFileExists) {
return;
}
List<String> expectedErrors = InTextDirectivesUtils.findLinesWithPrefixesRemoved(myFixture.getFile().getText(), "// ERROR: ");
if (handler.canInlineElement(targetElement)) {
try {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
handler.inlineElement(myFixture.getProject(), myFixture.getEditor(), targetElement);
}
});
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
handler.inlineElement(myFixture.getProject(), myFixture.getEditor(), targetElement);
assertTrue(afterFileExists);
assertEmpty(expectedErrors);
myFixture.checkResult(FileUtil.loadFile(afterFile));
} catch (CommonRefactoringUtil.RefactoringErrorHintException e) {
assertFalse(afterFileExists);
assertEquals(1, expectedErrors.size());
assertEquals(expectedErrors.get(0).replace("\\n", "\n"), e.getMessage());
}
});
myFixture.checkResult(FileUtil.loadFile(afterFile));
}
else {
assertFalse(afterFileExists);
}
}
}
@@ -57,6 +57,11 @@ public class InlineTestGenerated extends AbstractInlineTest {
doTest("idea/testData/refactoring/inline/MethodReference.kt");
}
@TestMetadata("MultipleInitializers.kt")
public void testMultipleInitializers() throws Exception {
doTest("idea/testData/refactoring/inline/MultipleInitializers.kt");
}
@TestMetadata("MultipleUsages.kt")
public void testMultipleUsages() throws Exception {
doTest("idea/testData/refactoring/inline/MultipleUsages.kt");
@@ -67,6 +72,21 @@ public class InlineTestGenerated extends AbstractInlineTest {
doTest("idea/testData/refactoring/inline/Parameter.kt");
}
@TestMetadata("SeparateInitializer.kt")
public void testSeparateInitializer() throws Exception {
doTest("idea/testData/refactoring/inline/SeparateInitializer.kt");
}
@TestMetadata("SeparateInitializerInTry.kt")
public void testSeparateInitializerInTry() throws Exception {
doTest("idea/testData/refactoring/inline/SeparateInitializerInTry.kt");
}
@TestMetadata("UsedInAssignment.kt")
public void testUsedInAssignment() throws Exception {
doTest("idea/testData/refactoring/inline/UsedInAssignment.kt");
}
@TestMetadata("ValWithoutInitializer.kt")
public void testValWithoutInitializer() throws Exception {
doTest("idea/testData/refactoring/inline/ValWithoutInitializer.kt");