Some fixes for anonymous local classes and it's imports
diff --git a/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/DecompileIrTree.kt b/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/DecompileIrTree.kt
index 325c7a1..15f3395 100644
--- a/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/DecompileIrTree.kt
+++ b/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/DecompileIrTree.kt
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.decompiler
+import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.decompiler.util.*
import org.jetbrains.kotlin.decompiler.util.name
import org.jetbrains.kotlin.descriptors.ClassKind
@@ -38,6 +39,33 @@
companion object {
val irFileNamesToImportedDeclarationsMap = mutableMapOf<String, Set<String>>()
+ //TODO резолвить конфликты имен типов возвращаемых значений.
+ // Конфликт - если более 2 записей, заканчивающихся на этот тип
+ internal fun IrType.obtainTypeDescription(): String {
+ if ((this as? IrSimpleType)?.abbreviation != null) {
+ with(abbreviation!!.typeAlias.owner) {
+ return name() + this@obtainTypeDescription.arguments.joinToString(", ", "<", ">") { it.obtain() }
+ }
+ }
+ return if (toKotlinType().isFunctionTypeOrSubtype) {
+ val arguments = toKotlinType().arguments
+ val returnType = arguments.last().type
+ val inputTypes = arguments.dropLast(1)
+ "${inputTypes.joinToString(", ", prefix = "(", postfix = ")") {
+ it.type.toString() + ("?".takeIf { isNullable() } ?: EMPTY_TOKEN)
+ }} -> $returnType"
+ } else {
+ if (getClass()?.isLocalClass() ?: false) {
+ //Если локальный класс, то оставляем только его имя
+ getClass()!!.name()
+// toKotlinType().toString().substring(startIndex = toKotlinType().toString().indexOfLast { it == '.' })
+ } else {
+ //Пока так, но нужно резолвить через importStr и сравнение постфиксов
+ toKotlinType().toString()
+ }
+ }
+ }
+
}
override fun visitGetObjectValue(expression: IrGetObjectValue, data: String) {
@@ -78,29 +106,20 @@
ClassKind.CLASS, ClassKind.OBJECT -> {
declaration.obtainPrimaryCtorWithInheritance()
withBracesLn {
- declaration.declarations
- .filterIsInstance<IrProperty>()
- .filterNot {
- it.origin in setOf(
- IrDeclarationOrigin.FAKE_OVERRIDE,
- IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER
- )
- }
- .decompileElements(data)
-
val secondaryCtors = declaration.constructors.filterNot { it.isPrimary }
secondaryCtors.forEach {
it.obtainSecondaryCtor()
}
+
declaration.declarations
- .filterNot { it is IrConstructor || it is IrProperty || it is IrField }
+ .filterNot { it is IrConstructor || it is IrField }
.filterNot {
it.origin in setOf(
IrDeclarationOrigin.FAKE_OVERRIDE,
IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER
)
}
- .decompileElements(data)
+ .forEach { it.accept(this, data) }
}
}
ClassKind.ANNOTATION_CLASS -> {
@@ -150,6 +169,8 @@
}
with(primaryConstructor!!) {
val delegatingCtorCall = body!!.statements.filterIsInstance<IrDelegatingConstructorCall>().firstOrNull()
+ //TODO чтобы не дублировался вызов ктора и перечисления через запятую (делегирование)
+ superTypes.remove(delegatingCtorCall?.symbol?.owner?.constructedClassType)
val implStr = parentAsClass.obtainInheritanceWithDelegation()
val delegatingCtorCallStr = delegatingCtorCall?.decompile("") ?: ""
if (delegatingCtorCallStr.isEmpty()) {
@@ -169,11 +190,14 @@
delegatedMap[delegationFieldInitializer.type] = delegationFieldInitializer
}
// Для енамов в суперах лежит Enum<MyType>, который почему-то не isEnum(
- return superTypes.filterNot { it.isAny() || it.toKotlinType().toString().startsWith("Enum") }.joinToString(", ") {
- val result = it.obtainTypeDescription()
- val key = delegatedMap.keys.filter { it.isSubtypeOfClass(it.getClass()!!.symbol) }.firstOrNull()
- result + if (key != null) " by ${delegatedMap[key]?.decompile("")}" else EMPTY_TOKEN
- }
+ return superTypes
+ .filterNot { it.isAny() || it.toKotlinType().toString().startsWith("Enum") }
+ .filterNot { primaryConstructor?.constructedClass?.symbol?.let { it1 -> it.isSubtypeOfClass(it1) } ?: false }
+ .joinToString(", ") {
+ val result = it.obtainTypeDescription()
+ val key = delegatedMap.keys.filter { it.isSubtypeOfClass(it.getClass()!!.symbol) }.firstOrNull()
+ result + if (key != null) " by ${delegatedMap[key]?.decompile("")}" else EMPTY_TOKEN
+ }
}
@@ -349,14 +373,12 @@
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: String) {
- var result = ""
if (!expression.symbol.owner.returnType.isAny()) {
- result = concatenateNonEmptyWithSpace(":", expression.symbol.owner.returnType.obtainTypeDescription(),
- ((0 until expression.valueArgumentsCount)
- .mapNotNull { expression.getValueArgument(it)?.decompile(data) }
- .joinToString(", ", "(", ")")))
+ printer.println(listOf(" : ", expression.symbol.owner.returnType.obtainTypeDescription(),
+ ((0 until expression.valueArgumentsCount)
+ .mapNotNull { expression.getValueArgument(it)?.decompile(data) }
+ .joinToString(", ", "(", ")"))).joinToString(""))
}
- printer.println(result)
}
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: String) {
@@ -620,26 +642,26 @@
override fun visitModuleFragment(declaration: IrModuleFragment, data: String) {
declaration.files.forEach {
- printer.println("// FILE: ${it.path}")
+ printer.printlnWithNoIndent("// FILE: ${it.path}")
// Чтобы соблюсти очередность package -> imports -> declarations вынуждено вытащил это из visitFile
if (it.fqName != FqName.ROOT) {
printer.println("package ${it.fqName.asString()}\n")
}
val fileSources = it.decompile("")
- printer.println(irFileNamesToImportedDeclarationsMap[it.path]?.joinToString("\n") { "import $it" })
+ printer.println(irFileNamesToImportedDeclarationsMap[it.path]?.joinToString(separator = "\n", postfix = "\n") { "import $it" })
printer.println(fileSources)
+ printer.println()
}
}
override fun visitFile(declaration: IrFile, data: String) {
with(declaration) {
val importResolveVisitor = ImportResolveVisitor()
- accept(importResolveVisitor, fqName.asString().takeIf { declaration.fqName != FqName.ROOT } ?: EMPTY_TOKEN)
+ val filePackage = fqName.asString().takeIf { declaration.fqName != FqName.ROOT } ?: EMPTY_TOKEN
+ accept(importResolveVisitor, filePackage)
irFileNamesToImportedDeclarationsMap[path] = importResolveVisitor.importDirectivesSet
- declaration.declarations.forEach {
- printer.printlnWithNoIndent("${it.decompile(data)}\n")
- }
+ printer.println(declaration.declarations.joinToString(separator = "\n", postfix = "\n") { it.decompile(filePackage) })
}
}
diff --git a/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/ImportResolveVisitor.kt b/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/ImportResolveVisitor.kt
index 95af2876..28a7421 100644
--- a/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/ImportResolveVisitor.kt
+++ b/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/ImportResolveVisitor.kt
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.decompiler.util
+import org.jetbrains.kotlin.decompiler.decompile
import org.jetbrains.kotlin.decompiler.util.name
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
@@ -60,7 +61,7 @@
*/
override fun visitClass(declaration: IrClass, data: String) {
with(declaration) {
- val declarationNameWithPrefix = "${("$data.").takeIf { data.isNotEmpty() } ?: EMPTY_TOKEN}${this.name.identifier}"
+ val declarationNameWithPrefix = "${("$data.").takeIf { data.isNotEmpty() } ?: EMPTY_TOKEN}${this.name()}"
declaredNamesSet.add(declarationNameWithPrefix)
// Для енамов в суперах лежит Enum<MyType>, который почему-то не isEnum
// Добавляем
@@ -89,7 +90,6 @@
override fun visitConstructor(declaration: IrConstructor, data: String) {
with(declaration) {
- calledNamesSet.add(parentAsClass.asImportStr())
typeParameters.forEach { it.accept(this@ImportResolveVisitor, data) }
valueParameters.forEach { it.accept(this@ImportResolveVisitor, data) }
body?.accept(this@ImportResolveVisitor, data)
@@ -97,14 +97,29 @@
run { }
}
- override fun visitConstructorCall(expression: IrConstructorCall, data: String) {
+ override fun visitFunctionAccess(expression: IrFunctionAccessExpression, data: String) {
+ //TODO Здесь может быть больше всего проблем (extension и dispatcher receivers, superQualifier)
with(expression) {
- calledNamesSet.add(symbol.owner.parentAsClass.asImportStr())
+ when (origin) {
+ null -> {
+ dispatchReceiver?.accept(this@ImportResolveVisitor, data)
+ calledNamesSet.add(if (symbol.owner.parent is IrFile) symbol.owner.fqNameWhenAvailable?.asString() else symbol.owner.parentAsClass.asImportStr())
+ }
+ IrStatementOrigin.GET_PROPERTY -> {
+ val fullName = symbol.owner.fqNameWhenAvailable?.asString() ?: EMPTY_TOKEN
+ val ownerDataPrefix = fullName.substring(0, fullName.indexOfLast { it == '.' })
+ val regex = """<get-(.+)>""".toRegex()
+ val matchResult = regex.find(fullName)
+ val propName = matchResult?.groups?.get(1)?.value
+ calledNamesSet.add("$ownerDataPrefix.$propName")
+ }
+ }
(0 until typeArgumentsCount).forEach { calledNamesSet.add(getTypeArgument(it)?.asImportStr()) }
(0 until valueArgumentsCount).forEach { getValueArgument(it)?.accept(this@ImportResolveVisitor, data) }
}
}
+
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: String) {
calledNamesSet.add(expression.symbol.owner.parentAsClass.asImportStr())
}
@@ -142,6 +157,7 @@
override fun visitFunction(declaration: IrFunction, data: String) {
with(declaration) {
+ declaredNamesSet.add(if (parent is IrFile) fqNameWhenAvailable?.asString() else parentAsClass.asImportStr())
typeParameters.forEach { it.accept(this@ImportResolveVisitor, data) }
valueParameters.forEach { it.accept(this@ImportResolveVisitor, data) }
body?.accept(this@ImportResolveVisitor, data)
@@ -163,16 +179,6 @@
}
}
- override fun visitCall(expression: IrCall, data: String) {
- //TODO Здесь может быть больше всего проблем (extension и dispatcher receivers, superQualifier)
- with(expression) {
- dispatchReceiver?.accept(this@ImportResolveVisitor, data)
- (0 until typeArgumentsCount).forEach { calledNamesSet.add(getTypeArgument(it)?.asImportStr()) }
- (0 until valueArgumentsCount).forEach { getValueArgument(it)?.accept(this@ImportResolveVisitor, data) }
-
- }
- }
-
override fun visitVariable(declaration: IrVariable, data: String) {
//Здесь обрабатываем тип (потому что мог быть введен явно, а мы выводим явно всегда) и initializer
with(declaration) {
@@ -198,6 +204,18 @@
declaredNamesSet.add("$data.${declaration.name()}")
}
+ override fun visitClassReference(expression: IrClassReference, data: String) {
+ calledNamesSet.add(expression.classType.asImportStr())
+ }
+
+ override fun visitBlock(expression: IrBlock, data: String) {
+ expression.acceptChildren(this, data)
+ }
+
+ override fun visitBlockBody(body: IrBlockBody, data: String) {
+ body.acceptChildren(this, data)
+ }
+
override fun visitElement(element: IrElement, data: String) {
run { }
}
diff --git a/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/Utils.kt b/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/Utils.kt
index 696b3cf..cc00047 100644
--- a/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/Utils.kt
+++ b/compiler/decompiler/src/org/jetbrains/kotlin/decompiler/util/Utils.kt
@@ -7,6 +7,7 @@
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.decompiler.DecompileIrTreeVisitor
+import org.jetbrains.kotlin.decompiler.DecompileIrTreeVisitor.Companion.obtainTypeDescription
import org.jetbrains.kotlin.decompiler.decompile
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
@@ -387,25 +388,7 @@
"lateinit".takeIf { isLateinit },
if (isVar) "var" else "val"
)
-
-internal fun IrType.obtainTypeDescription(): String {
- //TODO разобраться с проблемой
- if ((this as? IrSimpleType)?.abbreviation != null) {
- with(abbreviation!!.typeAlias.owner) {
- return name() + this@obtainTypeDescription.arguments.joinToString(", ", "<", ">") { it.obtain() }
- }
- }
- return if (toKotlinType().isFunctionTypeOrSubtype) {
- val arguments = toKotlinType().arguments
- val returnType = arguments.last().type
- val inputTypes = arguments.dropLast(1)
- "${inputTypes.joinToString(", ", prefix = "(", postfix = ")") {
- it.type.toString() + ("?".takeIf { isNullable() } ?: EMPTY_TOKEN)
- }} -> $returnType"
- } else {
- toKotlinType().toString()
- }
-}
+// По идее эта штука должна быть в companion object визитора и резолвить конфликты имен
internal fun IrValueParameter.obtainValueParameterFlags(): String =
concatenateNonEmptyWithSpace(
diff --git a/compiler/testData/decompiler/box/classes/innerNested/innerGeneric.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/innerGeneric.kt.decompiled
index dd7cf10..e599cec 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/innerGeneric.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/innerGeneric.kt.decompiled
@@ -1,4 +1,4 @@
-// FILE: innerGeneric.kt
+// FILE: /innerGeneric.kt
class Outer {
@@ -10,7 +10,7 @@
}
}
fun box() : String {
- if (Outer().Inner<String>("OK").box() != "OK") {
+ if (Outer().Inner<String>("OK").box() != "OK") {
return "Fail"
}
val x = Outer().Inner<String>("OK")
diff --git a/compiler/testData/decompiler/box/classes/innerNested/innerSimple.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/innerSimple.kt.decompiled
index c99e6b3..36b63cb 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/innerSimple.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/innerSimple.kt.decompiled
@@ -1,5 +1,6 @@
// FILE: /innerSimple.kt
+
class Outer {
inner class Inner {
fun box() : String {
diff --git a/compiler/testData/decompiler/box/classes/innerNested/passingOuterRef.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/passingOuterRef.kt.decompiled
new file mode 100644
index 0000000..e1f8770
--- /dev/null
+++ b/compiler/testData/decompiler/box/classes/innerNested/passingOuterRef.kt.decompiled
@@ -0,0 +1,49 @@
+// FILE: /passingOuterRef.kt
+
+
+open class A1(y: String) {
+ val x = "A1.x,${y}"
+}
+open class A2(y: String) {
+ val x = "A2.x,${y}"
+ open inner class B1 : A1 {
+ constructor(p: String) : super("B1.param,${p}") {
+ }
+ }
+ open inner class B2 : A2 {
+ constructor(p: String) : super("B2.param,${p}") {
+ }
+ }
+ inner class B3 : B1 {
+ constructor(p: String) : super("B3.param,${p}") {
+ }
+ }
+ fun foo() : String {
+ return this.B1("q").x + ";" + this.B2("w").x + ";" + this.B3("e").x + ";" + this.x
+ }
+
+}
+open class A3(y: String) {
+ val x = "A3.x,${y}"
+ open inner class B1(p: String) : A1("B1.param,${p}") {
+ }
+ open inner class B2(p: String) : A3("B2.param,${p}") {
+ }
+ inner class B3(p: String) : B1("B3.param,${p}") {
+ }
+ fun foo() : String {
+ return this.B1("q").x + ";" + this.B2("w").x + ";" + this.B3("e").x + ";" + this.x
+ }
+
+}
+fun box() : String {
+ val r1 = A2("c").foo()
+ if (r1 != "A1.x,B1.param,q;A2.x,B2.param,w;A1.x,B1.param,B3.param,e;A2.x,c") {
+ return "fail1: ${r1}"
+ }
+ val r2 = A3("d").foo()
+ if (r2 != "A1.x,B1.param,q;A3.x,B2.param,w;A1.x,B1.param,B3.param,e;A3.x,d") {
+ return "fail2: ${r2}"
+ }
+ return "OK"
+}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/deepLocalHierarchy.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/deepLocalHierarchy.kt.decompiled
index a3ba071..9d39a05 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/deepLocalHierarchy.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/deepLocalHierarchy.kt.decompiled
@@ -1,18 +1,21 @@
+// FILE: /deepLocalHierarchy.kt
+
+
fun box() : String {
abstract class L1 {
abstract fun foo() : String
}
- open class L2(val s: String): L1 () {
+ open class L2(val s: String) : L1() {
override fun foo() : String {
return this.s
}
}
- open class L3(val unused: Double, val value: String = "OK"): L2 (value) {
+ open class L3(unused: Double, value: String = "OK") : L2(value) {
}
- open class L4(val i: Int, val j: Long, val z: Boolean, val l: L3): L3 (3.14) {
+ open class L4(i: Int, j: Long, z: Boolean, l: L3) : L3(3.14) {
}
- class L5: L4 (0, 0, false, L3(2.71, "Fail")) {
+ class L5 : L4(0, 0, false, L3(2.71, "Fail")) {
}
return L5().foo()
}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_1.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_1.kt.decompiled
index b2d7c3a..717ed43 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_1.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_1.kt.decompiled
@@ -1,16 +1,19 @@
+// FILE: /kt11833_1.kt
+
+
abstract class Father {
abstract inner class InClass {
- abstract fun work() : kotlin.String
+ abstract fun work() : String
}
}
-class Child: Father () {
- val ChildInClass : Father.InClass = object: Father.InClass () {
- override fun work() : kotlin.String {
+class Child : Father() {
+ val ChildInClass = object : InClass() {
+ override fun work() : String {
return "OK"
}
}
}
-fun box() : kotlin.String {
+fun box() : String {
return Child().ChildInClass.work()
}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_2.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_2.kt.decompiled
index aeca5b9..bcb3064 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_2.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/kt11833_2.kt.decompiled
@@ -1,12 +1,15 @@
+// FILE: /kt11833_2.kt
+
+
abstract class Father {
abstract inner class InClass {
- abstract fun work() : kotlin.String
+ abstract fun work() : String
}
}
-class Child: Father () {
- fun test() : Father.InClass {
- return object: Father.InClass () {
- override fun work() : kotlin.String {
+class Child : Father() {
+ fun test() : InClass {
+ return object : InClass() {
+ override fun work() : String {
return "OK"
}
@@ -14,6 +17,6 @@
}
}
-fun box() : kotlin.String {
+fun box() : String {
return Child().test().work()
}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/localExtendsLocalWithClosure.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/localExtendsLocalWithClosure.kt.decompiled
index 6247cde..2a0b9fa 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/localExtendsLocalWithClosure.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/localExtendsLocalWithClosure.kt.decompiled
@@ -1,17 +1,19 @@
+// FILE: /localExtendsLocalWithClosure.kt
+
+
fun box() : String {
- val result : String = "OK"
+ val result = "OK"
open class Local(val ok: Boolean) {
fun result() : String {
- return if (this.ok) {
- result
-}
-else {
- "Fail"
-}
+ return if (this.ok) {
+ result
+ } else {
+ "Fail"
+ }
}
}
- class Derived: Local (true) {
+ class Derived : Local(true) {
}
return Derived().result()
}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassDefaultArgument.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassDefaultArgument.kt.decompiled
new file mode 100644
index 0000000..1d3a4fc
--- /dev/null
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassDefaultArgument.kt.decompiled
@@ -0,0 +1,10 @@
+// FILE: /objectExtendsClassDefaultArgument.kt
+
+
+open class A(val result: String = "OK") {
+}
+fun box() : String {
+ val a = object : A() {
+}
+ return a.result
+}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassVararg.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassVararg.kt.decompiled
index 2dd8505..e8d2365 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassVararg.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsClassVararg.kt.decompiled
@@ -1,10 +1,13 @@
+// FILE: /objectExtendsClassVararg.kt
+
+
open class SomeClass(val some: Double, val other: Int, vararg val args: String) {
- fun result() : kotlin.String {
+ fun result() : String {
return this.args.get(1)
}
}
-fun box() : kotlin.String {
- return object: SomeClass (3.14, 42, "No", "OK", "Yes") {
+fun box() : String {
+ return object : SomeClass(3.14, 42, "No", "OK", "Yes") {
}.result()
}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsInner.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsInner.kt.decompiled
new file mode 100644
index 0000000..b8741bf
--- /dev/null
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsInner.kt.decompiled
@@ -0,0 +1,20 @@
+// FILE: /objectExtendsInner.kt
+
+
+class A {
+ open inner class Inner(val result: String) {
+ }
+ fun box() : String {
+ val o = object : Inner("OK") {
+ fun ok() : String {
+ return this.result
+ }
+
+}
+ return o.ok()
+ }
+
+}
+fun box() : String {
+ return A().box()
+}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt.decompiled
new file mode 100644
index 0000000..988bd52
--- /dev/null
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsInnerOfLocalWithCapture.kt.decompiled
@@ -0,0 +1,21 @@
+// FILE: /objectExtendsInnerOfLocalWithCapture.kt
+
+
+fun box() : String {
+ class Local {
+ open inner class Inner(val s: String) {
+ open fun result() : String {
+ return "Fail"
+ }
+
+ }
+ val realResult = "OK"
+ val obj = object : Inner(this.realResult) {
+ override fun result() : String {
+ return this.s
+ }
+
+}
+ }
+ return Local().obj.result()
+}
diff --git a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt.decompiled b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt.decompiled
index db67acb..7ad36b0 100644
--- a/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt.decompiled
+++ b/compiler/testData/decompiler/box/classes/innerNested/superConstructorCall/objectExtendsLocalCaptureInSuperCall.kt.decompiled
@@ -1,9 +1,12 @@
+// FILE: /objectExtendsLocalCaptureInSuperCall.kt
+
+
open class A(val s: String) {
}
-fun box() : kotlin.String {
+fun box() : String {
class B {
- val result : kotlin.String = "OK"
- val f : kotlin.String = object: A (this.result) {
+ val result = "OK"
+ val f = object : A(this.result) {
}.s
}
return B().f
diff --git a/compiler/testData/decompiler/box/imports/anon_and_local.kt b/compiler/testData/decompiler/box/imports/anon_and_local.kt
new file mode 100644
index 0000000..9d20328
--- /dev/null
+++ b/compiler/testData/decompiler/box/imports/anon_and_local.kt
@@ -0,0 +1,29 @@
+// FILE: AnonAndLocalDeclarations.kt
+package ru.spbau.mit.declaration
+
+open class FailedOk {
+ open fun ok() = "Fail"
+}
+
+val fixedOk = object : FailedOk() {
+ override fun ok(): String = "OK"
+}
+
+// FILE: AnonAndLocalInvocations.kt
+package ru.spbau.mit.invocation
+
+
+import ru.spbau.mit.declaration.FailedOk
+import ru.spbau.mit.declaration.fixedOk
+
+fun box(): String {
+ val failedOk = FailedOk()
+ val localAnonym = object : FailedOk() {
+ override fun ok() = "OK"
+ }
+ return if (localAnonym.ok() == fixedOk.ok()) {
+ "OK"
+ } else {
+ failedOk.ok()
+ }
+}
\ No newline at end of file
diff --git a/compiler/testData/decompiler/box/imports/anon_and_local.kt.decompiled b/compiler/testData/decompiler/box/imports/anon_and_local.kt.decompiled
new file mode 100644
index 0000000..e5081bc
--- /dev/null
+++ b/compiler/testData/decompiler/box/imports/anon_and_local.kt.decompiled
@@ -0,0 +1,38 @@
+// FILE: /AnonAndLocalDeclarations.kt
+package ru.spbau.mit.declaration
+
+
+
+open class FailedOk {
+ open fun ok() : String {
+ return "Fail"
+ }
+
+}
+val fixedOk = object : FailedOk() {
+ override fun ok() : String {
+ return "OK"
+ }
+
+}
+
+// FILE: /AnonAndLocalInvocations.kt
+package ru.spbau.mit.invocation
+
+import ru.spbau.mit.declaration.FailedOk
+import ru.spbau.mit.declaration.fixedOk
+
+fun box() : String {
+ val failedOk = FailedOk()
+ val localAnonym = object : FailedOk() {
+ override fun ok() : String {
+ return "OK"
+ }
+
+}
+ return if (localAnonym.ok() == fixedOk.ok()) {
+ "OK"
+ } else {
+ failedOk.ok()
+ }
+}
diff --git a/compiler/testData/decompiler/box/javaEnum.kt b/compiler/testData/decompiler/box/javaEnum.kt
index 93b6782..25f5d60 100644
--- a/compiler/testData/decompiler/box/javaEnum.kt
+++ b/compiler/testData/decompiler/box/javaEnum.kt
@@ -2,7 +2,7 @@
package a
-fun foo() {}
+fun foo() = "OK"
// FILE: B.kt
@@ -10,6 +10,5 @@
import a.foo
-fun test() {
- foo()
-}
+fun box() = foo()
+
diff --git a/compiler/testData/decompiler/box/javaEnum.kt.decompiled b/compiler/testData/decompiler/box/javaEnum.kt.decompiled
new file mode 100644
index 0000000..3c6cbe4
--- /dev/null
+++ b/compiler/testData/decompiler/box/javaEnum.kt.decompiled
@@ -0,0 +1,17 @@
+// FILE: /A.kt
+package a
+
+
+
+fun foo() : String {
+ return "OK"
+}
+
+// FILE: /B.kt
+package b
+
+import a.foo
+
+fun box() : String {
+ return foo()
+}
diff --git a/compiler/tests/org/jetbrains/kotlin/decompiler/IrDecompilerBlackBoxTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/decompiler/IrDecompilerBlackBoxTestGenerated.java
index 938c3e9..d54ac39 100644
--- a/compiler/tests/org/jetbrains/kotlin/decompiler/IrDecompilerBlackBoxTestGenerated.java
+++ b/compiler/tests/org/jetbrains/kotlin/decompiler/IrDecompilerBlackBoxTestGenerated.java
@@ -1109,6 +1109,11 @@
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/decompiler/box/imports"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
+ @TestMetadata("anon_and_local.kt")
+ public void testAnon_and_local() throws Exception {
+ runTest("compiler/testData/decompiler/box/imports/anon_and_local.kt");
+ }
+
@TestMetadata("deep_nesting.kt")
public void testDeep_nesting() throws Exception {
runTest("compiler/testData/decompiler/box/imports/deep_nesting.kt");