Create From Usage: Place generated declarations next to original element container if they have common parent

#KT-6687 Fixed
This commit is contained in:
Alexey Sedunov
2015-03-06 18:08:36 +03:00
parent fe9b08f93d
commit ab5a691612
19 changed files with 136 additions and 53 deletions
@@ -529,12 +529,37 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
return Math.max(lineBreaksNeeded - lineBreaksPresent, 0) return Math.max(lineBreaksNeeded - lineBreaksPresent, 0)
} }
val declarationInPlace = when (containingElement) { fun addNextToOriginalElementContainer(addBefore: Boolean): JetNamedDeclaration {
is JetFile -> containingElement.add(declaration) as JetNamedDeclaration val actualContainer = (containingElement as? JetClassOrObject)?.getBody() ?: containingElement
val sibling = config.originalElement.parents().first { it.getParent() == actualContainer }
return if (addBefore) {
actualContainer.addBefore(declaration, sibling)
}
else {
actualContainer.addAfter(declaration, sibling)
} as JetNamedDeclaration
}
is PsiClass -> jetFileToEdit.add(declaration) as JetNamedDeclaration val declarationInPlace = when {
containingElement.isAncestor(config.originalElement, true) -> {
val insertToBlock = containingElement is JetBlockExpression
if (insertToBlock) {
val parent = containingElement.getParent()
if (parent is JetFunctionLiteral) {
if (!parent.isMultiLine()) {
parent.addBefore(newLine, containingElement)
parent.addAfter(newLine, containingElement)
}
}
}
addNextToOriginalElementContainer(insertToBlock || declaration is JetProperty)
}
is JetClassOrObject -> { containingElement is JetFile -> containingElement.add(declaration) as JetNamedDeclaration
containingElement is PsiClass -> jetFileToEdit.add(declaration) as JetNamedDeclaration
containingElement is JetClassOrObject -> {
var classBody = containingElement.getBody() var classBody = containingElement.getBody()
if (classBody == null) { if (classBody == null) {
classBody = containingElement.add(psiFactory.createEmptyClassBody()) as JetClassBody classBody = containingElement.add(psiFactory.createEmptyClassBody()) as JetClassBody
@@ -550,20 +575,6 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
} }
else classBody.addAfter(declaration, classBody!!.getLBrace()!!) as JetNamedDeclaration else classBody.addAfter(declaration, classBody!!.getLBrace()!!) as JetNamedDeclaration
} }
is JetBlockExpression -> {
val parent = containingElement.getParent()
if (parent is JetFunctionLiteral) {
if (!parent.isMultiLine()) {
parent.addBefore(newLine, containingElement)
parent.addAfter(newLine, containingElement)
}
}
val sibling = config.originalElement.parents().first { it.getParent() == containingElement }
containingElement.addBefore(declaration, sibling) as JetNamedDeclaration
}
else -> throw AssertionError("Invalid containing element: ${containingElement.getText()}") else -> throw AssertionError("Invalid containing element: ${containingElement.getText()}")
} }
@@ -1,9 +1,9 @@
// "Create class 'Foo'" "true" // "Create class 'Foo'" "true"
class A<T>(val n: T) { class A<T>(val n: T) {
fun test() = this.Foo(2, "2")
inner class Foo(i: Int, s: String) { inner class Foo(i: Int, s: String) {
} }
fun test() = this.Foo(2, "2")
} }
@@ -2,10 +2,10 @@
class A<T>(val n: T) { class A<T>(val n: T) {
inner class B<U>(val m: U) { inner class B<U>(val m: U) {
fun test() = this.Foo(2, "2")
inner class Foo(i: Int, s: String) { inner class Foo(i: Int, s: String) {
} }
fun test() = this.Foo(2, "2")
} }
} }
@@ -1,11 +1,11 @@
// "Create class 'Foo'" "true" // "Create class 'Foo'" "true"
class A<T>(val n: T) { class A<T>(val n: T) {
inner class Foo(i: Int, s: String) {
}
inner class B<U>(val m: U) { inner class B<U>(val m: U) {
fun test() = this@A.Foo(2, "2") fun test() = this@A.Foo(2, "2")
} }
inner class Foo(i: Int, s: String) {
}
} }
@@ -3,10 +3,10 @@ package p
fun foo(): X = A fun foo(): X = A
open class X {
}
object A : X() { object A : X() {
} }
open class X {
}
@@ -3,10 +3,10 @@ package p
fun foo(): X = A fun foo(): X = A
trait X {
}
object A : X { object A : X {
} }
trait X {
}
@@ -0,0 +1,18 @@
// "Create function 'foo'" "true"
class A {
val baz = 1
fun test() {
val a: A = foo()
}
private fun foo(): A {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
fun bar() {
}
}
@@ -0,0 +1,16 @@
// "Create function 'foo'" "true"
val baz = 1
fun test() {
val a: Int = foo()
}
fun foo(): Int {
throw UnsupportedOperationException("not implemented") //To change body of created functions use File | Settings | File Templates.
}
fun bar() {
}
@@ -0,0 +1,14 @@
// "Create function 'foo'" "true"
class A {
val baz = 1
fun test() {
val a: A = <caret>foo()
}
fun bar() {
}
}
@@ -0,0 +1,12 @@
// "Create function 'foo'" "true"
val baz = 1
fun test() {
val a: Int = <caret>foo()
}
fun bar() {
}
@@ -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
@@ -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
@@ -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,8 +1,8 @@
// "Create extension property 'foo'" "true" // "Create extension property 'foo'" "true"
// ERROR: Property must be initialized // ERROR: Property must be initialized
val Unit.foo: Int
fun test() { fun test() {
val a: Int = Unit.foo val a: Int = Unit.foo
} }
val Unit.foo: Int
@@ -3,8 +3,8 @@
class A<T>(val n: T) class A<T>(val n: T)
val Int.foo: A<Int>
fun test() { fun test() {
val a: A<Int> = 2.foo val a: A<Int> = 2.foo
} }
val Int.foo: A<Int>
@@ -3,8 +3,8 @@
class A<T>(val n: T) class A<T>(val n: T)
var Int.foo: A<String>
fun test() { fun test() {
2.foo = A("2") 2.foo = A("2")
} }
var Int.foo: A<String>
@@ -1,8 +1,8 @@
// "Create extension property 'foo'" "true" // "Create extension property 'foo'" "true"
// ERROR: Unresolved reference: foo // ERROR: Unresolved reference: foo
val A.foo: String?
fun test(): String? { fun test(): String? {
return A().foo return A().foo
} }
val A.foo: String?
@@ -1,8 +1,8 @@
// "Create extension property 'foo'" "true" // "Create extension property 'foo'" "true"
// ERROR: Unresolved reference: foo // ERROR: Unresolved reference: foo
val A.foo: String?
fun test(): String? { fun test(): String? {
return A().foo return A().foo
} }
val A.foo: String?
@@ -1680,6 +1680,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("beforeFunPlacement.kt")
public void testFunPlacement() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeFunPlacement.kt");
doTest(fileName);
}
@TestMetadata("beforeFunWithExplicitParamNamesOnUserType.kt") @TestMetadata("beforeFunWithExplicitParamNamesOnUserType.kt")
public void testFunWithExplicitParamNamesOnUserType() throws Exception { public void testFunWithExplicitParamNamesOnUserType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeFunWithExplicitParamNamesOnUserType.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeFunWithExplicitParamNamesOnUserType.kt");
@@ -1806,6 +1812,12 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("beforeTopLevelFunPlacement.kt")
public void testTopLevelFunPlacement() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeTopLevelFunPlacement.kt");
doTest(fileName);
}
@TestMetadata("beforeUnitFun.kt") @TestMetadata("beforeUnitFun.kt")
public void testUnitFun() throws Exception { public void testUnitFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeUnitFun.kt"); String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/createFromUsage/createFunction/call/beforeUnitFun.kt");