aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Mishenev <vad-mishenev@yandex.ru>2023-09-04 17:18:55 +0300
committerGitHub <noreply@github.com>2023-09-04 17:18:55 +0300
commite9e8fbf59efc5eefdaef2a432dbdef299a89fde1 (patch)
treeb5fae211d545d7274b75a4b608f9a1cfadba141d
parent8065a0d974420898fe6142fa792d6dab50f8b1d5 (diff)
downloaddokka-e9e8fbf59efc5eefdaef2a432dbdef299a89fde1.tar.gz
dokka-e9e8fbf59efc5eefdaef2a432dbdef299a89fde1.tar.bz2
dokka-e9e8fbf59efc5eefdaef2a432dbdef299a89fde1.zip
[K2] Fix functional type and improve logging for unresolved link (#3157)
* [K2] Fix functional type and improve logging for unresolved link For example `typealias CompletionHandler = (cause: Throwable?) -> Unit` has a functional type with no type arguments in K2. In K1 we have a usual generic type
-rw-r--r--plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt5
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt2
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/ResolveKDocLink.kt27
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocCommentParser.kt8
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationParsingContext.kt28
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt6
-rw-r--r--subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt15
7 files changed, 65 insertions, 26 deletions
diff --git a/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt b/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt
index 198ffe8e..5dd62545 100644
--- a/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt
+++ b/plugins/base/src/test/kotlin/translators/ExternalDocumentablesTest.kt
@@ -14,7 +14,6 @@ import org.jetbrains.dokka.plugability.querySingle
import org.jetbrains.dokka.utilities.cast
import kotlin.test.Test
import kotlin.test.assertEquals
-import utils.OnlyDescriptors
import utils.UsingJDK
class ExternalDocumentablesTest : BaseAbstractTest() {
@@ -61,10 +60,6 @@ class ExternalDocumentablesTest : BaseAbstractTest() {
}
}
-
- // typealias CompletionHandler = (cause: Throwable?) -> Unit
- // FunctionalTypeConstructor(dri=kotlinx.coroutines/CompletionHandler///PointingToDeclaration/, projections=[], isExtensionFunction=false, isSuspendable=false, presentableName=null, extra=PropertyContainer(map={}))
- @OnlyDescriptors(reason = "FunctionType has not parameters") // TODO
@Test
fun `external documentable from dependency`() {
val coroutinesPath =
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt
index 9dd6857e..d8a4e476 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/KDocProvider.kt
@@ -64,7 +64,7 @@ internal fun KtAnalysisSession.getKDocDocumentationFrom(symbol: KtSymbol, logger
parseFromKDocTag(
kDocTag = kDocContent.contentTag,
- externalDri = { link -> resolveKDocLink(link).logIfNotResolved(link.getLinkText(), logger) },
+ externalDri = { link -> resolveKDocLink(link).ifUnresolved { logger.logUnresolvedLink(link.getLinkText(), kdocLocation) } },
kdocLocation = kdocLocation
)
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/ResolveKDocLink.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/ResolveKDocLink.kt
index be06d595..9a0b81bd 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/ResolveKDocLink.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/ResolveKDocLink.kt
@@ -15,15 +15,24 @@ import org.jetbrains.kotlin.kdoc.psi.impl.KDocLink
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.psi.KtPsiFactory
-internal fun DRI?.logIfNotResolved(link: String, logger: DokkaLogger): DRI? {
- if(this == null)
- logger.warn("Couldn't resolve link for $link")
- return this
+/**
+ * Util to print a message about unresolved [link]
+ */
+internal fun DokkaLogger.logUnresolvedLink(link: String, location: String?) {
+ warn("Couldn't resolve link for $link" + if (location != null) " in $location" else "")
+}
+
+internal inline fun DRI?.ifUnresolved(action: () -> Unit): DRI? = this ?: run {
+ action()
+ null
}
/**
- * It resolves KDoc link via creating PSI.
+ * Resolves KDoc link via creating PSI.
+ * If the [link] is ambiguous, i.e. leads to more than one declaration,
+ * it returns deterministically any declaration.
*
+ * @return [DRI] or null if the [link] is unresolved
*/
internal fun KtAnalysisSession.resolveKDocTextLink(link: String, context: PsiElement? = null): DRI? {
val psiFactory = context?.let { KtPsiFactory.contextual(it) } ?: KtPsiFactory(this.useSiteModule.project)
@@ -38,9 +47,15 @@ internal fun KtAnalysisSession.resolveKDocTextLink(link: String, context: PsiEle
return kDocLink?.let { resolveKDocLink(it) }
}
+/**
+ * If the [link] is ambiguous, i.e. leads to more than one declaration,
+ * it returns deterministically any declaration.
+ *
+ * @return [DRI] or null if the [link] is unresolved
+ */
internal fun KtAnalysisSession.resolveKDocLink(link: KDocLink): DRI? {
val lastNameSegment = link.children.filterIsInstance<KDocName>().lastOrNull()
val linkedSymbol = lastNameSegment?.mainReference?.resolveToSymbols()?.firstOrNull()
- return if (linkedSymbol == null) null // logger.warn("Couldn't resolve link for $link")
+ return if (linkedSymbol == null) null
else getDRIFromSymbol(linkedSymbol)
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocCommentParser.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocCommentParser.kt
index 7e2e2a59..33cc4305 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocCommentParser.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/java/KotlinDocCommentParser.kt
@@ -8,10 +8,11 @@ import com.intellij.psi.PsiNamedElement
import org.jetbrains.dokka.Platform
import org.jetbrains.dokka.analysis.java.doccomment.DocComment
import org.jetbrains.dokka.analysis.java.parsers.DocCommentParser
-import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.logIfNotResolved
-import org.jetbrains.dokka.analysis.kotlin.symbols.plugin.SymbolsAnalysisPlugin
+import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.*
+import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.logUnresolvedLink
import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.parseFromKDocTag
import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.resolveKDocLink
+import org.jetbrains.dokka.analysis.kotlin.symbols.plugin.SymbolsAnalysisPlugin
import org.jetbrains.dokka.model.doc.DocumentationNode
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.plugability.plugin
@@ -37,10 +38,11 @@ internal class KotlinDocCommentParser(
?: sourceSets.first { it.analysisPlatform == Platform.jvm }
}
val kotlinAnalysis = context.plugin<SymbolsAnalysisPlugin>().querySingle { kotlinAnalysis }
+ val elementName = element.resolveDocContext.ktElement.name
return analyze(kotlinAnalysis[sourceSet].mainModule) {
parseFromKDocTag(
kDocTag = element.comment,
- externalDri = { link -> resolveKDocLink(link).logIfNotResolved(link.getLinkText(), context.logger) },
+ externalDri = { link -> resolveKDocLink(link).ifUnresolved { context.logger.logUnresolvedLink(link.getLinkText(), elementName) } },
kdocLocation = null,
parseWithChildren = parseWithChildren
)
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationParsingContext.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationParsingContext.kt
index 9b748da2..ef59aa33 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationParsingContext.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/kdoc/moduledocs/ModuleAndPackageDocumentationParsingContext.kt
@@ -5,7 +5,8 @@
package org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.moduledocs
import org.jetbrains.dokka.DokkaConfiguration
-import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.logIfNotResolved
+import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.ifUnresolved
+import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.logUnresolvedLink
import org.jetbrains.dokka.analysis.kotlin.symbols.plugin.KotlinAnalysis
import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.moduledocs.ModuleAndPackageDocumentation.Classifier.Module
import org.jetbrains.dokka.analysis.kotlin.symbols.kdoc.moduledocs.ModuleAndPackageDocumentation.Classifier.Package
@@ -32,20 +33,31 @@ internal fun ModuleAndPackageDocumentationParsingContext(
sourceSet: DokkaConfiguration.DokkaSourceSet? = null
) = ModuleAndPackageDocumentationParsingContext { fragment, sourceLocation ->
- if(kotlinAnalysis == null || sourceSet == null) {
+ if (kotlinAnalysis == null || sourceSet == null) {
MarkdownParser(externalDri = { null }, sourceLocation)
} else {
val analysisContext = kotlinAnalysis[sourceSet]
- analyze(analysisContext.mainModule) {
+ val contextPsi = analyze(analysisContext.mainModule) {
val contextSymbol = when (fragment.classifier) {
Module -> ROOT_PACKAGE_SYMBOL
Package -> getPackageSymbolIfPackageExists(FqName(fragment.name))
}
-
- MarkdownParser(
- externalDri = { resolveKDocTextLink(it, contextSymbol?.psi).logIfNotResolved(it, logger) },
- sourceLocation
- )
+ contextSymbol?.psi
}
+ MarkdownParser(
+ externalDri = { link ->
+ analyze(analysisContext.mainModule) {
+ resolveKDocTextLink(
+ link,
+ contextPsi
+ ).ifUnresolved {
+ logger.logUnresolvedLink(link, fragment.name.ifBlank { "module documentation" })
+ }
+
+ }
+ },
+ sourceLocation
+ )
+
}
}
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt
index db2d14b8..faae08e2 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/AnnotationTranslator.kt
@@ -111,7 +111,10 @@ internal class AnnotationTranslator {
DRI(packageName = "", classNames = ERROR_CLASS_NAME)
)
- KtUnsupportedAnnotationValue -> TODO()
+ KtUnsupportedAnnotationValue -> ClassValue(
+ "<Unsupported Annotation Value>",
+ DRI(packageName = "", classNames = ERROR_CLASS_NAME)
+ )
}
private fun getDRIFrom(enumEntry: KtEnumEntryAnnotationValue): DRI {
@@ -129,6 +132,7 @@ internal class AnnotationTranslator {
/**
* Functional types can have **generated** [ParameterName] annotation
+ * @see ParameterName
*/
internal fun KtAnnotated.getPresentableName(): String? =
this.annotationsByClassId(parameterNameAnnotation)
diff --git a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt
index 66c699f7..7127cbdf 100644
--- a/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt
+++ b/subprojects/analysis-kotlin-symbols/src/main/kotlin/org/jetbrains/dokka/analysis/kotlin/symbols/translators/TypeTranslator.kt
@@ -52,7 +52,7 @@ internal class TypeTranslator(
throw IllegalStateException("Expected type alias symbol in type")
}
- private fun KtAnalysisSession.toTypeConstructorFrom(classType: KtUsualClassType) =
+ private fun KtAnalysisSession.toTypeConstructorFrom(classType: KtNonErrorClassType) =
GenericTypeConstructor(
dri = getDRIFromNonErrorClassType(classType),
projections = classType.ownTypeArguments.map { toProjection(it) },
@@ -91,7 +91,18 @@ internal class TypeTranslator(
)
is KtClassErrorType -> UnresolvedBound(type.toString())
- is KtFunctionalType -> toFunctionalTypeConstructorFrom(type)
+ is KtFunctionalType -> {
+ /**
+ * For example
+ * `typealias CompletionHandler = (cause: Throwable?) -> Unit`
+ * has functional type with no type arguments in K2
+ * In K1 we have a usual generic type
+ */
+ if (type.ownTypeArguments.isEmpty())
+ toTypeConstructorFrom(type)
+ else
+ toFunctionalTypeConstructorFrom(type)
+ }
is KtDynamicType -> Dynamic
is KtDefinitelyNotNullType -> DefinitelyNonNullable(
toBoundFrom(type.original)