Create from Usage: Place extension properties after the usage and generate stub getter
#KT-11795 Fixed
This commit is contained in:
@@ -221,6 +221,7 @@ These artifacts include extensions for the types available in the latter JDKs, s
|
|||||||
- [`KT-13365`](https://youtrack.jetbrains.com/issue/KT-13365) Disable "Create property" (non-abstract) in interfaces. Make "Create function" (non-abstract) generate function body in interfaces
|
- [`KT-13365`](https://youtrack.jetbrains.com/issue/KT-13365) Disable "Create property" (non-abstract) in interfaces. Make "Create function" (non-abstract) generate function body in interfaces
|
||||||
- [`KT-8903`](https://youtrack.jetbrains.com/issue/KT-8903) Remove Unused Receiver: update function/property usages
|
- [`KT-8903`](https://youtrack.jetbrains.com/issue/KT-8903) Remove Unused Receiver: update function/property usages
|
||||||
- [`KT-11799`](https://youtrack.jetbrains.com/issue/KT-11799) Create from Usage: Make extension functions/properties 'private' by default
|
- [`KT-11799`](https://youtrack.jetbrains.com/issue/KT-11799) Create from Usage: Make extension functions/properties 'private' by default
|
||||||
|
- [`KT-11795`](https://youtrack.jetbrains.com/issue/KT-11795) Create from Usage: Place extension properties after the usage and generate stub getter
|
||||||
|
|
||||||
##### New features
|
##### New features
|
||||||
|
|
||||||
|
|||||||
+21
-7
@@ -498,8 +498,18 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
CallableKind.PROPERTY -> {
|
CallableKind.PROPERTY -> {
|
||||||
val valVar = if ((callableInfo as PropertyInfo).writable) "var" else "val"
|
val isVar = (callableInfo as PropertyInfo).writable
|
||||||
psiFactory.createProperty("$modifiers$valVar<> $header")
|
val valVar = if (isVar) "var" else "val"
|
||||||
|
val accessors = if (isExtension) {
|
||||||
|
buildString {
|
||||||
|
append("\nget() {}")
|
||||||
|
if (isVar) {
|
||||||
|
append("\nset() {}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else ""
|
||||||
|
psiFactory.createProperty("$modifiers$valVar<> $header$accessors")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -559,7 +569,7 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
addNextToOriginalElementContainer(insertToBlock || declaration is KtProperty)
|
addNextToOriginalElementContainer(insertToBlock || (declaration is KtProperty && actualContainer !is KtFile))
|
||||||
}
|
}
|
||||||
|
|
||||||
containingElement is KtFile -> containingElement.add(declaration) as KtNamedDeclaration
|
containingElement is KtFile -> containingElement.add(declaration) as KtNamedDeclaration
|
||||||
@@ -683,18 +693,18 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
return typeRefsToShorten
|
return typeRefsToShorten
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupFunctionBody(func: KtFunction) {
|
private fun setupDeclarationBody(func: KtDeclarationWithBody) {
|
||||||
val oldBody = func.bodyExpression ?: return
|
val oldBody = func.bodyExpression ?: return
|
||||||
val templateKind = when (func) {
|
val templateKind = when (func) {
|
||||||
is KtSecondaryConstructor -> TemplateKind.SECONDARY_CONSTRUCTOR
|
is KtSecondaryConstructor -> TemplateKind.SECONDARY_CONSTRUCTOR
|
||||||
is KtNamedFunction -> TemplateKind.FUNCTION
|
is KtNamedFunction, is KtPropertyAccessor -> TemplateKind.FUNCTION
|
||||||
else -> throw AssertionError("Unexpected declaration: " + func.getElementTextWithContext())
|
else -> throw AssertionError("Unexpected declaration: " + func.getElementTextWithContext())
|
||||||
}
|
}
|
||||||
val bodyText = getFunctionBodyTextFromTemplate(
|
val bodyText = getFunctionBodyTextFromTemplate(
|
||||||
func.project,
|
func.project,
|
||||||
templateKind,
|
templateKind,
|
||||||
if (callableInfo.name.isNotEmpty()) callableInfo.name else null,
|
if (callableInfo.name.isNotEmpty()) callableInfo.name else null,
|
||||||
if (skipReturnType) "Unit" else func.typeReference!!.text,
|
if (skipReturnType) "Unit" else (func as? KtFunction)?.typeReference?.text ?: "",
|
||||||
receiverClassDescriptor?.importableFqName ?: receiverClassDescriptor?.name?.let { FqName.topLevel(it) }
|
receiverClassDescriptor?.importableFqName ?: receiverClassDescriptor?.name?.let { FqName.topLevel(it) }
|
||||||
)
|
)
|
||||||
oldBody.replace(KtPsiFactory(func).createBlock(bodyText))
|
oldBody.replace(KtPsiFactory(func).createBlock(bodyText))
|
||||||
@@ -988,7 +998,11 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
|
|||||||
runWriteAction {
|
runWriteAction {
|
||||||
// file templates
|
// file templates
|
||||||
if (newDeclaration is KtNamedFunction || newDeclaration is KtSecondaryConstructor) {
|
if (newDeclaration is KtNamedFunction || newDeclaration is KtSecondaryConstructor) {
|
||||||
setupFunctionBody(newDeclaration as KtFunction)
|
setupDeclarationBody(newDeclaration as KtFunction)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newDeclaration is KtProperty) {
|
||||||
|
newDeclaration.getter?.let { setupDeclarationBody(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val callElement = config.originalElement as? KtCallElement
|
val callElement = config.originalElement as? KtCallElement
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// "Create extension property 'A.foo'" "true"
|
// "Create extension property 'A.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
class A(val n: Int)
|
class A(val n: Int)
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
|
|||||||
+5
-3
@@ -1,9 +1,11 @@
|
|||||||
// "Create extension property 'A.foo'" "true"
|
// "Create extension property 'A.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
class A(val n: Int)
|
class A(val n: Int)
|
||||||
|
|
||||||
private val A.foo: Boolean
|
|
||||||
|
|
||||||
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
@@ -1,5 +1,4 @@
|
|||||||
// "Create extension property 'A.foo'" "true"
|
// "Create extension property 'A.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
class A(val n: Int)
|
class A(val n: Int)
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
|
|||||||
+7
-3
@@ -1,9 +1,6 @@
|
|||||||
// "Create extension property 'A.foo'" "true"
|
// "Create extension property 'A.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
class A(val n: Int)
|
class A(val n: Int)
|
||||||
|
|
||||||
private var A.foo: Boolean
|
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
var A.test: Boolean
|
var A.test: Boolean
|
||||||
get() = foo
|
get() = foo
|
||||||
@@ -11,3 +8,10 @@ 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() {
|
||||||
|
}
|
||||||
|
|||||||
+5
-2
@@ -3,11 +3,14 @@
|
|||||||
|
|
||||||
import package1.A
|
import package1.A
|
||||||
|
|
||||||
private val package2.A.foo: Any<caret>
|
|
||||||
|
|
||||||
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.
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+5
-2
@@ -1,8 +1,11 @@
|
|||||||
// "Create extension property 'A.foo'" "true"
|
// "Create extension property 'A.foo'" "true"
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
private val A.foo: String?<caret>
|
|
||||||
|
|
||||||
fun test(): String? {
|
fun test(): String? {
|
||||||
return A().foo
|
return A().foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val A.foo: String?
|
||||||
|
get() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+5
-2
@@ -1,8 +1,11 @@
|
|||||||
// "Create extension property 'A.foo'" "true"
|
// "Create extension property 'A.foo'" "true"
|
||||||
// ERROR: Unresolved reference: foo
|
// ERROR: Unresolved reference: foo
|
||||||
|
|
||||||
private val A.foo: String?<caret>
|
|
||||||
|
|
||||||
fun test(): String? {
|
fun test(): String? {
|
||||||
return A().foo
|
return A().foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val A.foo: String?
|
||||||
|
get() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// "Create extension property 'T.bar'" "true"
|
// "Create extension property 'T.bar'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
fun consume(n: Int) {}
|
fun consume(n: Int) {}
|
||||||
|
|
||||||
fun <T> foo(t: T) {
|
fun <T> foo(t: T) {
|
||||||
|
|||||||
+5
-3
@@ -1,9 +1,11 @@
|
|||||||
// "Create extension property 'T.bar'" "true"
|
// "Create extension property 'T.bar'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
fun consume(n: Int) {}
|
fun consume(n: Int) {}
|
||||||
|
|
||||||
private val <T> T.bar: 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.
|
||||||
|
}
|
||||||
|
|||||||
Vendored
+2
-2
@@ -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>
|
||||||
|
|||||||
+2
-2
@@ -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
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// ERROR: Property must be initialized
|
// ERROR: Property must be initialized
|
||||||
class Cyclic<E : Cyclic<E>>
|
class Cyclic<E : Cyclic<E>>
|
||||||
|
|
||||||
val foo: Cyclic<*>
|
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val c : Cyclic<*> = foo
|
val c : Cyclic<*> = foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val foo: Cyclic<*>
|
||||||
|
|||||||
Vendored
+2
-2
@@ -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
|
||||||
|
|||||||
Vendored
+2
-2
@@ -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
|
||||||
|
|||||||
Vendored
+2
-2
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
package foo
|
package foo
|
||||||
|
|
||||||
val foo: Int
|
|
||||||
|
|
||||||
fun test(): Int {
|
fun test(): Int {
|
||||||
return foo
|
return foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val foo: Int
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// "Create extension property 'Unit.foo'" "true"
|
// "Create extension property 'Unit.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
+5
-3
@@ -1,9 +1,11 @@
|
|||||||
// "Create extension property 'Unit.foo'" "true"
|
// "Create extension property 'Unit.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
private val Unit.foo: Int
|
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
val a: Int = Unit.foo
|
val a: Int = Unit.foo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val Unit.foo: Int
|
||||||
|
get() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|||||||
-1
@@ -1,5 +1,4 @@
|
|||||||
// "Create extension property 'Int.foo'" "true"
|
// "Create extension property 'Int.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
class A<T>(val n: T)
|
class A<T>(val n: T)
|
||||||
|
|||||||
+5
-3
@@ -1,11 +1,13 @@
|
|||||||
// "Create extension property 'Int.foo'" "true"
|
// "Create extension property 'Int.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
class A<T>(val n: T)
|
class A<T>(val n: T)
|
||||||
|
|
||||||
private val Int.foo: A<Int>
|
|
||||||
|
|
||||||
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
@@ -1,5 +1,4 @@
|
|||||||
// "Create extension property 'Int.foo'" "true"
|
// "Create extension property 'Int.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
class A<T>(val n: T)
|
class A<T>(val n: T)
|
||||||
|
|||||||
+7
-3
@@ -1,11 +1,15 @@
|
|||||||
// "Create extension property 'Int.foo'" "true"
|
// "Create extension property 'Int.foo'" "true"
|
||||||
// ERROR: Property must be initialized
|
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
|
|
||||||
class A<T>(val n: T)
|
class A<T>(val n: T)
|
||||||
|
|
||||||
private var Int.foo: A<String>
|
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
2.foo = A("2")
|
2.foo = A("2")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var Int.foo: A<String>
|
||||||
|
get() {
|
||||||
|
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
set() {
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user