diff options
author | Ignat Beresnev <ignat.beresnev@jetbrains.com> | 2022-06-17 15:16:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-17 15:16:03 +0200 |
commit | 9f67dcf75d3b86fa6e4e352d2cebc4f9e17b8048 (patch) | |
tree | 5b30ddf007113d5b3da04390e093dc8023c04c79 /plugins/base/src/main/kotlin/translators/psi | |
parent | b783439932372e823c36776c53cda5bdc8d0ccae (diff) | |
download | dokka-9f67dcf75d3b86fa6e4e352d2cebc4f9e17b8048.tar.gz dokka-9f67dcf75d3b86fa6e4e352d2cebc4f9e17b8048.tar.bz2 dokka-9f67dcf75d3b86fa6e4e352d2cebc4f9e17b8048.zip |
Handle more corner cases for inherited accessors (#2532)
Diffstat (limited to 'plugins/base/src/main/kotlin/translators/psi')
-rw-r--r-- | plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt | 33 | ||||
-rw-r--r-- | plugins/base/src/main/kotlin/translators/psi/PsiAccessorConventionUtil.kt | 38 |
2 files changed, 53 insertions, 18 deletions
diff --git a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt index c20073a4..bef86144 100644 --- a/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt +++ b/plugins/base/src/main/kotlin/translators/psi/DefaultPsiToDocumentableTranslator.kt @@ -17,9 +17,9 @@ import org.jetbrains.dokka.analysis.KotlinAnalysis import org.jetbrains.dokka.analysis.PsiDocumentableSource import org.jetbrains.dokka.analysis.from import org.jetbrains.dokka.base.DokkaBase -import org.jetbrains.dokka.base.translators.typeConstructorsBeingExceptions import org.jetbrains.dokka.base.translators.psi.parsers.JavaDocumentationParser import org.jetbrains.dokka.base.translators.psi.parsers.JavadocParser +import org.jetbrains.dokka.base.translators.typeConstructorsBeingExceptions import org.jetbrains.dokka.base.translators.unquotedValue import org.jetbrains.dokka.links.* import org.jetbrains.dokka.model.* @@ -40,12 +40,7 @@ import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.idea.base.utils.fqname.getKotlinFqName -import org.jetbrains.kotlin.load.java.JvmAbi -import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName -import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName -import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.psiUtil.getChildOfType -import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.io.File @@ -108,16 +103,6 @@ class DefaultPsiToDocumentableTranslator( private val cachedBounds = hashMapOf<String, Bound>() - private 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 - private val PsiMethod.hash: Int get() = "$returnType $name$parameterList".hashCode() @@ -641,7 +626,7 @@ class DefaultPsiToDocumentableTranslator( documentation = javadocParser.parseDocumentation(psi).toSourceSetDependent(), expectPresentInSet = null, sources = PsiDocumentableSource(psi).toSourceSetDependent(), - visibility = psi.getVisibility().toSourceSetDependent(), + visibility = psi.getVisibility(getter).toSourceSetDependent(), type = getBound(psi.type), receiver = null, setter = setter, @@ -666,6 +651,10 @@ class DefaultPsiToDocumentableTranslator( ) } + private fun PsiField.getVisibility(getter: DFunction?): Visibility { + return getter?.visibility?.get(sourceSetData) ?: this.getVisibility() + } + private fun Collection<PsiAnnotation>.toListOfAnnotations() = filter { it !is KtLightAbstractAnnotation }.mapNotNull { it.toAnnotation() } @@ -740,3 +729,13 @@ class DefaultPsiToDocumentableTranslator( get() = getChildOfType<PsiJavaCodeReferenceElement>()?.resolve() } } + +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/plugins/base/src/main/kotlin/translators/psi/PsiAccessorConventionUtil.kt b/plugins/base/src/main/kotlin/translators/psi/PsiAccessorConventionUtil.kt index c2ab8c03..2ab70843 100644 --- a/plugins/base/src/main/kotlin/translators/psi/PsiAccessorConventionUtil.kt +++ b/plugins/base/src/main/kotlin/translators/psi/PsiAccessorConventionUtil.kt @@ -3,6 +3,9 @@ package org.jetbrains.dokka.base.translators.psi import com.intellij.psi.PsiField import com.intellij.psi.PsiMethod import org.jetbrains.dokka.base.translators.firstNotNullOfOrNull +import org.jetbrains.dokka.model.JavaVisibility +import org.jetbrains.dokka.model.KotlinVisibility +import org.jetbrains.dokka.model.Visibility import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.load.java.propertyNameByGetMethodName import org.jetbrains.kotlin.load.java.propertyNamesBySetMethodName @@ -28,9 +31,32 @@ internal fun splitFunctionsAndAccessors(fields: Array<PsiField>, methods: Array< regularFunctions.add(method) } } + + val accessorLookalikes = removeNonAccessorsReturning(accessors) + regularFunctions.addAll(accessorLookalikes) + return PsiFunctionsHolder(regularFunctions, accessors) } +/** + * 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.getPossiblePropertyNamesForFunction(): List<String> { val jvmName = getAnnotation(DescriptorUtils.JVM_NAME.asString())?.findAttributeValue("name")?.text return jvmName?.let { listOf(jvmName) } @@ -46,7 +72,9 @@ internal fun PsiMethod.getPossiblePropertyNamesForFunction(): List<String> { } internal fun PsiMethod.isAccessorFor(field: PsiField): Boolean { - return this.isGetterFor(field) || this.isSetterFor(field) + return (this.isGetterFor(field) || this.isSetterFor(field)) + && !field.getVisibility().isPublicAPI() + && this.getVisibility().isPublicAPI() } internal fun PsiMethod.isGetterFor(field: PsiField): Boolean { @@ -56,3 +84,11 @@ internal fun PsiMethod.isGetterFor(field: PsiField): Boolean { internal fun PsiMethod.isSetterFor(field: PsiField): Boolean { return parameterList.getParameter(0)?.type == field.type } + +internal fun Visibility.isPublicAPI() = when(this) { + KotlinVisibility.Public, + KotlinVisibility.Protected, + JavaVisibility.Public, + JavaVisibility.Protected -> true + else -> false +} |