diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java index 9dbbe372057..47d78e95493 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/MutableClosure.java @@ -121,7 +121,7 @@ public final class MutableClosure implements CalculatedClosure { public void captureVariable(EnclosedValueDescriptor value) { if (captureVariables == null) { - captureVariables = new HashMap(); + captureVariables = new LinkedHashMap(); } captureVariables.put(value.getDescriptor(), value); } diff --git a/compiler/tests/org/jetbrains/jet/codegen/MethodOrderTest.kt b/compiler/tests/org/jetbrains/jet/codegen/MethodOrderTest.kt new file mode 100644 index 00000000000..30a18fef947 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/codegen/MethodOrderTest.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2010-2014 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.jet.codegen + +import org.jetbrains.jet.ConfigurationKind +import org.jetbrains.asm4.ClassReader +import org.jetbrains.asm4.ClassVisitor +import org.jetbrains.asm4.Opcodes +import org.jetbrains.asm4.MethodVisitor +import java.util.ArrayList +import junit.framework.TestCase + +public class MethodOrderTest: CodegenTestCase() { + public fun testLambdaClosureOrdering() { + doTest( + """ + class Klass { + fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) { + { a + b + c + d + e + this@f + this@Klass }() + } + } + """, + "\$f$1", + listOf("invoke()Ljava/lang/Object;", "invoke()Ljava/lang/String;", "(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V") + ) + } + + public fun testAnonymousObjectClosureOrdering() { + doTest( + """ + class Klass { + fun Any.f(a: String, b: Int, c: Double, d: Any, e: Long) { + object : Runnable { + override fun run() { + a + b + c + d + e + this@f + this@Klass + } + }.run() + } + } + """, + "\$f$1", + listOf("()V", "run()V", "(LKlass;Ljava/lang/Object;Ljava/lang/String;IDLjava/lang/Object;J)V") + ) + } + + private fun doTest(sourceText: String, classSuffix: String, expectedOrder: List) { + createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_AND_ANNOTATIONS) + myFiles = CodegenTestFiles.create("file.kt", sourceText, myEnvironment!!.getProject()) + + val classFileForObject = generateClassesInFile().asList().first { it.relativePath.endsWith("$classSuffix.class") } + val classReader = ClassReader(classFileForObject.asByteArray()) + + val methodNames = ArrayList() + + classReader.accept(object : ClassVisitor(Opcodes.ASM4) { + override fun visitMethod(access: Int, name: String, desc: String, signature: String?, exceptions: Array?): MethodVisitor? { + methodNames.add(name + desc) + return null + } + }, ClassReader.SKIP_CODE and ClassReader.SKIP_DEBUG and ClassReader.SKIP_FRAMES) + + TestCase.assertEquals(expectedOrder, methodNames) + } +} \ No newline at end of file