diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java index 9b680b7499b..82d3c8bbade 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ScriptCodegen.java @@ -26,8 +26,7 @@ import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.ScriptDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; -import org.jetbrains.jet.lang.psi.JetDeclaration; -import org.jetbrains.jet.lang.psi.JetScript; +import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.java.jvmSignature.JvmMethodSignature; import org.jetbrains.org.objectweb.asm.MethodVisitor; @@ -215,7 +214,12 @@ public class ScriptCodegen extends MemberCodegen { private void genMembers() { for (JetDeclaration declaration : scriptDeclaration.getDeclarations()) { - genFunctionOrProperty(declaration); + if (declaration instanceof JetProperty || declaration instanceof JetNamedFunction) { + genFunctionOrProperty(declaration); + } + else if (declaration instanceof JetClassOrObject) { + genClassOrObject((JetClassOrObject) declaration); + } } } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java index a526d6c1bb2..cfc510b16c4 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java @@ -309,6 +309,11 @@ public class CodegenBinding { return fqName.isRoot() ? shortName : fqName.asString().replace('.', '/') + '/' + shortName; } + if (container instanceof ScriptDescriptor) { + Type scriptType = asmTypeForScriptDescriptor(bindingContext, (ScriptDescriptor) container); + return scriptType.getInternalName() + "$" + name.getIdentifier(); + } + assert container instanceof ClassDescriptor : "Unexpected container: " + container + " for " + klass; String containerInternalName = getAsmType(bindingContext, (ClassDescriptor) container).getInternalName(); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java index bbbaad687bc..aa9d742fa1f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/OverloadResolver.java @@ -77,6 +77,9 @@ public class OverloadResolver { else if (containingDeclaration instanceof PackageFragmentDescriptor) { inPackages.put(getFqName(klass), klass.getConstructors()); } + else if (containingDeclaration instanceof ScriptDescriptor) { + // TODO: check overload conflicts of functions with constructors in scripts + } else if (!(containingDeclaration instanceof FunctionDescriptor)) { throw new IllegalStateException("Illegal class container: " + containingDeclaration); } diff --git a/compiler/testData/codegen/script/simpleClass.kts b/compiler/testData/codegen/script/simpleClass.kts new file mode 100644 index 00000000000..b2279d0b45e --- /dev/null +++ b/compiler/testData/codegen/script/simpleClass.kts @@ -0,0 +1,7 @@ +class SimpleClass(val s: String) { + fun foo() = s +} + +SimpleClass("OK").foo() + +// expected: rv: OK diff --git a/compiler/testData/repl/classes/classInheritance.repl b/compiler/testData/repl/classes/classInheritance.repl new file mode 100644 index 00000000000..5c954c4ee8c --- /dev/null +++ b/compiler/testData/repl/classes/classInheritance.repl @@ -0,0 +1,6 @@ +>>> open class A(val result: String) { +... fun foo() = result +... } +>>> class B : A("OK") +>>> B().foo() +OK diff --git a/compiler/testData/repl/classes/classRedeclaration.repl b/compiler/testData/repl/classes/classRedeclaration.repl new file mode 100644 index 00000000000..97e53be0ad1 --- /dev/null +++ b/compiler/testData/repl/classes/classRedeclaration.repl @@ -0,0 +1,13 @@ +>>> class A { +... fun foo() = "Old" +... } +>>> val oldA = A() +>>> class A { +... fun foo() = "New" +... } +>>> oldA.foo() +Old +>>> A().foo() +New +>>> oldA.javaClass == javaClass() +false diff --git a/compiler/testData/repl/classes/emptyClass.repl b/compiler/testData/repl/classes/emptyClass.repl new file mode 100644 index 00000000000..f3f96545cbe --- /dev/null +++ b/compiler/testData/repl/classes/emptyClass.repl @@ -0,0 +1,2 @@ +>>> class A +>>> class B {} diff --git a/compiler/testData/repl/classes/emptyClassRedeclaration.repl b/compiler/testData/repl/classes/emptyClassRedeclaration.repl new file mode 100644 index 00000000000..ee8c96cc136 --- /dev/null +++ b/compiler/testData/repl/classes/emptyClassRedeclaration.repl @@ -0,0 +1,2 @@ +>>> class A +>>> class A diff --git a/compiler/testData/repl/classes/enumEntrySubclass.repl b/compiler/testData/repl/classes/enumEntrySubclass.repl new file mode 100644 index 00000000000..ecd00bd46f9 --- /dev/null +++ b/compiler/testData/repl/classes/enumEntrySubclass.repl @@ -0,0 +1,11 @@ +>>> enum class E { +... FIRST { +... override fun foo() = "HELLO" +... } +... SECOND { +... override fun foo() = "WORLD" +... } +... open fun foo() = "E" +... } +>>> E.FIRST.foo() + " " + E.SECOND.foo() +HELLO WORLD diff --git a/compiler/testData/repl/classes/import.repl b/compiler/testData/repl/classes/import.repl new file mode 100644 index 00000000000..df7a9ba3453 --- /dev/null +++ b/compiler/testData/repl/classes/import.repl @@ -0,0 +1,5 @@ +>>> import java.util.Collections +>>> Collections.emptyList() +[] +>>> Collections.singletonList(":|||:") +[:|||:] diff --git a/compiler/testData/repl/classes/simpleClass.repl b/compiler/testData/repl/classes/simpleClass.repl new file mode 100644 index 00000000000..47507eccd64 --- /dev/null +++ b/compiler/testData/repl/classes/simpleClass.repl @@ -0,0 +1,6 @@ +>>> class A { override fun toString() = "A" } +>>> val a = A() +>>> a +A +>>> a.toString() +A diff --git a/compiler/testData/repl/classes/simpleEnum.repl b/compiler/testData/repl/classes/simpleEnum.repl new file mode 100644 index 00000000000..1e285125080 --- /dev/null +++ b/compiler/testData/repl/classes/simpleEnum.repl @@ -0,0 +1,8 @@ +>>> enum class E { +... FIRST +... SECOND +... } +>>> E.values().toList() +[FIRST, SECOND] +>>> E.FIRST.javaClass == E.SECOND.javaClass // check that no artificial classes are generated for simple enum entries +true diff --git a/compiler/testData/repl/classes/simpleTrait.repl b/compiler/testData/repl/classes/simpleTrait.repl new file mode 100644 index 00000000000..e976e55c927 --- /dev/null +++ b/compiler/testData/repl/classes/simpleTrait.repl @@ -0,0 +1,6 @@ +>>> trait A +>>> trait B : A { +... fun foo() = 45 +... } +>>> javaClass().isAssignableFrom(javaClass()) +true diff --git a/compiler/testData/repl/objects/emptyObject.repl b/compiler/testData/repl/objects/emptyObject.repl new file mode 100644 index 00000000000..bb914dee2ff --- /dev/null +++ b/compiler/testData/repl/objects/emptyObject.repl @@ -0,0 +1,3 @@ +>>> object Empty +>>> "Empty" in Empty.toString() +true diff --git a/compiler/testData/repl/objects/simpleObjectDeclaration.repl b/compiler/testData/repl/objects/simpleObjectDeclaration.repl new file mode 100644 index 00000000000..d6caef64249 --- /dev/null +++ b/compiler/testData/repl/objects/simpleObjectDeclaration.repl @@ -0,0 +1,5 @@ +>>> object Life { +... fun meaning() = 42 +... } +>>> Life.meaning() +42 diff --git a/compiler/tests/org/jetbrains/jet/codegen/ScriptCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/ScriptCodegenTestGenerated.java index ffe0c7d1806..688657f4726 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ScriptCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ScriptCodegenTestGenerated.java @@ -81,6 +81,11 @@ public class ScriptCodegenTestGenerated extends AbstractScriptCodegenTest { doTest("compiler/testData/codegen/script/secondLevelVal.kts"); } + @TestMetadata("simpleClass.kts") + public void testSimpleClass() throws Exception { + doTest("compiler/testData/codegen/script/simpleClass.kts"); + } + @TestMetadata("string.kts") public void testString() throws Exception { doTest("compiler/testData/codegen/script/string.kts"); diff --git a/compiler/tests/org/jetbrains/jet/repl/ReplInterpreterTestGenerated.java b/compiler/tests/org/jetbrains/jet/repl/ReplInterpreterTestGenerated.java index 9f8105278ab..c52128c1503 100644 --- a/compiler/tests/org/jetbrains/jet/repl/ReplInterpreterTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/repl/ReplInterpreterTestGenerated.java @@ -31,6 +31,7 @@ import org.jetbrains.jet.repl.AbstractReplInterpreterTest; /** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ @SuppressWarnings("all") @TestMetadata("compiler/testData/repl") +@InnerTestClasses({ReplInterpreterTestGenerated.Classes.class, ReplInterpreterTestGenerated.Objects.class}) public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest { public void testAllFilesPresentInRepl() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/repl"), Pattern.compile("^(.+)\\.repl$"), true); @@ -106,4 +107,82 @@ public class ReplInterpreterTestGenerated extends AbstractReplInterpreterTest { doTest("compiler/testData/repl/twoClosures.repl"); } + @TestMetadata("compiler/testData/repl/classes") + public static class Classes extends AbstractReplInterpreterTest { + public void testAllFilesPresentInClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/repl/classes"), Pattern.compile("^(.+)\\.repl$"), true); + } + + @TestMetadata("classInheritance.repl") + public void testClassInheritance() throws Exception { + doTest("compiler/testData/repl/classes/classInheritance.repl"); + } + + @TestMetadata("classRedeclaration.repl") + public void testClassRedeclaration() throws Exception { + doTest("compiler/testData/repl/classes/classRedeclaration.repl"); + } + + @TestMetadata("emptyClass.repl") + public void testEmptyClass() throws Exception { + doTest("compiler/testData/repl/classes/emptyClass.repl"); + } + + @TestMetadata("emptyClassRedeclaration.repl") + public void testEmptyClassRedeclaration() throws Exception { + doTest("compiler/testData/repl/classes/emptyClassRedeclaration.repl"); + } + + @TestMetadata("enumEntrySubclass.repl") + public void testEnumEntrySubclass() throws Exception { + doTest("compiler/testData/repl/classes/enumEntrySubclass.repl"); + } + + @TestMetadata("import.repl") + public void testImport() throws Exception { + doTest("compiler/testData/repl/classes/import.repl"); + } + + @TestMetadata("simpleClass.repl") + public void testSimpleClass() throws Exception { + doTest("compiler/testData/repl/classes/simpleClass.repl"); + } + + @TestMetadata("simpleEnum.repl") + public void testSimpleEnum() throws Exception { + doTest("compiler/testData/repl/classes/simpleEnum.repl"); + } + + @TestMetadata("simpleTrait.repl") + public void testSimpleTrait() throws Exception { + doTest("compiler/testData/repl/classes/simpleTrait.repl"); + } + + } + + @TestMetadata("compiler/testData/repl/objects") + public static class Objects extends AbstractReplInterpreterTest { + public void testAllFilesPresentInObjects() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/repl/objects"), Pattern.compile("^(.+)\\.repl$"), true); + } + + @TestMetadata("emptyObject.repl") + public void testEmptyObject() throws Exception { + doTest("compiler/testData/repl/objects/emptyObject.repl"); + } + + @TestMetadata("simpleObjectDeclaration.repl") + public void testSimpleObjectDeclaration() throws Exception { + doTest("compiler/testData/repl/objects/simpleObjectDeclaration.repl"); + } + + } + + public static Test suite() { + TestSuite suite = new TestSuite("ReplInterpreterTestGenerated"); + suite.addTestSuite(ReplInterpreterTestGenerated.class); + suite.addTestSuite(Classes.class); + suite.addTestSuite(Objects.class); + return suite; + } } diff --git a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ConstructorDescriptorImpl.java b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ConstructorDescriptorImpl.java index 6b486b21c66..dadc33dd1d9 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ConstructorDescriptorImpl.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/descriptors/impl/ConstructorDescriptorImpl.java @@ -20,7 +20,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.Annotations; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.Name; import java.util.Collections; @@ -71,7 +70,10 @@ public class ConstructorDescriptorImpl extends FunctionDescriptorImpl implements @Nullable private static ReceiverParameterDescriptor getExpectedThisObject(@NotNull ClassDescriptor descriptor) { DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration(); - return DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration); + if (containingDeclaration instanceof ClassDescriptor) { + return ((ClassDescriptor) containingDeclaration).getThisAsReceiverParameter(); + } + return NO_RECEIVER_PARAMETER; } @NotNull