diff options
author | Paweł Marks <pmarks@virtuslab.com> | 2020-02-12 16:01:38 +0100 |
---|---|---|
committer | Paweł Marks <Kordyjan@users.noreply.github.com> | 2020-02-18 13:28:23 +0100 |
commit | 848f2e0656e80604cb54932db5b250303aaccca8 (patch) | |
tree | 2d577faf9ee5f894fb2a97aa01a89d75d3c59841 /plugins | |
parent | 46b4bbb68ce1285a1aea700cc0d0000c6b7ed97b (diff) | |
download | dokka-848f2e0656e80604cb54932db5b250303aaccca8.tar.gz dokka-848f2e0656e80604cb54932db5b250303aaccca8.tar.bz2 dokka-848f2e0656e80604cb54932db5b250303aaccca8.zip |
Moves DescriptorToDocumentableTransformer to base plugin
Diffstat (limited to 'plugins')
9 files changed, 365 insertions, 12 deletions
diff --git a/plugins/base/build.gradle.kts b/plugins/base/build.gradle.kts index 386a3288..ba0b5753 100644 --- a/plugins/base/build.gradle.kts +++ b/plugins/base/build.gradle.kts @@ -5,4 +5,5 @@ publishing { from(components["java"]) } } -}
\ No newline at end of file +} + diff --git a/plugins/base/src/main/kotlin/DokkaBase.kt b/plugins/base/src/main/kotlin/DokkaBase.kt index e82a59bf..5c579e54 100644 --- a/plugins/base/src/main/kotlin/DokkaBase.kt +++ b/plugins/base/src/main/kotlin/DokkaBase.kt @@ -1,4 +1,11 @@ +package org.jetbrains.dokka.base + +import org.jetbrains.dokka.CoreExtensions +import org.jetbrains.dokka.base.transformers.descriptors.DefaultDescriptorToDocumentationTranslator import org.jetbrains.dokka.plugability.DokkaPlugin class DokkaBase: DokkaPlugin() { + val defaultDescriptorToDocumentationTranslator by extending { + CoreExtensions.descriptorToDocumentationTranslator providing ::DefaultDescriptorToDocumentationTranslator + } }
\ No newline at end of file diff --git a/plugins/base/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt b/plugins/base/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt new file mode 100644 index 00000000..1358cef1 --- /dev/null +++ b/plugins/base/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt @@ -0,0 +1,338 @@ +package org.jetbrains.dokka.base.transformers.descriptors + +import org.jetbrains.dokka.analysis.DokkaResolutionFacade +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.ClassKind +import org.jetbrains.dokka.model.Enum +import org.jetbrains.dokka.model.Function +import org.jetbrains.dokka.model.Property +import org.jetbrains.dokka.model.doc.* +import org.jetbrains.dokka.pages.PlatformData +import org.jetbrains.dokka.parsers.MarkdownParser +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.transformers.descriptors.DescriptorToDocumentationTranslator +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies +import org.jetbrains.kotlin.idea.kdoc.findKDoc +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperclassesWithoutAny +import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.types.KotlinType +import kotlin.reflect.KClass + +class DefaultDescriptorToDocumentationTranslator( + private val context: DokkaContext +) : DescriptorToDocumentationTranslator { + override fun invoke( + moduleName: String, + packageFragments: Iterable<PackageFragmentDescriptor>, + platformData: PlatformData + ) = DokkaDescriptorVisitor(platformData, context.platforms[platformData]?.facade!!).run { + packageFragments.map { + visitPackageFragmentDescriptor( + it, + DRIWithPlatformInfo(DRI.topLevel, null, emptyList()) + ) + } + }.let { Module(moduleName, it) } + +} + + +data class DRIWithPlatformInfo( + val dri: DRI, + val expected: PlatformInfo?, + val actual: List<PlatformInfo> +) + +fun DRI.withEmptyInfo() = DRIWithPlatformInfo(this, null, emptyList()) + +open class DokkaDescriptorVisitor( // TODO: close this class and make it private together with DRIWithPlatformInfo + private val platformData: PlatformData, + private val resolutionFacade: DokkaResolutionFacade +) : DeclarationDescriptorVisitorEmptyBodies<Documentable, DRIWithPlatformInfo>() { + override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor, parent: DRIWithPlatformInfo): Nothing { + throw IllegalStateException("${javaClass.simpleName} should never enter ${descriptor.javaClass.simpleName}") + } + + override fun visitPackageFragmentDescriptor( + descriptor: PackageFragmentDescriptor, + parent: DRIWithPlatformInfo + ): Package { + val driWithPlatform = DRI(packageName = descriptor.fqName.asString()).withEmptyInfo() + val scope = descriptor.getMemberScope() + + return Package( + dri = driWithPlatform.dri, + functions = scope.functions(driWithPlatform), + properties = scope.properties(driWithPlatform), + classlikes = scope.classlikes(driWithPlatform) + ) + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Classlike = + when (descriptor.kind) { + org.jetbrains.kotlin.descriptors.ClassKind.ENUM_CLASS -> enumDescriptor(descriptor, parent) + else -> classDescriptor(descriptor, parent) + } + + fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Enum { + val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() + val scope = descriptor.unsubstitutedMemberScope + val descriptorData = descriptor.takeUnless { it.isExpect }?.resolveClassDescriptionData() + + return Enum( + dri = driWithPlatform.dri, + name = descriptor.name.asString(), + entries = scope.classlikes(driWithPlatform).filter { it.kind == KotlinClassKindTypes.ENUM_ENTRY }.map { + EnumEntry( + it + ) + }, + constructors = descriptor.constructors.map { visitConstructorDescriptor(it, driWithPlatform) }, + functions = scope.functions(driWithPlatform), + properties = scope.properties(driWithPlatform), + classlikes = scope.classlikes(driWithPlatform), + expected = descriptor.takeIf { it.isExpect }?.resolveClassDescriptionData(), + actual = listOfNotNull(descriptorData), + extra = mutableSetOf(), // TODO Implement following method to return proper results getXMLDRIs(descriptor, descriptorData).toMutableSet() + visibility = mapOf(platformData to descriptor.visibility) + ) + } + + fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): Class { + val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo() + val scope = descriptor.unsubstitutedMemberScope + val descriptorData = descriptor.takeUnless { it.isExpect }?.resolveClassDescriptionData() + val expected = descriptor.takeIf { it.isExpect }?.resolveClassDescriptionData() + val actual = listOfNotNull(descriptorData) + return Class( + dri = driWithPlatform.dri, + name = descriptor.name.asString(), + kind = KotlinClassKindTypes.valueOf(descriptor.kind.toString()), + constructors = descriptor.constructors.map { + visitConstructorDescriptor( + it, + if (it.isPrimary) + DRIWithPlatformInfo( + driWithPlatform.dri, + expected?.info.filterTagWrappers(listOf(Constructor::class)), + actual.filterTagWrappers(listOf(Constructor::class)) + ) + else + DRIWithPlatformInfo(driWithPlatform.dri, null, emptyList()) + ) + }, + functions = scope.functions(driWithPlatform), + properties = scope.properties(driWithPlatform), + classlikes = scope.classlikes(driWithPlatform), + expected = expected, + actual = actual, + extra = mutableSetOf(), // TODO Implement following method to return proper results getXMLDRIs(descriptor, descriptorData).toMutableSet() + visibility = mapOf(platformData to descriptor.visibility) + ) + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): Property { + val expected = descriptor.takeIf { it.isExpect }?.resolveDescriptorData() + val actual = listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()) + val dri = parent.dri.copy(callable = Callable.from(descriptor)) + + return Property( + dri = dri, + name = descriptor.name.asString(), + receiver = descriptor.extensionReceiverParameter?.let { + visitReceiverParameterDescriptor( + it, + DRIWithPlatformInfo( + dri, + expected?.filterTagWrappers(listOf(Receiver::class)), + actual.filterTagWrappers(listOf(Receiver::class)) + ) + ) + }, + expected = expected, + actual = actual, + accessors = descriptor.accessors.map { visitPropertyAccessorDescriptor(it, descriptor, dri) }, + visibility = mapOf(platformData to descriptor.visibility) + ) + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): Function { + val expected = descriptor.takeIf { it.isExpect }?.resolveDescriptorData() + val actual = listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()) + val dri = parent.dri.copy(callable = Callable.from(descriptor)) + + return Function( + dri = dri, + name = descriptor.name.asString(), + returnType = descriptor.returnType?.let { KotlinTypeWrapper(it) }, + isConstructor = false, + receiver = descriptor.extensionReceiverParameter?.let { + visitReceiverParameterDescriptor( + it, + DRIWithPlatformInfo( + dri, + expected?.filterTagWrappers(listOf(Receiver::class)), + actual.filterTagWrappers(listOf(Receiver::class)) + ) + ) + }, + parameters = descriptor.valueParameters.mapIndexed { index, desc -> + parameter( + index, desc, + DRIWithPlatformInfo( + dri, + expected.filterTagWrappers(listOf(Param::class), desc.name.asString()), + actual.filterTagWrappers(listOf(Param::class), desc.name.asString()) + ) + ) + }, + expected = expected, + actual = actual, + visibility = mapOf(platformData to descriptor.visibility) + ) + } + + override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRIWithPlatformInfo): Function { + val dri = parent.dri.copy(callable = Callable.from(descriptor)) + return Function( + dri = dri, + name = "<init>", + returnType = KotlinTypeWrapper(descriptor.returnType), + isConstructor = true, + receiver = null, + parameters = descriptor.valueParameters.mapIndexed { index, desc -> + parameter( + index, desc, + DRIWithPlatformInfo( + dri, + parent.expected.filterTagWrappers(listOf(Param::class)), + parent.actual.filterTagWrappers(listOf(Param::class)) + ) + ) + }, + expected = parent.expected ?: descriptor.takeIf { it.isExpect }?.resolveDescriptorData(), + actual = parent.actual, + visibility = mapOf(platformData to descriptor.visibility) + ) + } + + override fun visitReceiverParameterDescriptor( + descriptor: ReceiverParameterDescriptor, + parent: DRIWithPlatformInfo + ) = Parameter( + dri = parent.dri.copy(target = 0), + name = null, + type = KotlinTypeWrapper(descriptor.type), + expected = parent.expected, + actual = parent.actual + ) + + open fun visitPropertyAccessorDescriptor( + descriptor: PropertyAccessorDescriptor, + propertyDescriptor: PropertyDescriptor, + parent: DRI + ): Function { + val dri = parent.copy(callable = Callable.from(descriptor)) + val isGetter = descriptor is PropertyGetterDescriptor + + fun PropertyDescriptor.asParameter(parent: DRI) = + Parameter( + parent.copy(target = 1), + this.name.asString(), + KotlinTypeWrapper(this.type), + descriptor.takeIf { it.isExpect }?.resolveDescriptorData(), + listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()) + ) + + val name = run { + val modifier = if (isGetter) "get" else "set" + val rawName = propertyDescriptor.name.asString() + "$modifier${rawName[0].toUpperCase()}${rawName.drop(1)}" + } + + descriptor.visibility + val parameters = + if (isGetter) { + emptyList() + } else { + listOf(propertyDescriptor.asParameter(dri)) + } + + return Function( + dri, + name, + descriptor.returnType?.let { KotlinTypeWrapper(it) }, + false, + null, + parameters, + descriptor.takeIf { it.isExpect }?.resolveDescriptorData(), + listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()), + visibility = mapOf(platformData to descriptor.visibility) + ) + } + + private fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRIWithPlatformInfo) = + Parameter( + dri = parent.dri.copy(target = index + 1), + name = descriptor.name.asString(), + type = KotlinTypeWrapper(descriptor.type), + expected = parent.expected, + actual = parent.actual + ) + + private fun MemberScope.functions(parent: DRIWithPlatformInfo): List<Function> = + getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) { true } + .filterIsInstance<FunctionDescriptor>() + .map { visitFunctionDescriptor(it, parent) } + + private fun MemberScope.properties(parent: DRIWithPlatformInfo): List<Property> = + getContributedDescriptors(DescriptorKindFilter.VALUES) { true } + .filterIsInstance<PropertyDescriptor>() + .map { visitPropertyDescriptor(it, parent) } + + private fun MemberScope.classlikes(parent: DRIWithPlatformInfo): List<Classlike> = + getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) { true } + .filterIsInstance<ClassDescriptor>() + .map { visitClassDescriptor(it, parent) } + + private fun DeclarationDescriptor.resolveDescriptorData(): PlatformInfo { + val doc = findKDoc() + val parser = MarkdownParser(resolutionFacade, this) + val docHeader = parser.parseFromKDocTag(doc) + + return BasePlatformInfo(docHeader, listOf(platformData)) + } + + private fun ClassDescriptor.resolveClassDescriptionData(): ClassPlatformInfo { + return ClassPlatformInfo(resolveDescriptorData(), + (getSuperInterfaces() + getAllSuperclassesWithoutAny()).map { DRI.from(it) }) + } + + private fun PlatformInfo?.filterTagWrappers( + types: List<KClass<out TagWrapper>>, + name: String? = null + ): PlatformInfo? { + if (this == null) + return null + return BasePlatformInfo( + DocumentationNode( + this.documentationNode.children.filter { it::class in types && (it as? NamedTagWrapper)?.name == name } + ), + this.platformData + ) + } + + private fun List<PlatformInfo>.filterTagWrappers( + types: List<KClass<out TagWrapper>>, + name: String? = null + ): List<PlatformInfo> = + this.map { it.filterTagWrappers(types, name)!! } +} + diff --git a/plugins/kotlin-as-java/build.gradle.kts b/plugins/kotlin-as-java/build.gradle.kts index 3b281d53..32f9c931 100644 --- a/plugins/kotlin-as-java/build.gradle.kts +++ b/plugins/kotlin-as-java/build.gradle.kts @@ -5,4 +5,8 @@ publishing { from(components["java"]) } } +} + +dependencies { + implementation(project(":plugins:base")) }
\ No newline at end of file diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentationTranslator.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentationTranslator.kt index 9c4ee9aa..1edf4aa1 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentationTranslator.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaDescriptorToDocumentationTranslator.kt @@ -1,6 +1,9 @@ package org.jetbrains.dokka.kotlinAsJava import org.jetbrains.dokka.analysis.DokkaResolutionFacade +import org.jetbrains.dokka.base.transformers.descriptors.DRIWithPlatformInfo +import org.jetbrains.dokka.base.transformers.descriptors.DokkaDescriptorVisitor +import org.jetbrains.dokka.base.transformers.descriptors.withEmptyInfo import org.jetbrains.dokka.links.Callable import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.links.withClass @@ -8,18 +11,16 @@ 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.DRIWithPlatformInfo import org.jetbrains.dokka.transformers.descriptors.DescriptorToDocumentationTranslator -import org.jetbrains.dokka.transformers.descriptors.DokkaDescriptorVisitor -import org.jetbrains.dokka.transformers.descriptors.withEmptyInfo import org.jetbrains.kotlin.descriptors.* -object KotlinAsJavaDescriptorToDocumentationTranslator : DescriptorToDocumentationTranslator { +class KotlinAsJavaDescriptorToDocumentationTranslator( + private val context: DokkaContext +) : DescriptorToDocumentationTranslator { override fun invoke( moduleName: String, packageFragments: Iterable<PackageFragmentDescriptor>, - platformData: PlatformData, - context: DokkaContext + platformData: PlatformData ): Module = KotlinAsJavaDokkaDescriptorVisitor(platformData, context.platforms[platformData]?.facade!!).run { packageFragments.map { visitPackageFragmentDescriptor(it, DRI.topLevel.withEmptyInfo()) } diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt index 8f026477..6fe10ce1 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageBuilder.kt @@ -9,7 +9,6 @@ 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.dokka.transformers.descriptors.KotlinClassKindTypes import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt index 05896d11..a5d0bd33 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPageContentBuilder.kt @@ -2,8 +2,8 @@ package org.jetbrains.dokka.kotlinAsJava 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.transformers.psi.JavaTypeWrapper import org.jetbrains.dokka.utilities.DokkaLogger class KotlinAsJavaPageContentBuilder( diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt index 345dc9be..e99e0843 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinAsJavaPlugin.kt @@ -12,8 +12,12 @@ import org.jetbrains.dokka.transformers.documentation.DocumentationToPageTransla import org.jetbrains.kotlin.descriptors.DeclarationDescriptor class KotlinAsJavaPlugin : DokkaPlugin() { - val kotlinAsJavaDescriptorToDocumentableTranslator by extending { CoreExtensions.descriptorToDocumentationTranslator with KotlinAsJavaDescriptorToDocumentationTranslator } - val kotlinAsJavaDocumentableToPageTranslator by extending { CoreExtensions.documentationToPageTranslator with KotlinAsJavaDocumentationToPageTranslator } + val kotlinAsJavaDescriptorToDocumentableTranslator by extending { + CoreExtensions.descriptorToDocumentationTranslator providing ::KotlinAsJavaDescriptorToDocumentationTranslator + } + val kotlinAsJavaDocumentableToPageTranslator by extending { + CoreExtensions.documentationToPageTranslator with KotlinAsJavaDocumentationToPageTranslator + } } object DescriptorCache { diff --git a/plugins/kotlin-as-java/src/main/kotlin/KotlinToJVMResolver.kt b/plugins/kotlin-as-java/src/main/kotlin/KotlinToJVMResolver.kt index 87a173f3..7b0495e9 100644 --- a/plugins/kotlin-as-java/src/main/kotlin/KotlinToJVMResolver.kt +++ b/plugins/kotlin-as-java/src/main/kotlin/KotlinToJVMResolver.kt @@ -5,7 +5,6 @@ import org.jetbrains.dokka.links.* import org.jetbrains.dokka.model.* import org.jetbrains.dokka.model.Function import org.jetbrains.dokka.model.Enum -import org.jetbrains.dokka.transformers.psi.JavaTypeWrapper import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor |