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 /plugins/base | |
parent | e9d7fc75b46bb44f2c946b8cbb0636deb71e20dc (diff) | |
download | dokka-3aeb65472be150a6098f2fac17dbdf0bb2a40013.tar.gz dokka-3aeb65472be150a6098f2fac17dbdf0bb2a40013.tar.bz2 dokka-3aeb65472be150a6098f2fac17dbdf0bb2a40013.zip |
Missing generics on class. Add generics to annotation #834
Diffstat (limited to 'plugins/base')
9 files changed, 208 insertions, 25 deletions
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( |