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");