Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix inheriting docs in case of diamond inheritance #2686

Merged
merged 2 commits into from Oct 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,5 +1,6 @@
package org.jetbrains.dokka.base.translators.descriptors

import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNamedElement
import com.intellij.psi.util.PsiLiteralUtil.*
import kotlinx.coroutines.Dispatchers
Expand Down Expand Up @@ -49,6 +50,7 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor
import org.jetbrains.kotlin.load.kotlin.toSourceElement
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.components.isVararg
import org.jetbrains.kotlin.resolve.calls.util.getValueArgumentsInParentheses
Expand Down Expand Up @@ -1016,7 +1018,13 @@ private class DokkaDescriptorVisitor(
org.jetbrains.kotlin.types.Variance.OUT_VARIANCE -> Covariance(this)
}

private fun DeclarationDescriptor.getDocumentation() = (findKDoc()?.let {
private fun descriptorToAnyDeclaration(descriptor: DeclarationDescriptor): PsiElement? {
val effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(descriptor)
//take any
return effectiveReferencedDescriptors.firstOrNull()?.let { DescriptorToSourceUtils.getSourceFromDescriptor(it) }
}

private fun DeclarationDescriptor.getDocumentation() = (findKDoc(::descriptorToAnyDeclaration)?.let {
MarkdownParser.parseFromKDocTag(
kDocTag = it,
externalDri = { link: String ->
Expand Down
59 changes: 50 additions & 9 deletions plugins/base/src/test/kotlin/model/InheritorsTest.kt
Expand Up @@ -106,15 +106,6 @@ class InheritorsTest : AbstractModelTest("/src/main/kotlin/inheritors/Test.kt",
}
}
}
interface A<E> {
val a: E
}

open class C
class B<E>() : C(), A<E> {
override val a: E
get() = TODO("Not yet implemented")
}

@Test
fun `should inherit docs`() {
Expand Down Expand Up @@ -370,4 +361,54 @@ class InheritorsTest : AbstractModelTest("/src/main/kotlin/inheritors/Test.kt",
}
}
}

@Test
fun `should inherit docs in case of diamond inheritance`() {
inlineModelTest(
"""
public interface Collection2<out E> {
/**
* Returns `true` if the collection is empty (contains no elements), `false` otherwise.
*/
public fun isEmpty(): Boolean

/**
* Checks if the specified element is contained in this collection.
*/
public operator fun contains(element: @UnsafeVariance E): Boolean
}

public interface MutableCollection2<E> : Collection2<E>, MutableIterable2<E>


public interface List2<out E> : Collection2<E> {
override fun isEmpty(): Boolean
override fun contains(element: @UnsafeVariance E): Boolean
}

public interface MutableList2<E> : List2<E>, MutableCollection2<E>

public class AbstractMutableList2<E> : MutableList2<E> {
protected constructor()

// From List

override fun isEmpty(): Boolean = size == 0
public override fun contains(element: E): Boolean = indexOf(element) != -1
}
public class ArrayDeque2<E> : AbstractMutableList2<E> {
override fun isEmpty(): Boolean = size == 0
public override fun contains(element: E): Boolean = indexOf(element) != -1

}
""".trimMargin()
) {
with((this / "inheritors" / "ArrayDeque2" / "isEmpty").cast<DFunction>()) {
documentation.size equals 1
}
with((this / "inheritors" / "ArrayDeque2" / "contains").cast<DFunction>()) {
documentation.size equals 1
}
}
}
}