diff options
author | Dmitry Jemerov <yole@jetbrains.com> | 2017-02-23 16:35:45 +0100 |
---|---|---|
committer | Dmitry Jemerov <yole@jetbrains.com> | 2017-02-23 16:35:45 +0100 |
commit | 99689adee954582da57268ff0375fdec52193a01 (patch) | |
tree | 82b41b04e568a564ba91473e1dcaba25b611a2b6 /core/src/main | |
parent | a39c7a161282d132d08bcf89eed0213374a574e9 (diff) | |
download | dokka-99689adee954582da57268ff0375fdec52193a01.tar.gz dokka-99689adee954582da57268ff0375fdec52193a01.tar.bz2 dokka-99689adee954582da57268ff0375fdec52193a01.zip |
Merge declarations with the same signature defined for multiple platforms
Diffstat (limited to 'core/src/main')
9 files changed, 103 insertions, 45 deletions
diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 95066eec..cc9a1b74 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -59,7 +59,8 @@ class DokkaGenerator(val logger: DokkaLogger, logger.info("Analysing sources and libraries... ") val startAnalyse = System.currentTimeMillis() - val injector = Guice.createInjector(DokkaAnalysisModule(environment, options, implicitPlatforms, logger)) + val injector = Guice.createInjector( + DokkaAnalysisModule(environment, options, implicitPlatforms, documentationModule.nodeRefGraph, logger)) buildDocumentationModule(injector, documentationModule, { isSample(it) }, includes) diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 806e9f92..b2f4aeaf 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -44,10 +44,10 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser - @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph) { + @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger) { this.options = options this.refGraph = refGraph - this.docParser = JavadocParser(refGraph) + this.docParser = JavadocParser(refGraph, logger) } constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 0fb98230..af45f150 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -20,7 +20,8 @@ interface JavaDocumentationParser { fun parseDocumentation(element: PsiNamedElement): JavadocParseResult } -class JavadocParser(private val refGraph: NodeReferenceGraph) : JavaDocumentationParser { +class JavadocParser(private val refGraph: NodeReferenceGraph, + private val logger: DokkaLogger) : JavaDocumentationParser { override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult { val docComment = (element as? PsiDocCommentOwner)?.docComment if (docComment == null) return JavadocParseResult.Empty @@ -99,7 +100,7 @@ class JavadocParser(private val refGraph: NodeReferenceGraph) : JavaDocumentatio private fun createLink(element: Element): ContentBlock { val docref = element.attr("docref") if (docref != null) { - return ContentNodeLazyLink(docref, { -> refGraph.lookup(docref)}) + return ContentNodeLazyLink(docref, { -> refGraph.lookupOrWarn(docref, logger)}) } val href = element.attr("href") if (href != null) { @@ -118,7 +119,7 @@ class JavadocParser(private val refGraph: NodeReferenceGraph) : JavaDocumentatio val linkSignature = resolveLink(linkElement) val text = ContentText(linkElement.text) if (linkSignature != null) { - val linkNode = ContentNodeLazyLink(tag.valueElement!!.text, { -> refGraph.lookup(linkSignature)}) + val linkNode = ContentNodeLazyLink(tag.valueElement!!.text, { -> refGraph.lookupOrWarn(linkSignature, logger)}) linkNode.append(text) seeSection.append(linkNode) } else { diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index 4c46f7d6..71b636bf 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -31,7 +31,7 @@ class DeclarationLinkResolver if (jdkHref != null) { return ContentExternalLink(jdkHref) } - return ContentNodeLazyLink(href, { -> refGraph.lookup(symbol.signature()) }) + return ContentNodeLazyLink(href, { -> refGraph.lookupOrWarn(symbol.signature(), logger) }) } if ("/" in href) { return ContentExternalLink(href) diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index d1f64eeb..06acf2e6 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -116,7 +116,7 @@ class DescriptorDocumentationParser fun parseJavadoc(descriptor: DeclarationDescriptor): Pair<Content, (DocumentationNode) -> Unit> { val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi if (psi is PsiDocCommentOwner) { - val parseResult = JavadocParser(refGraph).parseDocumentation(psi as PsiNamedElement) + val parseResult = JavadocParser(refGraph, logger).parseDocumentation(psi as PsiNamedElement) return parseResult.content to { node -> parseResult.deprecatedContent?.let { val deprecationNode = DocumentationNode("", it, NodeKind.Modifier) diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e165a2b5..ceeed491 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -260,11 +260,7 @@ class DocumentationBuilder } fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: RefKind): DocumentationNode? { - // do not include generated code - if (descriptor is CallableMemberDescriptor && descriptor.kind != CallableMemberDescriptor.Kind.DECLARATION) - return null - - if (descriptor.isDocumented(options)) { + if (!descriptor.isGenerated() && descriptor.isDocumented(options)) { val node = descriptor.build() append(node, kind) return node @@ -272,21 +268,57 @@ class DocumentationBuilder return null } - fun DocumentationNode.appendMembers(descriptors: Iterable<DeclarationDescriptor>, - inheritedLinkKind: RefKind = RefKind.InheritedMember): List<DocumentationNode> { - val nodes = descriptors.map { descriptor -> - if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { - val baseDescriptor = descriptor.overriddenDescriptors.firstOrNull() - if (baseDescriptor != null) { - link(this, baseDescriptor, inheritedLinkKind) + fun DocumentationNode.appendOrUpdateMember(descriptor: DeclarationDescriptor) { + if (descriptor.isGenerated() || !descriptor.isDocumented(options)) return + + val existingNode = refGraph.lookup(descriptor.signature()) + if (existingNode != null) { + existingNode.updatePlatforms() + + if (descriptor is ClassDescriptor) { + val membersToDocument = descriptor.collectMembersToDocument() + for ((memberDescriptor, inheritedLinkKind, extraModifier) in membersToDocument) { + if (memberDescriptor is ClassDescriptor) { + existingNode.appendOrUpdateMember(memberDescriptor) // recurse into nested classes + } + else { + val existingMemberNode = refGraph.lookup(memberDescriptor.signature()) + if (existingMemberNode != null) { + existingMemberNode.updatePlatforms() + } + else { + existingNode.appendClassMember(memberDescriptor, inheritedLinkKind, extraModifier) + } + } } - null - } else { - val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original - appendChild(descriptorToUse, RefKind.Member) } } - return nodes.filterNotNull() + else { + appendChild(descriptor, RefKind.Member) + } + } + + private fun DocumentationNode.updatePlatforms() { + for (platform in implicitPlatforms - platforms) { + append(platformNodeRegistry[platform], RefKind.Platform) + } + } + + fun DocumentationNode.appendClassMember(descriptor: DeclarationDescriptor, + inheritedLinkKind: RefKind = RefKind.InheritedMember, + extraModifier: String?) { + if (descriptor is CallableMemberDescriptor && descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { + val baseDescriptor = descriptor.overriddenDescriptors.firstOrNull() + if (baseDescriptor != null) { + link(this, baseDescriptor, inheritedLinkKind) + } + } else { + val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original + val child = appendChild(descriptorToUse, RefKind.Member) + if (extraModifier != null) { + child?.appendTextNode("static", NodeKind.Modifier) + } + } } fun DocumentationNode.appendInPageChildren(descriptors: Iterable<DeclarationDescriptor>, kind: RefKind) { @@ -444,29 +476,48 @@ class DocumentationBuilder } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) - val constructorsToDocument = if (getKind() == ClassKind.ENUM_CLASS) + } + for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) { + node.appendClassMember(descriptor, inheritedLinkKind, extraModifier) + } + node.appendAnnotations(this) + node.appendModifiers(this) + node.appendSourceLink(source) + node.appendImplicitPlatforms() + register(this, node) + return node + } + + data class ClassMember(val descriptor: DeclarationDescriptor, + val inheritedLinkKind: RefKind = RefKind.InheritedMember, + val extraModifier: String? = null) + + fun ClassDescriptor.collectMembersToDocument(): List<ClassMember> { + val result = arrayListOf<ClassMember>() + if (kind != ClassKind.OBJECT && kind != ClassKind.ENUM_ENTRY) { + val constructorsToDocument = if (kind == ClassKind.ENUM_CLASS) constructors.filter { it.valueParameters.size > 0 } else constructors - node.appendMembers(constructorsToDocument) - } - val members = defaultType.memberScope.getContributedDescriptors().filter { it != companionObjectDescriptor } - node.appendMembers(members) - node.appendMembers(staticScope.getContributedDescriptors()).forEach { - it.appendTextNode("static", NodeKind.Modifier) + constructorsToDocument.mapTo(result) { ClassMember(it) } } + + defaultType.memberScope.getContributedDescriptors() + .filter { it != companionObjectDescriptor } + .mapTo(result) { ClassMember(it) } + + staticScope.getContributedDescriptors() + .mapTo(result) { ClassMember(it, extraModifier = "static") } + val companionObjectDescriptor = companionObjectDescriptor if (companionObjectDescriptor != null) { val descriptors = companionObjectDescriptor.defaultType.memberScope.getContributedDescriptors() val descriptorsToDocument = descriptors.filter { it !is CallableDescriptor || !it.isInheritedFromAny() } - node.appendMembers(descriptorsToDocument, RefKind.InheritedCompanionObjectMember) + descriptorsToDocument.mapTo(result) { + ClassMember(it, inheritedLinkKind = RefKind.InheritedCompanionObjectMember) + } } - node.appendAnnotations(this) - node.appendModifiers(this) - node.appendSourceLink(source) - node.appendImplicitPlatforms() - register(this, node) - return node + return result } fun CallableDescriptor.isInheritedFromAny(): Boolean { @@ -681,6 +732,8 @@ fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean { (!options.skipDeprecated || !isDeprecated()) } +private fun DeclarationDescriptor.isGenerated() = this is CallableMemberDescriptor && kind != CallableMemberDescriptor.Kind.DECLARATION + class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { override fun buildPackageDocumentation(documentationBuilder: DocumentationBuilder, packageName: FqName, @@ -692,7 +745,7 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder { with(documentationBuilder) { if (descriptor.isDocumented(options)) { val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes, allFqNames) - parent.appendChild(descriptor, RefKind.Member) + parent.appendOrUpdateMember(descriptor) } } } diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 56c295cd..caacac14 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -138,6 +138,7 @@ open class DocumentationNode(val name: String, class DocumentationModule(name: String, content: Content = Content.Empty) : DocumentationNode(name, content, NodeKind.Module) { + val nodeRefGraph = NodeReferenceGraph() } val DocumentationNode.path: List<DocumentationNode> diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 4f28d7c3..a968f400 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka -import com.google.inject.Inject import com.google.inject.Singleton enum class RefKind { @@ -37,9 +36,7 @@ class PendingDocumentationReference(val lazyNodeFrom: () -> DocumentationNode?, } } -@Singleton -class NodeReferenceGraph - @Inject constructor(val logger: DokkaLogger) { +class NodeReferenceGraph() { private val nodeMap = hashMapOf<String, DocumentationNode>() val references = arrayListOf<PendingDocumentationReference>() @@ -59,7 +56,9 @@ class NodeReferenceGraph references.add(PendingDocumentationReference({ -> nodeMap[fromSignature]}, { -> nodeMap[toSignature]}, kind)) } - fun lookup(signature: String): DocumentationNode? { + fun lookup(signature: String) = nodeMap[signature] + + fun lookupOrWarn(signature: String, logger: DokkaLogger): DocumentationNode? { val result = nodeMap[signature] if (result == null) { logger.warn("Can't find node by signature $signature") diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 3352a846..9bb44e09 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -14,6 +14,7 @@ import java.io.File class DokkaAnalysisModule(val environment: AnalysisEnvironment, val options: DocumentationOptions, val implicitPlatforms: List<String>, + val nodeReferenceGraph: NodeReferenceGraph, val logger: DokkaLogger) : Module { override fun configure(binder: Binder) { val descriptor = ServiceLocator.lookup<FormatDescriptor>("format", options.outputFormat) @@ -33,6 +34,8 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, binder.bind<DokkaLogger>().toInstance(logger) binder.bind(StringListType).annotatedWith(Names.named(implicitPlatformName)).toInstance(implicitPlatforms) + + binder.bind<NodeReferenceGraph>().toInstance(nodeReferenceGraph) } } |