From e4044ec67ad90041b02bb84c4b966ffeac537617 Mon Sep 17 00:00:00 2001 From: Kamil Doległo Date: Sun, 1 Mar 2020 21:26:13 +0100 Subject: Add initial version of Kotlin as Java plugin --- .../DefaultDescriptorToDocumentableTranslator.kt | 2 +- .../src/main/kotlin/JavaSignatureProvider.kt | 112 ++++++++++ ...tlinAsJavaDescriptorToDocumentableTranslator.kt | 76 ------- .../src/main/kotlin/KotlinAsJavaPageBuilder.kt | 81 ------- .../main/kotlin/KotlinAsJavaPageContentBuilder.kt | 73 ------ .../src/main/kotlin/KotlinAsJavaPlugin.kt | 47 +--- .../src/main/kotlin/KotlinToJVMResolver.kt | 150 ------------- .../kotlin/converters/KotlinToJavaConverter.kt | 246 +++++++++++++++++++++ .../KotlinAsJavaDocumentableTransformer.kt | 11 + 9 files changed, 379 insertions(+), 419 deletions(-) create mode 100644 plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt delete mode 100644 plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentableTranslator.kt delete mode 100644 plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt delete mode 100644 plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt delete mode 100644 plugins/kotlin-as-java/src/main/kotlin/KotlinToJVMResolver.kt create mode 100644 plugins/kotlin-as-java/src/main/kotlin/converters/KotlinToJavaConverter.kt create mode 100644 plugins/kotlin-as-java/src/main/kotlin/transformers/KotlinAsJavaDocumentableTransformer.kt (limited to 'plugins') diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt index 117dd552..f30ffa00 100644 --- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt @@ -58,7 +58,7 @@ data class DRIWithPlatformInfo( fun DRI.withEmptyInfo() = DRIWithPlatformInfo(this, PlatformDependent.empty()) -open class DokkaDescriptorVisitor( // TODO: close this class and make it private together with DRIWithPlatformInfo +private class DokkaDescriptorVisitor( // TODO: close this class and make it private together with DRIWithPlatformInfo private val platformData: PlatformData, private val resolutionFacade: DokkaResolutionFacade ) : DeclarationDescriptorVisitorEmptyBodies() { diff --git a/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt b/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt new file mode 100644 index 00000000..526546f2 --- /dev/null +++ b/plugins/kotlin-as-java/src/main/kotlin/JavaSignatureProvider.kt @@ -0,0 +1,112 @@ +package org.jetbrains.dokka.kotlinAsJava + +import org.jetbrains.dokka.base.signatures.SignatureProvider +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.sureClassNames +import org.jetbrains.dokka.model.* +import org.jetbrains.dokka.model.Annotation +import org.jetbrains.dokka.model.Enum +import org.jetbrains.dokka.model.Function +import org.jetbrains.dokka.pages.ContentKind +import org.jetbrains.dokka.pages.ContentNode +import org.jetbrains.dokka.pages.PlatformData +import org.jetbrains.dokka.utilities.DokkaLogger + +class JavaSignatureProvider(ctcc: CommentsToContentConverter, logger: DokkaLogger) : SignatureProvider { + private val contentBuilder = PageContentBuilder(ctcc, logger) + + override fun signature(documentable: Documentable): List = when (documentable) { + is Function -> signature(documentable) + is Classlike -> signature(documentable) + else -> throw NotImplementedError( + "Cannot generate signature for ${documentable::class.qualifiedName} ${documentable.name}" + ) + } + + private fun signature(f: Function) = f.platformData.map { signature(f, it) }.distinct() + + private fun signature(c: Classlike) = c.platformData.map { signature(c, it) }.distinct() + + private fun signature(c: Classlike, platform: PlatformData) = contentBuilder.contentFor(c, ContentKind.Symbol) { + text(c.visibility[platform]?.externalDisplayName ?: "") + if (c is Class) { + text(c.modifier.toString()) + } + when (c) { + is Class -> text(" class ") + is Interface -> text(" interface ") + is Enum -> text(" enum ") + is Object -> text(" class ") + is Annotation -> text(" @interface ") + } + text(c.name!!) + if (c is WithSupertypes) { + list(c.supertypes.getValue(platform), prefix = " : ") { + link(it.sureClassNames, it) + } + } + } + + private fun signature(f: Function, platform: PlatformData) = contentBuilder.contentFor(f, ContentKind.Symbol) { + text(f.visibility[platform]?.externalDisplayName ?: "") + text(f.modifier.toString()) + val returnType = f.type + if (!f.isConstructor && returnType.constructorFqName != Unit::class.qualifiedName) { + text(": ") + type(returnType) + } + text(" ") + link(f.name, f.dri) + val generics = f.generics.filterOnPlatform(platform) + if (generics.isNotEmpty()) { + text("<") + generics.forEach { + signature(it) + } + text(">") + } + text("(") + list(listOfNotNull(f.receiver) + f.parameters.filterOnPlatform(platform)) { + type(it.type) + text(" ") + link(it.name!!, it.dri) + text(", ") + } + text(")") + } + + private fun signature(t: TypeParameter) = contentBuilder.contentFor(t, ContentKind.Symbol) { + link(t.name, t.dri) + if (t.bounds.isNotEmpty()) { + text("<") + t.bounds.forEach { + signature(it, t.dri, t.platformData) + } + text(">") + } + } + + private fun signature(p: Projection, dri: DRI, platforms: List): List = when (p) { + is OtherParameter -> contentBuilder.contentFor(dri, platforms.toSet()) { text(p.name) }.children + + is TypeConstructor -> contentBuilder.contentFor(dri, platforms.toSet()) { + link(p.dri.classNames.orEmpty(), p.dri) + }.children + p.projections.flatMap { signature(it, dri, platforms) } + + is Variance -> contentBuilder.contentFor(dri, platforms.toSet()) { + text(p.kind.toString() + " ") + }.children + signature(p.inner, dri, platforms) + + is Star -> contentBuilder.contentFor(dri, platforms.toSet()) { text("*") }.children + + is Nullable -> signature(p.inner, dri, platforms) + contentBuilder.contentFor( + dri, + platforms.toSet() + ) { text("?") }.children + } + + private fun Collection.filterOnPlatform(platformData: PlatformData) = + this.filter { it.platformData.contains(platformData) } +} \ No newline at end of file diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentableTranslator.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentableTranslator.kt deleted file mode 100644 index 3b615dcb..00000000 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentableTranslator.kt +++ /dev/null @@ -1,76 +0,0 @@ -package org.jetbrains.dokka.kotlinAsJava - -import org.jetbrains.dokka.analysis.DokkaResolutionFacade -import org.jetbrains.dokka.base.translators.descriptors.DRIWithPlatformInfo -import org.jetbrains.dokka.base.translators.descriptors.DokkaDescriptorVisitor -import org.jetbrains.dokka.base.translators.descriptors.withEmptyInfo -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.Function -import org.jetbrains.dokka.pages.PlatformData -import org.jetbrains.dokka.plugability.DokkaContext -import org.jetbrains.dokka.transformers.descriptors.DescriptorToDocumentableTranslator -import org.jetbrains.kotlin.descriptors.* - -class KotlinAsJavaDescriptorToDocumentableTranslator( - private val context: DokkaContext -) : DescriptorToDocumentableTranslator { - override fun invoke( - moduleName: String, - packageFragments: Iterable, - platformData: PlatformData - ): Module = - KotlinAsJavaDokkaDescriptorVisitor(platformData, context.platforms[platformData]?.facade!!).run { - packageFragments.map { visitPackageFragmentDescriptor(it, DRI.topLevel.withEmptyInfo()) } - }.let { Module(moduleName, it) } -} - -class KotlinAsJavaDokkaDescriptorVisitor( - platformData: PlatformData, - resolutionFacade: DokkaResolutionFacade -) : DokkaDescriptorVisitor(platformData, resolutionFacade) { - override fun visitPackageFragmentDescriptor( - descriptor: PackageFragmentDescriptor, - parent: DRIWithPlatformInfo - ): Package { - val dri = DRI(packageName = descriptor.fqName.asString()) - DescriptorCache.add(dri, descriptor) - return super.visitPackageFragmentDescriptor(descriptor, parent) - } - - override fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Classlike { - val dri = parent.dri.withClass(descriptor.name.asString()) - DescriptorCache.add(dri, descriptor) - return super.visitClassDescriptor(descriptor, parent) - } - - override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): Property { - val dri = parent.dri.copy(callable = Callable.from(descriptor)) - DescriptorCache.add(dri, descriptor) - return super.visitPropertyDescriptor(descriptor, parent) - } - - override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): Function { - val dri = parent.dri.copy(callable = Callable.from(descriptor)) - DescriptorCache.add(dri, descriptor) - return super.visitFunctionDescriptor(descriptor, parent) - } - - override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRIWithPlatformInfo): Function { - val dri = parent.dri.copy(callable = Callable.from(descriptor)) - DescriptorCache.add(dri, descriptor) - return super.visitConstructorDescriptor(descriptor, parent) - } - - override fun visitPropertyAccessorDescriptor( - descriptor: PropertyAccessorDescriptor, - propertyDescriptor: PropertyDescriptor, - parent: DRI - ): Function { - val dri = parent.copy(callable = Callable.from(descriptor)) - DescriptorCache.add(dri, descriptor) - return super.visitPropertyAccessorDescriptor(descriptor, propertyDescriptor, parent) - } -} \ No newline at end of file diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt deleted file mode 100644 index ef6f9c33..00000000 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt +++ /dev/null @@ -1,81 +0,0 @@ -package org.jetbrains.dokka.kotlinAsJava - -import org.jetbrains.dokka.base.translators.documentables.DefaultPageBuilder -import org.jetbrains.dokka.base.translators.documentables.RootContentBuilder -import org.jetbrains.dokka.kotlinAsJava.conversions.asJava -import org.jetbrains.dokka.kotlinAsJava.conversions.asStatic -import org.jetbrains.dokka.kotlinAsJava.conversions.withClass -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.withClass -import org.jetbrains.dokka.model.* -import org.jetbrains.dokka.model.Enum -import org.jetbrains.dokka.model.Function -import org.jetbrains.dokka.pages.* -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.descriptors.Visibilities -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi - -fun DeclarationDescriptor.sourceLocation(): String? = this.findPsi()?.containingFile?.virtualFile?.path -fun List.groupedByLocation(): Map> = - this.map { DescriptorCache[it.dri]?.sourceLocation() to it } - .filter { it.first != null }.groupBy({ (location, _) -> - location!!.let { it.split("/").last().split(".").first() + "Kt" } - }) { it.second } - -fun PlatformInfo.toClassPlatformInfo(inherited: List = emptyList()) = - ClassPlatformInfo(this, emptyList()) - -class KotlinAsJavaPageBuilder(rootContentGroup: RootContentBuilder) : DefaultPageBuilder(rootContentGroup) { - - override fun pageForModule(m: Module): ModulePageNode = - ModulePageNode(m.name.ifEmpty { "root" }, contentForModule(m), m, m.packages.map { pageForPackage(it) }) - - data class FunsAndProps(val key: String, val funs: List, val props: List) - - override fun pageForPackage(p: Package): PackagePageNode { - - val funs = p.functions.groupedByLocation() - - val props = p.properties.groupedByLocation() - - val zipped = (funs.keys + props.keys) - .map { k -> FunsAndProps(k, funs[k].orEmpty(), props[k].orEmpty()) } - - val classes = (p.classlikes + zipped.map { (key, funs, props) -> - val dri = p.dri.withClass(key) - val actual = - (funs.flatMap { it.actual } + props.flatMap { it.actual }).distinct().map { it.toClassPlatformInfo() } - Class( - dri = dri, - name = key, - kind = KotlinClassKindTypes.CLASS, - constructors = emptyList(), - functions = funs.map { it.withClass(key, dri).asStatic() }, - properties = props.map { it.withClass(key, dri) }, - classlikes = emptyList(), - actual = actual, - expected = null, - visibility = p.platformData.map { it to Visibilities.PUBLIC }.toMap() - ) - }).map { it.asJava() } - - return PackagePageNode( - p.name, contentForPackage(p, classes), setOf(p.dri), p, - classes.map(::pageForClasslike) - ) - } - - private fun contentForPackage(p: Package, nClasses: List) = group(p) { - header(1) { text("Package ${p.name}") } - block("Types", 2, ContentKind.Properties, nClasses, p.platformData) { - link(it.name, it.dri) - text(it.briefDocTagString) - } - } - - override fun contentForClasslike(c: Classlike): ContentGroup = when (c) { - is Class -> contentForClass(c) - is Enum -> contentForEnum(c) - else -> throw IllegalStateException("$c should not be present here") - } -} \ No newline at end of file diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt deleted file mode 100644 index a8ec7126..00000000 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt +++ /dev/null @@ -1,73 +0,0 @@ -package org.jetbrains.dokka.kotlinAsJava - -import org.jetbrains.dokka.base.translators.documentables.DefaultPageContentBuilder -import org.jetbrains.dokka.base.translators.documentables.PageContentBuilderFunction -import org.jetbrains.dokka.base.translators.documentables.type -import org.jetbrains.dokka.base.transformers.pages.comments.CommentsToContentConverter -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.model.Function -import org.jetbrains.dokka.model.JavaTypeWrapper -import org.jetbrains.dokka.pages.* -import org.jetbrains.dokka.utilities.DokkaLogger - -class KotlinAsJavaPageContentBuilder( - dri: Set, - platformData: Set, - kind: Kind, - commentsConverter: CommentsToContentConverter, - logger: DokkaLogger, - styles: Set