Properly capture local functions

Local functions in local classed wasn't captured properly
This commit is contained in:
Mikhael Bogdanov
2013-03-26 20:15:06 +04:00
parent 8f6c9d73b1
commit ad4eeb3f8a
10 changed files with 94 additions and 21 deletions
@@ -255,7 +255,7 @@ public class ClosureCodegen extends GenerationStateAware {
: typeMapper.mapType((VariableDescriptor) descriptor); : typeMapper.mapType((VariableDescriptor) descriptor);
args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName())); args.add(FieldInfo.createForHiddenField(ownerType, type, "$" + descriptor.getName().getName()));
} }
else if (isLocalNamedFun(state.getBindingContext(), descriptor)) { else if (isLocalNamedFun(descriptor)) {
Type type = Type type =
classNameForAnonymousClass(bindingContext, classNameForAnonymousClass(bindingContext,
(JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor)) (JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, descriptor))
@@ -51,7 +51,7 @@ import java.util.*;
import static org.jetbrains.asm4.Opcodes.*; import static org.jetbrains.asm4.Opcodes.*;
import static org.jetbrains.jet.codegen.AsmUtil.*; import static org.jetbrains.jet.codegen.AsmUtil.*;
import static org.jetbrains.jet.codegen.CodegenUtil.*; 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.callableDescriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration;
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE; import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
@@ -152,7 +152,7 @@ public class FunctionCodegen extends GenerationStateAware {
if (expectedThisObject != null) { if (expectedThisObject != null) {
thisType = typeMapper.mapType(expectedThisObject.getType()); 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()); thisType = typeMapper.mapType(context.getThisDescriptor());
} }
else { else {
@@ -1233,7 +1233,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
} }
} }
constructorContext.lookupInContext(descriptor, null, state, true); constructorContext.lookupInContext(descriptor, null, state, true);
} else if (descriptor instanceof CallableMemberDescriptor) { } else if (isLocalNamedFun(descriptor)) {
MutableClassDescriptor classDescriptor = MutableClassDescriptor classDescriptor =
(MutableClassDescriptor) constructorContext.getParentContext().getContextDescriptor(); (MutableClassDescriptor) constructorContext.getParentContext().getContextDescriptor();
@@ -295,19 +295,10 @@ public class CodegenBinding {
return false; return false;
} }
public static boolean isLocalFun(BindingContext bindingContext, DeclarationDescriptor fd) { public static boolean isLocalNamedFun(DeclarationDescriptor fd) {
PsiElement psiElement = descriptorToDeclaration(bindingContext, fd); if (fd instanceof FunctionDescriptor) {
if (psiElement instanceof JetNamedFunction && psiElement.getParent() instanceof JetBlockExpression) { FunctionDescriptor descriptor = (FunctionDescriptor) fd;
return true; return descriptor.getVisibility() == Visibilities.LOCAL && !descriptor.getName().isSpecial();
}
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;
} }
return false; return false;
} }
@@ -72,7 +72,7 @@ public interface LocalLookup {
LOCAL_NAMED_FUNCTION { LOCAL_NAMED_FUNCTION {
@Override @Override
public boolean isCase(DeclarationDescriptor d, GenerationState state) { public boolean isCase(DeclarationDescriptor d, GenerationState state) {
return isLocalNamedFun(state.getBindingContext(), d); return isLocalNamedFun(d);
} }
@Override @Override
@@ -85,7 +85,7 @@ public interface LocalLookup {
) { ) {
FunctionDescriptor vd = (FunctionDescriptor) d; FunctionDescriptor vd = (FunctionDescriptor) d;
boolean idx = localLookup.lookupLocal(vd); boolean idx = localLookup != null && localLookup.lookupLocal(vd);
if (!idx) return null; if (!idx) return null;
JetElement expression = (JetElement) callableDescriptorToDeclaration(state.getBindingContext(), vd); JetElement expression = (JetElement) callableDescriptorToDeclaration(state.getBindingContext(), vd);
@@ -816,7 +816,7 @@ public class JetTypeMapper extends BindingTraceAware {
signatureWriter.writeAsmType(sharedVarType, false); signatureWriter.writeAsmType(sharedVarType, false);
signatureWriter.writeParameterTypeEnd(); signatureWriter.writeParameterTypeEnd();
} }
else if (isLocalNamedFun(bindingContext, variableDescriptor)) { else if (isLocalNamedFun(variableDescriptor)) {
Type type = classNameForAnonymousClass( Type type = classNameForAnonymousClass(
bindingContext, bindingContext,
(JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, variableDescriptor) (JetElement) BindingContextUtils.descriptorToDeclaration(bindingContext, variableDescriptor)
@@ -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;
}
@@ -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
}
@@ -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"
}
@@ -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); 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") @TestMetadata("closureWithParameter.kt")
public void testClosureWithParameter() throws Exception { public void testClosureWithParameter() throws Exception {
doTest("compiler/testData/codegen/box/closures/closureWithParameter.kt"); doTest("compiler/testData/codegen/box/closures/closureWithParameter.kt");
@@ -1683,6 +1688,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
} }
@TestMetadata("compiler/testData/codegen/box/functions") @TestMetadata("compiler/testData/codegen/box/functions")
@InnerTestClasses({Functions.LocalFunctions.class})
public static class Functions extends AbstractBlackBoxCodegenTest { public static class Functions extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInFunctions() throws Exception { 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); 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"); 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") @TestMetadata("functionExpression.kt")
public void testFunctionExpression() throws Exception { public void testFunctionExpression() throws Exception {
doTest("compiler/testData/codegen/box/functions/functionExpression.kt"); 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"); 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") @TestMetadata("compiler/testData/codegen/box/innerNested")
@@ -3464,7 +3494,7 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
suite.addTestSuite(ExclExcl.class); suite.addTestSuite(ExclExcl.class);
suite.addTestSuite(ExtensionFunctions.class); suite.addTestSuite(ExtensionFunctions.class);
suite.addTestSuite(ExtensionProperties.class); suite.addTestSuite(ExtensionProperties.class);
suite.addTestSuite(Functions.class); suite.addTest(Functions.innerSuite());
suite.addTestSuite(InnerNested.class); suite.addTestSuite(InnerNested.class);
suite.addTest(Instructions.innerSuite()); suite.addTest(Instructions.innerSuite());
suite.addTestSuite(Intrinsics.class); suite.addTestSuite(Intrinsics.class);