Fix visibility flags for lambda classes in InnerClasses attribute

This commit is contained in:
Alexander Udalov
2016-02-18 20:56:44 +03:00
parent 343735e36c
commit 36de3008e3
11 changed files with 102 additions and 18 deletions
@@ -255,7 +255,10 @@ public class AsmUtil {
For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor) For other cases use getVisibilityAccessFlag(MemberDescriptor descriptor)
Classes in byte code should be public or package private Classes in byte code should be public or package private
*/ */
public static int getVisibilityAccessFlagForClass(ClassDescriptor descriptor) { public static int getVisibilityAccessFlagForClass(@NotNull ClassDescriptor descriptor) {
if (descriptor instanceof SyntheticClassDescriptorForLambda) {
return getVisibilityAccessFlagForAnonymous(descriptor);
}
if (descriptor.getVisibility() == Visibilities.PUBLIC || if (descriptor.getVisibility() == Visibilities.PUBLIC ||
// TODO: should be package private, but for now Kotlin's reflection can't access members of such classes // TODO: should be package private, but for now Kotlin's reflection can't access members of such classes
descriptor.getVisibility() == Visibilities.LOCAL || descriptor.getVisibility() == Visibilities.LOCAL ||
@@ -265,12 +268,17 @@ public class AsmUtil {
return NO_FLAG_PACKAGE_PRIVATE; return NO_FLAG_PACKAGE_PRIVATE;
} }
public static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) { private static int getVisibilityAccessFlagForAnonymous(@NotNull ClassDescriptor descriptor) {
return InlineUtil.isInlineOrContainingInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE; return InlineUtil.isInlineOrContainingInline(descriptor.getContainingDeclaration()) ? ACC_PUBLIC : NO_FLAG_PACKAGE_PRIVATE;
} }
public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) { public static int calculateInnerClassAccessFlags(@NotNull ClassDescriptor innerClass) {
int visibility = (innerClass.getVisibility() == Visibilities.LOCAL) ? ACC_PUBLIC : getVisibilityAccessFlag(innerClass); int visibility =
innerClass instanceof SyntheticClassDescriptorForLambda
? getVisibilityAccessFlagForAnonymous(innerClass)
: innerClass.getVisibility() == Visibilities.LOCAL
? ACC_PUBLIC
: getVisibilityAccessFlag(innerClass);
return visibility | return visibility |
innerAccessFlagsForModalityAndKind(innerClass) | innerAccessFlagsForModalityAndKind(innerClass) |
(innerClass.isInner() ? 0 : ACC_STATIC); (innerClass.isInner() ? 0 : ACC_STATIC);
@@ -126,7 +126,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
this.asmType = typeMapper.mapClass(classDescriptor); this.asmType = typeMapper.mapClass(classDescriptor);
visibilityFlag = AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor); visibilityFlag = AsmUtil.getVisibilityAccessFlagForClass(classDescriptor);
} }
@Override @Override
@@ -66,7 +66,7 @@ class PropertyReferenceCodegen(
v.defineClass( v.defineClass(
element, element,
V1_6, V1_6,
ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor), ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForClass(classDescriptor),
asmType.internalName, asmType.internalName,
null, null,
superAsmType.internalName, superAsmType.internalName,
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2016 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.kotlin.codegen
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.source.toSourceElement
import org.jetbrains.kotlin.types.KotlinType
class SyntheticClassDescriptorForLambda(
containingDeclaration: DeclarationDescriptor,
name: Name,
supertypes: Collection<KotlinType>,
element: KtElement
) : ClassDescriptorImpl(containingDeclaration, name, Modality.FINAL, ClassKind.CLASS, supertypes, element.toSourceElement()) {
init {
initialize(MemberScope.Empty, emptySet(), null)
}
}
@@ -24,10 +24,7 @@ import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cfg.WhenChecker; import org.jetbrains.kotlin.cfg.WhenChecker;
import org.jetbrains.kotlin.codegen.AsmUtil; import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.JvmRuntimeTypes;
import org.jetbrains.kotlin.codegen.SamCodegenUtil;
import org.jetbrains.kotlin.codegen.SamType;
import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil; import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping; import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
@@ -94,15 +91,12 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
@NotNull String name @NotNull String name
) { ) {
String simpleName = name.substring(name.lastIndexOf('/') + 1); String simpleName = name.substring(name.lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl( ClassDescriptor classDescriptor = new SyntheticClassDescriptorForLambda(
correctContainerForLambda(callableDescriptor, element), correctContainerForLambda(callableDescriptor, element),
Name.special("<closure-" + simpleName + ">"), Name.special("<closure-" + simpleName + ">"),
Modality.FINAL,
ClassKind.CLASS,
supertypes, supertypes,
KotlinSourceElementKt.toSourceElement(element) element
); );
classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.<ConstructorDescriptor>emptySet(), null);
bindingTrace.record(CLASS_FOR_CALLABLE, callableDescriptor, classDescriptor); bindingTrace.record(CLASS_FOR_CALLABLE, callableDescriptor, classDescriptor);
return classDescriptor; return classDescriptor;
@@ -0,0 +1,4 @@
class A {
fun foo() = fun() {}
fun bar() = {}
}
@@ -0,0 +1,7 @@
class Foo {
inline fun foo() = { }
}
// TESTED_OBJECT_KIND: class
// TESTED_OBJECTS: Foo$foo$1
// FLAGS: ACC_PUBLIC, ACC_FINAL, ACC_SUPER
+7
View File
@@ -0,0 +1,7 @@
class Foo {
fun foo() = { }
}
// TESTED_OBJECT_KIND: class
// TESTED_OBJECTS: Foo$foo$1
// FLAGS: ACC_FINAL, ACC_SUPER
@@ -103,6 +103,15 @@ public class InnerClassInfoGenTest extends CodegenTestCase {
checkAccess("A", "PublicClass", ACC_PUBLIC); checkAccess("A", "PublicClass", ACC_PUBLIC);
} }
public void testLambdaClassFlags() {
InnerClassAttribute foo = new InnerClassAttribute("A$foo$1", null, null, ACC_STATIC | ACC_FINAL);
InnerClassAttribute bar = new InnerClassAttribute("A$bar$1", null, null, ACC_STATIC | ACC_FINAL);
extractAndCompareInnerClasses("A", foo, bar);
extractAndCompareInnerClasses("A$foo$1", foo);
extractAndCompareInnerClasses("A$bar$1", bar);
}
private void checkAccess(@NotNull String outerName, @NotNull final String innerName, int accessFlags) { private void checkAccess(@NotNull String outerName, @NotNull final String innerName, int accessFlags) {
@@ -644,6 +644,27 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
} }
} }
@TestMetadata("compiler/testData/writeFlags/lambda")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Lambda extends AbstractWriteFlagsTest {
public void testAllFilesPresentInLambda() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/lambda"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("lambdaInInlineFunction.kt")
public void testLambdaInInlineFunction() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/lambda/lambdaInInlineFunction.kt");
doTest(fileName);
}
@TestMetadata("simpleLambda.kt")
public void testSimpleLambda() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/lambda/simpleLambda.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/writeFlags/lateinit") @TestMetadata("compiler/testData/writeFlags/lateinit")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -81,10 +81,6 @@ public class ClassDescriptorImpl extends ClassDescriptorBase {
this.primaryConstructor = primaryConstructor; this.primaryConstructor = primaryConstructor;
} }
public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) {
this.primaryConstructor = primaryConstructor;
}
@NotNull @NotNull
@Override @Override
public Annotations getAnnotations() { public Annotations getAnnotations() {