-
Notifications
You must be signed in to change notification settings - Fork 392
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1aba0ec
commit a5bd1e8
Showing
14 changed files
with
985 additions
and
220 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
package org.jetbrains.dokka.utilities | ||
|
||
inline fun <reified T : Enum<*>> enumValueOrNull(name: String): T? = | ||
T::class.java.enumConstants.firstOrNull { it.name == name } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
plugins/base/src/main/kotlin/translators/psi/PsiInheritance.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package org.jetbrains.dokka.base.translators.psi | ||
|
||
import com.intellij.psi.PsiClass | ||
import com.intellij.psi.PsiMethod | ||
import org.jetbrains.dokka.utilities.DokkaLogger | ||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName | ||
import org.jetbrains.kotlin.name.FqName | ||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs | ||
|
||
internal fun PsiClass.implementsInterface(fqName: FqName): Boolean { | ||
return allInterfaces().any { it.getKotlinFqName() == fqName } | ||
} | ||
|
||
internal fun PsiClass.allInterfaces(): Sequence<PsiClass> { | ||
return sequence { | ||
this.yieldAll(interfaces.toList()) | ||
interfaces.forEach { yieldAll(it.allInterfaces()) } | ||
} | ||
} | ||
|
||
/** | ||
* Workaround for failing [PsiMethod.findSuperMethods]. | ||
* This might be resolved once ultra light classes are enabled for dokka | ||
* See [KT-39518](https://youtrack.jetbrains.com/issue/KT-39518) | ||
*/ | ||
internal fun PsiMethod.findSuperMethodsOrEmptyArray(logger: DokkaLogger): Array<PsiMethod> { | ||
return try { | ||
/* | ||
We are not even attempting to call "findSuperMethods" on all methods called "getGetter" or "getSetter" | ||
on any object implementing "kotlin.reflect.KProperty", since we know that those methods will fail | ||
(KT-39518). Just catching the exception is not good enough, since "findSuperMethods" will | ||
print the whole exception to stderr internally and then spoil the console. | ||
*/ | ||
val kPropertyFqName = FqName("kotlin.reflect.KProperty") | ||
if ( | ||
this.parent?.safeAs<PsiClass>()?.implementsInterface(kPropertyFqName) == true && | ||
(this.name == "getSetter" || this.name == "getGetter") | ||
) { | ||
logger.warn("Skipped lookup of super methods for ${getKotlinFqName()} (KT-39518)") | ||
return emptyArray() | ||
} | ||
findSuperMethods() | ||
} catch (exception: Throwable) { | ||
logger.warn("Failed to lookup of super methods for ${getKotlinFqName()} (KT-39518)") | ||
emptyArray() | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
plugins/base/src/main/kotlin/translators/psi/parsers/InheritDocResolver.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
package org.jetbrains.dokka.base.translators.psi.parsers | ||
|
||
import com.intellij.psi.PsiClass | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiMethod | ||
import com.intellij.psi.javadoc.PsiDocComment | ||
import com.intellij.psi.javadoc.PsiDocTag | ||
import org.jetbrains.dokka.utilities.DokkaLogger | ||
import org.jetbrains.kotlin.idea.refactoring.fqName.getKotlinFqName | ||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull | ||
|
||
internal data class CommentResolutionContext( | ||
val comment: PsiDocComment, | ||
val tag: JavadocTag, | ||
val name: String? = null, | ||
val parameterIndex: Int? = null, | ||
) | ||
|
||
internal class InheritDocResolver( | ||
private val logger: DokkaLogger | ||
) { | ||
internal fun resolveFromContext(context: CommentResolutionContext) = | ||
when (context.tag) { | ||
JavadocTag.THROWS -> context.name?.let { name -> resolveThrowsTag(context.comment, name) } | ||
JavadocTag.PARAM -> context.parameterIndex?.let { paramIndex -> resolveParamTag(context.comment, paramIndex) } | ||
JavadocTag.DEPRECATED -> resolveGenericTag(context.comment, JavadocTag.DESCRIPTION) | ||
JavadocTag.SEE -> emptyList() | ||
else -> resolveGenericTag(context.comment, context.tag) | ||
} | ||
|
||
private fun resolveGenericTag(currentElement: PsiDocComment, tag: JavadocTag): List<PsiElement> = | ||
when (val owner = currentElement.owner) { | ||
is PsiClass -> lowestClassWithTag(owner, tag) | ||
is PsiMethod -> lowestMethodWithTag(owner, tag) | ||
else -> null | ||
}?.tagsByName(tag)?.flatMap { | ||
when (it) { | ||
is PsiDocTag -> it.contentElementsWithSiblingIfNeeded() | ||
else -> listOf(it) | ||
} | ||
}.orEmpty() | ||
|
||
private fun resolveThrowsTag( | ||
currentElement: PsiDocComment, | ||
exceptionFqName: String | ||
): List<PsiElement> = | ||
(currentElement.owner as? PsiMethod)?.let { method -> lowestMethodsWithTag(method, JavadocTag.THROWS) } | ||
.orEmpty().firstOrNull { | ||
findClosestDocComment(it, logger)?.hasThrowsTagWithExceptionOfType(exceptionFqName) == true | ||
}?.docComment?.tagsByName(JavadocTag.THROWS)?.flatMap { | ||
when (it) { | ||
is PsiDocTag -> it.contentElementsWithSiblingIfNeeded() | ||
else -> listOf(it) | ||
} | ||
}?.drop(1).orEmpty() | ||
|
||
private fun resolveParamTag( | ||
currentElement: PsiDocComment, | ||
parameterIndex: Int, | ||
): List<PsiElement> = | ||
(currentElement.owner as? PsiMethod)?.let { method -> lowestMethodsWithTag(method, JavadocTag.PARAM) } | ||
.orEmpty().flatMap { | ||
if (parameterIndex >= it.parameterList.parametersCount || parameterIndex < 0) emptyList() | ||
else { | ||
val closestTag = findClosestDocComment(it, logger) | ||
val hasTag = closestTag?.hasTag(JavadocTag.PARAM) | ||
if (hasTag != true) emptyList() | ||
else { | ||
val parameterName = it.parameterList.parameters[parameterIndex].name | ||
closestTag.tagsByName(JavadocTag.PARAM) | ||
.filterIsInstance<PsiDocTag>().map { it.contentElementsWithSiblingIfNeeded() }.firstOrNull { | ||
it.firstOrNull()?.text == parameterName | ||
}.orEmpty() | ||
} | ||
} | ||
}.drop(1) | ||
|
||
//if we are in psi class javadoc only inherits docs from classes and not from interfaces | ||
private fun lowestClassWithTag(baseClass: PsiClass, javadocTag: JavadocTag): PsiDocComment? = | ||
baseClass.superClass?.let { | ||
val tag = findClosestDocComment(it, logger) | ||
return if (tag?.hasTag(javadocTag) == true) tag | ||
else lowestClassWithTag(it, javadocTag) | ||
} | ||
|
||
private fun lowestMethodWithTag( | ||
baseMethod: PsiMethod, | ||
javadocTag: JavadocTag, | ||
): PsiDocComment? = | ||
lowestMethodsWithTag(baseMethod, javadocTag).firstOrNull()?.docComment | ||
|
||
private fun lowestMethodsWithTag(baseMethod: PsiMethod, javadocTag: JavadocTag) = | ||
baseMethod.findSuperMethods().filter { findClosestDocComment(it, logger)?.hasTag(javadocTag) == true } | ||
|
||
private fun PsiDocComment.hasThrowsTagWithExceptionOfType(exceptionFqName: String): Boolean = | ||
hasTag(JavadocTag.THROWS) && tagsByName(JavadocTag.THROWS).firstIsInstanceOrNull<PsiDocTag>() | ||
?.resolveToElement() | ||
?.getKotlinFqName()?.asString() == exceptionFqName | ||
} |
Oops, something went wrong.