From 49439594f86217d8a25e8df2580b8ef29d836230 Mon Sep 17 00:00:00 2001 From: Paweł Marks Date: Tue, 26 Nov 2019 13:44:27 +0100 Subject: Introduction of all important extension points and restructuring of DokkaGenerator --- core/src/main/kotlin/CoreExtensions.kt | 35 +++- core/src/main/kotlin/DokkaDescriptorVisitor.kt | 191 ----------------- core/src/main/kotlin/DokkaGenerator.kt | 183 +++++++++++----- core/src/main/kotlin/Model/DocumentationNode.kt | 2 +- .../transformers/DocumentationNodeTransformer.kt | 8 - .../Model/transformers/DocumentationNodesMerger.kt | 90 -------- .../pages/DefaultMarkdownToContentConverter.kt | 229 +++++++++++++++++++++ .../kotlin/pages/MarkdownToContentConverter.kt | 219 +------------------- .../pages/transformers/PageNodeTransformer.kt | 7 - .../main/kotlin/plugability/DefaultExtensions.kt | 25 +++ core/src/main/kotlin/plugability/DokkaContext.kt | 61 ++++-- core/src/main/kotlin/plugability/extensions.kt | 2 +- core/src/main/kotlin/renderers/DefaultRenderer.kt | 7 +- core/src/main/kotlin/renderers/HtmlRenderer.kt | 7 +- core/src/main/kotlin/renderers/Renderer.kt | 1 + .../kotlin/resolvers/DefaultLocationProvider.kt | 11 +- .../DefaultDocumentationToPageTransformer.kt | 20 -- .../transformers/DocumentationToPageTransformer.kt | 11 - .../kotlin/transformers/PageNodeTransformer.kt | 8 - .../DefaultDescriptorToDocumentationTranslator.kt | 208 +++++++++++++++++++ .../DescriptorToDocumentationTranslator.kt | 15 ++ .../DefaultDocumentationNodeMerger.kt | 86 ++++++++ .../DefaultDocumentationToPageTranslator.kt | 24 +++ .../documentation/DocumentationNodeMerger.kt | 8 + .../documentation/DocumentationNodeTransformer.kt | 8 + .../documentation/DocumentationToPageTranslator.kt | 12 ++ .../transformers/pages/PageNodeTransformer.kt | 8 + 27 files changed, 853 insertions(+), 633 deletions(-) delete mode 100644 core/src/main/kotlin/DokkaDescriptorVisitor.kt delete mode 100644 core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt delete mode 100644 core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt create mode 100644 core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt delete mode 100644 core/src/main/kotlin/pages/transformers/PageNodeTransformer.kt create mode 100644 core/src/main/kotlin/plugability/DefaultExtensions.kt delete mode 100644 core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt delete mode 100644 core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt delete mode 100644 core/src/main/kotlin/transformers/PageNodeTransformer.kt create mode 100644 core/src/main/kotlin/transformers/descriptors/DefaultDescriptorToDocumentationTranslator.kt create mode 100644 core/src/main/kotlin/transformers/descriptors/DescriptorToDocumentationTranslator.kt create mode 100644 core/src/main/kotlin/transformers/documentation/DefaultDocumentationNodeMerger.kt create mode 100644 core/src/main/kotlin/transformers/documentation/DefaultDocumentationToPageTranslator.kt create mode 100644 core/src/main/kotlin/transformers/documentation/DocumentationNodeMerger.kt create mode 100644 core/src/main/kotlin/transformers/documentation/DocumentationNodeTransformer.kt create mode 100644 core/src/main/kotlin/transformers/documentation/DocumentationToPageTranslator.kt create mode 100644 core/src/main/kotlin/transformers/pages/PageNodeTransformer.kt (limited to 'core/src') diff --git a/core/src/main/kotlin/CoreExtensions.kt b/core/src/main/kotlin/CoreExtensions.kt index 6579cab2..f56cd854 100644 --- a/core/src/main/kotlin/CoreExtensions.kt +++ b/core/src/main/kotlin/CoreExtensions.kt @@ -1,14 +1,37 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.Model.transformers.DocumentationNodeTransformer +import org.jetbrains.dokka.pages.MarkdownToContentConverter +import org.jetbrains.dokka.pages.PageNode +import org.jetbrains.dokka.plugability.DokkaContext import org.jetbrains.dokka.plugability.ExtensionPoint +import org.jetbrains.dokka.renderers.FileWriter import org.jetbrains.dokka.renderers.Renderer import org.jetbrains.dokka.resolvers.LocationProvider -import org.jetbrains.dokka.transformers.PageNodeTransformer +import org.jetbrains.dokka.transformers.descriptors.DescriptorToDocumentationTranslator +import org.jetbrains.dokka.transformers.documentation.DocumentationNodeMerger +import org.jetbrains.dokka.transformers.documentation.DocumentationNodeTransformer +import org.jetbrains.dokka.transformers.documentation.DocumentationToPageTranslator +import org.jetbrains.dokka.transformers.pages.PageNodeTransformer +import kotlin.reflect.KProperty + +/** + * Extension points declared by dokka core. + * Default values are stored in [org.jetbrains.dokka.plugability.DefaultExtensions] + */ object CoreExtensions { - val nodeTransformer = ExtensionPoint(this::class.qualifiedName!!, "nodeTransformer") - val pageTransformer = ExtensionPoint(this::class.qualifiedName!!, "pageTransformer") - val renderer = ExtensionPoint(this::class.qualifiedName!!, "renderer") - val locationProvider = ExtensionPoint(this::class.qualifiedName!!, "locationProvider") + val descriptorToDocumentationTranslator by coreExtension() + val documentationMerger by coreExtension() + val documentationTransformer by coreExtension() + val markdownToContentConverterFactory by coreExtension<(DokkaContext) -> MarkdownToContentConverter>() + val documentationToPageTranslator by coreExtension() + val pageTransformer by coreExtension() + val renderer by coreExtension<(FileWriter, LocationProvider, DokkaContext) -> Renderer>() + val locationProvider by coreExtension<(root: PageNode, DokkaConfiguration, DokkaContext) -> LocationProvider>() + val fileExtension by coreExtension() + + private fun coreExtension() = object { + operator fun provideDelegate(thisRef: CoreExtensions, property: KProperty<*>): Lazy> = + lazy { ExtensionPoint(thisRef::class.qualifiedName!!, property.name) } + } } \ No newline at end of file diff --git a/core/src/main/kotlin/DokkaDescriptorVisitor.kt b/core/src/main/kotlin/DokkaDescriptorVisitor.kt deleted file mode 100644 index 6c82f2c3..00000000 --- a/core/src/main/kotlin/DokkaDescriptorVisitor.kt +++ /dev/null @@ -1,191 +0,0 @@ -package org.jetbrains.dokka - -import org.jetbrains.dokka.Model.* -import org.jetbrains.dokka.Model.ClassKind -import org.jetbrains.dokka.Model.Function -import org.jetbrains.dokka.links.Callable -import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.withClass -import org.jetbrains.dokka.pages.PlatformData -import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies -import org.jetbrains.kotlin.idea.kdoc.findKDoc -import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink -import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink -import org.jetbrains.kotlin.kdoc.psi.impl.KDocName -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 - -class DokkaDescriptorVisitor( - private val platformData: PlatformData, - private val resolutionFacade: DokkaResolutionFacade -) : DeclarationDescriptorVisitorEmptyBodies() { - override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor, parent: DRI): Nothing { - throw IllegalStateException("${javaClass.simpleName} should never enter ${descriptor.javaClass.simpleName}") - } - - override fun visitPackageFragmentDescriptor( - descriptor: PackageFragmentDescriptor, - parent: DRI - ): Package { - val dri = DRI(packageName = descriptor.fqName.asString()) - val scope = descriptor.getMemberScope() - return Package( - dri, - scope.functions(dri), - scope.properties(dri), - scope.classes(dri) - ) - } - - override fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRI): Class { - val dri = parent.withClass(descriptor.name.asString()) - val scope = descriptor.getMemberScope(emptyList()) - val descriptorData = descriptor.takeUnless { it.isExpect }?.resolveClassDescriptionData() - return Class( - dri, - descriptor.name.asString(), - KotlinClassKindTypes.valueOf(descriptor.kind.toString()), - descriptor.constructors.map { visitConstructorDescriptor(it, dri) }, - scope.functions(dri), - scope.properties(dri), - scope.classes(dri), - descriptor.takeIf { it.isExpect }?.resolveClassDescriptionData(), - listOfNotNull(descriptorData), - getXMLDRIs(descriptor, descriptorData).toMutableSet() - ) - } - - override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRI): Property { - val dri = parent.copy(callable = Callable.from(descriptor)) - return Property( - dri, - descriptor.name.asString(), - descriptor.extensionReceiverParameter?.let { visitReceiverParameterDescriptor(it, dri) }, - descriptor.takeIf { it.isExpect }?.resolveDescriptorData(), - listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()) - ) - } - - override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRI): Function { - val dri = parent.copy(callable = Callable.from(descriptor)) - return Function( - dri, - descriptor.name.asString(), - descriptor.returnType?.let { KotlinTypeWrapper(it) }, - false, - descriptor.extensionReceiverParameter?.let { visitReceiverParameterDescriptor(it, dri) }, - descriptor.valueParameters.mapIndexed { index, desc -> parameter(index, desc, dri) }, - descriptor.takeIf { it.isExpect }?.resolveDescriptorData(), - listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()) - ) - } - - override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRI): Function { - val dri = parent.copy(callable = Callable.from(descriptor)) - return Function( - dri, - "", - KotlinTypeWrapper(descriptor.returnType), - true, - null, - descriptor.valueParameters.mapIndexed { index, desc -> parameter(index, desc, dri) }, - descriptor.takeIf { it.isExpect }?.resolveDescriptorData(), - listOfNotNull(descriptor.takeUnless { it.isExpect }?.resolveDescriptorData()) - ) - } - - override fun visitReceiverParameterDescriptor( - descriptor: ReceiverParameterDescriptor, - parent: DRI - ) = Parameter( - parent.copy(target = 0), - null, - KotlinTypeWrapper(descriptor.type), - listOf(descriptor.resolveDescriptorData()) - ) - - private fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRI) = - Parameter( - parent.copy(target = index + 1), - descriptor.name.asString(), - KotlinTypeWrapper(descriptor.type), - listOf(descriptor.resolveDescriptorData()) - ) - - private fun MemberScope.functions(parent: DRI): List = - getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) { true } - .filterIsInstance() - .map { visitFunctionDescriptor(it, parent) } - - private fun MemberScope.properties(parent: DRI): List = - getContributedDescriptors(DescriptorKindFilter.VALUES) { true } - .filterIsInstance() - .map { visitPropertyDescriptor(it, parent) } - - private fun MemberScope.classes(parent: DRI): List = - getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) { true } - .filterIsInstance() - .map { visitClassDescriptor(it, parent) } - - private fun DeclarationDescriptor.resolveDescriptorData(): PlatformInfo { - val doc = findKDoc() - val links = doc?.children?.filter { it is KDocLink }?.flatMap { link -> - val destination = link.children.first { it is KDocName }.text - resolveKDocLink( - resolutionFacade.resolveSession.bindingContext, - resolutionFacade, - this, - null, - destination.split('.') - ).map { Pair(destination, DRI.from(it)) } - }?.toMap() ?: emptyMap() - return BasePlatformInfo(doc, links, listOf(platformData)) - } - - private fun ClassDescriptor.resolveClassDescriptionData(): ClassPlatformInfo { - return ClassPlatformInfo(resolveDescriptorData(), - (getSuperInterfaces() + getAllSuperclassesWithoutAny()).map { DRI.from(it) }) - } - - private fun getXMLDRIs(descriptor: DeclarationDescriptor, platformInfo: PlatformInfo?) = - platformInfo?.docTag?.children - ?.filter { - it.text.contains("@attr") - }?.flatMap { ref -> - val matchResult = "@attr\\s+ref\\s+(.+)".toRegex().matchEntire(ref.text) - val toFind = matchResult?.groups?.last()?.value.orEmpty() - resolveKDocLink( - resolutionFacade.resolveSession.bindingContext, - resolutionFacade, - descriptor, - null, - toFind.split('.') - ).map { XMLMega("@attr ref", DRI.from(it)) } - }.orEmpty() -} - -data class XMLMega(val key: String, val dri: DRI) : Extra - -enum class KotlinClassKindTypes : ClassKind { - CLASS, - INTERFACE, - ENUM_CLASS, - ENUM_ENTRY, - ANNOTATION_CLASS, - OBJECT; -} - -class KotlinTypeWrapper(private val kotlinType: KotlinType) : TypeWrapper { - private val declarationDescriptor = kotlinType.constructor.declarationDescriptor - private val fqNameSafe = declarationDescriptor?.fqNameSafe - override val constructorFqName = fqNameSafe?.asString() - override val constructorNamePathSegments: List = - fqNameSafe?.pathSegments()?.map { it.asString() } ?: emptyList() - override val arguments: List by lazy { kotlinType.arguments.map { KotlinTypeWrapper(it.type) } } - override val dri: DRI? by lazy { declarationDescriptor?.let { DRI.from(it) } } -} \ No newline at end of file diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt index 05eb3054..b6bf7a73 100644 --- a/core/src/main/kotlin/DokkaGenerator.kt +++ b/core/src/main/kotlin/DokkaGenerator.kt @@ -1,20 +1,24 @@ package org.jetbrains.dokka import org.jetbrains.dokka.Model.Module -import org.jetbrains.dokka.Model.transformers.DocumentationNodesMerger import org.jetbrains.dokka.Utilities.pretty import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.pages.MarkdownToContentConverter +import org.jetbrains.dokka.pages.DefaultMarkdownToContentConverter import org.jetbrains.dokka.pages.PlatformData import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.plugability.single import org.jetbrains.dokka.renderers.FileWriter import org.jetbrains.dokka.renderers.HtmlRenderer import org.jetbrains.dokka.resolvers.DefaultLocationProvider -import org.jetbrains.dokka.transformers.DefaultDocumentationToPageTransformer +import org.jetbrains.dokka.resolvers.LocationProvider +import org.jetbrains.dokka.transformers.documentation.DefaultDocumentationToPageTranslator +import org.jetbrains.dokka.transformers.descriptors.DokkaDescriptorVisitor +import org.jetbrains.dokka.transformers.documentation.DefaultDocumentationNodeMerger import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageRenderer +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.utils.PathUtil import java.io.File @@ -22,56 +26,131 @@ class DokkaGenerator( private val configuration: DokkaConfiguration, private val logger: DokkaLogger ) { - fun generate(): Unit { + + fun generate() { + logger.debug("Setting up analysis environments") + val platforms: Map = configuration.passesConfigurations.map { + PlatformData(it.analysisPlatform, it.targets) to createEnvironmentAndFacade(it) + }.toMap() logger.debug("Initializing plugins") - val context = DokkaContext.create(configuration.pluginsClasspath, logger) - - configuration.passesConfigurations.map { pass -> - AnalysisEnvironment(DokkaMessageCollector(logger), pass.analysisPlatform).run { - if (analysisPlatform == Platform.jvm) { - addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) - } - for (element in pass.classpath) { - addClasspath(File(element)) - } - - addSources(pass.sourceRoots.map { it.path }) - - loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion) - - val environment = createCoreEnvironment() - val (facade, _) = createResolutionFacade(environment) - - environment.getSourceFiles().asSequence() - .map { it.packageFqName } - .distinct() - .mapNotNull { facade.resolveSession.getPackageFragment(it) } - .map { - DokkaDescriptorVisitor( - PlatformData(pass.analysisPlatform, pass.targets), - facade - ).visitPackageFragmentDescriptor( - it, - DRI.topLevel - ) - } - .toList() - .let { Module(it) } - .let { DocumentationNodesMerger(it) } - .also { println("${pass.analysisPlatform}:\n${it.pretty()}\n\n") } + val context = DokkaContext.create(configuration.pluginsClasspath, logger, platforms) + + logger.debug("Creating documentation models") + val modulesFromPlatforms = platforms.map { (pdata, _) -> translateDescriptors(pdata, context) } + + logger.debug("Merging documentation models") + val documentationModel = context.single(CoreExtensions.documentationMerger) + .invoke(modulesFromPlatforms, context) + + logger.debug("Transforming documentation model") + val transformedDocumentation = context[CoreExtensions.documentationTransformer] + .fold(documentationModel) { acc, t -> t(acc, context) } + + logger.debug("Creating pages") + val pages = context.single(CoreExtensions.documentationToPageTranslator) + .invoke(transformedDocumentation, context) + + logger.debug("Transforming pages") + val transformedPages = context[CoreExtensions.pageTransformer] + .fold(pages) { acc, t -> t(acc, context) } + + logger.debug("Rendering") + val fileWriter = FileWriter(configuration.outputDir, "") + val locationProvider = context.single(CoreExtensions.locationProvider) + .invoke(transformedPages, configuration, context) + val renderer = context.single(CoreExtensions.renderer) + .invoke(fileWriter, locationProvider, context) + + renderer.render(transformedPages) + } + +// fun generate(int: Int) { +// +// logger.debug("Initializing plugins") +// val context = DokkaContext.create(configuration.pluginsClasspath, logger, platforms) +// +// configuration.passesConfigurations.map { pass -> +// AnalysisEnvironment(DokkaMessageCollector(logger), pass.analysisPlatform).run { +// if (analysisPlatform == Platform.jvm) { +// addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) +// } +// for (element in pass.classpath) { +// addClasspath(File(element)) +// } +// +// addSources(pass.sourceRoots.map { it.path }) +// +// loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion) +// +// val environment = createCoreEnvironment() +// val (facade, _) = createResolutionFacade(environment) +// +// environment.getSourceFiles().asSequence() +// .map { it.packageFqName } +// .distinct() +// .mapNotNull { facade.resolveSession.getPackageFragment(it) } +// .map { +// DokkaDescriptorVisitor( +// PlatformData( +// pass.analysisPlatform, +// pass.targets +// ), facade +// ) +// .visitPackageFragmentDescriptor(it, DRI.topLevel) +// } +// .toList() +// .let { Module(it) } +// .let { DefaultDocumentationNodeMerger(it) } +// .also { println("${pass.analysisPlatform}:\n${it.pretty()}\n\n") } +// } +// }.let { +// val markdownConverter = DefaultMarkdownToContentConverter(logger) +// DefaultDocumentationToPageTranslator( +// markdownConverter, +// logger +// ).transform( +// DefaultDocumentationNodeMerger( +// it +// ) +// ) +// }.let { +// context[CoreExtensions.pageTransformer].fold(it) { pn, t -> t(pn, context) } +// }.also { +// HtmlRenderer( +// FileWriter(configuration.outputDir, ""), +// DefaultLocationProvider(it, configuration, ".${configuration.format}") +// ).render(it) +// } +// } + + private fun createEnvironmentAndFacade(pass: DokkaConfiguration.PassConfiguration): EnvironmentAndFacade = + AnalysisEnvironment(DokkaMessageCollector(logger), pass.analysisPlatform).run { + if (analysisPlatform == Platform.jvm) { + addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) } - }.let { - val markdownConverter = MarkdownToContentConverter(logger) - DefaultDocumentationToPageTransformer(markdownConverter, logger).transform(DocumentationNodesMerger(it)) - }.let { - context[CoreExtensions.pageTransformer].fold(it) { pn, t -> t.action.invoke(pn, context) } - }.also { - HtmlRenderer( - FileWriter(configuration.outputDir, ""), - DefaultLocationProvider(it, configuration, ".${configuration.format}") - ).render(it) + pass.classpath.forEach { addClasspath(File(it)) } + + addSources(pass.sourceRoots.map { it.path }) + + loadLanguageVersionSettings(pass.languageVersion, pass.apiVersion) + + val environment = createCoreEnvironment() + val (facade, _) = createResolutionFacade(environment) + EnvironmentAndFacade(environment, facade) } + + private fun translateDescriptors(platformData: PlatformData, context: DokkaContext): Module { + val (environment, facade) = context.platforms.getValue(platformData) + + val packageFragments = environment.getSourceFiles().asSequence() + .map { it.packageFqName } + .distinct() + .mapNotNull { facade.resolveSession.getPackageFragment(it) } + .toList() + + return context.single(CoreExtensions.descriptorToDocumentationTranslator) + .invoke(packageFragments, platformData, context) } private class DokkaMessageCollector(private val logger: DokkaLogger) : MessageCollector { @@ -90,4 +169,10 @@ class DokkaGenerator( override fun hasErrors() = seenErrors } +} + +// It is not data class due to ill-defined equals +class EnvironmentAndFacade(val environment: KotlinCoreEnvironment, val facade: DokkaResolutionFacade) { + operator fun component1() = environment + operator fun component2() = facade } \ No newline at end of file diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 0adb37b5..b1d4be55 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,6 +1,6 @@ package org.jetbrains.dokka.Model -import org.jetbrains.dokka.KotlinTypeWrapper +import org.jetbrains.dokka.transformers.descriptors.KotlinTypeWrapper import org.jetbrains.dokka.links.DRI import org.jetbrains.dokka.pages.PlatformData import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag diff --git a/core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt b/core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt deleted file mode 100644 index 318d20b3..00000000 --- a/core/src/main/kotlin/Model/transformers/DocumentationNodeTransformer.kt +++ /dev/null @@ -1,8 +0,0 @@ -package org.jetbrains.dokka.Model.transformers - -import org.jetbrains.dokka.Model.Module - -interface DocumentationNodeTransformer { - operator fun invoke(original: Module): Module - operator fun invoke(modules: Collection): Module -} \ No newline at end of file diff --git a/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt b/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt deleted file mode 100644 index ae4f8d99..00000000 --- a/core/src/main/kotlin/Model/transformers/DocumentationNodesMerger.kt +++ /dev/null @@ -1,90 +0,0 @@ -package org.jetbrains.dokka.Model.transformers - -import org.jetbrains.dokka.Model.* -import org.jetbrains.dokka.Model.Function - -internal object DocumentationNodesMerger : DocumentationNodeTransformer { - override fun invoke(original: Module) = Module( - original.packages.map { mergePackageContent(it) } - ) - override fun invoke(modules: Collection): Module = - Module(merge(modules.flatMap { it.packages }, Package::mergeWith)) -} - -private fun mergePackageContent(original: Package) = Package( - original.dri, - merge(original.functions, Function::mergeWith), - merge(original.properties, Property::mergeWith), - merge(original.classes, Class::mergeWith) -) - -private fun merge(elements: List, reducer: (T, T) -> T): List = - elements.groupingBy { it.dri } - .reduce { _, left, right -> reducer(left, right)} - .values.toList() - -fun PlatformInfo.mergeWith(other: PlatformInfo?) = BasePlatformInfo( - docTag, - links, - (platformData + (other?.platformData ?: emptyList())).distinct() -) - -fun ClassPlatformInfo.mergeWith(other: ClassPlatformInfo?) = ClassPlatformInfo( - info.mergeWith(other?.info), - (inherited + (other?.inherited ?: emptyList())).distinct() -) - -fun List.mergeClassPlatformInfo() : List = - groupingBy { it.docTag.toString() + it.links + it.inherited}.reduce { - _, left, right -> left.mergeWith(right) - }.values.toList() - -fun List.merge() : List = - groupingBy { it.docTag.toString() + it.links }.reduce { - _, left, right -> left.mergeWith(right) - }.values.toList() - -fun Function.mergeWith(other: Function) = Function( - dri, - name, - returnType, - isConstructor, - if (receiver != null && other.receiver != null) receiver.mergeWith(other.receiver) else null, - merge(parameters + other.parameters, Parameter::mergeWith), - expected?.mergeWith(other.expected), - (actual + other.actual).merge() -) - -fun Property.mergeWith(other: Property) = Property( - dri, - name, - if (receiver != null && other.receiver != null) receiver.mergeWith(other.receiver) else null, - expected?.mergeWith(other.expected), - (actual + other.actual).merge() -) - -fun Class.mergeWith(other: Class) = Class( - dri, - name, - kind, - merge(constructors + other.constructors, Function::mergeWith), - merge(functions + other.functions, Function::mergeWith), - merge(properties + other.properties, Property::mergeWith), - merge(classes + other.classes, Class::mergeWith), - expected?.mergeWith(other.expected), - (actual + other.actual).mergeClassPlatformInfo() -) - -fun Parameter.mergeWith(other: Parameter) = Parameter( - dri, - name, - type, - (actual + other.actual).merge() -) - -fun Package.mergeWith(other: Package) = Package( - dri, - merge(functions + other.functions, Function::mergeWith), - merge(properties + other.properties, Property::mergeWith), - merge(classes + other.classes, Class::mergeWith) -) \ No newline at end of file diff --git a/core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt b/core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt new file mode 100644 index 00000000..72b5ead2 --- /dev/null +++ b/core/src/main/kotlin/pages/DefaultMarkdownToContentConverter.kt @@ -0,0 +1,229 @@ +package org.jetbrains.dokka.pages + +import org.intellij.markdown.MarkdownElementTypes +import org.intellij.markdown.MarkdownTokenTypes +import org.jetbrains.dokka.MarkdownNode +import org.jetbrains.dokka.links.DRI +import org.jetbrains.dokka.plugability.DokkaContext + +class DefaultMarkdownToContentConverter( + private val context: DokkaContext +) : MarkdownToContentConverter { + override fun buildContent( + node: MarkdownNode, + dci: DCI, + platforms: Set, + links: Map, + styles: Set