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

Add ability to suppress obvious functions like equals, toString... #1758

Merged
merged 2 commits into from
Mar 1, 2021
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions core/src/main/kotlin/configuration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ object DokkaDefaults {
const val sourceSetName = "main"
val moduleVersion: String? = null
val pluginsConfiguration = mutableListOf<PluginConfigurationImpl>()
const val suppressObviousFunctions = true
}

enum class Platform(val key: String) {
Expand Down Expand Up @@ -98,6 +99,7 @@ interface DokkaConfiguration : Serializable {
val pluginsClasspath: List<File>
val pluginsConfiguration: List<PluginConfiguration>
val delayTemplateSubstitution: Boolean
val suppressObviousFunctions: Boolean

enum class SerializationFormat : Serializable {
JSON, XML
Expand Down
1 change: 1 addition & 0 deletions core/src/main/kotlin/defaultConfiguration.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ data class DokkaConfigurationImpl(
override val modules: List<DokkaModuleDescriptionImpl> = emptyList(),
override val failOnWarning: Boolean = DokkaDefaults.failOnWarning,
override val delayTemplateSubstitution: Boolean = false,
override val suppressObviousFunctions: Boolean = DokkaDefaults.suppressObviousFunctions,
) : DokkaConfiguration

data class PluginConfigurationImpl(
Expand Down
4 changes: 4 additions & 0 deletions core/src/main/kotlin/model/documentableProperties.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,8 @@ data class ExceptionInSupertypes(val exceptions: SourceSetDependent<List<TypeCon
}

override val key: ExtraProperty.Key<Documentable, *> = ExceptionInSupertypes
}

object ObviousMember : ExtraProperty<Documentable>, ExtraProperty.Key<Documentable, ObviousMember> {
override val key: ExtraProperty.Key<Documentable, *> = this
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class TestDokkaConfigurationBuilder {
var pluginsConfigurations: MutableList<PluginConfigurationImpl> = mutableListOf()
var failOnWarning: Boolean = false
var modules: List<DokkaModuleDescriptionImpl> = emptyList()
var suppressObviousFunctions: Boolean = DokkaDefaults.suppressObviousFunctions
private val lazySourceSets = mutableListOf<Lazy<DokkaSourceSetImpl>>()

fun build() = DokkaConfigurationImpl(
Expand All @@ -47,6 +48,7 @@ class TestDokkaConfigurationBuilder {
pluginsConfiguration = pluginsConfigurations,
modules = modules,
failOnWarning = failOnWarning,
suppressObviousFunctions = suppressObviousFunctions
)

fun sourceSets(block: SourceSetsBuilder.() -> Unit) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package org.jetbrains.dokka.android.transformers

import org.jetbrains.dokka.base.transformers.documentables.SuppressedByTagDocumentableFilterTransformer
import org.jetbrains.dokka.base.transformers.documentables.SuppressedByConditionDocumentableFilterTransformer
import org.jetbrains.dokka.model.Documentable
import org.jetbrains.dokka.model.dfs
import org.jetbrains.dokka.model.doc.CustomTagWrapper
import org.jetbrains.dokka.plugability.DokkaContext

class HideTagDocumentableFilter(val dokkaContext: DokkaContext) :
SuppressedByTagDocumentableFilterTransformer(dokkaContext) {
SuppressedByConditionDocumentableFilterTransformer(dokkaContext) {
override fun shouldBeSuppressed(d: Documentable): Boolean =
d.documentation.any { (_, docs) -> docs.dfs { it is CustomTagWrapper && it.name.trim() == "hide" } != null }
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class HideTagDocumentableFilterTest : BaseAbstractTest() {
|}
""".trimIndent(), configuration
) {
documentablesFirstTransformationStep = { modules ->
preMergeDocumentablesTransformationStage = { modules ->
val testingClass = modules.flatMap { it.packages }.flatMap { it.classlikes }.single() as DClass
assertEquals(0, testingClass.functions.size)
}
Expand Down Expand Up @@ -60,7 +60,7 @@ class HideTagDocumentableFilterTest : BaseAbstractTest() {
|}
""".trimIndent(), configuration
) {
documentablesFirstTransformationStep = { modules ->
preMergeDocumentablesTransformationStage = { modules ->
val classes = modules.flatMap { it.packages }.flatMap { it.classlikes }.map { it.name }
assertEquals(listOf("Visible"), classes)
}
Expand Down
11 changes: 8 additions & 3 deletions plugins/base/src/main/kotlin/DokkaBase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,17 +74,22 @@ class DokkaBase : DokkaPlugin() {
preMergeDocumentableTransformer providing ::SuppressTagDocumentableFilter
}

val documentableVisbilityFilter by extending {
val documentableVisibilityFilter by extending {
preMergeDocumentableTransformer providing ::DocumentableVisibilityFilterTransformer
}

val obviousFunctionsVisbilityFilter by extending {
preMergeDocumentableTransformer providing ::ObviousFunctionsDocumentableFilterTransformer
}

val emptyPackagesFilter by extending {
preMergeDocumentableTransformer providing ::EmptyPackagesFilterTransformer order {
after(
deprecatedDocumentableFilter,
suppressedDocumentableFilter,
documentableVisbilityFilter,
suppressedBySuppressTagDocumentableFilter
documentableVisibilityFilter,
suppressedBySuppressTagDocumentableFilter,
obviousFunctionsVisbilityFilter
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.jetbrains.dokka.base.transformers.documentables

import org.jetbrains.dokka.model.DFunction
import org.jetbrains.dokka.model.Documentable
import org.jetbrains.dokka.model.ObviousMember
import org.jetbrains.dokka.plugability.DokkaContext

class ObviousFunctionsDocumentableFilterTransformer(context: DokkaContext) : SuppressedByConditionDocumentableFilterTransformer(context) {
override fun shouldBeSuppressed(d: Documentable): Boolean =
context.configuration.suppressObviousFunctions && d is DFunction && d.extra[ObviousMember] != null
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.model.doc.Suppress

class SuppressTagDocumentableFilter(val dokkaContext: DokkaContext) :
SuppressedByTagDocumentableFilterTransformer(dokkaContext) {
SuppressedByConditionDocumentableFilterTransformer(dokkaContext) {
override fun shouldBeSuppressed(d: Documentable): Boolean =
d.documentation.any { (_, docs) -> docs.dfs { it is Suppress } != null }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.jetbrains.dokka.model.*
import org.jetbrains.dokka.plugability.DokkaContext
import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer

abstract class SuppressedByTagDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer {
abstract class SuppressedByConditionDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer {
override fun invoke(modules: List<DModule>): List<DModule> =
modules.map { module ->
val (documentable, wasChanged) = processModule(module)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ private class DokkaDescriptorVisitor(
descriptor.additionalExtras().toSourceSetDependent().toAdditionalModifiers(),
(descriptor.getAnnotations() + descriptor.fileLevelAnnotations()).toSourceSetDependent()
.toAnnotations(),
ObviousMember.takeIf { descriptor.isFake },
)
)
}
Expand Down Expand Up @@ -1036,6 +1037,9 @@ private class DokkaDescriptorVisitor(
?.toList()
?.parallelMap { it.toAnnotation(scope = Annotations.AnnotationScope.FILE) }
.orEmpty()

private val FunctionDescriptor.isFake: Boolean
get() = kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE || kind == CallableMemberDescriptor.Kind.SYNTHESIZED
}

private data class AncestryLevel(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,11 +111,12 @@ class DefaultPsiToDocumentableTranslator(

private val cachedBounds = hashMapOf<String, Bound>()

private fun PsiModifierListOwner.getVisibility() = modifierList?.children?.toList()?.let { ml ->
private fun PsiModifierListOwner.getVisibility() = modifierList?.let {
val ml = it.children.toList()
when {
ml.any { it.text == PsiKeyword.PUBLIC } -> JavaVisibility.Public
ml.any { it.text == PsiKeyword.PROTECTED } -> JavaVisibility.Protected
ml.any { it.text == PsiKeyword.PRIVATE } -> JavaVisibility.Private
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
Expand All @@ -126,6 +127,9 @@ class DefaultPsiToDocumentableTranslator(
private val PsiClassType.shouldBeIgnored: Boolean
get() = isClass("java.lang.Enum") || isClass("java.lang.Object")

private val DRI.isObvious: Boolean
get() = packageName == "java.lang" && (classNames == "Object" || classNames == "Enum")

private fun PsiClassType.isClass(qName: String): Boolean {
val shortName = qName.substringAfterLast('.')
if (className == shortName) {
Expand Down Expand Up @@ -184,7 +188,7 @@ class DefaultPsiToDocumentableTranslator(
ancestryTree.add(AncestryLevel(level, classes.firstOrNull()?.first, interfaces.map { it.first }))

superTypes.forEach { type ->
(type as? PsiClassType)?.takeUnless { type.shouldBeIgnored }?.resolve()?.let {
(type as? PsiClassType)?.resolve()?.let {
val definedAt = DRI.from(it)
it.methods.forEach { method ->
val hash = method.hash
Expand Down Expand Up @@ -392,7 +396,8 @@ class DefaultPsiToDocumentableTranslator(
it.toSourceSetDependent().toAdditionalModifiers(),
(psi.annotations.toList()
.toListOfAnnotations() + it.toListOfAnnotations()).toSourceSetDependent()
.toAnnotations()
.toAnnotations(),
ObviousMember.takeIf { inheritedFrom != null && inheritedFrom.isObvious }
)
}
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package transformers

import org.jetbrains.dokka.base.testApi.testRunner.BaseAbstractTest
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

class ObviousFunctionsDocumentableFilterTest : BaseAbstractTest() {
val suppressingConfiguration = dokkaConfiguration {
sourceSets {
sourceSet {
sourceRoots = listOf("src")
}
}
}

val nonSuppressingConfiguration = dokkaConfiguration {
suppressObviousFunctions = false
sourceSets {
sourceSet {
sourceRoots = listOf("src")
}
}
}

@Test
fun `should suppress toString, equals and hashcode`() {
testInline(
"""
/src/suppressed/Suppressed.kt
package suppressed
data class Suppressed(val x: String)
""".trimIndent(),
suppressingConfiguration
) {
preMergeDocumentablesTransformationStage = { modules ->
val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions }
assertEquals(0, functions.size)
}
}
}

@Test
fun `should suppress toString, equals and hashcode in Java`() {
testInline(
"""
/src/suppressed/Suppressed.java
package suppressed;
public class Suppressed {
}
""".trimIndent(),
suppressingConfiguration
) {
preMergeDocumentablesTransformationStage = { modules ->
val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions }
assertEquals(0, functions.size)
}
}
}

@Test
fun `should suppress toString, equals and hashcode but keep custom ones`() {
testInline(
"""
/src/suppressed/Suppressed.kt
package suppressed
data class Suppressed(val x: String) {
override fun toString(): String {
return "custom"
}
}
""".trimIndent(),
suppressingConfiguration
) {
preMergeDocumentablesTransformationStage = { modules ->
val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions }
assertEquals(listOf("toString"), functions.map { it.name })
}
}
}

@Test
fun `should suppress toString, equals and hashcode but keep custom ones in Java`() {
testInline(
"""
/src/suppressed/Suppressed.java
package suppressed;
public class Suppressed {
@Override
public String toString() {
return "";
}
}
""".trimIndent(),
suppressingConfiguration
) {
preMergeDocumentablesTransformationStage = { modules ->
val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions }
assertEquals(listOf("toString"), functions.map { it.name })
}
}
}

@Test
fun `should not suppress toString, equals and hashcode if custom config is provided`() {
testInline(
"""
/src/suppressed/Suppressed.kt
package suppressed
data class Suppressed(val x: String)
""".trimIndent(),
nonSuppressingConfiguration
) {
preMergeDocumentablesTransformationStage = { modules ->
val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions }
assertEquals(
listOf("copy", "equals", "toString", "component1", "hashCode").sorted(),
functions.map { it.name }.sorted()
)
}
}
}

@Test
fun `should not suppress toString, equals and hashcode if custom config is provided in Java`() {
testInline(
"""
/src/suppressed/Suppressed.java
package suppressed;
public class Suppressed {
}
""".trimIndent(),
nonSuppressingConfiguration
) {
preMergeDocumentablesTransformationStage = { modules ->
val functions = modules.flatMap { it.packages }.flatMap { it.classlikes }.flatMap { it.functions }
//I would normally just assert names but this would make it JDK dependent, so this is better
assertEquals(
5,
setOf("equals", "hashCode", "toString", "notify", "notifyAll").intersect(functions.map { it.name }).size
)
}
}
}
}
Loading