From ad4eeb3f8ab84cbbe38004a2bef015dc743124f6 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 26 Mar 2013 20:15:06 +0400 Subject: [PATCH] Properly capture local functions Local functions in local classed wasn't captured properly --- .../jetbrains/jet/codegen/ClosureCodegen.java | 2 +- .../jet/codegen/FunctionCodegen.java | 4 +-- .../codegen/ImplementationBodyCodegen.java | 2 +- .../jet/codegen/binding/CodegenBinding.java | 17 +++------- .../jet/codegen/context/LocalLookup.java | 4 +-- .../jet/codegen/state/JetTypeMapper.java | 2 +- .../box/closures/closureInsideConstrucor.kt | 14 ++++++++ .../fakeDescriptorWithSeveralOverridenOne.kt | 23 +++++++++++++ .../localFunctionInConstructor.kt | 15 +++++++++ .../BlackBoxCodegenTestGenerated.java | 32 ++++++++++++++++++- 10 files changed, 94 insertions(+), 21 deletions(-) create mode 100644 compiler/testData/codegen/box/closures/closureInsideConstrucor.kt create mode 100644 compiler/testData/codegen/box/functions/fakeDescriptorWithSeveralOverridenOne.kt create mode 100644 compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java index 6c6d0f99f32..0e9c5b42c79 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClosureCodegen.java @@ -255,7 +255,7 @@ public class ClosureCodegen extends GenerationStateAware { : typeMapper.mapType((VariableDescriptor) descriptor); args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName())); } - else if (isLocalNamedFun(state.getBindingContext(), descriptor)) { + else if (isLocalNamedFun(descriptor)) { Type type = classNameForAnonymousClass(bindingContext, (JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)) diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index c69fbb86d56..d1514793ecc 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -51,7 +51,7 @@ import java.util.*; import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.jet.codegen.AsmUtil.*; import static org.jetbrains.jet.codegen.CodegenUtil.*; -import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalFun; +import static org.jetbrains.jet.codegen.binding.CodegenBinding.isLocalNamedFun; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.callableDescriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; @@ -152,7 +152,7 @@ public class FunctionCodegen extends GenerationStateAware { if (expectedThisObject != null) { thisType = typeMapper.mapType(expectedThisObject.getType()); } - else if (declaration instanceof JetFunctionLiteral || isLocalFun(bindingContext, functionDescriptor)) { + else if (declaration instanceof JetFunctionLiteral || isLocalNamedFun(functionDescriptor)) { thisType = typeMapper.mapType(context.getThisDescriptor()); } else { diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index 0915a7ad618..eddc3442a6c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -1233,7 +1233,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } constructorContext.lookupInContext(descriptor, null, state, true); - } else if (descriptor instanceof CallableMemberDescriptor) { + } else if (isLocalNamedFun(descriptor)) { MutableClassDescriptor classDescriptor = (MutableClassDescriptor) constructorContext.getParentContext().getContextDescriptor(); 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 cbb0fb3df9f..d50f60c7977 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/binding/CodegenBinding.java @@ -295,19 +295,10 @@ public class CodegenBinding { return false; } - public static boolean isLocalFun(BindingContext bindingContext, DeclarationDescriptor fd) { - PsiElement psiElement = descriptorToDeclaration(bindingContext, fd); - if (psiElement instanceof JetNamedFunction && psiElement.getParent() instanceof JetBlockExpression) { - return true; - } - return false; - } - - public static boolean isLocalNamedFun(BindingContext bindingContext, DeclarationDescriptor fd) { - PsiElement psiElement = descriptorToDeclaration(bindingContext, fd); - if (psiElement instanceof JetNamedFunction) { - DeclarationDescriptor declaration = fd.getContainingDeclaration(); - return declaration instanceof FunctionDescriptor || declaration instanceof PropertyDescriptor; + public static boolean isLocalNamedFun(DeclarationDescriptor fd) { + if (fd instanceof FunctionDescriptor) { + FunctionDescriptor descriptor = (FunctionDescriptor) fd; + return descriptor.getVisibility() == Visibilities.LOCAL && !descriptor.getName().isSpecial(); } return false; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java b/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java index c3c04f79e01..f5c01e8644b 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/context/LocalLookup.java @@ -72,7 +72,7 @@ public interface LocalLookup { LOCAL_NAMED_FUNCTION { @Override public boolean isCase(DeclarationDescriptor d, GenerationState state) { - return isLocalNamedFun(state.getBindingContext(), d); + return isLocalNamedFun(d); } @Override @@ -85,7 +85,7 @@ public interface LocalLookup { ) { FunctionDescriptor vd = (FunctionDescriptor) d; - boolean idx = localLookup.lookupLocal(vd); + boolean idx = localLookup != null && localLookup.lookupLocal(vd); if (!idx) return null; JetElement expression = (JetElement) callableDescriptorToDeclaration(state.getBindingContext(), vd); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java index fee60e620a7..ba22bba3075 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/state/JetTypeMapper.java @@ -816,7 +816,7 @@ public class JetTypeMapper extends BindingTraceAware { signatureWriter.writeAsmType(sharedVarType, false); signatureWriter.writeParameterTypeEnd(); } - else if (isLocalNamedFun(bindingContext, variableDescriptor)) { + else if (isLocalNamedFun(variableDescriptor)) { Type type = classNameForAnonymousClass( bindingContext, (JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, variableDescriptor) diff --git a/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt b/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt new file mode 100644 index 00000000000..fd99329f1ca --- /dev/null +++ b/compiler/testData/codegen/box/closures/closureInsideConstrucor.kt @@ -0,0 +1,14 @@ +//adopted snippet from kdoc +open class KModel { + val sourcesInfo: String + ;{ + fun relativePath(psiFile: String): String { + return psiFile; + } + sourcesInfo = relativePath("OK") + } +} + +fun box():String { + return KModel().sourcesInfo; +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/functions/fakeDescriptorWithSeveralOverridenOne.kt b/compiler/testData/codegen/box/functions/fakeDescriptorWithSeveralOverridenOne.kt new file mode 100644 index 00000000000..862108d8b89 --- /dev/null +++ b/compiler/testData/codegen/box/functions/fakeDescriptorWithSeveralOverridenOne.kt @@ -0,0 +1,23 @@ +trait Named { + abstract fun getName() : String; +} + +trait MemberDescriptor : Named {} + +trait ClassifierDescriptor : Named {} + +trait ClassDescriptor : MemberDescriptor, ClassifierDescriptor {} + +class ClassDescriptorImpl : ClassDescriptor { + override fun getName(): String { + return "OK" + } +} + +class A(val descriptor : ClassDescriptor) { + val result : String = descriptor.getName() +} + +fun box(): String { + return A(ClassDescriptorImpl()).result +} diff --git a/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt b/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt new file mode 100644 index 00000000000..34789b96480 --- /dev/null +++ b/compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt @@ -0,0 +1,15 @@ +class Test { + + val property:Int + ;{ + fun local():Int { + return 10; + } + property = local(); + } + +} + +fun box(): String { + return if (Test().property == 10) "OK" else "fail" +} diff --git a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java index cf55cdcf6af..279a4872133 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/codegen/generated/BlackBoxCodegenTestGenerated.java @@ -916,6 +916,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/closures"), Pattern.compile("^(.+)\\.kt$"), true); } + @TestMetadata("closureInsideConstrucor.kt") + public void testClosureInsideConstrucor() throws Exception { + doTest("compiler/testData/codegen/box/closures/closureInsideConstrucor.kt"); + } + @TestMetadata("closureWithParameter.kt") public void testClosureWithParameter() throws Exception { doTest("compiler/testData/codegen/box/closures/closureWithParameter.kt"); @@ -1683,6 +1688,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { } @TestMetadata("compiler/testData/codegen/box/functions") + @InnerTestClasses({Functions.LocalFunctions.class}) public static class Functions extends AbstractBlackBoxCodegenTest { public void testAllFilesPresentInFunctions() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions"), Pattern.compile("^(.+)\\.kt$"), true); @@ -1733,6 +1739,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/functions/ea33909.kt"); } + @TestMetadata("fakeDescriptorWithSeveralOverridenOne.kt") + public void testFakeDescriptorWithSeveralOverridenOne() throws Exception { + doTest("compiler/testData/codegen/box/functions/fakeDescriptorWithSeveralOverridenOne.kt"); + } + @TestMetadata("functionExpression.kt") public void testFunctionExpression() throws Exception { doTest("compiler/testData/codegen/box/functions/functionExpression.kt"); @@ -1838,6 +1849,25 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest("compiler/testData/codegen/box/functions/nothisnoclosure.kt"); } + @TestMetadata("compiler/testData/codegen/box/functions/localFunctions") + public static class LocalFunctions extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInLocalFunctions() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("compiler/testData/codegen/box/functions/localFunctions"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("localFunctionInConstructor.kt") + public void testLocalFunctionInConstructor() throws Exception { + doTest("compiler/testData/codegen/box/functions/localFunctions/localFunctionInConstructor.kt"); + } + + } + + public static Test innerSuite() { + TestSuite suite = new TestSuite("Functions"); + suite.addTestSuite(Functions.class); + suite.addTestSuite(LocalFunctions.class); + return suite; + } } @TestMetadata("compiler/testData/codegen/box/innerNested") @@ -3464,7 +3494,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { suite.addTestSuite(ExclExcl.class); suite.addTestSuite(ExtensionFunctions.class); suite.addTestSuite(ExtensionProperties.class); - suite.addTestSuite(Functions.class); + suite.addTest(Functions.innerSuite()); suite.addTestSuite(InnerNested.class); suite.addTest(Instructions.innerSuite()); suite.addTestSuite(Intrinsics.class);