aboutsummaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/kotlin/Analysis/AnalysisEnvironment.kt58
-rw-r--r--core/src/main/kotlin/Formats/StructuredFormatService.kt25
-rw-r--r--core/src/main/kotlin/Kotlin/DocumentationBuilder.kt96
-rw-r--r--core/src/main/kotlin/Kotlin/KotlinLanguageService.kt8
-rw-r--r--core/src/main/kotlin/Model/Content.kt4
-rw-r--r--core/src/main/kotlin/Model/DocumentationNode.kt5
-rw-r--r--core/src/main/kotlin/javadoc/docbase.kt50
-rw-r--r--core/src/main/kotlin/javadoc/tags.kt29
8 files changed, 186 insertions, 89 deletions
diff --git a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt
index 46fcb6c2..b192794e 100644
--- a/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt
+++ b/core/src/main/kotlin/Analysis/AnalysisEnvironment.kt
@@ -30,13 +30,17 @@ import org.jetbrains.kotlin.context.ProjectContext
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
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.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.CompilerEnvironment
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.JvmPlatformParameters
+import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
import java.io.File
@@ -81,26 +85,61 @@ class AnalysisEnvironment(val messageCollector: MessageCollector) : Disposable {
return environment
}
+ fun createSourceModuleSearchScope(project: Project, sourceFiles: List<KtFile>): GlobalSearchScope {
+ // TODO: Fix when going to implement dokka for JS
+ return TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, sourceFiles)
+ }
+
+
fun createResolutionFacade(environment: KotlinCoreEnvironment): DokkaResolutionFacade {
+
val projectContext = ProjectContext(environment.project)
val sourceFiles = environment.getSourceFiles()
+
+ val library = object : ModuleInfo {
+ override val name: Name = Name.special("<library>")
+ override fun dependencies(): List<ModuleInfo> = listOf(this)
+ }
val module = object : ModuleInfo {
override val name: Name = Name.special("<module>")
- override fun dependencies(): List<ModuleInfo> = listOf(this)
+ override fun dependencies(): List<ModuleInfo> = listOf(this, library)
}
+
+ val sourcesScope = createSourceModuleSearchScope(environment.project, sourceFiles)
+
+ val builtIns = JvmBuiltIns(projectContext.storageManager)
val resolverForProject = JvmAnalyzerFacade.setupResolverForProject(
"Dokka",
projectContext,
- listOf(module),
- { ModuleContent(sourceFiles, GlobalSearchScope.allScope(environment.project)) },
- JvmPlatformParameters { module },
+ listOf(library, module),
+ {
+ 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(environment, content.moduleContentScope) }
+ packagePartProviderFactory = {
+ info, content ->
+ JvmPackagePartProvider(environment, content.moduleContentScope)
+ },
+ builtIns = builtIns
)
+ resolverForProject.resolverForModule(library) // Required before module to initialize library properly
val resolverForModule = resolverForProject.resolverForModule(module)
- return DokkaResolutionFacade(environment.project, resolverForProject.descriptorForModule(module), resolverForModule)
+ val moduleDescriptor = resolverForProject.descriptorForModule(module)
+ builtIns.initialize(moduleDescriptor, true)
+ return DokkaResolutionFacade(environment.project, moduleDescriptor, resolverForModule)
}
/**
@@ -168,6 +207,10 @@ fun contentRootFromPath(path: String): ContentRoot {
class DokkaResolutionFacade(override val project: Project,
override val moduleDescriptor: ModuleDescriptor,
val resolverForModule: ResolverForModule) : ResolutionFacade {
+ override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor {
+ return resolveSession.resolveToDescriptor(declaration)
+ }
+
override fun analyze(elements: Collection<KtElement>, bodyResolveMode: BodyResolveMode): BindingContext {
throw UnsupportedOperationException()
}
@@ -198,7 +241,4 @@ class DokkaResolutionFacade(override val project: Project,
throw UnsupportedOperationException()
}
- override fun resolveToDescriptor(declaration: KtDeclaration): DeclarationDescriptor {
- return resolveSession.resolveToDescriptor(declaration)
- }
}
diff --git a/core/src/main/kotlin/Formats/StructuredFormatService.kt b/core/src/main/kotlin/Formats/StructuredFormatService.kt
index 183282ea..7896bcd8 100644
--- a/core/src/main/kotlin/Formats/StructuredFormatService.kt
+++ b/core/src/main/kotlin/Formats/StructuredFormatService.kt
@@ -23,11 +23,9 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
body()
if (checkEndsWith && to.endsWith(suffix)) {
to.setLength(to.length - suffix.length)
- }
- else if (to.length > startLength + prefix.length) {
+ } else if (to.length > startLength + prefix.length) {
to.append(suffix)
- }
- else {
+ } else {
to.setLength(startLength)
}
}
@@ -125,8 +123,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
val child = content.children.singleOrNull()
if (child is ContentParagraph) {
appendContent(child.children)
- }
- else {
+ } else {
appendContent(content.children)
}
}
@@ -371,7 +368,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
inner class SingleNodePageBuilder(val node: DocumentationNode)
- : PageBuilder(listOf(node)) {
+ : PageBuilder(listOf(node)) {
override fun build() {
super.build()
@@ -382,14 +379,15 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
appendSection("Packages", node.members(NodeKind.Package))
- appendSection("Types", node.members.filter { it.kind in NodeKind.classLike && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception })
+ appendSection("Types", node.members.filter { it.kind in NodeKind.classLike && it.kind != NodeKind.TypeAlias && it.kind != NodeKind.AnnotationClass && it.kind != NodeKind.Exception })
appendSection("Annotations", node.members(NodeKind.AnnotationClass))
appendSection("Exceptions", node.members(NodeKind.Exception))
+ appendSection("Type Aliases", node.members(NodeKind.TypeAlias))
appendSection("Extensions for External Classes", node.members(NodeKind.ExternalClass))
appendSection("Enum Values", node.members(NodeKind.EnumItem), sortMembers = false)
appendSection("Constructors", node.members(NodeKind.Constructor))
appendSection("Properties", node.members(NodeKind.Property))
- appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property))
+ appendSection("Inherited Properties", node.inheritedMembers(NodeKind.Property))
appendSection("Functions", node.members(NodeKind.Function))
appendSection("Inherited Functions", node.inheritedMembers(NodeKind.Function))
appendSection("Companion Object Properties", node.members(NodeKind.CompanionObjectProperty))
@@ -404,6 +402,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
NodeKind.Object,
NodeKind.AnnotationClass,
NodeKind.Exception,
+ NodeKind.TypeAlias,
NodeKind.Constructor,
NodeKind.Property,
NodeKind.Package,
@@ -482,7 +481,7 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
}
inner class AllTypesNodeBuilder(val node: DocumentationNode)
- : PageBuilder(listOf(node)) {
+ : PageBuilder(listOf(node)) {
override fun build() {
appendContent(node.owner!!.summary)
@@ -518,12 +517,10 @@ abstract class StructuredOutputBuilder(val to: StringBuilder,
if (singleNode != null) {
if (singleNode.kind == NodeKind.AllTypes) {
AllTypesNodeBuilder(singleNode).build()
- }
- else {
+ } else {
SingleNodePageBuilder(singleNode).build()
}
- }
- else {
+ } else {
PageBuilder(nodes).build()
}
}
diff --git a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
index ecb6edf2..f922a25b 100644
--- a/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
+++ b/core/src/main/kotlin/Kotlin/DocumentationBuilder.kt
@@ -25,10 +25,7 @@ import org.jetbrains.kotlin.resolve.findTopMostOverriddenDescriptors
import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
import org.jetbrains.kotlin.resolve.source.getPsi
-import org.jetbrains.kotlin.types.ErrorUtils
-import org.jetbrains.kotlin.types.KotlinType
-import org.jetbrains.kotlin.types.TypeProjection
-import org.jetbrains.kotlin.types.TypeUtils
+import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
import org.jetbrains.kotlin.types.typeUtil.supertypes
@@ -61,13 +58,12 @@ interface PackageDocumentationBuilder {
}
class DocumentationBuilder
- @Inject constructor(val resolutionFacade: DokkaResolutionFacade,
- val descriptorDocumentationParser: DescriptorDocumentationParser,
- val options: DocumentationOptions,
- val refGraph: NodeReferenceGraph,
- val logger: DokkaLogger,
- val linkResolver: DeclarationLinkResolver)
-{
+@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
+ val descriptorDocumentationParser: DescriptorDocumentationParser,
+ val options: DocumentationOptions,
+ val refGraph: NodeReferenceGraph,
+ val logger: DokkaLogger,
+ val linkResolver: DeclarationLinkResolver) {
val boringBuiltinClasses = setOf(
"kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean",
"kotlin.Float", "kotlin.Double", "kotlin.String", "kotlin.Array", "kotlin.Any")
@@ -97,7 +93,7 @@ class DocumentationBuilder
return node
}
- private fun DocumentationNode.withModifiers(descriptor: DeclarationDescriptor) : DocumentationNode{
+ private fun DocumentationNode.withModifiers(descriptor: DeclarationDescriptor): DocumentationNode {
if (descriptor is MemberDescriptor) {
appendVisibility(descriptor)
if (descriptor !is ConstructorDescriptor) {
@@ -124,15 +120,15 @@ class DocumentationBuilder
appendTextNode(modifier, NodeKind.Modifier)
}
- fun DocumentationNode.appendSupertypes(descriptor: ClassDescriptor) {
- val superTypes = descriptor.typeConstructor.supertypes
- for (superType in superTypes) {
- if (!ignoreSupertype(superType)) {
- appendType(superType, NodeKind.Supertype)
- val superclass = superType?.constructor?.declarationDescriptor
- link(superclass, descriptor, RefKind.Inheritor)
- link(descriptor, superclass, RefKind.Superclass)
- }
+ fun DocumentationNode.appendSupertype(descriptor: ClassDescriptor, superType: KotlinType) {
+ val unwrappedType = superType.unwrap()
+ if (unwrappedType is AbbreviatedType) {
+ appendSupertype(descriptor, unwrappedType.abbreviation)
+ } else if (!ignoreSupertype(unwrappedType)) {
+ appendType(unwrappedType, NodeKind.Supertype)
+ val superclass = unwrappedType.constructor.declarationDescriptor
+ link(superclass, descriptor, RefKind.Inheritor)
+ link(descriptor, superclass, RefKind.Superclass)
}
}
@@ -148,8 +144,7 @@ class DocumentationBuilder
fun DocumentationNode.appendProjection(projection: TypeProjection, kind: NodeKind = NodeKind.Type) {
if (projection.isStarProjection) {
appendTextNode("*", NodeKind.Type)
- }
- else {
+ } else {
appendType(projection.type, kind, projection.projectionKind.label)
}
}
@@ -157,14 +152,17 @@ class DocumentationBuilder
fun DocumentationNode.appendType(kotlinType: KotlinType?, kind: NodeKind = NodeKind.Type, prefix: String = "") {
if (kotlinType == null)
return
+ (kotlinType.unwrap() as? AbbreviatedType)?.let {
+ return appendType(it.abbreviation)
+ }
+
val classifierDescriptor = kotlinType.constructor.declarationDescriptor
val name = when (classifierDescriptor) {
is ClassDescriptor -> {
if (classifierDescriptor.isCompanionObject) {
classifierDescriptor.containingDeclaration.name.asString() +
"." + classifierDescriptor.name.asString()
- }
- else {
+ } else {
classifierDescriptor.name.asString()
}
}
@@ -182,8 +180,7 @@ class DocumentationBuilder
val jdkLink = linkResolver.buildJdkLink(classifierDescriptor)
if (jdkLink != null) {
node.append(DocumentationNode(jdkLink, Content.Empty, NodeKind.ExternalLink), RefKind.Link)
- }
- else {
+ } else {
link(node, classifierDescriptor,
if (classifierDescriptor.isBoringBuiltinClass()) RefKind.HiddenLink else RefKind.Link)
}
@@ -197,7 +194,7 @@ class DocumentationBuilder
}
fun ClassifierDescriptor.isBoringBuiltinClass(): Boolean =
- DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses
+ DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses
fun DocumentationNode.appendAnnotations(annotated: Annotated) {
annotated.annotations.filter { it.isDocumented() }.forEach {
@@ -250,8 +247,7 @@ class DocumentationBuilder
link(this, baseDescriptor, inheritedLinkKind)
}
null
- }
- else {
+ } else {
val descriptorToUse = if (descriptor is ConstructorDescriptor) descriptor else descriptor.original
appendChild(descriptorToUse, RefKind.Member)
}
@@ -378,9 +374,25 @@ class DocumentationBuilder
is TypeParameterDescriptor -> build()
is ValueParameterDescriptor -> build()
is ReceiverParameterDescriptor -> build()
+ is TypeAliasDescriptor -> build()
else -> throw IllegalStateException("Descriptor $this is not known")
}
+ fun TypeAliasDescriptor.build(): DocumentationNode {
+ val node = nodeForDescriptor(this, NodeKind.TypeAlias)
+
+ node.appendAnnotations(this)
+ node.appendModifiers(this)
+ node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail)
+
+ node.appendType(underlyingType, NodeKind.TypeAliasUnderlyingType)
+
+ node.appendSourceLink(source)
+
+ register(this, node)
+ return node
+ }
+
fun ClassDescriptor.build(): DocumentationNode {
val kind = when {
kind == ClassKind.OBJECT -> NodeKind.Object
@@ -392,7 +404,9 @@ class DocumentationBuilder
else -> NodeKind.Class
}
val node = nodeForDescriptor(this, kind)
- node.appendSupertypes(this)
+ typeConstructor.supertypes.forEach {
+ node.appendSupertype(this, it)
+ }
if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) {
node.appendInPageChildren(typeConstructor.parameters, RefKind.Detail)
val constructorsToDocument = if (getKind() == ClassKind.ENUM_CLASS)
@@ -572,8 +586,7 @@ class DocumentationBuilder
var receiverClass: DeclarationDescriptor = type.constructor.declarationDescriptor!!
if ((receiverClass as? ClassDescriptor)?.isCompanionObject ?: false) {
receiverClass = receiverClass.containingDeclaration!!
- }
- else if (receiverClass is TypeParameterDescriptor) {
+ } else if (receiverClass is TypeParameterDescriptor) {
val upperBoundClass = receiverClass.upperBounds.singleOrNull()?.constructor?.declarationDescriptor
if (upperBoundClass != null) {
receiverClass = upperBoundClass
@@ -648,11 +661,10 @@ class KotlinPackageDocumentationBuilder : PackageDocumentationBuilder {
}
class KotlinJavaDocumentationBuilder
- @Inject constructor(val resolutionFacade: DokkaResolutionFacade,
- val documentationBuilder: DocumentationBuilder,
- val options: DocumentationOptions,
- val logger: DokkaLogger) : JavaDocumentationBuilder
-{
+@Inject constructor(val resolutionFacade: DokkaResolutionFacade,
+ val documentationBuilder: DocumentationBuilder,
+ val options: DocumentationOptions,
+ val logger: DokkaLogger) : JavaDocumentationBuilder {
override fun appendFile(file: PsiJavaFile, module: DocumentationModule, packageContent: Map<String, Content>) {
val classDescriptors = file.classes.map {
val javaDescriptorResolver = resolutionFacade.getFrontendService(JavaDescriptorResolver::class.java)
@@ -731,8 +743,12 @@ fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor
return null
}
-fun DeclarationDescriptor.signature(): String = when(this) {
- is ClassDescriptor, is PackageFragmentDescriptor, is PackageViewDescriptor -> DescriptorUtils.getFqName(this).asString()
+fun DeclarationDescriptor.signature(): String = when (this) {
+ is ClassDescriptor,
+ is PackageFragmentDescriptor,
+ is PackageViewDescriptor,
+ is TypeAliasDescriptor -> DescriptorUtils.getFqName(this).asString()
+
is PropertyDescriptor -> containingDeclaration.signature() + "$" + name + receiverSignature()
is FunctionDescriptor -> containingDeclaration.signature() + "$" + name + parameterSignature()
is ValueParameterDescriptor -> containingDeclaration.signature() + "/" + name
diff --git a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
index a0d8f95d..6fcf3772 100644
--- a/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
+++ b/core/src/main/kotlin/Kotlin/KotlinLanguageService.kt
@@ -315,6 +315,7 @@ class KotlinLanguageService : LanguageService {
NodeKind.Interface -> keyword("interface ")
NodeKind.EnumItem -> keyword("enum val ")
NodeKind.Object -> keyword("object ")
+ NodeKind.TypeAlias -> keyword("typealias ")
else -> throw IllegalArgumentException("Node $node is not a class-like object")
}
@@ -322,6 +323,13 @@ class KotlinLanguageService : LanguageService {
renderTypeParametersForNode(node, renderMode)
renderSupertypesForNode(node, renderMode)
renderExtraTypeParameterConstraints(node, renderMode)
+
+ if (node.kind == NodeKind.TypeAlias) {
+ nbsp()
+ symbol("=")
+ nbsp()
+ renderType(node.detail(NodeKind.TypeAliasUnderlyingType), renderMode)
+ }
}
private fun ContentBlock.renderFunction(node: DocumentationNode,
diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt
index ecf75b20..c8585418 100644
--- a/core/src/main/kotlin/Model/Content.kt
+++ b/core/src/main/kotlin/Model/Content.kt
@@ -132,6 +132,8 @@ class ContentSection(val tag: String, val subjectName: String?) : ContentBlock()
object ContentTags {
val Description = "Description"
val SeeAlso = "See Also"
+ val Return = "Return"
+ val Exceptions = "Exceptions"
}
fun content(body: ContentBlock.() -> Unit): ContentBlock {
@@ -237,6 +239,6 @@ open class MutableContent() : Content() {
fun javadocSectionDisplayName(sectionName: String?): String? =
when(sectionName) {
"param" -> "Parameters"
- "throws", "exception" -> "Exceptions"
+ "throws", "exception" -> ContentTags.Exceptions
else -> sectionName?.capitalize()
}
diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt
index 9aacbca0..def0f626 100644
--- a/core/src/main/kotlin/Model/DocumentationNode.kt
+++ b/core/src/main/kotlin/Model/DocumentationNode.kt
@@ -13,6 +13,7 @@ enum class NodeKind {
Exception,
EnumItem,
Object,
+ TypeAlias,
Constructor,
Function,
@@ -30,6 +31,8 @@ enum class NodeKind {
UpperBound,
LowerBound,
+ TypeAliasUnderlyingType,
+
Modifier,
NullabilityModifier,
@@ -55,7 +58,7 @@ enum class NodeKind {
OverloadGroupNote;
companion object {
- val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object)
+ val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias)
}
}
diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt
index 20d74088..eafa216b 100644
--- a/core/src/main/kotlin/javadoc/docbase.kt
+++ b/core/src/main/kotlin/javadoc/docbase.kt
@@ -297,6 +297,10 @@ fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode
node
}
+private fun DocumentationNode.hasNonEmptyContent() =
+ this.content.summary !is ContentEmpty || this.content.description !is ContentEmpty || this.content.sections.isNotEmpty()
+
+
open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), ExecutableMemberDoc {
override fun isSynthetic(): Boolean = false
@@ -305,20 +309,16 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio
override fun thrownExceptions(): Array<out ClassDoc> = emptyArray() // TODO
override fun throwsTags(): Array<out ThrowsTag> =
node.content.sections
- .filter { it.tag == "Exceptions" }
- .map { it.subjectName }
- .filterNotNull()
- .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it, NodeKind.Exception))) }
+ .filter { it.tag == ContentTags.Exceptions && it.subjectName != null }
+ .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 isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" }
- override fun paramTags(): Array<out ParamTag> = node.details(NodeKind.Parameter)
- .filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }
- .map { ParamTagAdapter(module, this, it.name, false, it.content.children) }
- .toTypedArray()
+ override fun paramTags(): Array<out ParamTag> =
+ collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } })
override fun thrownExceptionTypes(): Array<out Type> = emptyArray()
override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) }
@@ -332,9 +332,8 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, node: Documentatio
override fun typeParameters(): Array<out TypeVariable> = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray()
- override fun typeParamTags(): Array<out ParamTag> = node.details(NodeKind.TypeParameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map {
- ParamTagAdapter(module, this, it.name, true, it.content.children)
- }.toTypedArray()
+ override fun typeParamTags(): Array<out ParamTag> =
+ collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers ->
when {
@@ -365,6 +364,17 @@ class MethodAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : Docume
override fun isDefault(): Boolean = false
override fun returnType(): Type = TypeAdapter(module, node.detail(NodeKind.Type))
+
+ override fun tags(tagname: String?) = super.tags(tagname)
+
+ override fun tags(): Array<out Tag> {
+ val tags = super.tags().toMutableList()
+ node.content.findSectionByTag(ContentTags.Return)?.let {
+ tags += ReturnTagAdapter(module, this, it.children)
+ }
+
+ return tags.toTypedArray()
+ }
}
class FieldAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), FieldDoc {
@@ -416,11 +426,8 @@ open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNod
.map { ClassDocumentationNodeAdapter(module, it) }
.toTypedArray()
- override fun typeParamTags(): Array<out ParamTag> = (classNode.details(NodeKind.TypeParameter).filter { it.content.summary !is ContentEmpty || it.content.description !is ContentEmpty || it.content.sections.isNotEmpty() }.map {
- ParamTagAdapter(module, this, it.name, true, it.content.children)
- } + classNode.content.sections.filter { it.subjectName in typeParameters().map { it.simpleTypeName() } }.map {
- ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children)
- }).toTypedArray()
+ override fun typeParamTags(): Array<out ParamTag> =
+ collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } })
override fun fields(): Array<out FieldDoc> = fields(true)
override fun fields(filter: Boolean): Array<out FieldDoc> = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray()
@@ -503,3 +510,14 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR
override fun specifiedClasses(): Array<out ClassDoc> = classes()
}
+
+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.content.sections
+ .filter(sectionFilter)
+ .map { ParamTagAdapter(module, this, it.subjectName ?: "?", true, it.children) })
+
+ .toTypedArray() \ No newline at end of file
diff --git a/core/src/main/kotlin/javadoc/tags.kt b/core/src/main/kotlin/javadoc/tags.kt
index aab5ecf1..9e023a81 100644
--- a/core/src/main/kotlin/javadoc/tags.kt
+++ b/core/src/main/kotlin/javadoc/tags.kt
@@ -104,8 +104,8 @@ class ParamTagAdapter(val module: ModuleNodeAdapter,
override fun holder(): Doc = holder
override fun position(): SourcePosition? = holder.position()
- override fun text(): String = "@param $parameterName ..."
- override fun inlineTags(): Array<out Tag> = content.flatMap { buildInlineTags(module, holder, it) }.toTypedArray()
+ override fun text(): String = "@param $parameterName ${parameterComment()}" // Seems has no effect, so used for debug
+ override fun inlineTags(): Array<out Tag> = buildInlineTags(module, holder, content).toTypedArray()
override fun firstSentenceTags(): Array<out Tag> = arrayOf(TextTag(holder, ContentText(text())))
override fun isTypeParameter(): Boolean = typeParameter
@@ -114,23 +114,36 @@ class ParamTagAdapter(val module: ModuleNodeAdapter,
}
-class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter) : ThrowsTag {
+class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter, val content: List<ContentNode>) : ThrowsTag {
override fun name(): String = "@throws"
override fun kind(): String = name()
override fun holder(): Doc = holder
override fun position(): SourcePosition? = holder.position()
- override fun text(): String = "@throws ${type.qualifiedTypeName()}"
- override fun inlineTags(): Array<out Tag> = emptyArray()
+ override fun text(): String = "${name()} ${exceptionName()} ${exceptionComment()}"
+ override fun inlineTags(): Array<out Tag> = buildInlineTags(type.module, holder, content).toTypedArray()
override fun firstSentenceTags(): Array<out Tag> = emptyArray()
- override fun exceptionComment(): String = ""
+ override fun exceptionComment(): String = content.toString()
override fun exceptionType(): Type = type
override fun exception(): ClassDoc = type
- override fun exceptionName(): String = type.qualifiedName()
+ override fun exceptionName(): String = type.qualifiedTypeName()
}
-fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List<Tag> = ArrayList<Tag>().let { buildInlineTags(module, holder, root, it); it }
+class ReturnTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val content: List<ContentNode>) : Tag {
+ override fun name(): String = "@return"
+ override fun kind() = name()
+ override fun holder() = holder
+ override fun position(): SourcePosition? = holder.position()
+
+ override fun text(): String = "@return $content" // Seems has no effect, so used for debug
+ override fun inlineTags(): Array<Tag> = buildInlineTags(module, holder, content).toTypedArray()
+ override fun firstSentenceTags(): Array<Tag> = inlineTags()
+}
+
+fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, tags: List<ContentNode>): List<Tag> = ArrayList<Tag>().apply { tags.forEach { buildInlineTags(module, holder, it, this) } }
+
+fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List<Tag> = ArrayList<Tag>().apply { buildInlineTags(module, holder, root, this) }
private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, nodes: List<ContentNode>, result: MutableList<Tag>) {
nodes.forEach {