Support sealed class inheritors in the same file

#KT-11573 Fixed
This commit is contained in:
Stanislav Erokhin
2016-05-17 19:23:32 +03:00
parent 26be254fbe
commit 7332032bb6
22 changed files with 343 additions and 72 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* 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.
@@ -34,7 +34,9 @@ import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class PackageCodegen {
private final GenerationState state;
@@ -76,6 +78,12 @@ public class PackageCodegen {
}
}
private void generateClassesAndObjectsInFile(@NotNull List<KtClassOrObject> classOrObjects, @NotNull PackageContext packagePartContext) {
for (KtClassOrObject classOrObject : CodegenUtilKt.sortTopLevelClassesAndPrepareContextForSealedClasses(classOrObjects, packagePartContext, state)) {
generateClassOrObject(classOrObject, packagePartContext);
}
}
private void generateFile(@NotNull KtFile file) {
JvmFileClassInfo fileClassInfo = state.getFileClassesProvider().getFileClassInfo(file);
@@ -88,6 +96,8 @@ public class PackageCodegen {
boolean generatePackagePart = false;
List<KtClassOrObject> classOrObjects = new ArrayList<KtClassOrObject>();
for (KtDeclaration declaration : file.getDeclarations()) {
if (declaration instanceof KtProperty || declaration instanceof KtNamedFunction) {
generatePackagePart = true;
@@ -95,7 +105,7 @@ public class PackageCodegen {
else if (declaration instanceof KtClassOrObject) {
KtClassOrObject classOrObject = (KtClassOrObject) declaration;
if (state.getGenerateDeclaredClassFilter().shouldGenerateClass(classOrObject)) {
generateClassOrObject(classOrObject, packagePartContext);
classOrObjects.add(classOrObject);
}
}
else if (declaration instanceof KtScript) {
@@ -106,6 +116,7 @@ public class PackageCodegen {
}
}
}
generateClassesAndObjectsInFile(classOrObjects, packagePartContext);
if (!generatePackagePart || !state.getGenerateDeclaredClassFilter().shouldGeneratePackagePart(file)) return;
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* 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.
@@ -18,21 +18,27 @@
package org.jetbrains.kotlin.codegen
import org.jetbrains.kotlin.codegen.context.FieldOwnerContext
import org.jetbrains.kotlin.codegen.context.PackageContext
import org.jetbrains.kotlin.codegen.intrinsics.TypeIntrinsics
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature.SpecialSignatureInfo
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtObjectDeclaration
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.ErrorUtils
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.utils.DFS
import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.*
fun generateIsCheck(
v: InstructionAdapter,
@@ -125,4 +131,48 @@ fun populateCompanionBackingFieldNamesToOuterContextIfNeeded(companion: KtObject
}
}
}
// Top level subclasses of a sealed class should be generated before that sealed class,
// so that we'd generate the necessary accessor for its constructor afterwards
fun sortTopLevelClassesAndPrepareContextForSealedClasses(
classOrObjects: List<KtClassOrObject>,
packagePartContext: PackageContext,
state: GenerationState
): List<KtClassOrObject> {
fun prepareContextIfNeeded(descriptor: ClassDescriptor?) {
if (DescriptorUtils.isSealedClass(descriptor)) {
// save context for sealed class
packagePartContext.intoClass(descriptor!!, OwnerKind.IMPLEMENTATION, state)
}
}
// optimization
when (classOrObjects.size) {
0 -> return emptyList()
1 -> {
prepareContextIfNeeded(state.bindingContext.get(BindingContext.CLASS, classOrObjects.first()))
return classOrObjects
}
}
val result = ArrayList<KtClassOrObject>(classOrObjects.size)
val descriptorToPsi = LinkedHashMap<ClassDescriptor, KtClassOrObject>()
for (classOrObject in classOrObjects) {
val descriptor = state.bindingContext.get(BindingContext.CLASS, classOrObject)
if (descriptor == null) {
result.add(classOrObject)
}
else {
prepareContextIfNeeded(descriptor)
descriptorToPsi[descriptor] = classOrObject
}
}
// topologicalOrder(listOf(1, 2, 3)) { emptyList() } = listOf(3, 2, 1). Because of this used keys.reversed().
val sortedDescriptors = DFS.topologicalOrder(descriptorToPsi.keys.reversed()) {
it.typeConstructor.supertypes.map { it.constructor.declarationDescriptor as? ClassDescriptor }.filter { it in descriptorToPsi.keys }
}
sortedDescriptors.mapTo(result) { descriptorToPsi[it]!! }
return result
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* 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.
@@ -274,15 +274,16 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
@NotNull
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
if (descriptor.isCompanionObject()) {
CodegenContext companionContext = this.findChildContext(descriptor);
if (companionContext != null) {
assert companionContext.getContextKind() == kind : "Kinds should be same, but: " +
companionContext.getContextKind() + "!= " + kind;
return (ClassContext) companionContext;
public ClassContext intoClass(@NotNull ClassDescriptor descriptor, @NotNull OwnerKind kind, @NotNull GenerationState state) {
if (shouldAddChild(descriptor)) {
CodegenContext savedContext = this.findChildContext(descriptor);
if (savedContext != null) {
assert savedContext.getContextKind() == kind : "Kinds should be same, but: " +
savedContext.getContextKind() + "!= " + kind;
return (ClassContext) savedContext;
}
}
ClassContext classContext = new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
if (descriptor.getCompanionObjectDescriptor() != null) {
@@ -571,6 +572,17 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this);
}
if (descriptorContext == null && descriptor instanceof ConstructorDescriptor) {
ClassDescriptor classDescriptor = ((ConstructorDescriptor) descriptor).getContainingDeclaration();
if (DescriptorUtils.isSealedClass(classDescriptor)) {
CodegenContext parentContextForClass = findParentContextWithDescriptor(classDescriptor.getContainingDeclaration());
if (parentContextForClass != null) {
//generate super constructor calls for top-level sealed classes from top level child
descriptorContext = parentContextForClass.findChildContext(classDescriptor);
}
}
}
if (descriptorContext == null) {
return descriptor;
}
@@ -630,7 +642,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
private void addChild(@NotNull CodegenContext child) {
if (shouldAddChild(child)) {
if (shouldAddChild(child.contextDescriptor)) {
if (childContexts == null) {
childContexts = new HashMap<DeclarationDescriptor, CodegenContext>();
}
@@ -639,8 +651,8 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
}
protected boolean shouldAddChild(@NotNull CodegenContext child) {
return DescriptorUtils.isCompanionObject(child.contextDescriptor);
private static boolean shouldAddChild(@NotNull DeclarationDescriptor childContextDescriptor) {
return DescriptorUtils.isCompanionObject(childContextDescriptor) || DescriptorUtils.isSealedClass(childContextDescriptor);
}
@Nullable
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* 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.
@@ -16,29 +16,30 @@
package org.jetbrains.kotlin.cfg
import org.jetbrains.kotlin.psi.*
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.checkReservedPrefixWord
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.CompileTimeConstantUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumClass
import org.jetbrains.kotlin.resolve.DescriptorUtils.isEnumEntry
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.isFlexible
import java.util.*
interface WhenMissingCase {
@@ -229,9 +230,8 @@ private object WhenOnSealedExhaustivenessChecker : WhenOnClassExhaustivenessChec
subjectDescriptor: ClassDescriptor?,
nullable: Boolean
): List<WhenMissingCase> {
assert(subjectDescriptor != null) { "isWhenOnSealedClassExhaustive should be called with not-null subject class descriptor" }
assert(subjectDescriptor!!.modality === Modality.SEALED) {
"isWhenOnSealedClassExhaustive should be called with a sealed class descriptor"
assert(DescriptorUtils.isSealedClass(subjectDescriptor)) {
"isWhenOnSealedClassExhaustive should be called with a sealed class descriptor: $subjectDescriptor"
}
val memberClassDescriptors = LinkedHashSet<ClassDescriptor>()
collectNestedSubclasses(subjectDescriptor!!, subjectDescriptor, memberClassDescriptors)
@@ -241,21 +241,27 @@ private object WhenOnSealedExhaustivenessChecker : WhenOnClassExhaustivenessChec
}
override fun isApplicable(subjectType: KotlinType): Boolean {
return TypeUtils.getClassDescriptor(subjectType)?.modality == Modality.SEALED
return DescriptorUtils.isSealedClass(TypeUtils.getClassDescriptor(subjectType))
}
private fun collectNestedSubclasses(
baseDescriptor: ClassDescriptor,
currentDescriptor: ClassDescriptor,
subclasses: MutableSet<ClassDescriptor>) {
for (descriptor in DescriptorUtils.getAllDescriptors(currentDescriptor.unsubstitutedInnerClassesScope)) {
if (descriptor is ClassDescriptor) {
if (DescriptorUtils.isDirectSubclass(descriptor, baseDescriptor)) {
subclasses.add(descriptor)
subclasses: MutableSet<ClassDescriptor>
) {
fun collectSubclasses(scope: MemberScope, collectNested: Boolean) {
for (descriptor in scope.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS)) {
if (descriptor is ClassDescriptor) {
if (DescriptorUtils.isDirectSubclass(descriptor, baseDescriptor)) subclasses.add(descriptor)
if (collectNested) collectNestedSubclasses(baseDescriptor, descriptor, subclasses)
}
collectNestedSubclasses(baseDescriptor, descriptor, subclasses)
}
}
if (currentDescriptor == baseDescriptor && DescriptorUtils.isTopLevelDeclaration(currentDescriptor)) {
collectSubclasses((currentDescriptor.containingDeclaration as PackageFragmentDescriptor).getMemberScope(), collectNested = false)
}
collectSubclasses(currentDescriptor.unsubstitutedInnerClassesScope, collectNested = true)
}
}
@@ -55,6 +55,8 @@ import static org.jetbrains.kotlin.resolve.BindingContext.*;
import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
public class BodyResolver {
private static final boolean ALLOW_TOP_LEVEL_SEALED_INHERITANCE = true;
@NotNull private final AnnotationChecker annotationChecker;
@NotNull private final ExpressionTypingServices expressionTypingServices;
@NotNull private final CallResolver callResolver;
@@ -384,18 +386,26 @@ public class BodyResolver {
@NotNull
private static Set<TypeConstructor> getAllowedFinalSupertypes(
@NotNull ClassDescriptor descriptor,
@NotNull KtClassOrObject jetClass
@NotNull Map<KtTypeReference, KotlinType> supertypes,
@NotNull KtClassOrObject ktClassOrObject
) {
Set<TypeConstructor> parentEnumOrSealed;
if (jetClass instanceof KtEnumEntry) {
Set<TypeConstructor> parentEnumOrSealed = Collections.emptySet();
if (ktClassOrObject instanceof KtEnumEntry) {
parentEnumOrSealed = Collections.singleton(((ClassDescriptor) descriptor.getContainingDeclaration()).getTypeConstructor());
}
else if (ALLOW_TOP_LEVEL_SEALED_INHERITANCE && DescriptorUtils.isTopLevelDeclaration(descriptor)) {
for (KotlinType superType : supertypes.values()) {
ClassifierDescriptor classifierDescriptor = superType.getConstructor().getDeclarationDescriptor();
if (DescriptorUtils.isSealedClass(classifierDescriptor) && DescriptorUtils.isTopLevelDeclaration(classifierDescriptor)) {
parentEnumOrSealed = Collections.singleton(classifierDescriptor.getTypeConstructor());
}
}
}
else {
parentEnumOrSealed = Collections.emptySet();
ClassDescriptor currentDescriptor = descriptor;
while (currentDescriptor.getContainingDeclaration() instanceof ClassDescriptor) {
currentDescriptor = (ClassDescriptor) currentDescriptor.getContainingDeclaration();
if (currentDescriptor.getModality() == Modality.SEALED) {
if (DescriptorUtils.isSealedClass(currentDescriptor)) {
if (parentEnumOrSealed.isEmpty()) {
parentEnumOrSealed = new HashSet<TypeConstructor>();
}
@@ -418,9 +428,9 @@ public class BodyResolver {
private void checkSupertypeList(
@NotNull ClassDescriptor supertypeOwner,
@NotNull Map<KtTypeReference, KotlinType> supertypes,
@NotNull KtClassOrObject jetClass
@NotNull KtClassOrObject ktClassOrObject
) {
Set<TypeConstructor> allowedFinalSupertypes = getAllowedFinalSupertypes(supertypeOwner, jetClass);
Set<TypeConstructor> allowedFinalSupertypes = getAllowedFinalSupertypes(supertypeOwner, supertypes, ktClassOrObject);
Set<TypeConstructor> typeConstructors = Sets.newHashSet();
boolean classAppeared = false;
for (Map.Entry<KtTypeReference, KotlinType> entry : supertypes.entrySet()) {
@@ -458,13 +468,13 @@ public class BodyResolver {
trace.report(INTERFACE_WITH_SUPERCLASS.on(typeReference));
addSupertype = false;
}
else if (jetClass.hasModifier(KtTokens.DATA_KEYWORD)) {
else if (ktClassOrObject.hasModifier(KtTokens.DATA_KEYWORD)) {
trace.report(DATA_CLASS_CANNOT_HAVE_CLASS_SUPERTYPES.on(typeReference));
addSupertype = false;
}
else if (DescriptorUtils.isSubclass(classDescriptor, builtIns.getThrowable()) &&
!supertypeOwner.getDeclaredTypeParameters().isEmpty()) {
trace.report(GENERIC_THROWABLE_SUBCLASS.on(jetClass.getTypeParameterList()));
trace.report(GENERIC_THROWABLE_SUBCLASS.on(ktClassOrObject.getTypeParameterList()));
addSupertype = false;
}
@@ -492,7 +502,7 @@ public class BodyResolver {
}
}
else if (!allowedFinalSupertypes.contains(constructor)) {
if (classDescriptor.getModality() == Modality.SEALED) {
if (DescriptorUtils.isSealedClass(classDescriptor)) {
DeclarationDescriptor containingDescriptor = supertypeOwner.getContainingDeclaration();
while (containingDescriptor != null && containingDescriptor != classDescriptor) {
containingDescriptor = containingDescriptor.getContainingDeclaration();
@@ -20,7 +20,9 @@ import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.Errors.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
@@ -214,7 +216,7 @@ class CallExpressionResolver(
if (DescriptorUtils.isEnumClass(containingDescriptor)) {
context.trace.report(ENUM_CLASS_CONSTRUCTOR_CALL.on(callExpression))
}
if (containingDescriptor is ClassDescriptor && containingDescriptor.modality === Modality.SEALED) {
if (DescriptorUtils.isSealedClass(containingDescriptor)) {
context.trace.report(SEALED_CLASS_CONSTRUCTOR_CALL.on(callExpression))
}
}
@@ -0,0 +1,38 @@
class B : A()
sealed class A() {
constructor(i: Int): this()
class C: A()
}
object T : Y()
class D : A(4)
class E : A {
constructor(i: Int): super(i)
constructor(): super()
}
object S : Z()
sealed class Y : X()
sealed class Z : Y()
sealed class X : A()
class Q : Y()
fun box() : String {
B()
A.C()
D()
E()
E(4)
T
S
Q()
return "OK"
}
@@ -0,0 +1,10 @@
sealed class Base
class Derived: Base() {
class Derived2: <!INVISIBLE_MEMBER, SEALED_SUPERTYPE!>Base<!>()
}
fun test() {
class Local: <!INVISIBLE_MEMBER, SEALED_SUPERTYPE!>Base<!>()
}
@@ -1,5 +1,7 @@
package
public fun test(): kotlin.Unit
public sealed class Base {
private constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
@@ -12,4 +14,11 @@ public final class Derived : Base {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class Derived2 : Base {
public constructor Derived2()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
@@ -1,7 +0,0 @@
sealed class Base {
}
class Derived: <!INVISIBLE_MEMBER, SEALED_SUPERTYPE!>Base<!>() {
}
@@ -0,0 +1,9 @@
class A {
sealed class Base
}
class Derived : <!INVISIBLE_MEMBER, SEALED_SUPERTYPE!>A.Base<!>()
fun test() {
class DerivedLocal : <!INVISIBLE_MEMBER, SEALED_SUPERTYPE!>A.Base<!>()
}
@@ -0,0 +1,24 @@
package
public fun test(): kotlin.Unit
public final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public sealed class Base {
private constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public final class Derived : A.Base {
public constructor Derived()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,22 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
sealed class A {
class B: A() {
class C: A()
}
}
class D: A()
fun test(a: A) {
val nonExhaustive = <!NO_ELSE_IN_WHEN!>when<!> (a) {
is A.B -> "B"
is A.B.C -> "C"
}
val exhaustive = when (a) {
is A.B -> "B"
is A.B.C -> "C"
is D -> "D"
}
}
@@ -0,0 +1,31 @@
package
public fun test(/*0*/ a: A): kotlin.Unit
public sealed class A {
private constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class B : A {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class C : A {
public constructor C()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
}
public final class D : A {
public constructor D()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -15657,6 +15657,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/sealed"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("DerivedTopLevel.kt")
public void testDerivedTopLevel() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sealed/DerivedTopLevel.kt");
doTest(fileName);
}
@TestMetadata("DoubleInner.kt")
public void testDoubleInner() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sealed/DoubleInner.kt");
@@ -15735,9 +15741,9 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("NeverDerived.kt")
public void testNeverDerived() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sealed/NeverDerived.kt");
@TestMetadata("NeverDerivedFromNested.kt")
public void testNeverDerivedFromNested() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sealed/NeverDerivedFromNested.kt");
doTest(fileName);
}
@@ -19584,6 +19590,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("TopLevelSealed.kt")
public void testTopLevelSealed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/TopLevelSealed.kt");
doTest(fileName);
}
@TestMetadata("When.kt")
public void testWhen() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/when/When.kt");
@@ -2902,6 +2902,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("sealedInSameFile.kt")
public void testSealedInSameFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/sealedInSameFile.kt");
doTest(fileName);
}
@TestMetadata("selfcreate.kt")
public void testSelfcreate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/selfcreate.kt");
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
* 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.
@@ -36,12 +36,28 @@ public class Visibilities {
return true;
}
private boolean inSameFile(@NotNull DeclarationDescriptor what, @NotNull DeclarationDescriptor from) {
SourceFile fromContainingFile = DescriptorUtils.getContainingSourceFile(from);
if (fromContainingFile != SourceFile.NO_SOURCE_FILE) {
return fromContainingFile.equals(DescriptorUtils.getContainingSourceFile(what));
}
return false;
}
@Override
public boolean isVisible(@Nullable ReceiverValue receiver, @NotNull DeclarationDescriptorWithVisibility what, @NotNull DeclarationDescriptor from) {
if (DescriptorUtils.isTopLevelDeclaration(what)) {
SourceFile fromContainingFile = DescriptorUtils.getContainingSourceFile(from);
if (fromContainingFile != SourceFile.NO_SOURCE_FILE) {
return fromContainingFile.equals(DescriptorUtils.getContainingSourceFile(what));
return inSameFile(what, from);
}
if (what instanceof ConstructorDescriptor) {
ClassDescriptor classDescriptor = ((ConstructorDescriptor) what).getContainingDeclaration();
if (DescriptorUtils.isSealedClass(classDescriptor)
&& DescriptorUtils.isTopLevelDeclaration(classDescriptor)
&& from instanceof ConstructorDescriptor
&& DescriptorUtils.isTopLevelDeclaration(from.getContainingDeclaration())
&& inSameFile(what, from)) {
return true;
}
}
@@ -129,8 +129,8 @@ public class DescriptorUtils {
return getFqNameFromTopLevelClass(containingDeclaration).child(name);
}
public static boolean isTopLevelDeclaration(@NotNull DeclarationDescriptor descriptor) {
return descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor;
public static boolean isTopLevelDeclaration(@Nullable DeclarationDescriptor descriptor) {
return descriptor != null && descriptor.getContainingDeclaration() instanceof PackageFragmentDescriptor;
}
public static boolean isExtension(@NotNull CallableDescriptor descriptor) {
@@ -276,6 +276,10 @@ public class DescriptorUtils {
return isKindOf(descriptor, ClassKind.OBJECT) && ((ClassDescriptor) descriptor).isCompanionObject();
}
public static boolean isSealedClass(@Nullable DeclarationDescriptor descriptor) {
return isKindOf(descriptor, ClassKind.CLASS) && ((ClassDescriptor) descriptor).getModality() == Modality.SEALED;
}
public static boolean isAnonymousObject(@NotNull DeclarationDescriptor descriptor) {
return isClass(descriptor) && descriptor.getName().equals(SpecialNames.NO_NAME_PROVIDED);
}
@@ -369,7 +373,7 @@ public class DescriptorUtils {
@NotNull
public static Visibility getDefaultConstructorVisibility(@NotNull ClassDescriptor classDescriptor) {
ClassKind classKind = classDescriptor.getKind();
if (classKind == ClassKind.ENUM_CLASS || classKind.isSingleton() || classDescriptor.getModality() == Modality.SEALED) {
if (classKind == ClassKind.ENUM_CLASS || classKind.isSingleton() || isSealedClass(classDescriptor)) {
return Visibilities.PRIVATE;
}
if (isAnonymousObject(classDescriptor)) {
@@ -456,7 +460,7 @@ public class DescriptorUtils {
public static boolean classCanHaveAbstractMembers(@NotNull ClassDescriptor classDescriptor) {
return classDescriptor.getModality() == Modality.ABSTRACT
|| classDescriptor.getModality() == Modality.SEALED
|| isSealedClass(classDescriptor)
|| classDescriptor.getKind() == ClassKind.ENUM_CLASS;
}
@@ -683,6 +683,12 @@ public class ClassesTestGenerated extends AbstractClassesTest {
doTest(fileName);
}
@TestMetadata("sealedInSameFile.kt")
public void testSealedInSameFile() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/sealedInSameFile.kt");
doTest(fileName);
}
@TestMetadata("selfcreate.kt")
public void testSelfcreate() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/classes/selfcreate.kt");
@@ -7,12 +7,12 @@ c 1 0/Ann1
d 0/Ann2
c 0 0/Ann2
c 1 0/Ann2
d 0/A
a org.test.Ann1 2
c 2 0/A
d 0/A$DefaultImpls
d 0/B
a org.test.Ann2 3
c 3 0/B
d 0/C
d 0/D
d 0/C
d 0/B
a org.test.Ann2 2
c 2 0/B
d 0/A
a org.test.Ann1 3
c 3 0/A
d 0/A$DefaultImpls
@@ -4,8 +4,8 @@ a java.lang.annotation.Inherited 0
c 0 0/Ann
a java.lang.annotation.Retention 1
c 1 0/Ann
d 0/B
d 0/A
a org.test.Ann 2
c 2 0/A
d 0/A$DefaultImpls
d 0/B
@@ -2,7 +2,7 @@ a java.lang.annotation.Retention 0
p org.test 0
c 0 0/Ann
a org.test.Ann 1
m 1 0/Parent overridenWithoutAnnotation
m 1 0/Parent notOverriden
m 1 0/Child overridenWithAnnotation
m 1 0/Child childMethod
m 1 0/Parent overridenWithoutAnnotation
m 1 0/Parent notOverriden