From b536699655e40c62cd603e1f98869786566604bd Mon Sep 17 00:00:00 2001 From: Kamil Doległo Date: Tue, 10 Sep 2019 15:15:09 +0200 Subject: WIP on restructuring --- core/src/main/kotlin/javadoc/docbase.kt | 539 --------------------- core/src/main/kotlin/javadoc/dokka-adapters.kt | 42 -- core/src/main/kotlin/javadoc/reporter.kt | 34 -- core/src/main/kotlin/javadoc/source-position.kt | 19 - core/src/main/kotlin/javadoc/tags.kt | 228 --------- .../main/resources/dokka/format/javadoc.properties | 2 - 6 files changed, 864 deletions(-) delete mode 100644 core/src/main/kotlin/javadoc/docbase.kt delete mode 100644 core/src/main/kotlin/javadoc/dokka-adapters.kt delete mode 100644 core/src/main/kotlin/javadoc/reporter.kt delete mode 100644 core/src/main/kotlin/javadoc/source-position.kt delete mode 100644 core/src/main/kotlin/javadoc/tags.kt delete mode 100644 core/src/main/resources/dokka/format/javadoc.properties (limited to 'core/src/main') diff --git a/core/src/main/kotlin/javadoc/docbase.kt b/core/src/main/kotlin/javadoc/docbase.kt deleted file mode 100644 index 0bf72ccf..00000000 --- a/core/src/main/kotlin/javadoc/docbase.kt +++ /dev/null @@ -1,539 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.javadoc.* -import org.jetbrains.dokka.* -import java.lang.reflect.Modifier.* -import java.util.* -import kotlin.reflect.KClass - -private interface HasModule { - val module: ModuleNodeAdapter -} - -private interface HasDocumentationNode { - val node: DocumentationNode -} - -open class DocumentationNodeBareAdapter(override val node: DocumentationNode) : Doc, HasDocumentationNode { - private var rawCommentText_: String? = null - - override fun name(): String = node.name - override fun position(): SourcePosition? = SourcePositionAdapter(node) - - override fun inlineTags(): Array? = emptyArray() - override fun firstSentenceTags(): Array? = emptyArray() - override fun tags(): Array = emptyArray() - override fun tags(tagname: String?): Array? = tags().filter { it.kind() == tagname || it.kind() == "@$tagname" }.toTypedArray() - override fun seeTags(): Array? = tags().filterIsInstance().toTypedArray() - override fun commentText(): String = "" - - override fun setRawCommentText(rawDocumentation: String?) { - rawCommentText_ = rawDocumentation ?: "" - } - - override fun getRawCommentText(): String = rawCommentText_ ?: "" - - override fun isError(): Boolean = false - override fun isException(): Boolean = node.kind == NodeKind.Exception - override fun isEnumConstant(): Boolean = node.kind == NodeKind.EnumItem - override fun isEnum(): Boolean = node.kind == NodeKind.Enum - override fun isMethod(): Boolean = node.kind == NodeKind.Function - override fun isInterface(): Boolean = node.kind == NodeKind.Interface - override fun isField(): Boolean = node.kind == NodeKind.Field - override fun isClass(): Boolean = node.kind == NodeKind.Class - override fun isAnnotationType(): Boolean = node.kind == NodeKind.AnnotationClass - override fun isConstructor(): Boolean = node.kind == NodeKind.Constructor - override fun isOrdinaryClass(): Boolean = node.kind == NodeKind.Class - override fun isAnnotationTypeElement(): Boolean = node.kind == NodeKind.Annotation - - override fun compareTo(other: Any?): Int = when (other) { - !is DocumentationNodeAdapter -> 1 - else -> node.name.compareTo(other.node.name) - } - - override fun equals(other: Any?): Boolean = node.qualifiedName() == (other as? DocumentationNodeAdapter)?.node?.qualifiedName() - override fun hashCode(): Int = node.name.hashCode() - - override fun isIncluded(): Boolean = node.kind != NodeKind.ExternalClass -} - - -// TODO think of source position instead of null -// TODO tags -open class DocumentationNodeAdapter(override val module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeBareAdapter(node), HasModule { - override fun inlineTags(): Array = buildInlineTags(module, this, node.content).toTypedArray() - override fun firstSentenceTags(): Array = buildInlineTags(module, this, node.summary).toTypedArray() - - override fun tags(): Array { - val result = ArrayList(buildInlineTags(module, this, node.content)) - node.content.sections.flatMapTo(result) { - when (it.tag) { - ContentTags.SeeAlso -> buildInlineTags(module, this, it) - else -> emptyList() - } - } - - node.deprecation?.let { - val content = it.content.asText() - result.add(TagImpl(this, "deprecated", content ?: "")) - } - - return result.toTypedArray() - } -} - -// should be extension property but can't because of KT-8745 -private fun nodeAnnotations(self: T): List where T : HasModule, T : HasDocumentationNode - = self.node.annotations.map { AnnotationDescAdapter(self.module, it) } - -private fun DocumentationNode.hasAnnotation(klass: KClass<*>) = klass.qualifiedName in annotations.map { it.qualifiedName() } -private fun DocumentationNode.hasModifier(name: String) = details(NodeKind.Modifier).any { it.name == name } - - -class PackageAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc { - private val allClasses = listOf(node).collectAllTypesRecursively() - - override fun findClass(className: String?): ClassDoc? = - allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) } - - override fun annotationTypes(): Array = emptyArray() - override fun annotations(): Array = node.members(NodeKind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray() - override fun exceptions(): Array = node.members(NodeKind.Exception).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() - override fun ordinaryClasses(): Array = node.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() - override fun interfaces(): Array = node.members(NodeKind.Interface).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() - override fun errors(): Array = emptyArray() - override fun enums(): Array = node.members(NodeKind.Enum).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() - override fun allClasses(filter: Boolean): Array = allClasses.values.map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() - override fun allClasses(): Array = allClasses(true) - - override fun isIncluded(): Boolean = node.name in module.allPackages -} - -class AnnotationTypeDocAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ClassDocumentationNodeAdapter(module, node), AnnotationTypeDoc { - override fun elements(): Array? = emptyArray() // TODO -} - -class AnnotationDescAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : AnnotationDesc { - 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 -} - -open class ProgramElementAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc { - 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 = 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 = node.hasModifier("protected") - - override fun isFinal(): Boolean = node.hasModifier("final") - - override fun containingPackage(): PackageDoc? { - if (node.kind == NodeKind.Type) { - return null - } - - var owner: DocumentationNode? = node - while (owner != null) { - if (owner.kind == NodeKind.Package) { - return PackageAdapter(module, owner) - } - owner = owner.owner - } - - return null - } - - override fun containingClass(): ClassDoc? { - if (node.kind == NodeKind.Type) { - return null - } - - var owner = node.owner - while (owner != null) { - if (owner.kind in NodeKind.classLike) { - return ClassDocumentationNodeAdapter(module, owner) - } - owner = owner.owner - } - - return null - } - - override fun isPrivate(): Boolean = node.hasModifier("private") - override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true -} - -open class TypeAdapter(override val module: ModuleNodeAdapter, override val node: DocumentationNode) : Type, HasDocumentationNode, HasModule { - private val javaLanguageService = JavaLanguageService() - - override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedNameFromType() ?: node.qualifiedNameFromType() - 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("") - override fun isPrimitive(): Boolean = simpleTypeName() in setOf("int", "long", "short", "byte", "char", "double", "float", "boolean", "void") - - override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else - elementType?.asClassDoc() ?: - when (node.kind) { - in NodeKind.classLike, - NodeKind.ExternalClass, - NodeKind.Exception -> module.classNamed(qualifiedTypeName()) ?: ClassDocumentationNodeAdapter(module, node) - - else -> when { - node.links.isNotEmpty() -> TypeAdapter(module, node.links.first()).asClassDoc() - else -> ClassDocumentationNodeAdapter(module, node) // TODO ? - } - } - - override fun asTypeVariable(): TypeVariable? = if (node.kind == NodeKind.TypeParameter) TypeVariableAdapter(module, node) else null - override fun asParameterizedType(): ParameterizedType? = - if (node.details(NodeKind.Type).isNotEmpty() && javaLanguageService.getArrayElementType(node) == null) - ParameterizedTypeAdapter(module, node) - else - null - - override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == NodeKind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null - override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null - override fun getElementType(): Type? = javaLanguageService.getArrayElementType(node)?.let { et -> TypeAdapter(module, et) } - override fun asWildcardType(): WildcardType? = null - - override fun toString(): String = qualifiedTypeName() + dimension() - override fun hashCode(): Int = node.name.hashCode() - override fun equals(other: Any?): Boolean = other is TypeAdapter && toString() == other.toString() -} - -class NotAnnotatedTypeAdapter(typeAdapter: AnnotatedTypeAdapter) : Type by typeAdapter { - override fun asAnnotatedType() = null -} - -class AnnotatedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), AnnotatedType { - override fun underlyingType(): Type? = NotAnnotatedTypeAdapter(this) - override fun annotations(): Array = nodeAnnotations(this).toTypedArray() -} - -class WildcardTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), WildcardType { - override fun extendsBounds(): Array = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray() - override fun superBounds(): Array = node.details(NodeKind.LowerBound).map { TypeAdapter(module, it) }.toTypedArray() -} - -class TypeVariableAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), TypeVariable { - override fun owner(): ProgramElementDoc = node.owner!!.let { owner -> - when (owner.kind) { - NodeKind.Function, - NodeKind.Constructor -> ExecutableMemberAdapter(module, owner) - - NodeKind.Class, - NodeKind.Interface, - NodeKind.Enum -> ClassDocumentationNodeAdapter(module, owner) - - else -> ProgramElementAdapter(module, node.owner!!) - } - } - - override fun bounds(): Array? = node.details(NodeKind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray() - override fun annotations(): Array? = node.members(NodeKind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray() - - override fun qualifiedTypeName(): String = node.name - override fun simpleTypeName(): String = node.name - override fun typeName(): String = node.name - - override fun hashCode(): Int = node.name.hashCode() - override fun equals(other: Any?): Boolean = other is Type && other.typeName() == typeName() && other.asTypeVariable()?.owner() == owner() - - override fun asTypeVariable(): TypeVariableAdapter = this -} - -class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType { - override fun typeArguments(): Array = node.details(NodeKind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray() - override fun superclassType(): Type? = - node.lookupSuperClasses(module) - .firstOrNull { it.kind == NodeKind.Class || it.kind == NodeKind.ExternalClass } - ?.let { ClassDocumentationNodeAdapter(module, it) } - - override fun interfaceTypes(): Array = - node.lookupSuperClasses(module) - .filter { it.kind == NodeKind.Interface } - .map { ClassDocumentationNodeAdapter(module, it) } - .toTypedArray() - - override fun containingType(): Type? = when (node.owner?.kind) { - NodeKind.Package -> null - NodeKind.Class, - NodeKind.Interface, - NodeKind.Object, - NodeKind.Enum -> ClassDocumentationNodeAdapter(module, node.owner!!) - - else -> null - } -} - -class ParameterAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter { - override fun typeName(): String? = type()?.typeName() - override fun type(): Type? = TypeAdapter(module, node.detail(NodeKind.Type)) - override fun annotations(): Array = nodeAnnotations(this).toTypedArray() -} - -class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode, val parent: ExecutableMemberAdapter) : DocumentationNodeAdapter(module, receiverType), Parameter { - override fun typeName(): String? = receiverType.name - override fun type(): Type? = TypeAdapter(module, receiverType) - override fun annotations(): Array = nodeAnnotations(this).toTypedArray() - override fun name(): String = tryName("receiver") - - private tailrec fun tryName(name: String): String = when (name) { - in parent.parameters().drop(1).map { it.name() } -> tryName("$$name") - else -> name - } -} - -fun classOf(fqName: String, kind: NodeKind = NodeKind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node -> - val pkg = fqName.substringBeforeLast(".", "") - if (pkg.isNotEmpty()) { - node.append(DocumentationNode(pkg, Content.Empty, NodeKind.Package), RefKind.Owner) - } - - 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) : ProgramElementAdapter(module, node), ExecutableMemberDoc { - - override fun isSynthetic(): Boolean = false - override fun isNative(): Boolean = node.annotations.any { it.name == "native" } - - override fun thrownExceptions(): Array = emptyArray() // TODO - override fun throwsTags(): Array = - node.content.sections - .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).last().hasModifier("vararg") - - override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" } - - override fun paramTags(): Array = - collectParamTags(NodeKind.Parameter, sectionFilter = { it.subjectName in parameters().map { it.name() } }) - - override fun thrownExceptionTypes(): Array = emptyArray() - override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) } - override fun flatSignature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") - override fun signature(): String = node.details(NodeKind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types - - override fun parameters(): Array = - ((receiverNode()?.let { receiver -> listOf(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList()) - + node.details(NodeKind.Parameter).map { ParameterAdapter(module, it) } - ).toTypedArray() - - override fun typeParameters(): Array = node.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray() - - override fun typeParamTags(): Array = - collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } }) - - private fun receiverNode() = node.details(NodeKind.Receiver).let { receivers -> - when { - receivers.isNotEmpty() -> receivers.single().detail(NodeKind.Type) - else -> null - } - } -} - -class ConstructorAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), ConstructorDoc { - override fun name(): String = node.owner?.name ?: throw IllegalStateException("No owner for $node") - - override fun containingClass(): ClassDoc? { - return super.containingClass() - } -} - -class MethodAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : ExecutableMemberAdapter(module, node), MethodDoc { - override fun overrides(meth: MethodDoc?): Boolean = false // TODO - - override fun overriddenType(): Type? = node.overrides.firstOrNull()?.owner?.let { owner -> TypeAdapter(module, owner) } - - override fun overriddenMethod(): MethodDoc? = node.overrides.map { MethodAdapter(module, it) }.firstOrNull() - override fun overriddenClass(): ClassDoc? = overriddenMethod()?.containingClass() - - override fun isAbstract(): Boolean = false // TODO - - 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 { - 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) : ProgramElementAdapter(module, node), FieldDoc { - override fun isSynthetic(): Boolean = false - - override fun constantValueExpression(): String? = node.detailOrNull(NodeKind.Value)?.let { it.name } - override fun constantValue(): Any? = constantValueExpression() - - override fun type(): Type = TypeAdapter(module, node.detail(NodeKind.Type)) - override fun isTransient(): Boolean = node.hasAnnotation(Transient::class) - override fun serialFieldTags(): Array = emptyArray() - - override fun isVolatile(): Boolean = node.hasAnnotation(Volatile::class) -} -open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode) - : ProgramElementAdapter(module, classNode), - Type by TypeAdapter(module, classNode), - ClassDoc, - AnnotationTypeDoc { - - override fun elements(): Array? = emptyArray() // TODO - - override fun name(): String { - val parent = classNode.owner - if (parent?.kind in NodeKind.classLike) { - return parent!!.name + "." + classNode.name - } - 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() - override fun importedClasses(): Array? = emptyArray() - override fun typeParameters(): Array = classNode.details(NodeKind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray() - override fun asTypeVariable(): TypeVariable? = if (classNode.kind == NodeKind.Class) TypeVariableAdapter(module, classNode) else null - override fun isExternalizable(): Boolean = interfaces().any { it.qualifiedName() == "java.io.Externalizable" } - override fun definesSerializableFields(): Boolean = false - override fun methods(filter: Boolean): Array = classNode.members(NodeKind.Function).map { MethodAdapter(module, it) }.toTypedArray() // TODO include get/set methods - override fun methods(): Array = methods(true) - override fun enumConstants(): Array? = classNode.members(NodeKind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray() - override fun isAbstract(): Boolean = classNode.details(NodeKind.Modifier).any { it.name == "abstract" } - override fun interfaceTypes(): Array = classNode.lookupSuperClasses(module) - .filter { it.kind == NodeKind.Interface } - .map { ClassDocumentationNodeAdapter(module, it) } - .toTypedArray() - - override fun interfaces(): Array = classNode.lookupSuperClasses(module) - .filter { it.kind == NodeKind.Interface } - .map { ClassDocumentationNodeAdapter(module, it) } - .toTypedArray() - - override fun typeParamTags(): Array = - collectParamTags(NodeKind.TypeParameter, sectionFilter = { it.subjectName in typeParameters().map { it.simpleTypeName() } }) - - override fun fields(): Array = fields(true) - override fun fields(filter: Boolean): Array = classNode.members(NodeKind.Field).map { FieldAdapter(module, it) }.toTypedArray() - - override fun findClass(className: String?): ClassDoc? = null // TODO !!! - override fun serializableFields(): Array = emptyArray() - override fun superclassType(): Type? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) } - override fun serializationMethods(): Array = emptyArray() // TODO - override fun superclass(): ClassDoc? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == NodeKind.Class }?.let { ClassDocumentationNodeAdapter(module, it) } - override fun isSerializable(): Boolean = false // TODO - override fun subclassOf(cd: ClassDoc?): Boolean { - if (cd == null) { - return false - } - - val expectedFQName = cd.qualifiedName() - val types = arrayListOf(classNode) - val visitedTypes = HashSet() - - while (types.isNotEmpty()) { - val type = types.removeAt(types.lastIndex) - val fqName = type.qualifiedName() - - if (expectedFQName == fqName) { - return true - } - - visitedTypes.add(fqName) - types.addAll(type.details(NodeKind.Supertype).filter { it.qualifiedName() !in visitedTypes }) - } - - return false - } - - override fun innerClasses(): Array = classNode.members(NodeKind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() - override fun innerClasses(filter: Boolean): Array = innerClasses() -} - -fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) = - details(NodeKind.Supertype) - .map { it.links.firstOrNull() }.mapNotNull { module.allTypes[it?.qualifiedName()] } - -fun List.collectAllTypesRecursively(): Map { - val result = hashMapOf() - - fun DocumentationNode.collectTypesRecursively() { - val classLikeMembers = NodeKind.classLike.flatMap { members(it) } - classLikeMembers.forEach { - result.put(it.qualifiedName(), it) - it.collectTypesRecursively() - } - } - - forEach { it.collectTypesRecursively() } - return result -} - -class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { - val allPackages = module.members(NodeKind.Package).associateBy { it.name } - val allTypes = module.members(NodeKind.Package).collectAllTypesRecursively() - - override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) } - - override fun classes(): Array = - allTypes.values.map { ClassDocumentationNodeAdapter(this, it) }.toTypedArray() - - override fun options(): Array> = arrayOf( - arrayOf("-d", outputPath), - arrayOf("-docencoding", "UTF-8"), - arrayOf("-charset", "UTF-8"), - arrayOf("-keywords") - ) - - override fun specifiedPackages(): Array? = module.members(NodeKind.Package).map { PackageAdapter(this, it) }.toTypedArray() - - override fun classNamed(qualifiedName: String?): ClassDoc? = - allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) } - - override fun specifiedClasses(): Array = 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.filterNot { contentNode -> contentNode is LazyContentBlock } - ) - } - ) - .distinctBy { it.parameterName } - .toTypedArray() \ No newline at end of file diff --git a/core/src/main/kotlin/javadoc/dokka-adapters.kt b/core/src/main/kotlin/javadoc/dokka-adapters.kt deleted file mode 100644 index 1329876a..00000000 --- a/core/src/main/kotlin/javadoc/dokka-adapters.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.google.inject.Binder -import com.google.inject.Inject -import com.sun.tools.doclets.formats.html.HtmlDoclet -import org.jetbrains.dokka.* -import org.jetbrains.dokka.Formats.DefaultAnalysisComponent -import org.jetbrains.dokka.Formats.DefaultAnalysisComponentServices -import org.jetbrains.dokka.Formats.FormatDescriptor -import org.jetbrains.dokka.Formats.KotlinAsJava -import org.jetbrains.dokka.Utilities.bind -import org.jetbrains.dokka.Utilities.toType - -class JavadocGenerator @Inject constructor(val configuration: DokkaConfiguration, val logger: DokkaLogger) : Generator { - - override fun buildPages(nodes: Iterable) { - val module = nodes.single() as DocumentationModule - - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(logger), configuration.outputDir)) - } - - override fun buildOutlines(nodes: Iterable) { - // no outline could be generated separately - } - - override fun buildSupportFiles() { - } - - override fun buildPackageList(nodes: Iterable) { - // handled by javadoc itself - } -} - -class JavadocFormatDescriptor : - FormatDescriptor, - DefaultAnalysisComponent, - DefaultAnalysisComponentServices by KotlinAsJava { - - override fun configureOutput(binder: Binder): Unit = with(binder) { - bind() toType JavadocGenerator::class - } -} diff --git a/core/src/main/kotlin/javadoc/reporter.kt b/core/src/main/kotlin/javadoc/reporter.kt deleted file mode 100644 index fc38368c..00000000 --- a/core/src/main/kotlin/javadoc/reporter.kt +++ /dev/null @@ -1,34 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.javadoc.DocErrorReporter -import com.sun.javadoc.SourcePosition -import org.jetbrains.dokka.DokkaLogger - -class StandardReporter(val logger: DokkaLogger) : DocErrorReporter { - override fun printWarning(msg: String?) { - logger.warn(msg.toString()) - } - - override fun printWarning(pos: SourcePosition?, msg: String?) { - logger.warn(format(pos, msg)) - } - - override fun printError(msg: String?) { - logger.error(msg.toString()) - } - - override fun printError(pos: SourcePosition?, msg: String?) { - logger.error(format(pos, msg)) - } - - override fun printNotice(msg: String?) { - logger.info(msg.toString()) - } - - override fun printNotice(pos: SourcePosition?, msg: String?) { - logger.info(format(pos, msg)) - } - - private fun format(pos: SourcePosition?, msg: String?) = - if (pos == null) msg.toString() else "${pos.file()}:${pos.line()}:${pos.column()}: $msg" -} \ No newline at end of file diff --git a/core/src/main/kotlin/javadoc/source-position.kt b/core/src/main/kotlin/javadoc/source-position.kt deleted file mode 100644 index 6125f968..00000000 --- a/core/src/main/kotlin/javadoc/source-position.kt +++ /dev/null @@ -1,19 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.javadoc.SourcePosition -import org.jetbrains.dokka.DocumentationNode -import org.jetbrains.dokka.NodeKind -import java.io.File - -class SourcePositionAdapter(val docNode: DocumentationNode) : SourcePosition { - - private val sourcePositionParts: List by lazy { - docNode.details(NodeKind.SourcePosition).firstOrNull()?.name?.split(":") ?: emptyList() - } - - override fun file(): File? = if (sourcePositionParts.isEmpty()) null else File(sourcePositionParts[0]) - - override fun line(): Int = sourcePositionParts.getOrNull(1)?.toInt() ?: -1 - - override fun column(): Int = sourcePositionParts.getOrNull(2)?.toInt() ?: -1 -} diff --git a/core/src/main/kotlin/javadoc/tags.kt b/core/src/main/kotlin/javadoc/tags.kt deleted file mode 100644 index 99c9bfff..00000000 --- a/core/src/main/kotlin/javadoc/tags.kt +++ /dev/null @@ -1,228 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.javadoc.* -import org.jetbrains.dokka.* -import java.util.* - -class TagImpl(val holder: Doc, val name: String, val text: String): Tag { - override fun text(): String? = text - - override fun holder(): Doc = holder - override fun firstSentenceTags(): Array? = arrayOf() - override fun inlineTags(): Array? = arrayOf() - - override fun name(): String = name - override fun kind(): String = name - - override fun position(): SourcePosition = holder.position() -} - -class TextTag(val holder: Doc, val content: ContentText) : Tag { - val plainText: String - get() = content.text - - override fun name(): String = "Text" - override fun kind(): String = name() - override fun text(): String? = plainText - override fun inlineTags(): Array = arrayOf(this) - override fun holder(): Doc = holder - override fun firstSentenceTags(): Array = arrayOf(this) - override fun position(): SourcePosition = holder.position() -} - -abstract class SeeTagAdapter(val holder: Doc, val content: ContentNodeLink) : SeeTag { - override fun position(): SourcePosition? = holder.position() - override fun name(): String = "@see" - override fun kind(): String = "@see" - override fun holder(): Doc = holder - - override fun text(): String? = content.node?.name ?: "(?)" -} - -class SeeExternalLinkTagAdapter(val holder: Doc, val link: ContentExternalLink) : SeeTag { - override fun position(): SourcePosition = holder.position() - override fun text(): String = label() - override fun inlineTags(): Array = emptyArray() // TODO - - override fun label(): String { - val label = link.asText() ?: link.href - return "$label" - } - - override fun referencedPackage(): PackageDoc? = null - override fun referencedClass(): ClassDoc? = null - override fun referencedMemberName(): String? = null - override fun referencedClassName(): String? = null - override fun referencedMember(): MemberDoc? = null - override fun holder(): Doc = holder - override fun firstSentenceTags(): Array = inlineTags() - override fun name(): String = "@link" - override fun kind(): String = "@see" -} - -fun ContentBlock.asText(): String? { - val contentText = children.singleOrNull() as? ContentText - return contentText?.text -} - -class SeeMethodTagAdapter(holder: Doc, val method: MethodAdapter, content: ContentNodeLink) : SeeTagAdapter(holder, content) { - override fun referencedMember(): MemberDoc = method - override fun referencedMemberName(): String = method.name() - override fun referencedPackage(): PackageDoc? = null - override fun referencedClass(): ClassDoc? = method.containingClass() - override fun referencedClassName(): String = method.containingClass()?.name() ?: "" - override fun label(): String = content.text ?: "${method.containingClass()?.name()}.${method.name()}" - - override fun inlineTags(): Array = emptyArray() // TODO - override fun firstSentenceTags(): Array = inlineTags() // TODO -} - -class SeeClassTagAdapter(holder: Doc, val clazz: ClassDocumentationNodeAdapter, content: ContentNodeLink) : SeeTagAdapter(holder, content) { - override fun referencedMember(): MemberDoc? = null - override fun referencedMemberName(): String? = null - override fun referencedPackage(): PackageDoc? = null - override fun referencedClass(): ClassDoc = clazz - override fun referencedClassName(): String = clazz.name() - override fun label(): String = "${clazz.classNode.kind.name.toLowerCase()} ${clazz.name()}" - - override fun inlineTags(): Array = emptyArray() // TODO - override fun firstSentenceTags(): Array = inlineTags() // TODO -} - -class ParamTagAdapter(val module: ModuleNodeAdapter, - val holder: Doc, - val parameterName: String, - val typeParameter: Boolean, - val content: List) : ParamTag { - - constructor(module: ModuleNodeAdapter, holder: Doc, parameterName: String, isTypeParameter: Boolean, content: ContentNode) - : this(module, holder, parameterName, isTypeParameter, listOf(content)) { - } - - override fun name(): String = "@param" - override fun kind(): String = name() - override fun holder(): Doc = holder - override fun position(): SourcePosition? = holder.position() - - override fun text(): String = "@param $parameterName ${parameterComment()}" // Seems has no effect, so used for debug - override fun inlineTags(): Array = buildInlineTags(module, holder, content).toTypedArray() - override fun firstSentenceTags(): Array = arrayOf(TextTag(holder, ContentText(text()))) - - override fun isTypeParameter(): Boolean = typeParameter - override fun parameterComment(): String = content.toString() // TODO - override fun parameterName(): String = parameterName -} - - -class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter, val content: List) : 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 = "${name()} ${exceptionName()} ${exceptionComment()}" - override fun inlineTags(): Array = buildInlineTags(type.module, holder, content).toTypedArray() - override fun firstSentenceTags(): Array = emptyArray() - - override fun exceptionComment(): String = content.toString() - override fun exceptionType(): Type = type - override fun exception(): ClassDoc = type - override fun exceptionName(): String = type.qualifiedTypeName() -} - -class ReturnTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val content: List) : 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 = buildInlineTags(module, holder, content).toTypedArray() - override fun firstSentenceTags(): Array = inlineTags() -} - -fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, tags: List): List = ArrayList().apply { tags.forEach { buildInlineTags(module, holder, it, this) } } - -fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List = ArrayList().apply { buildInlineTags(module, holder, root, this) } - -private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, nodes: List, result: MutableList) { - nodes.forEach { - buildInlineTags(module, holder, it, result) - } -} - - -private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, node: ContentNode, result: MutableList) { - fun surroundWith(module: ModuleNodeAdapter, holder: Doc, prefix: String, postfix: String, node: ContentBlock, result: MutableList) { - if (node.children.isNotEmpty()) { - val open = TextTag(holder, ContentText(prefix)) - val close = TextTag(holder, ContentText(postfix)) - - result.add(open) - buildInlineTags(module, holder, node.children, result) - - if (result.last() === open) { - result.removeAt(result.lastIndex) - } else { - result.add(close) - } - } - } - - fun surroundWith(module: ModuleNodeAdapter, holder: Doc, prefix: String, postfix: String, node: ContentNode, result: MutableList) { - if (node !is ContentEmpty) { - val open = TextTag(holder, ContentText(prefix)) - val close = TextTag(holder, ContentText(postfix)) - - result.add(open) - buildInlineTags(module, holder, node, result) - if (result.last() === open) { - result.removeAt(result.lastIndex) - } else { - result.add(close) - } - } - } - - when (node) { - is ContentText -> result.add(TextTag(holder, node)) - is ContentNodeLink -> { - val target = node.node - when (target?.kind) { - NodeKind.Function -> result.add(SeeMethodTagAdapter(holder, MethodAdapter(module, node.node!!), node)) - - in NodeKind.classLike -> result.add(SeeClassTagAdapter(holder, ClassDocumentationNodeAdapter(module, node.node!!), node)) - - else -> buildInlineTags(module, holder, node.children, result) - } - } - is ContentExternalLink -> result.add(SeeExternalLinkTagAdapter(holder, node)) - is ContentCode -> surroundWith(module, holder, "", "", node, result) - is ContentBlockCode -> surroundWith(module, holder, "
", "
", node, result) - is ContentEmpty -> {} - is ContentEmphasis -> surroundWith(module, holder, "", "", node, result) - is ContentHeading -> surroundWith(module, holder, "", "", node, result) - is ContentEntity -> result.add(TextTag(holder, ContentText(node.text))) // TODO ?? - is ContentIdentifier -> result.add(TextTag(holder, ContentText(node.text))) // TODO - is ContentKeyword -> result.add(TextTag(holder, ContentText(node.text))) // TODO - is ContentListItem -> surroundWith(module, holder, "
  • ", "
  • ", node, result) - is ContentOrderedList -> surroundWith(module, holder, "
      ", "
    ", node, result) - is ContentUnorderedList -> surroundWith(module, holder, "
      ", "
    ", node, result) - is ContentParagraph -> surroundWith(module, holder, "

    ", "

    ", node, result) - is ContentSection -> surroundWith(module, holder, "

    ", "

    ", node, result) // TODO how section should be represented? - is ContentNonBreakingSpace -> result.add(TextTag(holder, ContentText(" "))) - is ContentStrikethrough -> surroundWith(module, holder, "", "", node, result) - is ContentStrong -> surroundWith(module, holder, "", "", node, result) - is ContentSymbol -> result.add(TextTag(holder, ContentText(node.text))) // TODO? - is Content -> { - surroundWith(module, holder, "

    ", "

    ", node.summary, result) - surroundWith(module, holder, "

    ", "

    ", node.description, result) - } - is ContentBlock -> { - surroundWith(module, holder, "", "", node, result) - } - is ContentHardLineBreak -> result.add(TextTag(holder, ContentText("
    "))) - - else -> result.add(TextTag(holder, ContentText("$node"))) - } -} \ No newline at end of file diff --git a/core/src/main/resources/dokka/format/javadoc.properties b/core/src/main/resources/dokka/format/javadoc.properties deleted file mode 100644 index a0d8a945..00000000 --- a/core/src/main/resources/dokka/format/javadoc.properties +++ /dev/null @@ -1,2 +0,0 @@ -class=org.jetbrains.dokka.javadoc.JavadocFormatDescriptor -description=Produces Javadoc, with Kotlin declarations as Java view \ No newline at end of file -- cgit From 8de3af68d4415418cfe2ff548f9653d33210b44d Mon Sep 17 00:00:00 2001 From: Kamil Doległo Date: Thu, 3 Oct 2019 13:19:45 +0200 Subject: Partial fix for email links in markdown #179 --- core/src/main/kotlin/Kotlin/ContentBuilder.kt | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'core/src/main') diff --git a/core/src/main/kotlin/Kotlin/ContentBuilder.kt b/core/src/main/kotlin/Kotlin/ContentBuilder.kt index 573b41b6..0e60ff26 100644 --- a/core/src/main/kotlin/Kotlin/ContentBuilder.kt +++ b/core/src/main/kotlin/Kotlin/ContentBuilder.kt @@ -161,6 +161,10 @@ fun buildContentTo(tree: MarkdownNode, target: ContentBlock, linkResolver: LinkR MarkdownElementTypes.LINK_DEFINITION -> { } + MarkdownTokenTypes.EMAIL_AUTOLINK -> { + parent.append(ContentText(node.text)) // TODO: create new ContentType for email to create mailto: links + } + else -> { processChildren() } -- cgit From eec585065fa1865bd8cee188b94634f1c9a90c95 Mon Sep 17 00:00:00 2001 From: Błażej Kardyś Date: Tue, 29 Oct 2019 11:28:42 +0100 Subject: New dokka model --- core/src/main/kotlin/Model/Content.kt | 2 +- core/src/main/kotlin/Model/DocumentationNode.kt | 314 ++++++++++++--------- .../main/kotlin/Model/DocumentationReference.kt | 13 +- core/src/main/kotlin/Model/SourceLinks.kt | 64 ----- 4 files changed, 186 insertions(+), 207 deletions(-) (limited to 'core/src/main') diff --git a/core/src/main/kotlin/Model/Content.kt b/core/src/main/kotlin/Model/Content.kt index 5530e1b4..3881ee20 100644 --- a/core/src/main/kotlin/Model/Content.kt +++ b/core/src/main/kotlin/Model/Content.kt @@ -209,7 +209,7 @@ fun ContentBlock.code(body: ContentBlock.() -> Unit) { } fun ContentBlock.link(to: DocumentationNode, body: ContentBlock.() -> Unit) { - val block = if (to.kind == NodeKind.ExternalLink) + val block = if (to is DocumentationNodes.ExternalLink) ContentExternalLink(to.name) else ContentNodeDirectLink(to) diff --git a/core/src/main/kotlin/Model/DocumentationNode.kt b/core/src/main/kotlin/Model/DocumentationNode.kt index 311b46e4..66ee33e1 100644 --- a/core/src/main/kotlin/Model/DocumentationNode.kt +++ b/core/src/main/kotlin/Model/DocumentationNode.kt @@ -1,89 +1,160 @@ package org.jetbrains.dokka +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import java.util.* +import kotlin.reflect.KClass +import kotlin.reflect.full.primaryConstructor -enum class NodeKind { - Unknown, +class DocumentationNodes { - Package, - Class, - Interface, - Enum, - AnnotationClass, - Exception, - EnumItem, - Object, - TypeAlias, + class Unknown(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) - Constructor, - Function, - Property, - Field, + class Package(name: String) : + DocumentationNode(name) - CompanionObjectProperty, - CompanionObjectFunction, + class Class(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val classLike: Boolean = true + } - Parameter, - Receiver, - TypeParameter, - Type, - Supertype, - UpperBound, - LowerBound, + class Interface(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val classLike: Boolean = true + override val superclassType: DocumentationNode? = null + } - TypeAliasUnderlyingType, + class Enum(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val classLike: Boolean = true + } - Modifier, - NullabilityModifier, + class AnnotationClass(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val classLike: Boolean = true + } - Module, + class Exception(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val classLike: Boolean = true + } - ExternalClass, - Annotation, + class EnumItem(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true + } - Value, + class Object(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val classLike: Boolean = true + } - SourceUrl, - SourcePosition, - Signature, + class TypeAlias(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) - ExternalLink, - QualifiedName, - Platform, + class Constructor(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true + } - AllTypes, + class Function(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true + } - /** - * A note which is rendered once on a page documenting a group of overloaded functions. - * Needs to be generated equally on all overloads. - */ - OverloadGroupNote, + class Property(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true + } - GroupNode; + class Field(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true + } - companion object { - val classLike = setOf(Class, Interface, Enum, AnnotationClass, Exception, Object, TypeAlias) - val memberLike = setOf(Function, Property, Field, Constructor, CompanionObjectFunction, CompanionObjectProperty, EnumItem) + class CompanionObjectProperty(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true } -} -open class DocumentationNode(val name: String, - content: Content, - val kind: NodeKind) { + class CompanionObjectFunction(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val memberLike = true + } - private val references = LinkedHashSet() + class Parameter(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) - var content: Content = content - private set + class Receiver(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) - val summary: ContentNode get() = when (kind) { - NodeKind.GroupNode -> this.origins - .map { it.content } - .firstOrNull { !it.isEmpty() } - ?.summary ?: ContentEmpty - else -> content.summary + class TypeParameter(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class Type(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class Supertype(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) { + override val superclassType: DocumentationNode? = + (links + listOfNotNull(externalType)).firstOrNull { it.classLike }?.superclassType } + class UpperBound(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class LowerBound(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class TypeAliasUnderlyingType(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class NullabilityModifier(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class Module(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class ExternalClass(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class Annotation(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class Value(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class SourceUrl(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class SourcePosition(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class ExternalLink(name: String) : DocumentationNode(name) + + class QualifiedName(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class Platform(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class AllTypes(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) + + class OverloadGroupNote(name: String, descriptor: DeclarationDescriptor?) : + DocumentationNode(name, descriptor) +} + +abstract class DocumentationNode( + var name: String, + val descriptor: DeclarationDescriptor? = null +) { + + private val references = LinkedHashSet() + + open val classLike = false + + open val memberLike = false val owner: DocumentationNode? get() = references(RefKind.Owner).singleOrNull()?.to @@ -119,29 +190,12 @@ open class DocumentationNode(val name: String, val externalType: DocumentationNode? get() = references(RefKind.ExternalType).map { it.to }.firstOrNull() - var sinceKotlin: String? - get() = references(RefKind.SinceKotlin).singleOrNull()?.to?.name - set(value) { - dropReferences { it.kind == RefKind.SinceKotlin } - if (value != null) { - append(DocumentationNode(value, Content.Empty, NodeKind.Value), RefKind.SinceKotlin) - } - } - - val supertypes: List - get() = details(NodeKind.Supertype) - - val superclassType: DocumentationNode? - get() = when (kind) { - NodeKind.Supertype -> { - (links + listOfNotNull(externalType)).firstOrNull { it.kind in NodeKind.classLike }?.superclassType - } - NodeKind.Interface -> null - in NodeKind.classLike -> supertypes.firstOrNull { + open val superclassType: DocumentationNode? + get() = if (classLike) { + supertypes.firstOrNull { (it.links + listOfNotNull(it.externalType)).any { it.isSuperclassFor(this) } } - else -> null - } + } else null val superclassTypeSequence: Sequence get() = generateSequence(superclassType) { @@ -165,36 +219,46 @@ open class DocumentationNode(val name: String, references.addAll(other.references) } - fun updateContent(body: MutableContent.() -> Unit) { - if (content !is MutableContent) { - content = MutableContent() - } - (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 } - fun inheritedCompanionObjectMembers(kind: NodeKind): List = inheritedCompanionObjectMembers.filter { it.kind == kind } - fun links(kind: NodeKind): List = links.filter { it.kind == kind } + private fun Collection.filterByKind(kind: KClass) = + filter { node: DocumentationNode -> node::class == kind } + + private fun Collection.singleByKind(kind: KClass) = + single { node: DocumentationNode -> node::class == kind } + + fun details(kind: KClass) = details.filterByKind(kind) + fun members(kind: KClass) = members.filterByKind(kind) + fun inheritedMembers(kind: KClass): List = + inheritedMembers.filterByKind(kind) + + fun inheritedCompanionObjectMembers(kind: KClass): List = + inheritedCompanionObjectMembers.filterByKind(kind) + + fun links(kind: KClass): List = links.filterByKind(kind) + + fun detail(kind: KClass): DocumentationNode = details.singleByKind(kind) + fun detailOrNull(kind: KClass): DocumentationNode? = + details.singleOrNull { it::class == kind } - fun detail(kind: NodeKind): DocumentationNode = details.single { it.kind == kind } - fun detailOrNull(kind: NodeKind): DocumentationNode? = details.singleOrNull { it.kind == kind } - fun member(kind: NodeKind): DocumentationNode = members.single { it.kind == kind } - fun link(kind: NodeKind): DocumentationNode = links.single { it.kind == kind } + fun member(kind: KClass): DocumentationNode = members.singleByKind(kind) + fun link(kind: KClass): DocumentationNode = links.singleByKind(kind) fun references(kind: RefKind): List = references.filter { it.kind == kind } fun allReferences(): Set = references override fun toString(): String { - return "$kind:$name" + return "${javaClass.name}:$name" } } -class DocumentationModule(name: String, content: Content = Content.Empty, val nodeRefGraph: NodeReferenceGraph = NodeReferenceGraph()) - : DocumentationNode(name, content, NodeKind.Module) { +fun KClass.createNode(name: String, descriptor: DeclarationDescriptor? = null) = + primaryConstructor?.call(name, descriptor) + ?: throw IllegalArgumentException("Cannot create node of type ${this::class}: invalid primary constructor") -} +val DocumentationNode.supertypes: List + get() = details(DocumentationNodes.Supertype::class) + +class DocumentationModule(name: String) : DocumentationNode(name) val DocumentationNode.path: List get() { @@ -202,23 +266,6 @@ val DocumentationNode.path: List return parent.path + this } -fun findOrCreatePackageNode(module: DocumentationNode?, packageName: String, packageContent: Map, refGraph: NodeReferenceGraph): DocumentationNode { - val node = refGraph.lookup(packageName) ?: run { - val newNode = DocumentationNode( - packageName, - packageContent.getOrElse(packageName) { Content.Empty }, - NodeKind.Package - ) - - 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) { addReferenceTo(child, kind) when (kind) { @@ -231,19 +278,23 @@ fun DocumentationNode.append(child: DocumentationNode, kind: RefKind) { } } -fun DocumentationNode.appendTextNode(text: String, - kind: NodeKind, - refKind: RefKind = RefKind.Detail) { - append(DocumentationNode(text, Content.Empty, kind), refKind) +fun DocumentationNode.appendTextNode( + text: String, + kind: KClass, + descriptor: DeclarationDescriptor? = null, + refKind: RefKind = RefKind.Detail +) { + append(kind.createNode(text, descriptor), refKind) } fun DocumentationNode.qualifiedName(): String { - if (kind == NodeKind.Type) { + if (this is DocumentationNodes.Type) { return qualifiedNameFromType() - } else if (kind == NodeKind.Package) { + } else if (this is DocumentationNodes.Package) { return name } - return path.dropWhile { it.kind == NodeKind.Module }.map { it.name }.filter { it.isNotEmpty() }.joinToString(".") + return path.dropWhile { it is DocumentationNodes.Module }.map { it.name }.filter { it.isNotEmpty() } + .joinToString(".") } fun DocumentationNode.simpleName() = name.substringAfterLast('.') @@ -257,20 +308,23 @@ private fun DocumentationNode.recursiveInheritedMembers(): List) { allInheritedMembers.addAll(inheritedMembers) System.out.println(allInheritedMembers.size) - inheritedMembers.groupBy { it.owner!! } .forEach { (node, _) -> + 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 + return when (node) { + is DocumentationNodes.Object, + is DocumentationNodes.Class, + is DocumentationNodes.Enum -> this is DocumentationNodes.Class + is DocumentationNodes.Exception -> this is DocumentationNodes.Class || this is DocumentationNodes.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 } + assert(classLike) + return path.dropWhile { it is DocumentationNodes.Package || it is DocumentationNodes.Module } + .joinToString(separator = ".") { it.name } } \ No newline at end of file diff --git a/core/src/main/kotlin/Model/DocumentationReference.kt b/core/src/main/kotlin/Model/DocumentationReference.kt index 0b890a78..e46a4a21 100644 --- a/core/src/main/kotlin/Model/DocumentationReference.kt +++ b/core/src/main/kotlin/Model/DocumentationReference.kt @@ -112,15 +112,4 @@ class NodeReferenceGraph { fun resolveReferences() { references.forEach { it.resolve(this) } } -} - -@Singleton -class PlatformNodeRegistry { - private val platformNodes = hashMapOf() - - operator fun get(platform: String): DocumentationNode { - return platformNodes.getOrPut(platform) { - DocumentationNode(platform, Content.Empty, NodeKind.Platform) - } - } -} +} \ No newline at end of file diff --git a/core/src/main/kotlin/Model/SourceLinks.kt b/core/src/main/kotlin/Model/SourceLinks.kt index 99ee362e..68cdab4a 100644 --- a/core/src/main/kotlin/Model/SourceLinks.kt +++ b/core/src/main/kotlin/Model/SourceLinks.kt @@ -7,72 +7,8 @@ import org.jetbrains.dokka.DokkaConfiguration.SourceLinkDefinition import org.jetbrains.kotlin.psi.psiUtil.startOffset 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 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 += sourceLinkDefinition.lineSuffix + line.toString() - } - } - append(DocumentationNode(url, Content.Empty, NodeKind.SourceUrl), RefKind.Detail) - } - - if (target != null) { - append(DocumentationNode(target.sourcePosition(), Content.Empty, NodeKind.SourcePosition), RefKind.Detail) - } -} - -private fun determineSourceLinkDefinition( - canonicalPath: String, - sourceLinks: List -): Pair? { - return sourceLinks - .asSequence() - .map { it to File(it.path).canonicalPat