Inline properties without setter / with default setter correctly

Related to KT-21237
This commit is contained in:
Mikhail Glukhikh
2017-11-23 19:01:49 +03:00
parent fba50a8d15
commit bddaab9d48
12 changed files with 212 additions and 7 deletions
@@ -20,10 +20,7 @@ import com.intellij.openapi.util.Key
import com.intellij.psi.PsiElement
import com.intellij.refactoring.rename.RenameProcessor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.resolveImportReference
@@ -69,16 +66,16 @@ class CodeInliner<TCallElement : KtElement>(
val assignment = (qualifiedElement as? KtExpression)
?.getAssignmentByLHS()
?.takeIf { it.operationToken == KtTokens.EQ }
val elementToBeReplaced = assignment ?: qualifiedElement
val callableForParameters = if (assignment != null && descriptor is PropertyDescriptor)
descriptor.setter ?: descriptor
descriptor.setter?.takeIf { it.hasBody() } ?: descriptor
else
descriptor
val elementToBeReplaced = assignment.takeIf { callableForParameters is PropertySetterDescriptor } ?: qualifiedElement
val commentSaver = CommentSaver(elementToBeReplaced, saveLineBreaks = true)
// if the value to be inlined is not used and has no side effects we may drop it
if (codeToInline.mainExpression != null
&& assignment == null
&& elementToBeReplaced is KtExpression
&& !elementToBeReplaced.isUsedAsExpression(bindingContext)
&& !codeToInline.mainExpression.shouldKeepValue(usageCount = 0)
@@ -0,0 +1,19 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old
get() = new
set(value) {
new = value
}
var new = ""
}
fun foo() {
val a = A()
// Works incorrectly yet
a.<caret>old = "foo"
}
@@ -0,0 +1,19 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old
get() = new
set(value) {
new = value
}
var new = ""
}
fun foo() {
val a = A()
// Works incorrectly yet
a.new
}
@@ -0,0 +1,16 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old = ""
get() = new
public set
var new = ""
}
fun foo() {
val a = A()
a.<caret>old = "foo"
}
@@ -0,0 +1,16 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old = ""
get() = new
public set
var new = ""
}
fun foo() {
val a = A()
a.new = "foo"
}
@@ -0,0 +1,21 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old
get() = new
set(value) {
new = value
}
var new = ""
}
fun foo() {
val a = A()
a.apply {
// Works incorrectly yet
<caret>old = "foo"
}
}
@@ -0,0 +1,21 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old
get() = new
set(value) {
new = value
}
var new = ""
}
fun foo() {
val a = A()
a.apply {
// Works incorrectly yet
new
}
}
@@ -0,0 +1,15 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old = ""
get() = new
var new = ""
}
fun foo() {
val a = A()
a.<caret>old = "foo"
}
@@ -0,0 +1,15 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old = ""
get() = new
var new = ""
}
fun foo() {
val a = A()
a.new = "foo"
}
@@ -0,0 +1,18 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old
get() = new
set(value) {
new = value
}
var new = ""
}
fun foo() {
val a = A()
a.<caret>old += "foo"
}
@@ -0,0 +1,18 @@
// "Replace with 'new'" "true"
// WITH_RUNTIME
class A {
@Deprecated("msg", ReplaceWith("new"))
var old
get() = new
set(value) {
new = value
}
var new = ""
}
fun foo() {
val a = A()
a.new += "foo"
}
@@ -5222,6 +5222,36 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName);
}
@TestMetadata("propertyAssignment.kt")
public void testPropertyAssignment() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/propertyAssignment.kt");
doTest(fileName);
}
@TestMetadata("propertyAssignmentDefaultSetter.kt")
public void testPropertyAssignmentDefaultSetter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/propertyAssignmentDefaultSetter.kt");
doTest(fileName);
}
@TestMetadata("propertyAssignmentNoReceiver.kt")
public void testPropertyAssignmentNoReceiver() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/propertyAssignmentNoReceiver.kt");
doTest(fileName);
}
@TestMetadata("propertyAssignmentNoSetter.kt")
public void testPropertyAssignmentNoSetter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/propertyAssignmentNoSetter.kt");
doTest(fileName);
}
@TestMetadata("propertyModification.kt")
public void testPropertyModification() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/propertyModification.kt");
doTest(fileName);
}
@TestMetadata("propertyToMethod.kt")
public void testPropertyToMethod() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/quickfix/deprecatedSymbolUsage/propertyToMethod.kt");