Fix visibility flags for lambda classes in InnerClasses attribute
This commit is contained in:
@@ -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,
|
||||
|
||||
+38
@@ -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)
|
||||
}
|
||||
}
|
||||
+3
-9
@@ -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
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user