diff options
author | Marcin Aman <maman@virtuslab.com> | 2020-05-07 17:10:10 +0200 |
---|---|---|
committer | Paweł Marks <Kordyjan@users.noreply.github.com> | 2020-05-19 13:47:03 +0200 |
commit | 3aeb65472be150a6098f2fac17dbdf0bb2a40013 (patch) | |
tree | 03540fe12ce6b139fbb7658a2d57d0e97023721c | |
parent | e9d7fc75b46bb44f2c946b8cbb0636deb71e20dc (diff) | |
download | dokka-3aeb65472be150a6098f2fac17dbdf0bb2a40013.tar.gz dokka-3aeb65472be150a6098f2fac17dbdf0bb2a40013.tar.bz2 dokka-3aeb65472be150a6098f2fac17dbdf0bb2a40013.zip |
Missing generics on class. Add generics to annotation #834
13 files changed, 271 insertions, 47 deletions
diff --git a/core/src/main/kotlin/links/DRI.kt b/core/src/main/kotlin/links/DRI.kt index 3d9012ec..1c823d92 100644 --- a/core/src/main/kotlin/links/DRI.kt +++ b/core/src/main/kotlin/links/DRI.kt @@ -1,9 +1,6 @@ package org.jetbrains.dokka.links -import com.intellij.psi.PsiClass -import com.intellij.psi.PsiElement -import com.intellij.psi.PsiMethod -import com.intellij.psi.PsiParameter +import com.intellij.psi.* import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -20,17 +17,15 @@ data class DRI( val packageName: String? = null, val classNames: String? = null, val callable: Callable? = null, - val target: Int? = null, - val genericTarget: Int? = null, + val target: DriTarget = PointingToDeclaration, val extra: String? = null ) { override fun toString(): String = - "${packageName.orEmpty()}/${classNames.orEmpty()}/${callable?.name.orEmpty()}/${callable?.signature().orEmpty()}/${target?.toString().orEmpty()}/${extra.orEmpty()}" + "${packageName.orEmpty()}/${classNames.orEmpty()}/${callable?.name.orEmpty()}/${callable?.signature().orEmpty()}/$target/${extra.orEmpty()}" companion object { fun from(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.run { val callable = firstIsInstanceOrNull<CallableDescriptor>() - val params = callable?.let { listOfNotNull(it.extensionReceiverParameter) + it.valueParameters }.orEmpty() DRI( firstIsInstanceOrNull<PackageFragmentDescriptor>()?.fqName?.asString(), (filterIsInstance<ClassDescriptor>() + filterIsInstance<TypeAliasDescriptor>()).toList() @@ -38,20 +33,18 @@ data class DRI( ?.asReversed() ?.joinToString(separator = ".") { it.name.asString() }, callable?.let { Callable.from(it) }, - firstIsInstanceOrNull<ParameterDescriptor>()?.let { params.indexOf(it) }, - null + DriTarget.from(descriptor) ) } fun from(psi: PsiElement) = psi.parentsWithSelf.run { val callable = firstIsInstanceOrNull<PsiMethod>() - val params = (callable?.parameterList?.parameters).orEmpty() val classes = filterIsInstance<PsiClass>().toList() DRI( classes.lastOrNull()?.qualifiedName?.substringBeforeLast('.', ""), classes.toList().takeIf { it.isNotEmpty() }?.asReversed()?.mapNotNull { it.name }?.joinToString("."), callable?.let { Callable.from(it) }, - firstIsInstanceOrNull<PsiParameter>()?.let { params.indexOf(it) } + DriTarget.from(psi) ) } val topLevel = DRI() @@ -63,11 +56,12 @@ val DriOfAny = DRI("kotlin", "Any") fun DRI.withClass(name: String) = copy(classNames = if (classNames.isNullOrBlank()) name else "$classNames.$name") +fun DRI.withTargetToDeclaration() = copy(target = PointingToDeclaration) + val DRI.parent: DRI get() = when { extra != null -> copy(extra = null) - genericTarget != null -> copy(genericTarget = null) - target != null -> copy(target = null) + target != PointingToDeclaration -> copy(target = PointingToDeclaration) callable != null -> copy(callable = null) classNames != null -> copy(classNames = classNames.substringBeforeLast(".", "").takeIf { it.isNotBlank() }) else -> DRI.topLevel @@ -167,8 +161,53 @@ object StarProjection : TypeReference() { override fun toString() = "*" } -private operator fun <T> List<T>.component6(): T = get(5) - private val KotlinType.constructorName get() = constructor.declarationDescriptor?.fqNameSafe?.asString() +sealed class DriTarget { + override fun toString(): String = this.javaClass.simpleName + + companion object { + fun from(descriptor: DeclarationDescriptor): DriTarget = descriptor.parentsWithSelf.run { + return when(descriptor){ + is TypeParameterDescriptor -> PointingToGenericParameters(descriptor.index) + else -> { + val callable = firstIsInstanceOrNull<CallableDescriptor>() + val params = callable?.let { listOfNotNull(it.extensionReceiverParameter) + it.valueParameters }.orEmpty() + val parameterDescriptor = firstIsInstanceOrNull<ParameterDescriptor>() + + parameterDescriptor?.let { PointingToCallableParameters(params.indexOf(it)) } + ?: PointingToDeclaration + } + } + } + + fun from(psi: PsiElement): DriTarget = psi.parentsWithSelf.run { + return when(psi) { + is PsiTypeParameter -> PointingToGenericParameters(psi.index) + else -> firstIsInstanceOrNull<PsiParameter>()?.let { + val callable = firstIsInstanceOrNull<PsiMethod>() + val params = (callable?.parameterList?.parameters).orEmpty() + PointingToCallableParameters(params.indexOf(it)) + } ?: PointingToDeclaration + } + } + } +} + +data class PointingToGenericParameters(val parameterIndex: Int) : DriTarget() { + override fun toString(): String = "PointingToGenericParameters($parameterIndex)" +} + +object PointingToDeclaration: DriTarget() + +data class PointingToCallableParameters(val parameterIndex: Int): DriTarget(){ + override fun toString(): String = "PointingToCallableParameters($parameterIndex)" +} + +fun DriTarget.nextTarget(): DriTarget = when(this){ + is PointingToGenericParameters -> PointingToGenericParameters(this.parameterIndex+1) + is PointingToCallableParameters -> PointingToCallableParameters(this.parameterIndex+1) + else -> this + } + diff --git a/core/src/main/kotlin/model/Documentable.kt b/core/src/main/kotlin/model/Documentable.kt index 85487725..9f17638c 100644 --- a/core/src/main/kotlin/model/Documentable.kt +++ b/core/src/main/kotlin/model/Documentable.kt @@ -263,9 +263,10 @@ data class DAnnotation( override val visibility: SourceSetDependent<Visibility>, override val companion: DObject?, override val constructors: List<DFunction>, + override val generics: List<DTypeParameter>, override val sourceSets: List<SourceSetData>, override val extra: PropertyContainer<DAnnotation> = PropertyContainer.empty() -) : DClasslike(), WithCompanion, WithConstructors, WithExtraProperties<DAnnotation> { +) : DClasslike(), WithCompanion, WithConstructors, WithExtraProperties<DAnnotation>, WithGenerics { override val children: List<Documentable> get() = (functions + properties + classlikes + constructors) as List<Documentable> @@ -344,7 +345,7 @@ data class DTypeAlias( sealed class Projection sealed class Bound : Projection() -data class OtherParameter(val name: String) : Bound() +data class OtherParameter(val declarationDRI: DRI, val name: String) : Bound() object Star : Projection() data class TypeConstructor( val dri: DRI, diff --git a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt index 3836f45d..617af959 100644 --- a/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt +++ b/plugins/base/src/main/kotlin/signatures/KotlinSignatureProvider.kt @@ -2,11 +2,10 @@ package org.jetbrains.dokka.base.signatures import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter import org.jetbrains.dokka.base.translators.documentables.PageContentBuilder -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.DriOfAny -import org.jetbrains.dokka.links.DriOfUnit -import org.jetbrains.dokka.links.sureClassNames +import org.jetbrains.dokka.links.* import org.jetbrains.dokka.model.* +import org.jetbrains.dokka.model.Nullable +import org.jetbrains.dokka.model.TypeConstructor import org.jetbrains.dokka.model.properties.WithExtraProperties import org.jetbrains.dokka.pages.ContentKind import org.jetbrains.dokka.pages.ContentNode @@ -71,6 +70,11 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog is DAnnotation -> text("annotation class ") } link(c.name!!, c.dri) + if(c is WithGenerics){ + list(c.generics, prefix = "<", suffix = "> ") { + +buildSignature(it) + } + } if (c is DClass) { val pConstructor = c.constructors.singleOrNull { it.extra[PrimaryConstructorExtra] != null } list(pConstructor?.parameters.orEmpty(), "(", ")", ",", pConstructor?.sourceSets.orEmpty().toSet()) { @@ -158,7 +162,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog } private fun signature(t: DTypeParameter) = contentBuilder.contentFor(t) { - link(t.name, t.dri) + link(t.name, t.dri.withTargetToDeclaration()) list(t.bounds, prefix = " : ") { signatureForProjection(it) } @@ -166,7 +170,7 @@ class KotlinSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLog private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(p: Projection): Unit = when (p) { - is OtherParameter -> text(p.name) + is OtherParameter -> link(p.name, p.declarationDRI) is TypeConstructor -> if (p.function) +funType(mainDRI.single(), mainPlatformData, p) diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt index 862f9240..1b8fa299 100644 --- a/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt +++ b/plugins/base/src/main/kotlin/transformers/documentables/DefaultDocumentableMerger.kt @@ -175,7 +175,8 @@ fun DAnnotation.mergeWith(other: DAnnotation): DAnnotation = copy( expectPresentInSet = expectPresentInSet ?: other.expectPresentInSet, sources = sources+ other.sources, visibility = visibility + other.visibility, - sourceSets = sourceSets + other.sourceSets + sourceSets = sourceSets + other.sourceSets, + generics = merge(generics + other.generics, DTypeParameter::mergeWith) ).mergeExtras(this, other) fun DParameter.mergeWith(other: DParameter): DParameter = copy( diff --git a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt index 6fdce3a8..d15ec791 100644 --- a/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt +++ b/plugins/base/src/main/kotlin/transformers/documentables/DocumentableVisibilityFilter.kt @@ -265,6 +265,7 @@ internal class DocumentableVisibilityFilter(val context: DokkaContext) : PreMerg visibility.filtered(filteredPlatforms), companion, constructors, + generics, filteredPlatforms, extra ) diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt index 7cc96a24..a62d9a0b 100644 --- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt @@ -1,10 +1,11 @@ package org.jetbrains.dokka.base.translators.descriptors import org.jetbrains.dokka.analysis.DokkaResolutionFacade +import org.jetbrains.dokka.links.* import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.withClass import org.jetbrains.dokka.model.* +import org.jetbrains.dokka.model.Nullable +import org.jetbrains.dokka.model.TypeConstructor import org.jetbrains.dokka.model.doc.* import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.dokka.parsers.MarkdownParser @@ -127,7 +128,7 @@ private class DokkaDescriptorVisitor( visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), supertypes = info.supertypes.toSourceSetDependent(), documentation = info.docs, - generics = descriptor.typeConstructor.parameters.map { it.toTypeParameter() }, + generics = descriptor.declaredTypeParameters.map { it.toTypeParameter() }, companion = descriptor.companion(driWithPlatform), sourceSets = listOf(sourceSet), extra = PropertyContainer.withAll(descriptor.additionalExtras(), descriptor.getAnnotations()) @@ -216,6 +217,7 @@ private class DokkaDescriptorVisitor( extra = PropertyContainer.withAll(descriptor.additionalExtras(), descriptor.getAnnotations()), companion = descriptor.companionObjectDescriptor?.let { objectDescriptor(it, driWithPlatform) }, visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), + generics = descriptor.declaredTypeParameters.map { it.toTypeParameter() }, constructors = descriptor.constructors.map { visitConstructorDescriptor(it, driWithPlatform) }, sources = descriptor.createSources() ) @@ -245,7 +247,7 @@ private class DokkaDescriptorVisitor( expectPresentInSet = sourceSet.takeIf { isExpect }, visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(), supertypes = info.supertypes.toSourceSetDependent(), - generics = descriptor.typeConstructor.parameters.map { it.toTypeParameter() }, + generics = descriptor.declaredTypeParameters.map { it.toTypeParameter() }, documentation = info.docs, modifier = descriptor.modifier().toSourceSetDependent(), companion = descriptor.companion(driWithPlatform), @@ -364,7 +366,7 @@ private class DokkaDescriptorVisitor( descriptor: ReceiverParameterDescriptor, parent: DRIWithPlatformInfo ) = DParameter( - dri = parent.dri.copy(target = 0), + dri = parent.dri.copy(target = PointingToDeclaration), name = null, type = descriptor.type.toBound(), expectPresentInSet = null, @@ -383,7 +385,7 @@ private class DokkaDescriptorVisitor( fun PropertyDescriptor.asParameter(parent: DRI) = DParameter( - parent.copy(target = 1), + parent.copy(target = PointingToCallableParameters(parameterIndex = 1)), this.name.asString(), type = this.type.toBound(), expectPresentInSet = sourceSet.takeIf { isExpect }, @@ -444,7 +446,7 @@ private class DokkaDescriptorVisitor( private fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRIWithPlatformInfo) = DParameter( - dri = parent.dri.copy(target = index + 1), + dri = parent.dri.copy(target = PointingToCallableParameters(index)), name = descriptor.name.asString(), type = descriptor.type.toBound(), expectPresentInSet = null, @@ -518,7 +520,10 @@ private class DokkaDescriptorVisitor( ) private fun KotlinType.toBound(): Bound = when (val ctor = constructor.declarationDescriptor) { - is TypeParameterDescriptor -> OtherParameter(ctor.name.asString()).let { + is TypeParameterDescriptor -> OtherParameter( + declarationDRI = DRI.from(ctor.containingDeclaration), + name = ctor.name.asString() + ).let { if (isMarkedNullable) Nullable(it) else it } else -> TypeConstructor( diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt index ca8055c8..ab4a84f6 100644 --- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.vfs.VirtualFileManager import com.intellij.psi.* import com.intellij.psi.impl.source.PsiClassReferenceType import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.links.nextTarget import org.jetbrains.dokka.links.withClass import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.properties.PropertyContainer @@ -159,6 +160,7 @@ object DefaultPsiToDocumentableTranslator : SourceToDocumentableTranslator { visibility, null, constructors.map { parseFunction(it, true) }, + mapTypeParameters(dri), listOf(sourceSetData), PropertyContainer.empty<DAnnotation>() + annotations.toList().toExtra() ) @@ -238,9 +240,9 @@ object DefaultPsiToDocumentableTranslator : SourceToDocumentableTranslator { dri, if (isConstructor) "<init>" else psi.name, isConstructor, - psi.parameterList.parameters.mapIndexed { index, psiParameter -> + psi.parameterList.parameters.map { psiParameter -> DParameter( - dri.copy(target = index + 1), + dri.copy(target = dri.target.nextTarget()), psiParameter.name, javadocParser.parseDocumentation(psiParameter).toPlatformDependant(), null, @@ -321,9 +323,9 @@ object DefaultPsiToDocumentableTranslator : SourceToDocumentableTranslator { if (bounds.isEmpty()) emptyList() else bounds.mapNotNull { (it as? PsiClassType)?.let { classType -> Nullable(getBound(classType)) } } - return typeParameters.mapIndexed { index, type -> + return typeParameters.map { type -> DTypeParameter( - dri.copy(genericTarget = index), + dri.copy(target = dri.target.nextTarget()), type.name.orEmpty(), javadocParser.parseDocumentation(type).toPlatformDependant(), null, diff --git a/plugins/base/src/test/kotlin/basic/DRITest.kt b/plugins/base/src/test/kotlin/basic/DRITest.kt index e85ca30e..1ac05177 100644 --- a/plugins/base/src/test/kotlin/basic/DRITest.kt +++ b/plugins/base/src/test/kotlin/basic/DRITest.kt @@ -1,8 +1,10 @@ package basic import org.jetbrains.dokka.links.* -import org.jetbrains.dokka.pages.ContentPage -import org.jetbrains.dokka.pages.asSequence +import org.jetbrains.dokka.model.DClass +import org.jetbrains.dokka.model.DFunction +import org.jetbrains.dokka.model.DParameter +import org.jetbrains.dokka.pages.* import org.junit.jupiter.api.Assertions.assertEquals import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest @@ -131,7 +133,7 @@ class DRITest : AbstractCoreTest() { configuration ) { pagesGenerationStage = { module -> - // DRI(//qux/Foo[TypeParam(bounds=[kotlin.Comparable[kotlin.Any?]]),*]#//) + // DRI(//qux/Foo[TypeParam(bounds=[kotlin.Comparable[kotlin.Any?]]),*]#/PointingToFunctionOrClasslike/) val expectedDRI = DRI( "", null, @@ -163,4 +165,114 @@ class DRITest : AbstractCoreTest() { } } } + + @Test + fun driForGenericClass(){ + val configuration = dokkaConfiguration { + passes { + pass { + sourceRoots = listOf("src/") + } + } + } + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + |class Sample<S>(first: S){ } + | + | + """.trimMargin(), + configuration + ) { + pagesGenerationStage = { module -> + val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode + val classDocumentable = sampleClass.documentable as DClass + + assertEquals( "example/Sample///PointingToDeclaration/", sampleClass.dri.first().toString()) + assertEquals("example/Sample///PointingToGenericParameters(0)/", classDocumentable.generics.first().dri.toString()) + } + } + } + + @Test + fun driForGenericFunction(){ + val configuration = dokkaConfiguration { + passes { + pass { + sourceRoots = listOf("src/") + classpath = listOfNotNull(jvmStdlibPath) + } + } + } + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + |class Sample<S>(first: S){ + | fun <T> genericFun(param1: String): Triple<S,T> = TODO() + |} + | + | + """.trimMargin(), + configuration + ) { + pagesGenerationStage = { module -> + val sampleClass = module.dfs { it.name == "Sample" } as ClasslikePageNode + val functionNode = sampleClass.children.first { it.name == "genericFun" } as MemberPageNode + val functionDocumentable = functionNode.documentable as DFunction + val parameter = functionDocumentable.parameters.first() + + assertEquals("example/Sample/genericFun/#kotlin.String/PointingToDeclaration/", functionNode.dri.first().toString()) + + assertEquals(1, functionDocumentable.parameters.size) + assertEquals("example/Sample/genericFun/#kotlin.String/PointingToCallableParameters(0)/", parameter.dri.toString()) + //1 since from the function's perspective there is only 1 new generic declared + //The other one is 'inherited' from class + assertEquals( 1, functionDocumentable.generics.size) + assertEquals( "T", functionDocumentable.generics.first().name) + assertEquals( "example/Sample/genericFun/#kotlin.String/PointingToGenericParameters(0)/", functionDocumentable.generics.first().dri.toString()) + } + } + } + + @Test + fun driForGenericExtensionFunction(){ + val configuration = dokkaConfiguration { + passes { + pass { + sourceRoots = listOf("src/") + } + } + } + testInline( + """ + |/src/main/kotlin/Test.kt + |package example + | + | fun <T> List<T>.extensionFunction(): String = "" + | + """.trimMargin(), + configuration + ) { + pagesGenerationStage = { module -> + val extensionFunction = module.dfs { it.name == "extensionFunction" } as MemberPageNode + val documentable = extensionFunction.documentable as DFunction + + assertEquals( + "example//extensionFunction/kotlin.collections.List[TypeParam(bounds=[kotlin.Any?])]#/PointingToDeclaration/", + extensionFunction.dri.first().toString() + ) + assertEquals(1, documentable.generics.size) + assertEquals("T", documentable.generics.first().name) + assertEquals( + "example//extensionFunction/kotlin.collections.List[TypeParam(bounds=[kotlin.Any?])]#/PointingToGenericParameters(0)/", + documentable.generics.first().dri.toString() + ) + + } + } + } } diff --git a/plugins/base/src/test/kotlin/markdown/LinkTest.kt b/plugins/base/src/test/kotlin/markdown/LinkTest.kt index d38486b5..bf234b6b 100644 --- a/plugins/base/src/test/kotlin/markdown/LinkTest.kt +++ b/plugins/base/src/test/kotlin/markdown/LinkTest.kt @@ -1,10 +1,12 @@ package markdown +import org.jetbrains.dokka.pages.ClasslikePageNode import org.jetbrains.dokka.pages.ContentDRILink import org.jetbrains.dokka.pages.MemberPageNode import org.jetbrains.dokka.pages.dfs import org.jetbrains.dokka.testApi.testRunner.AbstractCoreTest import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Test class LinkTest : AbstractCoreTest() { @@ -36,11 +38,43 @@ class LinkTest : AbstractCoreTest() { .dfs { node -> node is ContentDRILink } .let { assertEquals( - "parser//test/#java.lang.ClassLoader//", + "parser//test/#java.lang.ClassLoader/PointingToDeclaration/", (it as ContentDRILink).address.toString() ) } } } } + + @Test + fun returnTypeShouldHaveLinkToOuterClassFromInner() { + val configuration = dokkaConfiguration { + passes { + pass { + sourceRoots = listOf("src/main/kotlin/parser") + } + } + } + testInline( + """ + |/src/main/kotlin/parser/Test.kt + |package parser + | + |class Outer<OUTER> { + | inner class Inner<INNER> { + | fun foo(): OUTER = TODO() + | } + |} + """.trimMargin(), + configuration + ) { + renderingStage = { rootPageNode, _ -> + val root = rootPageNode.children.single().children.single() as ClasslikePageNode + val innerClass = root.children.first { it is ClasslikePageNode } + val foo = innerClass.children.first { it.name == "foo" } as MemberPageNode + + assertNotNull(foo.content.dfs { it is ContentDRILink && it.address.toString() == "parser/Outer///PointingToDeclaration/" } ) + } + } + } }
\ No newline at end of file diff --git a/plugins/base/src/test/kotlin/model/ClassesTest.kt b/plugins/base/src/test/kotlin/model/ClassesTest.kt index a349e54a..ea0d93ed 100644 --- a/plugins/base/src/test/kotlin/model/ClassesTest.kt +++ b/plugins/base/src/test/kotlin/model/ClassesTest.kt @@ -425,7 +425,7 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class ) { with((this / "classes" / "Foo").cast<DClass>()) { with(extra[Annotations]?.content?.firstOrNull().assertNotNull("annotations")) { - dri.toString() equals "kotlin/Suppress////" + dri.toString() equals "kotlin/Suppress///PointingToDeclaration/" with(params["names"].assertNotNull("param")) { this equals "[\"abc\"]" } @@ -459,4 +459,29 @@ class ClassesTest : AbstractModelTest("/src/main/kotlin/classes/Test.kt", "class } } } + + @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") + } + } + } + + @Test fun nestedGenericClasses(){ + inlineModelTest( + """ + |class Outer<OUTER> { + | inner class Inner<INNER, T : OUTER> { } + |} + """.trimMargin() + ){ + 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") + } + } + } }
\ No newline at end of file diff --git a/plugins/base/src/test/kotlin/model/JavaTest.kt b/plugins/base/src/test/kotlin/model/JavaTest.kt index a58b380c..76924f0f 100644 --- a/plugins/base/src/test/kotlin/model/JavaTest.kt +++ b/plugins/base/src/test/kotlin/model/JavaTest.kt @@ -394,7 +394,6 @@ class JavaTest : AbstractModelTest("/src/main/kotlin/java/Test.java", "java") { } } - @Disabled("reenable after fixing subtypes") @Test fun inheritorLinks() { inlineModelTest( diff --git a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt index 5a77016d..8d9ac20d 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt @@ -1,12 +1,13 @@ package org.jetbrains.dokka.kotlinAsJava.converters +import org.jetbrains.dokka.links.* import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.withClass import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.DAnnotation import org.jetbrains.dokka.model.DEnum import org.jetbrains.dokka.model.DFunction +import org.jetbrains.dokka.model.Nullable +import org.jetbrains.dokka.model.TypeConstructor import org.jetbrains.dokka.model.properties.PropertyContainer import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.name.ClassId @@ -243,7 +244,7 @@ internal fun ClassId.toDRI(dri: DRI?): DRI = DRI( classNames = classNames(), callable = dri?.callable,//?.asJava(), TODO: check this extra = null, - target = null + target = PointingToDeclaration ) private fun PropertyContainer<out Documentable>.mergeAdditionalModifiers(second: Set<ExtraModifiers>) = diff --git a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt index d737cedb..9135d36e 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/signatures/JavaSignatureProvider.kt @@ -92,7 +92,7 @@ class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogge private fun PageContentBuilder.DocumentableContentBuilder.signatureForProjection(p: Projection): Unit = when (p) { - is OtherParameter -> text(p.name) + is OtherParameter -> link(p.name, p.declarationDRI) is TypeConstructor -> group { link(p.dri.classNames.orEmpty(), p.dri) |