aboutsummaryrefslogtreecommitdiff
path: root/subprojects/analysis-java-psi/src/main
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-10 11:46:54 +0100
committerGitHub <noreply@github.com>2023-11-10 11:46:54 +0100
commit8e5c63d035ef44a269b8c43430f43f5c8eebfb63 (patch)
tree1b915207b2b9f61951ddbf0ff2e687efd053d555 /subprojects/analysis-java-psi/src/main
parenta44efd4ba0c2e4ab921ff75e0f53fc9335aa79db (diff)
downloaddokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.gz
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.tar.bz2
dokka-8e5c63d035ef44a269b8c43430f43f5c8eebfb63.zip
Restructure the project to utilize included builds (#3174)
* Refactor and simplify artifact publishing * Update Gradle to 8.4 * Refactor and simplify convention plugins and build scripts Fixes #3132 --------- Co-authored-by: Adam <897017+aSemy@users.noreply.github.com> Co-authored-by: Oleg Yukhnevich <whyoleg@gmail.com>
Diffstat (limited to 'subprojects/analysis-java-psi/src/main')
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/DefaultPsiToDocumentableTranslator.kt87
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavaAnalysisPlugin.kt110
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavadocTag.kt54
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/SynheticElementDocumentationProvider.kt46
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocComment.kt18
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentCreator.kt13
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFactory.kt24
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFinder.kt68
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocumentationContent.kt15
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocComment.kt88
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocCommentCreator.kt15
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/PsiDocumentationContent.kt26
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/CommentResolutionContext.kt13
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DocCommentParser.kt16
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt803
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavaDocCommentParser.kt232
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavadocParser.kt28
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/DocTagParserContext.kt51
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/HtmlToDocTagConverter.kt118
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagContentProvider.kt14
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagResolver.kt118
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiDocTagParser.kt43
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiElementToHtmlConverter.kt218
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/CoreCopyPaste.kt24
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/NoopIntellijLogger.kt47
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PropertiesConventionUtil.kt105
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiAccessorConventionUtil.kt102
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiCommentsUtils.kt53
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt126
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/StdlibUtil.kt37
-rw-r--r--subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/resolveToGetDri.kt11
-rw-r--r--subprojects/analysis-java-psi/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin5
32 files changed, 0 insertions, 2728 deletions
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/DefaultPsiToDocumentableTranslator.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/DefaultPsiToDocumentableTranslator.kt
deleted file mode 100644
index 3b8ff25b..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/DefaultPsiToDocumentableTranslator.kt
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java
-
-import com.intellij.openapi.vfs.VirtualFileManager
-import com.intellij.psi.PsiJavaFile
-import com.intellij.psi.PsiKeyword
-import com.intellij.psi.PsiManager
-import com.intellij.psi.PsiModifierListOwner
-import kotlinx.coroutines.coroutineScope
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.analysis.java.parsers.DokkaPsiParser
-import org.jetbrains.dokka.analysis.java.parsers.JavaPsiDocCommentParser
-import org.jetbrains.dokka.analysis.java.parsers.JavadocParser
-import org.jetbrains.dokka.model.DModule
-import org.jetbrains.dokka.model.JavaVisibility
-import org.jetbrains.dokka.plugability.DokkaContext
-import org.jetbrains.dokka.plugability.plugin
-import org.jetbrains.dokka.plugability.query
-import org.jetbrains.dokka.plugability.querySingle
-import org.jetbrains.dokka.transformers.sources.AsyncSourceToDocumentableTranslator
-import org.jetbrains.dokka.utilities.parallelMap
-import org.jetbrains.dokka.utilities.parallelMapNotNull
-
-internal class DefaultPsiToDocumentableTranslator : AsyncSourceToDocumentableTranslator {
-
- override suspend fun invokeSuspending(sourceSet: DokkaSourceSet, context: DokkaContext): DModule {
- return coroutineScope {
- val projectProvider = context.plugin<JavaAnalysisPlugin>().querySingle { projectProvider }
- val project = projectProvider.getProject(sourceSet, context)
-
- val sourceRootsExtractor = context.plugin<JavaAnalysisPlugin>().querySingle { sourceRootsExtractor }
- val sourceRoots = sourceRootsExtractor.extract(sourceSet, context)
-
- val localFileSystem = VirtualFileManager.getInstance().getFileSystem("file")
-
- val psiFiles = sourceRoots.parallelMap { sourceRoot ->
- sourceRoot.absoluteFile.walkTopDown().mapNotNull {
- localFileSystem.findFileByPath(it.path)?.let { vFile ->
- PsiManager.getInstance(project).findFile(vFile) as? PsiJavaFile
- }
- }.toList()
- }.flatten()
-
- val docParser = createPsiParser(sourceSet, context)
-
- DModule(
- name = context.configuration.moduleName,
- packages = psiFiles.parallelMapNotNull { it }.groupBy { it.packageName }.toList()
- .parallelMap { (packageName: String, psiFiles: List<PsiJavaFile>) ->
- docParser.parsePackage(packageName, psiFiles)
- },
- documentation = emptyMap(),
- expectPresentInSet = null,
- sourceSets = setOf(sourceSet)
- )
- }
- }
-
- private fun createPsiParser(sourceSet: DokkaSourceSet, context: DokkaContext): DokkaPsiParser {
- val projectProvider = context.plugin<JavaAnalysisPlugin>().querySingle { projectProvider }
- val docCommentParsers = context.plugin<JavaAnalysisPlugin>().query { docCommentParsers }
- return DokkaPsiParser(
- sourceSetData = sourceSet,
- project = projectProvider.getProject(sourceSet, context),
- logger = context.logger,
- javadocParser = JavadocParser(
- docCommentParsers = docCommentParsers,
- docCommentFinder = context.plugin<JavaAnalysisPlugin>().docCommentFinder
- ),
- javaPsiDocCommentParser = docCommentParsers.single { it is JavaPsiDocCommentParser } as JavaPsiDocCommentParser,
- lightMethodChecker = context.plugin<JavaAnalysisPlugin>().querySingle { kotlinLightMethodChecker }
- )
- }
-}
-
-internal fun PsiModifierListOwner.getVisibility() = modifierList?.let {
- val ml = it.children.toList()
- when {
- ml.any { it.text == PsiKeyword.PUBLIC } || it.hasModifierProperty("public") -> JavaVisibility.Public
- ml.any { it.text == PsiKeyword.PROTECTED } || it.hasModifierProperty("protected") -> JavaVisibility.Protected
- ml.any { it.text == PsiKeyword.PRIVATE } || it.hasModifierProperty("private") -> JavaVisibility.Private
- else -> JavaVisibility.Default
- }
-} ?: JavaVisibility.Default
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavaAnalysisPlugin.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavaAnalysisPlugin.kt
deleted file mode 100644
index 9426adf1..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavaAnalysisPlugin.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java
-
-import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute
-import com.intellij.openapi.diagnostic.Logger
-import com.intellij.openapi.project.Project
-import com.intellij.psi.PsiAnnotation
-import org.jetbrains.dokka.CoreExtensions
-import org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.doccomment.DocCommentCreator
-import org.jetbrains.dokka.analysis.java.doccomment.DocCommentFactory
-import org.jetbrains.dokka.analysis.java.doccomment.DocCommentFinder
-import org.jetbrains.dokka.analysis.java.doccomment.JavaDocCommentCreator
-import org.jetbrains.dokka.analysis.java.parsers.DocCommentParser
-import org.jetbrains.dokka.analysis.java.parsers.doctag.InheritDocTagContentProvider
-import org.jetbrains.dokka.analysis.java.parsers.JavaPsiDocCommentParser
-import org.jetbrains.dokka.analysis.java.parsers.doctag.InheritDocTagResolver
-import org.jetbrains.dokka.analysis.java.parsers.doctag.PsiDocTagParser
-import org.jetbrains.dokka.analysis.java.util.NoopIntellijLoggerFactory
-import org.jetbrains.dokka.plugability.*
-import java.io.File
-
-
-@InternalDokkaApi
-public interface ProjectProvider {
- public fun getProject(sourceSet: DokkaSourceSet, context: DokkaContext): Project
-}
-
-@InternalDokkaApi
-public interface SourceRootsExtractor {
- public fun extract(sourceSet: DokkaSourceSet, context: DokkaContext): List<File>
-}
-
-@InternalDokkaApi
-public interface BreakingAbstractionKotlinLightMethodChecker {
- // TODO [beresnev] not even sure it's needed, but left for compatibility and to preserve behaviour
- public fun isLightAnnotation(annotation: PsiAnnotation): Boolean
- public fun isLightAnnotationAttribute(attribute: JvmAnnotationAttribute): Boolean
-}
-
-@InternalDokkaApi
-public class JavaAnalysisPlugin : DokkaPlugin() {
-
- // single
- public val projectProvider: ExtensionPoint<ProjectProvider> by extensionPoint()
-
- // single
- public val sourceRootsExtractor: ExtensionPoint<SourceRootsExtractor> by extensionPoint()
-
- // multiple
- public val docCommentCreators: ExtensionPoint<DocCommentCreator> by extensionPoint()
-
- // multiple
- public val docCommentParsers: ExtensionPoint<DocCommentParser> by extensionPoint()
-
- // none or more
- public val inheritDocTagContentProviders: ExtensionPoint<InheritDocTagContentProvider> by extensionPoint()
-
- // TODO [beresnev] figure out a better way depending on what it's used for
- public val kotlinLightMethodChecker: ExtensionPoint<BreakingAbstractionKotlinLightMethodChecker> by extensionPoint()
-
- private val docCommentFactory by lazy {
- DocCommentFactory(query { docCommentCreators }.reversed())
- }
-
- public val docCommentFinder: DocCommentFinder by lazy {
- DocCommentFinder(logger, docCommentFactory)
- }
-
- internal val javaDocCommentCreator by extending {
- docCommentCreators providing { JavaDocCommentCreator() }
- }
-
- private val psiDocTagParser by lazy {
- PsiDocTagParser(
- inheritDocTagResolver = InheritDocTagResolver(
- docCommentFactory = docCommentFactory,
- docCommentFinder = docCommentFinder,
- contentProviders = query { inheritDocTagContentProviders }
- )
- )
- }
-
- internal val javaDocCommentParser by extending {
- docCommentParsers providing {
- JavaPsiDocCommentParser(
- psiDocTagParser
- )
- }
- }
-
- internal val psiToDocumentableTranslator by extending {
- CoreExtensions.sourceToDocumentableTranslator providing { DefaultPsiToDocumentableTranslator() }
- }
-
- @OptIn(DokkaPluginApiPreview::class)
- override fun pluginApiPreviewAcknowledgement(): PluginApiPreviewAcknowledgement = PluginApiPreviewAcknowledgement
-
- private companion object {
- init {
- // Suppress messages emitted by the IntelliJ logger since
- // there's not much the end user can do about it
- Logger.setFactory(NoopIntellijLoggerFactory())
- }
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavadocTag.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavadocTag.kt
deleted file mode 100644
index 23aee764..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/JavadocTag.kt
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java
-
-import com.intellij.psi.PsiMethod
-import org.jetbrains.dokka.InternalDokkaApi
-
-@InternalDokkaApi
-public sealed class JavadocTag(
- public val name: String
-)
-
-public object AuthorJavadocTag : JavadocTag("author")
-public object DeprecatedJavadocTag : JavadocTag("deprecated")
-public object DescriptionJavadocTag : JavadocTag("description")
-public object ReturnJavadocTag : JavadocTag("return")
-public object SinceJavadocTag : JavadocTag("since")
-
-public class ParamJavadocTag(
- public val method: PsiMethod,
- public val paramName: String,
- public val paramIndex: Int
-) : JavadocTag(name) {
- public companion object {
- public const val name: String = "param"
- }
-}
-
-public class SeeJavadocTag(
- public val qualifiedReference: String
-) : JavadocTag(name) {
- public companion object {
- public const val name: String = "see"
- }
-}
-
-public sealed class ThrowingExceptionJavadocTag(
- name: String,
- public val exceptionQualifiedName: String?
-) : JavadocTag(name)
-
-public class ThrowsJavadocTag(exceptionQualifiedName: String?) : ThrowingExceptionJavadocTag(name, exceptionQualifiedName) {
- public companion object {
- public const val name: String = "throws"
- }
-}
-
-public class ExceptionJavadocTag(exceptionQualifiedName: String?) : ThrowingExceptionJavadocTag(name, exceptionQualifiedName) {
- public companion object {
- public const val name: String = "exception"
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/SynheticElementDocumentationProvider.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/SynheticElementDocumentationProvider.kt
deleted file mode 100644
index 5b19a42d..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/SynheticElementDocumentationProvider.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java
-
-import com.intellij.openapi.project.Project
-import com.intellij.psi.JavaPsiFacade
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.SyntheticElement
-import com.intellij.psi.javadoc.PsiDocComment
-import org.jetbrains.dokka.analysis.java.parsers.JavaPsiDocCommentParser
-import org.jetbrains.dokka.model.doc.DocumentationNode
-
-private const val ENUM_VALUEOF_TEMPLATE_PATH = "/dokka/docs/javadoc/EnumValueOf.java.template"
-private const val ENUM_VALUES_TEMPLATE_PATH = "/dokka/docs/javadoc/EnumValues.java.template"
-
-internal class SyntheticElementDocumentationProvider(
- private val javadocParser: JavaPsiDocCommentParser,
- private val project: Project
-) {
- fun isDocumented(psiElement: PsiElement): Boolean = psiElement is PsiMethod
- && (psiElement.isSyntheticEnumValuesMethod() || psiElement.isSyntheticEnumValueOfMethod())
-
- fun getDocumentation(psiElement: PsiElement): DocumentationNode? {
- val psiMethod = psiElement as? PsiMethod ?: return null
- val templatePath = when {
- psiMethod.isSyntheticEnumValuesMethod() -> ENUM_VALUES_TEMPLATE_PATH
- psiMethod.isSyntheticEnumValueOfMethod() -> ENUM_VALUEOF_TEMPLATE_PATH
- else -> return null
- }
- val docComment = loadSyntheticDoc(templatePath) ?: return null
- return javadocParser.parsePsiDocComment(docComment, psiElement)
- }
-
- private fun loadSyntheticDoc(path: String): PsiDocComment? {
- val text = javaClass.getResource(path)?.readText() ?: return null
- return JavaPsiFacade.getElementFactory(project).createDocCommentFromText(text)
- }
-}
-
-private fun PsiMethod.isSyntheticEnumValuesMethod() = this.isSyntheticEnumFunction() && this.name == "values"
-private fun PsiMethod.isSyntheticEnumValueOfMethod() = this.isSyntheticEnumFunction() && this.name == "valueOf"
-private fun PsiMethod.isSyntheticEnumFunction() = this is SyntheticElement && this.containingClass?.isEnum == true
-
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocComment.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocComment.kt
deleted file mode 100644
index be5f7eaa..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocComment.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.JavadocTag
-
-/**
- * MUST override equals and hashcode
- */
-@InternalDokkaApi
-public interface DocComment {
- public fun hasTag(tag: JavadocTag): Boolean
-
- public fun resolveTag(tag: JavadocTag): List<DocumentationContent>
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentCreator.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentCreator.kt
deleted file mode 100644
index 2e22c77c..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentCreator.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import com.intellij.psi.PsiNamedElement
-import org.jetbrains.dokka.InternalDokkaApi
-
-@InternalDokkaApi
-public interface DocCommentCreator {
- public fun create(element: PsiNamedElement): DocComment?
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFactory.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFactory.kt
deleted file mode 100644
index 4647d4d9..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFactory.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import com.intellij.psi.PsiNamedElement
-import org.jetbrains.dokka.InternalDokkaApi
-
-@InternalDokkaApi
-public class DocCommentFactory(
- private val docCommentCreators: List<DocCommentCreator>
-) {
- public fun fromElement(element: PsiNamedElement): DocComment? {
- docCommentCreators.forEach { creator ->
- val comment = creator.create(element)
- if (comment != null) {
- return comment
- }
- }
- return null
- }
-}
-
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFinder.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFinder.kt
deleted file mode 100644
index 18463e0e..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocCommentFinder.kt
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.PsiNamedElement
-import com.intellij.psi.javadoc.PsiDocComment
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.util.from
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.utilities.DokkaLogger
-
-@InternalDokkaApi
-public class DocCommentFinder(
- private val logger: DokkaLogger,
- private val docCommentFactory: DocCommentFactory,
-) {
- public fun findClosestToElement(element: PsiNamedElement): DocComment? {
- val docComment = docCommentFactory.fromElement(element)
- if (docComment != null) {
- return docComment
- }
-
- return if (element is PsiMethod) {
- findClosestToMethod(element)
- } else {
- element.children
- .filterIsInstance<PsiDocComment>()
- .firstOrNull()
- ?.let { JavaDocComment(it) }
- }
- }
-
- private fun findClosestToMethod(method: PsiMethod): DocComment? {
- val superMethods = method.findSuperMethods()
- if (superMethods.isEmpty()) return null
-
- if (superMethods.size == 1) {
- return findClosestToElement(superMethods.single())
- }
-
- val superMethodDocumentation = superMethods.map { superMethod -> findClosestToElement(superMethod) }.distinct()
- if (superMethodDocumentation.size == 1) {
- return superMethodDocumentation.single()
- }
-
- logger.debug(
- "Conflicting documentation for ${DRI.from(method)}" +
- "${superMethods.map { DRI.from(it) }}"
- )
-
- /* Prioritize super class over interface */
- val indexOfSuperClass = superMethods.indexOfFirst { superMethod ->
- val parent = superMethod.parent
- if (parent is PsiClass) !parent.isInterface
- else false
- }
-
- return if (indexOfSuperClass >= 0) {
- superMethodDocumentation[indexOfSuperClass]
- } else {
- superMethodDocumentation.first()
- }
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocumentationContent.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocumentationContent.kt
deleted file mode 100644
index 64e9ceb8..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/DocumentationContent.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.JavadocTag
-
-@InternalDokkaApi
-public interface DocumentationContent {
- public val tag: JavadocTag
-
- public fun resolveSiblings(): List<DocumentationContent>
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocComment.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocComment.kt
deleted file mode 100644
index 066b5162..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocComment.kt
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import com.intellij.psi.PsiElement
-import com.intellij.psi.javadoc.PsiDocComment
-import com.intellij.psi.javadoc.PsiDocTag
-import org.jetbrains.dokka.analysis.java.*
-import org.jetbrains.dokka.analysis.java.util.contentElementsWithSiblingIfNeeded
-import org.jetbrains.dokka.analysis.java.util.getKotlinFqName
-import org.jetbrains.dokka.analysis.java.util.hasTag
-import org.jetbrains.dokka.analysis.java.util.resolveToElement
-import org.jetbrains.dokka.utilities.firstIsInstanceOrNull
-
-internal class JavaDocComment(val comment: PsiDocComment) : DocComment {
- override fun hasTag(tag: JavadocTag): Boolean {
- return when (tag) {
- is ThrowingExceptionJavadocTag -> hasTag(tag)
- else -> comment.hasTag(tag)
- }
- }
-
- private fun hasTag(tag: ThrowingExceptionJavadocTag): Boolean =
- comment.hasTag(tag) && comment.resolveTag(tag).firstIsInstanceOrNull<PsiDocTag>()
- ?.resolveToElement()
- ?.getKotlinFqName() == tag.exceptionQualifiedName
-
- override fun resolveTag(tag: JavadocTag): List<DocumentationContent> {
- return when (tag) {
- is ParamJavadocTag -> resolveParamTag(tag)
- is ThrowingExceptionJavadocTag -> resolveThrowingTag(tag)
- else -> comment.resolveTag(tag).map { PsiDocumentationContent(it, tag) }
- }
- }
-
- private fun resolveParamTag(tag: ParamJavadocTag): List<DocumentationContent> {
- val resolvedParamElements = comment.resolveTag(tag)
- .filterIsInstance<PsiDocTag>()
- .map { it.contentElementsWithSiblingIfNeeded() }
- .firstOrNull {
- it.firstOrNull()?.text == tag.method.parameterList.parameters[tag.paramIndex].name
- }.orEmpty()
-
- return resolvedParamElements
- .withoutReferenceLink()
- .map { PsiDocumentationContent(it, tag) }
- }
-
- private fun resolveThrowingTag(tag: ThrowingExceptionJavadocTag): List<DocumentationContent> {
- val resolvedElements = comment.resolveTag(tag)
- .flatMap {
- when (it) {
- is PsiDocTag -> it.contentElementsWithSiblingIfNeeded()
- else -> listOf(it)
- }
- }
-
- return resolvedElements
- .withoutReferenceLink()
- .map { PsiDocumentationContent(it, tag) }
- }
-
- private fun PsiDocComment.resolveTag(tag: JavadocTag): List<PsiElement> {
- return when (tag) {
- DescriptionJavadocTag -> this.descriptionElements.toList()
- else -> this.findTagsByName(tag.name).toList()
- }
- }
-
- private fun List<PsiElement>.withoutReferenceLink(): List<PsiElement> = drop(1)
-
- override fun equals(other: Any?): Boolean {
- if (this === other) return true
- if (javaClass != other?.javaClass) return false
-
- other as JavaDocComment
-
- if (comment != other.comment) return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return comment.hashCode()
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocCommentCreator.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocCommentCreator.kt
deleted file mode 100644
index 79da0ee2..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/JavaDocCommentCreator.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import com.intellij.psi.PsiDocCommentOwner
-import com.intellij.psi.PsiNamedElement
-
-internal class JavaDocCommentCreator : DocCommentCreator {
- override fun create(element: PsiNamedElement): DocComment? {
- val psiDocComment = (element as? PsiDocCommentOwner)?.docComment ?: return null
- return JavaDocComment(psiDocComment)
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/PsiDocumentationContent.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/PsiDocumentationContent.kt
deleted file mode 100644
index aa1fe120..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/doccomment/PsiDocumentationContent.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.doccomment
-
-import com.intellij.psi.PsiElement
-import com.intellij.psi.javadoc.PsiDocTag
-import org.jetbrains.dokka.analysis.java.JavadocTag
-import org.jetbrains.dokka.analysis.java.util.contentElementsWithSiblingIfNeeded
-
-internal data class PsiDocumentationContent(
- val psiElement: PsiElement,
- override val tag: JavadocTag
-) : DocumentationContent {
-
- override fun resolveSiblings(): List<DocumentationContent> {
- return if (psiElement is PsiDocTag) {
- psiElement.contentElementsWithSiblingIfNeeded()
- .map { content -> PsiDocumentationContent(content, tag) }
- } else {
- listOf(this)
- }
- }
-
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/CommentResolutionContext.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/CommentResolutionContext.kt
deleted file mode 100644
index 1cd7d604..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/CommentResolutionContext.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers
-
-import com.intellij.psi.javadoc.PsiDocComment
-import org.jetbrains.dokka.analysis.java.JavadocTag
-
-internal data class CommentResolutionContext(
- val comment: PsiDocComment,
- val tag: JavadocTag?
-)
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DocCommentParser.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DocCommentParser.kt
deleted file mode 100644
index 4a381e80..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DocCommentParser.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers
-
-import com.intellij.psi.PsiNamedElement
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.doccomment.DocComment
-import org.jetbrains.dokka.model.doc.DocumentationNode
-
-@InternalDokkaApi
-public interface DocCommentParser {
- public fun canParse(docComment: DocComment): Boolean
- public fun parse(docComment: DocComment, context: PsiNamedElement): DocumentationNode
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt
deleted file mode 100644
index b8dabe42..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/DokkaPsiParser.kt
+++ /dev/null
@@ -1,803 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers
-
-import com.intellij.lang.jvm.JvmModifier
-import com.intellij.lang.jvm.annotation.JvmAnnotationAttribute
-import com.intellij.lang.jvm.annotation.JvmAnnotationAttributeValue
-import com.intellij.lang.jvm.annotation.JvmAnnotationConstantValue
-import com.intellij.lang.jvm.annotation.JvmAnnotationEnumFieldValue
-import com.intellij.lang.jvm.types.JvmReferenceType
-import com.intellij.openapi.project.Project
-import com.intellij.psi.*
-import kotlinx.coroutines.async
-import kotlinx.coroutines.coroutineScope
-import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.analysis.java.BreakingAbstractionKotlinLightMethodChecker
-import org.jetbrains.dokka.analysis.java.SyntheticElementDocumentationProvider
-import org.jetbrains.dokka.analysis.java.getVisibility
-import org.jetbrains.dokka.analysis.java.util.*
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.links.nextTarget
-import org.jetbrains.dokka.links.withClass
-import org.jetbrains.dokka.links.withEnumEntryExtra
-import org.jetbrains.dokka.model.*
-import org.jetbrains.dokka.model.AnnotationTarget
-import org.jetbrains.dokka.model.doc.DocumentationNode
-import org.jetbrains.dokka.model.doc.Param
-import org.jetbrains.dokka.model.properties.PropertyContainer
-import org.jetbrains.dokka.utilities.DokkaLogger
-import org.jetbrains.dokka.utilities.parallelForEach
-import org.jetbrains.dokka.utilities.parallelMap
-import org.jetbrains.dokka.utilities.parallelMapNotNull
-
-internal class DokkaPsiParser(
- private val sourceSetData: DokkaConfiguration.DokkaSourceSet,
- private val project: Project,
- private val logger: DokkaLogger,
- private val javadocParser: JavadocParser,
- private val javaPsiDocCommentParser: JavaPsiDocCommentParser,
- private val lightMethodChecker: BreakingAbstractionKotlinLightMethodChecker,
-) {
- private val syntheticDocProvider = SyntheticElementDocumentationProvider(javaPsiDocCommentParser, project)
-
- private val cachedBounds = hashMapOf<String, Bound>()
-
- private val PsiMethod.hash: Int
- get() = "$returnType $name$parameterList".hashCode()
-
- private val PsiField.hash: Int
- get() = "$type $name".hashCode()
-
- private val PsiClassType.shouldBeIgnored: Boolean
- get() = isClass("java.lang.Enum") || isClass("java.lang.Object")
-
- private fun PsiClassType.isClass(qName: String): Boolean {
- val shortName = qName.substringAfterLast('.')
- if (className == shortName) {
- val psiClass = resolve()
- return psiClass?.qualifiedName == qName
- }
- return false
- }
-
- private fun <T> T.toSourceSetDependent() = mapOf(sourceSetData to this)
-
- suspend fun parsePackage(packageName: String, psiFiles: List<PsiJavaFile>): DPackage = coroutineScope {
- val dri = DRI(packageName = packageName)
- val packageInfo = psiFiles.singleOrNull { it.name == "package-info.java" }
- val documentation = packageInfo?.let {
- javadocParser.parseDocumentation(it).toSourceSetDependent()
- }.orEmpty()
- val annotations = packageInfo?.packageStatement?.annotationList?.annotations
-
- DPackage(
- dri = dri,
- functions = emptyList(),
- properties = emptyList(),
- classlikes = psiFiles.parallelMap { psiFile ->
- coroutineScope {
- psiFile.classes.asIterable().parallelMap { parseClasslike(it, dri) }
- }
- }.flatten(),
- typealiases = emptyList(),
- documentation = documentation,
- expectPresentInSet = null,
- sourceSets = setOf(sourceSetData),
- extra = PropertyContainer.withAll(
- annotations?.toList().orEmpty().toListOfAnnotations().toSourceSetDependent().toAnnotations()
- )
- )
- }
-
- private suspend fun parseClasslike(psi: PsiClass, parent: DRI): DClasslike = coroutineScope {
- with(psi) {
- val dri = parent.withClass(name.toString())
- val superMethodsKeys = hashSetOf<Int>()
- val superMethods = mutableListOf<Pair<PsiMethod, DRI>>()
- val superFieldsKeys = hashSetOf<Int>()
- val superFields = mutableListOf<Pair<PsiField, DRI>>()
- methods.asIterable().parallelForEach { superMethodsKeys.add(it.hash) }
-
- /**
- * Caution! This method mutates
- * - superMethodsKeys
- * - superMethods
- * - superFieldsKeys
- * - superKeys
- */
- /**
- * Caution! This method mutates
- * - superMethodsKeys
- * - superMethods
- * - superFieldsKeys
- * - superKeys
- */
- fun Array<PsiClassType>.getSuperTypesPsiClasses(): List<Pair<PsiClass, JavaClassKindTypes>> {
- forEach { type ->
- (type as? PsiClassType)?.resolve()?.let {
- val definedAt = DRI.from(it)
- it.methods.forEach { method ->
- val hash = method.hash
- if (!method.isConstructor && !superMethodsKeys.contains(hash) &&
- method.getVisibility() != JavaVisibility.Private
- ) {
- superMethodsKeys.add(hash)
- superMethods.add(Pair(method, definedAt))
- }
- }
- it.fields.forEach { field ->
- val hash = field.hash
- if (!superFieldsKeys.contains(hash)) {
- superFieldsKeys.add(hash)
- superFields.add(Pair(field, definedAt))
- }
- }
- }
- }
- return filter { !it.shouldBeIgnored }.mapNotNull { supertypePsi ->
- supertypePsi.resolve()?.let { supertypePsiClass ->
- val javaClassKind = when {
- supertypePsiClass.isInterface -> JavaClassKindTypes.INTERFACE
- else -> JavaClassKindTypes.CLASS
- }
- supertypePsiClass to javaClassKind
- }
- }
- }
-
- fun traversePsiClassForAncestorsAndInheritedMembers(psiClass: PsiClass): AncestryNode {
- val (classes, interfaces) = psiClass.superTypes.getSuperTypesPsiClasses()
- .partition { it.second == JavaClassKindTypes.CLASS }
-
- return AncestryNode(
- typeConstructor = GenericTypeConstructor(
- DRI.from(psiClass),
- psiClass.typeParameters.map { typeParameter ->
- TypeParameter(
- dri = DRI.from(typeParameter),
- name = typeParameter.name.orEmpty(),
- extra = typeParameter.annotations()
- )
- }
- ),
- superclass = classes.singleOrNull()?.first?.let(::traversePsiClassForAncestorsAndInheritedMembers),
- interfaces = interfaces.map { traversePsiClassForAncestorsAndInheritedMembers(it.first) }
- )
- }
-
- val ancestry: AncestryNode = traversePsiClassForAncestorsAndInheritedMembers(this)
-
- val (regularFunctions, accessors) = splitFunctionsAndAccessors(psi.fields, psi.methods)
- val (regularSuperFunctions, superAccessors) = splitFunctionsAndAccessors(
- fields = superFields.map { it.first }.toTypedArray(),
- methods = superMethods.map { it.first }.toTypedArray()
- )
-
- val regularSuperFunctionsKeys = regularSuperFunctions.map { it.hash }.toSet()
- val regularSuperFunctionsWithDRI = superMethods.filter { it.first.hash in regularSuperFunctionsKeys }
-
- val superAccessorsWithDRI = superAccessors.mapValues { (field, methods) ->
- val containsJvmField = field.annotations.mapNotNull { it.toAnnotation() }.any { it.isJvmField() }
- if (containsJvmField) {
- emptyList()
- } else {
- methods.mapNotNull { method -> superMethods.find { it.first.hash == method.hash } }
- }
- }
-
- val overridden = regularFunctions.flatMap { it.findSuperMethods().toList() }
- val documentation = javadocParser.parseDocumentation(this).toSourceSetDependent()
- val allFunctions = async {
- val parsedRegularFunctions = regularFunctions.parallelMapNotNull {
- if (!it.isConstructor) parseFunction(
- it,
- parentDRI = dri
- ) else null
- }
- val parsedSuperFunctions = regularSuperFunctionsWithDRI
- .filter { it.first !in overridden }
- .parallelMap { parseFunction(it.first, inheritedFrom = it.second) }
-
- parsedRegularFunctions + parsedSuperFunctions
- }
- val allFields = async {
- val parsedFields = fields.toList().parallelMapNotNull {
- parseField(it, accessors[it].orEmpty())
- }
- val parsedSuperFields = superFields.parallelMapNotNull { (field, dri) ->
- parseFieldWithInheritingAccessors(
- field,
- superAccessorsWithDRI[field].orEmpty(),
- inheritedFrom = dri
- )
- }
- parsedFields + parsedSuperFields
- }
- val source = parseSources()
- val classlikes = async { innerClasses.asIterable().parallelMap { parseClasslike(it, dri) } }
- val visibility = getVisibility().toSourceSetDependent()
- val ancestors = (listOfNotNull(ancestry.superclass?.let {
- it.typeConstructor.let { typeConstructor ->
- TypeConstructorWithKind(
- typeConstructor,
- JavaClassKindTypes.CLASS
- )
- }
- }) + ancestry.interfaces.map {
- TypeConstructorWithKind(
- it.typeConstructor,
- JavaClassKindTypes.INTERFACE
- )
- }).toSourceSetDependent()
- val modifiers = getModifier().toSourceSetDependent()
- val implementedInterfacesExtra =
- ImplementedInterfaces(ancestry.allImplementedInterfaces().toSourceSetDependent())
-
- when {
- isAnnotationType ->
- DAnnotation(
- name = name.orEmpty(),
- dri = dri,
- documentation = documentation,
- expectPresentInSet = null,
- sources = source,
- functions = allFunctions.await(),
- properties = allFields.await(),
- classlikes = classlikes.await(),
- visibility = visibility,
- companion = null,
- constructors = parseConstructors(dri),
- generics = mapTypeParameters(dri),
- sourceSets = setOf(sourceSetData),
- isExpectActual = false,
- extra = PropertyContainer.withAll(
- implementedInterfacesExtra,
- annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
-
- isEnum -> DEnum(
- dri = dri,
- name = name.orEmpty(),
- entries = fields.filterIsInstance<PsiEnumConstant>().map { entry ->
- DEnumEntry(
- dri = dri.withClass(entry.name).withEnumEntryExtra(),
- name = entry.name,
- documentation = javadocParser.parseDocumentation(entry).toSourceSetDependent(),
- expectPresentInSet = null,
- functions = emptyList(),
- properties = emptyList(),
- classlikes = emptyList(),
- sourceSets = setOf(sourceSetData),
- extra = PropertyContainer.withAll(
- implementedInterfacesExtra,
- annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
- },
- documentation = documentation,
- expectPresentInSet = null,
- sources = source,
- functions = allFunctions.await(),
- properties = fields.filter { it !is PsiEnumConstant }
- .map { parseField(it, accessors[it].orEmpty()) },
- classlikes = classlikes.await(),
- visibility = visibility,
- companion = null,
- constructors = parseConstructors(dri),
- supertypes = ancestors,
- sourceSets = setOf(sourceSetData),
- isExpectActual = false,
- extra = PropertyContainer.withAll(
- implementedInterfacesExtra,
- annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
-
- isInterface -> DInterface(
- dri = dri,
- name = name.orEmpty(),
- documentation = documentation,
- expectPresentInSet = null,
- sources = source,
- functions = allFunctions.await(),
- properties = allFields.await(),
- classlikes = classlikes.await(),
- visibility = visibility,
- companion = null,
- generics = mapTypeParameters(dri),
- supertypes = ancestors,
- sourceSets = setOf(sourceSetData),
- isExpectActual = false,
- extra = PropertyContainer.withAll(
- implementedInterfacesExtra,
- annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
-
- else -> DClass(
- dri = dri,
- name = name.orEmpty(),
- constructors = parseConstructors(dri),
- functions = allFunctions.await(),
- properties = allFields.await(),
- classlikes = classlikes.await(),
- sources = source,
- visibility = visibility,
- companion = null,
- generics = mapTypeParameters(dri),
- supertypes = ancestors,
- documentation = documentation,
- expectPresentInSet = null,
- modifier = modifiers,
- sourceSets = setOf(sourceSetData),
- isExpectActual = false,
- extra = PropertyContainer.withAll(
- implementedInterfacesExtra,
- annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations(),
- ancestry.exceptionInSupertypesOrNull()
- )
- )
- }
- }
- }
-
- /*
- * Parameter `parentDRI` required for substitute package name:
- * in the case of synthetic constructor, it will return empty from [DRI.Companion.from].
- */
- private fun PsiClass.parseConstructors(parentDRI: DRI): List<DFunction> {
- val constructors = when {
- isAnnotationType || isInterface -> emptyArray()
- isEnum -> this.constructors
- else -> this.constructors.takeIf { it.isNotEmpty() } ?: arrayOf(createDefaultConstructor())
- }
- return constructors.map { parseFunction(psi = it, isConstructor = true, parentDRI = parentDRI) }
- }
-
- /**
- * PSI doesn't return a default constructor if class doesn't contain an explicit one.
- * This method create synthetic constructor
- * Visibility modifier is preserved from the class.
- */
- private fun PsiClass.createDefaultConstructor(): PsiMethod {
- val psiElementFactory = JavaPsiFacade.getElementFactory(project)
- val signature = when (val classVisibility = getVisibility()) {
- JavaVisibility.Default -> name.orEmpty()
- else -> "${classVisibility.name} $name"
- }
- return psiElementFactory.createConstructor(signature, this)
- }
-
- private fun AncestryNode.exceptionInSupertypesOrNull(): ExceptionInSupertypes? =
- typeConstructorsBeingExceptions().takeIf { it.isNotEmpty() }
- ?.let { ExceptionInSupertypes(it.toSourceSetDependent()) }
-
- private fun parseFunction(
- psi: PsiMethod,
- isConstructor: Boolean = false,
- inheritedFrom: DRI? = null,
- parentDRI: DRI? = null,
- ): DFunction {
- val dri = parentDRI?.let { dri ->
- DRI.from(psi).copy(packageName = dri.packageName, classNames = dri.classNames)
- } ?: DRI.from(psi)
- val docs = psi.getDocumentation()
- return DFunction(
- dri = dri,
- name = psi.name,
- isConstructor = isConstructor,
- parameters = psi.parameterList.parameters.map { psiParameter ->
- DParameter(
- dri = dri.copy(target = dri.target.nextTarget()),
- name = psiParameter.name,
- documentation = DocumentationNode(
- listOfNotNull(docs.firstChildOfTypeOrNull<Param> {
- it.name == psiParameter.name
- })
- ).toSourceSetDependent(),
- expectPresentInSet = null,
- type = getBound(psiParameter.type),
- sourceSets = setOf(sourceSetData),
- extra = PropertyContainer.withAll(
- psiParameter.annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
- },
- documentation = docs.toSourceSetDependent(),
- expectPresentInSet = null,
- sources = psi.parseSources(),
- visibility = psi.getVisibility().toSourceSetDependent(),
- type = psi.returnType?.let { getBound(type = it) } ?: Void,
- generics = psi.mapTypeParameters(dri),
- receiver = null,
- modifier = psi.getModifier().toSourceSetDependent(),
- sourceSets = setOf(sourceSetData),
- isExpectActual = false,
- extra = psi.additionalExtras().let {
- PropertyContainer.withAll(
- inheritedFrom?.let { InheritedMember(it.toSourceSetDependent()) },
- it.toSourceSetDependent().toAdditionalModifiers(),
- (psi.annotations.toList()
- .toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
- .toAnnotations(),
- ObviousMember.takeIf { psi.isObvious(inheritedFrom) },
- psi.throwsList.toDriList().takeIf { it.isNotEmpty() }
- ?.let { CheckedExceptions(it.toSourceSetDependent()) }
- )
- }
- )
- }
-
- private fun PsiNamedElement.parseSources(): SourceSetDependent<DocumentableSource> {
- return when {
- // `isPhysical` detects the virtual declarations without real sources.
- // Otherwise, `PsiDocumentableSource` initialization will fail: non-physical declarations doesn't have `virtualFile`.
- // This check protects from accidentally requesting sources for synthetic / virtual declarations.
- isPhysical -> PsiDocumentableSource(this).toSourceSetDependent()
- else -> emptyMap()
- }
- }
-
- private fun PsiMethod.getDocumentation(): DocumentationNode =
- this.takeIf { it is SyntheticElement }?.let { syntheticDocProvider.getDocumentation(it) }
- ?: javadocParser.parseDocumentation(this)
-
- private fun PsiMethod.isObvious(inheritedFrom: DRI? = null): Boolean {
- return (this is SyntheticElement && !syntheticDocProvider.isDocumented(this))
- || inheritedFrom?.isObvious() == true
- }
-
- private fun DRI.isObvious(): Boolean {
- return packageName == "java.lang" && (classNames == "Object" || classNames == "Enum")
- }
-
- private fun PsiReferenceList.toDriList() = referenceElements.mapNotNull { it?.resolve()?.let { DRI.from(it) } }
-
- private fun PsiModifierListOwner.additionalExtras() = listOfNotNull(
- ExtraModifiers.JavaOnlyModifiers.Static.takeIf { hasModifier(JvmModifier.STATIC) },
- ExtraModifiers.JavaOnlyModifiers.Native.takeIf { hasModifier(JvmModifier.NATIVE) },
- ExtraModifiers.JavaOnlyModifiers.Synchronized.takeIf { hasModifier(JvmModifier.SYNCHRONIZED) },
- ExtraModifiers.JavaOnlyModifiers.StrictFP.takeIf { hasModifier(JvmModifier.STRICTFP) },
- ExtraModifiers.JavaOnlyModifiers.Transient.takeIf { hasModifier(JvmModifier.TRANSIENT) },
- ExtraModifiers.JavaOnlyModifiers.Volatile.takeIf { hasModifier(JvmModifier.VOLATILE) },
- ExtraModifiers.JavaOnlyModifiers.Transitive.takeIf { hasModifier(JvmModifier.TRANSITIVE) }
- ).toSet()
-
- private fun Set<ExtraModifiers>.toListOfAnnotations() = map {
- if (it !is ExtraModifiers.JavaOnlyModifiers.Static)
- Annotations.Annotation(DRI("kotlin.jvm", it.name.toLowerCase().capitalize()), emptyMap())
- else
- Annotations.Annotation(DRI("kotlin.jvm", "JvmStatic"), emptyMap())
- }
-
- /**
- * Workaround for getting JvmField Kotlin annotation in PSIs
- */
- private fun Collection<PsiAnnotation>.findJvmFieldAnnotation(): Annotations.Annotation? {
- val anyJvmFieldAnnotation = this.any {
- it.qualifiedName == "$JVM_FIELD_PACKAGE_NAME.$JVM_FIELD_CLASS_NAMES"
- }
- return if (anyJvmFieldAnnotation) {
- Annotations.Annotation(DRI(JVM_FIELD_PACKAGE_NAME, JVM_FIELD_CLASS_NAMES), emptyMap())
- } else {
- null
- }
- }
-
- private fun <T : AnnotationTarget> PsiTypeParameter.annotations(): PropertyContainer<T> = this.annotations.toList().toListOfAnnotations().annotations()
- private fun <T : AnnotationTarget> PsiType.annotations(): PropertyContainer<T> = this.annotations.toList().toListOfAnnotations().annotations()
-
- private fun <T : AnnotationTarget> List<Annotations.Annotation>.annotations(): PropertyContainer<T> =
- this.takeIf { it.isNotEmpty() }?.let { annotations ->
- PropertyContainer.withAll(annotations.toSourceSetDependent().toAnnotations())
- } ?: PropertyContainer.empty()
-
- private fun getBound(type: PsiType): Bound {
- //We would like to cache most of the bounds since it is not common to annotate them,
- //but if this is the case, we treat them as 'one of'
- fun PsiType.cacheBoundIfHasNoAnnotation(f: (List<Annotations.Annotation>) -> Bound): Bound {
- val annotations = this.annotations.toList().toListOfAnnotations()
- return if (annotations.isNotEmpty()) f(annotations)
- else cachedBounds.getOrPut(canonicalText) {
- f(annotations)
- }
- }
-
- return when (type) {
- is PsiClassType ->
- type.resolve()?.let { resolved ->
- when {
- resolved.qualifiedName == "java.lang.Object" -> type.cacheBoundIfHasNoAnnotation { annotations -> JavaObject(annotations.annotations()) }
- resolved is PsiTypeParameter -> {
- TypeParameter(
- dri = DRI.from(resolved),
- name = resolved.name.orEmpty(),
- extra = type.annotations()
- )
- }
-
- Regex("kotlin\\.jvm\\.functions\\.Function.*").matches(resolved.qualifiedName ?: "") ||
- Regex("java\\.util\\.function\\.Function.*").matches(
- resolved.qualifiedName ?: ""
- ) -> FunctionalTypeConstructor(
- DRI.from(resolved),
- type.parameters.map { getProjection(it) },
- extra = type.annotations()
- )
-
- else -> {
- // cache types that have no annotation and no type parameter
- // since we cache only by name and type parameters depend on context
- val typeParameters = type.parameters.map { getProjection(it) }
- if (typeParameters.isEmpty())
- type.cacheBoundIfHasNoAnnotation { annotations ->
- GenericTypeConstructor(
- DRI.from(resolved),
- typeParameters,
- extra = annotations.annotations()
- )
- }
- else
- GenericTypeConstructor(
- DRI.from(resolved),
- typeParameters,
- extra = type.annotations()
- )
- }
- }
- } ?: UnresolvedBound(type.presentableText, type.annotations())
-
- is PsiArrayType -> GenericTypeConstructor(
- DRI("kotlin", "Array"),
- listOf(getProjection(type.componentType)),
- extra = type.annotations()
- )
-
- is PsiPrimitiveType -> if (type.name == "void") Void
- else type.cacheBoundIfHasNoAnnotation { annotations -> PrimitiveJavaType(type.name, annotations.annotations()) }
- else -> throw IllegalStateException("${type.presentableText} is not supported by PSI parser")
- }
- }
-
-
- private fun getVariance(type: PsiWildcardType): Projection = when {
- type.isExtends -> Covariance(getBound(type.extendsBound))
- type.isSuper -> Contravariance(getBound(type.superBound))
- // If the type isn't explicitly bounded, it still has an implicit `extends Object` bound
- type.extendsBound != PsiType.NULL -> Covariance(getBound(type.extendsBound))
- else -> throw IllegalStateException("${type.presentableText} has incorrect bounds")
- }
-
- private fun getProjection(type: PsiType): Projection = when (type) {
- is PsiEllipsisType -> Star
- is PsiWildcardType -> getVariance(type)
- else -> getBound(type)
- }
-
- private fun PsiModifierListOwner.getModifier() = when {
- hasModifier(JvmModifier.ABSTRACT) -> JavaModifier.Abstract
- hasModifier(JvmModifier.FINAL) -> JavaModifier.Final
- else -> JavaModifier.Empty
- }
-
- private fun PsiTypeParameterListOwner.mapTypeParameters(dri: DRI): List<DTypeParameter> {
- fun mapBounds(bounds: Array<JvmReferenceType>): List<Bound> =
- if (bounds.isEmpty()) emptyList() else bounds.mapNotNull {
- (it as? PsiClassType)?.let { classType -> Nullable(getBound(classType)) }
- }
- return typeParameters.map { type ->
- DTypeParameter(
- dri = dri.copy(target = dri.target.nextTarget()),
- name = type.name.orEmpty(),
- presentableName = null,
- documentation = javadocParser.parseDocumentation(type).toSourceSetDependent(),
- expectPresentInSet = null,
- bounds = mapBounds(type.bounds),
- sourceSets = setOf(sourceSetData),
- extra = PropertyContainer.withAll(
- type.annotations.toList().toListOfAnnotations().toSourceSetDependent()
- .toAnnotations()
- )
- )
- }
- }
-
- private fun parseFieldWithInheritingAccessors(
- psi: PsiField,
- accessors: List<Pair<PsiMethod, DRI>>,
- inheritedFrom: DRI
- ): DProperty {
- val getter = accessors
- .firstOrNull { (method, _) -> method.isGetterFor(psi) }
- ?.let { (method, dri) -> parseFunction(method, inheritedFrom = dri) }
-
- val setter = accessors
- .firstOrNull { (method, _) -> method.isSetterFor(psi) }
- ?.let { (method, dri) -> parseFunction(method, inheritedFrom = dri) }
-
- return parseField(
- psi = psi,
- getter = getter,
- setter = setter,
- inheritedFrom = inheritedFrom
- )
- }
-
- private fun parseField(psi: PsiField, accessors: List<PsiMethod>, inheritedFrom: DRI? = null): DProperty {
- val getter = accessors.firstOrNull { it.isGetterFor(psi) }?.let { parseFunction(it) }
- val setter = accessors.firstOrNull { it.isSetterFor(psi) }?.let { parseFunction(it) }
- return parseField(
- psi = psi,
- getter = getter,
- setter = setter,
- inheritedFrom = inheritedFrom
- )
- }
-
- private fun parseField(psi: PsiField, getter: DFunction?, setter: DFunction?, inheritedFrom: DRI? = null): DProperty {
- val dri = DRI.from(psi)
-
- // non-final java field without accessors should be a var
- // setter should be not null when inheriting kotlin vars
- val isMutable = !psi.hasModifierProperty("final")
- val isVar = (isMutable && getter == null && setter == null) || (getter != null && setter != null)
-
- return DProperty(
- dri = dri,
- name = psi.name,
- documentation = javadocParser.parseDocumentation(psi).toSourceSetDependent(),
- expectPresentInSet = null,
- sources = psi.parseSources(),
- visibility = psi.getVisibility(getter).toSourceSetDependent(),
- type = getBound(psi.type),
- receiver = null,
- setter = setter,
- getter = getter,
- modifier = psi.getModifier().toSourceSetDependent(),
- sourceSets = setOf(sourceSetData),
- generics = emptyList(),
- isExpectActual = false,
- extra = psi.additionalExtras().let {
- val psiAnnotations = psi.annotations.toList()
- val parsedAnnotations = psiAnnotations.toListOfAnnotations()
- val extraModifierAnnotations = it.toListOfAnnotations()
- val jvmFieldAnnotation = psiAnnotations.findJvmFieldAnnotation()
- val annotations = parsedAnnotations + extraModifierAnnotations + listOfNotNull(jvmFieldAnnotation)
-
- PropertyContainer.withAll(
- inheritedFrom?.let { inheritedFrom -> InheritedMember(inheritedFrom.toSourceSetDependent()) },
- it.toSourceSetDependent().toAdditionalModifiers(),
- annotations.toSourceSetDependent().toAnnotations(),
- psi.getConstantExpression()?.let { DefaultValue(it.toSourceSetDependent()) },
- takeIf { isVar }?.let { IsVar }
- )
- }
- )
- }
-
- private fun PsiField.getVisibility(getter: DFunction?): Visibility {
- return getter?.visibility?.get(sourceSetData) ?: this.getVisibility()
- }
-
- private fun Collection<PsiAnnotation>.toListOfAnnotations() =
- filter { !lightMethodChecker.isLightAnnotation(it) }.mapNotNull { it.toAnnotation() }
-
- private fun PsiField.getConstantExpression(): Expression? {
- val constantValue = this.computeConstantValue() ?: return null
- return when (constantValue) {
- is Byte -> IntegerConstant(constantValue.toLong())
- is Short -> IntegerConstant(constantValue.toLong())
- is Int -> IntegerConstant(constantValue.toLong())
- is Long -> IntegerConstant(constantValue)
- is Char -> StringConstant(constantValue.toString())
- is String -> StringConstant(constantValue)
- is Double -> DoubleConstant(constantValue)
- is Float -> FloatConstant(constantValue)
- is Boolean -> BooleanConstant(constantValue)
- else -> ComplexExpression(constantValue.toString())
- }
- }
-
- private fun JvmAnnotationAttribute.toValue(): AnnotationParameterValue = when (this) {
- is PsiNameValuePair -> value?.toValue() ?: attributeValue?.toValue() ?: StringValue("")
- else -> StringValue(this.attributeName)
- }.let { annotationValue ->
- if (annotationValue is StringValue) annotationValue.copy(annotationValue.value.removeSurrounding("\""))
- else annotationValue
- }
-
- /**
- * This is a workaround for static imports from JDK like RetentionPolicy
- * For some reason they are not represented in the same way than using normal import
- */
- private fun JvmAnnotationAttributeValue.toValue(): AnnotationParameterValue? {
- return when (this) {
- is JvmAnnotationEnumFieldValue -> (field as? PsiElement)?.let { EnumValue(fieldName ?: "", DRI.from(it)) }
- // static import of a constant is resolved to constant value instead of a field/link
- is JvmAnnotationConstantValue -> this.constantValue?.toAnnotationLiteralValue()
- else -> null
- }
- }
-
- private fun Any.toAnnotationLiteralValue() = when (this) {
- is Byte -> IntValue(this.toInt())
- is Short -> IntValue(this.toInt())
- is Char -> StringValue(this.toString())
- is Int -> IntValue(this)
- is Long -> LongValue(this)
- is Boolean -> BooleanValue(this)
- is Float -> FloatValue(this)
- is Double -> DoubleValue(this)
- else -> StringValue(this.toString())
- }
-
- private fun PsiAnnotationMemberValue.toValue(): AnnotationParameterValue? = when (this) {
- is PsiAnnotation -> toAnnotation()?.let { AnnotationValue(it) }
- is PsiArrayInitializerMemberValue -> ArrayValue(initializers.mapNotNull { it.toValue() })
- is PsiReferenceExpression -> psiReference?.let { EnumValue(text ?: "", DRI.from(it)) }
- is PsiClassObjectAccessExpression -> {
- val parameterType = (type as? PsiClassType)?.parameters?.firstOrNull()
- val classType = when (parameterType) {
- is PsiClassType -> parameterType.resolve()
- // Notice: Array<String>::class will be passed down as String::class
- // should probably be Array::class instead but this reflects behaviour for Kotlin sources
- is PsiArrayType -> (parameterType.componentType as? PsiClassType)?.resolve()
- else -> null
- }
- classType?.let { ClassValue(it.name ?: "", DRI.from(it)) }
- }
- is PsiLiteralExpression -> toValue()
- else -> StringValue(text ?: "")
- }
-
- private fun PsiLiteralExpression.toValue(): AnnotationParameterValue? = when (type) {
- PsiType.INT -> (value as? Int)?.let { IntValue(it) }
- PsiType.LONG -> (value as? Long)?.let { LongValue(it) }
- PsiType.FLOAT -> (value as? Float)?.let { FloatValue(it) }
- PsiType.DOUBLE -> (value as? Double)?.let { DoubleValue(it) }
- PsiType.BOOLEAN -> (value as? Boolean)?.let { BooleanValue(it) }
- PsiType.NULL -> NullValue
- else -> StringValue(text ?: "")
- }
-
- private fun PsiAnnotation.toAnnotation(): Annotations.Annotation? {
- // TODO Mitigating workaround for issue https://github.com/Kotlin/dokka/issues/1341
- // Tracking https://youtrack.jetbrains.com/issue/KT-41234
- // Needs to be removed once this issue is fixed in light classes
- fun PsiElement.getAnnotationsOrNull(): Array<PsiAnnotation>? {
- this as PsiClass
- return try {
- this.annotations
- } catch (e: Exception) {
- logger.warn("Failed to get annotations from ${this.qualifiedName}")
- null
- }
- }
-
- return psiReference?.let { psiElement ->
- Annotations.Annotation(
- dri = DRI.from(psiElement),
- params = attributes
- .filter { !lightMethodChecker.isLightAnnotationAttribute(it) }
- .mapNotNull { it.attributeName to it.toValue() }
- .toMap(),
- mustBeDocumented = psiElement.getAnnotationsOrNull().orEmpty().any { annotation ->
- annotation.hasQualifiedName("java.lang.annotation.Documented")
- }
- )
- }
- }
-
- private val PsiElement.psiReference
- get() = getChildOfType<PsiJavaCodeReferenceElement>()?.resolve()
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavaDocCommentParser.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavaDocCommentParser.kt
deleted file mode 100644
index 1e4c9f2d..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavaDocCommentParser.kt
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers
-
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.PsiNamedElement
-import com.intellij.psi.PsiWhiteSpace
-import com.intellij.psi.impl.source.tree.JavaDocElementType
-import com.intellij.psi.impl.source.tree.LazyParseablePsiElement
-import com.intellij.psi.javadoc.PsiDocComment
-import com.intellij.psi.javadoc.PsiDocTag
-
-import org.jetbrains.dokka.analysis.java.*
-import org.jetbrains.dokka.analysis.java.doccomment.DocComment
-import org.jetbrains.dokka.analysis.java.doccomment.JavaDocComment
-import org.jetbrains.dokka.analysis.java.parsers.doctag.PsiDocTagParser
-import org.jetbrains.dokka.analysis.java.util.*
-import org.jetbrains.dokka.analysis.markdown.jb.MARKDOWN_ELEMENT_FILE_NAME
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.doc.*
-import org.jetbrains.dokka.model.doc.Deprecated
-
-internal class JavaPsiDocCommentParser(
- private val psiDocTagParser: PsiDocTagParser,
-) : DocCommentParser {
-
- override fun canParse(docComment: DocComment): Boolean {
- return docComment is JavaDocComment
- }
-
- override fun parse(docComment: DocComment, context: PsiNamedElement): DocumentationNode {
- val javaDocComment = docComment as JavaDocComment
- return parsePsiDocComment(javaDocComment.comment, context)
- }
-
- internal fun parsePsiDocComment(docComment: PsiDocComment, context: PsiNamedElement): DocumentationNode {
- val description = listOfNotNull(docComment.getDescription())
- val tags = docComment.tags.mapNotNull { tag ->
- parseDocTag(tag, docComment, context)
- }
- return DocumentationNode(description + tags)
- }
-
- private fun PsiDocComment.getDescription(): Description? {
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = descriptionElements.asIterable(),
- commentResolutionContext = CommentResolutionContext(this, DescriptionJavadocTag),
- )
- return docTags.takeIf { it.isNotEmpty() }?.let {
- Description(wrapTagIfNecessary(it))
- }
- }
-
- private fun parseDocTag(tag: PsiDocTag, docComment: PsiDocComment, analysedElement: PsiNamedElement): TagWrapper? {
- return when (tag.name) {
- ParamJavadocTag.name -> parseParamTag(tag, docComment, analysedElement)
- ThrowsJavadocTag.name, ExceptionJavadocTag.name -> parseThrowsTag(tag, docComment)
- ReturnJavadocTag.name -> parseReturnTag(tag, docComment)
- SinceJavadocTag.name -> parseSinceTag(tag, docComment)
- AuthorJavadocTag.name -> parseAuthorTag(tag, docComment)
- SeeJavadocTag.name -> parseSeeTag(tag, docComment)
- DeprecatedJavadocTag.name -> parseDeprecatedTag(tag, docComment)
- else -> emptyTagWrapper(tag, docComment)
- }
- }
-
- private fun parseParamTag(
- tag: PsiDocTag,
- docComment: PsiDocComment,
- analysedElement: PsiNamedElement
- ): TagWrapper? {
- val paramName = tag.dataElements.firstOrNull()?.text.orEmpty()
-
- // can be a PsiClass if @param is referencing class generics, like here:
- // https://github.com/biojava/biojava/blob/2417c230be36e4ba73c62bb3631b60f876265623/biojava-core/src/main/java/org/biojava/nbio/core/alignment/SimpleProfilePair.java#L43
- // not supported at the moment
- val method = analysedElement as? PsiMethod ?: return null
- val paramIndex = method.parameterList.parameters.map { it.name }.indexOf(paramName)
-
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.contentElementsWithSiblingIfNeeded().drop(1),
- commentResolutionContext = CommentResolutionContext(
- comment = docComment,
- tag = ParamJavadocTag(method, paramName, paramIndex)
- )
- )
- return Param(root = wrapTagIfNecessary(docTags), name = paramName)
- }
-
- private fun parseThrowsTag(
- tag: PsiDocTag,
- docComment: PsiDocComment
- ): Throws {
- val resolvedElement = tag.resolveToElement()
- val exceptionAddress = resolvedElement?.let { DRI.from(it) }
-
- /* we always would like to have a fully qualified name as name,
- * because it will be used as a display name later and we would like to have those unified
- * even if documentation states shortened version
- * Only if dri search fails we should use the provided phrase (since then we are not able to get a fq name)
- */
- val fullyQualifiedExceptionName =
- resolvedElement?.getKotlinFqName() ?: tag.dataElements.firstOrNull()?.text.orEmpty()
-
- val javadocTag = when (tag.name) {
- ThrowsJavadocTag.name -> ThrowsJavadocTag(fullyQualifiedExceptionName)
- ExceptionJavadocTag.name -> ExceptionJavadocTag(fullyQualifiedExceptionName)
- else -> throw IllegalArgumentException("Expected @throws or @exception")
- }
-
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.dataElements.drop(1),
- commentResolutionContext = CommentResolutionContext(
- comment = docComment,
- tag = javadocTag
- ),
- )
- return Throws(
- root = wrapTagIfNecessary(docTags),
- name = fullyQualifiedExceptionName,
- exceptionAddress = exceptionAddress
- )
- }
-
- private fun parseReturnTag(
- tag: PsiDocTag,
- docComment: PsiDocComment
- ): Return {
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.contentElementsWithSiblingIfNeeded(),
- commentResolutionContext = CommentResolutionContext(comment = docComment, tag = ReturnJavadocTag),
- )
- return Return(root = wrapTagIfNecessary(docTags))
- }
-
- private fun parseSinceTag(
- tag: PsiDocTag,
- docComment: PsiDocComment
- ): Since {
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.contentElementsWithSiblingIfNeeded(),
- commentResolutionContext = CommentResolutionContext(comment = docComment, tag = ReturnJavadocTag),
- )
- return Since(root = wrapTagIfNecessary(docTags))
- }
-
- private fun parseAuthorTag(
- tag: PsiDocTag,
- docComment: PsiDocComment
- ): Author {
- // TODO [beresnev] see what the hell this is
- // Workaround: PSI returns first word after @author tag as a `DOC_TAG_VALUE_ELEMENT`,
- // then the rest as a `DOC_COMMENT_DATA`, so for `Name Surname` we get them parted
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.contentElementsWithSiblingIfNeeded(),
- commentResolutionContext = CommentResolutionContext(comment = docComment, tag = AuthorJavadocTag),
- )
- return Author(root = wrapTagIfNecessary(docTags))
- }
-
- private fun parseSeeTag(
- tag: PsiDocTag,
- docComment: PsiDocComment
- ): See {
- val referenceElement = tag.referenceElement()
- val fullyQualifiedSeeReference = tag.resolveToElement()?.getKotlinFqName()
- ?: referenceElement?.text.orEmpty().removePrefix("#")
-
- val context = CommentResolutionContext(comment = docComment, tag = SeeJavadocTag(fullyQualifiedSeeReference))
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.dataElements.dropWhile {
- it is PsiWhiteSpace || it.isDocReferenceHolder() || it == referenceElement
- },
- commentResolutionContext = context,
- )
-
- return See(
- root = wrapTagIfNecessary(docTags),
- name = fullyQualifiedSeeReference,
- address = referenceElement?.toDocumentationLink(context = context)?.dri
- )
- }
-
- private fun PsiElement.isDocReferenceHolder(): Boolean {
- return (this as? LazyParseablePsiElement)?.elementType == JavaDocElementType.DOC_REFERENCE_HOLDER
- }
-
- private fun parseDeprecatedTag(
- tag: PsiDocTag,
- docComment: PsiDocComment
- ): Deprecated {
- val docTags = psiDocTagParser.parseAsParagraph(
- tag.contentElementsWithSiblingIfNeeded(),
- CommentResolutionContext(comment = docComment, tag = DeprecatedJavadocTag),
- )
- return Deprecated(root = wrapTagIfNecessary(docTags))
- }
-
- private fun wrapTagIfNecessary(tags: List<DocTag>): CustomDocTag {
- val isFile = (tags.singleOrNull() as? CustomDocTag)?.name == MARKDOWN_ELEMENT_FILE_NAME
- return if (isFile) {
- tags.first() as CustomDocTag
- } else {
- CustomDocTag(tags, name = MARKDOWN_ELEMENT_FILE_NAME)
- }
- }
-
- // Wrapper for unsupported tags https://github.com/Kotlin/dokka/issues/1618
- private fun emptyTagWrapper(
- tag: PsiDocTag,
- docComment: PsiDocComment,
- ): CustomTagWrapper {
- val docTags = psiDocTagParser.parseAsParagraph(
- psiElements = tag.contentElementsWithSiblingIfNeeded(),
- commentResolutionContext = CommentResolutionContext(docComment, null),
- )
- return CustomTagWrapper(
- root = wrapTagIfNecessary(docTags),
- name = tag.name
- )
- }
-
- private fun PsiElement.toDocumentationLink(labelElement: PsiElement? = null, context: CommentResolutionContext): DocumentationLink? {
- val resolvedElement = this.resolveToGetDri() ?: return null
- val label = labelElement ?: defaultLabel()
- val docTags = psiDocTagParser.parse(listOfNotNull(label), context)
- return DocumentationLink(dri = DRI.from(resolvedElement), children = docTags)
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavadocParser.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavadocParser.kt
deleted file mode 100644
index 140e64c9..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/JavadocParser.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers
-
-import com.intellij.psi.PsiNamedElement
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.doccomment.DocCommentFinder
-import org.jetbrains.dokka.model.doc.DocumentationNode
-
-internal fun interface JavaDocumentationParser {
- fun parseDocumentation(element: PsiNamedElement): DocumentationNode
-}
-
-@InternalDokkaApi
-public class JavadocParser(
- private val docCommentParsers: List<DocCommentParser>,
- private val docCommentFinder: DocCommentFinder
-) : JavaDocumentationParser {
-
- override fun parseDocumentation(element: PsiNamedElement): DocumentationNode {
- val comment = docCommentFinder.findClosestToElement(element) ?: return DocumentationNode(emptyList())
- return docCommentParsers
- .first { it.canParse(comment) }
- .parse(comment, element)
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/DocTagParserContext.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/DocTagParserContext.kt
deleted file mode 100644
index e8df804b..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/DocTagParserContext.kt
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers.doctag
-
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.doc.DocumentationNode
-import java.util.*
-
-@InternalDokkaApi
-public class DocTagParserContext {
- /**
- * exists for resolving `@link element` links, where the referenced
- * PSI element is mapped as DRI
- *
- * only used in the context of parsing to html and then from html to doctag
- */
- private val driMap = mutableMapOf<String, DRI>()
-
- /**
- * Cache created to make storing entries from kotlin easier.
- *
- * It has to be mutable to allow for adding entries when @inheritDoc resolves to kotlin code,
- * from which we get a DocTags not descriptors.
- */
- private val inheritDocSections = mutableMapOf<String, DocumentationNode>()
-
- /**
- * @return key of the stored DRI
- */
- public fun store(dri: DRI): String {
- val id = dri.toString()
- driMap[id] = dri
- return id
- }
-
- /**
- * @return key of the stored documentation node
- */
- public fun store(documentationNode: DocumentationNode): String {
- val id = UUID.randomUUID().toString()
- inheritDocSections[id] = documentationNode
- return id
- }
-
- public fun getDri(id: String): DRI? = driMap[id]
-
- public fun getDocumentationNode(id: String): DocumentationNode? = inheritDocSections[id]
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/HtmlToDocTagConverter.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/HtmlToDocTagConverter.kt
deleted file mode 100644
index 195ce79a..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/HtmlToDocTagConverter.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers.doctag
-
-import org.jetbrains.dokka.analysis.markdown.jb.parseHtmlEncodedWithNormalisedSpaces
-import org.jetbrains.dokka.model.doc.*
-import org.jsoup.Jsoup
-import org.jsoup.nodes.Comment
-import org.jsoup.nodes.Element
-import org.jsoup.nodes.Node
-import org.jsoup.nodes.TextNode
-
-internal class HtmlToDocTagConverter(
- private val docTagParserContext: DocTagParserContext
-) {
- fun convertToDocTag(html: String): List<DocTag> {
- return Jsoup.parseBodyFragment(html)
- .body()
- .childNodes()
- .flatMap { convertHtmlNode(it) }
- }
-
- private fun convertHtmlNode(node: Node, keepFormatting: Boolean = false): List<DocTag> = when (node) {
- is TextNode -> (if (keepFormatting) {
- node.wholeText.takeIf { it.isNotBlank() }?.let { listOf(Text(body = it)) }
- } else {
- node.wholeText.parseHtmlEncodedWithNormalisedSpaces(renderWhiteCharactersAsSpaces = true)
- }).orEmpty()
- is Comment -> listOf(Text(body = node.outerHtml(), params = DocTag.contentTypeParam("html")))
- is Element -> createBlock(node, keepFormatting)
- else -> emptyList()
- }
-
- private fun createBlock(element: Element, keepFormatting: Boolean = false): List<DocTag> {
- val tagName = element.tagName()
- val children = element.childNodes()
- .flatMap { convertHtmlNode(it, keepFormatting = keepFormatting || tagName == "pre" || tagName == "code") }
-
- fun ifChildrenPresent(operation: () -> DocTag): List<DocTag> {
- return if (children.isNotEmpty()) listOf(operation()) else emptyList()
- }
- return when (tagName) {
- "blockquote" -> ifChildrenPresent { BlockQuote(children) }
- "p" -> ifChildrenPresent { P(children) }
- "b" -> ifChildrenPresent { B(children) }
- "strong" -> ifChildrenPresent { Strong(children) }
- "index" -> listOf(Index(children))
- "i" -> ifChildrenPresent { I(children) }
- "img" -> listOf(
- Img(
- children,
- element.attributes().associate { (if (it.key == "src") "href" else it.key) to it.value })
- )
- "em" -> listOf(Em(children))
- "code" -> ifChildrenPresent { if(keepFormatting) CodeBlock(children) else CodeInline(children) }
- "pre" -> if(children.size == 1) {
- when(children.first()) {
- is CodeInline -> listOf(CodeBlock(children.first().children))
- is CodeBlock -> listOf(children.first())
- else -> listOf(Pre(children))
- }
- } else {
- listOf(Pre(children))
- }
- "ul" -> ifChildrenPresent { Ul(children) }
- "ol" -> ifChildrenPresent { Ol(children) }
- "li" -> listOf(Li(children))
- "dl" -> ifChildrenPresent { Dl(children) }
- "dt" -> listOf(Dt(children))
- "dd" -> listOf(Dd(children))
- "a" -> listOf(createLink(element, children))
- "table" -> ifChildrenPresent { Table(children) }
- "tr" -> ifChildrenPresent { Tr(children) }
- "td" -> listOf(Td(children))
- "thead" -> listOf(THead(children))
- "tbody" -> listOf(TBody(children))
- "tfoot" -> listOf(TFoot(children))
- "caption" -> ifChildrenPresent { Caption(children) }
- "inheritdoc" -> {
- // TODO [beresnev] describe how it works
- val id = element.attr("id")
- val section = docTagParserContext.getDocumentationNode(id)
- val parsed = section?.children?.flatMap { it.root.children }.orEmpty()
- if(parsed.size == 1 && parsed.first() is P){
- parsed.first().children
- } else {
- parsed
- }
- }
- "h1" -> ifChildrenPresent { H1(children) }
- "h2" -> ifChildrenPresent { H2(children) }
- "h3" -> ifChildrenPresent { H3(children) }
- "var" -> ifChildrenPresent { Var(children) }
- "u" -> ifChildrenPresent { U(children) }
- else -> listOf(Text(body = element.ownText()))
- }
- }
-
- private fun createLink(element: Element, children: List<DocTag>): DocTag {
- return when {
- element.hasAttr("docref") ->
- A(children, params = mapOf("docref" to element.attr("docref")))
- element.hasAttr("href") ->
- A(children, params = mapOf("href" to element.attr("href")))
- element.hasAttr("data-dri") && docTagParserContext.getDri(element.attr("data-dri")) != null -> {
- val referencedDriId = element.attr("data-dri")
- DocumentationLink(
- dri = docTagParserContext.getDri(referencedDriId)
- ?: error("docTagParserContext.getDri is null, TODO"), // TODO [beresnev] handle
- children = children
- )
- }
- else -> Text(body = children.filterIsInstance<Text>().joinToString { it.body })
- }
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagContentProvider.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagContentProvider.kt
deleted file mode 100644
index a09f85c4..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagContentProvider.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers.doctag
-
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.analysis.java.doccomment.DocumentationContent
-
-@InternalDokkaApi
-public interface InheritDocTagContentProvider {
- public fun canConvert(content: DocumentationContent): Boolean
- public fun convertToHtml(content: DocumentationContent, docTagParserContext: DocTagParserContext): String
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagResolver.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagResolver.kt
deleted file mode 100644
index 344f69b1..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/InheritDocTagResolver.kt
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers.doctag
-
-import com.intellij.psi.PsiClass
-import com.intellij.psi.PsiMethod
-import com.intellij.psi.javadoc.PsiDocComment
-import org.jetbrains.dokka.analysis.java.*
-import org.jetbrains.dokka.analysis.java.doccomment.*
-import org.jetbrains.dokka.analysis.java.doccomment.JavaDocComment
-import org.jetbrains.dokka.analysis.java.parsers.CommentResolutionContext
-
-internal class InheritDocTagResolver(
- private val docCommentFactory: DocCommentFactory,
- private val docCommentFinder: DocCommentFinder,
- private val contentProviders: List<InheritDocTagContentProvider>
-) {
- internal fun convertToHtml(content: DocumentationContent, docTagParserContext: DocTagParserContext): String? {
- return contentProviders
- .firstOrNull { it.canConvert(content) }
- ?.convertToHtml(content, docTagParserContext)
- }
-
- internal fun resolveContent(context: CommentResolutionContext): List<DocumentationContent>? {
- val javadocTag = context.tag ?: return null
-
- return when (javadocTag) {
- is ThrowingExceptionJavadocTag -> {
- javadocTag.exceptionQualifiedName?.let { _ ->
- resolveThrowsTag(
- javadocTag,
- context.comment,
- )
- } ?: return null
- }
- is ParamJavadocTag -> resolveParamTag(context.comment, javadocTag)
- is DeprecatedJavadocTag -> resolveGenericTag(context.comment, DescriptionJavadocTag)
- is SeeJavadocTag -> emptyList()
- else -> resolveGenericTag(context.comment, javadocTag)
- }
- }
-
- private fun resolveGenericTag(currentElement: PsiDocComment, tag: JavadocTag): List<DocumentationContent> {
- val docComment = when (val owner = currentElement.owner) {
- is PsiClass -> lowestClassWithTag(owner, tag)
- is PsiMethod -> lowestMethodWithTag(owner, tag)
- else -> null
- }
- return docComment?.resolveTag(tag)?.flatMap {
- it.resolveSiblings()
- }.orEmpty()
- }
-
- /**
- * Main resolution point for exception like tags
- *
- * This should be used only with [ThrowsJavadocTag] or [ExceptionJavadocTag] as their resolution path should be the same
- */
- private fun resolveThrowsTag(
- tag: ThrowingExceptionJavadocTag,
- currentElement: PsiDocComment,
- ): List<DocumentationContent> {
- val closestDocsWithThrows =
- (currentElement.owner as? PsiMethod)?.let { method -> lowestMethodsWithTag(method, tag) }
- .orEmpty().firstOrNull {
- docCommentFinder.findClosestToElement(it)?.hasTag(tag) == true
- } ?: return emptyList()
-
- return docCommentFactory.fromElement(closestDocsWithThrows)
- ?.resolveTag(tag)
- ?: emptyList()
- }
-
- private fun resolveParamTag(
- currentElement: PsiDocComment,
- paramTag: ParamJavadocTag,
- ): List<DocumentationContent> {
- val parameterIndex = paramTag.paramIndex
-
- val methods = (currentElement.owner as? PsiMethod)
- ?.let { method -> lowestMethodsWithTag(method, paramTag) }
- .orEmpty()
-
- return methods.flatMap {
- if (parameterIndex >= it.parameterList.parametersCount || parameterIndex < 0) {
- return@flatMap emptyList()
- }
-
- val closestTag = docCommentFinder.findClosestToElement(it)
- val hasTag = closestTag?.hasTag(paramTag) ?: false
- closestTag?.takeIf { hasTag }?.resolveTag(ParamJavadocTag(it, "", parameterIndex)) ?: emptyList()
- }
- }
-
- //if we are in psi class javadoc only inherits docs from classes and not from interfaces
- private fun lowestClassWithTag(baseClass: PsiClass, javadocTag: JavadocTag): DocComment? =
- baseClass.superClass?.let {
- docCommentFinder.findClosestToElement(it)?.takeIf { tag -> tag.hasTag(javadocTag) } ?: lowestClassWithTag(
- it,
- javadocTag
- )
- }
-
- private fun lowestMethodWithTag(
- baseMethod: PsiMethod,
- javadocTag: JavadocTag,
- ): DocComment? {
- val methodsWithTag = lowestMethodsWithTag(baseMethod, javadocTag).firstOrNull()
- return methodsWithTag?.let {
- it.docComment?.let { JavaDocComment(it) } ?: docCommentFinder.findClosestToElement(it)
- }
- }
-
- private fun lowestMethodsWithTag(baseMethod: PsiMethod, javadocTag: JavadocTag): List<PsiMethod> =
- baseMethod.findSuperMethods().filter { docCommentFinder.findClosestToElement(it)?.hasTag(javadocTag) == true }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiDocTagParser.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiDocTagParser.kt
deleted file mode 100644
index 18c506f6..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiDocTagParser.kt
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers.doctag
-
-import com.intellij.psi.PsiElement
-import com.intellij.psi.javadoc.PsiDocTag
-import org.jetbrains.dokka.analysis.java.parsers.CommentResolutionContext
-import org.jetbrains.dokka.model.doc.*
-
-/**
- * Parses [PsiElement] of [PsiDocTag] into Dokka's [DocTag]
- */
-internal class PsiDocTagParser(
- private val inheritDocTagResolver: InheritDocTagResolver
-) {
- fun parse(
- psiElements: Iterable<PsiElement>,
- commentResolutionContext: CommentResolutionContext
- ): List<DocTag> = parse(asParagraph = false, psiElements, commentResolutionContext)
-
- fun parseAsParagraph(
- psiElements: Iterable<PsiElement>,
- commentResolutionContext: CommentResolutionContext
- ): List<DocTag> = parse(asParagraph = true, psiElements, commentResolutionContext)
-
- private fun parse(
- asParagraph: Boolean,
- psiElements: Iterable<PsiElement>,
- commentResolutionContext: CommentResolutionContext
- ): List<DocTag> {
- val docTagParserContext = DocTagParserContext()
-
- val psiToHtmlConverter = PsiElementToHtmlConverter(inheritDocTagResolver)
- val elementsHtml = psiToHtmlConverter.convert(psiElements, docTagParserContext, commentResolutionContext)
- ?: return emptyList()
-
- val htmlToDocTagConverter = HtmlToDocTagConverter(docTagParserContext)
- val html = if (asParagraph) "<p>$elementsHtml</p>" else elementsHtml
- return htmlToDocTagConverter.convertToDocTag(html)
- }
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiElementToHtmlConverter.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiElementToHtmlConverter.kt
deleted file mode 100644
index 07aaacb9..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/parsers/doctag/PsiElementToHtmlConverter.kt
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.parsers.doctag
-
-import com.intellij.lexer.JavaDocTokenTypes
-import com.intellij.psi.*
-import com.intellij.psi.impl.source.javadoc.PsiDocParamRef
-import com.intellij.psi.impl.source.tree.LeafPsiElement
-import com.intellij.psi.javadoc.PsiDocTagValue
-import com.intellij.psi.javadoc.PsiDocToken
-import com.intellij.psi.javadoc.PsiInlineDocTag
-import org.jetbrains.dokka.analysis.java.doccomment.DocumentationContent
-import org.jetbrains.dokka.analysis.java.JavadocTag
-import org.jetbrains.dokka.analysis.java.doccomment.PsiDocumentationContent
-import org.jetbrains.dokka.analysis.java.parsers.CommentResolutionContext
-import org.jetbrains.dokka.analysis.java.util.*
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.utilities.htmlEscape
-
-private const val UNRESOLVED_PSI_ELEMENT = "UNRESOLVED_PSI_ELEMENT"
-
-private data class HtmlParserState(
- val currentJavadocTag: JavadocTag?,
- val previousElement: PsiElement? = null,
- val openPreTags: Int = 0,
- val closedPreTags: Int = 0
-)
-
-private data class HtmlParsingResult(val newState: HtmlParserState, val parsedLine: String? = null) {
- constructor(tag: JavadocTag?) : this(HtmlParserState(tag))
-
- operator fun plus(other: HtmlParsingResult): HtmlParsingResult {
- return HtmlParsingResult(
- newState = other.newState,
- parsedLine = listOfNotNull(parsedLine, other.parsedLine).joinToString(separator = "")
- )
- }
-}
-
-internal class PsiElementToHtmlConverter(
- private val inheritDocTagResolver: InheritDocTagResolver
-) {
- private val preOpeningTagRegex = "<pre(\\s+.*)?>".toRegex()
- private val preClosingTagRegex = "</pre>".toRegex()
-
- fun convert(
- psiElements: Iterable<PsiElement>,
- docTagParserContext: DocTagParserContext,
- commentResolutionContext: CommentResolutionContext
- ): String? {
- return WithContext(docTagParserContext, commentResolutionContext)
- .convert(psiElements)
- }
-
- private inner class WithContext(
- private val docTagParserContext: DocTagParserContext,
- private val commentResolutionContext: CommentResolutionContext
- ) {
- fun convert(psiElements: Iterable<PsiElement>): String? {
- val parsingResult =
- psiElements.fold(HtmlParsingResult(commentResolutionContext.tag)) { resultAccumulator, psiElement ->
- resultAccumulator + parseHtml(psiElement, resultAccumulator.newState)
- }
- return parsingResult.parsedLine?.trim()
- }
-
- private fun parseHtml(psiElement: PsiElement, state: HtmlParserState): HtmlParsingResult =
- when (psiElement) {
- is PsiReference -> psiElement.children.fold(HtmlParsingResult(state)) { acc, e ->
- acc + parseHtml(e, acc.newState)
- }
- else -> parseHtmlOfSimpleElement(psiElement, state)
- }
-
- private fun parseHtmlOfSimpleElement(psiElement: PsiElement, state: HtmlParserState): HtmlParsingResult {
- val text = psiElement.text
-
- val openPre = state.openPreTags + preOpeningTagRegex.findAll(text).count()
- val closedPre = state.closedPreTags + preClosingTagRegex.findAll(text).count()
- val isInsidePre = openPre > closedPre
-
- val parsed = when (psiElement) {
- is PsiInlineDocTag -> psiElement.toHtml(state.currentJavadocTag)
- is PsiDocParamRef -> psiElement.toDocumentationLinkString()
- is PsiDocTagValue, is LeafPsiElement -> {
- psiElement.stringifyElementAsText(isInsidePre, state.previousElement)
- }
- else -> null
- }
- val previousElement = if (text.trim() == "") state.previousElement else psiElement
- return HtmlParsingResult(
- state.copy(
- previousElement = previousElement,
- closedPreTags = closedPre,
- openPreTags = openPre
- ), parsed
- )
- }
-
- /**
- * Inline tags can be met in the middle of some text. Example of an inline tag usage:
- *
- * ```java
- * Use the {@link #getComponentAt(int, int) getComponentAt} method.
- * ```
- */
- private fun PsiInlineDocTag.toHtml(javadocTag: JavadocTag?): String? =
- when (this.name) {
- "link", "linkplain" -> this.referenceElement()
- ?.toDocumentationLinkString(this.dataElements.filterIsInstance<PsiDocToken>().joinToString(" ") {
- it.stringifyElementAsText(keepFormatting = false).orEmpty()
- })
-
- "code" -> "<code data-inline>${dataElementsAsText(this)}</code>"
- "literal" -> "<literal>${dataElementsAsText(this)}</literal>"
- "index" -> "<index>${this.children.filterIsInstance<PsiDocTagValue>().joinToString { it.text }}</index>"
- "inheritDoc" -> {
- val inheritDocContent = inheritDocTagResolver.resolveContent(commentResolutionContext)
- val html = inheritDocContent?.fold(HtmlParsingResult(javadocTag)) { result, content ->
- result + content.toInheritDocHtml(result.newState, docTagParserContext)
- }?.parsedLine.orEmpty()
- html
- }
-
- else -> this.text
- }
-
- private fun DocumentationContent.toInheritDocHtml(
- parserState: HtmlParserState,
- docTagParserContext: DocTagParserContext
- ): HtmlParsingResult {
- // TODO [beresnev] comment
- return if (this is PsiDocumentationContent) {
- parseHtml(this.psiElement, parserState)
- } else {
- HtmlParsingResult(parserState, inheritDocTagResolver.convertToHtml(this, docTagParserContext))
- }
- }
-
- private fun dataElementsAsText(tag: PsiInlineDocTag): String {
- return tag.dataElements.joinToString("") {
- it.stringifyElementAsText(keepFormatting = true).orEmpty()
- }.htmlEscape()
- }
-
- private fun PsiElement.toDocumentationLinkString(label: String = ""): String {
- val driId = reference?.resolve()?.takeIf { it !is PsiParameter }?.let {
- val dri = DRI.from(it)
- val id = docTagParserContext.store(dri)
- id
- } ?: UNRESOLVED_PSI_ELEMENT // TODO [beresnev] log this somewhere maybe?
-
- // TODO [beresnev] data-dri into a constant
- return """<a data-dri="${driId.htmlEscape()}">${label.ifBlank { defaultLabel().text }}</a>"""
- }
- }
-}
-
-private fun PsiElement.stringifyElementAsText(keepFormatting: Boolean, previousElement: PsiElement? = null) =
- if (keepFormatting) {
- /*
- For values in the <pre> tag we try to keep formatting, so only the leading space is trimmed,
- since it is there because it separates this line from the leading asterisk
- */
- text.let {
- if (((prevSibling as? PsiDocToken)?.isLeadingAsterisk() == true || (prevSibling as? PsiDocToken)?.isTagName() == true) && it.firstOrNull() == ' ')
- it.drop(1) else it
- }.let {
- if ((nextSibling as? PsiDocToken)?.isLeadingAsterisk() == true) it.dropLastWhile { it == ' ' } else it
- }
- } else {
- /*
- Outside of the <pre> we would like to trim everything from the start and end of a line since
- javadoc doesn't care about it.
- */
- text.let {
- if ((prevSibling as? PsiDocToken)?.isLeadingAsterisk() == true && text.isNotBlank() && previousElement !is PsiInlineDocTag) it?.trimStart() else it
- }?.let {
- if ((nextSibling as? PsiDocToken)?.isLeadingAsterisk() == true && text.isNotBlank()) it.trimEnd() else it
- }?.let {
- if (shouldHaveSpaceAtTheEnd()) "$it " else it
- }
- }
-
-private fun PsiDocToken.isLeadingAsterisk() = tokenType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS
-
-private fun PsiDocToken.isTagName() = tokenType == JavaDocTokenType.DOC_TAG_NAME
-
-/**
- * We would like to know if we need to have a space after a this tag
- *
- * The space is required when:
- * - tag spans multiple lines, between every line we would need a space
- *
- * We wouldn't like to render a space if:
- * - tag is followed by an end of comment
- * - after a tag there is another tag (eg. multiple @author tags)
- * - they end with an html tag like: <a href="...">Something</a> since then the space will be displayed in the following text
- * - next line starts with a <p> or <pre> token
- */
-private fun PsiElement.shouldHaveSpaceAtTheEnd(): Boolean {
- val siblings = siblings(withItself = false).toList().filterNot { it.text.trim() == "" }
- val nextNotEmptySibling = (siblings.firstOrNull() as? PsiDocToken)
- val furtherNotEmptySibling =
- (siblings.drop(1).firstOrNull { it is PsiDocToken && !it.isLeadingAsterisk() } as? PsiDocToken)
- val lastHtmlTag = text.trim().substringAfterLast("<")
- val endsWithAnUnclosedTag = lastHtmlTag.endsWith(">") && !lastHtmlTag.startsWith("</")
-
- return (nextSibling as? PsiWhiteSpace)?.text?.startsWith("\n ") == true &&
- (getNextSiblingIgnoringWhitespace() as? PsiDocToken)?.tokenType != JavaDocTokenTypes.INSTANCE.commentEnd() &&
- nextNotEmptySibling?.isLeadingAsterisk() == true &&
- furtherNotEmptySibling?.tokenType == JavaDocTokenTypes.INSTANCE.commentData() &&
- !endsWithAnUnclosedTag
-}
-
-
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/CoreCopyPaste.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/CoreCopyPaste.kt
deleted file mode 100644
index e875fb82..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/CoreCopyPaste.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import org.jetbrains.dokka.links.DRI
-import org.jetbrains.dokka.model.AncestryNode
-import org.jetbrains.dokka.model.TypeConstructor
-
-// TODO [beresnev] copy-pasted
-internal fun AncestryNode.typeConstructorsBeingExceptions(): List<TypeConstructor> {
- fun traverseSupertypes(ancestry: AncestryNode): List<TypeConstructor> =
- listOf(ancestry.typeConstructor) + (ancestry.superclass?.let(::traverseSupertypes) ?: emptyList())
-
- return superclass?.let(::traverseSupertypes)?.filter { type -> type.dri.isDirectlyAnException() } ?: emptyList()
-}
-
-// TODO [beresnev] copy-pasted
-internal fun DRI.isDirectlyAnException(): Boolean =
- toString().let { stringed ->
- stringed == "kotlin/Exception///PointingToDeclaration/" ||
- stringed == "java.lang/Exception///PointingToDeclaration/"
- }
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/NoopIntellijLogger.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/NoopIntellijLogger.kt
deleted file mode 100644
index e5cb6ef0..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/NoopIntellijLogger.kt
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import com.intellij.openapi.diagnostic.Attachment
-import com.intellij.openapi.diagnostic.DefaultLogger
-import com.intellij.openapi.diagnostic.Logger
-
-internal class NoopIntellijLoggerFactory : Logger.Factory {
- override fun getLoggerInstance(p0: String): Logger = NoopIntellijLogger
-}
-
-/**
- * Ignores all messages passed to it
- */
-internal object NoopIntellijLogger : DefaultLogger(null) {
- override fun isDebugEnabled(): Boolean = false
- override fun isTraceEnabled(): Boolean = false
-
- override fun debug(message: String?) {}
- override fun debug(t: Throwable?) {}
- override fun debug(message: String?, t: Throwable?) {}
- override fun debug(message: String, vararg details: Any?) {}
- override fun debugValues(header: String, values: MutableCollection<*>) {}
-
- override fun trace(message: String?) {}
- override fun trace(t: Throwable?) {}
-
- override fun info(message: String?) {}
- override fun info(message: String?, t: Throwable?) {}
- override fun info(t: Throwable) {}
-
- override fun warn(message: String?, t: Throwable?) {}
- override fun warn(message: String?) {}
- override fun warn(t: Throwable) {}
-
- override fun error(message: String?, t: Throwable?, vararg details: String?) {}
- override fun error(message: String?) {}
- override fun error(message: Any?) {}
- override fun error(message: String?, vararg attachments: Attachment?) {}
- override fun error(message: String?, t: Throwable?, vararg attachments: Attachment?) {}
- override fun error(message: String?, vararg details: String?) {}
- override fun error(message: String?, t: Throwable?) {}
- override fun error(t: Throwable) {}
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PropertiesConventionUtil.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PropertiesConventionUtil.kt
deleted file mode 100644
index de24552e..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PropertiesConventionUtil.kt
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-// TODO [beresnev] copy-paste
-
-internal fun propertyNamesBySetMethodName(methodName: String): List<String> =
- listOfNotNull(propertyNameBySetMethodName(methodName, false), propertyNameBySetMethodName(methodName, true))
-
-internal fun propertyNameByGetMethodName(methodName: String): String? =
- propertyNameFromAccessorMethodName(methodName, "get") ?: propertyNameFromAccessorMethodName(methodName, "is", removePrefix = false)
-
-private fun propertyNameBySetMethodName(methodName: String, withIsPrefix: Boolean): String? =
- propertyNameFromAccessorMethodName(methodName, "set", addPrefix = if (withIsPrefix) "is" else null)
-
-private fun propertyNameFromAccessorMethodName(
- methodName: String,
- prefix: String,
- removePrefix: Boolean = true,
- addPrefix: String? = null
-): String? {
- val isSpecial = methodName.startsWith("<") // see special in org.jetbrains.kotlin.Name
- if (isSpecial) return null
- if (!methodName.startsWith(prefix)) return null
- if (methodName.length == prefix.length) return null
- if (methodName[prefix.length] in 'a'..'z') return null
-
- if (addPrefix != null) {
- assert(removePrefix)
- return addPrefix + methodName.removePrefix(prefix)
- }
-
- if (!removePrefix) return methodName
- val name = methodName.removePrefix(prefix).decapitalizeSmartForCompiler(asciiOnly = true)
- if (!isValidIdentifier(name)) return null
- return name
-}
-
-/**
- * "FooBar" -> "fooBar"
- * "FOOBar" -> "fooBar"
- * "FOO" -> "foo"
- * "FOO_BAR" -> "foO_BAR"
- */
-private fun String.decapitalizeSmartForCompiler(asciiOnly: Boolean = false): String {
- if (isEmpty() || !isUpperCaseCharAt(0, asciiOnly)) return this
-
- if (length == 1 || !isUpperCaseCharAt(1, asciiOnly)) {
- return if (asciiOnly) decapitalizeAsciiOnly() else replaceFirstChar(Char::lowercaseChar)
- }
-
- val secondWordStart = (indices.firstOrNull { !isUpperCaseCharAt(it, asciiOnly) } ?: return toLowerCase(this, asciiOnly)) - 1
-
- return toLowerCase(substring(0, secondWordStart), asciiOnly) + substring(secondWordStart)
-}
-
-private fun String.isUpperCaseCharAt(index: Int, asciiOnly: Boolean): Boolean {
- val c = this[index]
- return if (asciiOnly) c in 'A'..'Z' else c.isUpperCase()
-}
-
-private fun toLowerCase(string: String, asciiOnly: Boolean): String {
- return if (asciiOnly) string.toLowerCaseAsciiOnly() else string.lowercase()
-}
-
-private fun toUpperCase(string: String, asciiOnly: Boolean): String {
- return if (asciiOnly) string.toUpperCaseAsciiOnly() else string.uppercase()
-}
-
-private fun String.decapitalizeAsciiOnly(): String {
- if (isEmpty()) return this
- val c = this[0]
- return if (c in 'A'..'Z')
- c.lowercaseChar() + substring(1)
- else
- this
-}
-
-private fun String.toLowerCaseAsciiOnly(): String {
- val builder = StringBuilder(length)
- for (c in this) {
- builder.append(if (c in 'A'..'Z') c.lowercaseChar() else c)
- }
- return builder.toString()
-}
-
-private fun String.toUpperCaseAsciiOnly(): String {
- val builder = StringBuilder(length)
- for (c in this) {
- builder.append(if (c in 'a'..'z') c.uppercaseChar() else c)
- }
- return builder.toString()
-}
-
-private fun isValidIdentifier(name: String): Boolean {
- if (name.isEmpty() || name.startsWith("<")) return false
- for (element in name) {
- if (element == '.' || element == '/' || element == '\\') {
- return false
- }
- }
- return true
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiAccessorConventionUtil.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiAccessorConventionUtil.kt
deleted file mode 100644
index 190fc5bd..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiAccessorConventionUtil.kt
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import com.intellij.psi.PsiField
-import com.intellij.psi.PsiMethod
-import org.jetbrains.dokka.analysis.java.getVisibility
-import org.jetbrains.dokka.model.JavaVisibility
-import org.jetbrains.dokka.model.KotlinVisibility
-import org.jetbrains.dokka.model.Visibility
-
-
-internal data class PsiFunctionsHolder(
- val regularFunctions: List<PsiMethod>,
- val accessors: Map<PsiField, List<PsiMethod>>
-)
-
-internal fun splitFunctionsAndAccessors(fields: Array<PsiField>, methods: Array<PsiMethod>): PsiFunctionsHolder {
- val fieldsByName = fields.associateBy { it.name }
- val regularFunctions = mutableListOf<PsiMethod>()
- val accessors = mutableMapOf<PsiField, MutableList<PsiMethod>>()
- methods.forEach { method ->
- val possiblePropertyNamesForFunction = method.getPossiblePropertyNamesForFunction()
- val field = possiblePropertyNamesForFunction.firstNotNullOfOrNull { fieldsByName[it] }
- if (field != null && method.isAccessorFor(field)) {
- accessors.getOrPut(field, ::mutableListOf).add(method)
- } else {
- regularFunctions.add(method)
- }
- }
-
- val accessorLookalikes = removeNonAccessorsReturning(accessors)
- regularFunctions.addAll(accessorLookalikes)
-
- return PsiFunctionsHolder(regularFunctions, accessors)
-}
-
-private fun PsiMethod.getPossiblePropertyNamesForFunction(): List<String> {
- val jvmName = getAnnotation("kotlin.jvm.JvmName")?.findAttributeValue("name")?.text
- if (jvmName != null) return listOf(jvmName)
-
- return when {
- isGetterName(name) -> listOfNotNull(
- propertyNameByGetMethodName(name)
- )
- isSetterName(name) -> {
- propertyNamesBySetMethodName(name)
- }
- else -> listOf()
- }
-}
-
-private fun isGetterName(name: String): Boolean {
- return name.startsWith("get") || name.startsWith("is")
-}
-
-private fun isSetterName(name: String): Boolean {
- return name.startsWith("set")
-}
-
-/**
- * If a field has no getter, it's not accessible as a property from Kotlin's perspective,
- * but it still might have a setter. In this case, this "setter" should be just a regular function
- */
-private fun removeNonAccessorsReturning(
- fieldAccessors: MutableMap<PsiField, MutableList<PsiMethod>>
-): List<PsiMethod> {
- val nonAccessors = mutableListOf<PsiMethod>()
- fieldAccessors.entries.removeIf { (field, methods) ->
- if (methods.size == 1 && methods[0].isSetterFor(field)) {
- nonAccessors.add(methods[0])
- true
- } else {
- false
- }
- }
- return nonAccessors
-}
-
-internal fun PsiMethod.isAccessorFor(field: PsiField): Boolean {
- return (this.isGetterFor(field) || this.isSetterFor(field))
- && !field.getVisibility().isPublicAPI()
- && this.getVisibility().isPublicAPI()
-}
-
-internal fun PsiMethod.isGetterFor(field: PsiField): Boolean {
- return this.returnType == field.type && !this.hasParameters()
-}
-
-internal fun PsiMethod.isSetterFor(field: PsiField): Boolean {
- return parameterList.getParameter(0)?.type == field.type && parameterList.getParametersCount() == 1
-}
-
-private fun Visibility.isPublicAPI() = when(this) {
- KotlinVisibility.Public,
- KotlinVisibility.Protected,
- JavaVisibility.Public,
- JavaVisibility.Protected -> true
- else -> false
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiCommentsUtils.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiCommentsUtils.kt
deleted file mode 100644
index 573f479e..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiCommentsUtils.kt
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import com.intellij.psi.JavaDocTokenType
-import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiJavaCodeReferenceElement
-import com.intellij.psi.PsiWhiteSpace
-import com.intellij.psi.impl.source.tree.JavaDocElementType
-import com.intellij.psi.javadoc.PsiDocComment
-import com.intellij.psi.javadoc.PsiDocTag
-import com.intellij.psi.javadoc.PsiDocToken
-import com.intellij.psi.util.PsiTreeUtil
-import org.jetbrains.dokka.analysis.java.DescriptionJavadocTag
-import org.jetbrains.dokka.analysis.java.JavadocTag
-
-internal fun PsiDocComment.hasTag(tag: JavadocTag): Boolean =
- when (tag) {
- DescriptionJavadocTag -> descriptionElements.isNotEmpty()
- else -> findTagByName(tag.name) != null
- }
-
-internal fun PsiDocTag.contentElementsWithSiblingIfNeeded(): List<PsiElement> = if (dataElements.isNotEmpty()) {
- listOfNotNull(
- dataElements[0],
- dataElements[0].nextSibling?.takeIf { it.text != dataElements.drop(1).firstOrNull()?.text },
- *dataElements.drop(1).toTypedArray()
- )
-} else {
- emptyList()
-}
-
-internal fun PsiDocTag.resolveToElement(): PsiElement? =
- dataElements.firstOrNull()?.firstChild?.referenceElementOrSelf()?.resolveToGetDri()
-
-internal fun PsiDocTag.referenceElement(): PsiElement? =
- linkElement()?.referenceElementOrSelf()
-
-internal fun PsiElement.referenceElementOrSelf(): PsiElement? =
- if (node.elementType == JavaDocElementType.DOC_REFERENCE_HOLDER) {
- PsiTreeUtil.findChildOfType(this, PsiJavaCodeReferenceElement::class.java)
- } else this
-
-internal fun PsiDocTag.linkElement(): PsiElement? =
- valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace }
-
-internal fun PsiElement.defaultLabel() = children.firstOrNull {
- it is PsiDocToken && it.text.isNotBlank() && !it.isSharpToken()
-} ?: this
-
-internal fun PsiDocToken.isSharpToken() = tokenType == JavaDocTokenType.DOC_TAG_VALUE_SHARP_TOKEN
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt
deleted file mode 100644
index 162f940e..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/PsiUtil.kt
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import com.intellij.psi.*
-import com.intellij.psi.util.PsiTreeUtil
-import org.jetbrains.dokka.InternalDokkaApi
-import org.jetbrains.dokka.links.*
-import org.jetbrains.dokka.model.DocumentableSource
-import org.jetbrains.dokka.utilities.firstIsInstanceOrNull
-
-// TODO [beresnev] copy-paste
-
-internal val PsiElement.parentsWithSelf: Sequence<PsiElement>
- get() = generateSequence(this) { if (it is PsiFile) null else it.parent }
-
-@InternalDokkaApi
-public fun DRI.Companion.from(psi: PsiElement): DRI = psi.parentsWithSelf.run {
- val psiMethod = firstIsInstanceOrNull<PsiMethod>()
- val psiField = firstIsInstanceOrNull<PsiField>()
- val classes = filterIsInstance<PsiClass>().filterNot { it is PsiTypeParameter }
- .toList() // We only want exact PsiClass types, not PsiTypeParameter subtype
- val additionalClasses = if (psi is PsiEnumConstant) listOfNotNull(psiField?.name) else emptyList()
- DRI(
- packageName = classes.lastOrNull()?.qualifiedName?.substringBeforeLast('.', "") ?: "",
- classNames = (additionalClasses + classes.mapNotNull { it.name }).takeIf { it.isNotEmpty() }
- ?.asReversed()?.joinToString("."),
- // The fallback strategy test whether psi is not `PsiEnumConstant`. The reason behind this is that
- // we need unified DRI for both Java and Kotlin enums, so we can link them properly and treat them alike.
- // To achieve that, we append enum name to classNames list and leave the callable part set to null. For Kotlin enums
- // it is by default, while for Java enums we have to explicitly test for that in this `takeUnless` condition.
- callable = psiMethod?.let { Callable.from(it) } ?: psiField?.takeUnless { psi is PsiEnumConstant }?.let { Callable.from(it) },
- target = DriTarget.from(psi),
- extra = if (psi is PsiEnumConstant)
- DRIExtraContainer().also { it[EnumEntryDRIExtra] = EnumEntryDRIExtra }.encode()
- else null
- )
-}
-
-internal fun Callable.Companion.from(psi: PsiMethod) = with(psi) {
- Callable(
- name,
- null,
- parameterList.parameters.map { param -> JavaClassReference(param.type.canonicalText) })
-}
-
-internal fun Callable.Companion.from(psi: PsiField): Callable {
- return Callable(
- name = psi.name,
- receiver = null,
- params = emptyList()
- )
-}
-
-internal fun DriTarget.Companion.from(psi: PsiElement): DriTarget = psi.parentsWithSelf.run {
- return when (psi) {
- is PsiTypeParameter -> PointingToGenericParameters(psi.index)
- else -> firstIsInstanceOrNull<PsiParameter>()?.let {
- val callable = firstIsInstanceOrNull<PsiMethod>()
- val params = (callable?.parameterList?.parameters).orEmpty()
- PointingToCallableParameters(params.indexOf(it))
- } ?: PointingToDeclaration
- }
-}
-
-// TODO [beresnev] copy-paste
-internal fun PsiElement.siblings(forward: Boolean = true, withItself: Boolean = true): Sequence<PsiElement> {
- return object : Sequence<PsiElement> {
- override fun iterator(): Iterator<PsiElement> {
- var next: PsiElement? = this@siblings
- return object : Iterator<PsiElement> {
- init {
- if (!withItself) next()
- }
-
- override fun hasNext(): Boolean = next != null
- override fun next(): PsiElement {
- val result = next ?: throw NoSuchElementException()
- next = if (forward) result.nextSibling else result.prevSibling
- return result
- }
- }
- }
- }
-}
-
-// TODO [beresnev] copy-paste
-internal fun PsiElement.getNextSiblingIgnoringWhitespace(withItself: Boolean = false): PsiElement? {
- return siblings(withItself = withItself).filter { it !is PsiWhiteSpace }.firstOrNull()
-}
-
-@InternalDokkaApi
-public class PsiDocumentableSource(
- public val psi: PsiNamedElement
-) : DocumentableSource {
- override val path: String = psi.containingFile.virtualFile.path
-
- override fun computeLineNumber(): Int? {
- val range = psi.getChildOfType<PsiIdentifier>()?.textRange ?: psi.textRange
- val doc = PsiDocumentManager.getInstance(psi.project).getDocument(psi.containingFile)
- // IJ uses 0-based line-numbers; external source browsers use 1-based
- return doc?.getLineNumber(range.startOffset)?.plus(1)
- }
-}
-
-public inline fun <reified T : PsiElement> PsiElement.getChildOfType(): T? {
- return PsiTreeUtil.getChildOfType(this, T::class.java)
-}
-
-internal fun PsiElement.getKotlinFqName(): String? = this.kotlinFqNameProp
-
-//// from import org.jetbrains.kotlin.idea.base.psi.kotlinFqName
-internal val PsiElement.kotlinFqNameProp: String?
- get() = when (val element = this) {
- is PsiPackage -> element.qualifiedName
- is PsiClass -> element.qualifiedName
- is PsiMember -> element.name?.let { name ->
- val prefix = element.containingClass?.qualifiedName
- if (prefix != null) "$prefix.$name" else name
- }
-// is KtNamedDeclaration -> element.fqName TODO [beresnev] decide what to do with it
- is PsiQualifiedNamedElement -> element.qualifiedName
- else -> null
- }
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/StdlibUtil.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/StdlibUtil.kt
deleted file mode 100644
index 00658ce9..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/StdlibUtil.kt
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import java.util.*
-
-// TODO [beresnev] copy-paste
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal fun <T, R : Any> Iterable<T>.firstNotNullOfOrNull(transform: (T) -> R?): R? {
- for (element in this) {
- val result = transform(element)
- if (result != null) {
- return result
- }
- }
- return null
-}
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal fun Char.uppercaseChar(): Char = Character.toUpperCase(this)
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal fun Char.lowercaseChar(): Char = Character.toLowerCase(this)
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal fun String.lowercase(): String = this.toLowerCase(Locale.ROOT)
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal fun String.uppercase(): String = this.toUpperCase(Locale.ROOT)
-
-// TODO [beresnev] remove this copy-paste and use the same method from stdlib instead after updating to 1.5
-internal fun String.replaceFirstChar(transform: (Char) -> Char): String {
- return if (isNotEmpty()) transform(this[0]) + substring(1) else this
-}
diff --git a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/resolveToGetDri.kt b/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/resolveToGetDri.kt
deleted file mode 100644
index aabe57c0..00000000
--- a/subprojects/analysis-java-psi/src/main/kotlin/org/jetbrains/dokka/analysis/java/util/resolveToGetDri.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-/*
- * Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
- */
-
-package org.jetbrains.dokka.analysis.java.util
-
-import com.intellij.psi.PsiElement
-
-// TODO [beresnev] get rid of
-internal fun PsiElement.resolveToGetDri(): PsiElement? =
- reference?.resolve()
diff --git a/subprojects/analysis-java-psi/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin b/subprojects/analysis-java-psi/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
deleted file mode 100644
index 9fa991c2..00000000
--- a/subprojects/analysis-java-psi/src/main/resources/META-INF/services/org.jetbrains.dokka.plugability.DokkaPlugin
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Copyright 2014-2023 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
-#
-
-org.jetbrains.dokka.analysis.java.JavaAnalysisPlugin