Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Skip
@Deprecated
documentables with HIDDEN level (#2486)
- Loading branch information
1 parent
88d3623
commit 12bf21b
Showing
3 changed files
with
126 additions
and
184 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
225 changes: 44 additions & 181 deletions
225
...ase/src/main/kotlin/transformers/documentables/DeprecatedDocumentableFilterTransformer.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 |
---|---|---|
@@ -1,194 +1,57 @@ | ||
package org.jetbrains.dokka.base.transformers.documentables | ||
|
||
import org.jetbrains.dokka.DokkaConfiguration.PackageOptions | ||
import org.jetbrains.dokka.DokkaConfiguration | ||
import org.jetbrains.dokka.model.* | ||
import org.jetbrains.dokka.model.Annotations | ||
import org.jetbrains.dokka.model.Documentable | ||
import org.jetbrains.dokka.model.EnumValue | ||
import org.jetbrains.dokka.model.properties.WithExtraProperties | ||
import org.jetbrains.dokka.plugability.DokkaContext | ||
import org.jetbrains.dokka.transformers.documentation.PreMergeDocumentableTransformer | ||
|
||
class DeprecatedDocumentableFilterTransformer(val context: DokkaContext) : PreMergeDocumentableTransformer { | ||
override fun invoke(modules: List<DModule>) = modules.map { original -> | ||
val sourceSet = original.sourceSets.single() | ||
val packageOptions = | ||
sourceSet.perPackageOptions | ||
original.let { | ||
DeprecatedDocumentableFilter(sourceSet, packageOptions).processModule(it) | ||
} | ||
import org.jetbrains.dokka.transformers.documentation.perPackageOptions | ||
import org.jetbrains.dokka.transformers.documentation.sourceSet | ||
|
||
/** | ||
* If [PackageOptions.skipDeprecated] or [DokkaConfiguration.DokkaSourceSet.skipDeprecated] is set | ||
* to `true`, suppresses documentables marked with [kotlin.Deprecated] or [java.lang.Deprecated]. | ||
* Package options are given preference over global options. | ||
* | ||
* Documentables with [kotlin.Deprecated.level] set to [DeprecationLevel.HIDDEN] | ||
* are suppressed regardless of global and package options. | ||
*/ | ||
class DeprecatedDocumentableFilterTransformer(context: DokkaContext) : | ||
SuppressedByConditionDocumentableFilterTransformer(context) { | ||
|
||
override fun shouldBeSuppressed(d: Documentable): Boolean { | ||
val annotations = (d as? WithExtraProperties<*>)?.annotations() ?: return false | ||
if (annotations.isEmpty()) | ||
return false | ||
|
||
val deprecatedAnnotations = filterDeprecatedAnnotations(annotations) | ||
if (deprecatedAnnotations.isEmpty()) | ||
return false | ||
|
||
val kotlinDeprecated = deprecatedAnnotations.find { it.dri.packageName == "kotlin" } | ||
if (kotlinDeprecated?.isHidden() == true) | ||
return true | ||
|
||
return perPackageOptions(d)?.skipDeprecated ?: sourceSet(d).skipDeprecated | ||
} | ||
|
||
private class DeprecatedDocumentableFilter( | ||
val globalOptions: DokkaConfiguration.DokkaSourceSet, | ||
val packageOptions: List<DokkaConfiguration.PackageOptions> | ||
) { | ||
|
||
fun <T> T.isAllowedInPackage(): Boolean where T : WithExtraProperties<T>, T : Documentable { | ||
val packageName = this.dri.packageName | ||
val condition = packageName != null && packageOptions.firstOrNull { | ||
Regex(it.matchingRegex).matches(packageName) | ||
}?.skipDeprecated | ||
?: globalOptions.skipDeprecated | ||
|
||
return !(condition && this.isDeprecated()) | ||
} | ||
|
||
fun processModule(original: DModule) = | ||
filterPackages(original.packages).let { (modified, packages) -> | ||
if (!modified) original | ||
else | ||
original.copy( | ||
packages = packages | ||
) | ||
} | ||
|
||
|
||
private fun filterPackages(packages: List<DPackage>): Pair<Boolean, List<DPackage>> { | ||
var packagesListChanged = false | ||
val filteredPackages = packages.mapNotNull { pckg -> | ||
var modified = false | ||
val functions = filterFunctions(pckg.functions).let { (listModified, list) -> | ||
modified = modified || listModified | ||
list | ||
} | ||
val properties = filterProperties(pckg.properties).let { (listModified, list) -> | ||
modified = modified || listModified | ||
list | ||
} | ||
val classlikes = filterClasslikes(pckg.classlikes).let { (listModified, list) -> | ||
modified = modified || listModified | ||
list | ||
} | ||
val typeAliases = filterTypeAliases(pckg.typealiases).let { (listModified, list) -> | ||
modified = modified || listModified | ||
list | ||
} | ||
when { | ||
!modified -> pckg | ||
else -> { | ||
packagesListChanged = true | ||
pckg.copy( | ||
functions = functions, | ||
properties = properties, | ||
classlikes = classlikes, | ||
typealiases = typeAliases | ||
) | ||
} | ||
} | ||
} | ||
return Pair(packagesListChanged, filteredPackages) | ||
} | ||
|
||
private fun filterFunctions( | ||
functions: List<DFunction> | ||
) = functions.filter { it.isAllowedInPackage() }.let { | ||
Pair(it.size != functions.size, it) | ||
private fun WithExtraProperties<*>.annotations(): List<Annotations.Annotation> { | ||
return this.extra.allOfType<Annotations>().flatMap { annotations -> | ||
annotations.directAnnotations.values.singleOrNull() ?: emptyList() | ||
} | ||
} | ||
|
||
private fun filterProperties( | ||
properties: List<DProperty> | ||
): Pair<Boolean, List<DProperty>> = properties.filter { | ||
it.isAllowedInPackage() | ||
}.let { | ||
Pair(properties.size != it.size, it) | ||
private fun filterDeprecatedAnnotations(annotations: List<Annotations.Annotation>): List<Annotations.Annotation> { | ||
return annotations.filter { | ||
(it.dri.packageName == "kotlin" && it.dri.classNames == "Deprecated") || | ||
(it.dri.packageName == "java.lang" && it.dri.classNames == "Deprecated") | ||
} | ||
} | ||
|
||
private fun filterEnumEntries(entries: List<DEnumEntry>) = | ||
entries.filter { it.isAllowedInPackage() }.map { entry -> | ||
entry.copy( | ||
functions = filterFunctions(entry.functions).second, | ||
properties = filterProperties(entry.properties).second, | ||
classlikes = filterClasslikes(entry.classlikes).second, | ||
) | ||
} | ||
|
||
private fun filterTypeAliases(typeAliases: List<DTypeAlias>) = | ||
typeAliases.filter { it.isAllowedInPackage() }.let { | ||
Pair(typeAliases.size != it.size, it) | ||
} | ||
|
||
private fun filterClasslikes( | ||
classlikeList: List<DClasslike> | ||
): Pair<Boolean, List<DClasslike>> { | ||
var modified = false | ||
return classlikeList.filter { classlike -> | ||
when (classlike) { | ||
is DClass -> classlike.isAllowedInPackage() | ||
is DInterface -> classlike.isAllowedInPackage() | ||
is DEnum -> classlike.isAllowedInPackage() | ||
is DObject -> classlike.isAllowedInPackage() | ||
is DAnnotation -> classlike.isAllowedInPackage() | ||
} | ||
}.map { classlike -> | ||
fun helper(): DClasslike = when (classlike) { | ||
is DClass -> classlike.copy( | ||
constructors = filterFunctions(classlike.constructors).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
functions = filterFunctions(classlike.functions).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
properties = filterProperties(classlike.properties).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
classlikes = filterClasslikes(classlike.classlikes).let { | ||
modified = modified || it.first; it.second | ||
} | ||
) | ||
is DAnnotation -> classlike.copy( | ||
functions = filterFunctions(classlike.functions).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
properties = filterProperties(classlike.properties).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
classlikes = filterClasslikes(classlike.classlikes).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
constructors = filterFunctions(classlike.constructors).let { | ||
modified = modified || it.first; it.second | ||
} | ||
) | ||
is DEnum -> classlike.copy( | ||
entries = filterEnumEntries(classlike.entries), | ||
functions = filterFunctions(classlike.functions).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
properties = filterProperties(classlike.properties).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
classlikes = filterClasslikes(classlike.classlikes).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
constructors = filterFunctions(classlike.constructors).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
) | ||
is DInterface -> classlike.copy( | ||
functions = filterFunctions(classlike.functions).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
properties = filterProperties(classlike.properties).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
classlikes = filterClasslikes(classlike.classlikes).let { | ||
modified = modified || it.first; it.second | ||
} | ||
) | ||
is DObject -> classlike.copy( | ||
functions = filterFunctions(classlike.functions).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
properties = filterProperties(classlike.properties).let { | ||
modified = modified || it.first; it.second | ||
}, | ||
classlikes = filterClasslikes(classlike.classlikes).let { | ||
modified = modified || it.first; it.second | ||
} | ||
) | ||
} | ||
helper() | ||
}.let { | ||
Pair(it.size != classlikeList.size || modified, it) | ||
} | ||
} | ||
private fun Annotations.Annotation.isHidden(): Boolean { | ||
val level = (this.params["level"] as? EnumValue) ?: return false | ||
return level.enumName == "DeprecationLevel.HIDDEN" | ||
} | ||
} |
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