diff options
Diffstat (limited to 'core/src/main')
| -rw-r--r-- | core/src/main/kotlin/Analysis/AnalysisEnvironment.kt | 58 | ||||
| -rw-r--r-- | core/src/main/kotlin/Formats/StructuredFormatService.kt | 25 | ||||
| -rw-r--r-- | core/src/main/kotlin/Kotlin/DocumentationBuilder.kt | 96 | ||||
| -rw-r--r-- | core/src/main/kotlin/Kotlin/KotlinLanguageService.kt | 8 | ||||
| -rw-r--r-- | core/src/main/kotlin/Model/Content.kt | 4 | ||||
| -rw-r--r-- | core/src/main/kotlin/Model/DocumentationNode.kt | 5 | ||||
| -rw-r--r-- | core/src/main/kotlin/javadoc/docbase.kt | 50 | ||||
| -rw-r--r-- | core/src/main/kotlin/javadoc/tags.kt | 29 |
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 { |
