diff options
author | Paweł Marks <pmarks@virtuslab.com> | 2019-10-31 22:58:42 +0100 |
---|---|---|
committer | Paweł Marks <pmarks@virtuslab.com> | 2019-10-31 22:58:42 +0100 |
commit | 5f36bdd75e32743f54193aa8eff8cd5185b3cf67 (patch) | |
tree | 51c148449cfec75b455bea34eba89aed0189ebf6 /core/src/main | |
parent | 2f293770a61220b7ab3a26ea459c4a52501ec053 (diff) | |
download | dokka-5f36bdd75e32743f54193aa8eff8cd5185b3cf67.tar.gz dokka-5f36bdd75e32743f54193aa8eff8cd5185b3cf67.tar.bz2 dokka-5f36bdd75e32743f54193aa8eff8cd5185b3cf67.zip |
Adds transformation from descriptors to documentation graph
Diffstat (limited to 'core/src/main')
6 files changed, 192 insertions, 39 deletions
diff --git a/core/src/main/kotlin/DokkaDescriptorVisitor.kt b/core/src/main/kotlin/DokkaDescriptorVisitor.kt new file mode 100644 index 00000000..e2485a2c --- /dev/null +++ b/core/src/main/kotlin/DokkaDescriptorVisitor.kt @@ -0,0 +1,86 @@ +package org.jetbrains.dokka + +import org.jetbrains.dokka.Model.* +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.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope + +object DokkaDescriptorVisitor : DeclarationDescriptorVisitorEmptyBodies<DocumentationNode<*>, DRI>() { + 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()) + return Package( + dri, + descriptor.getMemberScope().functions(dri), + descriptor.getMemberScope().properties(dri), + descriptor.getMemberScope().classes(dri) + ) + } + + override fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRI): Class { + val dri = parent.withClass(descriptor.name.asString()) + return Class( + dri, + descriptor.name.asString(), + descriptor.getMemberScope(emptyList()).functions(dri), + descriptor.getMemberScope(emptyList()).properties(dri), + descriptor.getMemberScope(emptyList()).classes(dri), + descriptor + ) + } + + override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRI): Property { + val dri = parent.copy(callable = Callable.Companion.from(descriptor)) + return Property( + dri, + descriptor.name.asString(), + descriptor.extensionReceiverParameter?.let { visitReceiverParameterDescriptor(it, dri) }, + descriptor + ) + } + + override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRI): Function { + val dri = parent.copy(callable = Callable.Companion.from(descriptor)) + return Function( + dri, + descriptor.name.asString(), + descriptor.extensionReceiverParameter?.let { visitReceiverParameterDescriptor(it, dri) }, + descriptor.valueParameters.mapIndexed { index, desc -> parameter(index, desc, dri) }, + descriptor + ) + } + + override fun visitReceiverParameterDescriptor( + descriptor: ReceiverParameterDescriptor, + parent: DRI + ) = Parameter(parent.copy(target = 0), null, descriptor) + + private fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRI) = + Parameter(parent.copy(target = index + 1), descriptor.name.asString(), descriptor) + + private fun MemberScope.functions(parent: DRI): List<Function> = + getContributedDescriptors(DescriptorKindFilter.FUNCTIONS) { true } + .filterIsInstance<FunctionDescriptor>() + .map { visitFunctionDescriptor(it, parent) } + + private fun MemberScope.properties(parent: DRI): List<Property> = + getContributedDescriptors(DescriptorKindFilter.VALUES) { true } + .filterIsInstance<PropertyDescriptor>() + .map { visitPropertyDescriptor(it, parent) } + + private fun MemberScope.classes(parent: DRI): List<Class> = + getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) { true } + .filterIsInstance<ClassDescriptor>() + .map { visitClassDescriptor(it, parent) } +} diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt index abb6f069..f1aa7b71 100644 --- a/core/src/main/kotlin/DokkaGenerator.kt +++ b/core/src/main/kotlin/DokkaGenerator.kt @@ -1,13 +1,62 @@ package org.jetbrains.dokka +import kotlinx.html.DD +import org.jetbrains.dokka.Model.Module +import org.jetbrains.dokka.Utilities.pretty +import org.jetbrains.dokka.links.DRI +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.utils.PathUtil +import java.io.File + class DokkaGenerator( - private val configurationWithLinks: DokkaConfiguration, + private val configuration: DokkaConfiguration, private val logger: DokkaLogger ) { - fun generate() { - println("RUNNED") - logger.error("runned") - throw AssertionError() + fun generate() = configuration.passesConfigurations.forEach { 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.visitPackageFragmentDescriptor(it, DRI.topLevel) } + .toList() + .let { Module(it) } + }.also { println("${pass.analysisPlatform}:\n${it.pretty()}\n\n") } } + } + +private class DokkaMessageCollector(private val logger: DokkaLogger) : MessageCollector { + override fun clear() { + seenErrors = false + } + + private var seenErrors = false + + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { + if (severity == CompilerMessageSeverity.ERROR) { + seenErrors = true + } + logger.error(MessageRenderer.PLAIN_FULL_PATHS.render(severity, message, location)) + } + + override fun hasErrors() = seenErrors +}
\ 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 8da099ca..1871e21c 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,72 +1,73 @@ package org.jetbrains.dokka.Model -import org.jetbrains.dokka.links.Callable import org.jetbrains.dokka.links.DRI -import org.jetbrains.dokka.links.withClass import org.jetbrains.kotlin.descriptors.* -class Module(val packages: List<Package>) : DocumentationNode<Nothing>(DRI.topLevel, DRI.topLevel) { +class Module(val packages: List<Package>) : DocumentationNode<Nothing>() { + override val dri: DRI + get() = DRI.topLevel + override val children: List<Package> get() = packages } class Package( - val name: String, + override val dri: DRI, override val functions: List<Function>, override val properties: List<Property>, override val classes: List<Class> -) : ScopeNode<Nothing>(DRI(packageName = name), DRI.topLevel) +) : ScopeNode<Nothing>() { + val name = dri.packageName.orEmpty() +} class Class( + override val dri: DRI, val name: String, override val functions: List<Function>, override val properties: List<Property>, override val classes: List<Class>, - override val descriptor: ClassDescriptor, - parent: DRI -) : ScopeNode<ClassDescriptor>(parent.withClass(name), parent) + override val descriptor: ClassDescriptor +) : ScopeNode<ClassDescriptor>() class Function( + override val dri: DRI, val name: String, override val receiver: Parameter?, val parameters: List<Parameter>, - override val descriptor: FunctionDescriptor, - parent: DRI -) : CallableNode<FunctionDescriptor>(parent, descriptor) { + override val descriptor: FunctionDescriptor +) : CallableNode<FunctionDescriptor>() { override val children: List<Parameter> get() = listOfNotNull(receiver) + parameters } class Property( + override val dri: DRI, val name: String, override val receiver: Parameter?, - override val descriptor: PropertyDescriptor, - parent: DRI -) : CallableNode<PropertyDescriptor>(parent, descriptor) { + override val descriptor: PropertyDescriptor +) : CallableNode<PropertyDescriptor>() { override val children: List<Parameter> get() = listOfNotNull(receiver) } class Parameter( - val name: String, - override val descriptor: ParameterDescriptor, - parent: DRI, - index: Int -) : DocumentationNode<ParameterDescriptor>(parent, parent.copy(target = index)) { + override val dri: DRI, + val name: String?, + override val descriptor: ParameterDescriptor +) : DocumentationNode<ParameterDescriptor>() { override val children: List<DocumentationNode<*>> get() = emptyList() } -abstract class DocumentationNode<out T : DeclarationDescriptor>( - val dri: DRI, - val parent: DRI -) { +abstract class DocumentationNode<out T : DeclarationDescriptor> { open val descriptor: T? = null + abstract val dri: DRI + abstract val children: List<DocumentationNode<*>> override fun toString(): String { - return "${javaClass.name}($dri)" + return "${javaClass.simpleName}($dri)" } override fun equals(other: Any?) = other is DocumentationNode<*> && this.dri == other.dri @@ -74,10 +75,7 @@ abstract class DocumentationNode<out T : DeclarationDescriptor>( override fun hashCode() = dri.hashCode() } -abstract class ScopeNode<out T : ClassOrPackageFragmentDescriptor>( - dri: DRI, - parent: DRI -) : DocumentationNode<T>(dri, parent) { +abstract class ScopeNode<out T : ClassOrPackageFragmentDescriptor> : DocumentationNode<T>() { abstract val functions: List<Function> abstract val properties: List<Property> abstract val classes: List<Class> @@ -86,9 +84,6 @@ abstract class ScopeNode<out T : ClassOrPackageFragmentDescriptor>( get() = functions + properties + classes } -abstract class CallableNode<out T: CallableDescriptor>( - parent: DRI, - descriptor: CallableDescriptor -) : DocumentationNode<T>(parent.copy(callable = Callable.from(descriptor)), parent) { +abstract class CallableNode<out T : CallableDescriptor> : DocumentationNode<T>() { abstract val receiver: Parameter? }
\ No newline at end of file diff --git a/core/src/main/kotlin/Utilities/nodeDebug.kt b/core/src/main/kotlin/Utilities/nodeDebug.kt new file mode 100644 index 00000000..423e3e5f --- /dev/null +++ b/core/src/main/kotlin/Utilities/nodeDebug.kt @@ -0,0 +1,24 @@ +package org.jetbrains.dokka.Utilities + +import org.jetbrains.dokka.Model.DocumentationNode +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +const val DOWN = '\u2503' +const val BRANCH = '\u2523' +const val LAST = '\u2517' + +fun <T : DeclarationDescriptor> DocumentationNode<T>.pretty(prefix: String = "", isLast: Boolean = true): String { + val nextPrefix = prefix + (if (isLast) ' ' else DOWN) + ' ' + + return prefix + (if (isLast) LAST else BRANCH) + this.toString() + children.dropLast(1).map { + it.pretty( + nextPrefix, + false + ) + }.plus( + children.lastOrNull()?.pretty(nextPrefix) + ).filterNotNull().takeIf { it.isNotEmpty() }?.joinToString( + prefix = "\n", + separator = "" + ).orEmpty() + if (children.isEmpty()) "\n" else "" +}
\ No newline at end of file diff --git a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt index fd2e6797..010c46f4 100644 --- a/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt +++ b/core/src/main/kotlin/transformers/DefaultDocumentationToPageTransformer.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka.transformers -import org.jetbrains.dokka.DocumentationNode import org.jetbrains.dokka.pages.ContentNode import org.jetbrains.dokka.pages.ContentSymbol import org.jetbrains.dokka.pages.ModulePageNode diff --git a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt b/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt index b410915c..bf9a80ea 100644 --- a/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt +++ b/core/src/main/kotlin/transformers/DocumentationToPageTransformer.kt @@ -1,6 +1,6 @@ package org.jetbrains.dokka.transformers -import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.Model.DocumentationNode import org.jetbrains.dokka.pages.PageNode interface DocumentationToPageTransformer { |