aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2018-01-17 20:01:20 +0300
committerSimon Ogorodnik <Simon.Ogorodnik@jetbrains.com>2018-07-13 18:30:33 +0300
commit1391dcca35a871881420c53755fed08bf47e4087 (patch)
tree8b0c4906722a86afca0b8a8b5834494c73c0a2af
parentc776aaab9af80987e3c073a40f92de748dbd38ca (diff)
downloaddokka-1391dcca35a871881420c53755fed08bf47e4087.tar.gz
dokka-1391dcca35a871881420c53755fed08bf47e4087.tar.bz2
dokka-1391dcca35a871881420c53755fed08bf47e4087.zip
[backport] Support propagating inherited extensions from libraries
Original: bf2945d
-rw-r--r--core/src/main/kotlin/DokkaBootstrapImpl.kt3
-rw-r--r--core/src/main/kotlin/Generation/DokkaGenerator.kt2
-rw-r--r--core/src/main/kotlin/Generation/configurationImpl.kt47
-rw-r--r--core/src/main/kotlin/Kotlin/DocumentationBuilder.kt200
-rw-r--r--core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt2
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt2
-rw-r--r--core/src/test/kotlin/TestAPI.kt32
-rw-r--r--integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt48
-rw-r--r--runners/cli/src/main/kotlin/cli/main.kt28
-rw-r--r--runners/gradle-plugin/src/main/kotlin/main.kt51
10 files changed, 273 insertions, 142 deletions
diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt
index aeaca8be..b7787be8 100644
--- a/core/src/main/kotlin/DokkaBootstrapImpl.kt
+++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt
@@ -69,7 +69,8 @@ class DokkaBootstrapImpl : DokkaBootstrap {
languageVersion,
apiVersion,
cacheRoot,
- suppressedFiles.map { File(it) }.toSet()
+ suppressedFiles.map { File(it) }.toSet(),
+ collectInheritedExtensionsFromLibraries
)
)
}
diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt
index 09e5cedf..33170f35 100644
--- a/core/src/main/kotlin/Generation/DokkaGenerator.kt
+++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt
@@ -160,6 +160,8 @@ fun buildDocumentationModule(injector: Injector,
with(injector.getInstance(DocumentationBuilder::class.java)) {
documentationModule.appendFragments(fragments, packageDocs.packageContent,
injector.getInstance(PackageDocumentationBuilder::class.java))
+
+ propagateExtensionFunctionsToSubclasses(fragments, resolutionFacade)
}
val javaFiles = coreEnvironment.getJavaSourceFiles().filter(filesToDocumentFilter)
diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt
index 34d4154e..52e8446f 100644
--- a/core/src/main/kotlin/Generation/configurationImpl.kt
+++ b/core/src/main/kotlin/Generation/configurationImpl.kt
@@ -36,27 +36,28 @@ data class PackageOptionsImpl(override val prefix: String,
override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions
data class DokkaConfigurationImpl(
- override val moduleName: String,
- override val classpath: List<String>,
- override val sourceRoots: List<SourceRootImpl>,
- override val samples: List<String>,
- override val includes: List<String>,
- override val outputDir: String,
- override val format: String,
- override val includeNonPublic: Boolean,
- override val includeRootPackage: Boolean,
- override val reportUndocumented: Boolean,
- override val skipEmptyPackages: Boolean,
- override val skipDeprecated: Boolean,
- override val jdkVersion: Int,
- override val generateIndexPages: Boolean,
- override val sourceLinks: List<SourceLinkDefinitionImpl>,
- override val impliedPlatforms: List<String>,
- override val perPackageOptions: List<PackageOptionsImpl>,
- override val externalDocumentationLinks: List<ExternalDocumentationLinkImpl>,
- override val noStdlibLink: Boolean,
- override val cacheRoot: String?,
- override val suppressedFiles: List<String>,
- override val languageVersion: String?,
- override val apiVersion: String?
+ override val moduleName: String,
+ override val classpath: List<String>,
+ override val sourceRoots: List<SourceRootImpl>,
+ override val samples: List<String>,
+ override val includes: List<String>,
+ override val outputDir: String,
+ override val format: String,
+ override val includeNonPublic: Boolean,
+ override val includeRootPackage: Boolean,
+ override val reportUndocumented: Boolean,
+ override val skipEmptyPackages: Boolean,
+ override val skipDeprecated: Boolean,
+ override val jdkVersion: Int,
+ override val generateIndexPages: Boolean,
+ override val sourceLinks: List<SourceLinkDefinitionImpl>,
+ override val impliedPlatforms: List<String>,
+ override val perPackageOptions: List<PackageOptionsImpl>,
+ override val externalDocumentationLinks: List<ExternalDocumentationLinkImpl>,
+ override val noStdlibLink: Boolean,
+ override val cacheRoot: String?,
+ override val suppressedFiles: List<String>,
+ override val languageVersion: String?,
+ override val apiVersion: String?,
+ override val collectInheritedExtensionsFromLibraries: Boolean
) : DokkaConfiguration \ No newline at end of file
diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
index 11a36a4f..125f9fd4 100644
--- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
@@ -11,6 +11,9 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotated
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
import org.jetbrains.kotlin.idea.kdoc.findKDoc
+import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
+import org.jetbrains.kotlin.idea.util.makeNotNullable
+import org.jetbrains.kotlin.idea.util.toFuzzyType
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection
import org.jetbrains.kotlin.lexer.KtTokens
@@ -25,10 +28,11 @@ import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
+import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
+import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
import org.jetbrains.kotlin.types.*
-import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.supertypes
import java.io.File
import java.nio.file.Path
@@ -53,7 +57,8 @@ class DocumentationOptions(val outputDir: String,
val languageVersion: String?,
val apiVersion: String?,
cacheRoot: String? = null,
- val suppressedFiles: Set<File> = emptySet()) {
+ val suppressedFiles: Set<File> = emptySet(),
+ val collectInheritedExtensionsFromLibraries: Boolean = false) {
init {
if (perPackageOptions.any { it.prefix == "" })
throw IllegalArgumentException("Please do not register packageOptions with all match pattern, use global settings instead")
@@ -138,8 +143,20 @@ class DocumentationBuilder
refGraph.register(descriptor.signature(), node)
}
- fun <T> nodeForDescriptor(descriptor: T, kind: NodeKind): DocumentationNode where T : DeclarationDescriptor, T : Named {
- val (doc, callback) = descriptorDocumentationParser.parseDocumentationAndDetails(descriptor, kind == NodeKind.Parameter)
+ fun <T> nodeForDescriptor(
+ descriptor: T,
+ kind: NodeKind,
+ external: Boolean = false
+ ): DocumentationNode where T : DeclarationDescriptor, T : Named {
+ val (doc, callback) =
+ if (external) {
+ Content.Empty to { node -> }
+ } else {
+ descriptorDocumentationParser.parseDocumentationAndDetails(
+ descriptor,
+ kind == NodeKind.Parameter
+ )
+ }
val node = DocumentationNode(descriptor.name.asString(), doc, kind).withModifiers(descriptor)
node.appendSignature(descriptor)
callback(node)
@@ -226,14 +243,20 @@ class DocumentationBuilder
node.appendTextNode("?", NodeKind.NullabilityModifier)
}
if (classifierDescriptor != null) {
- val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor)
+ val externalLink =
+ linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor)
if (externalLink != null) {
- val targetNode = refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true)
- node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
- node.append(targetNode, RefKind.ExternalType)
+ if (classifierDescriptor !is TypeParameterDescriptor) {
+ val targetNode =
+ refGraph.lookup(classifierDescriptor.signature()) ?: classifierDescriptor.build(true)
+ node.append(targetNode, RefKind.ExternalType)
+ node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
+ }
} else {
- link(node, classifierDescriptor,
- if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link)
+ link(
+ node, classifierDescriptor,
+ if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link
+ )
}
if (classifierDescriptor !is TypeParameterDescriptor) {
node.append(
@@ -280,6 +303,17 @@ class DocumentationBuilder
}
}
+ fun DocumentationNode.appendExternalLink(externalLink: String) {
+ append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
+ }
+
+ fun DocumentationNode.appendExternalLink(descriptor: DeclarationDescriptor) {
+ val target = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(descriptor)
+ if (target != null) {
+ appendExternalLink(target)
+ }
+ }
+
fun DocumentationNode.appendSinceKotlin(annotation: DocumentationNode) {
val kotlinVersion = annotation
.detail(NodeKind.Parameter)
@@ -426,15 +460,44 @@ class DocumentationBuilder
declarations, allFqNames)
}
- propagateExtensionFunctionsToSubclasses(fragments)
}
- private fun propagateExtensionFunctionsToSubclasses(fragments: Collection<PackageFragmentDescriptor>) {
- val allDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() }
- val allClasses = allDescriptors.filterIsInstance<ClassDescriptor>()
- val classHierarchy = buildClassHierarchy(allClasses)
+ fun propagateExtensionFunctionsToSubclasses(
+ fragments: Collection<PackageFragmentDescriptor>,
+ resolutionFacade: DokkaResolutionFacade
+ ) {
+
+ val moduleDescriptor = resolutionFacade.moduleDescriptor
+
+ // Wide-collect all view descriptors
+ val allPackageViewDescriptors = generateSequence(listOf(moduleDescriptor.getPackage(FqName.ROOT))) { packages ->
+ packages
+ .flatMap { pkg ->
+ moduleDescriptor.getSubPackagesOf(pkg.fqName) { true }
+ }.map { fqName ->
+ moduleDescriptor.getPackage(fqName)
+ }.takeUnless { it.isEmpty() }
+ }.flatten()
+
+ val allDescriptors =
+ if (options.collectInheritedExtensionsFromLibraries) {
+ allPackageViewDescriptors.map { it.memberScope }
+ } else {
+ fragments.asSequence().map { it.getMemberScope() }
+ }.flatMap {
+ it.getDescriptorsFiltered(
+ DescriptorKindFilter.CALLABLES
+ ).asSequence()
+ }
+
- val allExtensionFunctions = allDescriptors
+ val documentingDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() }
+ val documentingClasses = documentingDescriptors.filterIsInstance<ClassDescriptor>()
+
+ val classHierarchy = buildClassHierarchy(documentingClasses)
+
+ val allExtensionFunctions =
+ allDescriptors
.filterIsInstance<CallableMemberDescriptor>()
.filter { it.extensionReceiverParameter != null }
val extensionFunctionsByName = allExtensionFunctions.groupBy { it.name }
@@ -442,15 +505,31 @@ class DocumentationBuilder
for (extensionFunction in allExtensionFunctions) {
if (extensionFunction.dispatchReceiverParameter != null) continue
val possiblyShadowingFunctions = extensionFunctionsByName[extensionFunction.name]
- ?.filter { fn -> fn.canShadow(extensionFunction) }
+ ?.filter { fn -> fn.canShadow(extensionFunction) }
?: emptyList()
if (extensionFunction.extensionReceiverParameter?.type?.isDynamic() == true) continue
- val classDescriptor = extensionFunction.getExtensionClassDescriptor() ?: continue
- val subclasses = classHierarchy[classDescriptor] ?: continue
- subclasses.forEach { subclass ->
+ val subclasses =
+ classHierarchy.filter { (key) -> key.isExtensionApplicable(extensionFunction) }
+ if (subclasses.isEmpty()) continue
+ subclasses.values.flatten().forEach { subclass ->
if (subclass.isExtensionApplicable(extensionFunction) &&
- possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) {
+ possiblyShadowingFunctions.none { subclass.isExtensionApplicable(it) }) {
+
+ val hasExternalLink =
+ linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(
+ extensionFunction
+ ) != null
+ if (hasExternalLink) {
+ val containerDesc =
+ extensionFunction.containingDeclaration as? PackageFragmentDescriptor
+ if (containerDesc != null) {
+ val container = refGraph.lookup(containerDesc.signature())
+ ?: containerDesc.buildExternal()
+ container.append(extensionFunction.buildExternal(), RefKind.Member)
+ }
+ }
+
refGraph.link(subclass.signature(), extensionFunction.signature(), RefKind.Extension)
}
}
@@ -458,12 +537,9 @@ class DocumentationBuilder
}
private fun ClassDescriptor.isExtensionApplicable(extensionFunction: CallableMemberDescriptor): Boolean {
- val receiverType = extensionFunction.extensionReceiverParameter!!.type
- if (receiverType.arguments.any { it.type.constructor.declarationDescriptor is TypeParameterDescriptor }) {
- val receiverClass = receiverType.constructor.declarationDescriptor
- return receiverClass is ClassDescriptor && DescriptorUtils.isSubclass(this, receiverClass)
- }
- return defaultType.isSubtypeOf(receiverType)
+ val receiverType = extensionFunction.fuzzyExtensionReceiverType()?.makeNotNullable()
+ val classType = defaultType.toFuzzyType(declaredTypeParameters)
+ return receiverType != null && classType.checkIsSubtypeOf(receiverType) != null
}
private fun buildClassHierarchy(classes: List<ClassDescriptor>): Map<ClassDescriptor, List<ClassDescriptor>> {
@@ -511,6 +587,24 @@ class DocumentationBuilder
else -> throw IllegalStateException("Descriptor $this is not known")
}
+ fun PackageFragmentDescriptor.buildExternal(): DocumentationNode {
+ val node = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.Package)
+
+ val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(this)
+ if (externalLink != null) {
+ node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
+ }
+ register(this, node)
+ return node
+ }
+
+ fun CallableDescriptor.buildExternal(): DocumentationNode = when(this) {
+ is FunctionDescriptor -> build(true)
+ is PropertyDescriptor -> build(true)
+ else -> throw IllegalStateException("Descriptor $this is not known")
+ }
+
+
fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) {
is ClassDescriptor -> build(external)
is TypeAliasDescriptor -> build(external)
@@ -547,7 +641,7 @@ class DocumentationBuilder
isSubclassOfThrowable() -> NodeKind.Exception
else -> NodeKind.Class
}
- val node = nodeForDescriptor(this, kind)
+ val node = nodeForDescriptor(this, kind, external)
register(this, node)
typeConstructor.supertypes.forEach {
node.appendSupertype(this, it)
@@ -632,12 +726,12 @@ class DocumentationBuilder
return (receiver?.type?.constructor?.declarationDescriptor as? ClassDescriptor)?.isCompanionObject ?: false
}
- fun FunctionDescriptor.build(): DocumentationNode {
+ fun FunctionDescriptor.build(external: Boolean = false): DocumentationNode {
if (ErrorUtils.containsErrorType(this)) {
logger.warn("Found an unresolved type in ${signatureWithSourceLocation()}")
}
- val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function)
+ val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectFunction else NodeKind.Function, external)
node.appendInPageChildren(typeParameters, RefKind.Detail)
extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
@@ -645,8 +739,12 @@ class DocumentationBuilder
node.appendType(returnType)
node.appendAnnotations(this)
node.appendModifiers(this)
- node.appendSourceLink(source)
- node.appendDefaultPlatforms(this)
+ if (!external) {
+ node.appendSourceLink(source)
+ node.appendDefaultPlatforms(this)
+ } else {
+ node.appendExternalLink(this)
+ }
overriddenDescriptors.forEach {
addOverrideLink(it, this)
@@ -667,32 +765,42 @@ class DocumentationBuilder
}
}
- fun PropertyDescriptor.build(): DocumentationNode {
- val node = nodeForDescriptor(this, if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property)
+ fun PropertyDescriptor.build(external: Boolean = false): DocumentationNode {
+ val node = nodeForDescriptor(
+ this,
+ if (inCompanionObject()) NodeKind.CompanionObjectProperty else NodeKind.Property,
+ external
+ )
node.appendInPageChildren(typeParameters, RefKind.Detail)
extensionReceiverParameter?.let { node.appendChild(it, RefKind.Detail) }
node.appendType(returnType)
node.appendAnnotations(this)
node.appendModifiers(this)
- node.appendSourceLink(source)
- if (isVar) {
- node.appendTextNode("var", NodeKind.Modifier)
- }
- getter?.let {
- if (!it.isDefault) {
- node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter")
+ if (!external) {
+ node.appendSourceLink(source)
+ if (isVar) {
+ node.appendTextNode("var", NodeKind.Modifier)
}
- }
- setter?.let {
- if (!it.isDefault) {
- node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter")
+
+ getter?.let {
+ if (!it.isDefault) {
+ node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter")
+ }
}
+ setter?.let {
+ if (!it.isDefault) {
+ node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Setter")
+ }
+ }
+ node.appendDefaultPlatforms(this)
+ }
+ if (external) {
+ node.appendExternalLink(this)
}
overriddenDescriptors.forEach {
addOverrideLink(it, this)
}
- node.appendDefaultPlatforms(this)
register(this, node)
return node
diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt
index e19ecf76..400326d2 100644
--- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt
+++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt
@@ -155,8 +155,8 @@ class ExternalDocumentationLinkResolver @Inject constructor(
fun buildExternalDocumentationLink(symbol: DeclarationDescriptor): String? {
val packageFqName: FqName =
when (symbol) {
- is DeclarationDescriptorNonRoot -> symbol.parents.firstOrNull { it is PackageFragmentDescriptor }?.fqNameSafe ?: return null
is PackageFragmentDescriptor -> symbol.fqName
+ is DeclarationDescriptorNonRoot -> symbol.parents.firstOrNull { it is PackageFragmentDescriptor }?.fqNameSafe ?: return null
else -> return null
}
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index a792460f..85ecdf87 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -209,6 +209,8 @@ fun DocumentationNode.appendTextNode(text: String,
fun DocumentationNode.qualifiedName(): String {
if (kind == NodeKind.Type) {
return qualifiedNameFromType()
+ } else if (kind == NodeKind.Package) {
+ return name
}
return path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".")
}
diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt
index 559b715e..aeff9284 100644
--- a/core/src/test/kotlin/TestAPI.kt
+++ b/core/src/test/kotlin/TestAPI.kt
@@ -25,22 +25,24 @@ fun verifyModel(vararg roots: ContentRoot,
includeNonPublic: Boolean = true,
perPackageOptions: List<DokkaConfiguration.PackageOptions> = emptyList(),
noStdlibLink: Boolean = true,
+ collectInheritedExtensionsFromLibraries: Boolean = false,
verifier: (DocumentationModule) -> Unit) {
val documentation = DocumentationModule("test")
val options = DocumentationOptions(
- "",
- format,
- includeNonPublic = includeNonPublic,
- skipEmptyPackages = false,
- includeRootPackage = true,
- sourceLinks = listOf(),
- perPackageOptions = perPackageOptions,
- generateIndexPages = false,
- noStdlibLink = noStdlibLink,
- cacheRoot = "default",
- languageVersion = null,
- apiVersion = null
+ "",
+ format,
+ includeNonPublic = includeNonPublic,
+ skipEmptyPackages = false,
+ includeRootPackage = true,
+ sourceLinks = listOf(),
+ perPackageOptions = perPackageOptions,
+ generateIndexPages = false,
+ noStdlibLink = noStdlibLink,
+ cacheRoot = "default",
+ languageVersion = null,
+ apiVersion = null,
+ collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries
)
appendDocumentation(documentation, *roots,
@@ -162,6 +164,7 @@ fun verifyOutput(roots: Array<ContentRoot>,
format: String = "html",
includeNonPublic: Boolean = true,
noStdlibLink: Boolean = true,
+ collectInheritedExtensionsFromLibraries: Boolean = false,
outputGenerator: (DocumentationModule, StringBuilder) -> Unit) {
verifyModel(
*roots,
@@ -169,7 +172,8 @@ fun verifyOutput(roots: Array<ContentRoot>,
withKotlinRuntime = withKotlinRuntime,
format = format,
includeNonPublic = includeNonPublic,
- noStdlibLink = noStdlibLink
+ noStdlibLink = noStdlibLink,
+ collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries
) {
verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator)
}
@@ -194,6 +198,7 @@ fun verifyOutput(
format: String = "html",
includeNonPublic: Boolean = true,
noStdlibLink: Boolean = true,
+ collectInheritedExtensionsFromLibraries: Boolean = false,
outputGenerator: (DocumentationModule, StringBuilder) -> Unit
) {
verifyOutput(
@@ -204,6 +209,7 @@ fun verifyOutput(
format,
includeNonPublic,
noStdlibLink,
+ collectInheritedExtensionsFromLibraries,
outputGenerator
)
}
diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt
index 90e5b5fc..46a57278 100644
--- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt
+++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt
@@ -41,6 +41,7 @@ interface DokkaConfiguration {
val noStdlibLink: Boolean
val cacheRoot: String?
val suppressedFiles: List<String>
+ val collectInheritedExtensionsFromLibraries: Boolean
interface SourceRoot {
val path: String
@@ -82,29 +83,30 @@ interface DokkaConfiguration {
}
data class SerializeOnlyDokkaConfiguration(
- override val moduleName: String,
- override val classpath: List<String>,
- override val sourceRoots: List<DokkaConfiguration.SourceRoot>,
- override val samples: List<String>,
- override val includes: List<String>,
- override val outputDir: String,
- override val format: String,
- override val includeNonPublic: Boolean,
- override val includeRootPackage: Boolean,
- override val reportUndocumented: Boolean,
- override val skipEmptyPackages: Boolean,
- override val skipDeprecated: Boolean,
- override val jdkVersion: Int,
- override val generateIndexPages: Boolean,
- override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>,
- override val impliedPlatforms: List<String>,
- override val perPackageOptions: List<DokkaConfiguration.PackageOptions>,
- override val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>,
- override val noStdlibLink: Boolean,
- override val cacheRoot: String?,
- override val suppressedFiles: List<String>,
- override val languageVersion: String?,
- override val apiVersion: String?
+ override val moduleName: String,
+ override val classpath: List<String>,
+ override val sourceRoots: List<DokkaConfiguration.SourceRoot>,
+ override val samples: List<String>,
+ override val includes: List<String>,
+ override val outputDir: String,
+ override val format: String,
+ override val includeNonPublic: Boolean,
+ override val includeRootPackage: Boolean,
+ override val reportUndocumented: Boolean,
+ override val skipEmptyPackages: Boolean,
+ override val skipDeprecated: Boolean,
+ override val jdkVersion: Int,
+ override val generateIndexPages: Boolean,
+ override val sourceLinks: List<DokkaConfiguration.SourceLinkDefinition>,
+ override val impliedPlatforms: List<String>,
+ override val perPackageOptions: List<DokkaConfiguration.PackageOptions>,
+ override val externalDocumentationLinks: List<DokkaConfiguration.ExternalDocumentationLink>,
+ override val noStdlibLink: Boolean,
+ override val cacheRoot: String?,
+ override val suppressedFiles: List<String>,
+ override val languageVersion: String?,
+ override val apiVersion: String?,
+ override val collectInheritedExtensionsFromLibraries: Boolean
) : DokkaConfiguration
diff --git a/runners/cli/src/main/kotlin/cli/main.kt b/runners/cli/src/main/kotlin/cli/main.kt
index fe945ed3..111e1420 100644
--- a/runners/cli/src/main/kotlin/cli/main.kt
+++ b/runners/cli/src/main/kotlin/cli/main.kt
@@ -62,6 +62,9 @@ class DokkaArguments {
@set:Argument(value = "apiVersion", description = "Kotlin Api Version to pass to Kotlin Analysis")
var apiVersion: String? = null
+ @set:Argument(value = "collectInheritedExtensionsFromLibraries", description = "Search for applicable extensions in libraries")
+ var collectInheritedExtensionsFromLibraries: Boolean = false
+
}
@@ -106,18 +109,19 @@ object MainKt {
val classPath = arguments.classpath.split(File.pathSeparatorChar).toList()
val documentationOptions = DocumentationOptions(
- arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' },
- arguments.outputFormat,
- skipDeprecated = arguments.nodeprecated,
- sourceLinks = sourceLinks,
- impliedPlatforms = arguments.impliedPlatforms.split(','),
- perPackageOptions = parsePerPackageOptions(arguments.packageOptions),
- jdkVersion = arguments.jdkVersion,
- externalDocumentationLinks = parseLinks(arguments.links),
- noStdlibLink = arguments.noStdlibLink,
- cacheRoot = arguments.cacheRoot,
- languageVersion = arguments.languageVersion,
- apiVersion = arguments.apiVersion
+ arguments.outputDir.let { if (it.endsWith('/')) it else it + '/' },
+ arguments.outputFormat,
+ skipDeprecated = arguments.nodeprecated,
+ sourceLinks = sourceLinks,
+ impliedPlatforms = arguments.impliedPlatforms.split(','),
+ perPackageOptions = parsePerPackageOptions(arguments.packageOptions),
+ jdkVersion = arguments.jdkVersion,
+ externalDocumentationLinks = parseLinks(arguments.links),
+ noStdlibLink = arguments.noStdlibLink,
+ cacheRoot = arguments.cacheRoot,
+ languageVersion = arguments.languageVersion,
+ apiVersion = arguments.apiVersion,
+ collectInheritedExtensionsFromLibraries = arguments.collectInheritedExtensionsFromLibraries
)
val generator = DokkaGenerator(
diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt
index 5f02cd0e..4812e217 100644
--- a/runners/gradle-plugin/src/main/kotlin/main.kt
+++ b/runners/gradle-plugin/src/main/kotlin/main.kt
@@ -134,6 +134,9 @@ open class DokkaTask : DefaultTask() {
@Optional @Input
var apiVersion: String? = null
+ @Input
+ var collectInheritedExtensionsFromLibraries: Boolean = false
+
@get:Internal
internal val kotlinCompileBasedClasspathAndSourceRoots: ClasspathAndSourceRoots by lazy { extractClasspathAndSourceRootsFromKotlinTasks() }
@@ -287,29 +290,31 @@ open class DokkaTask : DefaultTask() {
val bootstrapProxy: DokkaBootstrap = automagicTypedProxy(javaClass.classLoader, bootstrapInstance)
val configuration = SerializeOnlyDokkaConfiguration(
- moduleName,
- fullClasspath.map { it.absolutePath },
- sourceRoots,
- samples.filterNotNull().map { project.file(it).absolutePath },
- includes.filterNotNull().map { project.file(it).absolutePath },
- outputDirectory,
- outputFormat,
- includeNonPublic,
- false,
- reportUndocumented,
- skipEmptyPackages,
- skipDeprecated,
- jdkVersion,
- true,
- linkMappings,
- impliedPlatforms,
- perPackageOptions,
- externalDocumentationLinks,
- noStdlibLink,
- cacheRoot,
- collectSuppressedFiles(sourceRoots),
- languageVersion,
- apiVersion)
+ moduleName,
+ fullClasspath.map { it.absolutePath },
+ sourceRoots,
+ samples.filterNotNull().map { project.file(it).absolutePath },
+ includes.filterNotNull().map { project.file(it).absolutePath },
+ outputDirectory,
+ outputFormat,
+ includeNonPublic,
+ false,
+ reportUndocumented,
+ skipEmptyPackages,
+ skipDeprecated,
+ jdkVersion,
+ true,
+ linkMappings,
+ impliedPlatforms,
+ perPackageOptions,
+ externalDocumentationLinks,
+ noStdlibLink,
+ cacheRoot,
+ collectSuppressedFiles(sourceRoots),
+ languageVersion,
+ apiVersion,
+ collectInheritedExtensionsFromLibraries
+ )
bootstrapProxy.configure(