diff --git a/.idea/modules.xml b/.idea/modules.xml index e09a99b7117..86992a19673 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -14,6 +14,7 @@ + diff --git a/compiler/ir/backend.common/backend.common.iml b/compiler/ir/backend.common/backend.common.iml new file mode 100644 index 00000000000..56e15c15f12 --- /dev/null +++ b/compiler/ir/backend.common/backend.common.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/xbackend/common/AbstractClosureAnnotator.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/xbackend/common/AbstractClosureAnnotator.kt new file mode 100644 index 00000000000..76addd66009 --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/xbackend/common/AbstractClosureAnnotator.kt @@ -0,0 +1,148 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.xbackend.common + +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrGeneralFunction +import org.jetbrains.kotlin.ir.declarations.IrLocalPropertyAccessor +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.resolve.DescriptorUtils +import java.util.* + +class Closure( + val capturedThisReferences: List, + val capturedReceiverParameters: List, + val capturedVariables: List +) + +abstract class AbstractClosureAnnotator : IrElementVisitorVoid { + protected abstract fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) + protected abstract fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) + + private class ClosureBuilder(val owner: DeclarationDescriptor) { + val capturedThisReferences = mutableSetOf() + val capturedReceiverParameters = mutableSetOf() + val capturedVariables = mutableSetOf() + + fun buildClosure() = Closure( + capturedThisReferences.toList(), + capturedReceiverParameters.toList(), + capturedVariables.toList() + ) + + fun addNested(closure: Closure) { + fillInCapturedThisReferences(closure) + fillInNestedClosure(capturedReceiverParameters, closure.capturedReceiverParameters) + fillInNestedClosure(capturedVariables, closure.capturedVariables) + } + + private fun fillInCapturedThisReferences(closure: Closure) { + if (owner is ClassDescriptor) { + closure.capturedThisReferences.filterTo(capturedThisReferences) { it != owner } + } + else if (owner is CallableMemberDescriptor && owner.dispatchReceiverParameter != null) { + val ownerClass = owner.containingDeclaration as? ClassDescriptor + closure.capturedThisReferences.filterTo(capturedThisReferences) { it != ownerClass } + } + } + + private fun fillInNestedClosure(destination: MutableSet, nested: List) { + nested.filterTo(destination) { + it.containingDeclaration != owner + } + } + + fun addCapturedThis(classDescriptor: ClassDescriptor) { + if (owner is ClassDescriptor && owner != classDescriptor) { + capturedThisReferences.add(classDescriptor) + } + else if (owner is CallableMemberDescriptor && owner.containingDeclaration != classDescriptor) { + capturedThisReferences.add(classDescriptor) + } + } + } + + private val closuresStack = ArrayDeque() + + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitClass(declaration: IrClass) { + val classDescriptor = declaration.descriptor + val closureBuilder = ClosureBuilder(classDescriptor) + + closuresStack.push(closureBuilder) + declaration.acceptChildrenVoid(this) + closuresStack.pop() + + val closure = closureBuilder.buildClosure() + + if (DescriptorUtils.isLocal(classDescriptor)) { + recordClassClosure(classDescriptor, closure) + } + + closuresStack.peek()?.addNested(closure) + } + + override fun visitGeneralFunction(declaration: IrGeneralFunction) { + val functionDescriptor = declaration.descriptor + val closureBuilder = ClosureBuilder(functionDescriptor) + + closuresStack.push(closureBuilder) + declaration.acceptChildrenVoid(this) + closuresStack.pop() + + val closure = closureBuilder.buildClosure() + + if (DescriptorUtils.isLocal(functionDescriptor)) { + recordFunctionClosure(functionDescriptor, closure) + } + + closuresStack.peek()?.addNested(closure) + } + + override fun visitLocalPropertyAccessor(declaration: IrLocalPropertyAccessor) { + // Local property accessors are created for delegated local properties and have no closure. + } + + override fun visitThisReference(expression: IrThisReference) { + closuresStack.peek().addCapturedThis(expression.classDescriptor) + } + + override fun visitVariableAccess(expression: IrVariableAccessExpression) { + val closureBuilder = closuresStack.peek() + val variableDescriptor = expression.descriptor + if (variableDescriptor.containingDeclaration != closureBuilder.owner) { + closureBuilder.capturedVariables.add(variableDescriptor) + } + + expression.acceptChildrenVoid(this) + } + + override fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver) { + val closureBuilder = closuresStack.peek() + val receiverDescriptor = expression.descriptor + if (receiverDescriptor.containingDeclaration != closureBuilder.owner) { + closureBuilder.capturedReceiverParameters.add(receiverDescriptor) + } + } +} diff --git a/compiler/ir/ir.tests/ir.tests.iml b/compiler/ir/ir.tests/ir.tests.iml index e30224002d3..d50982cac59 100644 --- a/compiler/ir/ir.tests/ir.tests.iml +++ b/compiler/ir/ir.tests/ir.tests.iml @@ -15,5 +15,6 @@ + \ No newline at end of file diff --git a/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractClosureAnnotatorTestCase.kt b/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractClosureAnnotatorTestCase.kt new file mode 100644 index 00000000000..349ab54c65e --- /dev/null +++ b/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractClosureAnnotatorTestCase.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir + +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.xbackend.common.AbstractClosureAnnotator +import org.jetbrains.kotlin.xbackend.common.Closure +import java.io.File +import java.io.PrintWriter +import java.io.StringWriter + +abstract class AbstractClosureAnnotatorTestCase : AbstractIrGeneratorTestCase() { + override fun doTest(wholeFile: File, testFiles: List) { + val dir = wholeFile.parentFile + val ignoreErrors = shouldIgnoreErrors(wholeFile) + for ((testFile, irFile) in generateIrFilesAsSingleModule(testFiles, ignoreErrors)) { + doTestIrFileAgainstExpectations(dir, testFile, irFile) + } + } + + private fun doTestIrFileAgainstExpectations(dir: File, testFile: TestFile, irFile: IrFile) { + val expectedFile = File(dir, testFile.name.replace(".kt", ".closure")) + val actualClosures = renderClosures(irFile) + KotlinTestUtils.assertEqualsToFile(expectedFile, actualClosures) + } + + private fun renderClosures(irFile: IrFile): String { + val actualStringWriter = StringWriter() + val actualOut = PrintWriter(actualStringWriter) + + irFile.acceptChildrenVoid(object : AbstractClosureAnnotator() { + override fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure) { + actualOut.println("Closure for class ${classDescriptor.name}:") + printClosure(closure) + actualOut.println() + } + + override fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure) { + if (functionDescriptor is ConstructorDescriptor) { + actualOut.println("Closure for constructor ${functionDescriptor.containingDeclaration.name}:") + } + else { + actualOut.println("Closure for function ${functionDescriptor.name}:") + } + printClosure(closure) + actualOut.println() + } + + private fun printClosure(closure: Closure) { + closure.capturedThisReferences.forEach { + actualOut.println(" 'this' for ${it.name}") + } + closure.capturedReceiverParameters.forEach { + actualOut.println(" receiver for ${it.containingDeclaration.name}") + } + closure.capturedVariables.forEach { + actualOut.println(" variable ${it.name}") + } + } + }) + + return actualStringWriter.toString() + } +} diff --git a/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrGeneratorTestCase.kt b/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrGeneratorTestCase.kt index bfa42b88b17..03c06ad89d4 100644 --- a/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrGeneratorTestCase.kt +++ b/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrGeneratorTestCase.kt @@ -16,6 +16,7 @@ package org.jetbrains.kotlin.ir +import junit.framework.TestCase import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.codegen.CodegenTestCase @@ -28,6 +29,8 @@ import org.jetbrains.kotlin.test.ConfigurationKind import org.jetbrains.kotlin.test.InTextDirectivesUtils import org.jetbrains.kotlin.test.KotlinTestUtils.getAnnotationsJar import java.io.File +import java.io.FileWriter +import java.io.PrintWriter import java.util.* abstract class AbstractIrGeneratorTestCase : CodegenTestCase() { @@ -86,6 +89,24 @@ abstract class AbstractIrGeneratorTestCase : CodegenTestCase() { val ktFiles = testFiles.filter { it.name.endsWith(".kt") } return ktFiles.zip(irModule.files).toMap() } + + companion object { + private val IGNORE_ERRORS_PATTERN = Regex("""// !IGNORE_ERRORS""") + + internal fun shouldIgnoreErrors(wholeFile: File): Boolean = + IGNORE_ERRORS_PATTERN.containsMatchIn(wholeFile.readText()) + + internal fun createExpectedTextFile(testFile: TestFile, dir: File, fileName: String): File { + val textFile = File(dir, fileName) + if (!textFile.exists()) { + TestCase.assertTrue("Can't create an expected text containingFile: ${textFile.absolutePath}", textFile.createNewFile()) + PrintWriter(FileWriter(textFile)).use { + it.println("$fileName: new expected text containingFile for ${testFile.name}") + } + } + return textFile + } + } } diff --git a/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt b/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt index 3468f5dda26..76c62efe051 100644 --- a/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt +++ b/compiler/ir/ir.tests/tests/org/jetbrains/kotlin/ir/AbstractIrTextTestCase.kt @@ -75,10 +75,6 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() { companion object { private val EXPECTED_OCCURRENCES_PATTERN = Regex("""^\s*//\s*(\d+)\s*(.*)$""") private val IR_FILE_TXT_PATTERN = Regex("""// IR_FILE: (.*)$""") - private val IGNORE_ERRORS_PATTERN = Regex("""// !IGNORE_ERRORS""") - - internal fun shouldIgnoreErrors(wholeFile: File): Boolean = - IGNORE_ERRORS_PATTERN.containsMatchIn(wholeFile.readText()) internal fun parseExpectations(dir: File, testFile: TestFile): Expectations { val regexps = ArrayList() @@ -102,17 +98,6 @@ abstract class AbstractIrTextTestCase : AbstractIrGeneratorTestCase() { return Expectations(regexps, treeFiles) } - - internal fun createExpectedTextFile(testFile: TestFile, dir: File, fileName: String): File { - val textFile = File(dir, fileName) - if (!textFile.exists()) { - TestCase.assertTrue("Can't create an IR expected text containingFile: ${textFile.absolutePath}", textFile.createNewFile()) - PrintWriter(FileWriter(textFile)).use { - it.println("$fileName: new IR expected text containingFile for ${testFile.name}") - } - } - return textFile - } } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index 5350ffa6d10..11a5d1a0671 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -60,8 +60,9 @@ interface IrElementVisitor { fun visitSingletonReference(expression: IrGetSingletonValue, data: D) = visitDeclarationReference(expression, data) fun visitGetObjectValue(expression: IrGetObjectValue, data: D) = visitSingletonReference(expression, data) fun visitGetEnumValue(expression: IrGetEnumValue, data: D) = visitSingletonReference(expression, data) - fun visitGetVariable(expression: IrGetVariable, data: D) = visitDeclarationReference(expression, data) - fun visitSetVariable(expression: IrSetVariable, data: D) = visitDeclarationReference(expression, data) + fun visitVariableAccess(expression: IrVariableAccessExpression, data: D) = visitDeclarationReference(expression, data) + fun visitGetVariable(expression: IrGetVariable, data: D) = visitVariableAccess(expression, data) + fun visitSetVariable(expression: IrSetVariable, data: D) = visitVariableAccess(expression, data) fun visitBackingFieldReference(expression: IrBackingFieldExpression, data: D) = visitDeclarationReference(expression, data) fun visitGetBackingField(expression: IrGetBackingField, data: D) = visitBackingFieldReference(expression, data) fun visitSetBackingField(expression: IrSetBackingField, data: D) = visitBackingFieldReference(expression, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt index b3c0fef7e75..133e4cbf3f8 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt @@ -123,10 +123,13 @@ interface IrElementVisitorVoid : IrElementVisitor { fun visitGetEnumValue(expression: IrGetEnumValue) = visitSingletonReference(expression) override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?) = visitGetEnumValue(expression) - fun visitGetVariable(expression: IrGetVariable) = visitDeclarationReference(expression) + fun visitVariableAccess(expression: IrVariableAccessExpression) = visitDeclarationReference(expression) + override fun visitVariableAccess(expression: IrVariableAccessExpression, data: Nothing?) = visitVariableAccess(expression) + + fun visitGetVariable(expression: IrGetVariable) = visitVariableAccess(expression) override fun visitGetVariable(expression: IrGetVariable, data: Nothing?) = visitGetVariable(expression) - fun visitSetVariable(expression: IrSetVariable) = visitDeclarationReference(expression) + fun visitSetVariable(expression: IrSetVariable) = visitVariableAccess(expression) override fun visitSetVariable(expression: IrSetVariable, data: Nothing?) = visitSetVariable(expression) fun visitBackingFieldReference(expression: IrBackingFieldExpression) = visitDeclarationReference(expression) diff --git a/compiler/testData/ir/closureAnnotator/localFunctions.closure b/compiler/testData/ir/closureAnnotator/localFunctions.closure new file mode 100644 index 00000000000..5f075e464fa --- /dev/null +++ b/compiler/testData/ir/closureAnnotator/localFunctions.closure @@ -0,0 +1,7 @@ +Closure for function test2: + receiver for outer + variable y + +Closure for function test1: + receiver for outer + diff --git a/compiler/testData/ir/closureAnnotator/localFunctions.kt b/compiler/testData/ir/closureAnnotator/localFunctions.kt new file mode 100644 index 00000000000..f52502beac1 --- /dev/null +++ b/compiler/testData/ir/closureAnnotator/localFunctions.kt @@ -0,0 +1,7 @@ +fun String.outer(x: Int) { + fun test1(x: Int, y: Int) { + fun test2(x: Int) = this + x + y + test2(y).length + x + y + } + test1(x, x * x) +} \ No newline at end of file diff --git a/compiler/testData/ir/closureAnnotator/multipleThisReferences.closure b/compiler/testData/ir/closureAnnotator/multipleThisReferences.closure new file mode 100644 index 00000000000..e6a5403d14a --- /dev/null +++ b/compiler/testData/ir/closureAnnotator/multipleThisReferences.closure @@ -0,0 +1,15 @@ +Closure for constructor : + +Closure for function test1: + 'this' for C + +Closure for function : + 'this' for C + 'this' for + +Closure for function test2: + 'this' for C + +Closure for class : + 'this' for C + diff --git a/compiler/testData/ir/closureAnnotator/multipleThisReferences.kt b/compiler/testData/ir/closureAnnotator/multipleThisReferences.kt new file mode 100644 index 00000000000..4b8f116ab1e --- /dev/null +++ b/compiler/testData/ir/closureAnnotator/multipleThisReferences.kt @@ -0,0 +1,6 @@ +class C { + fun foo() = object { + fun test1() = this@C.toString() + this.toString() + fun test2() = { this@C.toString() + this.toString() } + } +} \ No newline at end of file diff --git a/compiler/testData/ir/closureAnnotator/topLevelDeclarations.closure b/compiler/testData/ir/closureAnnotator/topLevelDeclarations.closure new file mode 100644 index 00000000000..a0a3948e6ce --- /dev/null +++ b/compiler/testData/ir/closureAnnotator/topLevelDeclarations.closure @@ -0,0 +1,6 @@ +Closure for constructor : + +Closure for function test6: + +Closure for class : + diff --git a/compiler/testData/ir/closureAnnotator/topLevelDeclarations.kt b/compiler/testData/ir/closureAnnotator/topLevelDeclarations.kt new file mode 100644 index 00000000000..9395cd8e52c --- /dev/null +++ b/compiler/testData/ir/closureAnnotator/topLevelDeclarations.kt @@ -0,0 +1,10 @@ +fun Int.test1(x: Int) = this + x + +class Test2(val x: Int) { + fun test3() = x + fun Int.test4() = this + x +} + +val test5 = object { + fun Int.test6(x: Int) = this + x +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/ir/ClosureAnnotatorTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/ClosureAnnotatorTestCaseGenerated.java new file mode 100644 index 00000000000..89aafd18774 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/ir/ClosureAnnotatorTestCaseGenerated.java @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.ir; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/ir/closureAnnotator") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class ClosureAnnotatorTestCaseGenerated extends AbstractClosureAnnotatorTestCase { + public void testAllFilesPresentInClosureAnnotator() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/closureAnnotator"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("localFunctions.kt") + public void testLocalFunctions() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/closureAnnotator/localFunctions.kt"); + doTest(fileName); + } + + @TestMetadata("multipleThisReferences.kt") + public void testMultipleThisReferences() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/closureAnnotator/multipleThisReferences.kt"); + doTest(fileName); + } + + @TestMetadata("topLevelDeclarations.kt") + public void testTopLevelDeclarations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/closureAnnotator/topLevelDeclarations.kt"); + doTest(fileName); + } +} diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt index a98cf230951..db036e5f57f 100755 --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -121,6 +121,7 @@ import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest import org.jetbrains.kotlin.idea.stubs.AbstractStubBuilderTest import org.jetbrains.kotlin.integration.AbstractAntTaskTest +import org.jetbrains.kotlin.ir.AbstractClosureAnnotatorTestCase import org.jetbrains.kotlin.ir.AbstractIrTextTestCase import org.jetbrains.kotlin.ir.AbstractPsi2IrAcceptanceTestCase import org.jetbrains.kotlin.j2k.AbstractJavaToKotlinConverterForWebDemoTest @@ -249,6 +250,10 @@ fun main(args: Array) { model("codegen/box") } + testClass { + model("ir/closureAnnotator") + } + testClass() { model("codegen/bytecodeListing") }