aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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())
Pair(DRI.from(this), wasOverridenBy)
else
overriddenDescriptors.first().createDRI(DRI.from(this))
- override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): DFunction {
+ private suspend fun visitFunctionDescriptor(descriptor: FunctionDescriptor, parent: DRIWithPlatformInfo): DFunction {
val (dri, inheritedFrom) = descriptor.createDRI()
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
val actual = descriptor.createSources()
- return DFunction(
- dri = dri,
- name = descriptor.name.asString(),
- isConstructor = false,
- receiver = descriptor.extensionReceiverParameter?.let {
- visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
- },
- parameters = descriptor.valueParameters.mapIndexed { index, desc ->
- parameter(index, desc, DRIWithPlatformInfo(dri, actual))
- },
- expectPresentInSet = sourceSet.takeIf { isExpect },
- sources = actual,
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- generics = descriptor.typeParameters.map { it.toVariantTypeParameter() },
- documentation = descriptor.takeIf { it.kind != CallableMemberDescriptor.Kind.SYNTHESIZED }
- ?.resolveDescriptorData() ?: emptyMap(),
- modifier = descriptor.modifier().toSourceSetDependent(),
- type = descriptor.returnType!!.toBound(),
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(
- InheritedFunction(inheritedFrom.toSourceSetDependent()),
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ return coroutineScope {
+ val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } }
+
+ DFunction(
+ dri = dri,
+ name = descriptor.name.asString(),
+ isConstructor = false,
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
+ },
+ parameters = descriptor.valueParameters.mapIndexed { index, desc ->
+ parameter(index, desc, DRIWithPlatformInfo(dri, actual))
+ },
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ sources = actual,
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ generics = generics.await(),
+ documentation = descriptor.takeIf { it.kind != CallableMemberDescriptor.Kind.SYNTHESIZED }
+ ?.resolveDescriptorData() ?: emptyMap(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ type = descriptor.returnType!!.toBound(),
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll(
+ InheritedFunction(inheritedFrom.toSourceSetDependent()),
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ )
)
- )
+ }
}
- override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRIWithPlatformInfo): DFunction {
+ suspend fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, parent: DRIWithPlatformInfo): DFunction {
val name = descriptor.constructedClass.name.toString()
val dri = parent.dri.copy(callable = Callable.from(descriptor, name))
val actual = descriptor.createSources()
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
- return DFunction(
- dri = dri,
- name = name,
- isConstructor = true,
- receiver = descriptor.extensionReceiverParameter?.let {
- visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
- },
- parameters = descriptor.valueParameters.mapIndexed { index, desc ->
- parameter(index, desc, DRIWithPlatformInfo(dri, actual))
- },
- sources = actual,
- expectPresentInSet = sourceSet.takeIf { isExpect },
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- documentation = descriptor.resolveDescriptorData().let { sourceSetDependent ->
- if (descriptor.isPrimary) {
- sourceSetDependent.map { entry ->
- Pair(
- entry.key,
- entry.value.copy(children = (entry.value.children.find { it is Constructor }?.root?.let { constructor ->
- listOf(Description(constructor))
- } ?: emptyList<TagWrapper>()) + entry.value.children.filterIsInstance<Param>()))
- }.toMap()
- } else {
- sourceSetDependent
+ return coroutineScope {
+ val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } }
+
+ DFunction(
+ dri = dri,
+ name = name,
+ isConstructor = true,
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(it, DRIWithPlatformInfo(dri, actual))
+ },
+ parameters = descriptor.valueParameters.mapIndexed { index, desc ->
+ parameter(index, desc, DRIWithPlatformInfo(dri, actual))
+ },
+ sources = actual,
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = descriptor.resolveDescriptorData().let { sourceSetDependent ->
+ if (descriptor.isPrimary) {
+ sourceSetDependent.map { entry ->
+ Pair(
+ entry.key,
+ entry.value.copy(children = (entry.value.children.find { it is Constructor }?.root?.let { constructor ->
+ listOf(Description(constructor))
+ } ?: emptyList<TagWrapper>()) + entry.value.children.filterIsInstance<Param>()))
+ }.toMap()
+ } else {
+ sourceSetDependent
+ }
+ },
+ type = descriptor.returnType.toBound(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ generics = generics.await(),
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll<DFunction>(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ ).let {
+ if (descriptor.isPrimary) {
+ it + PrimaryConstructorExtra
+ } else it
}
- },
- type = descriptor.returnType.toBound(),
- modifier = descriptor.modifier().toSourceSetDependent(),
- generics = descriptor.typeParameters.map { it.toVariantTypeParameter() },
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll<DFunction>(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
- ).let {
- if (descriptor.isPrimary) {
- it + PrimaryConstructorExtra
- } else it
- }
- )
+ )
+ }
}
- override fun visitReceiverParameterDescriptor(
+ private suspend fun visitReceiverParameterDescriptor(
descriptor: ReceiverParameterDescriptor,
parent: DRIWithPlatformInfo
) = DParameter(
@@ -457,7 +539,7 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(descriptor.getAnnotations().toSourceSetDependent().toAnnotations())
)
- private fun visitPropertyAccessorDescriptor(
+ private suspend fun visitPropertyAccessorDescriptor(
descriptor: PropertyAccessorDescriptor,
propertyDescriptor: PropertyDescriptor,
parent: DRI
@@ -467,7 +549,7 @@ private class DokkaDescriptorVisitor(
val isExpect = descriptor.isExpect
val isActual = descriptor.isActual
- fun PropertyDescriptor.asParameter(parent: DRI) =
+ suspend fun PropertyDescriptor.asParameter(parent: DRI) =
DParameter(
parent.copy(target = PointingToCallableParameters(parameterIndex = 1)),
this.name.asString(),
@@ -494,52 +576,60 @@ private class DokkaDescriptorVisitor(
listOf(propertyDescriptor.asParameter(dri))
}
- return DFunction(
- dri,
- name,
- isConstructor = false,
- parameters = parameters,
- visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
- documentation = descriptor.resolveDescriptorData(),
- type = descriptor.returnType!!.toBound(),
- generics = descriptor.typeParameters.map { it.toVariantTypeParameter() },
- modifier = descriptor.modifier().toSourceSetDependent(),
- expectPresentInSet = sourceSet.takeIf { isExpect },
- receiver = descriptor.extensionReceiverParameter?.let {
- visitReceiverParameterDescriptor(
- it,
- DRIWithPlatformInfo(dri, descriptor.createSources())
+ return coroutineScope {
+ val generics = async { descriptor.typeParameters.parallelMap { it.toVariantTypeParameter() } }
+
+ DFunction(
+ dri,
+ name,
+ isConstructor = false,
+ parameters = parameters,
+ visibility = descriptor.visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = descriptor.resolveDescriptorData(),
+ type = descriptor.returnType!!.toBound(),
+ generics = generics.await(),
+ modifier = descriptor.modifier().toSourceSetDependent(),
+ expectPresentInSet = sourceSet.takeIf { isExpect },
+ receiver = descriptor.extensionReceiverParameter?.let {
+ visitReceiverParameterDescriptor(
+ it,
+ DRIWithPlatformInfo(dri, descriptor.createSources())
+ )
+ },
+ sources = descriptor.createSources(),
+ sourceSets = setOf(sourceSet),
+ isExpectActual = (isExpect || isActual),
+ extra = PropertyContainer.withAll<DFunction>(
+ descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
)
- },
- sources = descriptor.createSources(),
- sourceSets = setOf(sourceSet),
- isExpectActual = (isExpect || isActual),
- extra = PropertyContainer.withAll(
- descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
)
- )
+ }
}
- override fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, parent: DRIWithPlatformInfo?) =
+ private suspend fun visitTypeAliasDescriptor(descriptor: TypeAliasDescriptor, parent: DRIWithPlatformInfo?) =
with(descriptor) {
- DTypeAlias(
- dri = DRI.from(this),
- name = name.asString(),
- type = defaultType.toBound(),
- expectPresentInSet = null,
- underlyingType = underlyingType.toBound().toSourceSetDependent(),
- visibility = visibility.toDokkaVisibility().toSourceSetDependent(),
- documentation = resolveDescriptorData(),
- sourceSets = setOf(sourceSet),
- generics = descriptor.declaredTypeParameters.map { it.toVariantTypeParameter() },
- extra = PropertyContainer.withAll(
- descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ coroutineScope {
+ val generics = async { descriptor.declaredTypeParameters.parallelMap { it.toVariantTypeParameter() } }
+
+ DTypeAlias(
+ dri = DRI.from(this@with),
+ name = name.asString(),
+ type = defaultType.toBound(),
+ expectPresentInSet = null,
+ underlyingType = underlyingType.toBound().toSourceSetDependent(),
+ visibility = visibility.toDokkaVisibility().toSourceSetDependent(),
+ documentation = resolveDescriptorData(),
+ sourceSets = setOf(sourceSet),
+ generics = generics.await(),
+ extra = PropertyContainer.withAll(
+ descriptor.getAnnotations().toSourceSetDependent().toAnnotations()
+ )
)
- )
+ }
}
- private fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRIWithPlatformInfo) =
+ private suspend fun parameter(index: Int, descriptor: ValueParameterDescriptor, parent: DRIWithPlatformInfo) =
DParameter(
dri = parent.dri.copy(target = PointingToCallableParameters(index)),
name = descriptor.name.asString(),
@@ -554,77 +644,100 @@ private class DokkaDescriptorVisitor(
))
)
- private fun MemberScope.getContributedDescriptors(kindFilter: DescriptorKindFilter, shouldFilter: Boolean) =
- getContributedDescriptors(kindFilter) { true }.let {
+ private data class DescriptorsWithKind(
+ val functions: List<FunctionDescriptor>,
+ val properties: List<PropertyDescriptor>,
+ val classlikes: List<ClassDescriptor>,
+ val typealiases: List<TypeAliasDescriptor>,
+ val enumEntries: List<ClassDescriptor>
+ )
+
+ private suspend fun MemberScope.getDescriptorsWithKind(shouldFilter: Boolean = false): DescriptorsWithKind {
+ val descriptors = getContributedDescriptors { true }.let {
if (shouldFilter) it.filterDescriptorsInSourceSet() else it
}
- private fun MemberScope.functions(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DFunction> =
- getContributedDescriptors(DescriptorKindFilter.FUNCTIONS, packageLevel)
- .filterIsInstance<FunctionDescriptor>()
- .map { visitFunctionDescriptor(it, parent) }
+ class EnumEntryDescriptor
+
+ val groupedDescriptors = descriptors.groupBy { when {
+ it is FunctionDescriptor -> FunctionDescriptor::class
+ it is PropertyDescriptor -> PropertyDescriptor::class
+ it is ClassDescriptor && it.kind != ClassKind.ENUM_ENTRY -> ClassDescriptor::class
+ it is TypeAliasDescriptor -> TypeAliasDescriptor::class
+ it is ClassDescriptor && it.kind == ClassKind.ENUM_ENTRY -> EnumEntryDescriptor::class
+ else -> IllegalStateException::class
+ } }
+
+ return DescriptorsWithKind(
+ (groupedDescriptors[FunctionDescriptor::class] ?: emptyList()) as List<FunctionDescriptor>,
+ (groupedDescriptors[PropertyDescriptor::class] ?: emptyList()) as List<PropertyDescriptor>,
+ (groupedDescriptors[ClassDescriptor::class] ?: emptyList()) as List<ClassDescriptor>,
+ (groupedDescriptors[TypeAliasDescriptor::class] ?: emptyList()) as List<TypeAliasDescriptor>,
+ (groupedDescriptors[EnumEntryDescriptor::class] ?: emptyList()) as List<ClassDescriptor>
+ )
+ }
- private fun MemberScope.properties(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DProperty> =
- getContributedDescriptors(DescriptorKindFilter.VALUES, packageLevel)
- .filterIsInstance<PropertyDescriptor>()
- .map { visitPropertyDescriptor(it, parent) }
+ private suspend fun List<FunctionDescriptor>.visitFunctions(parent: DRIWithPlatformInfo): List<DFunction> =
+ coroutineScope { parallelMap { visitFunctionDescriptor(it, parent) } }
- private fun MemberScope.classlikes(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DClasslike> =
- getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS, packageLevel)
- .filter { it is ClassDescriptor && it.kind != ClassKind.ENUM_ENTRY }
- .map { visitClassDescriptor(it as ClassDescriptor, parent) }
+ private suspend fun List<PropertyDescriptor>.visitProperties(parent: DRIWithPlatformInfo): List<DProperty> =
+ coroutineScope { parallelMap { visitPropertyDescriptor(it, parent) } }
- private fun MemberScope.typealiases(parent: DRIWithPlatformInfo, packageLevel: Boolean = false): List<DTypeAlias> =
- getContributedDescriptors(DescriptorKindFilter.TYPE_ALIASES, packageLevel)
- .filterIsInstance<TypeAliasDescriptor>()
- .map { visitTypeAliasDescriptor(it, parent) }
+ private suspend fun List<ClassDescriptor>.visitClasslikes(parent: DRIWithPlatformInfo): List<DClasslike> =
+ coroutineScope { parallelMap { visitClassDescriptor(it, parent) } }
- private fun MemberScope.enumEntries(parent: DRIWithPlatformInfo): List<DEnumEntry> =
- this.getContributedDescriptors(DescriptorKindFilter.CLASSIFIERS) { true }
- .filterIsInstance<ClassDescriptor>()
- .filter { it.kind == ClassKind.ENUM_ENTRY }
- .map { enumEntryDescriptor(it, parent) }
+ private suspend fun List<TypeAliasDescriptor>.visitTypealiases(parent: DRIWithPlatformInfo): List<DTypeAlias> =
+ coroutineScope { parallelMap { visitTypeAliasDescriptor(it, parent) } }
+ private suspend fun List<ClassDescriptor>.visitEnumEntries(parent: DRIWithPlatformInfo): List<DEnumEntry> =
+ coroutineScope { parallelMap { visitEnumEntryDescriptor(it, parent) } }
- private fun DeclarationDescriptor.resolveDescriptorData(): SourceSetDependent<DocumentationNode> =
+ private suspend fun DeclarationDescriptor.resolveDescriptorData(): SourceSetDependent<DocumentationNode> =
getDocumentation()?.toSourceSetDependent() ?: emptyMap()
- private fun ClassDescriptor.resolveClassDescriptionData(): ClassInfo {
- fun toTypeConstructor(kt: KotlinType) =
- GenericTypeConstructor(
- DRI.from(kt.constructor.declarationDescriptor as DeclarationDescriptor),
- kt.arguments.map { it.toProjection() })
+ private suspend fun toTypeConstructor(kt: KotlinType) =
+ GenericTypeConstructor(
+ DRI.from(kt.constructor.declarationDescriptor as DeclarationDescriptor),
+ kt.arguments.map { it.toProjection() })
- tailrec fun buildAncestryInformation(
- supertypes: Collection<KotlinType>,
- level: Int = 0,
- ancestryInformation: Set<AncestryLevel> = emptySet()
- ): Set<AncestryLevel> {
- if (supertypes.isEmpty()) return ancestryInformation
- val (interfaces, superclass) = supertypes.partition {
- (it.constructor.declarationDescriptor as ClassDescriptor).kind == ClassKind.INTERFACE
- }
+ private tailrec suspend fun buildAncestryInformation(
+ supertypes: Collection<KotlinType>,
+ level: Int = 0,
+ ancestryInformation: Set<AncestryLevel> = emptySet()
+ ): Set<AncestryLevel> {
+ if (supertypes.isEmpty()) return ancestryInformation
+
+ val (interfaces, superclass) = supertypes.partition {
+ (it.constructor.declarationDescriptor as ClassDescriptor).kind == ClassKind.INTERFACE
+ }
- val updated = ancestryInformation + AncestryLevel(
+ val updated = coroutineScope {
+ ancestryInformation + AncestryLevel(
level,
- superclass.map(::toTypeConstructor).singleOrNull(),
- interfaces.map(::toTypeConstructor)
- )
- return buildAncestryInformation(
- supertypes = supertypes.flatMap { it.supertypes() },
- level = level + 1,
- ancestryInformation = updated
+ superclass.parallelMap(::toTypeConstructor).singleOrNull(),
+ interfaces.parallelMap(::toTypeConstructor)
)
}
- return ClassInfo(
- buildAncestryInformation(this.typeConstructor.supertypes.filterNot { it.isAnyOrNullableAny() }).sortedBy { it.level },
- resolveDescriptorData()
+
+ return buildAncestryInformation(
+ supertypes = supertypes.flatMap { it.supertypes() },
+ level = level + 1,
+ ancestryInformation = updated
)
}
- private fun TypeParameterDescriptor.toVariantTypeParameter() =
+ private suspend fun ClassDescriptor.resolveClassDescriptionData(): ClassInfo {
+ return coroutineScope {
+ ClassInfo(
+ buildAncestryInformation(this@resolveClassDescriptionData.typeConstructor.supertypes.filterNot { it.isAnyOrNullableAny() }).sortedBy { it.level },
+ resolveDescriptorData()
+ )
+ }
+ }
+
+ private suspend fun TypeParameterDescriptor.toVariantTypeParameter() =
DTypeParameter(
variantTypeParameter(
TypeParameter(DRI.from(this), name.identifier, annotations.getPresentableName())
@@ -636,11 +749,12 @@ private class DokkaDescriptorVisitor(
extra = PropertyContainer.withAll(additionalExtras().toSourceSetDependent().toAdditionalModifiers())
)
- private fun org.jetbrains.kotlin.descriptors.annotations.Annotations.getPresentableName(): String? =
+ private suspend fun org.jetbrains.kotlin.descriptors.annotations.Annotations.getPresentableName(): String? =
map { it.toAnnotation() }.singleOrNull { it.dri.classNames == "ParameterName" }?.params?.get("name")
.safeAs<StringValue>()?.value?.drop(1)?.dropLast(1) // Dropping enclosing doublequotes because we don't want to have it in our custom signature serializer
- private fun KotlinType.toBound(): Bound = when (this) {
+ private suspend fun KotlinType.toBound(): Bound = when (this) {
+
is DynamicType -> Dynamic
is AbbreviatedType -> TypeAliased(
abbreviation.toBound(),
@@ -669,20 +783,23 @@ private class DokkaDescriptorVisitor(
}
}
- private fun TypeProjection.toProjection(): Projection =
+ private suspend fun TypeProjection.toProjection(): Projection =
if (isStarProjection) Star else formPossiblyVariant()
- private fun TypeProjection.formPossiblyVariant(): Projection = type.toBound().wrapWithVariance(projectionKind)
+ private suspend fun TypeProjection.formPossiblyVariant(): Projection =
+ type.toBound().wrapWithVariance(projectionKind)
- private fun TypeParameterDescriptor.variantTypeParameter(type: TypeParameter) = type.wrapWithVariance(variance)
+ private suspend fun TypeParameterDescriptor.variantTypeParameter(type: TypeParameter) =
+ type.wrapWithVariance(variance)
- private fun <T : Bound> T.wrapWithVariance(variance: org.jetbrains.kotlin.types.Variance) = when (variance) {
- org.jetbrains.kotlin.types.Variance.INVARIANT -> Invariance(this)
- org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Contravariance(this)
- org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Covariance(this)
- }
+ private fun <T : Bound> T.wrapWithVariance(variance: org.jetbrains.kotlin.types.Variance) =
+ when (variance) {
+ org.jetbrains.kotlin.types.Variance.INVARIANT -> Invariance(this)
+ org.jetbrains.kotlin.types.Variance.IN_VARIANCE -> Contravariance(this)
+ org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Covariance(this)
+ }
- private fun DeclarationDescriptor.getDocumentation() = findKDoc().let {
+ private suspend fun DeclarationDescriptor.getDocumentation() = findKDoc().let {
MarkdownParser.parseFromKDocTag(
kDocTag = it,
externalDri = { link: String ->
@@ -702,7 +819,7 @@ private class DokkaDescriptorVisitor(
)
}.takeIf { it.children.isNotEmpty() }
- private fun ClassDescriptor.companion(dri: DRIWithPlatformInfo): DObject? = companionObjectDescriptor?.let {
+ private suspend fun ClassDescriptor.companion(dri: DRIWithPlatformInfo): DObject? = companionObjectDescriptor?.let {
objectDescriptor(it, dri)
}
@@ -756,9 +873,9 @@ private class DokkaDescriptorVisitor(
ExtraModifiers.KotlinOnlyModifiers.Override.takeIf { DescriptorUtils.isOverride(this) }
)
- private fun Annotated.getAnnotations() = annotations.mapNotNull { it.toAnnotation() }
+ private suspend fun Annotated.getAnnotations() = annotations.parallelMapNotNull { it.toAnnotation() }
- private fun ConstantValue<*>.toValue(): AnnotationParameterValue? = when (this) {
+ private suspend fun ConstantValue<*>.toValue(): AnnotationParameterValue? = when (this) {
is ConstantsAnnotationValue -> value.toAnnotation()?.let { AnnotationValue(it) }
is ConstantsArrayValue -> ArrayValue(value.mapNotNull { it.toValue() })
is ConstantsEnumValue -> EnumValue(
@@ -782,7 +899,7 @@ private class DokkaDescriptorVisitor(
else -> StringValue(toString())
}
- private fun AnnotationDescriptor.toAnnotation(): Annotations.Annotation {
+ private suspend fun AnnotationDescriptor.toAnnotation(): Annotations.Annotation {
return Annotations.Annotation(
DRI.from(annotationClass as DeclarationDescriptor),
allValueArguments.map { it.key.asString() to it.value.toValue() }.filter {
@@ -792,7 +909,7 @@ private class DokkaDescriptorVisitor(
)
}
- private fun PropertyDescriptor.getAnnotationsWithBackingField(): List<Annotations.Annotation> =
+ private suspend fun PropertyDescriptor.getAnnotationsWithBackingField(): List<Annotations.Annotation> =
getAnnotations() + (backingField?.getAnnotations() ?: emptyList())
private fun List<Annotations.Annotation>.toAdditionalExtras() = mapNotNull {
@@ -803,24 +920,25 @@ private class DokkaDescriptorVisitor(
}
}
- private fun ValueParameterDescriptor.getDefaultValue(): String? =
+ private suspend fun ValueParameterDescriptor.getDefaultValue(): String? =
(source as? KotlinSourceElement)?.psi?.children?.find { it is KtExpression }?.text
- private fun PropertyDescriptor.getDefaultValue(): String? =
+ private suspend fun PropertyDescriptor.getDefaultValue(): String? =
(source as? KotlinSourceElement)?.psi?.children?.find { it is KtConstantExpression }?.text
- private fun ClassDescriptor.getAppliedConstructorParameters() =
+ private suspend fun ClassDescriptor.getAppliedConstructorParameters() =
(source as PsiSourceElement).psi?.children?.flatMap {
it.safeAs<KtInitializerList>()?.initializersAsText().orEmpty()
}.orEmpty()
- private fun KtInitializerList.initializersAsText() =
+ private suspend fun KtInitializerList.initializersAsText() =
initializers.firstIsInstanceOrNull<KtCallElement>()
?.getValueArgumentsInParentheses()
?.flatMap { it.childrenAsText() }
.orEmpty()
- private fun ValueArgument.childrenAsText() = this.safeAs<KtValueArgument>()?.children?.map { it.text }.orEmpty()
+ private fun ValueArgument.childrenAsText() =
+ this.safeAs<KtValueArgument>()?.children?.map { it.text }.orEmpty()
private data class AncestryLevel(
val level: Int,
@@ -853,5 +971,4 @@ private class DokkaDescriptorVisitor(
private fun ConstantsEnumValue.fullEnumEntryName() =
"${this.enumClassId.relativeClassName.asString()}.${this.enumEntryName.identifier}"
-
}
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
index 39cb3c89..cbd02158 100644
--- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
+++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt
@@ -8,6 +8,8 @@ import com.intellij.psi.*
import com.intellij.psi.impl.source.PsiClassReferenceType
import com.intellij.psi.impl.source.PsiImmediateClassType
import com.intellij.psi.javadoc.PsiDocComment
+import kotlinx.coroutines.async
+import kotlinx.coroutines.coroutineScope
import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
import org.jetbrains.dokka.analysis.KotlinAnalysis
import org.jetbrains.dokka.analysis.PsiDocumentableSource
@@ -22,6 +24,9 @@ import org.jetbrains.dokka.model.properties.PropertyContainer
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.sources.SourceToDocumentableTranslator
import org.jetbrains.dokka.utilities.DokkaLogger
+import org.jetbrains.dokka.utilities.parallelForEach
+import org.jetbrains.dokka.utilities.parallelMap
+import org.jetbrains.dokka.utilities.parallelMapNotNull
import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
@@ -44,42 +49,45 @@ class DefaultPsiToDocumentableTranslator(
private val kotlinAnalysis: KotlinAnalysis
) : SourceToDocumentableTranslator {
- override fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
+ override suspend fun invoke(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
+ return coroutineScope {
+ fun isFileInSourceRoots(file: File): Boolean =
+ sourceSet.sourceRoots.any { root -> file.startsWith(root) }
- fun isFileInSourceRoots(file: File): Boolean =
- sourceSet.sourceRoots.any { root -> file.startsWith(root) }
+ val (environment, _) = kotlinAnalysis[sourceSet]
- val (environment, _) = kotlinAnalysis[sourceSet]
+ val sourceRoots = environment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
+ ?.filterIsInstance<JavaSourceRoot>()
+ ?.mapNotNull { it.file.takeIf(::isFileInSourceRoots) }
+ ?: listOf()
+ val localFileSystem = VirtualFileManager.getInstance().getFileSystem("file")
- val sourceRoots = environment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS)
- ?.filterIsInstance<JavaSourceRoot>()
- ?.mapNotNull { it.file.takeIf(::isFileInSourceRoots) }
- ?: listOf()
- val localFileSystem = VirtualFileManager.getInstance().getFileSystem("file")
+ val psiFiles = sourceRoots.parallelMap { sourceRoot ->
+ sourceRoot.absoluteFile.walkTopDown().mapNotNull {
+ localFileSystem.findFileByPath(it.path)?.let { vFile ->
+ PsiManager.getInstance(environment.project).findFile(vFile) as? PsiJavaFile
+ }
+ }.toList()
+ }.flatten()
- val psiFiles = sourceRoots.map { sourceRoot ->
- sourceRoot.absoluteFile.walkTopDown().mapNotNull {
- localFileSystem.findFileByPath(it.path)?.let { vFile ->
- PsiManager.getInstance(environment.project).findFile(vFile) as? PsiJavaFile
- }
- }.toList()
- }.flatten()
+ val docParser =
+ DokkaPsiParser(
+ sourceSet,
+ context.logger
+ )
- val docParser =
- DokkaPsiParser(
- sourceSet,
- context.logger
+ DModule(
+ context.configuration.moduleName,
+ psiFiles.parallelMapNotNull { it.safeAs<PsiJavaFile>() }.groupBy { it.packageName }.toList()
+ .parallelMap { (packageName: String, psiFiles: List<PsiJavaFile>) ->
+ docParser.parsePackage(packageName, psiFiles)
+ },
+ emptyMap(),
+ null,
+ setOf(sourceSet)
)
- return DModule(
- context.configuration.moduleName,
- psiFiles.mapNotNull { it.safeAs<PsiJavaFile>() }.groupBy { it.packageName }.map { (packageName, psiFiles) ->
- docParser.parsePackage(packageName, psiFiles)
- },
- emptyMap(),
- null,
- setOf(sourceSet)
- )
+ }
}
class DokkaPsiParser(
@@ -117,19 +125,21 @@ class DefaultPsiToDocumentableTranslator(
private fun <T> T.toSourceSetDependent() = mapOf(sourceSetData to this)
- fun parsePackage(packageName: String, psiFiles: List<PsiJavaFile>): DPackage {
+ suspend fun parsePackage(packageName: String, psiFiles: List<PsiJavaFile>): DPackage = coroutineScope {
val dri = DRI(packageName = packageName)
val documentation = psiFiles.firstOrNull { it.name == "package-info.java" }?.let {
javadocParser.parseDocumentation(it).toSourceSetDependent()
} ?: emptyMap()
- return DPackage(
+ DPackage(
dri,
emptyList(),
emptyList(),
- psiFiles.flatMap { psiFile ->
- psiFile.classes.map { parseClasslike(it, dri) }
- },
+ psiFiles.parallelMap { psiFile ->
+ coroutineScope {
+ psiFile.classes.asIterable().parallelMap { parseClasslike(it, dri) }
+ }
+ }.flatten(),
emptyList(),
documentation,
null,
@@ -137,85 +147,144 @@ class DefaultPsiToDocumentableTranslator(
)
}
-
- private fun parseClasslike(psi: PsiClass, parent: DRI): DClasslike = with(psi) {
- val dri = parent.withClass(name.toString())
- val ancestryTree = mutableListOf<AncestryLevel>()
- val superMethodsKeys = hashSetOf<Int>()
- val superMethods = mutableListOf<Pair<PsiMethod, DRI>>()
- methods.forEach { superMethodsKeys.add(it.hash) }
- fun parseSupertypes(superTypes: Array<PsiClassType>, level: Int = 0) {
- if (superTypes.isEmpty()) return
- val parsedClasses = superTypes.filter { !it.shouldBeIgnored }.mapNotNull { psi ->
- psi.resolve()?.let { psiClass ->
- val (dri, javaClassKind) = when {
- psiClass.isInterface -> DRI.from(psiClass) to JavaClassKindTypes.INTERFACE
- else -> DRI.from(psiClass) to JavaClassKindTypes.CLASS
+ private suspend fun parseClasslike(psi: PsiClass, parent: DRI): DClasslike = coroutineScope {
+ with(psi) {
+ val dri = parent.withClass(name.toString())
+ val ancestryTree = mutableListOf<AncestryLevel>()
+ val superMethodsKeys = hashSetOf<Int>()
+ val superMethods = mutableListOf<Pair<PsiMethod, DRI>>()
+ methods.asIterable().parallelForEach { superMethodsKeys.add(it.hash) }
+ fun parseSupertypes(superTypes: Array<PsiClassType>, level: Int = 0) { // TODO: Rewrite it
+ if (superTypes.isEmpty()) return
+ val parsedClasses = superTypes.filter { !it.shouldBeIgnored }.mapNotNull { psi ->
+ psi.resolve()?.let { psiClass ->
+ val (dri, javaClassKind) = when {
+ psiClass.isInterface -> DRI.from(psiClass) to JavaClassKindTypes.INTERFACE
+ else -> DRI.from(psiClass) to JavaClassKindTypes.CLASS
+ }
+ GenericTypeConstructor(
+ dri,
+ psi.parameters.map(::getProjection)
+ ) to javaClassKind
}
- GenericTypeConstructor(
- dri,
- psi.parameters.map(::getProjection)
- ) to javaClassKind
}
- }
- val (classes, interfaces) = parsedClasses.partition { it.second == JavaClassKindTypes.CLASS }
- ancestryTree.add(AncestryLevel(level, classes.firstOrNull()?.first, interfaces.map { it.first }))
-
- superTypes.forEach { type ->
- (type as? PsiClassType)?.takeUnless { type.shouldBeIgnored }?.resolve()?.let {
- val definedAt = DRI.from(it)
- it.methods.forEach { method ->
- val hash = method.hash
- if (!method.isConstructor && !superMethodsKeys.contains(hash) &&
- method.getVisibility() != Visibilities.PRIVATE
- ) {
- superMethodsKeys.add(hash)
- superMethods.add(Pair(method, definedAt))
+ val (classes, interfaces) = parsedClasses.partition { it.second == JavaClassKindTypes.CLASS }
+ ancestryTree.add(AncestryLevel(level, classes.firstOrNull()?.first, interfaces.map { it.first }))
+
+ superTypes.forEach { type ->
+ (type as? PsiClassType)?.takeUnless { type.shouldBeIgnored }?.resolve()?.let {
+ val definedAt = DRI.from(it)
+ it.methods.forEach { method ->
+ val hash = method.hash
+ if (!method.isConstructor && !superMethodsKeys.contains(hash) &&
+ method.getVisibility() != Visibilities.PRIVATE
+ ) {
+ superMethodsKeys.add(hash)
+ superMethods.add(Pair(method, definedAt))
+ }
}
+ parseSupertypes(it.superTypes, level + 1)
}
- parseSupertypes(it.superTypes, level + 1)
}
}
- }
- parseSupertypes(superTypes)
- val (regularFunctions, accessors) = splitFunctionsAndAccessors()
- val documentation = javadocParser.parseDocumentation(this).toSourceSetDependent()
- val allFunctions = regularFunctions.mapNotNull { if (!it.isConstructor) parseFunction(it) else null } +
- superMethods.map { parseFunction(it.first, inheritedFrom = it.second) }
- val source = PsiDocumentableSource(this).toSourceSetDependent()
- val classlikes = innerClasses.map { parseClasslike(it, dri) }
- val visibility = getVisibility().toSourceSetDependent()
- val ancestors = ancestryTree.filter { it.level == 0 }.flatMap {
- listOfNotNull(it.superclass?.let {
- TypeConstructorWithKind(
- typeConstructor = it,
- kind = JavaClassKindTypes.CLASS
- )
- }) + it.interfaces.map {
- TypeConstructorWithKind(
- typeConstructor = it,
- kind = JavaClassKindTypes.INTERFACE
- )
- }
- }.toSourceSetDependent()
- val modifiers = getModifier().toSourceSetDependent()
- val implementedInterfacesExtra =
- ImplementedInterfaces(ancestryTree.flatMap { it.interfaces }.distinct().toSourceSetDependent())
- return when {
- isAnnotationType ->
- DAnnotation(
+ parseSupertypes(superTypes)
+ val (regularFunctions, accessors) = splitFunctionsAndAccessors()
+ val documentation = javadocParser.parseDocumentation(this).toSourceSetDependent()
+ val allFunctions = async { regularFunctions.parallelMapNotNull { if (!it.isConstructor) parseFunction(it) else null } +
+ superMethods.parallelMap { parseFunction(it.first, inheritedFrom = it.second) } }
+ val source = PsiDocumentableSource(this).toSourceSetDependent()
+ val classlikes = async { innerClasses.asIterable().parallelMap { parseClasslike(it, dri) } }
+ val visibility = getVisibility().toSourceSetDependent()
+ val ancestors = ancestryTree.filter { it.level == 0 }.flatMap {
+ listOfNotNull(it.superclass?.let {
+ TypeConstructorWithKind(
+ typeConstructor = it,
+ kind = JavaClassKindTypes.CLASS
+ )
+ }) + it.interfaces.map {
+ TypeConstructorWithKind(
+ typeConstructor = it,
+ kind = JavaClassKindTypes.INTERFACE
+ )
+ }
+ }.toSourceSetDependent()
+ val modifiers = getModifier().toSourceSetDependent()
+ val implementedInterfacesExtra =
+ ImplementedInterfaces(ancestryTree.flatMap { it.interfaces }.distinct().toSourceSetDependent())
+ when {
+ isAnnotationType ->
+ DAnnotation(
+ name.orEmpty(),
+ dri,
+ documentation,
+ null,
+ source,
+ allFunctions.await(),
+ fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
+ classlikes.await(),
+ visibility,
+ null,
+ constructors.map { parseFunction(it, true) },
+ mapTypeParameters(dri),
+ setOf(sourceSetData),
+ false,
+ PropertyContainer.withAll(
+ implementedInterfacesExtra,
+ annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
+ )
+ isEnum -> DEnum(
+ dri,
name.orEmpty(),
+ fields.filterIsInstance<PsiEnumConstant>().map { entry ->
+ DEnumEntry(
+ dri.withClass("${entry.name}"),
+ entry.name,
+ javadocParser.parseDocumentation(entry).toSourceSetDependent(),
+ null,
+ emptyList(),
+ emptyList(),
+ emptyList(),
+ setOf(sourceSetData),
+ PropertyContainer.withAll(
+ implementedInterfacesExtra,
+ annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
+ )
+ },
+ documentation,
+ null,
+ source,
+ allFunctions.await(),
+ fields.filter { it !is PsiEnumConstant }.map { parseField(it, accessors[it].orEmpty()) },
+ classlikes.await(),
+ visibility,
+ null,
+ constructors.map { parseFunction(it, true) },
+ ancestors,
+ setOf(sourceSetData),
+ false,
+ PropertyContainer.withAll(
+ implementedInterfacesExtra,
+ annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
+ )
+ )
+ isInterface -> DInterface(
dri,
+ name.orEmpty(),
documentation,
null,
source,
- allFunctions,
+ allFunctions.await(),
fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
- classlikes,
+ classlikes.await(),
visibility,
null,
- constructors.map { parseFunction(it, true) },
mapTypeParameters(dri),
+ ancestors,
setOf(sourceSetData),
false,
PropertyContainer.withAll(
@@ -224,85 +293,30 @@ class DefaultPsiToDocumentableTranslator(
.toAnnotations()
)
)
- isEnum -> DEnum(
- dri,
- name.orEmpty(),
- fields.filterIsInstance<PsiEnumConstant>().map { entry ->
- DEnumEntry(
- dri.withClass("${entry.name}"),
- entry.name,
- javadocParser.parseDocumentation(entry).toSourceSetDependent(),
- null,
- emptyList(),
- emptyList(),
- emptyList(),
- setOf(sourceSetData),
- PropertyContainer.withAll(
- implementedInterfacesExtra,
- annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
+ else -> DClass(
+ dri,
+ name.orEmpty(),
+ constructors.map { parseFunction(it, true) },
+ allFunctions.await(),
+ fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
+ classlikes.await(),
+ source,
+ visibility,
+ null,
+ mapTypeParameters(dri),
+ ancestors,
+ documentation,
+ null,
+ modifiers,
+ setOf(sourceSetData),
+ false,
+ PropertyContainer.withAll(
+ implementedInterfacesExtra,
+ annotations.toList().toListOfAnnotations().toSourceSetDependent()
+ .toAnnotations()
)
- },
- documentation,
- null,
- source,
- allFunctions,
- fields.filter { it !is PsiEnumConstant }.map { parseField(it, accessors[it].orEmpty()) },
- classlikes,
- visibility,
- null,
- constructors.map { parseFunction(it, true) },
- ancestors,
- setOf(sourceSetData),
- false,
- PropertyContainer.withAll(
- implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
- isInterface -> DInterface(
- dri,
- name.orEmpty(),
- documentation,
- null,
- source,
- allFunctions,
- fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
- classlikes,
- visibility,
- null,
- mapTypeParameters(dri),
- ancestors,
- setOf(sourceSetData),
- false,
- PropertyContainer.withAll(
- implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
)
- )
- else -> DClass(
- dri,
- name.orEmpty(),
- constructors.map { parseFunction(it, true) },
- allFunctions,
- fields.mapNotNull { parseField(it, accessors[it].orEmpty()) },
- classlikes,
- source,
- visibility,
- null,
- mapTypeParameters(dri),
- ancestors,
- documentation,
- null,
- modifiers,
- setOf(sourceSetData),
- false,
- PropertyContainer.withAll(
- implementedInterfacesExtra, annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
+ }
}
}