aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrzej Ratajczak <andrzej.ratajczak98@gmail.com>2020-09-22 11:08:16 +0200
committerAndrzej Ratajczak <32793002+BarkingBad@users.noreply.github.com>2020-10-02 12:40:50 +0200
commit8de5296b18083361055d11acf6d522c1eef821a4 (patch)
tree5e4f4c42bf801f33c40c4efeb5601e0fc4523e36
parent71b03f6d311c6ebfdf67c593e97a7483a64844f4 (diff)
downloaddokka-8de5296b18083361055d11acf6d522c1eef821a4.tar.gz
dokka-8de5296b18083361055d11acf6d522c1eef821a4.tar.bz2
dokka-8de5296b18083361055d11acf6d522c1eef821a4.zip
Make translators run in parallel.
-rw-r--r--.idea/codeStyles/Project.xml2
-rw-r--r--core/build.gradle.kts3
-rw-r--r--core/src/main/kotlin/DokkaGenerator.kt13
-rw-r--r--core/src/main/kotlin/plugability/LazyEvaluated.kt3
-rw-r--r--core/src/main/kotlin/transformers/sources/SourceToDocumentableTranslator.kt4
-rw-r--r--core/src/main/kotlin/utilities/parallelCollectionOperations.kt17
-rw-r--r--plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt2
-rw-r--r--plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt831
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt364
9 files changed, 697 insertions, 542 deletions
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 69ebce06..f063496e 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -14,4 +14,4 @@
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
-</component> \ No newline at end of file
+</component>
diff --git a/core/build.gradle.kts b/core/build.gradle.kts
index f4fb1017..971f08f4 100644
--- a/core/build.gradle.kts
+++ b/core/build.gradle.kts
@@ -12,6 +12,9 @@ dependencies {
implementation("org.jsoup:jsoup:1.12.1")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.11.1")
+ val coroutines_version: String by project
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version")
+
testImplementation(project(":core:test-api"))
testImplementation(kotlin("test-junit"))
}
diff --git a/core/src/main/kotlin/DokkaGenerator.kt b/core/src/main/kotlin/DokkaGenerator.kt
index 6f42b259..bee85325 100644
--- a/core/src/main/kotlin/DokkaGenerator.kt
+++ b/core/src/main/kotlin/DokkaGenerator.kt
@@ -9,6 +9,8 @@ import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.DokkaPlugin
import org.jetbrains.dokka.utilities.DokkaLogger
import org.jetbrains.dokka.utilities.report
+import kotlinx.coroutines.*
+import org.jetbrains.dokka.utilities.parallelMap
/**
@@ -73,9 +75,10 @@ class DokkaGenerator(
fun createDocumentationModels(
context: DokkaContext
- ) = context.configuration.sourceSets
- .flatMap { sourceSet -> translateSources(sourceSet, context) }
- .also { modules -> if (modules.isEmpty()) exitGenerationGracefully("Nothing to document") }
+ ) = runBlocking(Dispatchers.Default) {
+ context.configuration.sourceSets.parallelMap { sourceSet -> translateSources(sourceSet, context) }.flatten()
+ .also { modules -> if (modules.isEmpty()) exitGenerationGracefully("Nothing to document") }
+ }
fun transformDocumentationModelBeforeMerge(
modulesFromPlatforms: List<DModule>,
@@ -133,8 +136,8 @@ class DokkaGenerator(
}
}
- private fun translateSources(sourceSet: DokkaSourceSet, context: DokkaContext) =
- context[CoreExtensions.sourceToDocumentableTranslator].map {
+ private suspend fun translateSources(sourceSet: DokkaSourceSet, context: DokkaContext) =
+ context[CoreExtensions.sourceToDocumentableTranslator].parallelMap {
it.invoke(sourceSet, context)
}
}
diff --git a/core/src/main/kotlin/plugability/LazyEvaluated.kt b/core/src/main/kotlin/plugability/LazyEvaluated.kt
index c0c271f4..17fad525 100644
--- a/core/src/main/kotlin/plugability/LazyEvaluated.kt
+++ b/core/src/main/kotlin/plugability/LazyEvaluated.kt
@@ -2,6 +2,7 @@ package org.jetbrains.dokka.plugability
internal class LazyEvaluated<T : Any> private constructor(private val recipe: ((DokkaContext) -> T)? = null, private var value: T? = null) {
+ @Synchronized
internal fun get(context: DokkaContext): T {
if(value == null) {
value = recipe?.invoke(context)
@@ -13,4 +14,4 @@ internal class LazyEvaluated<T : Any> private constructor(private val recipe: ((
fun <T : Any> fromInstance(value: T) = LazyEvaluated(value = value)
fun <T : Any> fromRecipe(recipe: (DokkaContext) -> T) = LazyEvaluated(recipe = recipe)
}
-} \ No newline at end of file
+}
diff --git a/core/src/main/kotlin/transformers/sources/SourceToDocumentableTranslator.kt b/core/src/main/kotlin/transformers/sources/SourceToDocumentableTranslator.kt
index 6bc8fb14..8ac59a15 100644
--- a/core/src/main/kotlin/transformers/sources/SourceToDocumentableTranslator.kt
+++ b/core/src/main/kotlin/transformers/sources/SourceToDocumentableTranslator.kt
@@ -5,5 +5,5 @@ import org.jetbrains.dokka.model.DModule
import org.jetbrains.dokka.plugability.DokkaContext
interface SourceToDocumentableTranslator {
- fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule
-} \ No newline at end of file
+ suspend fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule
+}
diff --git a/core/src/main/kotlin/utilities/parallelCollectionOperations.kt b/core/src/main/kotlin/utilities/parallelCollectionOperations.kt
new file mode 100644
index 00000000..b3191e8b
--- /dev/null
+++ b/core/src/main/kotlin/utilities/parallelCollectionOperations.kt
@@ -0,0 +1,17 @@
+package org.jetbrains.dokka.utilities
+
+import kotlinx.coroutines.async
+import kotlinx.coroutines.awaitAll
+import kotlinx.coroutines.coroutineScope
+
+suspend inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> = coroutineScope {
+ map { async { f(it) } }.awaitAll()
+}
+
+suspend inline fun <A, B> Iterable<A>.parallelMapNotNull(crossinline f: suspend (A) -> B?): List<B> = coroutineScope {
+ map { async { f(it) } }.awaitAll().filterNotNull()
+}
+
+suspend inline fun <A> Iterable<A>.parallelForEach(crossinline f: suspend (A) -> Unit): Unit = coroutineScope {
+ map { async { f(it) } }.awaitAll()
+}
diff --git a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
index 47180042..5c0f54d8 100644
--- a/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
+++ b/plugins/base/src/main/kotlin/renderers/DefaultRenderer.kt
@@ -228,4 +228,4 @@ fun ContentPage.sourceSets() = this.content.sourceSets
fun ContentEmbeddedResource.isImage(): Boolean {
val imageExtensions = setOf("png", "jpg", "jpeg", "gif", "bmp", "tif", "webp", "svg")
return File(address).extension.toLowerCase() in imageExtensions
-} \ No newline at end of file
+}
diff --git a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
index ecfd5172..d64a7b29 100644
--- a/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/descriptors/DefaultDescriptorToDocumentableTranslator.kt
@@ -1,5 +1,9 @@
package org.jetbrains.dokka.base.translators.descriptors
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.async
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.withContext
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.analysis.DescriptorDocumentableSource
import org.jetbrains.dokka.analysis.DokkaResolutionFacade
@@ -18,8 +22,9 @@ import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
import org.jetbrains.dokka.utilities.DokkaLogger
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
+import org.jetbrains.dokka.utilities.parallelMap
+import org.jetbrains.dokka.utilities.parallelMapNotNull
import org.jetbrains.kotlin.builtins.isExtensionFunctionType
-import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
import org.jetbrains.kotlin.codegen.isJvmStaticInObjectOrClassOrInterface
import org.jetbrains.kotlin.descriptors.*
@@ -27,7 +32,6 @@ import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
-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.load.kotlin.toSourceElement
@@ -40,7 +44,6 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.LocalClass
import org.jetbrains.kotlin.resolve.constants.KClassValue.Value.NormalClass
import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
-import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
@@ -49,6 +52,7 @@ import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
import org.jetbrains.kotlin.types.typeUtil.supertypes
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
+import java.lang.IllegalStateException
import java.nio.file.Paths
import org.jetbrains.kotlin.resolve.constants.AnnotationValue as ConstantsAnnotationValue
import org.jetbrains.kotlin.resolve.constants.ArrayValue as ConstantsArrayValue
@@ -59,7 +63,7 @@ class DefaultDescriptorToDocumentableTranslator(
private val kotlinAnalysis: KotlinAnalysis
) : SourceToDocumentableTranslator {
- override fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
+ override suspend fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
val (environment, facade) = kotlinAnalysis[sourceSet]
val packageFragments = environment.getSourceFiles().asSequence()
.map { it.packageFqName }
@@ -68,7 +72,7 @@ class DefaultDescriptorToDocumentableTranslator(
.toList()
return DokkaDescriptorVisitor(sourceSet, kotlinAnalysis[sourceSet].facade, context.logger).run {
- packageFragments.mapNotNull { it.safeAs<PackageFragmentDescriptor>() }.map {
+ packageFragments.mapNotNull { it.safeAs<PackageFragmentDescriptor>() }.parallelMap {
visitPackageFragmentDescriptor(
it,
DRIWithPlatformInfo(DRI.topLevel, emptyMap())
@@ -97,11 +101,7 @@ private class DokkaDescriptorVisitor(
private val sourceSet: DokkaSourceSet,
private val resolutionFacade: DokkaResolutionFacade,
private val logger: DokkaLogger
-) : DeclarationDescriptorVisitorEmptyBodies<Documentable, DRIWithPlatformInfo>() {
- override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor, parent: DRIWithPlatformInfo): Nothing {
- throw IllegalStateException("${javaClass.simpleName} should never enter ${descriptor.javaClass.simpleName}")
- }
-
+) {
private fun Collection<DeclarationDescriptor>.filterDescriptorsInSourceSet() = filter {
it.toSourceElement.containingFile.toString().let { path ->
path.isNotBlank() && sourceSet.sourceRoots.any { root ->
@@ -112,26 +112,34 @@ private class DokkaDescriptorVisitor(
private fun <T> T.toSourceSetDependent() = mapOf(sourceSet to this)
- override fun visitPackageFragmentDescriptor(
+ suspend fun visitPackageFragmentDescriptor(
descriptor: PackageFragmentDescriptor,
parent: DRIWithPlatformInfo
): DPackage {
val name = descriptor.fqName.asString().takeUnless { it.isBlank() } ?: ""
val driWithPlatform = DRI(packageName = name).withEmptyInfo()
val scope = descriptor.getMemberScope()
-
- return DPackage(
- dri = driWithPlatform.dri,
- functions = scope.functions(driWithPlatform, true),
- properties = scope.properties(driWithPlatform, true),
- classlikes = scope.classlikes(driWithPlatform, true),
- typealiases = scope.typealiases(driWithPlatform, true),
- documentation = descriptor.resolveDescriptorData(),
- sourceSets = setOf(sourceSet)
- )
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind(true)
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+ val typealiases = async { descriptorsWithKind.typealiases.visitTypealiases(driWithPlatform) }
+
+ DPackage(
+ dri = driWithPlatform.dri,
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ typealiases = typealiases.await(),
+ documentation = descriptor.resolveDescriptorData(),
+ sourceSets = setOf(sourceSet)
+ )
+ }
}
- override fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClasslike =
+ private suspend fun visitClassDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClasslike =
when (descriptor.kind) {
ClassKind.ENUM_CLASS -> enumDescriptor(descriptor, parent)
ClassKind.OBJECT -> objectDescriptor(descriptor, parent)
@@ -140,37 +148,46 @@ private class DokkaDescriptorVisitor(
else -> classDescriptor(descriptor, parent)
}
- private fun interfaceDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DInterface {
+ private suspend fun interfaceDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DInterface {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
val info = descriptor.resolveClassDescriptionData()
- return DInterface(
- dri = driWithPlatform.dri,
- name = descriptor.name.asString(),
- functions = scope.functions(driWithPlatform),
- properties = scope.properties(driWithPlatform),
- classlikes = scope.classlikes(driWithPlatform),
- sources = descriptor.createSources(),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- supertypes = info.supertypes.toSourceSetDependent(),
- documentation = info.docs,
- generics = descriptor.declaredTypeParameters.map { it.toVariantTypeParameter() },
- companion = descriptor.companion(driWithPlatform),
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind()
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+ val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } }
+
+ DInterface(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ sources = descriptor.createSources(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ documentation = info.docs,
+ generics = generics.await(),
+ companion = descriptor.companion(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
)
- )
+ }
}
- private fun objectDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DObject {
+ private suspend fun objectDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DObject {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
@@ -178,109 +195,149 @@ private class DokkaDescriptorVisitor(
val info = descriptor.resolveClassDescriptionData()
- return DObject(
- dri = driWithPlatform.dri,
- name = descriptor.name.asString(),
- functions = scope.functions(driWithPlatform),
- properties = scope.properties(driWithPlatform),
- classlikes = scope.classlikes(driWithPlatform),
- sources = descriptor.createSources(),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- supertypes = info.supertypes.toSourceSetDependent(),
- documentation = info.docs,
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind()
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+
+ DObject(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ sources = descriptor.createSources(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ documentation = info.docs,
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
)
- )
+ }
+
+
}
- private fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnum {
+ private suspend fun enumDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnum {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
val info = descriptor.resolveClassDescriptionData()
- return DEnum(
- dri = driWithPlatform.dri,
- name = descriptor.name.asString(),
- entries = scope.enumEntries(driWithPlatform),
- constructors = descriptor.constructors.map { visitConstructorDescriptor(it, driWithPlatform) },
- functions = scope.functions(driWithPlatform),
- properties = scope.properties(driWithPlatform),
- classlikes = scope.classlikes(driWithPlatform),
- sources = descriptor.createSources(),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- supertypes = info.supertypes.toSourceSetDependent(),
- documentation = info.docs,
- companion = descriptor.companion(driWithPlatform),
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind()
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+ val constructors = async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } }
+ val entries = async { descriptorsWithKind.enumEntries.visitEnumEntries(driWithPlatform) }
+
+ DEnum(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ entries = entries.await(),
+ constructors = constructors.await(),
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ sources = descriptor.createSources(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ documentation = info.docs,
+ companion = descriptor.companion(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
+ )
)
- )
+ }
}
- private fun enumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnumEntry {
+ private suspend fun visitEnumEntryDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DEnumEntry {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
- return DEnumEntry(
- dri = driWithPlatform.dri,
- name = descriptor.name.asString(),
- documentation = descriptor.resolveDescriptorData(),
- classlikes = scope.classlikes(driWithPlatform),
- functions = scope.functions(driWithPlatform),
- properties = scope.properties(driWithPlatform),
- sourceSets = setOf(sourceSet),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- extra = PropertyContainer.withAll(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ConstructorValues(descriptor.getAppliedConstructorParameters().toSourceSetDependent())
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind()
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+
+ DEnumEntry(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ documentation = descriptor.resolveDescriptorData(),
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ sourceSets = setOf(sourceSet),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ConstructorValues(descriptor.getAppliedConstructorParameters().toSourceSetDependent())
+ )
)
- )
+ }
}
- fun annotationDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DAnnotation {
+ private suspend fun annotationDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DAnnotation {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
- return DAnnotation(
- dri = driWithPlatform.dri,
- name = descriptor.name.asString(),
- documentation = descriptor.resolveDescriptorData(),
- classlikes = scope.classlikes(driWithPlatform),
- functions = scope.functions(driWithPlatform),
- properties = scope.properties(driWithPlatform),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
- ),
- companion = descriptor.companionObjectDescriptor?.let { objectDescriptor(it, driWithPlatform) },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- generics = descriptor.declaredTypeParameters.map { it.toVariantTypeParameter() },
- constructors = descriptor.constructors.map { visitConstructorDescriptor(it, driWithPlatform) },
- sources = descriptor.createSources()
- )
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind()
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+ val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } }
+ val constructors = async { descriptor.constructors.parallelMap { visitConstructorDescriptor(it, driWithPlatform) } }
+
+ DAnnotation(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ documentation = descriptor.resolveDescriptorData(),
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ ),
+ companion = descriptor.companionObjectDescriptor?.let { objectDescriptor(it, driWithPlatform) },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ generics = generics.await(),
+ constructors = constructors.await(),
+ sources = descriptor.createSources()
+ )
+ }
+
+
}
- private fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClass {
+ private suspend fun classDescriptor(descriptor: ClassDescriptor, parent: DRIWithPlatformInfo): DClass {
val driWithPlatform = parent.dri.withClass(descriptor.name.asString()).withEmptyInfo()
val scope = descriptor.unsubstitutedMemberScope
val isExpect = descriptor.isExpect
@@ -288,163 +345,188 @@ private class DokkaDescriptorVisitor(
val info = descriptor.resolveClassDescriptionData()
val actual = descriptor.createSources()
- return DClass(
- dri = driWithPlatform.dri,
- name = descriptor.name.asString(),
- constructors = descriptor.constructors.map {
- visitConstructorDescriptor(
- it,
- if (it.isPrimary) DRIWithPlatformInfo(driWithPlatform.dri, actual)
- else DRIWithPlatformInfo(driWithPlatform.dri, emptyMap())
+ return coroutineScope {
+ val descriptorsWithKind = scope.getDescriptorsWithKind()
+
+ val functions = async { descriptorsWithKind.functions.visitFunctions(driWithPlatform) }
+ val properties = async { descriptorsWithKind.properties.visitProperties(driWithPlatform) }
+ val classlikes = async { descriptorsWithKind.classlikes.visitClasslikes(driWithPlatform) }
+ val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } }
+ val constructors = async {
+ descriptor.constructors.parallelMap {
+ visitConstructorDescriptor(
+ it,
+ if (it.isPrimary) DRIWithPlatformInfo(driWithPlatform.dri, actual)
+ else DRIWithPlatformInfo(driWithPlatform.dri, emptyMap())
+ )
+ }
+ }
+
+ DClass(
+ dri = driWithPlatform.dri,
+ name = descriptor.name.asString(),
+ constructors = constructors.await(),
+ functions = functions.await(),
+ properties = properties.await(),
+ classlikes = classlikes.await(),
+ sources = actual,
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ supertypes = info.supertypes.toSourceSetDependent(),
+ generics = generics.await(),
+ documentation = info.docs,
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ companion = descriptor.companion(driWithPlatform),
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll<DClass>(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
+ ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
)
- },
- functions = scope.functions(driWithPlatform),
- properties = scope.properties(driWithPlatform),
- classlikes = scope.classlikes(driWithPlatform),
- sources = actual,
- expectPresentInSet = sourceSet.takeIf { isExpect },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- supertypes = info.supertypes.toSourceSetDependent(),
- generics = descriptor.declaredTypeParameters.map { it.toVariantTypeParameter() },
- documentation = info.docs,
- modifier = descriptor.modifier().toSourceSetDependent(),
- companion = descriptor.companion(driWithPlatform),
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll<DClass>(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations(),
- ImplementedInterfaces(info.allImplementedInterfaces.toSourceSetDependent())
)
- )
+ }
}
- override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): DProperty {
+ private suspend fun visitPropertyDescriptor(descriptor: PropertyDescriptor, parent: DRIWithPlatformInfo): DProperty {
val dri = parent.dri.copy(callable = Callable.from(descriptor))
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
val actual = descriptor.createSources()
- return DProperty(
- dri = dri,
- name = descriptor.name.asString(),
- receiver = descriptor.extensionReceiverParameter?.let {
- visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
- },
- sources = actual,
- getter = descriptor.accessors.filterIsInstance<PropertyGetterDescriptor>().singleOrNull()?.let {
- visitPropertyAccessorDescriptor(it, descriptor, dri)
- },
- setter = descriptor.accessors.filterIsInstance<PropertySetterDescriptor>().singleOrNull()?.let {
- visitPropertyAccessorDescriptor(it, descriptor, dri)
- },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- documentation = descriptor.resolveDescriptorData(),
- modifier = descriptor.modifier().toSourceSetDependent(),
- type = descriptor.returnType!!.toBound(),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- sourceSets = setOf(sourceSet),
- generics = descriptor.typeParameters.map { it.toVariantTypeParameter() },
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(listOfNotNull(
- (descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField()
- .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations(),
- descriptor.getDefaultValue()?.let { DefaultValue(it) }
- ))
- )
+
+ return coroutineScope {
+ val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } }
+
+ DProperty(
+ dri = dri,
+ name = descriptor.name.asString(),
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
+ },
+ sources = actual,
+ getter = descriptor.accessors.filterIsInstance<PropertyGetterDescriptor>().singleOrNull()?.let {
+ visitPropertyAccessorDescriptor(it, descriptor, dri)
+ },
+ setter = descriptor.accessors.filterIsInstance<PropertySetterDescriptor>().singleOrNull()?.let {
+ visitPropertyAccessorDescriptor(it, descriptor, dri)
+ },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = descriptor.resolveDescriptorData(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ type = descriptor.returnType!!.toBound(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ sourceSets = setOf(sourceSet),
+ generics = generics.await(),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll(listOfNotNull(
+ (descriptor.additionalExtras() + descriptor.getAnnotationsWithBackingField()
+ .toAdditionalExtras()).toSet().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotationsWithBackingField().toSourceSetDependent().toAnnotations(),
+ descriptor.getDefaultValue()?.let { DefaultValue(it) }
+ ))
+ )
+ }
}
- fun CallableMemberDescriptor.createDRI(wasOverridenBy: DRI? = null): Pair<DRI, DRI?> =
+ private fun CallableMemberDescriptor.createDRI(wasOverridenBy: DRI? = null): Pair<DRI, DRI?> =
if (kind == CallableMemberDescriptor.Kind.DECLARATION || overriddenDescriptors.isEmpty())