Improve Create property from Usage

Place generated property next to other properties
 #KT-14886 Fixed
This commit is contained in:
Dmitry Gridin
2019-02-26 18:45:12 +03:00
parent 5d599ee2ff
commit c89d1af9fa
35 changed files with 228 additions and 85 deletions
@@ -1096,6 +1096,15 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
(container as KtClass).createPrimaryConstructorIfAbsent().replaced(declaration) as D (container as KtClass).createPrimaryConstructorIfAbsent().replaced(declaration) as D
} }
declaration is KtProperty && container !is KtBlockExpression -> {
val sibling = actualContainer.getChildOfType<KtProperty>() ?: when (actualContainer) {
is KtClassBody -> actualContainer.declarations.firstOrNull() ?: actualContainer.rBrace
is KtFile -> actualContainer.declarations.first()
else -> null
}
sibling?.let { actualContainer.addBefore(declaration, it) as D } ?: fileToEdit.add(declaration) as D
}
actualContainer.isAncestor(anchor, true) -> { actualContainer.isAncestor(anchor, true) -> {
val insertToBlock = container is KtBlockExpression val insertToBlock = container is KtBlockExpression
if (insertToBlock) { if (insertToBlock) {
@@ -1107,11 +1116,7 @@ internal fun <D : KtNamedDeclaration> placeDeclarationInContainer(
} }
} }
} }
addNextToOriginalElementContainer( addNextToOriginalElementContainer(insertToBlock || declaration is KtTypeAlias)
insertToBlock
|| (declaration is KtProperty && actualContainer !is KtFile)
|| declaration is KtTypeAlias
)
} }
container is KtFile -> container.add(declaration) as D container is KtFile -> container.add(declaration) as D
@@ -1,11 +1,11 @@
private val A.foo: Boolean
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
// "Create extension property 'A.foo'" "true" // "Create extension property 'A.foo'" "true"
class A(val n: Int) class A(val n: Int)
class B { class B {
val A.test: Boolean get() = foo val A.test: Boolean get() = foo
} }
private val A.foo: Boolean
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,3 +1,9 @@
private var A.foo: Boolean
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
set() {}
// "Create extension property 'A.foo'" "true" // "Create extension property 'A.foo'" "true"
class A(val n: Int) class A(val n: Int)
@@ -8,9 +14,3 @@ class B {
foo = v foo = v
} }
} }
private var A.foo: Boolean
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
set() {}
@@ -1,9 +1,9 @@
// "Create abstract property 'foo'" "true" // "Create abstract property 'foo'" "true"
abstract class A { abstract class A {
fun bar(b: Boolean) {}
abstract val foo: Boolean<caret> abstract val foo: Boolean<caret>
fun bar(b: Boolean) {}
fun test() { fun test() {
bar(foo) bar(foo)
} }
@@ -1,9 +1,9 @@
// "Create abstract property 'A.foo'" "true" // "Create abstract property 'A.foo'" "true"
abstract class A { abstract class A {
fun bar(b: Boolean) {}
abstract val foo: Boolean<caret> abstract val foo: Boolean<caret>
fun bar(b: Boolean) {}
fun test(a: A) { fun test(a: A) {
bar(a.foo) bar(a.foo)
} }
@@ -1,9 +1,9 @@
// "Create abstract property 'foo'" "true" // "Create abstract property 'foo'" "true"
interface A { interface A {
fun bar(b: Boolean) {}
val foo: Boolean<caret> val foo: Boolean<caret>
fun bar(b: Boolean) {}
fun test() { fun test() {
bar(foo) bar(foo)
} }
@@ -3,14 +3,14 @@
import package1.A import package1.A
private val package2.A.foo: Any
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
class X { class X {
init { init {
val y = package2.A() val y = package2.A()
val foo = y.foo val foo = y.foo
} }
} }
private val package2.A.foo: Any
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,11 +1,11 @@
// "Create extension property 'A.foo'" "true" // "Create extension property 'A.foo'" "true"
// ERROR: Unresolved reference: foo // ERROR: Unresolved reference: foo
fun test(): String? {
return A().foo
}
private val A.foo: String? private val A.foo: String?
get() { get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
fun test(): String? {
return A().foo
}
@@ -1,11 +1,11 @@
// "Create extension property 'A.foo'" "true" // "Create extension property 'A.foo'" "true"
// ERROR: Unresolved reference: foo // ERROR: Unresolved reference: foo
fun test(): String? {
return A().foo
}
private val A.foo: String? private val A.foo: String?
get() { get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
fun test(): String? {
return A().foo
}
@@ -1,11 +1,11 @@
private val <T> T.bar: Int
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
// "Create extension property 'T.bar'" "true" // "Create extension property 'T.bar'" "true"
fun consume(n: Int) {} fun consume(n: Int) {}
fun <T> foo(t: T) { fun <T> foo(t: T) {
consume(t.bar) consume(t.bar)
} }
private val <T> T.bar: Int
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,4 +1,4 @@
class K { class K {
lateinit var foo: String
lateinit var foo: String
} }
@@ -1,5 +1,5 @@
class K { class K {
@JvmField @JvmField
var foo: String = TODO("initialize me") var foo: String = TODO("initialize me")
} }
@@ -1,6 +1,6 @@
@file:JvmName("TestKt") @file:JvmName("TestKt")
fun test() {}
@JvmField @JvmField
var foo: String = TODO("initialize me") var foo: String = TODO("initialize me")
fun test() {}
@@ -3,8 +3,8 @@ import kotlin.properties.ReadOnlyProperty
// "Create property 'foo'" "true" // "Create property 'foo'" "true"
// ERROR: Property must be initialized // ERROR: Property must be initialized
val foo: ReadOnlyProperty<Nothing?, Int>
fun test() { fun test() {
val x: Int by foo val x: Int by foo
} }
val foo: ReadOnlyProperty<Nothing?, Int>
@@ -1,11 +1,11 @@
private val String?.notExistingVal: Int
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
// "Create extension property 'String?.notExistingVal'" "true" // "Create extension property 'String?.notExistingVal'" "true"
fun foo(n: Int) {} fun foo(n: Int) {}
fun context(p: String?) { fun context(p: String?) {
foo(p.notExistingVal) foo(p.notExistingVal)
} }
private val String?.notExistingVal: Int
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,7 +1,7 @@
val `!u00A0`: Int
// "Create property '!u00A0'" "true" // "Create property '!u00A0'" "true"
// ERROR: Property must be initialized // ERROR: Property must be initialized
fun test() { fun test() {
val t: Int = `!u00A0` val t: Int = `!u00A0`
} }
val `!u00A0`: Int
@@ -1,3 +1,5 @@
val foo: Cyclic<*>
// "Create property 'foo'" "true" // "Create property 'foo'" "true"
// ERROR: Property must be initialized // ERROR: Property must be initialized
class Cyclic<E : Cyclic<E>> class Cyclic<E : Cyclic<E>>
@@ -5,5 +7,3 @@ class Cyclic<E : Cyclic<E>>
fun test() { fun test() {
val c : Cyclic<*> = foo val c : Cyclic<*> = foo
} }
val foo: Cyclic<*>
@@ -1,8 +1,8 @@
// "Create property 'foo'" "true" // "Create property 'foo'" "true"
// ERROR: Property must be initialized // ERROR: Property must be initialized
val foo: String
fun test() { fun test() {
println("a = $foo") println("a = $foo")
} }
val foo: String
@@ -0,0 +1,12 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class Test {
fun test(): Int {
return <caret>foo
}
val foo1 = 1
}
val bar = 1
@@ -0,0 +1,13 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class Test {
fun test(): Int {
return foo
}
private val foo: Int
val foo1 = 1
}
val bar = 1
@@ -0,0 +1,14 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class Test {
val foo1 = 1
fun test(): Int {
return <caret>foo
}
val foo2 = 42
}
val bar = 1
@@ -0,0 +1,15 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class Test {
private val foo: Int
val foo1 = 1
fun test(): Int {
return foo
}
val foo2 = 42
}
val bar = 1
@@ -0,0 +1,12 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class Test {
val foo1 = 1
fun test(): Int {
return <caret>foo
}
}
val bar = 1
@@ -0,0 +1,13 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized or be abstract
class Test {
private val foo: Int
val foo1 = 1
fun test(): Int {
return foo
}
}
val bar = 1
@@ -1,8 +1,8 @@
// "Create property 'foo'" "true" // "Create property 'foo'" "true"
// ERROR: Property must be initialized // ERROR: Property must be initialized
val foo: Int
fun test(): Int { fun test(): Int {
return foo return foo
} }
val foo: Int
@@ -0,0 +1,8 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized
fun test(): Int {
return <caret>foo
}
val bar = 1
@@ -0,0 +1,9 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized
fun test(): Int {
return foo
}
val foo: Int
val bar = 1
@@ -0,0 +1,8 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized
val bar = 1
fun test(): Int {
return <caret>foo
}
@@ -0,0 +1,9 @@
// "Create property 'foo'" "true"
// ERROR: Property must be initialized
val foo: Int
val bar = 1
fun test(): Int {
return foo
}
@@ -3,8 +3,8 @@
package foo package foo
val foo: Int
fun test(): Int { fun test(): Int {
return foo return foo
} }
val foo: Int
@@ -3,8 +3,8 @@
class A<T>(val n: T) { class A<T>(val n: T) {
companion object { companion object {
val foo: Int
val foo: Int
} }
} }
@@ -1,11 +1,11 @@
// "Create extension property 'Unit.foo'" "true" // "Create extension property 'Unit.foo'" "true"
// WITH_RUNTIME // WITH_RUNTIME
fun test() {
val a: Int = Unit.foo
}
private val Unit.foo: Int private val Unit.foo: Int
get() { get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
fun test() {
val a: Int = Unit.foo
}
@@ -1,13 +1,13 @@
// "Create extension property 'Int.foo'" "true" // "Create extension property 'Int.foo'" "true"
// WITH_RUNTIME // WITH_RUNTIME
private val Int.foo: A<Int>
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
class A<T>(val n: T) class A<T>(val n: T)
fun test() { fun test() {
val a: A<Int> = 2.foo val a: A<Int> = 2.foo
} }
private val Int.foo: A<Int>
get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
@@ -1,14 +1,14 @@
// "Create extension property 'Int.foo'" "true" // "Create extension property 'Int.foo'" "true"
// WITH_RUNTIME // WITH_RUNTIME
class A<T>(val n: T)
fun test() {
2.foo = A("2")
}
private var Int.foo: A<String> private var Int.foo: A<String>
get() { get() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
} }
set() {} set() {}
class A<T>(val n: T)
fun test() {
2.foo = A("2")
}
@@ -5137,6 +5137,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInClass.kt"); runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInClass.kt");
} }
@TestMetadata("thisInClassAlreadyExistsAfter.kt")
public void testThisInClassAlreadyExistsAfter() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInClassAlreadyExistsAfter.kt");
}
@TestMetadata("thisInClassAlreadyExistsAfterAndBefore.kt")
public void testThisInClassAlreadyExistsAfterAndBefore() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInClassAlreadyExistsAfterAndBefore.kt");
}
@TestMetadata("thisInClassAlreadyExistsBefore.kt")
public void testThisInClassAlreadyExistsBefore() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInClassAlreadyExistsBefore.kt");
}
@TestMetadata("thisInExtension.kt") @TestMetadata("thisInExtension.kt")
public void testThisInExtension() throws Exception { public void testThisInExtension() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInExtension.kt"); runTest("idea/testData/quickfix/createFromUsage/createVariable/property/thisInExtension.kt");
@@ -5157,6 +5172,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/topLevelValNoReceiver.kt"); runTest("idea/testData/quickfix/createFromUsage/createVariable/property/topLevelValNoReceiver.kt");
} }
@TestMetadata("topLevelValNoReceiverAlreadyExistsAfter.kt")
public void testTopLevelValNoReceiverAlreadyExistsAfter() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/topLevelValNoReceiverAlreadyExistsAfter.kt");
}
@TestMetadata("topLevelValNoReceiverAlreadyExistsBefore.kt")
public void testTopLevelValNoReceiverAlreadyExistsBefore() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/topLevelValNoReceiverAlreadyExistsBefore.kt");
}
@TestMetadata("topLevelValWithPackageName.kt") @TestMetadata("topLevelValWithPackageName.kt")
public void testTopLevelValWithPackageName() throws Exception { public void testTopLevelValWithPackageName() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createVariable/property/topLevelValWithPackageName.kt"); runTest("idea/testData/quickfix/createFromUsage/createVariable/property/topLevelValWithPackageName.kt");