aboutsummaryrefslogtreecommitdiff
path: root/plugins/base/src/main/kotlin/translators/psi
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/base/src/main/kotlin/translators/psi')
-rw-r--r--plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt364
1 files changed, 189 insertions, 175 deletions
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()
- )
- )
+ }
}
}