From dcd84d619665864b275591c93248f4637f6ee636 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 1 Jun 2018 21:42:34 +0300 Subject: Update bundled kotlin compiler to 1.2.60-dev-157 (cherry picked from commit efbcbd5) --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 64 ++++++++++++---------- 1 file changed, 34 insertions(+), 30 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index 5522d4f0..b2e4b490 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -131,32 +131,36 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } val resolverForProject = ResolverForProjectImpl( - "Dokka", - projectContext, - listOf(library, module), - { JvmAnalyzerFacade }, - { - when (it) { - library -> ModuleContent(emptyList(), GlobalSearchScope.notScope(sourcesScope)) - module -> ModuleContent(sourceFiles, sourcesScope) - else -> throw IllegalArgumentException("Unexpected module info") - } - }, - JvmPlatformParameters { - val file = (it as JavaClassImpl).psi.containingFile.virtualFile - if (file in sourcesScope) - module - else - library - }, - CompilerEnvironment, - packagePartProviderFactory = { info, content -> - JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { - addRoots(javaRoots) - } - }, - builtIns = builtIns, - modulePlatforms = { JvmPlatform.multiTargetPlatform } + "Dokka", + projectContext, + listOf(library, module), + { + when (it) { + library -> ModuleContent(it, emptyList(), GlobalSearchScope.notScope(sourcesScope)) + module -> ModuleContent(it, emptyList(), sourcesScope) + else -> throw IllegalArgumentException("Unexpected module info") + } + }, + { + JvmPlatform.multiTargetPlatform + }, + LanguageSettingsProvider.Default /* TODO: Fix this */, + { JvmAnalyzerFacade }, + + JvmPlatformParameters { + val file = (it as JavaClassImpl).psi.containingFile.virtualFile + if (file in sourcesScope) + module + else + library + }, + CompilerEnvironment, + packagePartProviderFactory = { content -> + JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { + addRoots(javaRoots) + } + }, + builtIns = builtIns ) resolverForProject.resolverForModule(library) // Required before module to initialize library properly @@ -241,6 +245,10 @@ fun contentRootFromPath(path: String): ContentRoot { class DokkaResolutionFacade(override val project: Project, override val moduleDescriptor: ModuleDescriptor, val resolverForModule: ResolverForModule) : ResolutionFacade { + override fun analyzeWithAllCompilerChecks(elements: Collection): AnalysisResult { + throw UnsupportedOperationException() + } + override fun tryGetFrontendService(element: PsiElement, serviceClass: Class): T? { return null } @@ -295,10 +303,6 @@ class DokkaResolutionFacade(override val project: Project, throw UnsupportedOperationException() } - override fun analyzeFullyAndGetResult(elements: Collection): AnalysisResult { - throw UnsupportedOperationException() - } - override fun getFrontendService(element: PsiElement, serviceClass: Class): T { throw UnsupportedOperationException() } -- cgit From d458983871a6fa6af10b86bc7529a8851a63b265 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 15 Dec 2017 00:16:10 +0300 Subject: [backport] Add class hierarchy for JLH Original: 33426ea --- core/src/main/kotlin/Model/DocumentationNode.kt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index da85cabf..897e3ad3 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -104,6 +104,12 @@ open class DocumentationNode(val name: String, val platforms: List get() = references(RefKind.Platform).map { it.to.name } + val supertypes: List + get() = references(RefKind.Superclass).map { it.to } + + val superclass: DocumentationNode? + get() = supertypes.find { it.kind == NodeKind.Class } + // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice fun addReferenceTo(to: DocumentationNode, kind: RefKind) { references.add(DocumentationReference(this, to, kind)) -- cgit From 59069606904d297a5b4c9a8a95ad88eb30f7fd4f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 20 Dec 2017 22:27:47 +0300 Subject: [backport] Make KotlinLanguageService render parameters Original: 7899f8e --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index f33c8c96..708facdb 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -17,6 +17,7 @@ class KotlinLanguageService : LanguageService { NodeKind.EnumItem, NodeKind.ExternalClass -> if (renderMode == RenderMode.FULL) identifier(node.name) + NodeKind.Parameter -> renderParameter(node, renderMode) NodeKind.TypeParameter -> renderTypeParameter(node, renderMode) NodeKind.Type, NodeKind.UpperBound -> renderType(node, renderMode) -- cgit From 63ab561b66974c52a7d13e0823bf94329c0cd7f7 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 15 Dec 2017 22:05:21 +0300 Subject: [backport] Make possible to generate signatures on output format side Original: 4469044 --- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 1 + .../main/kotlin/Kotlin/KotlinLanguageService.kt | 28 ++++++++++++---------- core/src/main/kotlin/Model/DocumentationNode.kt | 1 + 3 files changed, 17 insertions(+), 13 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 7b50fff5..99d4d888 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -234,6 +234,7 @@ class DocumentationBuilder val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(classifierDescriptor) if (externalLink != null) { node.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + node.append(DocumentationNode(classifierDescriptor.fqNameUnsafe.asString(), Content.Empty, NodeKind.QualifiedName), RefKind.Detail) } else { link(node, classifierDescriptor, if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link) diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 708facdb..b6f44716 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -48,8 +48,7 @@ class KotlinLanguageService : LanguageService { val typeParameter = functionWithTypeParameter.details(NodeKind.TypeParameter).first() if (functionWithTypeParameter.kind == NodeKind.Function) { renderFunction(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) - } - else { + } else { renderProperty(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) } } @@ -103,7 +102,7 @@ class KotlinLanguageService : LanguageService { fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) } - private class SummarizingMapper(val kind: ReceiverKind, val typeParameterName: String): SignatureMapper { + private class SummarizingMapper(val kind: ReceiverKind, val typeParameterName: String) : SignatureMapper { override fun renderReceiver(receiver: DocumentationNode, to: ContentBlock) { to.append(ContentIdentifier(kind.receiverName, IdentifierKind.SummarizedTypeName)) to.text("<$typeParameterName>") @@ -117,7 +116,7 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderList(nodes: List, separator: String = ", ", - noWrap: Boolean = false, renderItem: (T) -> Unit) { + noWrap: Boolean = false, renderItem: (T) -> Unit) { if (nodes.none()) return renderItem(nodes.first()) @@ -132,7 +131,7 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderLinked(node: DocumentationNode, body: ContentBlock.(DocumentationNode)->Unit) { + private fun ContentBlock.renderLinked(node: DocumentationNode, body: ContentBlock.(DocumentationNode) -> Unit) { val to = node.links.firstOrNull() if (to == null) body(node) @@ -216,13 +215,13 @@ class KotlinLanguageService : LanguageService { private fun ContentBlock.renderModifier(node: DocumentationNode, nowrap: Boolean = false) { when (node.name) { - "final", "public", "var" -> {} + "final", "public", "var" -> { + } else -> { keyword(node.name) if (nowrap) { nbsp() - } - else { + } else { text(" ") } } @@ -239,11 +238,12 @@ class KotlinLanguageService : LanguageService { nbsp() symbol(":") nbsp() - renderList(constraints, noWrap=true) { + renderList(constraints, noWrap = true) { renderType(it, renderMode) } } } + private fun ContentBlock.renderParameter(node: DocumentationNode, renderMode: RenderMode) { if (renderMode == RenderMode.FULL) { renderAnnotationsForNode(node) @@ -402,8 +402,7 @@ class KotlinLanguageService : LanguageService { symbol(")") symbol(": ") renderType(node.detail(NodeKind.Type), renderMode) - } - else { + } else { symbol(")") } renderExtraTypeParameterConstraints(node, renderMode) @@ -429,7 +428,7 @@ class KotlinLanguageService : LanguageService { } } - private fun needReturnType(node: DocumentationNode) = when(node.kind) { + private fun needReturnType(node: DocumentationNode) = when (node.kind) { NodeKind.Constructor -> false else -> !node.isUnitReturnType() } @@ -476,4 +475,7 @@ class KotlinLanguageService : LanguageService { } } -fun DocumentationNode.qualifiedNameFromType() = (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() ?: name +fun DocumentationNode.qualifiedNameFromType() = + details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name + ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() + ?: name diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 897e3ad3..4b108798 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -48,6 +48,7 @@ enum class NodeKind { Signature, ExternalLink, + QualifiedName, Platform, AllTypes, -- cgit From e4d3abee285844c002a8984efbae0bf0be23d237 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 28 Dec 2017 19:44:56 +0300 Subject: Build supertypes via Supertype nodes, not reference --- core/src/main/kotlin/Model/DocumentationNode.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 4b108798..813ff0f5 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -106,10 +107,10 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Platform).map { it.to.name } val supertypes: List - get() = references(RefKind.Superclass).map { it.to } + get() = details(NodeKind.Supertype) val superclass: DocumentationNode? - get() = supertypes.find { it.kind == NodeKind.Class } + get() = supertypes.firstNotNullResult { it.links.firstOrNull { it.kind in NodeKind.classLike } } // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice fun addReferenceTo(to: DocumentationNode, kind: RefKind) { -- cgit From 93ce43340730111df977921e62cae93c2bcc4a5b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 28 Dec 2017 20:27:28 +0300 Subject: [backport] Add uri.relativeTo Original: cca63f7 --- core/src/main/kotlin/Utilities/Uri.kt | 40 +++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 core/src/main/kotlin/Utilities/Uri.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Utilities/Uri.kt b/core/src/main/kotlin/Utilities/Uri.kt new file mode 100644 index 00000000..5b520188 --- /dev/null +++ b/core/src/main/kotlin/Utilities/Uri.kt @@ -0,0 +1,40 @@ +package org.jetbrains.dokka + +import java.net.URI + + +fun URI.relativeTo(uri: URI): URI { + // Normalize paths to remove . and .. segments + val base = uri.normalize() + val child = this.normalize() + + fun StringBuilder.appendRelativePath() { + // Split paths into segments + var bParts = base.path.split('/').dropLastWhile { it.isEmpty() } + val cParts = child.path.split('/').dropLastWhile { it.isEmpty() } + + // Discard trailing segment of base path + if (bParts.isNotEmpty() && !base.path.endsWith("/")) { + bParts = bParts.dropLast(1) + } + + // Compute common prefix + val commonPartsSize = bParts.zip(cParts).count { (basePart, childPart) -> basePart == childPart } + bParts.drop(commonPartsSize).joinTo(this, separator = "") { "../" } + cParts.drop(commonPartsSize).joinTo(this, separator = "/") + } + + return URI.create(buildString { + if (base.path != child.path) { + appendRelativePath() + } + child.rawQuery?.let { + append("?") + append(it) + } + child.rawFragment?.let { + append("#") + append(it) + } + }) +} \ No newline at end of file -- cgit From 87705bf24f6f7e541dbdb14c44e00d0b90a81f37 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 28 Dec 2017 21:23:27 +0300 Subject: [backport] Add package list support for JLH Original: 4256adf --- .../JavaLayoutHtmlPackageListService.kt | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt new file mode 100644 index 00000000..398758f2 --- /dev/null +++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt @@ -0,0 +1,28 @@ +package org.jetbrains.dokka.Formats + +import org.jetbrains.dokka.DocumentationModule +import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX +import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.PackageListService + +class JavaLayoutHtmlPackageListService: PackageListService { + + private fun StringBuilder.appendParam(name: String, value: String) { + append(DOKKA_PARAM_PREFIX) + append(name) + append(":") + appendln(value) + } + + override fun formatPackageList(module: DocumentationModule): String { + val packages = module.members(NodeKind.Package).map { it.name } + + return buildString { + appendParam("format", "java-layout-html") + for (p in packages) { + appendln(p) + } + } + } + +} \ No newline at end of file -- cgit From bd30fa4c84d749976568be00307297ab015d9b2e Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sun, 7 Jan 2018 01:49:34 +0300 Subject: [backport] Show type parameters substitution in class hierarchy Original: a06d6a8 --- core/src/main/kotlin/Model/DocumentationNode.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 813ff0f5..a145ae8d 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -110,7 +109,7 @@ open class DocumentationNode(val name: String, get() = details(NodeKind.Supertype) val superclass: DocumentationNode? - get() = supertypes.firstNotNullResult { it.links.firstOrNull { it.kind in NodeKind.classLike } } + get() = supertypes.firstOrNull { it.links.any { it.kind in NodeKind.classLike } } // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice fun addReferenceTo(to: DocumentationNode, kind: RefKind) { @@ -163,7 +162,7 @@ val DocumentationNode.path: List } fun DocumentationNode.findOrCreatePackageNode(packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { - val existingNode = members(NodeKind.Package).firstOrNull { it.name == packageName } + val existingNode = members(NodeKind.Package).firstOrNull { it.name == packageName } if (existingNode != null) { return existingNode } @@ -181,7 +180,8 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) { RefKind.Detail -> child.addReferenceTo(this, RefKind.Owner) RefKind.Member -> child.addReferenceTo(this, RefKind.Owner) RefKind.Owner -> child.addReferenceTo(this, RefKind.Member) - else -> { /* Do not add any links back for other types */ } + else -> { /* Do not add any links back for other types */ + } } } -- cgit From c776aaab9af80987e3c073a40f92de748dbd38ca Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 11 Jan 2018 22:22:36 +0300 Subject: [backport] Support deep inheritance with external classes Original: 9e65c3d --- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 70 ++++++++++++++-------- .../main/kotlin/Kotlin/KotlinLanguageService.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 19 +++++- .../main/kotlin/Model/DocumentationReference.kt | 3 +- core/src/test/kotlin/TestAPI.kt | 48 ++++++++------- core/src/test/kotlin/model/JavaTest.kt | 2 +- 6 files changed, 92 insertions(+), 52 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 99d4d888..11a36a4f 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -103,6 +103,10 @@ interface DefaultPlatformsProvider { fun getDefaultPlatforms(descriptor: DeclarationDescriptor): List } +val ignoredSupertypes = setOf( + "kotlin.Annotation", "kotlin.Enum", "kotlin.Any" +) + class DocumentationBuilder @Inject constructor(val resolutionFacade: DokkaResolutionFacade, val descriptorDocumentationParser: DescriptorDocumentationParser, @@ -173,7 +177,7 @@ class DocumentationBuilder val unwrappedType = superType.unwrap() if (unwrappedType is AbbreviatedType) { appendSupertype(descriptor, unwrappedType.abbreviation) - } else if (!ignoreSupertype(unwrappedType)) { + } else { appendType(unwrappedType, NodeKind.Supertype) val superclass = unwrappedType.constructor.declarationDescriptor link(superclass, descriptor, RefKind.Inheritor) @@ -181,15 +185,6 @@ class DocumentationBuilder } } - private fun ignoreSupertype(superType: KotlinType): Boolean { - val superClass = superType.constructor.declarationDescriptor as? ClassDescriptor - if (superClass != null) { - val fqName = DescriptorUtils.getFqNameSafe(superClass).asString() - return fqName == "kotlin.Annotation" || fqName == "kotlin.Enum" || fqName == "kotlin.Any" - } - return false - } - fun DocumentationNode.appendProjection(projection: TypeProjection, kind: NodeKind = NodeKind.Type) { if (projection.isStarProjection) { appendTextNode("*", NodeKind.Type) @@ -233,14 +228,25 @@ class DocumentationBuilder if (classifierDescriptor != null) { 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(DocumentationNode(classifierDescriptor.fqNameUnsafe.asString(), Content.Empty, NodeKind.QualifiedName), RefKind.Detail) + node.append(targetNode, RefKind.ExternalType) } else { link(node, classifierDescriptor, if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link) } + if (classifierDescriptor !is TypeParameterDescriptor) { + node.append( + DocumentationNode( + classifierDescriptor.fqNameUnsafe.asString(), + Content.Empty, + NodeKind.QualifiedName + ), RefKind.Detail + ) + } } + append(node, RefKind.Detail) node.appendAnnotations(kotlinType) for (typeArgument in kotlinType.arguments) { @@ -496,34 +502,42 @@ class DocumentationBuilder } fun DeclarationDescriptor.build(): DocumentationNode = when (this) { - is ClassDescriptor -> build() + is ClassifierDescriptor -> build() is ConstructorDescriptor -> build() is PropertyDescriptor -> build() is FunctionDescriptor -> build() - is TypeParameterDescriptor -> build() is ValueParameterDescriptor -> build() is ReceiverParameterDescriptor -> build() - is TypeAliasDescriptor -> build() else -> throw IllegalStateException("Descriptor $this is not known") } - fun TypeAliasDescriptor.build(): DocumentationNode { + fun ClassifierDescriptor.build(external: Boolean = false): DocumentationNode = when (this) { + is ClassDescriptor -> build(external) + is TypeAliasDescriptor -> build(external) + is TypeParameterDescriptor -> build() + else -> throw IllegalStateException("Descriptor $this is not known") + } + + fun TypeAliasDescriptor.build(external: Boolean = false): DocumentationNode { val node = nodeForDescriptor(this, NodeKind.TypeAlias) - node.appendAnnotations(this) + if (!external) { + node.appendAnnotations(this) + } node.appendModifiers(this) node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) node.appendType(underlyingType, NodeKind.TypeAliasUnderlyingType) - node.appendSourceLink(source) - node.appendDefaultPlatforms(this) - + if (!external) { + node.appendSourceLink(source) + node.appendDefaultPlatforms(this) + } register(this, node) return node } - fun ClassDescriptor.build(): DocumentationNode { + fun ClassDescriptor.build(external: Boolean = false): DocumentationNode { val kind = when { kind == ClassKind.OBJECT -> NodeKind.Object kind == ClassKind.INTERFACE -> NodeKind.Interface @@ -534,20 +548,24 @@ class DocumentationBuilder else -> NodeKind.Class } val node = nodeForDescriptor(this, kind) + register(this, node) typeConstructor.supertypes.forEach { node.appendSupertype(this, it) } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) } - for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) { - node.appendClassMember(descriptor, inheritedLinkKind, extraModifier) + if (!external) { + for ((descriptor, inheritedLinkKind, extraModifier) in collectMembersToDocument()) { + node.appendClassMember(descriptor, inheritedLinkKind, extraModifier) + } + node.appendAnnotations(this) } - node.appendAnnotations(this) node.appendModifiers(this) - node.appendSourceLink(source) - node.appendDefaultPlatforms(this) - register(this, node) + if (!external) { + node.appendSourceLink(source) + node.appendDefaultPlatforms(this) + } return node } diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index b6f44716..aa185de7 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -291,7 +291,7 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderSupertypesForNode(node: DocumentationNode, renderMode: RenderMode) { - val supertypes = node.details(NodeKind.Supertype) + val supertypes = node.details(NodeKind.Supertype).filterNot { it.qualifiedNameFromType() in ignoredSupertypes } if (supertypes.any()) { nbsp() symbol(":") diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a145ae8d..a792460f 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -104,12 +104,27 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Deprecation).singleOrNull()?.to val platforms: List get() = references(RefKind.Platform).map { it.to.name } + val externalType: DocumentationNode? + get() = references(RefKind.ExternalType).map { it.to }.firstOrNull() val supertypes: List get() = details(NodeKind.Supertype) - val superclass: DocumentationNode? - get() = supertypes.firstOrNull { it.links.any { it.kind in NodeKind.classLike } } + val superclassType: DocumentationNode? + get() = when (kind) { + NodeKind.Supertype -> (links.firstOrNull { it.kind in NodeKind.classLike } ?: externalType)?.superclassType + NodeKind.Interface -> null + in NodeKind.classLike -> supertypes.firstOrNull { + it.links.any { it.kind in NodeKind.classLike } || + it.externalType != null + } + else -> null + } + + val superclassTypeSequence: Sequence + get() = generateSequence(superclassType) { + it.superclassType + } // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice fun addReferenceTo(to: DocumentationNode, kind: RefKind) { diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index a968f400..b0f011be 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -18,7 +18,8 @@ enum class RefKind { HiddenAnnotation, Deprecation, TopLevelPage, - Platform + Platform, + ExternalType } data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: RefKind) { diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index aa3eff48..559b715e 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -6,7 +6,6 @@ import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* -import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity @@ -25,6 +24,7 @@ fun verifyModel(vararg roots: ContentRoot, format: String = "html", includeNonPublic: Boolean = true, perPackageOptions: List = emptyList(), + noStdlibLink: Boolean = true, verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") @@ -37,7 +37,7 @@ fun verifyModel(vararg roots: ContentRoot, sourceLinks = listOf(), perPackageOptions = perPackageOptions, generateIndexPages = false, - noStdlibLink = true, + noStdlibLink = noStdlibLink, cacheRoot = "default", languageVersion = null, apiVersion = null @@ -161,13 +161,15 @@ fun verifyOutput(roots: Array, withKotlinRuntime: Boolean = false, format: String = "html", includeNonPublic: Boolean = true, + noStdlibLink: Boolean = true, outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { verifyModel( - *roots, - withJdk = withJdk, - withKotlinRuntime = withKotlinRuntime, - format = format, - includeNonPublic = includeNonPublic + *roots, + withJdk = withJdk, + withKotlinRuntime = withKotlinRuntime, + format = format, + includeNonPublic = includeNonPublic, + noStdlibLink = noStdlibLink ) { verifyModelOutput(it, outputExtension, roots.first().path, outputGenerator) } @@ -184,21 +186,25 @@ fun verifyModelOutput(it: DocumentationModule, assertEqualsIgnoringSeparators(expectedFile, output.toString()) } -fun verifyOutput(path: String, - outputExtension: String, - withJdk: Boolean = false, - withKotlinRuntime: Boolean = false, - format: String = "html", - includeNonPublic: Boolean = true, - outputGenerator: (DocumentationModule, StringBuilder) -> Unit) { +fun verifyOutput( + path: String, + outputExtension: String, + withJdk: Boolean = false, + withKotlinRuntime: Boolean = false, + format: String = "html", + includeNonPublic: Boolean = true, + noStdlibLink: Boolean = true, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit +) { verifyOutput( - arrayOf(contentRootFromPath(path)), - outputExtension, - withJdk, - withKotlinRuntime, - format, - includeNonPublic, - outputGenerator + arrayOf(contentRootFromPath(path)), + outputExtension, + withJdk, + withKotlinRuntime, + format, + includeNonPublic, + noStdlibLink, + outputGenerator ) } diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index e6c22ee4..c2ede8f0 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -193,7 +193,7 @@ public class JavaTest { @Test fun enumValues() { verifyJavaPackageMember("testdata/java/enumValues.java") { cls -> val superTypes = cls.details(NodeKind.Supertype) - assertEquals(0, superTypes.size) + assertEquals(1, superTypes.size) assertEquals(1, cls.members(NodeKind.EnumItem).size) } } -- cgit From 1391dcca35a871881420c53755fed08bf47e4087 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 17 Jan 2018 20:01:20 +0300 Subject: [backport] Support propagating inherited extensions from libraries Original: bf2945d --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 3 +- core/src/main/kotlin/Generation/DokkaGenerator.kt | 2 + .../main/kotlin/Generation/configurationImpl.kt | 47 ++--- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 200 ++++++++++++++++----- .../Kotlin/ExternalDocumentationLinkResolver.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 2 + core/src/test/kotlin/TestAPI.kt | 32 ++-- .../kotlin/org/jetbrains/dokka/configuration.kt | 48 ++--- runners/cli/src/main/kotlin/cli/main.kt | 28 +-- runners/gradle-plugin/src/main/kotlin/main.kt | 51 +++--- 10 files changed, 273 insertions(+), 142 deletions(-) (limited to 'core/src/main/kotlin') 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, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - 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, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String? + override val moduleName: String, + override val classpath: List, + override val sourceRoots: List, + override val samples: List, + override val includes: List, + 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, + override val impliedPlatforms: List, + override val perPackageOptions: List, + override val externalDocumentationLinks: List, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List, + 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 = emptySet()) { + val suppressedFiles: Set = 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 nodeForDescriptor(descriptor: T, kind: NodeKind): DocumentationNode where T : DeclarationDescriptor, T : Named { - val (doc, callback) = descriptorDocumentationParser.parseDocumentationAndDetails(descriptor, kind == NodeKind.Parameter) + fun 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) { - val allDescriptors = fragments.flatMap { it.getMemberScope().getContributedDescriptors() } - val allClasses = allDescriptors.filterIsInstance() - val classHierarchy = buildClassHierarchy(allClasses) + fun propagateExtensionFunctionsToSubclasses( + fragments: Collection, + 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() + + val classHierarchy = buildClassHierarchy(documentingClasses) + + val allExtensionFunctions = + allDescriptors .filterIsInstance() .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): Map> { @@ -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 = 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, 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, 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 + 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, - override val sourceRoots: List, - override val samples: List, - override val includes: List, - 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, - override val impliedPlatforms: List, - override val perPackageOptions: List, - override val externalDocumentationLinks: List, - override val noStdlibLink: Boolean, - override val cacheRoot: String?, - override val suppressedFiles: List, - override val languageVersion: String?, - override val apiVersion: String? + override val moduleName: String, + override val classpath: List, + override val sourceRoots: List, + override val samples: List, + override val includes: List, + 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, + override val impliedPlatforms: List, + override val perPackageOptions: List, + override val externalDocumentationLinks: List, + override val noStdlibLink: Boolean, + override val cacheRoot: String?, + override val suppressedFiles: List, + 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( -- cgit From 2f1512f5ec7f23181cf5fcad96d9ee66507de472 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 20 Jan 2018 16:44:35 +0300 Subject: [backport] Add value for constants from Kotlin Original: fab0890 --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 125f9fd4..39202173 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.KtVariableDeclaration import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.* @@ -781,6 +782,11 @@ class DocumentationBuilder if (isVar) { node.appendTextNode("var", NodeKind.Modifier) } + if (isConst) { + val psi = sourcePsi() as? KtVariableDeclaration + val text = psi?.initializer?.text + text?.let { node.appendTextNode(it, NodeKind.Value) } + } getter?.let { if (!it.isDefault) { -- cgit From 85d2ea3a100001d3e5555786202e64ef3ea1679e Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 20 Jan 2018 17:26:00 +0300 Subject: [backport] Support constants from Java in KK mode Original: 7723826 --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 39202173..d22c48f9 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiField import com.intellij.psi.PsiJavaFile import org.jetbrains.dokka.DokkaConfiguration.* import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser @@ -782,12 +783,18 @@ class DocumentationBuilder if (isVar) { node.appendTextNode("var", NodeKind.Modifier) } + if (isConst) { - val psi = sourcePsi() as? KtVariableDeclaration - val text = psi?.initializer?.text - text?.let { node.appendTextNode(it, NodeKind.Value) } + val psi = sourcePsi() + val valueText = when (psi) { + is KtVariableDeclaration -> psi.initializer?.text + is PsiField -> psi.initializer?.text + else -> null + } + valueText?.let { node.appendTextNode(it, NodeKind.Value) } } + getter?.let { if (!it.isDefault) { node.addAccessorDocumentation(descriptorDocumentationParser.parseDocumentation(it), "Getter") -- cgit From f1252678883133709f13fa2d6b7adbce3156f112 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 31 Jan 2018 23:49:51 +0300 Subject: Refactor selecting of inbound link resolvers --- .../Kotlin/ExternalDocumentationLinkResolver.kt | 43 +++++++++++++++++----- core/src/main/kotlin/Utilities/ServiceLocator.kt | 16 ++++++-- .../inbound-link-resolver/dokka-default.properties | 2 + .../dokka/inbound-link-resolver/javadoc.properties | 2 + 4 files changed, 51 insertions(+), 12 deletions(-) create mode 100644 core/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties create mode 100644 core/src/main/resources/dokka/inbound-link-resolver/javadoc.properties (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 400326d2..7be37177 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -4,6 +4,10 @@ import com.google.inject.Inject import com.google.inject.Singleton import com.intellij.psi.PsiMethod import com.intellij.util.io.* +import org.jetbrains.dokka.Formats.FileGeneratorBasedFormatDescriptor +import org.jetbrains.dokka.Formats.FormatDescriptor +import org.jetbrains.dokka.Utilities.ServiceLocator +import org.jetbrains.dokka.Utilities.lookup import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor @@ -21,6 +25,7 @@ import java.net.URL import java.net.URLConnection import java.nio.file.Path import java.security.MessageDigest +import kotlin.reflect.full.findAnnotation fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) } @@ -129,13 +134,22 @@ class ExternalDocumentationLinkResolver @Inject constructor( .map { (key, value) -> key to value } .toMap() - val resolver = if (format == "javadoc") { - InboundExternalLinkResolutionService.Javadoc() - } else { - val linkExtension = paramsMap["linkExtension"]?.singleOrNull() ?: - throw RuntimeException("Failed to parse package list from $packageListUrl") - InboundExternalLinkResolutionService.Dokka(linkExtension) - } + + val defaultResolverDesc = services["dokka-default"]!! + val resolverDesc = services[format] + ?: defaultResolverDesc.takeIf { format in formatsWithDefaultResolver } + ?: defaultResolverDesc.also { + logger.warn("Couldn't find InboundExternalLinkResolutionService(format = `$format`) for $link, using Dokka default") + } + + + val resolverClass = javaClass.classLoader.loadClass(resolverDesc.className).kotlin + + val constructors = resolverClass.constructors + + val constructor = constructors.singleOrNull() + ?: constructors.first { it.findAnnotation() != null } + val resolver = constructor.call(paramsMap) as InboundExternalLinkResolutionService val rootInfo = ExternalDocumentationRoot(link.url, resolver, locations) @@ -170,6 +184,15 @@ class ExternalDocumentationLinkResolver @Inject constructor( companion object { const val DOKKA_PARAM_PREFIX = "\$dokka." + val services = ServiceLocator.allServices("inbound-link-resolver").associateBy { it.name } + private val formatsWithDefaultResolver = + ServiceLocator + .allServices("format") + .filter { + val desc = ServiceLocator.lookup(it) as? FileGeneratorBasedFormatDescriptor + desc?.generatorServiceClass == FileGenerator::class + }.map { it.name } + .toSet() } } @@ -177,7 +200,7 @@ class ExternalDocumentationLinkResolver @Inject constructor( interface InboundExternalLinkResolutionService { fun getPath(symbol: DeclarationDescriptor): String? - class Javadoc : InboundExternalLinkResolutionService { + class Javadoc(paramsMap: Map>) : InboundExternalLinkResolutionService { override fun getPath(symbol: DeclarationDescriptor): String? { if (symbol is EnumEntrySyntheticClassDescriptor) { return getPath(symbol.containingDeclaration)?.let { it + "#" + symbol.name.asString() } @@ -203,7 +226,9 @@ interface InboundExternalLinkResolutionService { } } - class Dokka(val extension: String) : InboundExternalLinkResolutionService { + class Dokka(val paramsMap: Map>) : InboundExternalLinkResolutionService { + val extension = paramsMap["linkExtension"]?.singleOrNull() ?: error("linkExtension not provided for Dokka resolver") + override fun getPath(symbol: DeclarationDescriptor): String? { val leafElement = when (symbol) { is CallableDescriptor, is TypeAliasDescriptor -> true diff --git a/core/src/main/kotlin/Utilities/ServiceLocator.kt b/core/src/main/kotlin/Utilities/ServiceLocator.kt index 71bfd21b..83c4c65c 100644 --- a/core/src/main/kotlin/Utilities/ServiceLocator.kt +++ b/core/src/main/kotlin/Utilities/ServiceLocator.kt @@ -14,12 +14,21 @@ class ServiceLookupException(message: String) : Exception(message) object ServiceLocator { fun lookup(clazz: Class, category: String, implementationName: String): T { val descriptor = lookupDescriptor(category, implementationName) + return lookup(clazz, descriptor) + } + + fun lookup( + clazz: Class, + descriptor: ServiceDescriptor + ): T { val loadedClass = javaClass.classLoader.loadClass(descriptor.className) val constructor = loadedClass.constructors - .filter { it.parameterTypes.isEmpty() } - .firstOrNull() ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor") + .filter { it.parameterTypes.isEmpty() } + .firstOrNull() + ?: throw ServiceLookupException("Class ${descriptor.className} has no corresponding constructor") - val implementationRawType: Any = if (constructor.parameterTypes.isEmpty()) constructor.newInstance() else constructor.newInstance(constructor) + val implementationRawType: Any = + if (constructor.parameterTypes.isEmpty()) constructor.newInstance() else constructor.newInstance(constructor) if (!clazz.isInstance(implementationRawType)) { throw ServiceLookupException("Class ${descriptor.className} is not a subtype of ${clazz.name}") @@ -79,6 +88,7 @@ object ServiceLocator { } inline fun ServiceLocator.lookup(category: String, implementationName: String): T = lookup(T::class.java, category, implementationName) +inline fun ServiceLocator.lookup(desc: ServiceDescriptor): T = lookup(T::class.java, desc) private val ZipEntry.fileName: String get() = name.substringAfterLast("/", name) diff --git a/core/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties b/core/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties new file mode 100644 index 00000000..c484a920 --- /dev/null +++ b/core/src/main/resources/dokka/inbound-link-resolver/dokka-default.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.InboundExternalLinkResolutionService$Dokka +description=Uses Dokka Default resolver \ No newline at end of file diff --git a/core/src/main/resources/dokka/inbound-link-resolver/javadoc.properties b/core/src/main/resources/dokka/inbound-link-resolver/javadoc.properties new file mode 100644 index 00000000..0d5d7d17 --- /dev/null +++ b/core/src/main/resources/dokka/inbound-link-resolver/javadoc.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.InboundExternalLinkResolutionService$Javadoc +description=Uses Javadoc Default resolver \ No newline at end of file -- cgit From 71ef970eacfab2fd948ab3fba9aa01808cb7b211 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 1 Feb 2018 19:02:33 +0300 Subject: [backport] Implement inbound links in java layout html Original: 4641470 --- .../JavaLayoutHtmlPackageListService.kt | 86 ++++++++++++++++++++++ .../java-layout-html.properties | 2 + 2 files changed, 88 insertions(+) create mode 100644 core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt index 398758f2..d04ed64b 100644 --- a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt +++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt @@ -2,8 +2,13 @@ package org.jetbrains.dokka.Formats import org.jetbrains.dokka.DocumentationModule import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX +import org.jetbrains.dokka.InboundExternalLinkResolutionService import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.PackageListService +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject +import org.jetbrains.kotlin.types.KotlinType class JavaLayoutHtmlPackageListService: PackageListService { @@ -19,10 +24,91 @@ class JavaLayoutHtmlPackageListService: PackageListService { return buildString { appendParam("format", "java-layout-html") + appendParam("mode", "kotlin") for (p in packages) { appendln(p) } } } +} + +class JavaLayoutHtmlInboundLinkResolutionService(private val paramMap: Map>) : InboundExternalLinkResolutionService { + private fun getContainerPath(symbol: DeclarationDescriptor): String? { + return when (symbol) { + is PackageFragmentDescriptor -> symbol.fqName.asString() + "/" + is ClassifierDescriptor -> getContainerPath(symbol.findPackage()) + symbol.nameWithOuter() + ".html" + else -> null + } + } + + private fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor = + generateSequence(this) { it.containingDeclaration }.filterIsInstance().first() + + private fun ClassifierDescriptor.nameWithOuter(): String = + generateSequence(this) { it.containingDeclaration as? ClassifierDescriptor } + .toList().asReversed().joinToString(".") { it.name.asString() } + + private fun getPagePath(symbol: DeclarationDescriptor): String? { + return when (symbol) { + is PackageFragmentDescriptor -> getContainerPath(symbol) + "package-summary.html" + is ClassifierDescriptor -> getContainerPath(symbol) + "#" + is FunctionDescriptor, is PropertyDescriptor -> getContainerPath(symbol.containingDeclaration!!) + "#" + symbol.signatureForAnchorUrlEncoded() + else -> null + } + } + + private fun DeclarationDescriptor.signatureForAnchor(): String? { + + fun ReceiverParameterDescriptor.extractReceiverName(): String { + var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!! + if (receiverClass.isCompanionObject()) { + receiverClass = receiverClass.containingDeclaration!! + } else if (receiverClass is TypeParameterDescriptor) { + val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor + if (upperBoundClass != null) { + receiverClass = upperBoundClass + } + } + + return receiverClass.name.asString() + } + + fun KotlinType.qualifiedNameForSignature(): String { + val desc = constructor.declarationDescriptor + return desc?.fqNameUnsafe?.asString() ?: "" + } + + fun StringBuilder.appendReceiverAndCompanion(desc: CallableDescriptor) { + if (desc.containingDeclaration.isCompanionObject()) { + append("Companion.") + } + desc.extensionReceiverParameter?.let { + append("(") + append(it.extractReceiverName()) + append(").") + } + } + + return when(this) { + is FunctionDescriptor -> buildString { + appendReceiverAndCompanion(this@signatureForAnchor) + append(name.asString()) + valueParameters.joinTo(this, prefix = "(", postfix = ")") { + it.type.qualifiedNameForSignature() + } + } + is PropertyDescriptor -> buildString { + appendReceiverAndCompanion(this@signatureForAnchor) + append(name.asString()) + append(":") + append(returnType?.qualifiedNameForSignature()) + } + else -> null + } + } + + private fun DeclarationDescriptor.signatureForAnchorUrlEncoded(): String? = signatureForAnchor()?.urlEncoded() + + override fun getPath(symbol: DeclarationDescriptor) = getPagePath(symbol) } \ No newline at end of file diff --git a/core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties b/core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties new file mode 100644 index 00000000..3b61eabe --- /dev/null +++ b/core/src/main/resources/dokka/inbound-link-resolver/java-layout-html.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.Formats.JavaLayoutHtmlInboundLinkResolutionService +description=Resolver for JavaLayoutHtml \ No newline at end of file -- cgit From 3e8448bf5d3f00cfaa7d4d6b4fbbf678aebc37b7 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 12 Apr 2018 03:06:15 +0300 Subject: [backport] Make possible to group extensions by receiver Original: d8e03a3 --- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index d22c48f9..d7d30ebb 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -934,6 +934,30 @@ class DocumentationBuilder DocumentationNode(valueString, Content.Empty, NodeKind.Value) } } + + + fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor, + externalClassNodes: MutableMap, + allFqNames: Collection): DocumentationNode { + if (descriptor is CallableMemberDescriptor) { + val extensionClassDescriptor = descriptor.getExtensionClassDescriptor() + if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) && + !ErrorUtils.isError(extensionClassDescriptor)) { + val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor) + return externalClassNodes.getOrPut(fqName, { + val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass) + val externalLink = linkResolver.externalDocumentationLinkResolver.buildExternalDocumentationLink(extensionClassDescriptor) + if (externalLink != null) { + newNode.append(DocumentationNode(externalLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link) + } + append(newNode, RefKind.Member) + newNode + }) + } + } + return this + } + } val visibleToDocumentation = setOf(Visibilities.PROTECTED, Visibilities.PUBLIC) @@ -1033,24 +1057,6 @@ fun DeclarationDescriptor.isDeprecated(): Boolean = annotations.any { DescriptorUtils.getFqName(it.type.constructor.declarationDescriptor!!).asString() == "kotlin.Deprecated" } || (this is ConstructorDescriptor && containingDeclaration.isDeprecated()) -fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor, - externalClassNodes: MutableMap, - allFqNames: Collection): DocumentationNode { - if (descriptor is CallableMemberDescriptor) { - val extensionClassDescriptor = descriptor.getExtensionClassDescriptor() - if (extensionClassDescriptor != null && isExtensionForExternalClass(descriptor, extensionClassDescriptor, allFqNames) && - !ErrorUtils.isError(extensionClassDescriptor)) { - val fqName = DescriptorUtils.getFqNameSafe(extensionClassDescriptor) - return externalClassNodes.getOrPut(fqName, { - val newNode = DocumentationNode(fqName.asString(), Content.Empty, NodeKind.ExternalClass) - append(newNode, RefKind.Member) - newNode - }) - } - } - return this -} - fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? { val extensionReceiver = extensionReceiverParameter if (extensionReceiver != null) { -- cgit From 8883839b8796589a1fa02b3dca5d1aae172b5c56 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 13 Apr 2018 19:47:07 +0300 Subject: [backport] Fix problems in as-java java-layout-html mode Extract common part of LanguageServices & other improvements Original: 853262e --- core/src/main/kotlin/Java/JavadocParser.kt | 43 +++-- .../main/kotlin/Kotlin/DeclarationLinkResolver.kt | 2 +- .../main/kotlin/Kotlin/KotlinLanguageService.kt | 164 ++++++++---------- .../main/kotlin/Languages/CommonLanguageService.kt | 65 +++++++ .../kotlin/Languages/NewJavaLanguageService.kt | 190 +++++++++++++++++++++ core/src/main/kotlin/Model/DocumentationNode.kt | 2 +- .../main/kotlin/Model/DocumentationReference.kt | 2 +- 7 files changed, 353 insertions(+), 115 deletions(-) create mode 100644 core/src/main/kotlin/Languages/CommonLanguageService.kt create mode 100644 core/src/main/kotlin/Languages/NewJavaLanguageService.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index c25f5813..db61a00a 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -20,8 +20,10 @@ interface JavaDocumentationParser { fun parseDocumentation(element: PsiNamedElement): JavadocParseResult } -class JavadocParser(private val refGraph: NodeReferenceGraph, - private val logger: DokkaLogger) : 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 @@ -31,7 +33,7 @@ class JavadocParser(private val refGraph: NodeReferenceGraph, result.append(para) para.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }) docComment.tags.forEach { tag -> - when(tag.name) { + when (tag.name) { "see" -> result.convertSeeTag(tag) "deprecated" -> { deprecatedContent = Content() @@ -50,9 +52,9 @@ class JavadocParser(private val refGraph: NodeReferenceGraph, private fun PsiDocTag.contentElements(): Iterable { val tagValueElements = children - .dropWhile { it.node?.elementType == JavaDocTokenType.DOC_TAG_NAME } - .dropWhile { it is PsiWhiteSpace } - .filterNot { it.node?.elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } + .dropWhile { it.node?.elementType == JavaDocTokenType.DOC_TAG_NAME } + .dropWhile { it is PsiWhiteSpace } + .filterNot { it.node?.elementType == JavaDocTokenType.DOC_COMMENT_LEADING_ASTERISKS } return if (getSubjectName() != null) tagValueElements.dropWhile { it is PsiDocTagValue } else tagValueElements } @@ -83,7 +85,7 @@ class JavadocParser(private val refGraph: NodeReferenceGraph, } } - private fun createBlock(element: Element): ContentBlock = when(element.tagName()) { + private fun createBlock(element: Element): ContentBlock = when (element.tagName()) { "p" -> ContentParagraph() "b", "strong" -> ContentStrong() "i", "em" -> ContentEmphasis() @@ -99,28 +101,26 @@ class JavadocParser(private val refGraph: NodeReferenceGraph, } private fun createLink(element: Element): ContentBlock { - val docref = element.attr("docref") - if (docref != null) { - return ContentNodeLazyLink(docref, { -> refGraph.lookupOrWarn(docref, logger)}) + if (element.hasAttr("docref")) { + val docref = element.attr("docref") + return ContentNodeLazyLink(docref, { -> refGraph.lookupOrWarn(docref, logger) }) } - val href = element.attr("href") - if (href != null) { - return ContentExternalLink(href) + return if (element.hasAttr("href")) { + val href = element.attr("href") + ContentExternalLink(href) } else { - return ContentBlock() + ContentBlock() } } private fun MutableContent.convertSeeTag(tag: PsiDocTag) { - val linkElement = tag.linkElement() - if (linkElement == null) { - return - } + val linkElement = tag.linkElement() ?: return val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) val linkSignature = resolveLink(linkElement) val text = ContentText(linkElement.text) if (linkSignature != null) { - val linkNode = ContentNodeLazyLink(tag.valueElement!!.text, { -> refGraph.lookupOrWarn(linkSignature, logger)}) + val linkNode = + ContentNodeLazyLink(tag.valueElement!!.text, { -> refGraph.lookupOrWarn(linkSignature, logger) }) linkNode.append(text) seeSection.append(linkNode) } else { @@ -136,8 +136,7 @@ class JavadocParser(private val refGraph: NodeReferenceGraph, val labelText = tag.dataElements.firstOrNull { it is PsiDocToken }?.text ?: valueElement!!.text val link = "${labelText.htmlEscape()}" if (tag.name == "link") "$link" else link - } - else if (valueElement != null) { + } else if (valueElement != null) { valueElement.text } else { "" @@ -153,7 +152,7 @@ class JavadocParser(private val refGraph: NodeReferenceGraph, } private fun PsiDocTag.linkElement(): PsiElement? = - valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } + valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } private fun resolveLink(valueElement: PsiElement?): String? { val target = valueElement?.reference?.resolve() diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index ffef399d..ec474900 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -41,7 +41,7 @@ class DeclarationLinkResolver val target = refGraph.lookup(signature) if (target == null) { - logger.warn("Can't find node by signature $signature, referenced at $referencedAt") + logger.warn("Can't find node by signature `$signature`, referenced at $referencedAt") } target }) diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index aa185de7..69a97848 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -5,8 +5,9 @@ import org.jetbrains.dokka.LanguageService.RenderMode /** * Implements [LanguageService] and provides rendering of symbols in Kotlin language */ -class KotlinLanguageService : LanguageService { - private val fullOnlyModifiers = setOf("public", "protected", "private", "inline", "noinline", "crossinline", "reified") +class KotlinLanguageService : CommonLanguageService() { + private val fullOnlyModifiers = + setOf("public", "protected", "private", "inline", "noinline", "crossinline", "reified") override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode { return content { @@ -22,7 +23,7 @@ class KotlinLanguageService : LanguageService { NodeKind.Type, NodeKind.UpperBound -> renderType(node, renderMode) - NodeKind.Modifier -> renderModifier(node) + NodeKind.Modifier -> renderModifier(this, node) NodeKind.Constructor, NodeKind.Function, NodeKind.CompanionObjectFunction -> renderFunction(node, renderMode) @@ -33,12 +34,6 @@ class KotlinLanguageService : LanguageService { } } - override fun renderName(node: DocumentationNode): String { - return when (node.kind) { - NodeKind.Constructor -> node.owner!!.name - else -> node.name - } - } override fun summarizeSignatures(nodes: List): ContentNode? { if (nodes.size < 2) return null @@ -47,9 +42,17 @@ class KotlinLanguageService : LanguageService { return content { val typeParameter = functionWithTypeParameter.details(NodeKind.TypeParameter).first() if (functionWithTypeParameter.kind == NodeKind.Function) { - renderFunction(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) + renderFunction( + functionWithTypeParameter, + RenderMode.SUMMARY, + SummarizingMapper(receiverKind, typeParameter.name) + ) } else { - renderProperty(functionWithTypeParameter, RenderMode.SUMMARY, SummarizingMapper(receiverKind, typeParameter.name)) + renderProperty( + functionWithTypeParameter, + RenderMode.SUMMARY, + SummarizingMapper(receiverKind, typeParameter.name) + ) } } } @@ -70,26 +73,27 @@ class KotlinLanguageService : LanguageService { companion object { private val arrayClasses = setOf( - "kotlin.Array", - "kotlin.BooleanArray", - "kotlin.ByteArray", - "kotlin.CharArray", - "kotlin.ShortArray", - "kotlin.IntArray", - "kotlin.LongArray", - "kotlin.FloatArray", - "kotlin.DoubleArray" + "kotlin.Array", + "kotlin.BooleanArray", + "kotlin.ByteArray", + "kotlin.CharArray", + "kotlin.ShortArray", + "kotlin.IntArray", + "kotlin.LongArray", + "kotlin.FloatArray", + "kotlin.DoubleArray" ) private val arrayOrListClasses = setOf("kotlin.List") + arrayClasses private val iterableClasses = setOf( - "kotlin.Collection", - "kotlin.Sequence", - "kotlin.Iterable", - "kotlin.Map", - "kotlin.String", - "kotlin.CharSequence") + arrayOrListClasses + "kotlin.Collection", + "kotlin.Sequence", + "kotlin.Iterable", + "kotlin.Map", + "kotlin.String", + "kotlin.CharSequence" + ) + arrayOrListClasses } private enum class ReceiverKind(val receiverName: String, val classes: Collection) { @@ -109,46 +113,14 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderPackage(node: DocumentationNode) { - keyword("package") - text(" ") - identifier(node.name) - } - - private fun ContentBlock.renderList(nodes: List, separator: String = ", ", - noWrap: Boolean = false, renderItem: (T) -> Unit) { - if (nodes.none()) - return - renderItem(nodes.first()) - nodes.drop(1).forEach { - if (noWrap) { - symbol(separator.removeSuffix(" ")) - nbsp() - } else { - symbol(separator) - } - renderItem(it) - } - } - - private fun ContentBlock.renderLinked(node: DocumentationNode, body: ContentBlock.(DocumentationNode) -> Unit) { - val to = node.links.firstOrNull() - if (to == null) - body(node) - else - link(to) { - body(node) - } - } - private fun ContentBlock.renderFunctionalTypeParameterName(node: DocumentationNode, renderMode: RenderMode) { node.references(RefKind.HiddenAnnotation).map { it.to } - .find { it.name == "ParameterName" }?.let { - val parameterNameValue = it.detail(NodeKind.Parameter).detail(NodeKind.Value) - identifier(parameterNameValue.name.removeSurrounding("\""), IdentifierKind.ParameterName) - symbol(":") - nbsp() - } + .find { it.name == "ParameterName" }?.let { + val parameterNameValue = it.detail(NodeKind.Parameter).detail(NodeKind.Value) + identifier(parameterNameValue.name.removeSurrounding("\""), IdentifierKind.ParameterName) + symbol(":") + nbsp() + } } private fun ContentBlock.renderFunctionalType(node: DocumentationNode, renderMode: RenderMode) { @@ -198,7 +170,7 @@ class KotlinLanguageService : LanguageService { renderAnnotationsForNode(node) } renderModifiersForNode(node, renderMode, true) - renderLinked(node) { identifier(it.name, IdentifierKind.TypeName) } + renderLinked(this, node) { identifier(it.name, IdentifierKind.TypeName) } val typeArguments = node.details(NodeKind.Type) if (typeArguments.isNotEmpty()) { symbol("<") @@ -213,17 +185,16 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderModifier(node: DocumentationNode, nowrap: Boolean = false) { + override fun renderModifier( + block: ContentBlock, + node: DocumentationNode, + nowrap: Boolean + ) { when (node.name) { "final", "public", "var" -> { } else -> { - keyword(node.name) - if (nowrap) { - nbsp() - } else { - text(" ") - } + super.renderModifier(block, node, nowrap) } } } @@ -275,9 +246,12 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderExtraTypeParameterConstraints(node: DocumentationNode, renderMode: RenderMode) { - val parametersWithMultipleConstraints = node.details(NodeKind.TypeParameter).filter { it.details(NodeKind.UpperBound).size > 1 } + val parametersWithMultipleConstraints = + node.details(NodeKind.TypeParameter).filter { it.details(NodeKind.UpperBound).size > 1 } val parametersWithConstraints = parametersWithMultipleConstraints - .flatMap { parameter -> parameter.details(NodeKind.UpperBound).map { constraint -> parameter to constraint } } + .flatMap { parameter -> + parameter.details(NodeKind.UpperBound).map { constraint -> parameter to constraint } + } if (parametersWithMultipleConstraints.isNotEmpty()) { keyword(" where ") renderList(parametersWithConstraints) { @@ -303,9 +277,11 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderModifiersForNode(node: DocumentationNode, - renderMode: RenderMode, - nowrap: Boolean = false) { + private fun ContentBlock.renderModifiersForNode( + node: DocumentationNode, + renderMode: RenderMode, + nowrap: Boolean = false + ) { val modifiers = node.details(NodeKind.Modifier) for (it in modifiers) { if (node.kind == org.jetbrains.dokka.NodeKind.Interface && it.name == "abstract") @@ -313,7 +289,7 @@ class KotlinLanguageService : LanguageService { if (renderMode == RenderMode.SUMMARY && it.name in fullOnlyModifiers) { continue } - renderModifier(it, nowrap) + renderModifier(this, it, nowrap) } } @@ -366,9 +342,11 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderFunction(node: DocumentationNode, - renderMode: RenderMode, - signatureMapper: SignatureMapper? = null) { + private fun ContentBlock.renderFunction( + node: DocumentationNode, + renderMode: RenderMode, + signatureMapper: SignatureMapper? = null + ) { if (renderMode == RenderMode.FULL) { renderAnnotationsForNode(node) } @@ -408,7 +386,11 @@ class KotlinLanguageService : LanguageService { renderExtraTypeParameterConstraints(node, renderMode) } - private fun ContentBlock.renderReceiver(node: DocumentationNode, renderMode: RenderMode, signatureMapper: SignatureMapper?) { + private fun ContentBlock.renderReceiver( + node: DocumentationNode, + renderMode: RenderMode, + signatureMapper: SignatureMapper? + ) { val receiver = node.details(NodeKind.Receiver).singleOrNull() if (receiver != null) { if (signatureMapper != null) { @@ -434,11 +416,13 @@ class KotlinLanguageService : LanguageService { } fun DocumentationNode.isUnitReturnType(): Boolean = - detail(NodeKind.Type).hiddenLinks.firstOrNull()?.qualifiedName() == "kotlin.Unit" + detail(NodeKind.Type).hiddenLinks.firstOrNull()?.qualifiedName() == "kotlin.Unit" - private fun ContentBlock.renderProperty(node: DocumentationNode, - renderMode: RenderMode, - signatureMapper: SignatureMapper? = null) { + private fun ContentBlock.renderProperty( + node: DocumentationNode, + renderMode: RenderMode, + signatureMapper: SignatureMapper? = null + ) { if (renderMode == RenderMode.FULL) { renderAnnotationsForNode(node) } @@ -462,7 +446,7 @@ class KotlinLanguageService : LanguageService { } fun DocumentationNode.getPropertyKeyword() = - if (details(NodeKind.Modifier).any { it.name == "var" }) "var" else "val" + if (details(NodeKind.Modifier).any { it.name == "var" }) "var" else "val" fun ContentBlock.identifierOrDeprecated(node: DocumentationNode) { if (node.deprecation != null) { @@ -476,6 +460,6 @@ class KotlinLanguageService : LanguageService { } fun DocumentationNode.qualifiedNameFromType() = - details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name - ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() - ?: name + details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name + ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() + ?: name diff --git a/core/src/main/kotlin/Languages/CommonLanguageService.kt b/core/src/main/kotlin/Languages/CommonLanguageService.kt new file mode 100644 index 00000000..f155192d --- /dev/null +++ b/core/src/main/kotlin/Languages/CommonLanguageService.kt @@ -0,0 +1,65 @@ +package org.jetbrains.dokka + + +abstract class CommonLanguageService : LanguageService { + + protected fun ContentBlock.renderPackage(node: DocumentationNode) { + keyword("package") + nbsp() + identifier(node.name) + } + + override fun renderName(node: DocumentationNode): String { + return when (node.kind) { + NodeKind.Constructor -> node.owner!!.name + else -> node.name + } + } + + open fun renderModifier( + block: ContentBlock, + node: DocumentationNode, + nowrap: Boolean = false + ) = with(block) { + keyword(node.name) + if (nowrap) { + nbsp() + } else { + text(" ") + } + } + + protected fun renderLinked( + block: ContentBlock, + node: DocumentationNode, + body: ContentBlock.(DocumentationNode) -> Unit + ) = with(block) { + val to = node.links.firstOrNull() + if (to == null) + body(node) + else + link(to) { + this.body(node) + } + } + + protected fun ContentBlock.renderList( + nodes: List, separator: String = ", ", + noWrap: Boolean = false, renderItem: (T) -> Unit + ) { + if (nodes.none()) + return + renderItem(nodes.first()) + nodes.drop(1).forEach { + if (noWrap) { + symbol(separator.removeSuffix(" ")) + nbsp() + } else { + symbol(separator) + } + renderItem(it) + } + } + + +} \ No newline at end of file diff --git a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt new file mode 100644 index 00000000..22ad62b2 --- /dev/null +++ b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt @@ -0,0 +1,190 @@ +package org.jetbrains.dokka + +/** + * Implements [LanguageService] and provides rendering of symbols in Java language + */ +class NewJavaLanguageService : CommonLanguageService() { + override fun render(node: DocumentationNode, renderMode: LanguageService.RenderMode): ContentNode { + return content { + (when (node.kind) { + NodeKind.Package -> renderPackage(node) + in NodeKind.classLike -> renderClass(node) + + NodeKind.Modifier -> renderModifier(this, node) + NodeKind.TypeParameter -> renderTypeParameter(node) + NodeKind.Type, + NodeKind.UpperBound -> renderType(node) + + NodeKind.Constructor, + NodeKind.Function -> renderFunction(node) + NodeKind.Property -> renderProperty(node) + else -> "${node.kind}: ${node.name}" + }) + } + } + + override fun summarizeSignatures(nodes: List): ContentNode? = null + + + override fun renderModifier(block: ContentBlock, node: DocumentationNode, nowrap: Boolean) { + when (node.name) { + "open", "internal" -> { + } + else -> super.renderModifier(block, node, nowrap) + } + } + + fun getArrayElementType(node: DocumentationNode): DocumentationNode? = when (node.qualifiedName()) { + "kotlin.Array" -> + node.details(NodeKind.Type).singleOrNull()?.let { et -> getArrayElementType(et) ?: et } + ?: DocumentationNode("Object", node.content, NodeKind.ExternalClass) + + "kotlin.IntArray", "kotlin.LongArray", "kotlin.ShortArray", "kotlin.ByteArray", + "kotlin.CharArray", "kotlin.DoubleArray", "kotlin.FloatArray", "kotlin.BooleanArray" -> + DocumentationNode(node.name.removeSuffix("Array").toLowerCase(), node.content, NodeKind.Type) + + else -> null + } + + fun getArrayDimension(node: DocumentationNode): Int = when (node.qualifiedName()) { + "kotlin.Array" -> + 1 + (node.details(NodeKind.Type).singleOrNull()?.let { getArrayDimension(it) } ?: 0) + + "kotlin.IntArray", "kotlin.LongArray", "kotlin.ShortArray", "kotlin.ByteArray", + "kotlin.CharArray", "kotlin.DoubleArray", "kotlin.FloatArray", "kotlin.BooleanArray" -> + 1 + else -> 0 + } + + fun ContentBlock.renderType(node: DocumentationNode) { + when (node.name) { + "Unit" -> identifier("void") + "Int" -> identifier("int") + "Long" -> identifier("long") + "Double" -> identifier("double") + "Float" -> identifier("float") + "Char" -> identifier("char") + "Boolean" -> identifier("bool") + // TODO: render arrays + else -> renderLinked(this, node) { + identifier(node.name) + } + } + } + + private fun ContentBlock.renderTypeParameter(node: DocumentationNode) { + val constraints = node.details(NodeKind.UpperBound) + if (constraints.none()) + identifier(node.name) + else { + identifier(node.name) + text(" ") + keyword("extends") + text(" ") + constraints.forEach { renderType(node) } + } + } + + private fun ContentBlock.renderParameter(node: DocumentationNode) { + renderType(node.detail(NodeKind.Type)) + text(" ") + identifier(node.name) + } + + private fun ContentBlock.renderTypeParametersForNode(node: DocumentationNode) { + val typeParameters = node.details(NodeKind.TypeParameter) + if (typeParameters.any()) { + symbol("<") + renderList(typeParameters, noWrap = true) { + renderTypeParameter(it) + } + symbol(">") + text(" ") + } + } + +// private fun renderModifiersForNode(node: DocumentationNode): String { +// val modifiers = node.details(NodeKind.Modifier).map { renderModifier(it) }.filter { it != "" } +// if (modifiers.none()) +// return "" +// return modifiers.joinToString(" ", postfix = " ") +// } + + private fun ContentBlock.renderClassKind(node: DocumentationNode) { + when (node.kind) { + NodeKind.Interface -> { + keyword("interface") + } + NodeKind.EnumItem -> { + keyword("enum value") + } + NodeKind.Enum -> { + keyword("enum") + } + NodeKind.Class, NodeKind.Exception, NodeKind.Object -> { + keyword("class") + } + else -> throw IllegalArgumentException("Node $node is not a class-like object") + } + text(" ") + } + + private fun ContentBlock.renderClass(node: DocumentationNode) { + renderClassKind(node) + + identifier(node.name) + renderTypeParametersForNode(node) + } + + private fun ContentBlock.renderParameters(nodes: List) { + renderList(nodes) { + renderParameter(it) + } + } + + private fun ContentBlock.renderFunction(node: DocumentationNode) { + when (node.kind) { + NodeKind.Constructor -> identifier(node.owner?.name ?: "") + NodeKind.Function -> { + renderTypeParametersForNode(node) + renderType(node.detail(NodeKind.Type)) + text(" ") + identifier(node.name) + + } + else -> throw IllegalArgumentException("Node $node is not a function-like object") + } + + val receiver = node.details(NodeKind.Receiver).singleOrNull() + symbol("(") + if (receiver != null) + renderParameters(listOf(receiver) + node.details(NodeKind.Parameter)) + else + renderParameters(node.details(NodeKind.Parameter)) + + symbol(")") + } + + private fun ContentBlock.renderProperty(node: DocumentationNode) { + + when (node.kind) { + NodeKind.Property -> { + keyword("val") + text(" ") + } + else -> throw IllegalArgumentException("Node $node is not a property") + } + renderTypeParametersForNode(node) + val receiver = node.details(NodeKind.Receiver).singleOrNull() + if (receiver != null) { + renderType(receiver.detail(NodeKind.Type)) + symbol(".") + } + + identifier(node.name) + symbol(":") + text(" ") + renderType(node.detail(NodeKind.Type)) + + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 85ecdf87..84501d2b 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -63,7 +63,7 @@ enum class NodeKind { companion object { val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias) - val memberLike = setOf(Function, Property, Constructor, CompanionObjectFunction, CompanionObjectProperty, EnumItem) + val memberLike = setOf(Function, Property, Field, Constructor, CompanionObjectFunction, CompanionObjectProperty, EnumItem) } } diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index b0f011be..89ec1b3e 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -62,7 +62,7 @@ class NodeReferenceGraph() { fun lookupOrWarn(signature: String, logger: DokkaLogger): DocumentationNode? { val result = nodeMap[signature] if (result == null) { - logger.warn("Can't find node by signature $signature") + logger.warn("Can't find node by signature `$signature`") } return result } -- cgit From ad35def2efbb6eae6fae423bb639890aaa2cb93f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 13 Jul 2018 18:36:31 +0300 Subject: Add missing urlEncoded function for JLH --- .../Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt | 5 +---- core/src/main/kotlin/Utilities/Html.kt | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt index d04ed64b..6d9b5fd0 100644 --- a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt +++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt @@ -1,10 +1,7 @@ package org.jetbrains.dokka.Formats -import org.jetbrains.dokka.DocumentationModule +import org.jetbrains.dokka.* import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX -import org.jetbrains.dokka.InboundExternalLinkResolutionService -import org.jetbrains.dokka.NodeKind -import org.jetbrains.dokka.PackageListService import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject diff --git a/core/src/main/kotlin/Utilities/Html.kt b/core/src/main/kotlin/Utilities/Html.kt index a5a93d9e..de1ce1a5 100644 --- a/core/src/main/kotlin/Utilities/Html.kt +++ b/core/src/main/kotlin/Utilities/Html.kt @@ -1,8 +1,12 @@ package org.jetbrains.dokka +import java.net.URLEncoder + /** * Replaces symbols reserved in HTML with their respective entities. * Replaces & with &, < with < and > with > */ fun String.htmlEscape(): String = replace("&", "&").replace("<", "<").replace(">", ">") + +fun String.urlEncoded(): String = URLEncoder.encode(this, "UTF-8") \ No newline at end of file -- cgit From 31a4a3804020130e7caf5826b317aaee5547c0d0 Mon Sep 17 00:00:00 2001 From: Douglas Sigelbaum Date: Fri, 20 Apr 2018 18:09:36 -0700 Subject: [backport] Use expression body Original: d889d4e --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 69a97848..79350237 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -459,7 +459,8 @@ class KotlinLanguageService : CommonLanguageService() { } } -fun DocumentationNode.qualifiedNameFromType() = - details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name +fun DocumentationNode.qualifiedNameFromType(): String { + return details.firstOrNull { it.kind == NodeKind.QualifiedName }?.name ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() ?: name +} -- cgit From a3f16fd75c200020465f79563ca58b2833236865 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 24 Apr 2018 20:35:42 +0300 Subject: [backport] Stabilize signatures to fix linking from Java to Kotlin Basically there is 2 ways to get signature, from PSI and from descriptors, and there should be only one way in one session Original: adc09f2 --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 3 +- .../main/kotlin/Analysis/JavaResolveExtension.kt | 131 +++++++++++++++++++++ core/src/main/kotlin/Formats/AnalysisComponents.kt | 14 +-- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 6 +- core/src/main/kotlin/Java/JavadocParser.kt | 5 +- .../main/kotlin/Kotlin/DeclarationLinkResolver.kt | 7 +- .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 6 +- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 23 ++-- .../KotlinAsJavaDescriptorSignatureProvider.kt | 22 ---- .../Kotlin/KotlinAsJavaElementSignatureProvider.kt | 25 ++++ .../Kotlin/KotlinDescriptorSignatureProvider.kt | 9 -- .../Kotlin/KotlinElementSignatureProvider.kt | 31 +++++ .../kotlin/Model/DescriptorSignatureProvider.kt | 7 -- core/src/main/kotlin/Model/DocumentationNode.kt | 7 +- .../main/kotlin/Model/ElementSignatureProvider.kt | 9 ++ core/src/main/kotlin/Utilities/DokkaModules.kt | 3 - 16 files changed, 230 insertions(+), 78 deletions(-) create mode 100644 core/src/main/kotlin/Analysis/JavaResolveExtension.kt delete mode 100644 core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt create mode 100644 core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt delete mode 100644 core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt create mode 100644 core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt delete mode 100644 core/src/main/kotlin/Model/DescriptorSignatureProvider.kt create mode 100644 core/src/main/kotlin/Model/ElementSignatureProvider.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index b2e4b490..6854b323 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.cli.jvm.config.* import org.jetbrains.kotlin.cli.jvm.index.JavaRoot import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.container.getService +import org.jetbrains.kotlin.container.tryGetService import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -250,7 +251,7 @@ class DokkaResolutionFacade(override val project: Project, } override fun tryGetFrontendService(element: PsiElement, serviceClass: Class): T? { - return null + return resolverForModule.componentProvider.tryGetService(serviceClass) } override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor { diff --git a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt new file mode 100644 index 00000000..f8992d45 --- /dev/null +++ b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2017 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:JvmName("JavaResolutionUtils") + +package org.jetbrains.dokka + +import com.intellij.psi.* +import org.jetbrains.kotlin.asJava.classes.KtLightClass +import org.jetbrains.kotlin.asJava.unwrapped +import org.jetbrains.kotlin.caches.resolve.KotlinCacheService +import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.idea.resolve.ResolutionFacade +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.load.java.sources.JavaSourceElement +import org.jetbrains.kotlin.load.java.structure.* +import org.jetbrains.kotlin.load.java.structure.impl.* +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtClassOrObject +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.psiUtil.parameterIndex +import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver +import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform +import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter +import org.jetbrains.kotlin.resolve.scopes.MemberScope + +// TODO: Remove that file + +@JvmOverloads +fun PsiMethod.getJavaMethodDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { + val method = originalElement as? PsiMethod ?: return null + if (method.containingClass == null || !Name.isValidIdentifier(method.name)) return null + val resolver = method.getJavaDescriptorResolver(resolutionFacade) + return when { + method.isConstructor -> resolver?.resolveConstructor(JavaConstructorImpl(method)) + else -> resolver?.resolveMethod(JavaMethodImpl(method)) + } +} + +@JvmOverloads +fun PsiClass.getJavaClassDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): ClassDescriptor? { + val psiClass = originalElement as? PsiClass ?: return null + return psiClass.getJavaDescriptorResolver(resolutionFacade)?.resolveClass(JavaClassImpl(psiClass)) +} + +@JvmOverloads +fun PsiField.getJavaFieldDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): PropertyDescriptor? { + val field = originalElement as? PsiField ?: return null + return field.getJavaDescriptorResolver(resolutionFacade)?.resolveField(JavaFieldImpl(field)) +} + +@JvmOverloads +fun PsiMember.getJavaMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { + return when (this) { + is PsiEnumConstant -> containingClass?.getJavaClassDescriptor(resolutionFacade) + is PsiClass -> getJavaClassDescriptor(resolutionFacade) + is PsiMethod -> getJavaMethodDescriptor(resolutionFacade) + is PsiField -> getJavaFieldDescriptor(resolutionFacade) + else -> null + } +} + +@JvmOverloads +fun PsiMember.getJavaOrKotlinMemberDescriptor(resolutionFacade: ResolutionFacade = javaResolutionFacade()): DeclarationDescriptor? { + val callable = unwrapped + return when (callable) { + is PsiMember -> getJavaMemberDescriptor(resolutionFacade) + is KtDeclaration -> { + val descriptor = resolutionFacade.resolveToDescriptor(callable) + if (descriptor is ClassDescriptor && this is PsiMethod) descriptor.unsubstitutedPrimaryConstructor else descriptor + } + else -> null + } +} + +private fun PsiElement.getJavaDescriptorResolver(resolutionFacade: ResolutionFacade): JavaDescriptorResolver? { + return resolutionFacade.tryGetFrontendService(this, JavaDescriptorResolver::class.java) +} + +private fun JavaDescriptorResolver.resolveMethod(method: JavaMethod): DeclarationDescriptor? { + return getContainingScope(method) + ?.getContributedDescriptors(nameFilter = { true }, kindFilter = DescriptorKindFilter.CALLABLES) + ?.filterIsInstance() + ?.findByJavaElement(method) +} + +private fun JavaDescriptorResolver.resolveConstructor(constructor: JavaConstructor): ConstructorDescriptor? { + return resolveClass(constructor.containingClass)?.constructors?.findByJavaElement(constructor) +} + +private fun JavaDescriptorResolver.resolveField(field: JavaField): PropertyDescriptor? { + return getContainingScope(field)?.getContributedVariables(field.name, NoLookupLocation.FROM_IDE)?.findByJavaElement(field) +} + +private fun JavaDescriptorResolver.getContainingScope(member: JavaMember): MemberScope? { + val containingClass = resolveClass(member.containingClass) + return if (member.isStatic) + containingClass?.staticScope + else + containingClass?.defaultType?.memberScope +} + +private fun Collection.findByJavaElement(javaElement: JavaElement): T? { + return firstOrNull { member -> + val memberJavaElement = (member.original.source as? JavaSourceElement)?.javaElement + when { + memberJavaElement == javaElement -> + true + memberJavaElement is JavaElementImpl<*> && javaElement is JavaElementImpl<*> -> + memberJavaElement.psi.isEquivalentTo(javaElement.psi) + else -> + false + } + } +} + +fun PsiElement.javaResolutionFacade() = + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform) diff --git a/core/src/main/kotlin/Formats/AnalysisComponents.kt b/core/src/main/kotlin/Formats/AnalysisComponents.kt index c4d97dbb..d78d4a0c 100644 --- a/core/src/main/kotlin/Formats/AnalysisComponents.kt +++ b/core/src/main/kotlin/Formats/AnalysisComponents.kt @@ -2,9 +2,9 @@ package org.jetbrains.dokka.Formats import com.google.inject.Binder import org.jetbrains.dokka.* -import org.jetbrains.dokka.Kotlin.KotlinAsJavaDescriptorSignatureProvider -import org.jetbrains.dokka.Kotlin.KotlinDescriptorSignatureProvider -import org.jetbrains.dokka.Model.DescriptorSignatureProvider +import org.jetbrains.dokka.KotlinAsJavaElementSignatureProvider +import org.jetbrains.dokka.KotlinElementSignatureProvider +import org.jetbrains.dokka.ElementSignatureProvider import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import org.jetbrains.dokka.Samples.SampleProcessingService import org.jetbrains.dokka.Utilities.bind @@ -16,12 +16,12 @@ interface DefaultAnalysisComponentServices { val packageDocumentationBuilderClass: KClass val javaDocumentationBuilderClass: KClass val sampleProcessingService: KClass - val descriptorSignatureProvider: KClass + val elementSignatureProvider: KClass } interface DefaultAnalysisComponent : FormatDescriptorAnalysisComponent, DefaultAnalysisComponentServices { override fun configureAnalysis(binder: Binder): Unit = with(binder) { - bind() toType descriptorSignatureProvider + bind() toType elementSignatureProvider bind() toType packageDocumentationBuilderClass bind() toType javaDocumentationBuilderClass bind() toType sampleProcessingService @@ -33,7 +33,7 @@ object KotlinAsJava : DefaultAnalysisComponentServices { override val packageDocumentationBuilderClass = KotlinAsJavaDocumentationBuilder::class override val javaDocumentationBuilderClass = JavaPsiDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinAsJavaDescriptorSignatureProvider::class + override val elementSignatureProvider = KotlinAsJavaElementSignatureProvider::class } @@ -41,5 +41,5 @@ object KotlinAsKotlin : DefaultAnalysisComponentServices { override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class + override val elementSignatureProvider = KotlinElementSignatureProvider::class } \ No newline at end of file diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index cf2b0514..646096e5 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -45,10 +45,10 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser - @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger) { + @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger, signatureProvider: ElementSignatureProvider) { this.options = options this.refGraph = refGraph - this.docParser = JavadocParser(refGraph, logger) + this.docParser = JavadocParser(refGraph, logger, signatureProvider) } constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, docParser: JavaDocumentationParser) { @@ -61,7 +61,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { if (skipFile(file) || file.classes.all { skipElement(it) }) { return } - val packageNode = module.findOrCreatePackageNode(file.packageName, emptyMap(), refGraph) + val packageNode = findOrCreatePackageNode(module, file.packageName, emptyMap(), refGraph) appendClasses(packageNode, file.classes) } diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index db61a00a..365ae298 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -22,7 +22,8 @@ interface JavaDocumentationParser { class JavadocParser( private val refGraph: NodeReferenceGraph, - private val logger: DokkaLogger + private val logger: DokkaLogger, + private val signatureProvider: ElementSignatureProvider ) : JavaDocumentationParser { override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult { val docComment = (element as? PsiDocCommentOwner)?.docComment @@ -157,7 +158,7 @@ class JavadocParser( private fun resolveLink(valueElement: PsiElement?): String? { val target = valueElement?.reference?.resolve() if (target != null) { - return getSignature(target) + return signatureProvider.signature(target) } return null } diff --git a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt index ec474900..d73bef4a 100644 --- a/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/DeclarationLinkResolver.kt @@ -1,13 +1,10 @@ package org.jetbrains.dokka import com.google.inject.Inject -import org.jetbrains.dokka.Model.DescriptorSignatureProvider import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.TypeAliasDescriptor import org.jetbrains.kotlin.idea.kdoc.resolveKDocLink -import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPrivateApi -import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi class DeclarationLinkResolver @Inject constructor(val resolutionFacade: DokkaResolutionFacade, @@ -15,7 +12,7 @@ class DeclarationLinkResolver val logger: DokkaLogger, val options: DocumentationOptions, val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver, - val descriptorSignatureProvider: DescriptorSignatureProvider) { + val elementSignatureProvider: ElementSignatureProvider) { fun tryResolveContentLink(fromDescriptor: DeclarationDescriptor, href: String): ContentBlock? { @@ -34,7 +31,7 @@ class DeclarationLinkResolver if (externalHref != null) { return ContentExternalLink(externalHref) } - val signature = descriptorSignatureProvider.signature(symbol) + val signature = elementSignatureProvider.signature(symbol) val referencedAt = fromDescriptor.signatureWithSourceLocation() return ContentNodeLazyLink(href, { -> diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 6e44df74..5f1118e8 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -33,7 +33,9 @@ class DescriptorDocumentationParser val linkResolver: DeclarationLinkResolver, val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, - val sampleService: SampleProcessingService) + val sampleService: SampleProcessingService, + val signatureProvider: KotlinElementSignatureProvider + ) { fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false): Content = parseDocumentationAndDetails(descriptor, inline).first @@ -129,7 +131,7 @@ class DescriptorDocumentationParser fun parseJavadoc(descriptor: DeclarationDescriptor): Pair Unit> { val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi if (psi is PsiDocCommentOwner) { - val parseResult = JavadocParser(refGraph, logger).parseDocumentation(psi as PsiNamedElement) + val parseResult = JavadocParser(refGraph, logger, signatureProvider).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 d7d30ebb..05bd2cc7 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -18,7 +18,6 @@ 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 -import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -29,7 +28,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils 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 @@ -192,14 +190,16 @@ class DocumentationBuilder appendTextNode(modifier, NodeKind.Modifier) } - fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType) { + fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType, backref: Boolean) { val unwrappedType = superType.unwrap() if (unwrappedType is AbbreviatedType) { - appendSupertype(descriptor, unwrappedType.abbreviation) + appendSupertype(descriptor, unwrappedType.abbreviation, backref) } else { appendType(unwrappedType, NodeKind.Supertype) val superclass = unwrappedType.constructor.declarationDescriptor - link(superclass, descriptor, RefKind.Inheritor) + if (backref) { + link(superclass, descriptor, RefKind.Inheritor) + } link(descriptor, superclass, RefKind.Superclass) } } @@ -457,7 +457,7 @@ class DocumentationBuilder if (options.skipEmptyPackages && declarations.none { it.isDocumented(options) }) continue logger.info(" package $packageName: ${declarations.count()} declarations") - val packageNode = findOrCreatePackageNode(packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) + val packageNode = findOrCreatePackageNode(this, packageName.asString(), packageContent, this@DocumentationBuilder.refGraph) packageDocumentationBuilder.buildPackageDocumentation(this@DocumentationBuilder, packageName, packageNode, declarations, allFqNames) } @@ -646,7 +646,7 @@ class DocumentationBuilder val node = nodeForDescriptor(this, kind, external) register(this, node) typeConstructor.supertypes.forEach { - node.appendSupertype(this, it) + node.appendSupertype(this, it, !external) } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail) @@ -997,16 +997,11 @@ class KotlinJavaDocumentationBuilder val logger: DokkaLogger) : JavaDocumentationBuilder { override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map) { val classDescriptors = file.classes.map { - val javaDescriptorResolver = resolutionFacade.getFrontendService(JavaDescriptorResolver::class.java) - - javaDescriptorResolver.resolveClass(JavaClassImpl(it)) ?: run { - logger.warn("Cannot find descriptor for Java class ${it.qualifiedName}") - null - } + it.getJavaClassDescriptor(resolutionFacade) } if (classDescriptors.any { it != null && it.isDocumented(options) }) { - val packageNode = module.findOrCreatePackageNode(file.packageName, packageContent, documentationBuilder.refGraph) + val packageNode = findOrCreatePackageNode(module, file.packageName, packageContent, documentationBuilder.refGraph) for (descriptor in classDescriptors.filterNotNull()) { with(documentationBuilder) { diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt deleted file mode 100644 index a3be658e..00000000 --- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDescriptorSignatureProvider.kt +++ /dev/null @@ -1,22 +0,0 @@ -package org.jetbrains.dokka.Kotlin - -import org.jetbrains.dokka.Model.DescriptorSignatureProvider -import org.jetbrains.dokka.getSignature -import org.jetbrains.dokka.sourcePsi -import org.jetbrains.kotlin.asJava.toLightElements -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.psi.KtElement - -class KotlinAsJavaDescriptorSignatureProvider : DescriptorSignatureProvider { - override fun signature(forDesc: DeclarationDescriptor): String { - val sourcePsi = forDesc.sourcePsi() - val javaLikePsi = if (sourcePsi is KtElement) { - sourcePsi.toLightElements().firstOrNull() - } else { - sourcePsi - } - - return getSignature(javaLikePsi) ?: - "not implemented for $forDesc with psi: $sourcePsi" - } -} \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt new file mode 100644 index 00000000..20ea179e --- /dev/null +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaElementSignatureProvider.kt @@ -0,0 +1,25 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.asJava.toLightElements +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.psi.KtElement + +class KotlinAsJavaElementSignatureProvider : ElementSignatureProvider { + + private fun PsiElement.javaLikePsi() = when { + this is KtElement -> toLightElements().firstOrNull() + else -> this + } + + override fun signature(forPsi: PsiElement): String { + return getSignature(forPsi.javaLikePsi()) ?: + "not implemented for $forPsi" + } + + override fun signature(forDesc: DeclarationDescriptor): String { + val sourcePsi = forDesc.sourcePsi() + return getSignature(sourcePsi?.javaLikePsi()) ?: + "not implemented for $forDesc with psi: $sourcePsi" + } +} \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt deleted file mode 100644 index 7ecd0389..00000000 --- a/core/src/main/kotlin/Kotlin/KotlinDescriptorSignatureProvider.kt +++ /dev/null @@ -1,9 +0,0 @@ -package org.jetbrains.dokka.Kotlin - -import org.jetbrains.dokka.Model.DescriptorSignatureProvider -import org.jetbrains.dokka.signature -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor - -class KotlinDescriptorSignatureProvider : DescriptorSignatureProvider { - override fun signature(forDesc: DeclarationDescriptor): String = forDesc.signature() -} \ No newline at end of file diff --git a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt new file mode 100644 index 00000000..4f788634 --- /dev/null +++ b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt @@ -0,0 +1,31 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMember +import com.intellij.psi.PsiNameIdentifierOwner +import org.jetbrains.kotlin.asJava.elements.KtLightElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.resolve.BindingContext +import javax.inject.Inject + +class KotlinElementSignatureProvider @Inject constructor( + val resolutionFacade: DokkaResolutionFacade +) : ElementSignatureProvider { + override fun signature(forPsi: PsiElement): String { + + val desc = when (forPsi) { + is KtLightElement<*, *> -> return signature(forPsi.kotlinOrigin!!) + is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) + else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] + } + + if (desc == null && (forPsi as? PsiNameIdentifierOwner)?.name == "remove") { + (forPsi as? PsiMember)?.getJavaOrKotlinMemberDescriptor(resolutionFacade) + } + + return desc?.let { signature(it) } + ?: run { "no desc for $forPsi in ${(forPsi as? PsiMember)?.containingClass}" } + } + + override fun signature(forDesc: DeclarationDescriptor): String = forDesc.signature() +} \ No newline at end of file diff --git a/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt b/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt deleted file mode 100644 index 85584e3c..00000000 --- a/core/src/main/kotlin/Model/DescriptorSignatureProvider.kt +++ /dev/null @@ -1,7 +0,0 @@ -package org.jetbrains.dokka.Model - -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor - -interface DescriptorSignatureProvider { - fun signature(forDesc: DeclarationDescriptor): String -} \ No newline at end of file diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 84501d2b..4739d736 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -176,16 +176,17 @@ val DocumentationNode.path: List return parent.path + this } -fun DocumentationNode.findOrCreatePackageNode(packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { - val existingNode = members(NodeKind.Package).firstOrNull { it.name == packageName } +fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { + val existingNode = refGraph.lookup(packageName) if (existingNode != null) { return existingNode } val newNode = DocumentationNode(packageName, packageContent.getOrElse(packageName) { Content.Empty }, NodeKind.Package) - append(newNode, RefKind.Member) + refGraph.register(packageName, newNode) + module?.append(newNode, RefKind.Member) return newNode } diff --git a/core/src/main/kotlin/Model/ElementSignatureProvider.kt b/core/src/main/kotlin/Model/ElementSignatureProvider.kt new file mode 100644 index 00000000..e8fdde6e --- /dev/null +++ b/core/src/main/kotlin/Model/ElementSignatureProvider.kt @@ -0,0 +1,9 @@ +package org.jetbrains.dokka + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor + +interface ElementSignatureProvider { + fun signature(forDesc: DeclarationDescriptor): String + fun signature(forPsi: PsiElement): String +} \ No newline at end of file diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 36704918..907d5ca7 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -2,14 +2,11 @@ package org.jetbrains.dokka.Utilities import com.google.inject.Binder import com.google.inject.Module -import com.google.inject.Provider import com.google.inject.TypeLiteral import com.google.inject.binder.AnnotatedBindingBuilder import com.google.inject.name.Names import org.jetbrains.dokka.* import org.jetbrains.dokka.Formats.FormatDescriptor -import org.jetbrains.dokka.Model.DescriptorSignatureProvider -import org.jetbrains.dokka.Samples.SampleProcessingService import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import java.io.File import kotlin.reflect.KClass -- cgit From 27deff9e3f8bb2190115f2e5f68f859f46af11a3 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 24 Apr 2018 20:37:18 +0300 Subject: Fix checking belonging to public API --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 05bd2cc7..8fec0bfb 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -960,12 +960,10 @@ class DocumentationBuilder } -val visibleToDocumentation = setOf(Visibilities.PROTECTED, Visibilities.PUBLIC) - fun DeclarationDescriptor.isDocumented(options: DocumentationOptions): Boolean { return (options.effectivePackageOptions(fqNameSafe).includeNonPublic || this !is MemberDescriptor - || this.visibility in visibleToDocumentation) + || this.visibility.isPublicAPI) && !isDocumentationSuppressed(options) && (!options.effectivePackageOptions(fqNameSafe).skipDeprecated || !isDeprecated()) } -- cgit From 54874733ff84998d26e21b57384ad3b2ca151fc2 Mon Sep 17 00:00:00 2001 From: Douglas Sigelbaum Date: Tue, 24 Apr 2018 20:27:21 -0700 Subject: [backport] Added logic for inherited constants. Also, switched to using recursively inherited members instead of just inherited members in the immediate super class. Original: 56c3558 --- core/src/main/kotlin/Model/DocumentationNode.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 4739d736..ca298802 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import org.jetbrains.dokka.Formats.constantValue import java.util.* enum class NodeKind { @@ -86,6 +87,8 @@ open class DocumentationNode(val name: String, get() = references(RefKind.Member).map { it.to } val inheritedMembers: List get() = references(RefKind.InheritedMember).map { it.to } + val allInheritedMembers: List + get() = recursiveInheritedMembers() val inheritedCompanionObjectMembers: List get() = references(RefKind.InheritedCompanionObjectMember).map { it.to } val extensions: List @@ -145,7 +148,6 @@ open class DocumentationNode(val name: String, } (content as MutableContent).body() } - fun details(kind: NodeKind): List = details.filter { it.kind == kind } fun members(kind: NodeKind): List = members.filter { it.kind == kind } fun inheritedMembers(kind: NodeKind): List = inheritedMembers.filter { it.kind == kind } @@ -217,3 +219,17 @@ fun DocumentationNode.qualifiedName(): String { } fun DocumentationNode.simpleName() = name.substringAfterLast('.') + +private fun DocumentationNode.recursiveInheritedMembers(): List { + val allInheritedMembers = mutableListOf() + recursiveInheritedMembers(allInheritedMembers) + return allInheritedMembers +} + +private fun DocumentationNode.recursiveInheritedMembers(allInheritedMembers: MutableList) { + allInheritedMembers.addAll(inheritedMembers) + System.out.println(allInheritedMembers.size) + inheritedMembers.groupBy { it.owner!! } .forEach { (node, _) -> + node.recursiveInheritedMembers(allInheritedMembers) + } +} \ No newline at end of file -- cgit From f8c358a6a5b269a8dcd5240db8dd14a497c261c2 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 26 Apr 2018 18:04:18 +0300 Subject: KT-24036: Don't show visibility modifiers in summary --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 9 ++++++--- core/src/main/kotlin/Languages/CommonLanguageService.kt | 1 + core/src/main/kotlin/Languages/NewJavaLanguageService.kt | 10 ++++++---- 3 files changed, 13 insertions(+), 7 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 79350237..613b9451 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -23,7 +23,7 @@ class KotlinLanguageService : CommonLanguageService() { NodeKind.Type, NodeKind.UpperBound -> renderType(node, renderMode) - NodeKind.Modifier -> renderModifier(this, node) + NodeKind.Modifier -> renderModifier(this, node, renderMode) NodeKind.Constructor, NodeKind.Function, NodeKind.CompanionObjectFunction -> renderFunction(node, renderMode) @@ -188,13 +188,16 @@ class KotlinLanguageService : CommonLanguageService() { override fun renderModifier( block: ContentBlock, node: DocumentationNode, + renderMode: RenderMode, nowrap: Boolean ) { when (node.name) { "final", "public", "var" -> { } else -> { - super.renderModifier(block, node, nowrap) + if (node.name !in fullOnlyModifiers || renderMode == RenderMode.FULL) { + super.renderModifier(block, node, renderMode, nowrap) + } } } } @@ -289,7 +292,7 @@ class KotlinLanguageService : CommonLanguageService() { if (renderMode == RenderMode.SUMMARY && it.name in fullOnlyModifiers) { continue } - renderModifier(this, it, nowrap) + renderModifier(this, it, renderMode, nowrap) } } diff --git a/core/src/main/kotlin/Languages/CommonLanguageService.kt b/core/src/main/kotlin/Languages/CommonLanguageService.kt index f155192d..edefa1b5 100644 --- a/core/src/main/kotlin/Languages/CommonLanguageService.kt +++ b/core/src/main/kotlin/Languages/CommonLanguageService.kt @@ -19,6 +19,7 @@ abstract class CommonLanguageService : LanguageService { open fun renderModifier( block: ContentBlock, node: DocumentationNode, + renderMode: LanguageService.RenderMode, nowrap: Boolean = false ) = with(block) { keyword(node.name) diff --git a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt index 22ad62b2..0266c033 100644 --- a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt +++ b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt @@ -1,16 +1,18 @@ package org.jetbrains.dokka +import org.jetbrains.dokka.LanguageService.RenderMode + /** * Implements [LanguageService] and provides rendering of symbols in Java language */ class NewJavaLanguageService : CommonLanguageService() { - override fun render(node: DocumentationNode, renderMode: LanguageService.RenderMode): ContentNode { + override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode { return content { (when (node.kind) { NodeKind.Package -> renderPackage(node) in NodeKind.classLike -> renderClass(node) - NodeKind.Modifier -> renderModifier(this, node) + NodeKind.Modifier -> renderModifier(this, node, renderMode) NodeKind.TypeParameter -> renderTypeParameter(node) NodeKind.Type, NodeKind.UpperBound -> renderType(node) @@ -26,11 +28,11 @@ class NewJavaLanguageService : CommonLanguageService() { override fun summarizeSignatures(nodes: List): ContentNode? = null - override fun renderModifier(block: ContentBlock, node: DocumentationNode, nowrap: Boolean) { + override fun renderModifier(block: ContentBlock, node: DocumentationNode, renderMode: RenderMode, nowrap: Boolean) { when (node.name) { "open", "internal" -> { } - else -> super.renderModifier(block, node, nowrap) + else -> super.renderModifier(block, node, renderMode, nowrap) } } -- cgit From 9539284e5dd72e2676dc5d656b78f21c1c7035ee Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 26 Apr 2018 19:37:07 +0300 Subject: KT-24109: Fix generation of superclass sequence --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 10 +++++++++- core/src/main/kotlin/Model/DocumentationNode.kt | 16 +++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 8fec0bfb..cb35e568 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -34,6 +34,7 @@ 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.supertypes +import org.jetbrains.kotlin.util.supertypesWithAny import java.io.File import java.nio.file.Path import java.nio.file.Paths @@ -645,7 +646,7 @@ class DocumentationBuilder } val node = nodeForDescriptor(this, kind, external) register(this, node) - typeConstructor.supertypes.forEach { + supertypesWithAnyPrecise().forEach { node.appendSupertype(this, it, !external) } if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { @@ -1152,3 +1153,10 @@ fun DocumentationNode.generateAllTypesNode() { append(allTypesNode, RefKind.Member) } + +fun ClassDescriptor.supertypesWithAnyPrecise(): Collection { + if (KotlinBuiltIns.isAny(this)) { + return emptyList() + } + return typeConstructor.supertypesWithAny() +} \ No newline at end of file diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index ca298802..a89f5080 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,6 +1,7 @@ package org.jetbrains.dokka import org.jetbrains.dokka.Formats.constantValue +import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -115,11 +116,12 @@ open class DocumentationNode(val name: String, val superclassType: DocumentationNode? get() = when (kind) { - NodeKind.Supertype -> (links.firstOrNull { it.kind in NodeKind.classLike } ?: externalType)?.superclassType + NodeKind.Supertype -> { + (links + listOfNotNull(externalType)).firstOrNull { it.kind in NodeKind.classLike }?.superclassType + } NodeKind.Interface -> null in NodeKind.classLike -> supertypes.firstOrNull { - it.links.any { it.kind in NodeKind.classLike } || - it.externalType != null + (it.links + listOfNotNull(it.externalType)).any { it.isSuperclassFor(this) } } else -> null } @@ -232,4 +234,12 @@ private fun DocumentationNode.recursiveInheritedMembers(allInheritedMembers: Mut inheritedMembers.groupBy { it.owner!! } .forEach { (node, _) -> node.recursiveInheritedMembers(allInheritedMembers) } +} + +private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean { + return when(node.kind) { + NodeKind.Object, NodeKind.Class, NodeKind.Enum -> kind == NodeKind.Class + NodeKind.Exception -> kind == NodeKind.Class || kind == NodeKind.Exception + else -> false + } } \ No newline at end of file -- cgit From d8e3a6b6811569b77d2b523df6ade772ef38dde1 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 26 Apr 2018 21:29:36 +0300 Subject: KT-24113: Render inner classes names qualified --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 613b9451..75d9fbbf 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -1,5 +1,6 @@ package org.jetbrains.dokka +import org.jetbrains.dokka.Formats.classNodeNameWithOuterClass import org.jetbrains.dokka.LanguageService.RenderMode /** @@ -170,7 +171,9 @@ class KotlinLanguageService : CommonLanguageService() { renderAnnotationsForNode(node) } renderModifiersForNode(node, renderMode, true) - renderLinked(this, node) { identifier(it.name, IdentifierKind.TypeName) } + renderLinked(this, node) { + identifier(it.typeDeclarationClass?.classNodeNameWithOuterClass() ?: it.name, IdentifierKind.TypeName) + } val typeArguments = node.details(NodeKind.Type) if (typeArguments.isNotEmpty()) { symbol("<") @@ -367,7 +370,7 @@ class KotlinLanguageService : CommonLanguageService() { renderReceiver(node, renderMode, signatureMapper) - if (node.kind != org.jetbrains.dokka.NodeKind.Constructor) + if (node.kind != NodeKind.Constructor) identifierOrDeprecated(node) symbol("(") @@ -467,3 +470,7 @@ fun DocumentationNode.qualifiedNameFromType(): String { ?: (links.firstOrNull() ?: hiddenLinks.firstOrNull())?.qualifiedName() ?: name } + + +private val DocumentationNode.typeDeclarationClass + get() = (links.firstOrNull { it.kind in NodeKind.classLike } ?: externalType) -- cgit From 9831944e07b5acd5558d901cefa0ba49c24d91ff Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 26 Apr 2018 22:24:20 +0300 Subject: [backport] Make accessible Original: 44ec370 KT-24039: Support Inherited xml attributes --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 75d9fbbf..b6474583 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -472,5 +472,5 @@ fun DocumentationNode.qualifiedNameFromType(): String { } -private val DocumentationNode.typeDeclarationClass +val DocumentationNode.typeDeclarationClass get() = (links.firstOrNull { it.kind in NodeKind.classLike } ?: externalType) -- cgit From eba83fb593ebae4c3d1498969feb0dc5a085689c Mon Sep 17 00:00:00 2001 From: Douglas Sigelbaum Date: Fri, 27 Apr 2018 10:42:49 -0700 Subject: [backport] Sort by lowercase name everywhere. Original: 2ca99c2 --- core/src/main/kotlin/Formats/OutlineService.kt | 2 +- core/src/main/kotlin/Formats/StructuredFormatService.kt | 2 +- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/OutlineService.kt b/core/src/main/kotlin/Formats/OutlineService.kt index 3c31ba57..958e93af 100644 --- a/core/src/main/kotlin/Formats/OutlineService.kt +++ b/core/src/main/kotlin/Formats/OutlineService.kt @@ -16,7 +16,7 @@ interface OutlineFormatService { for (node in nodes) { appendOutlineHeader(location, node, to) if (node.members.any()) { - val sortedMembers = node.members.sortedBy { it.name } + val sortedMembers = node.members.sortedBy { it.name.toLowerCase() } appendOutlineLevel(to) { appendOutline(location, to, sortedMembers) } diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index 952e14cf..ebc9cde6 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -570,7 +570,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, appendHeader(3) { appendText(caption) } - val children = if (sortMembers) members.sortedBy { it.name } else members + val children = if (sortMembers) members.sortedBy { it.name.toLowerCase() } else members val membersMap = children.groupBy { link(node, it) } diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index cb35e568..88fe7095 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -1144,7 +1144,7 @@ fun DocumentationModule.prepareForGeneration(options: DocumentationOptions) { fun DocumentationNode.generateAllTypesNode() { val allTypes = members(NodeKind.Package) .flatMap { it.members.filter { it.kind in NodeKind.classLike || it.kind == NodeKind.ExternalClass } } - .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.') else it.name } + .sortedBy { if (it.kind == NodeKind.ExternalClass) it.name.substringAfterLast('.').toLowerCase() else it.name.toLowerCase() } val allTypesNode = DocumentationNode("alltypes", Content.Empty, NodeKind.AllTypes) for (typeNode in allTypes) { -- cgit From 57a6bb55ddafbde4eab7c1c4344fff3ad3f0fe1f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 27 Apr 2018 18:05:35 +0300 Subject: [backport] KT-24042: Fix structure of content paragraphs in Javadoc parser Original: edc0581 --- core/src/main/kotlin/Java/JavadocParser.kt | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 365ae298..08ae5354 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -30,9 +30,18 @@ class JavadocParser( if (docComment == null) return JavadocParseResult.Empty val result = MutableContent() var deprecatedContent: Content? = null - val para = ContentParagraph() - result.append(para) - para.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }) + val firstParagraph = ContentParagraph() + firstParagraph.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }) + val paragraphs = firstParagraph.children.dropWhile { it !is ContentParagraph } + firstParagraph.children.removeAll(paragraphs) + if (!firstParagraph.isEmpty()) { + result.append(firstParagraph) + } + paragraphs.forEach { + result.append(it) + } + val attrs = mutableListOf() + var since: DocumentationNode? = null docComment.tags.forEach { tag -> when (tag.name) { "see" -> result.convertSeeTag(tag) @@ -70,20 +79,24 @@ class JavadocParser( } val doc = Jsoup.parse(htmlBuilder.toString().trim()) doc.body().childNodes().forEach { - convertHtmlNode(it) + convertHtmlNode(it)?.let { append(it) } } } - private fun ContentBlock.convertHtmlNode(node: Node) { + private fun convertHtmlNode(node: Node): ContentNode? { if (node is TextNode) { - append(ContentText(node.text())) + return ContentText(node.text()) } else if (node is Element) { val childBlock = createBlock(node) node.childNodes().forEach { - childBlock.convertHtmlNode(it) + val child = convertHtmlNode(it) + if (child != null) { + childBlock.append(child) + } } - append(childBlock) + return (childBlock) } + return null } private fun createBlock(element: Element): ContentBlock = when (element.tagName()) { -- cgit From 6cfaf04a6a0a34299d3a39803322b2eea2afbaac Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 27 Apr 2018 19:42:25 +0300 Subject: [backport] KT-24149: Fix resolution of links in Javadoc Original: edc0581 --- core/src/main/kotlin/Java/JavadocParser.kt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 08ae5354..0869081b 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -1,10 +1,12 @@ package org.jetbrains.dokka import com.intellij.psi.* +import com.intellij.psi.impl.source.tree.JavaDocElementType import com.intellij.psi.javadoc.PsiDocTag import com.intellij.psi.javadoc.PsiDocTagValue import com.intellij.psi.javadoc.PsiDocToken import com.intellij.psi.javadoc.PsiInlineDocTag +import com.intellij.psi.util.PsiTreeUtil import org.jsoup.Jsoup import org.jsoup.nodes.Element import org.jsoup.nodes.Node @@ -130,11 +132,11 @@ class JavadocParser( private fun MutableContent.convertSeeTag(tag: PsiDocTag) { val linkElement = tag.linkElement() ?: return val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) - val linkSignature = resolveLink(linkElement) + val linkSignature = resolveLink(tag.referenceElement()) val text = ContentText(linkElement.text) if (linkSignature != null) { val linkNode = - ContentNodeLazyLink(tag.valueElement!!.text, { -> refGraph.lookupOrWarn(linkSignature, logger) }) + ContentNodeLazyLink((tag.valueElement ?: linkElement).text, { -> refGraph.lookupOrWarn(linkSignature, logger) }) linkNode.append(text) seeSection.append(linkNode) } else { @@ -144,7 +146,7 @@ class JavadocParser( private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) { "link", "linkplain" -> { - val valueElement = tag.linkElement() + val valueElement = tag.referenceElement() val linkSignature = resolveLink(valueElement) if (linkSignature != null) { val labelText = tag.dataElements.firstOrNull { it is PsiDocToken }?.text ?: valueElement!!.text @@ -165,6 +167,15 @@ class JavadocParser( else -> tag.text } + private fun PsiDocTag.referenceElement(): PsiElement? = + linkElement()?.let { + if (it.node.elementType == JavaDocElementType.DOC_REFERENCE_HOLDER) { + PsiTreeUtil.findChildOfType(it, PsiJavaCodeReferenceElement::class.java) + } else { + it + } + } + private fun PsiDocTag.linkElement(): PsiElement? = valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } -- cgit From 432868e8732085a0b160466ddbe8262b793b4f95 Mon Sep 17 00:00:00 2001 From: Sean McQuillan Date: Thu, 26 Apr 2018 18:03:04 -0700 Subject: [backport] Support for {@inheritDoc} including grand inheritance and skip levels. Original: f100b73 --- core/src/main/kotlin/Java/JavadocParser.kt | 127 +++++++++++++++++++++++++---- 1 file changed, 113 insertions(+), 14 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 0869081b..f88f557d 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -2,11 +2,10 @@ package org.jetbrains.dokka import com.intellij.psi.* import com.intellij.psi.impl.source.tree.JavaDocElementType -import com.intellij.psi.javadoc.PsiDocTag -import com.intellij.psi.javadoc.PsiDocTagValue -import com.intellij.psi.javadoc.PsiDocToken -import com.intellij.psi.javadoc.PsiInlineDocTag +import com.intellij.psi.javadoc.* import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.IncorrectOperationException +import com.intellij.util.containers.isNullOrEmpty import org.jsoup.Jsoup import org.jsoup.nodes.Element import org.jsoup.nodes.Node @@ -33,7 +32,7 @@ class JavadocParser( val result = MutableContent() var deprecatedContent: Content? = null val firstParagraph = ContentParagraph() - firstParagraph.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }) + firstParagraph.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }, element) val paragraphs = firstParagraph.children.dropWhile { it !is ContentParagraph } firstParagraph.children.removeAll(paragraphs) if (!firstParagraph.isEmpty()) { @@ -49,13 +48,13 @@ class JavadocParser( "see" -> result.convertSeeTag(tag) "deprecated" -> { deprecatedContent = Content() - deprecatedContent!!.convertJavadocElements(tag.contentElements()) + deprecatedContent!!.convertJavadocElements(tag.contentElements(), element) } else -> { val subjectName = tag.getSubjectName() val section = result.addSection(javadocSectionDisplayName(tag.name), subjectName) - section.convertJavadocElements(tag.contentElements()) + section.convertJavadocElements(tag.contentElements(), element) } } } @@ -70,19 +69,23 @@ class JavadocParser( return if (getSubjectName() != null) tagValueElements.dropWhile { it is PsiDocTagValue } else tagValueElements } - private fun ContentBlock.convertJavadocElements(elements: Iterable) { + private fun ContentBlock.convertJavadocElements(elements: Iterable, element: PsiNamedElement) { + val doc = Jsoup.parse(expandAllForElements(elements, element)) + doc.body().childNodes().forEach { + convertHtmlNode(it)?.let { append(it) } + } + } + + private fun expandAllForElements(elements: Iterable, element: PsiNamedElement): String { val htmlBuilder = StringBuilder() elements.forEach { if (it is PsiInlineDocTag) { - htmlBuilder.append(convertInlineDocTag(it)) + htmlBuilder.append(convertInlineDocTag(it, element)) } else { htmlBuilder.append(it.text) } } - val doc = Jsoup.parse(htmlBuilder.toString().trim()) - doc.body().childNodes().forEach { - convertHtmlNode(it)?.let { append(it) } - } + return htmlBuilder.toString().trim() } private fun convertHtmlNode(node: Node): ContentNode? { @@ -144,7 +147,7 @@ class JavadocParser( } } - private fun convertInlineDocTag(tag: PsiInlineDocTag) = when (tag.name) { + private fun convertInlineDocTag(tag: PsiInlineDocTag, element: PsiNamedElement) = when (tag.name) { "link", "linkplain" -> { val valueElement = tag.referenceElement() val linkSignature = resolveLink(valueElement) @@ -164,6 +167,18 @@ class JavadocParser( val escaped = text.toString().trimStart().htmlEscape() if (tag.name == "code") "$escaped" else escaped } + "inheritDoc" -> { + val result = (element as? PsiMethod)?.let { + // @{inheritDoc} is only allowed on functions + val parent = tag.parent + when (parent) { + is PsiDocComment -> element.findSuperDocCommentOrWarn() + is PsiDocTag -> element.findSuperDocTagOrWarn(parent) + else -> null + } + } + result ?: tag.text + } else -> tag.text } @@ -193,4 +208,88 @@ class JavadocParser( } return null } + + private fun PsiMethod.findSuperDocCommentOrWarn(): String { + val method = findFirstSuperMethodWithDocumentation(this) + if (method != null) { + val descriptionElements = method.docComment?.descriptionElements?.dropWhile { + it.text.trim().isEmpty() + } ?: return "" + + return expandAllForElements(descriptionElements, method) + } + logger.warn("No docs found on supertype with {@inheritDoc} method ${this.name} in ${this.containingFile.name}:${this.lineNumber()}") + return "" + } + + + private fun PsiMethod.findSuperDocTagOrWarn(elementToExpand: PsiDocTag): String { + val result = findFirstSuperMethodWithDocumentationforTag(elementToExpand, this) + + if (result != null) { + val (method, tag) = result + + val contentElements = tag.contentElements().dropWhile { it.text.trim().isEmpty() } + + val expandedString = expandAllForElements(contentElements, method) + + return expandedString + } + logger.warn("No docs found on supertype for @${elementToExpand.name} ${elementToExpand.getSubjectName()} with {@inheritDoc} method ${this.name} in ${this.containingFile.name}:${this.lineNumber()}") + return "" + } + + private fun findFirstSuperMethodWithDocumentation(current: PsiMethod): PsiMethod? { + val superMethods = current.findSuperMethods() + for (method in superMethods) { + val docs = method.docComment?.descriptionElements?.dropWhile { it.text.trim().isEmpty() } + if (!docs.isNullOrEmpty()) { + return method + } + } + for (method in superMethods) { + val result = findFirstSuperMethodWithDocumentation(method) + if (result != null) { + return result + } + } + + return null + } + + private fun findFirstSuperMethodWithDocumentationforTag(elementToExpand: PsiDocTag, current: PsiMethod): Pair? { + val superMethods = current.findSuperMethods() + val mappedFilteredTags = superMethods.map { + it to it.docComment?.tags?.filter { it.name == elementToExpand.name } + } + + for ((method, tags) in mappedFilteredTags) { + tags ?: continue + for (tag in tags) { + val (tagSubject, elementSubject) = when (tag.name) { + "throws" -> { + // match class names only for throws, ignore possibly fully qualified path + // TODO: Always match exactly here + tag.getSubjectName()?.split(".")?.last() to elementToExpand.getSubjectName()?.split(".")?.last() + } + else -> { + tag.getSubjectName() to elementToExpand.getSubjectName() + } + } + + if (tagSubject == elementSubject) { + return method to tag + } + } + } + + for (method in superMethods) { + val result = findFirstSuperMethodWithDocumentationforTag(elementToExpand, method) + if (result != null) { + return result + } + } + return null + } + } -- cgit From a16ae6c02e1ec7270fb161c63908b5b3831bce8e Mon Sep 17 00:00:00 2001 From: Sean McQuillan Date: Thu, 26 Apr 2018 18:03:04 -0700 Subject: [backport] Support for {@inheritDoc} including grand inheritance and skip levels. Original: 0eda743 --- core/src/main/kotlin/Java/JavadocParser.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index f88f557d..554cd2d3 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -1,6 +1,8 @@ package org.jetbrains.dokka import com.intellij.psi.* +import com.intellij.psi.impl.source.javadoc.CorePsiDocTagValueImpl +import com.intellij.psi.javadoc.* import com.intellij.psi.impl.source.tree.JavaDocElementType import com.intellij.psi.javadoc.* import com.intellij.psi.util.PsiTreeUtil @@ -41,14 +43,13 @@ class JavadocParser( paragraphs.forEach { result.append(it) } - val attrs = mutableListOf() - var since: DocumentationNode? = null docComment.tags.forEach { tag -> when (tag.name) { "see" -> result.convertSeeTag(tag) "deprecated" -> { - deprecatedContent = Content() - deprecatedContent!!.convertJavadocElements(tag.contentElements(), element) + deprecatedContent = Content().apply { + convertJavadocElements(tag.contentElements(), element) + } } else -> { val subjectName = tag.getSubjectName() -- cgit From ee0b640ad5c4a8cc1b65403dc2c48e7723b8f53a Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 3 May 2018 18:18:53 +0300 Subject: Fix resolution of package links --- core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt index 4f788634..0a377dc1 100644 --- a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt +++ b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt @@ -3,8 +3,10 @@ package org.jetbrains.dokka import com.intellij.psi.PsiElement import com.intellij.psi.PsiMember import com.intellij.psi.PsiNameIdentifierOwner +import com.intellij.psi.PsiPackage import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.BindingContext import javax.inject.Inject @@ -15,6 +17,7 @@ class KotlinElementSignatureProvider @Inject constructor( val desc = when (forPsi) { is KtLightElement<*, *> -> return signature(forPsi.kotlinOrigin!!) + is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName)) is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] } -- cgit From 74b228108445a8a9024b6892f6562d77c658fc64 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Thu, 3 May 2018 18:20:33 +0300 Subject: [backport] KT-24152: Support implicit sections inheritance Original: 5636fac --- core/src/main/kotlin/Java/JavadocParser.kt | 40 +++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 554cd2d3..41b77aed 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -2,12 +2,12 @@ package org.jetbrains.dokka import com.intellij.psi.* import com.intellij.psi.impl.source.javadoc.CorePsiDocTagValueImpl -import com.intellij.psi.javadoc.* import com.intellij.psi.impl.source.tree.JavaDocElementType import com.intellij.psi.javadoc.* import com.intellij.psi.util.PsiTreeUtil import com.intellij.util.IncorrectOperationException import com.intellij.util.containers.isNullOrEmpty +import org.jetbrains.kotlin.utils.keysToMap import org.jsoup.Jsoup import org.jsoup.nodes.Element import org.jsoup.nodes.Node @@ -43,6 +43,17 @@ class JavadocParser( paragraphs.forEach { result.append(it) } + + if (element is PsiMethod) { + val tagsByName = element.searchInheritedTags() + for ((tagName, tags) in tagsByName) { + for ((tag, context) in tags) { + val section = result.addSection(javadocSectionDisplayName(tagName), tag.getSubjectName()) + section.convertJavadocElements(tag.contentElements(), context) + } + } + } + docComment.tags.forEach { tag -> when (tag.name) { "see" -> result.convertSeeTag(tag) @@ -51,6 +62,7 @@ class JavadocParser( convertJavadocElements(tag.contentElements(), element) } } + in tagsToInherit -> {} else -> { val subjectName = tag.getSubjectName() val section = result.addSection(javadocSectionDisplayName(tag.name), subjectName) @@ -62,6 +74,32 @@ class JavadocParser( return JavadocParseResult(result, deprecatedContent) } + private val tagsToInherit = setOf("param", "return", "throws") + + private data class TagWithContext(val tag: PsiDocTag, val context: PsiNamedElement) + + private fun PsiMethod.searchInheritedTags(): Map> { + + val output = tagsToInherit.keysToMap { mutableMapOf() } + + fun recursiveSearch(methods: Array) { + for (method in methods) { + recursiveSearch(method.findSuperMethods()) + } + for (method in methods) { + for (tag in method.docComment?.tags.orEmpty()) { + if (tag.name in tagsToInherit) { + output[tag.name]!![tag.getSubjectName()] = TagWithContext(tag, method) + } + } + } + } + + recursiveSearch(arrayOf(this)) + return output.mapValues { it.value.values } + } + + private fun PsiDocTag.contentElements(): Iterable { val tagValueElements = children .dropWhile { it.node?.elementType == JavaDocTokenType.DOC_TAG_NAME } -- cgit From a50de81d3d0ce88d2fd8e91a55b203ba49e66eb1 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 4 May 2018 00:32:40 +0300 Subject: [backport] KT-24028: Add type info to param and return section in javadoc Original: a603157 --- core/src/main/kotlin/Java/JavadocParser.kt | 23 +++++++++++++++++++++++ core/src/main/kotlin/Model/Content.kt | 30 +++++++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 41b77aed..5e23e357 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -28,6 +28,18 @@ class JavadocParser( private val logger: DokkaLogger, private val signatureProvider: ElementSignatureProvider ) : JavaDocumentationParser { + + private fun ContentSection.appendTypeElement(signature: String, selector: (DocumentationNode) -> DocumentationNode?) { + append(LazyContentBlock { + val node = refGraph.lookupOrWarn(signature, logger)?.let(selector) + if (node != null) { + it.append(NodeRenderContent(node, LanguageService.RenderMode.SUMMARY)) + it.symbol(":") + it.text(" ") + } + }) + } + override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult { val docComment = (element as? PsiDocCommentOwner)?.docComment if (docComment == null) return JavadocParseResult.Empty @@ -49,6 +61,17 @@ class JavadocParser( for ((tagName, tags) in tagsByName) { for ((tag, context) in tags) { val section = result.addSection(javadocSectionDisplayName(tagName), tag.getSubjectName()) + val signature = signatureProvider.signature(element) + when (tagName) { + "param" -> { + section.appendTypeElement(signature) { + it.details.find { it.kind == NodeKind.Parameter }?.detailOrNull(NodeKind.Type) + } + } + "return" -> { + section.appendTypeElement(signature) { it.detailOrNull(NodeKind.Type) } + } + } section.convertJavadocElements(tag.contentElements(), context) } } diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 1f5bbc83..010ee7ca 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -9,7 +9,7 @@ object ContentEmpty : ContentNode { } open class ContentBlock() : ContentNode { - val children = arrayListOf() + open val children = arrayListOf() fun append(node: ContentNode) { children.add(node) @@ -27,6 +27,34 @@ open class ContentBlock() : ContentNode { get() = children.sumBy { it.textLength } } +class NodeRenderContent( + val node: DocumentationNode, + val mode: LanguageService.RenderMode +): ContentNode { + override val textLength: Int + get() = 0 //TODO: Clarify? +} + +class LazyContentBlock(private val fillChildren: (ContentBlock) -> Unit) : ContentBlock() { + private var computed = false + override val children: ArrayList + get() { + if (!computed) { + computed = true + fillChildren(this) + } + return super.children + } + + override fun equals(other: Any?): Boolean { + return other is LazyContentBlock && other.fillChildren == fillChildren && super.equals(other) + } + + override fun hashCode(): Int { + return super.hashCode() + 31 * fillChildren.hashCode() + } +} + enum class IdentifierKind { TypeName, ParameterName, -- cgit From cf8b820682cf7af82d15f46f742d63a7766fe95e Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 4 May 2018 18:31:06 +0300 Subject: KT-24270: Render platform-types with bang --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 88fe7095..c165045d 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -242,7 +242,9 @@ class DocumentationBuilder if (prefix != "") { node.appendTextNode(prefix, NodeKind.Modifier) } - if (kotlinType.isMarkedNullable) { + if (kotlinType.isNullabilityFlexible()) { + node.appendTextNode("!", NodeKind.NullabilityModifier) + } else if (kotlinType.isNullable()) { node.appendTextNode("?", NodeKind.NullabilityModifier) } if (classifierDescriptor != null) { -- cgit From b00dabc4c53a71f745c29a135541b02f8dd7d266 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 4 May 2018 21:35:02 +0300 Subject: [backport] KT-24271: Support external link resolution in JavadocParser Original: ace3914 --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 8 ++-- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 10 ++++- core/src/main/kotlin/Java/JavadocParser.kt | 51 ++++++++++++++++------ .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 12 +++-- .../Kotlin/ExternalDocumentationLinkResolver.kt | 14 ++++-- .../Kotlin/KotlinElementSignatureProvider.kt | 30 ++++++------- core/src/main/kotlin/Utilities/DokkaModules.kt | 3 +- 7 files changed, 87 insertions(+), 41 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index 6854b323..d31fe187 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -99,7 +99,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } - fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade { + fun createResolutionFacade(environment: KotlinCoreEnvironment): Pair { val projectContext = ProjectContext(environment.project) val sourceFiles = environment.getSourceFiles() @@ -164,15 +164,17 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { builtIns = builtIns ) - resolverForProject.resolverForModule(library) // Required before module to initialize library properly + val resolverForLibrary = resolverForProject.resolverForModule(library) // Required before module to initialize library properly val resolverForModule = resolverForProject.resolverForModule(module) + val libraryModuleDescriptor = resolverForProject.descriptorForModule(library) val moduleDescriptor = resolverForProject.descriptorForModule(module) builtIns.initialize(moduleDescriptor, true) + val libraryResolutionFacade = DokkaResolutionFacade(environment.project, libraryModuleDescriptor, resolverForLibrary) val created = DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule) val projectComponentManager = environment.project as MockComponentManager projectComponentManager.registerService(KotlinCacheService::class.java, CoreKotlinCacheService(created)) - return created + return created to libraryResolutionFacade } fun loadLanguageVersionSettings(languageVersionString: String?, apiVersionString: String?) { diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 646096e5..8b30a6b4 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -45,10 +45,16 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private val refGraph: NodeReferenceGraph private val docParser: JavaDocumentationParser - @Inject constructor(options: DocumentationOptions, refGraph: NodeReferenceGraph, logger: DokkaLogger, signatureProvider: ElementSignatureProvider) { + @Inject constructor( + options: DocumentationOptions, + refGraph: NodeReferenceGraph, + logger: DokkaLogger, + signatureProvider: ElementSignatureProvider, + externalDocumentationLinkResolver: ExternalDocumentationLinkResolver + ) { this.options = options this.refGraph = refGraph - this.docParser = JavadocParser(refGraph, logger, signatureProvider) + this.docParser = JavadocParser(refGraph, logger, signatureProvider, externalDocumentationLinkResolver) } 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 5e23e357..e1b15cb2 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -26,7 +26,8 @@ interface JavaDocumentationParser { class JavadocParser( private val refGraph: NodeReferenceGraph, private val logger: DokkaLogger, - private val signatureProvider: ElementSignatureProvider + private val signatureProvider: ElementSignatureProvider, + private val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver ) : JavaDocumentationParser { private fun ContentSection.appendTypeElement(signature: String, selector: (DocumentationNode) -> DocumentationNode?) { @@ -197,25 +198,41 @@ class JavadocParser( private fun MutableContent.convertSeeTag(tag: PsiDocTag) { val linkElement = tag.linkElement() ?: return val seeSection = findSectionByTag(ContentTags.SeeAlso) ?: addSection(ContentTags.SeeAlso, null) - val linkSignature = resolveLink(tag.referenceElement()) + + val valueElement = tag.referenceElement() + val externalLink = resolveExternalLink(valueElement) val text = ContentText(linkElement.text) - if (linkSignature != null) { - val linkNode = - ContentNodeLazyLink((tag.valueElement ?: linkElement).text, { -> refGraph.lookupOrWarn(linkSignature, logger) }) - linkNode.append(text) - seeSection.append(linkNode) - } else { - seeSection.append(text) + + val linkSignature by lazy { resolveInternalLink(valueElement) } + val node = when { + externalLink != null -> { + val linkNode = ContentExternalLink(externalLink) + linkNode.append(text) + linkNode + } + linkSignature != null -> { + val linkNode = + ContentNodeLazyLink( + (tag.valueElement ?: linkElement).text, + { -> refGraph.lookupOrWarn(linkSignature, logger) } + ) + linkNode.append(text) + linkNode + } + else -> text } + seeSection.append(node) } private fun convertInlineDocTag(tag: PsiInlineDocTag, element: PsiNamedElement) = when (tag.name) { "link", "linkplain" -> { val valueElement = tag.referenceElement() - val linkSignature = resolveLink(valueElement) - if (linkSignature != null) { + val externalLink = resolveExternalLink(valueElement) + val linkSignature by lazy { resolveInternalLink(valueElement) } + if (externalLink != null || linkSignature != null) { val labelText = tag.dataElements.firstOrNull { it is PsiDocToken }?.text ?: valueElement!!.text - val link = "${labelText.htmlEscape()}" + val linkTarget = if (externalLink != null) "href=\"$externalLink\"" else "docref=\"$linkSignature\"" + val link = "${labelText.htmlEscape()}" if (tag.name == "link") "$link" else link } else if (valueElement != null) { valueElement.text @@ -256,7 +273,15 @@ class JavadocParser( private fun PsiDocTag.linkElement(): PsiElement? = valueElement ?: dataElements.firstOrNull { it !is PsiWhiteSpace } - private fun resolveLink(valueElement: PsiElement?): String? { + private fun resolveExternalLink(valueElement: PsiElement?): String? { + val target = valueElement?.reference?.resolve() + if (target != null) { + return externalDocumentationLinkResolver.buildExternalDocumentationLink(target) + } + return null + } + + private fun resolveInternalLink(valueElement: PsiElement?): String? { val target = valueElement?.reference?.resolve() if (target != null) { return signatureProvider.signature(target) diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 5f1118e8..7817da18 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -34,8 +34,9 @@ class DescriptorDocumentationParser val resolutionFacade: DokkaResolutionFacade, val refGraph: NodeReferenceGraph, val sampleService: SampleProcessingService, - val signatureProvider: KotlinElementSignatureProvider - ) + val signatureProvider: KotlinElementSignatureProvider, + val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver +) { fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false): Content = parseDocumentationAndDetails(descriptor, inline).first @@ -131,7 +132,12 @@ class DescriptorDocumentationParser fun parseJavadoc(descriptor: DeclarationDescriptor): Pair Unit> { val psi = ((descriptor as? DeclarationDescriptorWithSource)?.source as? PsiSourceElement)?.psi if (psi is PsiDocCommentOwner) { - val parseResult = JavadocParser(refGraph, logger, signatureProvider).parseDocumentation(psi as PsiNamedElement) + val parseResult = JavadocParser( + refGraph, + logger, + signatureProvider, + externalDocumentationLinkResolver + ).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/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index 7be37177..c766b869 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.Singleton +import com.intellij.psi.PsiElement import com.intellij.psi.PsiMethod import com.intellij.util.io.* import org.jetbrains.dokka.Formats.FileGeneratorBasedFormatDescriptor @@ -10,10 +11,7 @@ import org.jetbrains.dokka.Utilities.ServiceLocator import org.jetbrains.dokka.Utilities.lookup import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor -import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor +import org.jetbrains.kotlin.load.java.descriptors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe @@ -25,6 +23,7 @@ import java.net.URL import java.net.URLConnection import java.nio.file.Path import java.security.MessageDigest +import javax.inject.Named import kotlin.reflect.full.findAnnotation fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format(it) } @@ -32,6 +31,7 @@ fun ByteArray.toHexString() = this.joinToString(separator = "") { "%02x".format( @Singleton class ExternalDocumentationLinkResolver @Inject constructor( val options: DocumentationOptions, + @Named("libraryResolutionFacade") val libraryResolutionFacade: DokkaResolutionFacade, val logger: DokkaLogger ) { @@ -166,6 +166,12 @@ class ExternalDocumentationLinkResolver @Inject constructor( } } + fun buildExternalDocumentationLink(element: PsiElement): String? { + return element.extractDescriptor(libraryResolutionFacade)?.let { + buildExternalDocumentationLink(it) + } + } + fun buildExternalDocumentationLink(symbol: DeclarationDescriptor): String? { val packageFqName: FqName = when (symbol) { diff --git a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt index 0a377dc1..bcac0182 100644 --- a/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt +++ b/core/src/main/kotlin/Kotlin/KotlinElementSignatureProvider.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import com.intellij.psi.PsiElement import com.intellij.psi.PsiMember -import com.intellij.psi.PsiNameIdentifierOwner import com.intellij.psi.PsiPackage import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.descriptors.DeclarationDescriptor @@ -14,21 +13,22 @@ class KotlinElementSignatureProvider @Inject constructor( val resolutionFacade: DokkaResolutionFacade ) : ElementSignatureProvider { override fun signature(forPsi: PsiElement): String { - - val desc = when (forPsi) { - is KtLightElement<*, *> -> return signature(forPsi.kotlinOrigin!!) - is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName)) - is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) - else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] - } - - if (desc == null && (forPsi as? PsiNameIdentifierOwner)?.name == "remove") { - (forPsi as? PsiMember)?.getJavaOrKotlinMemberDescriptor(resolutionFacade) - } - - return desc?.let { signature(it) } + return forPsi.extractDescriptor(resolutionFacade) + ?.let { signature(it) } ?: run { "no desc for $forPsi in ${(forPsi as? PsiMember)?.containingClass}" } } override fun signature(forDesc: DeclarationDescriptor): String = forDesc.signature() -} \ No newline at end of file +} + + +fun PsiElement.extractDescriptor(resolutionFacade: DokkaResolutionFacade): DeclarationDescriptor? { + val forPsi = this + + return when (forPsi) { + is KtLightElement<*, *> -> return (forPsi.kotlinOrigin!!).extractDescriptor(resolutionFacade) + is PsiPackage -> resolutionFacade.moduleDescriptor.getPackage(FqName(forPsi.qualifiedName)) + is PsiMember -> forPsi.getJavaOrKotlinMemberDescriptor(resolutionFacade) + else -> resolutionFacade.resolveSession.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, forPsi] + } +} diff --git a/core/src/main/kotlin/Utilities/DokkaModules.kt b/core/src/main/kotlin/Utilities/DokkaModules.kt index 907d5ca7..732cbc48 100644 --- a/core/src/main/kotlin/Utilities/DokkaModules.kt +++ b/core/src/main/kotlin/Utilities/DokkaModules.kt @@ -24,8 +24,9 @@ class DokkaAnalysisModule(val environment: AnalysisEnvironment, val coreEnvironment = environment.createCoreEnvironment() binder.bind().toInstance(coreEnvironment) - val dokkaResolutionFacade = environment.createResolutionFacade(coreEnvironment) + val (dokkaResolutionFacade, libraryResolutionFacade) = environment.createResolutionFacade(coreEnvironment) binder.bind().toInstance(dokkaResolutionFacade) + binder.bind().annotatedWith(Names.named("libraryResolutionFacade")).toInstance(libraryResolutionFacade) binder.bind().toInstance(options) -- cgit From 3c6be4a1dbbcfec5e5438452f54857cce86d0d17 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 4 May 2018 21:35:36 +0300 Subject: Fix resolution of inbound links to constructors in Javadoc --- core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt index c766b869..a8129793 100644 --- a/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt +++ b/core/src/main/kotlin/Kotlin/ExternalDocumentationLinkResolver.kt @@ -216,7 +216,7 @@ interface InboundExternalLinkResolutionService { val containingClass = symbol.containingDeclaration as? JavaClassDescriptor ?: return null val containingClassLink = getPath(containingClass) if (containingClassLink != null) { - if (symbol is JavaMethodDescriptor) { + if (symbol is JavaMethodDescriptor || symbol is JavaClassConstructorDescriptor) { val psi = symbol.sourcePsi() as? PsiMethod if (psi != null) { val params = psi.parameterList.parameters.joinToString { it.type.canonicalText } -- cgit From 6361dd32aaf567c8e03e4aa63006193dc67cca7b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 5 May 2018 01:54:31 +0300 Subject: Fix relative uri's generation when there is matching trailing segments --- core/src/main/kotlin/Utilities/Uri.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Utilities/Uri.kt b/core/src/main/kotlin/Utilities/Uri.kt index 5b520188..9827c624 100644 --- a/core/src/main/kotlin/Utilities/Uri.kt +++ b/core/src/main/kotlin/Utilities/Uri.kt @@ -19,7 +19,7 @@ fun URI.relativeTo(uri: URI): URI { } // Compute common prefix - val commonPartsSize = bParts.zip(cParts).count { (basePart, childPart) -> basePart == childPart } + val commonPartsSize = bParts.zip(cParts).takeWhile { (basePart, childPart) -> basePart == childPart }.count() bParts.drop(commonPartsSize).joinTo(this, separator = "") { "../" } cParts.drop(commonPartsSize).joinTo(this, separator = "/") } -- cgit From e38d83905ff706b2d656f12896a6905f5a0729d7 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 5 May 2018 01:58:55 +0300 Subject: Fix inbound links to enum entries --- .../Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt index 6d9b5fd0..09bb2602 100644 --- a/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt +++ b/core/src/main/kotlin/Formats/JavaLayoutHtml/JavaLayoutHtmlPackageListService.kt @@ -3,6 +3,7 @@ package org.jetbrains.dokka.Formats import org.jetbrains.dokka.* import org.jetbrains.dokka.ExternalDocumentationLinkResolver.Companion.DOKKA_PARAM_PREFIX import org.jetbrains.kotlin.descriptors.* +import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe import org.jetbrains.kotlin.resolve.descriptorUtil.isCompanionObject import org.jetbrains.kotlin.types.KotlinType @@ -33,7 +34,7 @@ class JavaLayoutHtmlPackageListService: PackageListService { class JavaLayoutHtmlInboundLinkResolutionService(private val paramMap: Map>) : InboundExternalLinkResolutionService { private fun getContainerPath(symbol: DeclarationDescriptor): String? { return when (symbol) { - is PackageFragmentDescriptor -> symbol.fqName.asString() + "/" + is PackageFragmentDescriptor -> symbol.fqName.asString().replace('.', '/') + "/" is ClassifierDescriptor -> getContainerPath(symbol.findPackage()) + symbol.nameWithOuter() + ".html" else -> null } @@ -49,6 +50,7 @@ class JavaLayoutHtmlInboundLinkResolutionService(private val paramMap: Map getContainerPath(symbol) + "package-summary.html" + is EnumEntrySyntheticClassDescriptor -> getContainerPath(symbol.containingDeclaration) + "#" + symbol.signatureForAnchorUrlEncoded() is ClassifierDescriptor -> getContainerPath(symbol) + "#" is FunctionDescriptor, is PropertyDescriptor -> getContainerPath(symbol.containingDeclaration!!) + "#" + symbol.signatureForAnchorUrlEncoded() else -> null @@ -88,6 +90,10 @@ class JavaLayoutHtmlInboundLinkResolutionService(private val paramMap: Map buildString { + append("ENUM_VALUE:") + append(name.asString()) + } is FunctionDescriptor -> buildString { appendReceiverAndCompanion(this@signatureForAnchor) append(name.asString()) -- cgit From 44ad68386658dde985207ea0aedb19c96d9b3f93 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 7 May 2018 16:37:12 +0300 Subject: [backport] KT-24277: Persist inpage anchors (aka bookmarks) from Javadoc Original: 4fddba5 --- core/src/main/kotlin/Java/JavadocParser.kt | 22 +++++++++++++--------- core/src/main/kotlin/Model/Content.kt | 2 ++ 2 files changed, 15 insertions(+), 9 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index e1b15cb2..8cd274e7 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -183,15 +183,19 @@ class JavadocParser( } private fun createLink(element: Element): ContentBlock { - if (element.hasAttr("docref")) { - val docref = element.attr("docref") - return ContentNodeLazyLink(docref, { -> refGraph.lookupOrWarn(docref, logger) }) - } - return if (element.hasAttr("href")) { - val href = element.attr("href") - ContentExternalLink(href) - } else { - ContentBlock() + return when { + element.hasAttr("docref") -> { + val docref = element.attr("docref") + ContentNodeLazyLink(docref, { -> refGraph.lookupOrWarn(docref, logger) }) + } + element.hasAttr("href") -> { + val href = element.attr("href") + ContentExternalLink(href) + } + element.hasAttr("name") -> { + ContentBookmark(element.attr("name")) + } + else -> ContentBlock() } } diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 010ee7ca..4f142ca4 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -148,6 +148,8 @@ class ContentExternalLink(val href : String) : ContentBlock() { children.hashCode() * 31 + href.hashCode() } +data class ContentBookmark(val name: String): ContentBlock() + class ContentUnorderedList() : ContentBlock() class ContentOrderedList() : ContentBlock() class ContentListItem() : ContentBlock() -- cgit From 4301503416ed45783a81250295adf4b5a86c4280 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 7 May 2018 17:28:22 +0300 Subject: [backport] KT-24299: Fix local links resolved in incorrect context Original: fababd4 --- core/src/main/kotlin/Java/JavadocParser.kt | 14 +++++++++++++- core/src/main/kotlin/Model/Content.kt | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 8cd274e7..9f9ea017 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -12,6 +12,7 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Element import org.jsoup.nodes.Node import org.jsoup.nodes.TextNode +import java.net.URI data class JavadocParseResult(val content: Content, val deprecatedContent: Content?) { companion object { @@ -190,7 +191,18 @@ class JavadocParser( } element.hasAttr("href") -> { val href = element.attr("href") - ContentExternalLink(href) + + val uri = try { + URI(href) + } catch (_: Exception) { + null + } + + if (uri?.isAbsolute == false) { + ContentLocalLink(href) + } else { + ContentExternalLink(href) + } } element.hasAttr("name") -> { ContentBookmark(element.attr("name")) diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 4f142ca4..7c776bdb 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -149,6 +149,7 @@ class ContentExternalLink(val href : String) : ContentBlock() { } data class ContentBookmark(val name: String): ContentBlock() +data class ContentLocalLink(val href: String) : ContentBlock() class ContentUnorderedList() : ContentBlock() class ContentOrderedList() : ContentBlock() -- cgit From f301316151dc15b67d926423021abc5e3313aa2a Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 7 May 2018 20:08:43 +0300 Subject: KT-24300: Support inclusion overview.html into package summary --- core/src/main/kotlin/Generation/DokkaGenerator.kt | 15 ++++- core/src/main/kotlin/Model/PackageDocs.kt | 69 ++++++++++++++++++++++- 2 files changed, 82 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 33170f35..91471849 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode -import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis @@ -157,6 +156,8 @@ fun buildDocumentationModule(injector: Injector, } } + parseJavaPackageDocs(packageDocs, coreEnvironment) + with(injector.getInstance(DocumentationBuilder::class.java)) { documentationModule.appendFragments(fragments, packageDocs.packageContent, injector.getInstance(PackageDocumentationBuilder::class.java)) @@ -170,6 +171,18 @@ fun buildDocumentationModule(injector: Injector, } } +fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEnvironment) { + val contentRoots = coreEnvironment.configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + ?.filterIsInstance() + ?.map { it.file } + ?: listOf() + contentRoots.forEach { root -> + root.walkTopDown().filter { it.name == "overview.html" }.forEach { + packageDocs.parseJava(it.path, it.relativeTo(root).parent.replace("/", ".")) + } + } +} + fun KotlinCoreEnvironment.getJavaSourceFiles(): List { val sourceRoots = configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) diff --git a/core/src/main/kotlin/Model/PackageDocs.kt b/core/src/main/kotlin/Model/PackageDocs.kt index 1f6bdcb9..5b628914 100644 --- a/core/src/main/kotlin/Model/PackageDocs.kt +++ b/core/src/main/kotlin/Model/PackageDocs.kt @@ -2,16 +2,25 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.Singleton +import com.intellij.ide.highlighter.JavaFileType +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiFileFactory +import com.intellij.psi.util.PsiTreeUtil +import com.intellij.util.LocalTimeCounter import org.intellij.markdown.MarkdownElementTypes import org.intellij.markdown.MarkdownTokenTypes import org.intellij.markdown.parser.LinkMap +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import java.io.File @Singleton class PackageDocs @Inject constructor(val linkResolver: DeclarationLinkResolver?, - val logger: DokkaLogger) + val logger: DokkaLogger, + val environment: KotlinCoreEnvironment, + val refGraph: NodeReferenceGraph, + val elementSignatureProvider: ElementSignatureProvider) { val moduleContent: MutableContent = MutableContent() private val _packageContent: MutableMap = hashMapOf() @@ -40,6 +49,64 @@ class PackageDocs } } + private fun parseHtmlAsJavadoc(text: String, packageName: String, file: File) { + val javadocText = text + .replace("*/", "*/") + .removeSurrounding("", "", true).trim() + .removeSurrounding("", "", true) + .lineSequence() + .map { "* $it" } + .joinToString (separator = "\n", prefix = "/**\n", postfix = "\n*/") + parseJavadoc(javadocText, packageName, file) + } + + private fun CharSequence.removeSurrounding(prefix: CharSequence, suffix: CharSequence, ignoringCase: Boolean = false): CharSequence { + if ((length >= prefix.length + suffix.length) && startsWith(prefix, ignoringCase) && endsWith(suffix, ignoringCase)) { + return subSequence(prefix.length, length - suffix.length) + } + return subSequence(0, length) + } + + + private fun parseJavadoc(text: String, packageName: String, file: File) { + + val psiFileFactory = PsiFileFactory.getInstance(environment.project) + val psiFile = psiFileFactory.createFileFromText( + file.nameWithoutExtension + ".java", + JavaFileType.INSTANCE, + "package $packageName; $text\npublic class C {}", + LocalTimeCounter.currentTime(), + false, + true + ) + + val psiClass = PsiTreeUtil.getChildOfType(psiFile, PsiClass::class.java)!! + val parser = JavadocParser(refGraph, logger, elementSignatureProvider, linkResolver?.externalDocumentationLinkResolver!!) + findOrCreatePackageContent(packageName).apply { + val content = parser.parseDocumentation(psiClass).content + children.addAll(content.children) + content.sections.forEach { + addSection(it.tag, it.subjectName).children.addAll(it.children) + } + } + } + + + fun parseJava(fileName: String, packageName: String) { + val file = File(fileName) + if (file.exists()) { + val text = file.readText() + + val trimmedText = text.trim() + + if (trimmedText.startsWith("/**")) { + parseJavadoc(text, packageName, file) + } else if (trimmedText.toLowerCase().startsWith("")) { + parseHtmlAsJavadoc(trimmedText, packageName, file) + } + } + } + private fun findTargetContent(heading: String): MutableContent { if (heading.startsWith("Module") || heading.startsWith("module")) { return moduleContent -- cgit From b46ec0a7ccfb3a7347fd5d3717cc4b3aedf75429 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 8 May 2018 01:44:16 +0300 Subject: Fix nullability detection --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index c165045d..e6a75277 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -244,7 +244,7 @@ class DocumentationBuilder } if (kotlinType.isNullabilityFlexible()) { node.appendTextNode("!", NodeKind.NullabilityModifier) - } else if (kotlinType.isNullable()) { + } else if (kotlinType.isMarkedNullable) { node.appendTextNode("?", NodeKind.NullabilityModifier) } if (classifierDescriptor != null) { -- cgit From 9715d6300d6e0082a3e900c7e5cff873b8c294f2 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 26 May 2018 00:12:38 +0300 Subject: Provide signature for packages --- core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt | 1 + 1 file changed, 1 insertion(+) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 8b30a6b4..6d5825e9 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.KtModifierListOwner import java.io.File fun getSignature(element: PsiElement?) = when(element) { + is PsiPackage -> element.qualifiedName is PsiClass -> element.qualifiedName is PsiField -> element.containingClass!!.qualifiedName + "$" + element.name is PsiMethod -> -- cgit From 633fda36403e8c5483054737d285dd01b5c190bb Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 26 May 2018 00:15:47 +0300 Subject: KT-24025: Support constants in as java mode #KT-24025 fixed --- .../main/kotlin/Java/JavaPsiDocumentationBuilder.kt | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 6d5825e9..9eabc227 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -1,7 +1,9 @@ package org.jetbrains.dokka import com.google.inject.Inject +import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.* +import com.intellij.psi.impl.JavaConstantExpressionEvaluator import com.intellij.psi.util.InheritanceUtil import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration @@ -207,11 +209,28 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { fun PsiField.build(): DocumentationNode { val node = nodeForElement(this, nodeKind()) node.appendType(type) - node.appendModifiers(this) + + node.appendConstantValueIfAny(this) register(this, node) return node } + private fun DocumentationNode.appendConstantValueIfAny(field: PsiField) { + val modifierList = field.modifierList ?: return + val initializer = field.initializer ?: return + if (field.type is PsiPrimitiveType && + modifierList.hasExplicitModifier(PsiModifier.FINAL) && + modifierList.hasExplicitModifier(PsiModifier.STATIC)) { + val value = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false) + val text = when(value) { + is String -> + "\"" + StringUtil.escapeStringCharacters(value) + "\"" + else -> value.toString() + } + append(DocumentationNode(text, Content.Empty, NodeKind.Value), RefKind.Detail) + } + } + private fun PsiField.nodeKind(): NodeKind = when { this is PsiEnumConstant -> NodeKind.EnumItem else -> NodeKind.Field -- cgit From f5746c40cbb44204edd137b3183ef0d04958047b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 26 May 2018 00:19:54 +0300 Subject: KT-24624: Partial, more detailed signature on class page --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 20 ++++---------------- .../main/kotlin/Languages/CommonLanguageService.kt | 18 ++++++++++++++++++ .../main/kotlin/Languages/NewJavaLanguageService.kt | 9 +++++++-- 3 files changed, 29 insertions(+), 18 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index b6474583..237fa9b9 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -7,6 +7,10 @@ import org.jetbrains.dokka.LanguageService.RenderMode * Implements [LanguageService] and provides rendering of symbols in Kotlin language */ class KotlinLanguageService : CommonLanguageService() { + override fun showModifierInSummary(node: DocumentationNode): Boolean { + return node.name !in fullOnlyModifiers + } + private val fullOnlyModifiers = setOf("public", "protected", "private", "inline", "noinline", "crossinline", "reified") @@ -283,22 +287,6 @@ class KotlinLanguageService : CommonLanguageService() { } } - private fun ContentBlock.renderModifiersForNode( - node: DocumentationNode, - renderMode: RenderMode, - nowrap: Boolean = false - ) { - val modifiers = node.details(NodeKind.Modifier) - for (it in modifiers) { - if (node.kind == org.jetbrains.dokka.NodeKind.Interface && it.name == "abstract") - continue - if (renderMode == RenderMode.SUMMARY && it.name in fullOnlyModifiers) { - continue - } - renderModifier(this, it, renderMode, nowrap) - } - } - private fun ContentBlock.renderAnnotationsForNode(node: DocumentationNode) { node.annotations.forEach { renderAnnotation(it) diff --git a/core/src/main/kotlin/Languages/CommonLanguageService.kt b/core/src/main/kotlin/Languages/CommonLanguageService.kt index edefa1b5..ddc95d32 100644 --- a/core/src/main/kotlin/Languages/CommonLanguageService.kt +++ b/core/src/main/kotlin/Languages/CommonLanguageService.kt @@ -62,5 +62,23 @@ abstract class CommonLanguageService : LanguageService { } } + abstract fun showModifierInSummary(node: DocumentationNode): Boolean + + protected fun ContentBlock.renderModifiersForNode( + node: DocumentationNode, + renderMode: LanguageService.RenderMode, + nowrap: Boolean = false + ) { + val modifiers = node.details(NodeKind.Modifier) + for (it in modifiers) { + if (node.kind == NodeKind.Interface && it.name == "abstract") + continue + if (renderMode == LanguageService.RenderMode.SUMMARY && !showModifierInSummary(it)) { + continue + } + renderModifier(this, it, renderMode, nowrap) + } + } + } \ No newline at end of file diff --git a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt index 0266c033..fa9f70fd 100644 --- a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt +++ b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt @@ -6,11 +6,15 @@ import org.jetbrains.dokka.LanguageService.RenderMode * Implements [LanguageService] and provides rendering of symbols in Java language */ class NewJavaLanguageService : CommonLanguageService() { + override fun showModifierInSummary(node: DocumentationNode): Boolean { + return true + } + override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode { return content { (when (node.kind) { NodeKind.Package -> renderPackage(node) - in NodeKind.classLike -> renderClass(node) + in NodeKind.classLike -> renderClass(node, renderMode) NodeKind.Modifier -> renderModifier(this, node, renderMode) NodeKind.TypeParameter -> renderTypeParameter(node) @@ -131,7 +135,8 @@ class NewJavaLanguageService : CommonLanguageService() { text(" ") } - private fun ContentBlock.renderClass(node: DocumentationNode) { + private fun ContentBlock.renderClass(node: DocumentationNode, renderMode: RenderMode) { + renderModifiersForNode(node, renderMode) renderClassKind(node) identifier(node.name) -- cgit From 23861925232505dbd70344a1d690f2475bb022e8 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 4 Jun 2018 16:23:34 +0300 Subject: [backport] Introduce option to enable/disable jdk linking Original: 8e9e768 --- core/src/main/kotlin/DokkaBootstrapImpl.kt | 39 +++++++++++----------- .../main/kotlin/Generation/configurationImpl.kt | 1 + .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 6 +++- core/src/test/kotlin/TestAPI.kt | 9 +++++ .../test/kotlin/format/KotlinWebSiteFormatTest.kt | 1 + .../kotlin/format/KotlinWebSiteHtmlFormatTest.kt | 1 + core/src/test/kotlin/format/MarkdownFormatTest.kt | 2 ++ core/src/test/kotlin/model/JavaTest.kt | 4 +-- .../kotlin/org/jetbrains/dokka/configuration.kt | 2 ++ runners/ant/src/main/kotlin/ant/dokka.kt | 2 ++ runners/gradle-plugin/src/main/kotlin/main.kt | 14 +++++--- 11 files changed, 54 insertions(+), 27 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/DokkaBootstrapImpl.kt b/core/src/main/kotlin/DokkaBootstrapImpl.kt index b7787be8..e18ab6cf 100644 --- a/core/src/main/kotlin/DokkaBootstrapImpl.kt +++ b/core/src/main/kotlin/DokkaBootstrapImpl.kt @@ -52,25 +52,26 @@ class DokkaBootstrapImpl : DokkaBootstrap { includes, moduleName, DocumentationOptions( - outputDir, - format, - includeNonPublic, - includeRootPackage, - reportUndocumented, - skipEmptyPackages, - skipDeprecated, - jdkVersion, - generateIndexPages, - sourceLinks, - impliedPlatforms, - perPackageOptions, - externalDocumentationLinks, - noStdlibLink, - languageVersion, - apiVersion, - cacheRoot, - suppressedFiles.map { File(it) }.toSet(), - collectInheritedExtensionsFromLibraries + outputDir = outputDir, + outputFormat = format, + includeNonPublic = includeNonPublic, + includeRootPackage = includeRootPackage, + reportUndocumented = reportUndocumented, + skipEmptyPackages = skipEmptyPackages, + skipDeprecated = skipDeprecated, + jdkVersion = jdkVersion, + generateIndexPages = generateIndexPages, + sourceLinks = sourceLinks, + impliedPlatforms = impliedPlatforms, + perPackageOptions = perPackageOptions, + externalDocumentationLinks = externalDocumentationLinks, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + languageVersion = languageVersion, + apiVersion = apiVersion, + cacheRoot = cacheRoot, + suppressedFiles = suppressedFiles.map { File(it) }.toSet(), + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries ) ) } diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 52e8446f..90e27b4b 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -55,6 +55,7 @@ data class DokkaConfigurationImpl( override val perPackageOptions: List, override val externalDocumentationLinks: List, override val noStdlibLink: Boolean, + override val noJdkLink: Boolean, override val cacheRoot: String?, override val suppressedFiles: List, override val languageVersion: String?, diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e6a75277..58f5e246 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -55,6 +55,7 @@ class DocumentationOptions(val outputDir: String, perPackageOptions: List = emptyList(), externalDocumentationLinks: List = emptyList(), noStdlibLink: Boolean, + noJdkLink: Boolean, val languageVersion: String?, val apiVersion: String?, cacheRoot: String? = null, @@ -72,7 +73,10 @@ class DocumentationOptions(val outputDir: String, fun effectivePackageOptions(pack: FqName): PackageOptions = effectivePackageOptions(pack.asString()) val defaultLinks = run { - val links = mutableListOf(ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build()) + val links = mutableListOf() + if (!noJdkLink) + links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + if (!noStdlibLink) links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() links diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index aeff9284..953e3bab 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -39,6 +39,7 @@ fun verifyModel(vararg roots: ContentRoot, perPackageOptions = perPackageOptions, generateIndexPages = false, noStdlibLink = noStdlibLink, + noJdkLink = false, cacheRoot = "default", languageVersion = null, apiVersion = null, @@ -269,6 +270,14 @@ fun StringBuilder.appendNode(node: ContentNode): StringBuilder { is ContentBlock -> { appendChildren(node) } + is NodeRenderContent -> { + append("render(") + append(node.node) + append(",") + append(node.mode) + append(")") + } + is ContentSymbol -> { append(node.text) } is ContentEmpty -> { /* nothing */ } else -> throw IllegalStateException("Don't know how to format node $node") } diff --git a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt index b971b54d..062cf0b5 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteFormatTest.kt @@ -54,6 +54,7 @@ class KotlinWebSiteFormatTest: FileGeneratorTestCase() { outputFormat = "html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index 49fa6d2f..8076fb92 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -65,6 +65,7 @@ class KotlinWebSiteHtmlFormatTest: FileGeneratorTestCase() { outputFormat = "kotlin-website-html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 9e4c831d..3723e5ae 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -313,6 +313,7 @@ class MarkdownFormatTest: FileGeneratorTestCase() { outputFormat = "html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) @@ -447,6 +448,7 @@ class MarkdownFormatTest: FileGeneratorTestCase() { outputFormat = "html", generateIndexPages = false, noStdlibLink = true, + noJdkLink = true, languageVersion = null, apiVersion = null ) diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index c2ede8f0..66eb84f1 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -18,12 +18,12 @@ public class JavaTest { with(content.sections[0]) { assertEquals("Parameters", tag) assertEquals("name", subjectName) - assertEquals("is String parameter", toTestString()) + assertEquals("render(Type:String,SUMMARY): is String parameter", toTestString()) } with(content.sections[1]) { assertEquals("Parameters", tag) assertEquals("value", subjectName) - assertEquals("is int parameter", toTestString()) + assertEquals("render(Type:String,SUMMARY): is int parameter", toTestString()) } with(content.sections[2]) { assertEquals("Author", tag) diff --git a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt index 46a57278..69d19944 100644 --- a/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt +++ b/integration/src/main/kotlin/org/jetbrains/dokka/configuration.kt @@ -39,6 +39,7 @@ interface DokkaConfiguration { val languageVersion: String? val apiVersion: String? val noStdlibLink: Boolean + val noJdkLink: Boolean val cacheRoot: String? val suppressedFiles: List val collectInheritedExtensionsFromLibraries: Boolean @@ -102,6 +103,7 @@ data class SerializeOnlyDokkaConfiguration( override val perPackageOptions: List, override val externalDocumentationLinks: List, override val noStdlibLink: Boolean, + override val noJdkLink: Boolean, override val cacheRoot: String?, override val suppressedFiles: List, override val languageVersion: String?, diff --git a/runners/ant/src/main/kotlin/ant/dokka.kt b/runners/ant/src/main/kotlin/ant/dokka.kt index d1b6bef5..79583a1f 100644 --- a/runners/ant/src/main/kotlin/ant/dokka.kt +++ b/runners/ant/src/main/kotlin/ant/dokka.kt @@ -40,6 +40,7 @@ class DokkaAntTask: Task() { var jdkVersion: Int = 6 var noStdlibLink: Boolean = false + var noJdkLink: Boolean = false var skipDeprecated: Boolean = false @@ -131,6 +132,7 @@ class DokkaAntTask: Task() { perPackageOptions = antPackageOptions, externalDocumentationLinks = antExternalDocumentationLinks.map { it.build() }, noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, cacheRoot = cacheRoot, languageVersion = languageVersion, apiVersion = apiVersion diff --git a/runners/gradle-plugin/src/main/kotlin/main.kt b/runners/gradle-plugin/src/main/kotlin/main.kt index 4812e217..d3a341e0 100644 --- a/runners/gradle-plugin/src/main/kotlin/main.kt +++ b/runners/gradle-plugin/src/main/kotlin/main.kt @@ -124,6 +124,9 @@ open class DokkaTask : DefaultTask() { @Input var noStdlibLink: Boolean = false + @Input + var noJdkLink: Boolean = false + @Optional @Input var cacheRoot: String? = null @@ -309,11 +312,12 @@ open class DokkaTask : DefaultTask() { perPackageOptions, externalDocumentationLinks, noStdlibLink, - cacheRoot, - collectSuppressedFiles(sourceRoots), - languageVersion, - apiVersion, - collectInheritedExtensionsFromLibraries + noJdkLink, + cacheRoot, + collectSuppressedFiles(sourceRoots), + languageVersion, + apiVersion, + collectInheritedExtensionsFromLibraries ) -- cgit From d228c23bf72e196476ac0b49871d54116e371110 Mon Sep 17 00:00:00 2001 From: Douglas Sigelbaum Date: Wed, 13 Jun 2018 12:11:06 -0700 Subject: Fix default param. --- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index 58f5e246..f1b8e3d3 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -55,7 +55,7 @@ class DocumentationOptions(val outputDir: String, perPackageOptions: List = emptyList(), externalDocumentationLinks: List = emptyList(), noStdlibLink: Boolean, - noJdkLink: Boolean, + noJdkLink: Boolean = false, val languageVersion: String?, val apiVersion: String?, cacheRoot: String? = null, -- cgit From 0485472951134685c434d148b6fe5b6393217023 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sat, 9 Jun 2018 23:51:43 +0300 Subject: KT-24032: Fix parameter rendering in asJava mode #KT-24032 fixed --- core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt | 12 +++++++----- core/src/main/kotlin/Languages/NewJavaLanguageService.kt | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 9eabc227..332afffb 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -148,11 +148,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { hasSuppressDocTag(element) || skipElementBySuppressedFiles(element) - private fun skipElementByVisibility(element: Any): Boolean = element is PsiModifierListOwner && - !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && - (element.hasModifierProperty(PsiModifier.PRIVATE) || - element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || - element.isInternal()) + private fun skipElementByVisibility(element: Any): Boolean = + element is PsiModifierListOwner && + element !is PsiParameter && + !(options.effectivePackageOptions((element.containingFile as? PsiJavaFile)?.packageName ?: "").includeNonPublic) && + (element.hasModifierProperty(PsiModifier.PRIVATE) || + element.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) || + element.isInternal()) private fun skipElementBySuppressedFiles(element: Any): Boolean = element is PsiElement && File(element.containingFile.virtualFile.path).absoluteFile in options.suppressedFiles diff --git a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt index fa9f70fd..992cd090 100644 --- a/core/src/main/kotlin/Languages/NewJavaLanguageService.kt +++ b/core/src/main/kotlin/Languages/NewJavaLanguageService.kt @@ -20,7 +20,7 @@ class NewJavaLanguageService : CommonLanguageService() { NodeKind.TypeParameter -> renderTypeParameter(node) NodeKind.Type, NodeKind.UpperBound -> renderType(node) - + NodeKind.Parameter -> renderParameter(node) NodeKind.Constructor, NodeKind.Function -> renderFunction(node) NodeKind.Property -> renderProperty(node) -- cgit From f30807f4e78939fb59f8e46c39b3e538070aacfd Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Sun, 15 Jul 2018 00:48:46 +0300 Subject: Fix missing functions after rebase --- core/src/main/kotlin/Analysis/JavaResolveExtension.kt | 2 +- core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt | 3 +-- core/src/main/kotlin/Generation/DokkaGenerator.kt | 1 + core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 1 - core/src/main/kotlin/Model/DocumentationNode.kt | 7 +++++-- 5 files changed, 8 insertions(+), 6 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt index f8992d45..4dc6b366 100644 --- a/core/src/main/kotlin/Analysis/JavaResolveExtension.kt +++ b/core/src/main/kotlin/Analysis/JavaResolveExtension.kt @@ -128,4 +128,4 @@ private fun Collection.findByJavaElemen } fun PsiElement.javaResolutionFacade() = - KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform) + KotlinCacheService.getInstance(project).getResolutionFacadeByFile(this.originalElement.containingFile, JvmPlatform)!! diff --git a/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt b/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt index f73cd23e..885cdf6c 100644 --- a/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt +++ b/core/src/main/kotlin/Formats/JavaLayoutHtmlFormat.kt @@ -6,7 +6,6 @@ import kotlinx.html.li import kotlinx.html.stream.appendHTML import kotlinx.html.ul import org.jetbrains.dokka.* -import org.jetbrains.dokka.Kotlin.KotlinDescriptorSignatureProvider import org.jetbrains.dokka.Samples.DefaultSampleProcessingService import org.jetbrains.dokka.Utilities.bind import org.jetbrains.dokka.Utilities.toType @@ -17,7 +16,7 @@ class JavaLayoutHtmlFormatDescriptor : FormatDescriptor, DefaultAnalysisComponen override val packageDocumentationBuilderClass = KotlinPackageDocumentationBuilder::class override val javaDocumentationBuilderClass = KotlinJavaDocumentationBuilder::class override val sampleProcessingService = DefaultSampleProcessingService::class - override val descriptorSignatureProvider = KotlinDescriptorSignatureProvider::class + override val elementSignatureProvider = KotlinElementSignatureProvider::class override fun configureOutput(binder: Binder): Unit = with(binder) { bind() toType generatorServiceClass diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 91471849..46fdaf0a 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode +import org.jetbrains.kotlin.utils.PathUtil import java.io.File import kotlin.system.measureTimeMillis diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 237fa9b9..6088d3a5 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -1,6 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.Formats.classNodeNameWithOuterClass import org.jetbrains.dokka.LanguageService.RenderMode /** diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a89f5080..a3388031 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,7 +1,5 @@ package org.jetbrains.dokka -import org.jetbrains.dokka.Formats.constantValue -import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import java.util.* enum class NodeKind { @@ -242,4 +240,9 @@ private fun DocumentationNode.isSuperclassFor(node: DocumentationNode): Boolean NodeKind.Exception -> kind == NodeKind.Class || kind == NodeKind.Exception else -> false } +} + +fun DocumentationNode.classNodeNameWithOuterClass(): String { + assert(kind in NodeKind.classLike) + return path.dropWhile { it.kind == NodeKind.Package || it.kind == NodeKind.Module }.joinToString(separator = ".") { it.name } } \ No newline at end of file -- cgit From 17dd9747828a2ba8275714dc421a415c68d01615 Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Fri, 22 Jun 2018 10:25:09 +0200 Subject: convert line separators in PackageDocs, fixes PackageDocsTest --- core/src/main/kotlin/Model/PackageDocs.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Model/PackageDocs.kt b/core/src/main/kotlin/Model/PackageDocs.kt index 1f6bdcb9..bb8e98d1 100644 --- a/core/src/main/kotlin/Model/PackageDocs.kt +++ b/core/src/main/kotlin/Model/PackageDocs.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.Singleton +import com.intellij.openapi.util.text.StringUtil import org.intellij.markdown.MarkdownElementTypes import org.intellij.markdown.MarkdownTokenTypes import org.intellij.markdown.parser.LinkMap @@ -21,7 +22,7 @@ class PackageDocs fun parse(fileName: String, linkResolveContext: List) { val file = File(fileName) if (file.exists()) { - val text = file.readText() + val text = StringUtil.convertLineSeparators(file.readText()) val tree = parseMarkdown(text) val linkMap = LinkMap.buildLinkMap(tree.node, text) var targetContent: MutableContent = moduleContent @@ -51,7 +52,7 @@ class PackageDocs } private fun findOrCreatePackageContent(packageName: String) = - _packageContent.getOrPut(packageName) { -> MutableContent() } + _packageContent.getOrPut(packageName) { MutableContent() } private fun resolveContentLink(fileName: String, href: String, linkResolveContext: List): ContentBlock { if (linkResolver != null) { -- cgit From 7ef0cf32835d6d652e408a2115d58c37749320c5 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 29 Oct 2018 17:12:47 +0300 Subject: Cleanup support for NodeRenderContent --- core/src/main/kotlin/Formats/StructuredFormatService.kt | 4 ++++ core/src/main/kotlin/Java/JavadocParser.kt | 12 ++++++------ core/src/main/kotlin/Model/Content.kt | 4 ++-- core/src/test/kotlin/model/JavaTest.kt | 2 +- 4 files changed, 13 insertions(+), 9 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt index ebc9cde6..410de281 100644 --- a/core/src/main/kotlin/Formats/StructuredFormatService.kt +++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt @@ -152,6 +152,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder, } } + is NodeRenderContent -> { + val node = content.node + appendContent(languageService.render(node, content.mode)) + } is ContentNodeLink -> { val node = content.node val linkTo = if (node != null) locationHref(location, node) else "#" diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 9f9ea017..1144763b 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -33,12 +33,12 @@ class JavadocParser( private fun ContentSection.appendTypeElement(signature: String, selector: (DocumentationNode) -> DocumentationNode?) { append(LazyContentBlock { - val node = refGraph.lookupOrWarn(signature, logger)?.let(selector) - if (node != null) { - it.append(NodeRenderContent(node, LanguageService.RenderMode.SUMMARY)) - it.symbol(":") - it.text(" ") - } + val node = refGraph.lookupOrWarn(signature, logger)?.let(selector) ?: return@LazyContentBlock emptyList() + listOf(ContentBlock().apply { + append(NodeRenderContent(node, LanguageService.RenderMode.SUMMARY)) + symbol(":") + text(" ") + }) }) } diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 7c776bdb..87a8023a 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -35,13 +35,13 @@ class NodeRenderContent( get() = 0 //TODO: Clarify? } -class LazyContentBlock(private val fillChildren: (ContentBlock) -> Unit) : ContentBlock() { +class LazyContentBlock(private val fillChildren: () -> List) : ContentBlock() { private var computed = false override val children: ArrayList get() { if (!computed) { computed = true - fillChildren(this) + children.addAll(fillChildren()) } return super.children } diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index 66eb84f1..876d18c0 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -23,7 +23,7 @@ public class JavaTest { with(content.sections[1]) { assertEquals("Parameters", tag) assertEquals("value", subjectName) - assertEquals("render(Type:String,SUMMARY): is int parameter", toTestString()) + assertEquals("render(Type:Int,SUMMARY): is int parameter", toTestString()) } with(content.sections[2]) { assertEquals("Author", tag) -- cgit From 8afbc009483636adbc8562b0707439b595d59242 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 29 Oct 2018 17:13:42 +0300 Subject: Refactor code of javadoc paragraphs converting --- core/src/main/kotlin/Java/JavadocParser.kt | 39 ++++++++++++++++-------------- 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 1144763b..d6e46c50 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -1,11 +1,9 @@ package org.jetbrains.dokka import com.intellij.psi.* -import com.intellij.psi.impl.source.javadoc.CorePsiDocTagValueImpl import com.intellij.psi.impl.source.tree.JavaDocElementType import com.intellij.psi.javadoc.* import com.intellij.psi.util.PsiTreeUtil -import com.intellij.util.IncorrectOperationException import com.intellij.util.containers.isNullOrEmpty import org.jetbrains.kotlin.utils.keysToMap import org.jsoup.Jsoup @@ -43,20 +41,19 @@ class JavadocParser( } override fun parseDocumentation(element: PsiNamedElement): JavadocParseResult { - val docComment = (element as? PsiDocCommentOwner)?.docComment - if (docComment == null) return JavadocParseResult.Empty + val docComment = (element as? PsiDocCommentOwner)?.docComment ?: return JavadocParseResult.Empty val result = MutableContent() var deprecatedContent: Content? = null + + val nodes = convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }, element) + val firstParagraphContents = nodes.takeWhile { it !is ContentParagraph } val firstParagraph = ContentParagraph() - firstParagraph.convertJavadocElements(docComment.descriptionElements.dropWhile { it.text.trim().isEmpty() }, element) - val paragraphs = firstParagraph.children.dropWhile { it !is ContentParagraph } - firstParagraph.children.removeAll(paragraphs) - if (!firstParagraph.isEmpty()) { + if (firstParagraphContents.isNotEmpty()) { + firstParagraphContents.forEach { firstParagraph.append(it) } result.append(firstParagraph) } - paragraphs.forEach { - result.append(it) - } + + result.appendAll(nodes.drop(firstParagraphContents.size)) if (element is PsiMethod) { val tagsByName = element.searchInheritedTags() @@ -67,14 +64,16 @@ class JavadocParser( when (tagName) { "param" -> { section.appendTypeElement(signature) { - it.details.find { it.kind == NodeKind.Parameter }?.detailOrNull(NodeKind.Type) + it.details + .find { node -> node.kind == NodeKind.Parameter && node.name == tag.getSubjectName() } + ?.detailOrNull(NodeKind.Type) } } "return" -> { section.appendTypeElement(signature) { it.detailOrNull(NodeKind.Type) } } } - section.convertJavadocElements(tag.contentElements(), context) + section.appendAll(convertJavadocElements(tag.contentElements(), context)) } } } @@ -84,7 +83,7 @@ class JavadocParser( "see" -> result.convertSeeTag(tag) "deprecated" -> { deprecatedContent = Content().apply { - convertJavadocElements(tag.contentElements(), element) + appendAll(convertJavadocElements(tag.contentElements(), element)) } } in tagsToInherit -> {} @@ -92,7 +91,7 @@ class JavadocParser( val subjectName = tag.getSubjectName() val section = result.addSection(javadocSectionDisplayName(tag.name), subjectName) - section.convertJavadocElements(tag.contentElements(), element) + section.appendAll(convertJavadocElements(tag.contentElements(), element)) } } } @@ -133,13 +132,17 @@ class JavadocParser( return if (getSubjectName() != null) tagValueElements.dropWhile { it is PsiDocTagValue } else tagValueElements } - private fun ContentBlock.convertJavadocElements(elements: Iterable, element: PsiNamedElement) { + private fun convertJavadocElements(elements: Iterable, element: PsiNamedElement): List { val doc = Jsoup.parse(expandAllForElements(elements, element)) - doc.body().childNodes().forEach { - convertHtmlNode(it)?.let { append(it) } + return doc.body().childNodes().mapNotNull { + convertHtmlNode(it) } } + private fun ContentBlock.appendAll(nodes: List) { + nodes.forEach { append(it) } + } + private fun expandAllForElements(elements: Iterable, element: PsiNamedElement): String { val htmlBuilder = StringBuilder() elements.forEach { -- cgit From a18952be525f9683b23fc05a489cefc86a0bd11f Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 29 Oct 2018 17:15:09 +0300 Subject: Exclude `internal` visibility modifier from summary, fix exclusion logic --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index 6088d3a5..f57708ed 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -11,7 +11,7 @@ class KotlinLanguageService : CommonLanguageService() { } private val fullOnlyModifiers = - setOf("public", "protected", "private", "inline", "noinline", "crossinline", "reified") + setOf("public", "protected", "private", "internal", "inline", "noinline", "crossinline", "reified") override fun render(node: DocumentationNode, renderMode: RenderMode): ContentNode { return content { @@ -201,7 +201,7 @@ class KotlinLanguageService : CommonLanguageService() { "final", "public", "var" -> { } else -> { - if (node.name !in fullOnlyModifiers || renderMode == RenderMode.FULL) { + if (showModifierInSummary(node) || renderMode == RenderMode.FULL) { super.renderModifier(block, node, renderMode, nowrap) } } -- cgit From b9fa0e0741bfdfa76c3929e5343a2b19d96fc1ff Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 29 Oct 2018 18:45:33 +0300 Subject: #361: Fix varargs Fix #361 --- core/src/main/kotlin/javadoc/docbase.kt | 6 +++--- core/src/test/kotlin/javadoc/JavadocTest.kt | 18 +++++++++++++++++- core/testdata/javadoc/vararg.kt | 3 +++ 3 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 core/testdata/javadoc/vararg.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt index 2a14c6ff..61b13b46 100644 --- a/core/src/main/kotlin/javadoc/docbase.kt +++ b/core/src/main/kotlin/javadoc/docbase.kt @@ -173,7 +173,7 @@ open class TypeAdapter(override val module: ModuleNodeAdapter, override val node private val javaLanguageService = JavaLanguageService() override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedNameFromType() ?: node.qualifiedNameFromType() - override fun typeName(): String = javaLanguageService.getArrayElementType(node)?.simpleName() ?: node.simpleName() + override fun typeName(): String = (javaLanguageService.getArrayElementType(node)?.simpleName() ?: node.simpleName()) + dimension() override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName() override fun dimension(): String = Collections.nCopies(javaLanguageService.getArrayDimension(node), "[]").joinToString("") @@ -275,7 +275,7 @@ class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNod } class ParameterAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter { - override fun typeName(): String? = JavaLanguageService().renderType(node.detail(NodeKind.Type)) + override fun typeName(): String? = type()?.typeName() override fun type(): Type? = TypeAdapter(module, node.detail(NodeKind.Type)) override fun annotations(): Array = nodeAnnotations(this).toTypedArray() } @@ -317,7 +317,7 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it.subjectName!!, NodeKind.Exception)), it.children) } .toTypedArray() - override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).any { false } // TODO + override fun isVarArgs(): Boolean = node.details(NodeKind.Parameter).last().hasModifier("vararg") override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" } diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 45c45aa4..34b0b7a5 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -64,7 +64,7 @@ class JavadocTest { val member = classDoc.methods().find { it.name() == "main" }!! val paramType = member.parameters()[0].type() assertNull(paramType.asParameterizedType()) - assertEquals("String", paramType.typeName()) + assertEquals("String[]", paramType.typeName()) assertEquals("String", paramType.asClassDoc().name()) } } @@ -161,6 +161,22 @@ class JavadocTest { } } + @Test + fun testVararg() { + verifyJavadoc("testdata/javadoc/vararg.kt") { doc -> + val classDoc = doc.classNamed("VarargKt")!! + val methods = classDoc.methods() + methods.single { it.name() == "vararg" }.let { method -> + assertTrue(method.isVarArgs) + assertEquals("int", method.parameters().last().typeName()) + } + methods.single { it.name() == "varargInMiddle" }.let { method -> + assertFalse(method.isVarArgs) + assertEquals("int[]", method.parameters()[1].typeName()) + } + } + } + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/testdata/javadoc/vararg.kt b/core/testdata/javadoc/vararg.kt new file mode 100644 index 00000000..aa6c26d7 --- /dev/null +++ b/core/testdata/javadoc/vararg.kt @@ -0,0 +1,3 @@ +fun vararg(a: String, vararg b: Int) {} + +fun varargInMiddle(a: String, vararg b: Int, c: Short) {} \ No newline at end of file -- cgit From b0310f8f3e242ffc64c56e8fd95710b25b37dfff Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Fri, 23 Nov 2018 19:50:49 +0300 Subject: Fix constant values for Java --- .../main/kotlin/Java/JavaPsiDocumentationBuilder.kt | 4 ++-- core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 19 +++++-------------- core/src/test/kotlin/model/KotlinAsJavaTest.kt | 20 ++++++++++++++++++++ core/testdata/java/constants.java | 5 +++++ 4 files changed, 32 insertions(+), 16 deletions(-) create mode 100644 core/testdata/java/constants.java (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 332afffb..f0b3a56b 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -220,11 +220,11 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { private fun DocumentationNode.appendConstantValueIfAny(field: PsiField) { val modifierList = field.modifierList ?: return val initializer = field.initializer ?: return - if (field.type is PsiPrimitiveType && - modifierList.hasExplicitModifier(PsiModifier.FINAL) && + if (modifierList.hasExplicitModifier(PsiModifier.FINAL) && modifierList.hasExplicitModifier(PsiModifier.STATIC)) { val value = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false) val text = when(value) { + null -> return // No value found is String -> "\"" + StringUtil.escapeStringCharacters(value) + "\"" else -> value.toString() diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index f1b8e3d3..e15006cd 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -2,7 +2,6 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.intellij.openapi.util.text.StringUtil -import com.intellij.psi.PsiField import com.intellij.psi.PsiJavaFile import org.jetbrains.dokka.DokkaConfiguration.* import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser @@ -23,7 +22,6 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtParameter -import org.jetbrains.kotlin.psi.KtVariableDeclaration import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.* @@ -792,13 +790,7 @@ class DocumentationBuilder } if (isConst) { - val psi = sourcePsi() - val valueText = when (psi) { - is KtVariableDeclaration -> psi.initializer?.text - is PsiField -> psi.initializer?.text - else -> null - } - valueText?.let { node.appendTextNode(it, NodeKind.Value) } + this.compileTimeInitializer?.toDocumentationNode()?.let { node.append(it, RefKind.Detail) } } @@ -922,8 +914,8 @@ class DocumentationBuilder return node } - fun ConstantValue<*>.toDocumentationNode(): DocumentationNode? = value?.let { value -> - when (value) { + fun ConstantValue<*>.toDocumentationNode(): DocumentationNode? = value.let { value -> + val text = when (value) { is String -> "\"" + StringUtil.escapeStringCharacters(value) + "\"" is EnumEntrySyntheticClassDescriptor -> @@ -936,10 +928,9 @@ class DocumentationBuilder value.toString() } } - else -> value.toString() - }.let { valueString -> - DocumentationNode(valueString, Content.Empty, NodeKind.Value) + else -> "$value" } + DocumentationNode(text, Content.Empty, NodeKind.Value) } diff --git a/core/src/test/kotlin/model/KotlinAsJavaTest.kt b/core/src/test/kotlin/model/KotlinAsJavaTest.kt index d24d8bdd..22818038 100644 --- a/core/src/test/kotlin/model/KotlinAsJavaTest.kt +++ b/core/src/test/kotlin/model/KotlinAsJavaTest.kt @@ -2,6 +2,8 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.DocumentationModule import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.RefKind +import org.junit.Assert import org.junit.Test import org.junit.Assert.assertEquals @@ -27,6 +29,24 @@ class KotlinAsJavaTest { assertEquals("doc", getter.content.summary.toTestString()) } } + + + @Test fun constants() { + verifyModelAsJava("testdata/java/constants.java") { cls -> + selectNodes(cls) { + subgraphOf(RefKind.Member) + matching { it.name == "constStr" || it.name == "refConst" } + }.forEach { + assertEquals("In $it", "\"some value\"", it.detailOrNull(NodeKind.Value)?.name) + } + val nullConstNode = selectNodes(cls) { + subgraphOf(RefKind.Member) + withName("nullConst") + }.single() + + Assert.assertNull(nullConstNode.detailOrNull(NodeKind.Value)) + } + } } fun verifyModelAsJava(source: String, diff --git a/core/testdata/java/constants.java b/core/testdata/java/constants.java new file mode 100644 index 00000000..26f16639 --- /dev/null +++ b/core/testdata/java/constants.java @@ -0,0 +1,5 @@ +public class Constants { + public static final String constStr = "some value"; + public static final Object nullConst = null; + public static final String refConst = constStr; +} \ No newline at end of file -- cgit From 45187825aa63e5d1c3ac7fc3ae1b88aa34048812 Mon Sep 17 00:00:00 2001 From: Krystian Ujma Date: Fri, 14 Dec 2018 18:05:36 +0100 Subject: Modifiers sorted in wrong order #389 Fix #389 (modifiers sorted in wrong order) --- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 7 +++++- core/src/test/kotlin/format/MarkdownFormatTest.kt | 8 +++++++ core/src/test/kotlin/model/FunctionTest.kt | 27 ++++++++++++++++++++++ core/testdata/format/inlineSuspendFunction.kt | 6 +++++ core/testdata/format/inlineSuspendFunction.md | 8 +++++++ core/testdata/format/suspendInlineFunction.kt | 6 +++++ core/testdata/format/suspendInlineFunction.md | 8 +++++++ core/testdata/functions/inlineSuspendFunction.kt | 2 ++ core/testdata/functions/suspendFunction.kt | 2 ++ core/testdata/functions/suspendInlineFunction.kt | 2 ++ 10 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 core/testdata/format/inlineSuspendFunction.kt create mode 100644 core/testdata/format/inlineSuspendFunction.md create mode 100644 core/testdata/format/suspendInlineFunction.kt create mode 100644 core/testdata/format/suspendInlineFunction.md create mode 100644 core/testdata/functions/inlineSuspendFunction.kt create mode 100644 core/testdata/functions/suspendFunction.kt create mode 100644 core/testdata/functions/suspendInlineFunction.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index e15006cd..aa35634d 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.psi.addRemoveModifier.MODIFIERS_ORDER import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.descriptorUtil.* @@ -332,7 +333,11 @@ class DocumentationBuilder fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? KtModifierListOwner ?: return - KtTokens.MODIFIER_KEYWORDS_ARRAY.filter { it !in knownModifiers }.forEach { + KtTokens.MODIFIER_KEYWORDS_ARRAY.filter { + it !in knownModifiers + }.sortedBy { + MODIFIERS_ORDER.indexOf(it) + }.forEach { if (psi.hasModifier(it)) { appendTextNode(it.value, NodeKind.Modifier) } diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index a456836d..9fb34e95 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -165,6 +165,14 @@ class MarkdownFormatTest: FileGeneratorTestCase() { verifyMarkdownNode("reifiedTypeParameter", withKotlinRuntime = true) } + @Test fun suspendInlineFunctionOrder() { + verifyMarkdownNode("suspendInlineFunction", withKotlinRuntime = true) + } + + @Test fun inlineSuspendFunctionOrderChanged() { + verifyMarkdownNode("inlineSuspendFunction", withKotlinRuntime = true) + } + @Test fun annotatedTypeParameter() { verifyMarkdownNode("annotatedTypeParameter", withKotlinRuntime = true) } diff --git a/core/src/test/kotlin/model/FunctionTest.kt b/core/src/test/kotlin/model/FunctionTest.kt index 32910682..fd7a16a4 100644 --- a/core/src/test/kotlin/model/FunctionTest.kt +++ b/core/src/test/kotlin/model/FunctionTest.kt @@ -167,6 +167,33 @@ Documentation""", content.description.toTestString()) } } + @Test fun suspendFunction() { + verifyPackageMember("testdata/functions/suspendFunction.kt") { func -> + val modifiers = func.details(NodeKind.Modifier).map { it.name } + assertTrue("suspend" in modifiers) + } + } + + @Test fun suspendInlineFunctionOrder() { + verifyPackageMember("testdata/functions/suspendInlineFunction.kt") { func -> + val modifiers = func.details(NodeKind.Modifier).map { it.name }.filter { + it == "suspend" || it == "inline" + } + + assertEquals(listOf("suspend", "inline"), modifiers) + } + } + + @Test fun inlineSuspendFunctionOrderChanged() { + verifyPackageMember("testdata/functions/inlineSuspendFunction.kt") { func -> + val modifiers = func.details(NodeKind.Modifier).map { it.name }.filter { + it == "suspend" || it == "inline" + } + + assertEquals(listOf("suspend", "inline"), modifiers) + } + } + @Test fun functionWithAnnotatedParam() { verifyModel("testdata/functions/functionWithAnnotatedParam.kt") { model -> with(model.members.single().members.single { it.name == "function" }) { diff --git a/core/testdata/format/inlineSuspendFunction.kt b/core/testdata/format/inlineSuspendFunction.kt new file mode 100644 index 00000000..f2009eff --- /dev/null +++ b/core/testdata/format/inlineSuspendFunction.kt @@ -0,0 +1,6 @@ +/** + * returns 1 + */ +inline suspend fun foo(): Int { + 1 +} diff --git a/core/testdata/format/inlineSuspendFunction.md b/core/testdata/format/inlineSuspendFunction.md new file mode 100644 index 00000000..946463f7 --- /dev/null +++ b/core/testdata/format/inlineSuspendFunction.md @@ -0,0 +1,8 @@ +[test](index.md) / [foo](./foo.md) + +# foo + +`suspend inline fun foo(): Int` + +returns 1 + diff --git a/core/testdata/format/suspendInlineFunction.kt b/core/testdata/format/suspendInlineFunction.kt new file mode 100644 index 00000000..8af0d11a --- /dev/null +++ b/core/testdata/format/suspendInlineFunction.kt @@ -0,0 +1,6 @@ +/** + * returns 1 + */ +suspend inline fun foo(): Int { + 1 +} diff --git a/core/testdata/format/suspendInlineFunction.md b/core/testdata/format/suspendInlineFunction.md new file mode 100644 index 00000000..946463f7 --- /dev/null +++ b/core/testdata/format/suspendInlineFunction.md @@ -0,0 +1,8 @@ +[test](index.md) / [foo](./foo.md) + +# foo + +`suspend inline fun foo(): Int` + +returns 1 + diff --git a/core/testdata/functions/inlineSuspendFunction.kt b/core/testdata/functions/inlineSuspendFunction.kt new file mode 100644 index 00000000..54032ccf --- /dev/null +++ b/core/testdata/functions/inlineSuspendFunction.kt @@ -0,0 +1,2 @@ +inline suspend fun f() { +} diff --git a/core/testdata/functions/suspendFunction.kt b/core/testdata/functions/suspendFunction.kt new file mode 100644 index 00000000..49ecca2a --- /dev/null +++ b/core/testdata/functions/suspendFunction.kt @@ -0,0 +1,2 @@ +suspend fun f() { +} diff --git a/core/testdata/functions/suspendInlineFunction.kt b/core/testdata/functions/suspendInlineFunction.kt new file mode 100644 index 00000000..15a9018f --- /dev/null +++ b/core/testdata/functions/suspendInlineFunction.kt @@ -0,0 +1,2 @@ +suspend inline fun f() { +} -- cgit From f640397b6395d00783d476dfa5a082a02fc9d924 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 11 Feb 2019 22:44:34 +0300 Subject: Update bundled kotlin-compiler to 1.3.20-dev-564 --- .../main/kotlin/Analysis/AnalysisEnvironment.kt | 37 ++++++++++++---------- .../main/kotlin/Analysis/CoreProjectFileIndex.kt | 4 +-- core/src/main/kotlin/Generation/DokkaGenerator.kt | 6 ++-- core/src/test/kotlin/TestAPI.kt | 4 +-- core/src/test/kotlin/format/HtmlFormatTest.kt | 6 ++-- core/src/test/kotlin/model/PackageTest.kt | 14 ++++---- ...rFunctionalTypeInParenthesisWhenItIsReceiver.md | 4 +-- gradle.properties | 2 +- 8 files changed, 40 insertions(+), 37 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt index d31fe187..8ad7b8bb 100644 --- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt +++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt @@ -18,8 +18,12 @@ import com.intellij.psi.PsiElement import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.io.URLUtil import org.jetbrains.kotlin.analyzer.* +import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys +import org.jetbrains.kotlin.cli.common.config.ContentRoot +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot +import org.jetbrains.kotlin.cli.common.config.addKotlinSourceRoot import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider @@ -36,7 +40,6 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.platform.JvmBuiltIns import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace @@ -73,7 +76,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { val projectComponentManager = environment.project as MockComponentManager val projectFileIndex = CoreProjectFileIndex(environment.project, - environment.configuration.getList(JVMConfigurationKeys.CONTENT_ROOTS)) + environment.configuration.getList(CLIConfigurationKeys.CONTENT_ROOTS)) val moduleManager = object : CoreModuleManager(environment.project, this) { override fun getModules(): Array = arrayOf(projectFileIndex.module) @@ -147,20 +150,20 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { }, LanguageSettingsProvider.Default /* TODO: Fix this */, { JvmAnalyzerFacade }, - - JvmPlatformParameters { - val file = (it as JavaClassImpl).psi.containingFile.virtualFile - if (file in sourcesScope) - module - else - library + { + JvmPlatformParameters ({ content -> + JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { + addRoots(javaRoots, messageCollector) + } + }, { + val file = (it as JavaClassImpl).psi.containingFile.virtualFile + if (file in sourcesScope) + module + else + library + }) }, CompilerEnvironment, - packagePartProviderFactory = { content -> - JvmPackagePartProvider(configuration.languageVersionSettings, content.moduleContentScope).apply { - addRoots(javaRoots) - } - }, builtIns = builtIns ) @@ -209,7 +212,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { * List of source roots for this environment. */ val sources: List - get() = configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + get() = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) ?.filterIsInstance() ?.map { it.path } ?: emptyList() @@ -228,7 +231,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { } fun addRoots(list: List) { - configuration.addAll(JVMConfigurationKeys.CONTENT_ROOTS, list) + configuration.addAll(CLIConfigurationKeys.CONTENT_ROOTS, list) } /** @@ -241,7 +244,7 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable { fun contentRootFromPath(path: String): ContentRoot { val file = File(path) - return if (file.extension == "java") JavaSourceRoot(file, null) else KotlinSourceRoot(path) + return if (file.extension == "java") JavaSourceRoot(file, null) else KotlinSourceRoot(path, false) } diff --git a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt index 4f6a7c76..319d85b1 100644 --- a/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt +++ b/core/src/main/kotlin/Analysis/CoreProjectFileIndex.kt @@ -20,10 +20,10 @@ import com.intellij.openapi.vfs.VirtualFileFilter import com.intellij.psi.search.GlobalSearchScope import com.intellij.util.messages.MessageBus import org.jetbrains.jps.model.module.JpsModuleSourceRootType +import org.jetbrains.kotlin.cli.common.config.ContentRoot +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.jvm.config.JvmClasspathRoot import org.jetbrains.kotlin.cli.jvm.config.JvmContentRoot -import org.jetbrains.kotlin.config.ContentRoot -import org.jetbrains.kotlin.config.KotlinSourceRoot import org.picocontainer.PicoContainer import java.io.File diff --git a/core/src/main/kotlin/Generation/DokkaGenerator.kt b/core/src/main/kotlin/Generation/DokkaGenerator.kt index 46fdaf0a..a5279772 100644 --- a/core/src/main/kotlin/Generation/DokkaGenerator.kt +++ b/core/src/main/kotlin/Generation/DokkaGenerator.kt @@ -10,13 +10,13 @@ import com.intellij.psi.PsiManager import org.jetbrains.dokka.DokkaConfiguration.SourceRoot import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.dokka.Utilities.DokkaOutputModule +import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageRenderer import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot -import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode @@ -173,7 +173,7 @@ fun buildDocumentationModule(injector: Injector, } fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEnvironment) { - val contentRoots = coreEnvironment.configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + val contentRoots = coreEnvironment.configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) ?.filterIsInstance() ?.map { it.file } ?: listOf() @@ -186,7 +186,7 @@ fun parseJavaPackageDocs(packageDocs: PackageDocs, coreEnvironment: KotlinCoreEn fun KotlinCoreEnvironment.getJavaSourceFiles(): List { - val sourceRoots = configuration.get(JVMConfigurationKeys.CONTENT_ROOTS) + val sourceRoots = configuration.get(CLIConfigurationKeys.CONTENT_ROOTS) ?.filterIsInstance() ?.map { it.file } ?: listOf() diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index 953e3bab..f72373d9 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -7,12 +7,12 @@ import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* import org.jetbrains.dokka.Utilities.DokkaAnalysisModule +import org.jetbrains.kotlin.cli.common.config.ContentRoot +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot -import org.jetbrains.kotlin.config.ContentRoot -import org.jetbrains.kotlin.config.KotlinSourceRoot import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.junit.Assert import org.junit.Assert.fail diff --git a/core/src/test/kotlin/format/HtmlFormatTest.kt b/core/src/test/kotlin/format/HtmlFormatTest.kt index 54c367fd..807118c5 100644 --- a/core/src/test/kotlin/format/HtmlFormatTest.kt +++ b/core/src/test/kotlin/format/HtmlFormatTest.kt @@ -1,9 +1,8 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot -import org.jetbrains.kotlin.config.KotlinSourceRoot -import org.junit.Before import org.junit.Test import java.io.File @@ -100,7 +99,8 @@ class HtmlFormatTest: FileGeneratorTestCase() { } @Test fun crossLanguageKotlinExtendsJava() { - verifyOutput(arrayOf(KotlinSourceRoot("testdata/format/crossLanguage/kotlinExtendsJava/Bar.kt"), + verifyOutput(arrayOf( + KotlinSourceRoot("testdata/format/crossLanguage/kotlinExtendsJava/Bar.kt", false), JavaSourceRoot(File("testdata/format/crossLanguage/kotlinExtendsJava"), null)), ".html") { model, output -> buildPagesAndReadInto( diff --git a/core/src/test/kotlin/model/PackageTest.kt b/core/src/test/kotlin/model/PackageTest.kt index 052f0d28..7a8f0d06 100644 --- a/core/src/test/kotlin/model/PackageTest.kt +++ b/core/src/test/kotlin/model/PackageTest.kt @@ -3,7 +3,7 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.Content import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.PackageOptionsImpl -import org.jetbrains.kotlin.config.KotlinSourceRoot +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.junit.Assert.* import org.junit.Test @@ -48,8 +48,8 @@ public class PackageTest { } @Test fun multipleFiles() { - verifyModel(KotlinSourceRoot("testdata/packages/dottedNamePackage.kt"), - KotlinSourceRoot("testdata/packages/simpleNamePackage.kt")) { model -> + verifyModel(KotlinSourceRoot("testdata/packages/dottedNamePackage.kt", false), + KotlinSourceRoot("testdata/packages/simpleNamePackage.kt", false)) { model -> assertEquals(2, model.members.count()) with(model.members.single { it.name == "simple" }) { assertEquals(NodeKind.Package, kind) @@ -70,8 +70,8 @@ public class PackageTest { } @Test fun multipleFilesSamePackage() { - verifyModel(KotlinSourceRoot("testdata/packages/simpleNamePackage.kt"), - KotlinSourceRoot("testdata/packages/simpleNamePackage2.kt")) { model -> + verifyModel(KotlinSourceRoot("testdata/packages/simpleNamePackage.kt", false), + KotlinSourceRoot("testdata/packages/simpleNamePackage2.kt", false)) { model -> assertEquals(1, model.members.count()) with(model.members.elementAt(0)) { assertEquals(NodeKind.Package, kind) @@ -85,7 +85,7 @@ public class PackageTest { } @Test fun classAtPackageLevel() { - verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt")) { model -> + verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt", false)) { model -> assertEquals(1, model.members.count()) with(model.members.elementAt(0)) { assertEquals(NodeKind.Package, kind) @@ -99,7 +99,7 @@ public class PackageTest { } @Test fun suppressAtPackageLevel() { - verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt"), + verifyModel(KotlinSourceRoot("testdata/packages/classInPackage.kt", false), perPackageOptions = listOf(PackageOptionsImpl(prefix = "simple.name", suppress = true))) { model -> assertEquals(1, model.members.count()) with(model.members.elementAt(0)) { diff --git a/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md b/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md index ad632fef..4b5f3a64 100644 --- a/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md +++ b/core/testdata/format/renderFunctionalTypeInParenthesisWhenItIsReceiver.md @@ -1,6 +1,6 @@ -[test](../index.md) / [kotlin.SuspendFunction0](./index.md) +[test](../index.md) / [kotlin.coroutines.SuspendFunction0](./index.md) -### Extensions for kotlin.SuspendFunction0 +### Extensions for kotlin.coroutines.SuspendFunction0 | [foo](foo.md) | `fun (suspend () -> Unit).foo(): Unit` | diff --git a/gradle.properties b/gradle.properties index 65bd63f4..9436e38b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ dokka_version=0.9.18-SNAPSHOT dokka_publication_channel=dokka #Kotlin compiler and plugin -bundled_kotlin_compiler_version=1.2.60-dev-157 +bundled_kotlin_compiler_version=1.3.20-dev-564 kotlin_version=1.2.21 kotlin_for_gradle_runtime_version=1.1.60 -- cgit From 5afb808f984542bb550d124f87c65c71a9148b83 Mon Sep 17 00:00:00 2001 From: Krystian Ujma Date: Fri, 15 Feb 2019 14:10:27 +0100 Subject: Nullable left off function type parameter with default value (#401) (#328) --- core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 16 +++++++++++++--- core/src/test/kotlin/format/MarkdownFormatTest.kt | 4 ++++ core/testdata/format/nullableTypeParameterFunction.kt | 8 ++++++++ core/testdata/format/nullableTypeParameterFunction.md | 18 ++++++++++++++++++ 4 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 core/testdata/format/nullableTypeParameterFunction.kt create mode 100644 core/testdata/format/nullableTypeParameterFunction.md (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt index f57708ed..5f43c22e 100644 --- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt +++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt @@ -166,8 +166,18 @@ class KotlinLanguageService : CommonLanguageService() { keyword("dynamic") return } + + val nullabilityModifier = node.detailOrNull(NodeKind.NullabilityModifier) + if (node.isFunctionalType()) { - renderFunctionalType(node, renderMode) + if (nullabilityModifier != null) { + symbol("(") + renderFunctionalType(node, renderMode) + symbol(")") + symbol(nullabilityModifier.name) + } else { + renderFunctionalType(node, renderMode) + } return } if (renderMode == RenderMode.FULL) { @@ -185,8 +195,8 @@ class KotlinLanguageService : CommonLanguageService() { } symbol(">") } - val nullabilityModifier = node.details(NodeKind.NullabilityModifier).singleOrNull() - if (nullabilityModifier != null) { + + nullabilityModifier ?.apply { symbol(nullabilityModifier.name) } } diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 9fb34e95..b078292b 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -539,4 +539,8 @@ class MarkdownFormatTest: FileGeneratorTestCase() { nodesWithName } } + + @Test fun nullableTypeParameterFunction() { + verifyMarkdownNode("nullableTypeParameterFunction", withKotlinRuntime = true) + } } diff --git a/core/testdata/format/nullableTypeParameterFunction.kt b/core/testdata/format/nullableTypeParameterFunction.kt new file mode 100644 index 00000000..01805a7b --- /dev/null +++ b/core/testdata/format/nullableTypeParameterFunction.kt @@ -0,0 +1,8 @@ +class Bar { + val dataList = mutableListOf() + + open fun checkElement( + elem: T, + addFunc: ((elem: T) -> Unit)? = { dataList.add(it) } + ): Int = 1 +} \ No newline at end of file diff --git a/core/testdata/format/nullableTypeParameterFunction.md b/core/testdata/format/nullableTypeParameterFunction.md new file mode 100644 index 00000000..5764007b --- /dev/null +++ b/core/testdata/format/nullableTypeParameterFunction.md @@ -0,0 +1,18 @@ +[test](../index.md) / [Bar](./index.md) + +# Bar + +`class Bar` + +### Constructors + +| [<init>](-init-.md) | `Bar()` | + +### Properties + +| [dataList](data-list.md) | `val dataList: MutableList<`[`T`](index.md#T)`>` | + +### Functions + +| [checkElement](check-element.md) | `fun checkElement(elem: `[`T`](index.md#T)`, addFunc: ((elem: `[`T`](index.md#T)`) -> Unit)? = { dataList.add(it) }): Int` | + -- cgit From 9e2ca870881823498c8f65afda7bd9b77e575a2d Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Tue, 19 Feb 2019 16:08:12 +0300 Subject: Cleanup http --- .gitignore | 2 +- README.md | 8 ++-- build.gradle | 4 +- .../src/main/kotlin/Kotlin/DocumentationBuilder.kt | 2 +- core/src/test/kotlin/format/PackageDocsTest.kt | 2 +- core/src/test/kotlin/model/JavaTest.kt | 2 +- core/testdata/format/enumRef.md | 2 +- core/testdata/format/externalReferenceLink.kt | 2 +- core/testdata/format/externalReferenceLink.md | 4 +- core/testdata/format/inheritedLink.md | 2 +- core/testdata/format/jdkLinks.md | 8 ++-- core/testdata/format/markdownInLinks.html | 2 +- core/testdata/format/markdownInLinks.kt | 2 +- core/testdata/markdown/spec.txt | 52 +++++++++++----------- core/testdata/packagedocs/referenceLinks.kotlin.md | 5 +-- core/testdata/packagedocs/referenceLinks.md | 2 +- core/testdata/packagedocs/referenceLinks.module.md | 4 +- runners/android-gradle-plugin/build.gradle | 2 +- .../testData/androidApp/build.gradle | 4 +- .../testData/androidAppJavadoc/build.gradle | 4 +- .../testData/androidMultiFlavourApp/build.gradle | 4 +- .../testData/basic/build.gradle | 4 +- .../testData/multiProjectSingleOut/build.gradle | 4 +- .../testData/sourcesChange/build.gradle | 4 +- runners/gradle-plugin/build.gradle | 2 +- runners/maven-plugin/src/main/kotlin/DokkaMojo.kt | 2 +- 26 files changed, 67 insertions(+), 68 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/.gitignore b/.gitignore index fe5edc3b..59243df5 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,7 @@ buildNumber.properties *.war *.ear -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml hs_err_pid* ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm diff --git a/README.md b/README.md index 170ecfa6..341305fa 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -dokka [![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) +dokka [![official JetBrains project](https://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) [![TeamCity (build status)](https://img.shields.io/teamcity/http/teamcity.jetbrains.com/s/Kotlin_Dokka_DokkaAntMavenGradle.svg)](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_Dokka_DokkaAntMavenGradle&branch_KotlinTools_Dokka=%3Cdefault%3E&tab=buildTypeStatusDiv) [ ![Download](https://api.bintray.com/packages/kotlin/dokka/dokka/images/download.svg) ](https://bintray.com/kotlin/dokka/dokka/_latestVersion) ===== @@ -52,7 +52,7 @@ dokka { } // List of files with module and package documentation - // http://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation + // https://kotlinlang.org/docs/reference/kotlin-doc.html#module-and-package-documentation includes = ['packages.md', 'extra.md'] // The list of files or directories containing sample code (referenced with @sample tags) @@ -250,7 +250,7 @@ The available configuration options are shown below: default - + packages.md extra.md @@ -297,7 +297,7 @@ The available configuration options are shown below: ${project.basedir}/src/main/kotlin - http://github.com/me/myrepo + https://github.com/me/myrepo #L diff --git a/build.gradle b/build.gradle index d282aeb0..0b5d5dbc 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ allprojects { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } maven { url "https://plugins.gradle.org/m2/" } ivy(repo) @@ -30,7 +30,7 @@ allprojects { mavenCentral() mavenLocal() maven { url "https://dl.bintray.com/jetbrains/markdown" } - maven { url "http://dl.bintray.com/kotlin/kotlin-eap" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } maven { url 'https://jitpack.io' } maven { url "https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_dev_CompilerAllPlugins/$bundled_kotlin_compiler_version/maven" } diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt index aa35634d..38804e39 100644 --- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt @@ -74,7 +74,7 @@ class DocumentationOptions(val outputDir: String, val defaultLinks = run { val links = mutableListOf() if (!noJdkLink) - links += ExternalDocumentationLink.Builder("http://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + links += ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build() if (!noStdlibLink) links += ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() diff --git a/core/src/test/kotlin/format/PackageDocsTest.kt b/core/src/test/kotlin/format/PackageDocsTest.kt index b7fff1e2..3ff5f123 100644 --- a/core/src/test/kotlin/format/PackageDocsTest.kt +++ b/core/src/test/kotlin/format/PackageDocsTest.kt @@ -49,7 +49,7 @@ class PackageDocsTest { @Test fun testReferenceLinksInPackageDocs() { val mockLinkResolver = mock { - val exampleCom = "http://example.com" + val exampleCom = "https://example.com" on { tryResolveContentLink(any(), eq(exampleCom)) } doAnswer { ContentExternalLink(exampleCom) } } diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index 876d18c0..0bec6d01 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -150,7 +150,7 @@ public class JavaTest { /** * `@suppress` not supported in Java! * - * [Proposed tags](http://www.oracle.com/technetwork/java/javase/documentation/proposed-tags-142378.html) + * [Proposed tags](https://www.oracle.com/technetwork/java/javase/documentation/proposed-tags-142378.html) * Proposed tag `@exclude` for it, but not supported yet */ @Ignore("@suppress not supported in Java!") @Test fun suppressTag() { diff --git a/core/testdata/format/enumRef.md b/core/testdata/format/enumRef.md index 8b2a6650..f5f5a3e0 100644 --- a/core/testdata/format/enumRef.md +++ b/core/testdata/format/enumRef.md @@ -4,5 +4,5 @@ `fun f(): Unit` -[java.math.RoundingMode.UP](http://docs.oracle.com/javase/6/docs/api/java/math/RoundingMode.html#UP) +[java.math.RoundingMode.UP](https://docs.oracle.com/javase/6/docs/api/java/math/RoundingMode.html#UP) diff --git a/core/testdata/format/externalReferenceLink.kt b/core/testdata/format/externalReferenceLink.kt index 4ca0ee21..775b2e66 100644 --- a/core/testdata/format/externalReferenceLink.kt +++ b/core/testdata/format/externalReferenceLink.kt @@ -3,7 +3,7 @@ * * Sure, it is [example.com] * - * [example.com]: http://example.com + * [example.com]: https://example.com */ fun a() { diff --git a/core/testdata/format/externalReferenceLink.md b/core/testdata/format/externalReferenceLink.md index 38ffde78..3565d9aa 100644 --- a/core/testdata/format/externalReferenceLink.md +++ b/core/testdata/format/externalReferenceLink.md @@ -4,7 +4,7 @@ `fun a(): Unit` -It is link to [example site](http://example.com) +It is link to [example site](https://example.com) -Sure, it is [example.com](http://example.com) +Sure, it is [example.com](https://example.com) diff --git a/core/testdata/format/inheritedLink.md b/core/testdata/format/inheritedLink.md index e5af326c..aec07a75 100644 --- a/core/testdata/format/inheritedLink.md +++ b/core/testdata/format/inheritedLink.md @@ -13,5 +13,5 @@ Overrides [Foo.sayHello](../../p1/-foo/say-hello.md) -Says hello - [LinkedList](http://docs.oracle.com/javase/6/docs/api/java/util/LinkedList.html). +Says hello - [LinkedList](https://docs.oracle.com/javase/6/docs/api/java/util/LinkedList.html). diff --git a/core/testdata/format/jdkLinks.md b/core/testdata/format/jdkLinks.md index 7498171d..c3a5fbf4 100644 --- a/core/testdata/format/jdkLinks.md +++ b/core/testdata/format/jdkLinks.md @@ -2,13 +2,13 @@ # C -`class C : `[`ClassLoader`](http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) +`class C : `[`ClassLoader`](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) -This is a [ClassLoader](http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) and I can get its [ClassLoader.getResource](http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)) +This is a [ClassLoader](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) and I can get its [ClassLoader.getResource](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)) -You can print something to [java.lang.System.out](http://docs.oracle.com/javase/6/docs/api/java/lang/System.html#out) now! +You can print something to [java.lang.System.out](https://docs.oracle.com/javase/6/docs/api/java/lang/System.html#out) now! ### Constructors -| [<init>](-init-.md) | `C()`
This is a [ClassLoader](http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) and I can get its [ClassLoader.getResource](http://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)) | +| [<init>](-init-.md) | `C()`
This is a [ClassLoader](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html) and I can get its [ClassLoader.getResource](https://docs.oracle.com/javase/6/docs/api/java/lang/ClassLoader.html#getResource(java.lang.String)) | diff --git a/core/testdata/format/markdownInLinks.html b/core/testdata/format/markdownInLinks.html index 596cca73..f0bb475e 100644 --- a/core/testdata/format/markdownInLinks.html +++ b/core/testdata/format/markdownInLinks.html @@ -9,6 +9,6 @@

foo

fun foo(): Unit -

abd kas

+

abd kas

diff --git a/core/testdata/format/markdownInLinks.kt b/core/testdata/format/markdownInLinks.kt index 67b6311f..380727ee 100644 --- a/core/testdata/format/markdownInLinks.kt +++ b/core/testdata/format/markdownInLinks.kt @@ -1,4 +1,4 @@ /** - * [a**b**__d__ kas ](http://www.ibm.com) + * [a**b**__d__ kas ](https://www.ibm.com) */ fun foo() {} diff --git a/core/testdata/markdown/spec.txt b/core/testdata/markdown/spec.txt index fce87924..916bdd89 100644 --- a/core/testdata/markdown/spec.txt +++ b/core/testdata/markdown/spec.txt @@ -23,7 +23,7 @@ HTML but in LaTeX and many other formats. ## Why is a spec needed? John Gruber's [canonical description of Markdown's -syntax](http://daringfireball.net/projects/markdown/syntax) +syntax](https://daringfireball.net/projects/markdown/syntax) does not specify the syntax unambiguously. Here are some examples of questions it does not answer: @@ -34,7 +34,7 @@ questions it does not answer: not require that. This is hardly a "corner case," and divergences between implementations on this issue often lead to surprises for users in real documents. (See [this comment by John - Gruber](http://article.gmane.org/gmane.text.markdown.general/1997).) + Gruber](https://article.gmane.org/gmane.text.markdown.general/1997).) 2. Is a blank line needed before a block quote or header? Most implementations do not require the blank line. However, @@ -42,7 +42,7 @@ questions it does not answer: also to ambiguities in parsing (note that some implementations put the header inside the blockquote, while others do not). (John Gruber has also spoken [in favor of requiring the blank - lines](http://article.gmane.org/gmane.text.markdown.general/2146).) + lines](https://article.gmane.org/gmane.text.markdown.general/2146).) 3. Is a blank line needed before an indented code block? (`Markdown.pl` requires it, but this is not mentioned in the @@ -75,7 +75,7 @@ questions it does not answer: ``` (There are some relevant comments by John Gruber - [here](http://article.gmane.org/gmane.text.markdown.general/2554).) + [here](https://article.gmane.org/gmane.text.markdown.general/2554).) 5. Can list markers be indented? Can ordered list markers be right-aligned? @@ -509,7 +509,7 @@ More than six `#` characters is not a header: A space is required between the `#` characters and the header's contents. Note that many implementations currently do not require the space. However, the space was required by the [original ATX -implementation](http://www.aaronsw.com/2002/atx/atx.py), and it helps +implementation](https://www.aaronsw.com/2002/atx/atx.py), and it helps prevent things like the following from being parsed as headers: . @@ -3686,9 +3686,9 @@ raw HTML: . . - + . -

http://google.com?find=\*

+

https://google.com?find=\*

. . @@ -3736,7 +3736,7 @@ and simplifies the job of implementations targetting other languages, as these w UTF8 chars and need not be HTML-entity aware. [Named entities](#name-entities) consist of `&` -+ any of the valid HTML5 entity names + `;`. The [following document](http://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json) ++ any of the valid HTML5 entity names + `;`. The [following document](https://www.whatwg.org/specs/web-apps/current-work/multipage/entities.json) is used as an authoritative source of the valid entity names and their corresponding codepoints. Conforming implementations that target Markdown don't need to generate entities for all the valid @@ -3955,9 +3955,9 @@ And this is not parsed as a link: But this is a link: . -` +` . -

http://foo.bar.`baz`

+

https://foo.bar.`baz`

. And this is an HTML tag: @@ -3986,7 +3986,7 @@ we just have literal backticks: ## Emphasis and strong emphasis John Gruber's original [Markdown syntax -description](http://daringfireball.net/projects/markdown/syntax#em) says: +description](https://daringfireball.net/projects/markdown/syntax#em) says: > Markdown treats asterisks (`*`) and underscores (`_`) as indicators of > emphasis. Text wrapped with one `*` or `_` will be wrapped with an HTML @@ -4229,15 +4229,15 @@ _a `_`_ . . -**a +**a . -

**ahttp://foo.bar?q=**

+

**ahttps://foo.bar?q=**

. . -__a +__a . -

__ahttp://foo.bar?q=__

+

__ahttps://foo.bar?q=__

. This is not emphasis, because the opening delimiter is @@ -5455,15 +5455,15 @@ soap.beep`, `soap.beeps`, `tag`, `tel`, `telnet`, `tftp`, `thismessage`, Here are some valid autolinks: . - + . -

http://foo.bar.baz

+

https://foo.bar.baz

. . - + . -

http://foo.bar.baz?q=hello&id=22&boolean

+

https://foo.bar.baz?q=hello&id=22&boolean

. . @@ -5483,9 +5483,9 @@ Uppercase is also fine: Spaces are not allowed in autolinks: . - + . -

<http://foo.bar/baz bim>

+

<https://foo.bar/baz bim>

. An [email autolink](#email-autolink) @@ -5496,7 +5496,7 @@ and the URL is `mailto:` followed by the email address. An [email address](#email-address), for these purposes, is anything that matches the [non-normative regex from the HTML5 -spec](http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-%28type=email%29): +spec](https://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#e-mail-state-%28type=email%29): /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])? (?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ @@ -5530,9 +5530,9 @@ These are not autolinks: . . -< http://foo.bar > +< https://foo.bar > . -

< http://foo.bar >

+

< https://foo.bar >

. . @@ -5548,9 +5548,9 @@ These are not autolinks: . . -http://google.com +https://google.com . -

http://google.com

+

https://google.com

. . diff --git a/core/testdata/packagedocs/referenceLinks.kotlin.md b/core/testdata/packagedocs/referenceLinks.kotlin.md index ac7e4b48..f7b1edad 100644 --- a/core/testdata/packagedocs/referenceLinks.kotlin.md +++ b/core/testdata/packagedocs/referenceLinks.kotlin.md @@ -1,7 +1,6 @@ Core functions and types -See [ref](http://example.com) -Also, [example](http://example.com) +See [ref](https://example.com) +Also, [example](https://example.com) - \ No newline at end of file diff --git a/core/testdata/packagedocs/referenceLinks.md b/core/testdata/packagedocs/referenceLinks.md index 7583ee9d..177dea0c 100644 --- a/core/testdata/packagedocs/referenceLinks.md +++ b/core/testdata/packagedocs/referenceLinks.md @@ -14,4 +14,4 @@ See [ref] Also, [example][ref] -[ref]: http://example.com +[ref]: https://example.com diff --git a/core/testdata/packagedocs/referenceLinks.module.md b/core/testdata/packagedocs/referenceLinks.module.md index ddbdbe2f..08372175 100644 --- a/core/testdata/packagedocs/referenceLinks.module.md +++ b/core/testdata/packagedocs/referenceLinks.module.md @@ -4,6 +4,6 @@ The Kotlin standard library is a set of functions and types implementing idiomatic patterns when working with collections, text and files. -See [ref](http://example.com) -Also, [example](http://example.com) +See [ref](https://example.com) +Also, [example](https://example.com) diff --git a/runners/android-gradle-plugin/build.gradle b/runners/android-gradle-plugin/build.gradle index 72d1be9e..28b0cbb9 100644 --- a/runners/android-gradle-plugin/build.gradle +++ b/runners/android-gradle-plugin/build.gradle @@ -76,7 +76,7 @@ artifacts { } pluginBundle { - website = 'http://www.kotlinlang.org/' + website = 'https://www.kotlinlang.org/' vcsUrl = 'https://github.com/kotlin/dokka.git' description = 'Dokka, the Kotlin documentation tool' tags = ['dokka', 'kotlin', 'kdoc', 'android'] diff --git a/runners/gradle-integration-tests/testData/androidApp/build.gradle b/runners/gradle-integration-tests/testData/androidApp/build.gradle index 59477b52..35356b90 100644 --- a/runners/gradle-integration-tests/testData/androidApp/build.gradle +++ b/runners/gradle-integration-tests/testData/androidApp/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() jcenter() maven { url 'https://maven.google.com' } - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { @@ -15,7 +15,7 @@ allprojects { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } } diff --git a/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle b/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle index 59477b52..35356b90 100644 --- a/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle +++ b/runners/gradle-integration-tests/testData/androidAppJavadoc/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() jcenter() maven { url 'https://maven.google.com' } - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { @@ -15,7 +15,7 @@ allprojects { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } } diff --git a/runners/gradle-integration-tests/testData/androidMultiFlavourApp/build.gradle b/runners/gradle-integration-tests/testData/androidMultiFlavourApp/build.gradle index 59477b52..35356b90 100644 --- a/runners/gradle-integration-tests/testData/androidMultiFlavourApp/build.gradle +++ b/runners/gradle-integration-tests/testData/androidMultiFlavourApp/build.gradle @@ -3,7 +3,7 @@ buildscript { mavenCentral() jcenter() maven { url 'https://maven.google.com' } - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { @@ -15,7 +15,7 @@ allprojects { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } } diff --git a/runners/gradle-integration-tests/testData/basic/build.gradle b/runners/gradle-integration-tests/testData/basic/build.gradle index 4a259f50..a3116751 100644 --- a/runners/gradle-integration-tests/testData/basic/build.gradle +++ b/runners/gradle-integration-tests/testData/basic/build.gradle @@ -2,7 +2,7 @@ buildscript { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { @@ -21,7 +21,7 @@ repositories { mavenCentral() jcenter() maven { - url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" + url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" diff --git a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle index 68d93e30..4f561472 100644 --- a/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle +++ b/runners/gradle-integration-tests/testData/multiProjectSingleOut/build.gradle @@ -7,7 +7,7 @@ subprojects { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { @@ -17,7 +17,7 @@ subprojects { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } } diff --git a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle index bc20e1cf..4627e8ef 100644 --- a/runners/gradle-integration-tests/testData/sourcesChange/build.gradle +++ b/runners/gradle-integration-tests/testData/sourcesChange/build.gradle @@ -2,7 +2,7 @@ buildscript { repositories { mavenCentral() jcenter() - maven { url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" } + maven { url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" } } dependencies { @@ -21,7 +21,7 @@ repositories { mavenCentral() jcenter() maven { - url "http://dl.bintray.com/kotlin/kotlin-eap-1.1" + url "https://dl.bintray.com/kotlin/kotlin-eap-1.1" } maven { url "https://dl.bintray.com/kotlin/kotlin-dev" diff --git a/runners/gradle-plugin/build.gradle b/runners/gradle-plugin/build.gradle index 661d432b..8e59a7be 100644 --- a/runners/gradle-plugin/build.gradle +++ b/runners/gradle-plugin/build.gradle @@ -74,7 +74,7 @@ artifacts { } pluginBundle { - website = 'http://www.kotlinlang.org/' + website = 'https://www.kotlinlang.org/' vcsUrl = 'https://github.com/kotlin/dokka.git' description = 'Dokka, the Kotlin documentation tool' tags = ['dokka', 'kotlin', 'kdoc'] diff --git a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt index dcb9ac2c..41521388 100644 --- a/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt +++ b/runners/maven-plugin/src/main/kotlin/DokkaMojo.kt @@ -200,7 +200,7 @@ class DokkaJavadocJarMojo : AbstractDokkaMojo() { /** * The archive configuration to use. - * See [Maven Archiver Reference](http://maven.apache.org/shared/maven-archiver/index.html) + * See [Maven Archiver Reference](https://maven.apache.org/shared/maven-archiver/index.html) */ @Parameter private val archive = MavenArchiveConfiguration() -- cgit From 46af103c8dd43839e898368dbda744fa522e9789 Mon Sep 17 00:00:00 2001 From: Krystian Ujma Date: Mon, 25 Feb 2019 16:19:40 +0100 Subject: Fix protected property getters and setters show the wrong visibility… (#402) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/src/main/kotlin/javadoc/docbase.kt | 17 +++++++--- core/src/test/kotlin/javadoc/JavadocTest.kt | 46 ++++++++++++++++++++++++++++ core/testdata/javadoc/visibilityModifiers.kt | 15 +++++++++ 3 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 core/testdata/javadoc/visibilityModifiers.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt index 61b13b46..aeb806f1 100644 --- a/core/src/main/kotlin/javadoc/docbase.kt +++ b/core/src/main/kotlin/javadoc/docbase.kt @@ -2,7 +2,7 @@ package org.jetbrains.dokka.javadoc import com.sun.javadoc.* import org.jetbrains.dokka.* -import java.lang.reflect.Modifier +import java.lang.reflect.Modifier.* import java.util.* import kotlin.reflect.KClass @@ -122,14 +122,21 @@ class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: Documentati } open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc { - override fun isPublic(): Boolean = true + override fun isPublic(): Boolean = node.hasModifier("public") || node.hasModifier("internal") override fun isPackagePrivate(): Boolean = false override fun isStatic(): Boolean = node.hasModifier("static") - override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0 + override fun modifierSpecifier(): Int = visibilityModifier or (if (isStatic) STATIC else 0) + private val visibilityModifier + get() = when { + isPublic() -> PUBLIC + isPrivate() -> PRIVATE + isProtected() -> PROTECTED + else -> 0 + } override fun qualifiedName(): String? = node.qualifiedName() override fun annotations(): Array? = nodeAnnotations(this).toTypedArray() override fun modifiers(): String? = "public ${if (isStatic) "static" else ""}".trim() - override fun isProtected(): Boolean = false + override fun isProtected(): Boolean = node.hasModifier("protected") override fun isFinal(): Boolean = node.hasModifier("final") @@ -165,7 +172,7 @@ open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationN return null } - override fun isPrivate(): Boolean = false + override fun isPrivate(): Boolean = node.hasModifier("private") override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true } diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 34b0b7a5..b18dacca 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -7,6 +7,7 @@ import org.jetbrains.dokka.tests.assertEqualsIgnoringSeparators import org.jetbrains.dokka.tests.verifyModel import org.junit.Assert.* import org.junit.Test +import java.lang.reflect.Modifier.* class JavadocTest { @Test fun testTypes() { @@ -177,6 +178,51 @@ class JavadocTest { } } + @Test + fun shouldHaveValidVisibilityModifiers() { + verifyJavadoc("testdata/javadoc/visibilityModifiers.kt", withKotlinRuntime = true) { doc -> + val classDoc = doc.classNamed("foo.Apple")!! + val methods = classDoc.methods() + + val getName = methods[0] + val setName = methods[1] + val getWeight = methods[2] + val setWeight = methods[3] + val getRating = methods[4] + val setRating = methods[5] + val getCode = methods[6] + val color = classDoc.fields()[3] + val code = classDoc.fields()[4] + + assertTrue(getName.isProtected) + assertEquals(PROTECTED, getName.modifierSpecifier()) + assertTrue(setName.isProtected) + assertEquals(PROTECTED, setName.modifierSpecifier()) + + assertTrue(getWeight.isPublic) + assertEquals(PUBLIC, getWeight.modifierSpecifier()) + assertTrue(setWeight.isPublic) + assertEquals(PUBLIC, setWeight.modifierSpecifier()) + + assertTrue(getRating.isPublic) + assertEquals(PUBLIC, getRating.modifierSpecifier()) + assertTrue(setRating.isPublic) + assertEquals(PUBLIC, setRating.modifierSpecifier()) + + assertTrue(getCode.isPublic) + assertEquals(PUBLIC or STATIC, getCode.modifierSpecifier()) + + assertEquals(methods.size, 7) + + assertTrue(color.isPrivate) + assertEquals(PRIVATE, color.modifierSpecifier()) + + assertTrue(code.isPrivate) + assertTrue(code.isStatic) + assertEquals(PRIVATE or STATIC, code.modifierSpecifier()) + } + } + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/testdata/javadoc/visibilityModifiers.kt b/core/testdata/javadoc/visibilityModifiers.kt new file mode 100644 index 00000000..e48e7f62 --- /dev/null +++ b/core/testdata/javadoc/visibilityModifiers.kt @@ -0,0 +1,15 @@ +package foo + +abstract class Apple { + protected var name: String = "foo" + internal var weight: Int = 180 + var rating: Int = 10 + private var color: String = "red" + + companion object { + @JvmStatic + val code : Int = 123456 + } + + +} \ No newline at end of file -- cgit From 5b451ab6abf60e15c8044daebc90c3a46c21c4fb Mon Sep 17 00:00:00 2001 From: KrystianUjma Date: Fri, 18 Jan 2019 15:36:25 +0100 Subject: Fix java doc primary constructors have duplicated parameters #341 Fixed --- core/src/main/kotlin/javadoc/docbase.kt | 17 +++++++++-------- core/src/test/kotlin/javadoc/JavadocTest.kt | 10 ++++++++++ core/testdata/javadoc/constructorParameters.kt | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 core/testdata/javadoc/constructorParameters.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt index aeb806f1..fcc017fd 100644 --- a/core/src/main/kotlin/javadoc/docbase.kt +++ b/core/src/main/kotlin/javadoc/docbase.kt @@ -521,12 +521,13 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR } private fun DocumentationNodeAdapter.collectParamTags(kind: NodeKind, sectionFilter: (ContentSection) -> Boolean) = - (node.details(kind) - .filter(DocumentationNode::hasNonEmptyContent) - .map { ParamTagAdapter(module, this, it.name, true, it.content.children) } + (node.details(kind) + .filter(DocumentationNode::hasNonEmptyContent) + .map { ParamTagAdapter(module, this, it.name, true, it.content.children) } - + node.content.sections - .filter(sectionFilter) - .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) }) - - .toTypedArray() \ No newline at end of file + + node.content.sections + .filter(sectionFilter) + .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) } + ) + .distinctBy { it.parameterName } + .toTypedArray() \ No newline at end of file diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index b18dacca..9ca668d8 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -223,6 +223,16 @@ class JavadocTest { } } + @Test + fun shouldNotHaveDuplicatedConstructorParameters() { + verifyJavadoc("testdata/javadoc/constructorParameters.kt") { doc -> + val classDoc = doc.classNamed("bar.Banana")!! + val paramTags = classDoc.constructors()[0].paramTags() + + assertEquals(3, paramTags.size) + } + } + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/testdata/javadoc/constructorParameters.kt b/core/testdata/javadoc/constructorParameters.kt new file mode 100644 index 00000000..c29ae912 --- /dev/null +++ b/core/testdata/javadoc/constructorParameters.kt @@ -0,0 +1,14 @@ +package bar + +/** + * Just a fruit + * + * @param weight in grams + * @param ranking quality from 0 to 10, where 10 is best + * @param color yellow is default + */ +class Banana ( + private val weight: Double, + private val ranking: Int, + color: String = "yellow" +) \ No newline at end of file -- cgit From a2104d1e24a452cbfd2a76c204fc58475aa70057 Mon Sep 17 00:00:00 2001 From: Błażej Kardyś Date: Tue, 5 Feb 2019 16:05:15 +0100 Subject: Fix @deprecated visibility in JavaDoc (#420) #343 Fixed --- core/src/main/kotlin/Java/JavadocParser.kt | 7 ++++--- core/src/test/kotlin/javadoc/JavadocTest.kt | 10 ++++++++++ core/testdata/javadoc/deprecated.java | 28 ++++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 core/testdata/javadoc/deprecated.java (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index d6e46c50..39a4568a 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -83,7 +83,7 @@ class JavadocParser( "see" -> result.convertSeeTag(tag) "deprecated" -> { deprecatedContent = Content().apply { - appendAll(convertJavadocElements(tag.contentElements(), element)) + appendAll(convertJavadocElements(tag.contentElementsOrFirstChild(), element)) } } in tagsToInherit -> {} @@ -122,9 +122,10 @@ class JavadocParser( recursiveSearch(arrayOf(this)) return output.mapValues { it.value.values } } + private fun PsiDocTag.contentElementsOrFirstChild(): Collection = contentElements() + .takeIf { it.isNotEmpty() } ?: children.take(1) - - private fun PsiDocTag.contentElements(): Iterable { + private fun PsiDocTag.contentElements(): Collection { val tagValueElements = children .dropWhile { it.node?.elementType == JavaDocTokenType.DOC_TAG_NAME } .dropWhile { it is PsiWhiteSpace } diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 9ca668d8..7f1b44da 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -233,6 +233,16 @@ class JavadocTest { } } + @Test fun shouldHaveAllFunctionMarkedAsDeprecated() { + verifyJavadoc("testdata/javadoc/deprecated.java") { doc -> + val classDoc = doc.classNamed("bar.Banana")!! + + classDoc.methods().forEach { + assertNotNull((it as? DocumentationNodeAdapter)?.node?.deprecation) + } + } + } + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/testdata/javadoc/deprecated.java b/core/testdata/javadoc/deprecated.java new file mode 100644 index 00000000..5a6cdd77 --- /dev/null +++ b/core/testdata/javadoc/deprecated.java @@ -0,0 +1,28 @@ +package bar; + +/** + * Just a fruit + */ +public class Banana { + private Double weight; + + /** + * Returns weight + * + * @return weight + * @deprecated + */ + public Double getWeight() { + return weight; + } + + /** + * Sets weight + * + * @param weight in grams + * @deprecated with message + */ + public void setWeight(Double weight) { + this.weight = weight; + } +} \ No newline at end of file -- cgit From ff25593e8af941c624f3bee8bc031ae53c3700d5 Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 25 Feb 2019 19:45:09 +0300 Subject: Fix problem on consumer side, improve test (#420) --- core/src/main/kotlin/Java/JavadocParser.kt | 7 +++---- core/src/main/kotlin/javadoc/docbase.kt | 4 +--- core/src/test/kotlin/javadoc/JavadocTest.kt | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 39a4568a..d6e46c50 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -83,7 +83,7 @@ class JavadocParser( "see" -> result.convertSeeTag(tag) "deprecated" -> { deprecatedContent = Content().apply { - appendAll(convertJavadocElements(tag.contentElementsOrFirstChild(), element)) + appendAll(convertJavadocElements(tag.contentElements(), element)) } } in tagsToInherit -> {} @@ -122,10 +122,9 @@ class JavadocParser( recursiveSearch(arrayOf(this)) return output.mapValues { it.value.values } } - private fun PsiDocTag.contentElementsOrFirstChild(): Collection = contentElements() - .takeIf { it.isNotEmpty() } ?: children.take(1) - private fun PsiDocTag.contentElements(): Collection { + + private fun PsiDocTag.contentElements(): Iterable { val tagValueElements = children .dropWhile { it.node?.elementType == JavaDocTokenType.DOC_TAG_NAME } .dropWhile { it is PsiWhiteSpace } diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt index fcc017fd..fbf8c464 100644 --- a/core/src/main/kotlin/javadoc/docbase.kt +++ b/core/src/main/kotlin/javadoc/docbase.kt @@ -75,9 +75,7 @@ open class DocumentationNodeAdapter(override val module: ModuleNodeAdapter, node node.deprecation?.let { val content = it.content.asText() - if (content != null) { - result.add(TagImpl(this, "deprecated", content)) - } + result.add(TagImpl(this, "deprecated", content ?: "")) } return result.toTypedArray() diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 7f1b44da..04f8b920 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -237,8 +237,8 @@ class JavadocTest { verifyJavadoc("testdata/javadoc/deprecated.java") { doc -> val classDoc = doc.classNamed("bar.Banana")!! - classDoc.methods().forEach { - assertNotNull((it as? DocumentationNodeAdapter)?.node?.deprecation) + classDoc.methods().forEach { method -> + assertTrue(method.tags().any { it.kind() == "deprecated" }) } } } -- cgit From f4aeac0a974837a18d0c18d42bd5980dffa043fb Mon Sep 17 00:00:00 2001 From: Dominik Schürmann Date: Mon, 21 Jan 2019 01:16:09 +0100 Subject: Preserve newlines in javadoc code blocks --- core/src/main/kotlin/Java/JavadocParser.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index d6e46c50..3411b5c7 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -160,13 +160,17 @@ class JavadocParser( return ContentText(node.text()) } else if (node is Element) { val childBlock = createBlock(node) - node.childNodes().forEach { - val child = convertHtmlNode(it) - if (child != null) { - childBlock.append(child) + if (childBlock is ContentBlockCode) { + childBlock.append(ContentText(node.text())) + } else { + node.childNodes().forEach { + val child = convertHtmlNode(it) + if (child != null) { + childBlock.append(child) + } } + return (childBlock) } - return (childBlock) } return null } -- cgit From 3fc4102597437dbf217c96b70000cac5fb9b591b Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Mon, 25 Feb 2019 21:34:14 +0300 Subject: Rework logic to avoid loosing tags inside pre --- core/src/main/kotlin/Java/JavadocParser.kt | 26 ++++++++++++-------------- core/testdata/format/javadocHtml.java | 12 ++++++++++++ core/testdata/format/javadocHtml.md | 16 ++++++++++++++++ 3 files changed, 40 insertions(+), 14 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavadocParser.kt b/core/src/main/kotlin/Java/JavadocParser.kt index 3411b5c7..70af73f9 100644 --- a/core/src/main/kotlin/Java/JavadocParser.kt +++ b/core/src/main/kotlin/Java/JavadocParser.kt @@ -155,32 +155,30 @@ class JavadocParser( return htmlBuilder.toString().trim() } - private fun convertHtmlNode(node: Node): ContentNode? { + private fun convertHtmlNode(node: Node, insidePre: Boolean = false): ContentNode? { if (node is TextNode) { - return ContentText(node.text()) + val text = if (insidePre) node.wholeText else node.text() + return ContentText(text) } else if (node is Element) { - val childBlock = createBlock(node) - if (childBlock is ContentBlockCode) { - childBlock.append(ContentText(node.text())) - } else { - node.childNodes().forEach { - val child = convertHtmlNode(it) - if (child != null) { - childBlock.append(child) - } + val childBlock = createBlock(node, insidePre) + + node.childNodes().forEach { + val child = convertHtmlNode(it, insidePre || childBlock is ContentBlockCode) + if (child != null) { + childBlock.append(child) } - return (childBlock) } + return childBlock } return null } - private fun createBlock(element: Element): ContentBlock = when (element.tagName()) { + private fun createBlock(element: Element, insidePre: Boolean): ContentBlock = when (element.tagName()) { "p" -> ContentParagraph() "b", "strong" -> ContentStrong() "i", "em" -> ContentEmphasis() "s", "del" -> ContentStrikethrough() - "code" -> ContentCode() + "code" -> if (insidePre) ContentBlock() else ContentCode() "pre" -> ContentBlockCode() "ul" -> ContentUnorderedList() "ol" -> ContentOrderedList() diff --git a/core/testdata/format/javadocHtml.java b/core/testdata/format/javadocHtml.java index 622116b2..9e77402e 100644 --- a/core/testdata/format/javadocHtml.java +++ b/core/testdata/format/javadocHtml.java @@ -9,6 +9,18 @@ * Code *
Block code
*
  • List Item
+ *
+ * with( some ) {
+ *    multi = lines
+ *    sample()
+ * }
+ * 
+ *
+ * {@code
+ *  with (some) {  }
+ * }
+ * 
+ * */ public class C { } diff --git a/core/testdata/format/javadocHtml.md b/core/testdata/format/javadocHtml.md index 9b501fcb..77f6c829 100644 --- a/core/testdata/format/javadocHtml.md +++ b/core/testdata/format/javadocHtml.md @@ -16,6 +16,22 @@ Block code * List Item + +``` + + with( some ) { + multi = lines + sample() + } + ``` + + + +``` +with (some) { } + + ``` + ### Constructors | [<init>](-init-.md) | `C()`
**Bold** **Strong** *Italic* *Emphasized* | -- cgit From 01f2f0372410ff500c59247b639660161b314afa Mon Sep 17 00:00:00 2001 From: Krystian Ujma Date: Fri, 1 Mar 2019 14:43:14 +0100 Subject: Fix constructor tag does not work (#417) #300 Fixed --- .../kotlin/Kotlin/DescriptorDocumentationParser.kt | 20 ++++++++++++++++---- .../Kotlin/KotlinAsJavaDocumentationBuilder.kt | 5 ++++- core/src/test/kotlin/javadoc/JavadocTest.kt | 16 ++++++++++++++++ core/testdata/javadoc/defaultNoArgConstructor.kt | 12 ++++++++++++ core/testdata/javadoc/noArgConstructor.kt | 12 ++++++++++++ 5 files changed, 60 insertions(+), 5 deletions(-) create mode 100644 core/testdata/javadoc/defaultNoArgConstructor.kt create mode 100644 core/testdata/javadoc/noArgConstructor.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt index 7817da18..d1f98184 100644 --- a/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt +++ b/core/src/main/kotlin/Kotlin/DescriptorDocumentationParser.kt @@ -19,6 +19,8 @@ import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.annotations.argumentValue import org.jetbrains.kotlin.resolve.constants.StringValue @@ -38,10 +40,10 @@ class DescriptorDocumentationParser val externalDocumentationLinkResolver: ExternalDocumentationLinkResolver ) { - fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false): Content = - parseDocumentationAndDetails(descriptor, inline).first + fun parseDocumentation(descriptor: DeclarationDescriptor, inline: Boolean = false, isDefaultNoArgConstructor: Boolean = false): Content = + parseDocumentationAndDetails(descriptor, inline, isDefaultNoArgConstructor).first - fun parseDocumentationAndDetails(descriptor: DeclarationDescriptor, inline: Boolean = false): Pair Unit> { + fun parseDocumentationAndDetails(descriptor: DeclarationDescriptor, inline: Boolean = false, isDefaultNoArgConstructor: Boolean = false): Pair Unit> { if (descriptor is JavaClassDescriptor || descriptor is JavaCallableMemberDescriptor) { return parseJavadoc(descriptor) } @@ -62,7 +64,10 @@ class DescriptorDocumentationParser ?.resolveToDescriptorIfAny() ?: descriptor - var kdocText = kdoc.getContent() + var kdocText = if (isDefaultNoArgConstructor) { + getConstructorTagContent(descriptor) ?: kdoc.getContent() + } else kdoc.getContent() + // workaround for code fence parsing problem in IJ markdown parser if (kdocText.endsWith("```") || kdocText.endsWith("~~~")) { kdocText += "\n" @@ -90,6 +95,13 @@ class DescriptorDocumentationParser return content to { node -> } } + private fun getConstructorTagContent(descriptor: DeclarationDescriptor): String? { + return ((DescriptorToSourceUtils.descriptorToDeclaration(descriptor)?.navigationElement as? KtElement) as KtDeclaration).docComment?.findSectionByTag( + KDocKnownTag.CONSTRUCTOR + )?.getContent() + } + + private fun DeclarationDescriptor.isSuppressWarning() : Boolean { val suppressAnnotation = annotations.findAnnotation(FqName(Suppress::class.qualifiedName!!)) return if (suppressAnnotation != null) { diff --git a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt index c7ed8292..00a795d0 100644 --- a/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt +++ b/core/src/main/kotlin/Kotlin/KotlinAsJavaDocumentationBuilder.kt @@ -6,9 +6,11 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiNamedElement import org.jetbrains.dokka.Kotlin.DescriptorDocumentationParser import org.jetbrains.kotlin.asJava.elements.KtLightElement +import org.jetbrains.kotlin.asJava.elements.KtLightMethod import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtParameter import org.jetbrains.kotlin.psi.KtPropertyAccessor @@ -59,8 +61,9 @@ class KotlinAsJavaDocumentationParser return JavadocParseResult.Empty } } + val isDefaultNoArgConstructor = kotlinLightElement is KtLightMethod && origin is KtClass val descriptor = resolutionFacade.resolveToDescriptor(origin) - val content = descriptorDocumentationParser.parseDocumentation(descriptor, origin is KtParameter) + val content = descriptorDocumentationParser.parseDocumentation(descriptor, origin is KtParameter, isDefaultNoArgConstructor) return JavadocParseResult(content, null) } } diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 04f8b920..3e5b5ff8 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -243,6 +243,22 @@ class JavadocTest { } } + @Test + fun testDefaultNoArgConstructor() { + verifyJavadoc("testdata/javadoc/defaultNoArgConstructor.kt") { doc -> + val classDoc = doc.classNamed("foo.Peach")!! + assertTrue(classDoc.constructors()[0].tags()[2].text() == "print peach") + } + } + + @Test + fun testNoArgConstructor() { + verifyJavadoc("testdata/javadoc/noArgConstructor.kt") { doc -> + val classDoc = doc.classNamed("foo.Plum")!! + assertTrue(classDoc.constructors()[0].tags()[2].text() == "print plum") + } + } + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/testdata/javadoc/defaultNoArgConstructor.kt b/core/testdata/javadoc/defaultNoArgConstructor.kt new file mode 100644 index 00000000..3a6d04a5 --- /dev/null +++ b/core/testdata/javadoc/defaultNoArgConstructor.kt @@ -0,0 +1,12 @@ +package foo + +/** + * Description + * + * @constructor print peach + */ +class Peach { + init { + println("peach") + } +} \ No newline at end of file diff --git a/core/testdata/javadoc/noArgConstructor.kt b/core/testdata/javadoc/noArgConstructor.kt new file mode 100644 index 00000000..25e5548c --- /dev/null +++ b/core/testdata/javadoc/noArgConstructor.kt @@ -0,0 +1,12 @@ +package foo + +/** + * Description + * + * @constructor print plum + */ +class Plum() { + init { + println("plum") + } +} \ No newline at end of file -- cgit From 20bd82d30881f8b8439ea49baab923bc04ff1f2e Mon Sep 17 00:00:00 2001 From: Robert Stoll Date: Thu, 21 Jun 2018 22:35:31 +0200 Subject: Use canonicalPath instead of absolutePath for srcLink This way a user can define "./" instead of an absolute path to the root of the project dir (or a user can use ../ etc.). Thus: - use canonicalPath in: - SourceLinkDefinitionImpl::parseSourceLinkDefinition - and DocumentationNode.appendSourceLink => here because if the config is deserialized we bypass parseSourceLinkDefinition - also use canonicalPath for the path of PsiElement Moreover: - make sure the comparison works for unix and windows paths - fixes #289 --- README.md | 6 +- .../main/kotlin/Generation/configurationImpl.kt | 4 +- core/src/main/kotlin/Model/SourceLinks.kt | 38 ++++++++--- core/src/test/kotlin/TestAPI.kt | 10 ++- core/src/test/kotlin/model/SourceLinksErrorTest.kt | 34 ++++++++++ core/src/test/kotlin/model/SourceLinksTest.kt | 76 ++++++++++++++++++++++ core/testdata/sourceLinks/dummy.kt | 6 ++ 7 files changed, 158 insertions(+), 16 deletions(-) create mode 100644 core/src/test/kotlin/model/SourceLinksErrorTest.kt create mode 100644 core/src/test/kotlin/model/SourceLinksTest.kt create mode 100644 core/testdata/sourceLinks/dummy.kt (limited to 'core/src/main/kotlin') diff --git a/README.md b/README.md index 341305fa..f0cca532 100644 --- a/README.md +++ b/README.md @@ -100,11 +100,11 @@ dokka { // If provided, Dokka generates "source" links for each declaration. // Repeat for multiple mappings linkMapping { - // Source directory - dir = "src/main/kotlin" + // Directory relative to the root of the project (where you execute gradle respectively). + dir = "src/main/kotlin" // or simply "./" // URL showing where the source code can be accessed through the web browser - url = "https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin" + url = "https://github.com/cy6erGn0m/vertx3-lang-kotlin/blob/master/src/main/kotlin" //remove src/main/kotlin if you use "./" above // Suffix which is used to append the line number to the URL. Use #L for GitHub suffix = "#L" diff --git a/core/src/main/kotlin/Generation/configurationImpl.kt b/core/src/main/kotlin/Generation/configurationImpl.kt index 90e27b4b..eecf122e 100644 --- a/core/src/main/kotlin/Generation/configurationImpl.kt +++ b/core/src/main/kotlin/Generation/configurationImpl.kt @@ -11,9 +11,9 @@ data class SourceLinkDefinitionImpl(override val path: String, companion object { fun parseSourceLinkDefinition(srcLink: String): SourceLinkDefinition { val (path, urlAndLine) = srcLink.split('=') - return SourceLinkDefinitionImpl(File(path).absolutePath, + return SourceLinkDefinitionImpl(File(path).canonicalPath, urlAndLine.substringBefore("#"), - urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#" + it }) + urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" }) } } } diff --git a/core/src/main/kotlin/Model/SourceLinks.kt b/core/src/main/kotlin/Model/SourceLinks.kt index 2c75cfda..99ee362e 100644 --- a/core/src/main/kotlin/Model/SourceLinks.kt +++ b/core/src/main/kotlin/Model/SourceLinks.kt @@ -10,20 +10,20 @@ import java.io.File fun DocumentationNode.appendSourceLink(psi: PsiElement?, sourceLinks: List) { val path = psi?.containingFile?.virtualFile?.path ?: return + val canonicalPath = File(path).canonicalPath val target = if (psi is PsiNameIdentifierOwner) psi.nameIdentifier else psi - val absPath = File(path).absolutePath - val linkDef = sourceLinks.firstOrNull { absPath.startsWith(it.path) } - if (linkDef != null) { - var url = linkDef.url + path.substring(linkDef.path.length) - if (linkDef.lineSuffix != null) { + val pair = determineSourceLinkDefinition(canonicalPath, sourceLinks) + if (pair != null) { + val (sourceLinkDefinition, sourceLinkCanonicalPath) = pair + var url = determineUrl(canonicalPath, sourceLinkDefinition, sourceLinkCanonicalPath) + if (sourceLinkDefinition.lineSuffix != null) { val line = target?.lineNumber() if (line != null) { - url += linkDef.lineSuffix + line.toString() + url += sourceLinkDefinition.lineSuffix + line.toString() } } - append(DocumentationNode(url, Content.Empty, NodeKind.SourceUrl), - RefKind.Detail); + append(DocumentationNode(url, Content.Empty, NodeKind.SourceUrl), RefKind.Detail) } if (target != null) { @@ -31,6 +31,28 @@ fun DocumentationNode.appendSourceLink(psi: PsiElement?, sourceLinks: List +): Pair? { + return sourceLinks + .asSequence() + .map { it to File(it.path).canonicalPath } + .firstOrNull { (_, sourceLinkCanonicalPath) -> + canonicalPath.startsWith(sourceLinkCanonicalPath) + } +} + +private fun determineUrl( + canonicalPath: String, + sourceLinkDefinition: SourceLinkDefinition, + sourceLinkCanonicalPath: String +): String { + val relativePath = canonicalPath.substring(sourceLinkCanonicalPath.length) + val relativeUrl = relativePath.replace('\\', '/').removePrefix("/") + return "${sourceLinkDefinition.url.removeSuffix("/")}/$relativeUrl" +} + private fun PsiElement.sourcePosition(): String { val path = containingFile.virtualFile.path val lineNumber = lineNumber() diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt index f72373d9..4f77a2f6 100644 --- a/core/src/test/kotlin/TestAPI.kt +++ b/core/src/test/kotlin/TestAPI.kt @@ -6,6 +6,7 @@ import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.io.FileUtil import com.intellij.rt.execution.junit.FileComparisonFailure import org.jetbrains.dokka.* +import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition import org.jetbrains.dokka.Utilities.DokkaAnalysisModule import org.jetbrains.kotlin.cli.common.config.ContentRoot import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot @@ -26,6 +27,7 @@ fun verifyModel(vararg roots: ContentRoot, perPackageOptions: List = emptyList(), noStdlibLink: Boolean = true, collectInheritedExtensionsFromLibraries: Boolean = false, + sourceLinks: List = emptyList(), verifier: (DocumentationModule) -> Unit) { val documentation = DocumentationModule("test") @@ -35,7 +37,7 @@ fun verifyModel(vararg roots: ContentRoot, includeNonPublic = includeNonPublic, skipEmptyPackages = false, includeRootPackage = true, - sourceLinks = listOf(), + sourceLinks = sourceLinks, perPackageOptions = perPackageOptions, generateIndexPages = false, noStdlibLink = noStdlibLink, @@ -113,15 +115,17 @@ fun verifyModel(source: String, withKotlinRuntime: Boolean = false, format: String = "html", includeNonPublic: Boolean = true, + sourceLinks: List = emptyList(), verifier: (DocumentationModule) -> Unit) { - if (!File(source).exists()) { - throw IllegalArgumentException("Can't find test data file $source") + require (File(source).exists()) { + "Cannot find test data file $source" } verifyModel(contentRootFromPath(source), withJdk = withJdk, withKotlinRuntime = withKotlinRuntime, format = format, includeNonPublic = includeNonPublic, + sourceLinks = sourceLinks, verifier = verifier) } diff --git a/core/src/test/kotlin/model/SourceLinksErrorTest.kt b/core/src/test/kotlin/model/SourceLinksErrorTest.kt new file mode 100644 index 00000000..a72bd62a --- /dev/null +++ b/core/src/test/kotlin/model/SourceLinksErrorTest.kt @@ -0,0 +1,34 @@ +package org.jetbrains.dokka.tests.model + +import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.SourceLinkDefinitionImpl +import org.jetbrains.dokka.tests.verifyModel +import org.junit.Assert +import org.junit.Test +import java.io.File + +class SourceLinksErrorTest { + + @Test + fun absolutePath_notMatching() { + val sourceLink = SourceLinkDefinitionImpl(File("testdata/nonExisting").absolutePath, "http://...", null) + verifyNoSourceUrl(sourceLink) + } + + @Test + fun relativePath_notMatching() { + val sourceLink = SourceLinkDefinitionImpl("testdata/nonExisting", "http://...", null) + verifyNoSourceUrl(sourceLink) + } + + private fun verifyNoSourceUrl(sourceLink: SourceLinkDefinitionImpl) { + verifyModel("testdata/sourceLinks/dummy.kt", sourceLinks = listOf(sourceLink)) { model -> + with(model.members.single().members.single()) { + Assert.assertEquals("foo", name) + Assert.assertEquals(NodeKind.Function, kind) + Assert.assertTrue("should not have source urls", details(NodeKind.SourceUrl).isEmpty()) + } + } + } +} + diff --git a/core/src/test/kotlin/model/SourceLinksTest.kt b/core/src/test/kotlin/model/SourceLinksTest.kt new file mode 100644 index 00000000..1a74506f --- /dev/null +++ b/core/src/test/kotlin/model/SourceLinksTest.kt @@ -0,0 +1,76 @@ +package org.jetbrains.dokka.tests.model + +import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.SourceLinkDefinitionImpl +import org.jetbrains.dokka.tests.verifyModel +import org.junit.Assert +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import java.io.File + +@RunWith(Parameterized::class) +class SourceLinksTest( + private val srcLink: String, + private val url: String, + private val lineSuffix: String?, + private val expectedUrl: String +) { + + @Test + fun test() { + val link = if(srcLink.contains(sourceLinks)){ + srcLink.substringBeforeLast(sourceLinks) + sourceLinks + } else { + srcLink.substringBeforeLast(testdata) + testdata + } + val sourceLink = SourceLinkDefinitionImpl(link, url, lineSuffix) + + verifyModel(filePath, sourceLinks = listOf(sourceLink)) { model -> + with(model.members.single().members.single()) { + Assert.assertEquals("foo", name) + Assert.assertEquals(NodeKind.Function, kind) + Assert.assertEquals(expectedUrl, details(NodeKind.SourceUrl).single().name) + } + } + } + + companion object { + private const val testdata = "testdata" + private const val sourceLinks = "sourceLinks" + private const val dummy = "dummy.kt" + private const val pathSuffix = "$sourceLinks/$dummy" + private const val filePath = "$testdata/$pathSuffix/../dummy.kt" + private const val url = "https://example.com" + + @Parameterized.Parameters(name = "{index}: {0}, {1}, {2} = {3}") + @JvmStatic + fun data(): Collection> { + val longestPath = File(testdata).absolutePath.removeSuffix("/") + "/../$testdata/" + val maxLength = longestPath.length + val list = listOf( + arrayOf(File(testdata).absolutePath.removeSuffix("/"), "$url/$pathSuffix"), + arrayOf(File("$testdata/$sourceLinks").absolutePath.removeSuffix("/") + "/", "$url/$dummy"), + arrayOf(longestPath, "$url/$pathSuffix"), + + arrayOf(testdata, "$url/$pathSuffix"), + arrayOf("./$testdata", "$url/$pathSuffix"), + arrayOf("../core/$testdata", "$url/$pathSuffix"), + arrayOf("$testdata/$sourceLinks", "$url/$dummy"), + arrayOf("./$testdata/../$testdata/$sourceLinks", "$url/$dummy") + ) + val allPaths = list + + // we want to be sure Windows paths work as well + list.map { arrayOf(it[0].replace('/', '\\'), it[1]) } + return allPaths.map { arrayOf(it[0].padEnd(maxLength, '_'), url, null, it[1]) } + + listOf( + // check that it also works if url ends with / + arrayOf((File(testdata).absolutePath.removeSuffix("/") + "/").padEnd(maxLength, '_'), "$url/", null, "$url/$pathSuffix"), + // check if line suffix work + arrayOf("../core/../core/./$testdata/$sourceLinks/".padEnd(maxLength, '_'), "$url/", "#L", "$url/$dummy#L4") + ) + } + } + +} + diff --git a/core/testdata/sourceLinks/dummy.kt b/core/testdata/sourceLinks/dummy.kt new file mode 100644 index 00000000..cbaffe7c --- /dev/null +++ b/core/testdata/sourceLinks/dummy.kt @@ -0,0 +1,6 @@ +/** + * Some doc. + */ +fun foo(){ + +} -- cgit From 61b126692bb2ede06911ae1c493e8417f0bbe49d Mon Sep 17 00:00:00 2001 From: Kamil Doległo Date: Mon, 11 Mar 2019 17:11:50 +0100 Subject: Allow linking arguments with methods, change link label (#431) * Add PsiParameter to link arguments with methods, change link label --- core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt | 12 ++++++++++-- core/src/main/kotlin/Model/Content.kt | 5 +++++ core/src/main/kotlin/javadoc/tags.kt | 2 +- core/src/test/kotlin/javadoc/JavadocTest.kt | 12 ++++++++++++ core/testdata/javadoc/argumentReference.kt | 4 ++++ 5 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 core/testdata/javadoc/argumentReference.kt (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index f0b3a56b..1ef601d3 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -20,11 +20,19 @@ fun getSignature(element: PsiElement?) = when(element) { is PsiClass -> element.qualifiedName is PsiField -> element.containingClass!!.qualifiedName + "$" + element.name is PsiMethod -> - element.containingClass!!.qualifiedName + "$" + element.name + "(" + - element.parameterList.parameters.map { it.type.typeSignature() }.joinToString(",") + ")" + methodSignature(element) + is PsiParameter -> { + val method = (element.parent.parent as PsiMethod) + methodSignature(method) + } else -> null } +private fun methodSignature(method: PsiMethod): String { + return method.containingClass!!.qualifiedName + "$" + method.name + "(" + + method.parameterList.parameters.map { it.type.typeSignature() }.joinToString(",") + ")" +} + private fun PsiType.typeSignature(): String = when(this) { is PsiArrayType -> "Array((${componentType.typeSignature()}))" is PsiPrimitiveType -> "kotlin." + canonicalText.capitalize() diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 87a8023a..c142f4a4 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -115,6 +115,7 @@ class ContentBlockSampleCode(language: String = "kotlin", val importsBlock: Cont abstract class ContentNodeLink() : ContentBlock() { abstract val node: DocumentationNode? + abstract val text: String? } object ContentHardLineBreak : ContentNode { @@ -128,6 +129,8 @@ class ContentNodeDirectLink(override val node: DocumentationNode): ContentNodeLi override fun hashCode(): Int = children.hashCode() * 31 + node.name.hashCode() + + override val text: String? = null } class ContentNodeLazyLink(val linkText: String, val lazyNode: () -> DocumentationNode?): ContentNodeLink() { @@ -138,6 +141,8 @@ class ContentNodeLazyLink(val linkText: String, val lazyNode: () -> Documentatio override fun hashCode(): Int = children.hashCode() * 31 + linkText.hashCode() + + override val text: String? = linkText } class ContentExternalLink(val href : String) : ContentBlock() { diff --git a/core/src/main/kotlin/javadoc/tags.kt b/core/src/main/kotlin/javadoc/tags.kt index 05d98b71..99c9bfff 100644 --- a/core/src/main/kotlin/javadoc/tags.kt +++ b/core/src/main/kotlin/javadoc/tags.kt @@ -71,7 +71,7 @@ class SeeMethodTagAdapter(holder: Doc, val method: MethodAdapter, content: Conte override fun referencedPackage(): PackageDoc? = null override fun referencedClass(): ClassDoc? = method.containingClass() override fun referencedClassName(): String = method.containingClass()?.name() ?: "" - override fun label(): String = "${method.containingClass()?.name()}.${method.name()}" + override fun label(): String = content.text ?: "${method.containingClass()?.name()}.${method.name()}" override fun inlineTags(): Array = emptyArray() // TODO override fun firstSentenceTags(): Array = inlineTags() // TODO diff --git a/core/src/test/kotlin/javadoc/JavadocTest.kt b/core/src/test/kotlin/javadoc/JavadocTest.kt index 3e5b5ff8..6adbe7a0 100644 --- a/core/src/test/kotlin/javadoc/JavadocTest.kt +++ b/core/src/test/kotlin/javadoc/JavadocTest.kt @@ -259,6 +259,18 @@ class JavadocTest { } } + @Test + fun testArgumentReference() { + verifyJavadoc("testdata/javadoc/argumentReference.kt") { doc -> + val classDoc = doc.classNamed("ArgumentReferenceKt")!! + val method = classDoc.methods().first() + val tag = method.seeTags().first() + assertEquals("argNamedError", tag.referencedMemberName()) + assertEquals("error", tag.label()) + } + } + + private fun verifyJavadoc(name: String, withJdk: Boolean = false, withKotlinRuntime: Boolean = false, diff --git a/core/testdata/javadoc/argumentReference.kt b/core/testdata/javadoc/argumentReference.kt new file mode 100644 index 00000000..ac3104e9 --- /dev/null +++ b/core/testdata/javadoc/argumentReference.kt @@ -0,0 +1,4 @@ +/** + * [error] + */ +fun argNamedError(error: String) {} \ No newline at end of file -- cgit From 52b303d4251d54ddf9f09330f902621689a50f5d Mon Sep 17 00:00:00 2001 From: Krystian Ujma Date: Mon, 11 Mar 2019 17:12:44 +0100 Subject: Fix not null annotation java-as-html bug (#442) --- core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index 1ef601d3..e26fa13e 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -311,7 +311,7 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { } fun PsiAnnotation.build(): DocumentationNode { - val node = DocumentationNode(nameReferenceElement?.text ?: "", Content.Empty, NodeKind.Annotation) + val node = DocumentationNode(qualifiedName?.substringAfterLast(".") ?: "", Content.Empty, NodeKind.Annotation) parameterList.attributes.forEach { val parameter = DocumentationNode(it.name ?: "value", Content.Empty, NodeKind.Parameter) val value = it.value -- cgit From 69eefa767ccf692297cbdb9dc44240a4fa67aa3c Mon Sep 17 00:00:00 2001 From: Simon Ogorodnik Date: Wed, 13 Mar 2019 16:30:07 +0300 Subject: Fix nullability annotations in javadoc #446 fixed --- .../kotlin/Java/JavaPsiDocumentationBuilder.kt | 27 +++++++++++++++++++--- core/src/main/kotlin/Model/DocumentationNode.kt | 23 ++++++++++-------- core/src/main/kotlin/javadoc/docbase.kt | 5 +++- 3 files changed, 41 insertions(+), 14 deletions(-) (limited to 'core/src/main/kotlin') diff --git a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt index e26fa13e..f1f170d7 100644 --- a/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt +++ b/core/src/main/kotlin/Java/JavaPsiDocumentationBuilder.kt @@ -6,6 +6,7 @@ import com.intellij.psi.* import com.intellij.psi.impl.JavaConstantExpressionEvaluator import com.intellij.psi.util.InheritanceUtil import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.asJava.elements.KtLightAbstractAnnotation import org.jetbrains.kotlin.asJava.elements.KtLightDeclaration import org.jetbrains.kotlin.asJava.elements.KtLightElement import org.jetbrains.kotlin.kdoc.parser.KDocKnownTag @@ -109,9 +110,11 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { fun nodeForElement(element: PsiNamedElement, kind: NodeKind, - name: String = element.name ?: ""): DocumentationNode { + name: String = element.name ?: "", + register: Boolean = false): DocumentationNode { val (docComment, deprecatedContent) = docParser.parseDocumentation(element) val node = DocumentationNode(name, docComment, kind) + if (register) register(element, node) if (element is PsiModifierListOwner) { node.appendModifiers(element) val modifierList = element.modifierList @@ -180,13 +183,13 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { fun PsiClass.build(): DocumentationNode { val kind = when { + isAnnotationType -> NodeKind.AnnotationClass isInterface -> NodeKind.Interface isEnum -> NodeKind.Enum - isAnnotationType -> NodeKind.AnnotationClass isException() -> NodeKind.Exception else -> NodeKind.Class } - val node = nodeForElement(this, kind) + val node = nodeForElement(this, kind, register = isAnnotationType) superTypes.filter { !ignoreSupertype(it) }.forEach { node.appendType(it, NodeKind.Supertype) val superClass = it.resolve() @@ -310,8 +313,26 @@ class JavaPsiDocumentationBuilder : JavaDocumentationBuilder { return node } + private fun lookupOrBuildClass(psiClass: PsiClass): DocumentationNode { + val existing = refGraph.lookup(getSignature(psiClass)!!) + if (existing != null) return existing + val new = psiClass.build() + val packageNode = findOrCreatePackageNode(null, (psiClass.parent as PsiJavaFile).packageName, emptyMap(), refGraph) + packageNode.append(new, RefKind.Member) + return new + } + fun PsiAnnotation.build(): DocumentationNode { + + val original = when (this) { + is KtLightAbstractAnnotation -> clsDelegate + else -> this + } val node = DocumentationNode(qualifiedName?.substringAfterLast(".") ?: "", Content.Empty, NodeKind.Annotation) + val psiClass = original.nameReferenceElement?.resolve() as? PsiClass + if (psiClass != null && psiClass.isAnnotationType) { + node.append(lookupOrBuildClass(psiClass), RefKind.Link) + } parameterList.attributes.forEach { val parameter = DocumentationNode(it.name ?: "value", Content.Empty, NodeKind.Parameter) val value = it.value diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index a3388031..ad7801f2 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -179,17 +179,20 @@ val DocumentationNode.path: List } fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { - val existingNode = refGraph.lookup(packageName) - if (existingNode != null) { - return existingNode - } - val newNode = DocumentationNode(packageName, + val node = refGraph.lookup(packageName) ?: run { + val newNode = DocumentationNode( + packageName, packageContent.getOrElse(packageName) { Content.Empty }, - NodeKind.Package) + NodeKind.Package + ) - refGraph.register(packageName, newNode) - module?.append(newNode, RefKind.Member) - return newNode + refGraph.register(packageName, newNode) + newNode + } + if (module != null && node !in module.members) { + module.append(node, RefKind.Member) + } + return node } fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) { @@ -215,7 +218,7 @@ fun DocumentationNode.qualifiedName(): String { } else if (kind == NodeKind.Package) { return name } - return path.drop(1).map { it.name }.filter { it.length > 0 }.joinToString(".") + return path.dropWhile { it.kind == NodeKind.Module }.map { it.name }.filter { it.isNotEmpty() }.joinToString(".") } fun DocumentationNode.simpleName() = name.substringAfterLast('.') diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt index fbf8c464..118b134a 100644 --- a/core/src/main/kotlin/javadoc/docbase.kt +++ b/core/src/main/kotlin/javadoc/docbase.kt @@ -114,7 +114,7 @@ class AnnotationTypeDocAdapter(module: ModuleNodeAdapter, node: DocumentationNod } class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : AnnotationDesc { - override fun annotationType(): AnnotationTypeDoc? = AnnotationTypeDocAdapter(module, node) // TODO ????? + override fun annotationType(): AnnotationTypeDoc? = AnnotationTypeDocAdapter(module, node.links.find { it.kind == NodeKind.AnnotationClass } ?: node) // TODO ????? override fun isSynthesized(): Boolean = false override fun elementValues(): Array? = emptyArray() // TODO } @@ -411,6 +411,9 @@ open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNod return classNode.simpleName() } + override fun qualifiedName(): String? { + return super.qualifiedName() + } override fun constructors(filter: Boolean): Array = classNode.members(NodeKind.Constructor).map { ConstructorAdapter(module, it) }.toTypedArray() override fun constructors(): Array = constructors(true) override fun importedPackages(): Array = emptyArray() -- cgit