From 6c4102bf23cae4c65c209dc63b69f08da9d3efff Mon Sep 17 00:00:00 2001 From: Alex Tkachman Date: Wed, 12 Sep 2012 17:35:51 +0300 Subject: [PATCH] simple case (no closures) of class level objects #KT-2398 fixed --- .../jetbrains/jet/codegen/ClassCodegen.java | 5 ++- .../jet/codegen/ExpressionCodegen.java | 8 +++- .../codegen/ImplementationBodyCodegen.java | 2 +- .../jet/codegen/binding/CodegenBinding.java | 41 +++++++++++++++---- .../testData/codegen/regressions/kt2398.kt | 15 +++++++ .../jet/codegen/CodegenTestCase.java | 24 +++++++---- .../jetbrains/jet/codegen/ObjectGenTest.java | 5 +++ 7 files changed, 82 insertions(+), 18 deletions(-) create mode 100644 compiler/testData/codegen/regressions/kt2398.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java index 8c9a526f7ee..cf5a08ebaf2 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassCodegen.java @@ -60,9 +60,12 @@ public class ClassCodegen extends GenerationStateAware { generate(contextForInners, (JetClass) declaration); } - if (declaration instanceof JetClassObject) { + else if (declaration instanceof JetClassObject) { generate(contextForInners, ((JetClassObject) declaration).getObjectDeclaration()); } + else if (declaration instanceof JetObjectDeclaration) { + generate(contextForInners, (JetObjectDeclaration) declaration); + } } if (state.getClassBuilderMode() != ClassBuilderMode.SIGNATURES) { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java index cb49db99d81..5a967aa8167 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ExpressionCodegen.java @@ -2925,7 +2925,13 @@ public class ExpressionCodegen extends JetVisitor implem receiver.put(receiver.type, v); - pushClosureOnStack(bindingContext.get(CLOSURE, classDescriptor), true); + final MutableClosure closure = bindingContext.get(CLOSURE, classDescriptor); + + if(receiver.type.getSort() != Type.VOID && (closure == null || closure.getCaptureThis() == null)) { + v.pop(); + } + + pushClosureOnStack(closure, true); invokeMethodWithArguments(method, expression, StackValue.none()); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 300071c9632..0520454ae4c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1156,7 +1156,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { @Override protected void generateDeclaration(PropertyCodegen propertyCodegen, JetDeclaration declaration, FunctionCodegen functionCodegen) { - if (declaration instanceof JetClassObject) { + if (declaration instanceof JetClassObject || declaration instanceof JetObjectDeclaration) { // done earlier in order to have accessors } else if (declaration instanceof JetEnumEntry) { 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 05faf962fe6..a858d1bc3dd 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java @@ -26,7 +26,6 @@ import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingTrace; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -137,15 +136,35 @@ public class CodegenBinding { bindingTrace.record(CLASS_FOR_FUNCTION, scriptDescriptor, classDescriptor); } - private static boolean canHaveOuter(BindingContext bindingContext, ClassDescriptor classDescriptor) { - if (DescriptorUtils.isClassObject(classDescriptor)) { - return false; - } - if (classDescriptor.getKind() == ClassKind.ENUM_CLASS || classDescriptor.getKind() == ClassKind.ENUM_ENTRY) { + private static boolean canHaveOuter(BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) { + final ClassKind kind = classDescriptor.getKind(); + if (isSingleton(bindingContext, classDescriptor)) { return false; } - return enclosingClassDescriptor(bindingContext, classDescriptor) != null; + if (kind == ClassKind.ENUM_CLASS) { + return false; + } + + final ClassDescriptor enclosing = enclosingClassDescriptor(bindingContext, classDescriptor); + return enclosing != null && !isSingleton(bindingContext, enclosing); + } + + public static boolean isSingleton(BindingContext bindingContext, @NotNull ClassDescriptor classDescriptor) { + final ClassKind kind = classDescriptor.getKind(); + if (kind == ClassKind.CLASS_OBJECT) { + return true; + } + + if (kind == ClassKind.OBJECT && isObjectDeclaration(bindingContext, classDescriptor)) { + return true; + } + + if (kind == ClassKind.ENUM_ENTRY) { + return true; + } + + return false; } static void recordClosure( @@ -227,6 +246,14 @@ public class CodegenBinding { return false; } + public static boolean isObjectDeclaration(BindingContext bindingContext, ClassDescriptor declaration) { + PsiElement psiElement = descriptorToDeclaration(bindingContext, declaration); + if (psiElement instanceof JetObjectDeclaration && !((JetObjectDeclaration) psiElement).isObjectLiteral()) { + return true; + } + return false; + } + public static boolean isLocalFun(BindingContext bindingContext, DeclarationDescriptor fd) { PsiElement psiElement = descriptorToDeclaration(bindingContext, fd); if (psiElement instanceof JetNamedFunction && psiElement.getParent() instanceof JetBlockExpression) { diff --git a/compiler/testData/codegen/regressions/kt2398.kt b/compiler/testData/codegen/regressions/kt2398.kt new file mode 100644 index 00000000000..06a51f9f83d --- /dev/null +++ b/compiler/testData/codegen/regressions/kt2398.kt @@ -0,0 +1,15 @@ +class C { + public object Obj { + val o = "O" + + object InnerObj { + fun k() = "K" + } + + class D { + val ko = "KO" + } + } +} + +fun box() = C().Obj.o + C().Obj.InnerObj.k() + C().Obj.D().ko \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java index ab716d5bfac..e3386b20590 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java +++ b/compiler/tests/org/jetbrains/jet/codegen/CodegenTestCase.java @@ -25,23 +25,23 @@ import com.intellij.psi.PsiFile; import com.intellij.testFramework.UsefulTestCase; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.asm4.Type; import org.jetbrains.jet.CompileCompilerDependenciesTest; import org.jetbrains.jet.ConfigurationKind; +import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.TestJdkKind; +import org.jetbrains.jet.analyzer.AnalyzeExhaust; import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys; +import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.codegen.state.GenerationStrategy; import org.jetbrains.jet.lang.BuiltinsScopeExtensionMode; -import org.jetbrains.jet.lang.resolve.ScriptNameUtil; -import org.jetbrains.jet.utils.ExceptionUtils; -import org.jetbrains.jet.JetTestUtils; -import org.jetbrains.jet.analyzer.AnalyzeExhaust; -import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.AnalyzingUtils; +import org.jetbrains.jet.lang.resolve.ScriptNameUtil; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; import org.jetbrains.jet.parsing.JetParsingTest; -import org.jetbrains.asm4.Type; +import org.jetbrains.jet.utils.ExceptionUtils; import java.io.File; import java.io.IOException; @@ -152,8 +152,12 @@ public abstract class CodegenTestCase extends UsefulTestCase { } protected void blackBoxFile(String filename) { + blackBoxFile(filename, "OK"); + } + + protected void blackBoxFile(String filename, String expected) { loadFile(filename); - blackBox(); + blackBox(expected); } protected void blackBoxFileByFullPath(String filename) { @@ -206,6 +210,10 @@ public abstract class CodegenTestCase extends UsefulTestCase { } protected void blackBox() { + blackBox("OK"); + } + + protected void blackBox(String expected) { GenerationState state = generateClassesInFileGetState(); GeneratedClassLoader loader = createClassLoader(state.getFactory()); @@ -248,7 +256,7 @@ public abstract class CodegenTestCase extends UsefulTestCase { try { Method method = namespaceClass.getMethod("box"); r = (String) method.invoke(null); - assertEquals("OK", r); + assertEquals(expected, r); } catch (NoSuchMethodException e) { Method method = namespaceClass.getMethod("main",String[].class); diff --git a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java index eaea4f12fcc..300971d753b 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/ObjectGenTest.java @@ -99,4 +99,9 @@ public class ObjectGenTest extends CodegenTestCase { public void testFlist() { blackBoxFile("objects/flist.kt"); } + + public void testKt2398() { + blackBoxFile("regressions/kt2398.kt", "OKKO"); + System.out.println(generateToText()); + } }