diff options
author | Kamil Doległo <kamilok1965@interia.pl> | 2020-10-15 18:11:17 +0200 |
---|---|---|
committer | Kamil Doległo <kamilok1965@interia.pl> | 2020-10-15 18:11:17 +0200 |
commit | c5a31b47ef182e4de3ec58d5ce5624e65fe11015 (patch) | |
tree | 9df60d122c56ea2ea2d918584f47051ef533622e /plugins | |
parent | 7f948864077388e10ba3608b0d5e1d9a4ea0f4d9 (diff) | |
download | dokka-c5a31b47ef182e4de3ec58d5ce5624e65fe11015.tar.gz dokka-c5a31b47ef182e4de3ec58d5ce5624e65fe11015.tar.bz2 dokka-c5a31b47ef182e4de3ec58d5ce5624e65fe11015.zip |
Fix class cast exception when creating the ancestry tree
Diffstat (limited to 'plugins')
-rw-r--r-- | plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt | 50 | ||||
-rw-r--r-- | plugins/base/src/test/kotlin/model/ClassesTest.kt | 62 |
2 files changed, 80 insertions, 32 deletions
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt index 1a643624..8db3aa43 100644 --- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt @@ -241,7 +241,8 @@ private class DokkaDescriptorVisitor( val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) } val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } - val constructors = async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } } + val constructors = + async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } } val entries = async { descriptorsWithKind.enumEntries.visitEnumEntries(driWithPlatform) } DEnum( @@ -312,7 +313,8 @@ private class DokkaDescriptorVisitor( val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) } val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) } val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } } - val constructors = async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } } + val constructors = + async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } } DAnnotation( dri = driWithPlatform.dri, @@ -391,7 +393,10 @@ private class DokkaDescriptorVisitor( } } - private suspend fun visitPropertyDescriptor(originalDescriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): DProperty { + private suspend fun visitPropertyDescriptor( + originalDescriptor: PropertyDescriptor, + parent: DRIWithPlatformInfo + ): DProperty { val dri = parent.dri.copy(callable = Callable.from(originalDescriptor)) val descriptor = originalDescriptor.getConcreteDescriptor() val isExpect = descriptor.isExpect @@ -439,7 +444,10 @@ private class DokkaDescriptorVisitor( else overriddenDescriptors.first().createDRI(DRI.from(this)) - private suspend fun visitFunctionDescriptor(originalDescriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): DFunction { + private suspend fun visitFunctionDescriptor( + originalDescriptor: FunctionDescriptor, + parent: DRIWithPlatformInfo + ): DFunction { val (dri, inheritedFrom) = originalDescriptor.createDRI() val descriptor = originalDescriptor.getConcreteDescriptor() val isExpect = descriptor.isExpect @@ -630,7 +638,8 @@ private class DokkaDescriptorVisitor( generics = generics.await(), extra = PropertyContainer.withAll( descriptor.getAnnotations().toSourceSetDependent().toAnnotations(), - info.exceptionsInSupertypes()?.takeIf { it.isNotEmpty() }?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }, + info.exceptionsInSupertypes()?.takeIf { it.isNotEmpty() } + ?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }, ) ) } @@ -666,14 +675,16 @@ private class DokkaDescriptorVisitor( class EnumEntryDescriptor - val groupedDescriptors = descriptors.groupBy { when { - it is FunctionDescriptor -> FunctionDescriptor::class - it is PropertyDescriptor -> PropertyDescriptor::class - it is ClassDescriptor && it.kind != ClassKind.ENUM_ENTRY -> ClassDescriptor::class - it is TypeAliasDescriptor -> TypeAliasDescriptor::class - it is ClassDescriptor && it.kind == ClassKind.ENUM_ENTRY -> EnumEntryDescriptor::class - else -> IllegalStateException::class - } } + val groupedDescriptors = descriptors.groupBy { + when { + it is FunctionDescriptor -> FunctionDescriptor::class + it is PropertyDescriptor -> PropertyDescriptor::class + it is ClassDescriptor && it.kind != ClassKind.ENUM_ENTRY -> ClassDescriptor::class + it is TypeAliasDescriptor -> TypeAliasDescriptor::class + it is ClassDescriptor && it.kind == ClassKind.ENUM_ENTRY -> EnumEntryDescriptor::class + else -> IllegalStateException::class + } + } return DescriptorsWithKind( (groupedDescriptors[FunctionDescriptor::class] ?: emptyList()) as List<FunctionDescriptor>, @@ -716,9 +727,13 @@ private class DokkaDescriptorVisitor( ): Set<AncestryLevel> { if (supertypes.isEmpty()) return ancestryInformation - val (interfaces, superclass) = supertypes.partition { - (it.constructor.declarationDescriptor as ClassDescriptor).kind == ClassKind.INTERFACE - } + val (interfaces, superclass) = supertypes + .partition { + val declaration = it.constructor.declarationDescriptor + val descriptor = declaration as? ClassDescriptor + ?: (declaration as? TypeAliasDescriptor)?.underlyingType?.constructor?.declarationDescriptor as? ClassDescriptor + descriptor?.kind == ClassKind.INTERFACE + } val updated = coroutineScope { ancestryInformation + AncestryLevel( @@ -758,7 +773,8 @@ private class DokkaDescriptorVisitor( private suspend fun org.jetbrains.kotlin.descriptors.annotations.Annotations.getPresentableName(): String? = map { it.toAnnotation() }.singleOrNull { it.dri.classNames == "ParameterName" }?.params?.get("name") - .safeAs<StringValue>()?.value?.drop(1)?.dropLast(1) // Dropping enclosing doublequotes because we don't want to have it in our custom signature serializer + .safeAs<StringValue>()?.value?.drop(1) + ?.dropLast(1) // Dropping enclosing doublequotes because we don't want to have it in our custom signature serializer private suspend fun KotlinType.toBound(): Bound = when (this) { diff --git a/plugins/base/src/test/kotlin/model/ClassesTest.kt b/plugins/base/src/test/kotlin/model/ClassesTest.kt index bb7bac2d..b6787126 100644 --- a/plugins/base/src/test/kotlin/model/ClassesTest.kt +++ b/plugins/base/src/test/kotlin/model/ClassesTest.kt @@ -460,32 +460,40 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class } } - @Test fun genericAnnotationClass() { + @Test + fun genericAnnotationClass() { inlineModelTest( """annotation class Foo<A,B,C,D:Number>() {}""" ) { - with((this / "classes" / "Foo").cast<DAnnotation>()){ - generics.map { it.name to it.bounds.first().name } equals listOf("A" to "Any", "B" to "Any", "C" to "Any", "D" to "Number") + with((this / "classes" / "Foo").cast<DAnnotation>()) { + generics.map { it.name to it.bounds.first().name } equals listOf( + "A" to "Any", + "B" to "Any", + "C" to "Any", + "D" to "Number" + ) } } } - @Test fun nestedGenericClasses(){ + @Test + fun nestedGenericClasses() { inlineModelTest( """ |class Outer<OUTER> { | inner class Inner<INNER, T : OUTER> { } |} """.trimMargin() - ){ - with((this / "classes" / "Outer").cast<DClass>()){ + ) { + with((this / "classes" / "Outer").cast<DClass>()) { val inner = classlikes.single().cast<DClass>() inner.generics.map { it.name to it.bounds.first().name } equals listOf("INNER" to "Any", "T" to "OUTER") } } } - @Test fun allImplementedInterfaces() { + @Test + fun allImplementedInterfaces() { inlineModelTest( """ | interface Highest { } @@ -494,14 +502,16 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class | interface LowerImplInterface: Lower { } | class Tested : HighestImpl(), LowerImplInterface { } """.trimIndent() - ){ - with((this / "classes" / "Tested").cast<DClass>()){ - extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.dri.sureClassNames }?.sorted() equals listOf("Highest", "Lower", "LowerImplInterface").sorted() + ) { + with((this / "classes" / "Tested").cast<DClass>()) { + extra[ImplementedInterfaces]?.interfaces?.entries?.single()?.value?.map { it.dri.sureClassNames } + ?.sorted() equals listOf("Highest", "Lower", "LowerImplInterface").sorted() } } } - @Test fun multipleClassInheritance() { + @Test + fun multipleClassInheritance() { inlineModelTest( """ | open class A { } @@ -515,7 +525,8 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class } } - @Test fun multipleClassInheritanceWithInterface(){ + @Test + fun multipleClassInheritanceWithInterface() { inlineModelTest( """ | open class A { } @@ -524,10 +535,31 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class | interface Y : X { } | class Tested : B(), Y { } """.trimIndent() - ){ + ) { with((this / "classes" / "Tested").cast<DClass>()) { - supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames to it.kind }.sortedBy { it.first } equals listOf("B" to KotlinClassKindTypes.CLASS, "Y" to KotlinClassKindTypes.INTERFACE) + supertypes.entries.single().value.map { it.typeConstructor.dri.sureClassNames to it.kind } + .sortedBy { it.first } equals listOf( + "B" to KotlinClassKindTypes.CLASS, + "Y" to KotlinClassKindTypes.INTERFACE + ) + } + } + } + + @Test + fun doublyTypealiasedException() { + inlineModelTest( + """ + | typealias B = RuntimeException + | typealias A = B + """.trimMargin() + ) { + with((this / "classes" / "A").cast<DTypeAlias>()) { + extra[ExceptionInSupertypes].assertNotNull("Typealias A should have ExceptionInSupertypes in its extra field") + } + with((this / "classes" / "B").cast<DTypeAlias>()) { + extra[ExceptionInSupertypes].assertNotNull("Typealias B should have ExceptionInSupertypes in its extra field") } } } -}
\ No newline at end of file +} |