From e3d8d819da7a153dbdce9529b6b19ec551445872 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Mon, 28 Sep 2015 19:28:12 +0300 Subject: [PATCH] Inline Variable: Var support #KT-5169 Fixed --- .../inline/KotlinInlineValHandler.java | 43 +++++++++++++++---- idea/testData/refactoring/inline/Var.kt | 4 -- .../inline/addParenthesis/IfIntoPostfix.kt | 1 + .../addParenthesis/IfIntoPostfix.kt.after | 3 -- .../testData/refactoring/inline/varNoWrite.kt | 4 ++ .../refactoring/inline/varNoWrite.kt.after | 3 ++ .../refactoring/inline/varWithAssignment.kt | 6 +++ .../testData/refactoring/inline/varWithInc.kt | 6 +++ .../inline/InlineTestGenerated.java | 18 ++++++-- 9 files changed, 70 insertions(+), 18 deletions(-) delete mode 100644 idea/testData/refactoring/inline/Var.kt delete mode 100644 idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt.after create mode 100644 idea/testData/refactoring/inline/varNoWrite.kt create mode 100644 idea/testData/refactoring/inline/varNoWrite.kt.after create mode 100644 idea/testData/refactoring/inline/varWithAssignment.kt create mode 100644 idea/testData/refactoring/inline/varWithInc.kt diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.java index 939195c39f3..6768c4f55b0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/inline/KotlinInlineValHandler.java @@ -54,18 +54,20 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory; import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.idea.JetLanguage; -import org.jetbrains.kotlin.idea.resolve.ResolutionFacade; import org.jetbrains.kotlin.idea.caches.resolve.ResolutionUtils; +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade; import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers; import org.jetbrains.kotlin.idea.util.ShortenReferences; import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.*; +import org.jetbrains.kotlin.psi.psiUtil.JetPsiUtilKt; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode; import org.jetbrains.kotlin.types.ErrorUtils; import org.jetbrains.kotlin.types.JetType; +import org.jetbrains.kotlin.types.expressions.OperatorConventions; import java.util.List; import java.util.Map; @@ -85,7 +87,7 @@ public class KotlinInlineValHandler extends InlineActionHandler { return false; } JetProperty property = (JetProperty) element; - return !property.isVar() && property.getGetter() == null && property.getReceiverTypeReference() == null; + return property.getGetter() == null && property.getReceiverTypeReference() == null; } @Override @@ -101,9 +103,15 @@ public class KotlinInlineValHandler extends InlineActionHandler { final Set assignments = Sets.newHashSet(); for (JetExpression expression : referenceExpressions) { PsiElement parent = expression.getParent(); - if (parent instanceof JetBinaryExpression && - ((JetBinaryExpression) parent).getOperationToken() == JetTokens.EQ && - ((JetBinaryExpression) parent).getLeft() == expression) { + + JetBinaryExpression assignment = JetPsiUtilKt.getAssignmentByLHS(expression); + if (assignment != null) { + assignments.add(parent); + } + + //noinspection SuspiciousMethodCalls + if (parent instanceof JetUnaryExpression && + OperatorConventions.INCREMENT_OPERATIONS.contains(((JetUnaryExpression) parent).getOperationToken())) { assignments.add(parent); } } @@ -111,6 +119,10 @@ public class KotlinInlineValHandler extends InlineActionHandler { final JetExpression initializer; if (initializerInDeclaration != null) { initializer = initializerInDeclaration; + if (!assignments.isEmpty()) { + reportAmbiguousAssignment(project, editor, name, assignments); + return; + } } else { if (assignments.size() == 1) { @@ -120,9 +132,7 @@ public class KotlinInlineValHandler extends InlineActionHandler { 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); + reportAmbiguousAssignment(project, editor, name, assignments); return; } } @@ -196,6 +206,23 @@ public class KotlinInlineValHandler extends InlineActionHandler { null); } + private static void reportAmbiguousAssignment(Project project, Editor editor, String name, Set assignments) { + String key = assignments.isEmpty() ? "variable.has.no.initializer" : "variable.has.no.dominating.definition"; + String message = RefactoringBundle.getCannotRefactorMessage(RefactoringBundle.message(key, name)); + showErrorHint(project, editor, message); + } + + private static void reportWriteAccess(Project project, Editor editor, String name) { + String message = RefactoringBundle.getCannotRefactorMessage( + RefactoringBundle.message("variable.is.accessed.for.writing", name) + ); + showErrorHint(project, editor, message); + } + + private static void showErrorHint(Project project, Editor editor, String message) { + CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("inline.variable.title"), HelpID.INLINE_VARIABLE); + } + private static void highlightExpressions(Project project, Editor editor, List elements) { if (editor == null || ApplicationManager.getApplication().isUnitTestMode()) { return; diff --git a/idea/testData/refactoring/inline/Var.kt b/idea/testData/refactoring/inline/Var.kt deleted file mode 100644 index 2717803d0ea..00000000000 --- a/idea/testData/refactoring/inline/Var.kt +++ /dev/null @@ -1,4 +0,0 @@ -fun f() { - var v = 239 - println(v) -} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt b/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt index a13ddf4e01f..f9cd4d7d2a7 100644 --- a/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt +++ b/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt @@ -1,3 +1,4 @@ +// ERROR: Cannot perform refactoring.\nCannot find a single definition to inline fun f() { val v = if (true) a else b println(v++) diff --git a/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt.after b/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt.after deleted file mode 100644 index ba606f82a70..00000000000 --- a/idea/testData/refactoring/inline/addParenthesis/IfIntoPostfix.kt.after +++ /dev/null @@ -1,3 +0,0 @@ -fun f() { - println((if (true) a else b)++) -} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/varNoWrite.kt b/idea/testData/refactoring/inline/varNoWrite.kt new file mode 100644 index 00000000000..2d59f4361ed --- /dev/null +++ b/idea/testData/refactoring/inline/varNoWrite.kt @@ -0,0 +1,4 @@ +fun foo() { + var x = 1 + val t = x + 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/varNoWrite.kt.after b/idea/testData/refactoring/inline/varNoWrite.kt.after new file mode 100644 index 00000000000..077d21ccbba --- /dev/null +++ b/idea/testData/refactoring/inline/varNoWrite.kt.after @@ -0,0 +1,3 @@ +fun foo() { + val t = 1 + 1 +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/varWithAssignment.kt b/idea/testData/refactoring/inline/varWithAssignment.kt new file mode 100644 index 00000000000..5fc73551c1b --- /dev/null +++ b/idea/testData/refactoring/inline/varWithAssignment.kt @@ -0,0 +1,6 @@ +// ERROR: Cannot perform refactoring.\nCannot find a single definition to inline +fun foo() { + var x = 1 + val t = x + 1 + x = 2 +} \ No newline at end of file diff --git a/idea/testData/refactoring/inline/varWithInc.kt b/idea/testData/refactoring/inline/varWithInc.kt new file mode 100644 index 00000000000..12c7156b684 --- /dev/null +++ b/idea/testData/refactoring/inline/varWithInc.kt @@ -0,0 +1,6 @@ +// ERROR: Cannot perform refactoring.\nCannot find a single definition to inline +fun foo() { + var x = 1 + val t = x + 1 + x++ +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java index ce13cad053b..bccd28a9c35 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/inline/InlineTestGenerated.java @@ -101,9 +101,21 @@ public class InlineTestGenerated extends AbstractInlineTest { doTest(fileName); } - @TestMetadata("Var.kt") - public void testVar() throws Exception { - String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/inline/Var.kt"); + @TestMetadata("varNoWrite.kt") + public void testVarNoWrite() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/inline/varNoWrite.kt"); + doTest(fileName); + } + + @TestMetadata("varWithAssignment.kt") + public void testVarWithAssignment() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/inline/varWithAssignment.kt"); + doTest(fileName); + } + + @TestMetadata("varWithInc.kt") + public void testVarWithInc() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/inline/varWithInc.kt"); doTest(fileName); }