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)
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 ||
// TODO: should be package private, but for now Kotlin's reflection can't access members of such classes
descriptor.getVisibility() == Visibilities.LOCAL ||
@@ -265,12 +268,17 @@ public class AsmUtil {
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;
}
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 |
innerAccessFlagsForModalityAndKind(innerClass) |
(innerClass.isInner() ? 0 : ACC_STATIC);
@@ -126,7 +126,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
this.asmType = typeMapper.mapClass(classDescriptor);
visibilityFlag = AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor);
visibilityFlag = AsmUtil.getVisibilityAccessFlagForClass(classDescriptor);
}
@Override
@@ -66,7 +66,7 @@ class PropertyReferenceCodegen(
v.defineClass(
element,
V1_6,
ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForAnonymous(classDescriptor),
ACC_FINAL or ACC_SUPER or AsmUtil.getVisibilityAccessFlagForClass(classDescriptor),
asmType.internalName,
null,
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.Nullable;
import org.jetbrains.kotlin.cfg.WhenChecker;
import org.jetbrains.kotlin.codegen.AsmUtil;
import org.jetbrains.kotlin.codegen.JvmRuntimeTypes;
import org.jetbrains.kotlin.codegen.SamCodegenUtil;
import org.jetbrains.kotlin.codegen.SamType;
import org.jetbrains.kotlin.codegen.*;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenUtil;
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
@@ -94,15 +91,12 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
@NotNull String name
) {
String simpleName = name.substring(name.lastIndexOf('/') + 1);
ClassDescriptorImpl classDescriptor = new ClassDescriptorImpl(
ClassDescriptor classDescriptor = new SyntheticClassDescriptorForLambda(
correctContainerForLambda(callableDescriptor, element),
Name.special("<closure-" + simpleName + ">"),
Modality.FINAL,
ClassKind.CLASS,
supertypes,
KotlinSourceElementKt.toSourceElement(element)
element
);
classDescriptor.initialize(MemberScope.Empty.INSTANCE, Collections.<ConstructorDescriptor>emptySet(), null);
bindingTrace.record(CLASS_FOR_CALLABLE, callableDescriptor, 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);
}
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) {
@@ -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")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -81,10 +81,6 @@ public class ClassDescriptorImpl extends ClassDescriptorBase {
this.primaryConstructor = primaryConstructor;
}
public void setPrimaryConstructor(@NotNull ConstructorDescriptor primaryConstructor) {
this.primaryConstructor = primaryConstructor;
}
@NotNull
@Override
public Annotations getAnnotations() {