From 12f91ee7d491b21359ff8e8822c594f35b904def Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Tue, 28 Jul 2015 14:15:55 +0300 Subject: Initial javadoc generation module --- javadoc/src/main/kotlin/docbase.kt | 500 +++++++++++++++++++++++++++++ javadoc/src/main/kotlin/main.kt | 24 ++ javadoc/src/main/kotlin/reporter.kt | 30 ++ javadoc/src/main/kotlin/source-position.kt | 18 ++ javadoc/src/main/kotlin/tags.kt | 180 +++++++++++ javadoc/src/main/kotlin/utils.kt | 10 + 6 files changed, 762 insertions(+) create mode 100644 javadoc/src/main/kotlin/docbase.kt create mode 100644 javadoc/src/main/kotlin/main.kt create mode 100644 javadoc/src/main/kotlin/reporter.kt create mode 100644 javadoc/src/main/kotlin/source-position.kt create mode 100644 javadoc/src/main/kotlin/tags.kt create mode 100644 javadoc/src/main/kotlin/utils.kt (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt new file mode 100644 index 00000000..fe66a672 --- /dev/null +++ b/javadoc/src/main/kotlin/docbase.kt @@ -0,0 +1,500 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.* +import org.jetbrains.dokka.* +import java.lang.reflect.Modifier +import java.util.Collections +import java.util.HashSet + +open class DocumentationNodeBareAdapter(val docNode: DocumentationNode) : Doc { + private var rawCommentText_ = rawCommentText + + override fun name(): String = docNode.name + override fun position(): SourcePosition? = SourcePositionAdapter(docNode) + + 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 = docNode.kind == DocumentationNode.Kind.Exception + override fun isEnumConstant(): Boolean = docNode.kind == DocumentationNode.Kind.EnumItem + override fun isEnum(): Boolean = docNode.kind == DocumentationNode.Kind.Enum + override fun isMethod(): Boolean = docNode.kind == DocumentationNode.Kind.Function + override fun isInterface(): Boolean = docNode.kind == DocumentationNode.Kind.Interface + override fun isField(): Boolean = docNode.kind == DocumentationNode.Kind.Property + override fun isClass(): Boolean = docNode.kind == DocumentationNode.Kind.Class + override fun isAnnotationType(): Boolean = docNode.kind == DocumentationNode.Kind.AnnotationClass + override fun isConstructor(): Boolean = docNode.kind == DocumentationNode.Kind.Constructor + override fun isOrdinaryClass(): Boolean = docNode.kind == DocumentationNode.Kind.Class + override fun isAnnotationTypeElement(): Boolean = docNode.kind == DocumentationNode.Kind.Annotation + + override fun compareTo(other: Any?): Int = when (other) { + !is DocumentationNodeAdapter -> 1 + else -> docNode.name.compareTo(other.docNode.name) + } + + override fun equals(other: Any?): Boolean = docNode.qualifiedName == (other as? DocumentationNodeAdapter)?.docNode?.qualifiedName + override fun hashCode(): Int = docNode.name.hashCode() + + override fun isIncluded(): Boolean = docNode.kind != DocumentationNode.Kind.ExternalClass +} + + +// TODO think of source position instead of null +// TODO tags +open class DocumentationNodeAdapter(val module: ModuleNodeAdapter, docNode: DocumentationNode) : DocumentationNodeBareAdapter(docNode) { + override fun inlineTags(): Array = buildInlineTags(module, this, docNode.content).toTypedArray() + override fun firstSentenceTags(): Array = buildInlineTags(module, this, docNode.summary).toTypedArray() + override fun tags(): Array = (buildInlineTags(module, this, docNode.content) + docNode.content.sections.flatMap { + when (it.tag) { + "See Also" -> buildInlineTags(module, this, it) + else -> emptyList() + } + }).toTypedArray() +} + +private val allClassKinds = setOf(DocumentationNode.Kind.Class, DocumentationNode.Kind.Enum, DocumentationNode.Kind.Interface, DocumentationNode.Kind.Object, DocumentationNode.Kind.Exception) + +class PackageAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), PackageDoc { + private val allClasses = node.members.filter { it.kind in allClassKinds }.toMap { it.name } + private val packageFacade = PackageFacadeAdapter(module, node) + + override fun findClass(className: String?): ClassDoc? = + allClasses.get(className)?.let { ClassDocumentationNodeAdapter(module, it) } + ?: if (packageFacade.name() == className) packageFacade else null + + override fun annotationTypes(): Array = emptyArray() + override fun annotations(): Array = node.members(DocumentationNode.Kind.AnnotationClass).map { AnnotationDescAdapter(module, it) }.toTypedArray() + override fun exceptions(): Array = node.members(DocumentationNode.Kind.Exception).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun ordinaryClasses(): Array = (node.members(DocumentationNode.Kind.Class).map { ClassDocumentationNodeAdapter(module, it) } + packageFacade).toTypedArray() + override fun interfaces(): Array = node.members(DocumentationNode.Kind.Interface).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun errors(): Array = emptyArray() + override fun enums(): Array = node.members(DocumentationNode.Kind.Enum).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun allClasses(filter: Boolean): Array = (allClasses.values().map { ClassDocumentationNodeAdapter(module, it) } + packageFacade).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) // TODO ????? + override fun isSynthesized(): Boolean = false + override fun elementValues(): Array? = emptyArray() // TODO +} + +class ProgramElementAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc { + override fun isPublic(): Boolean = true + override fun isPackagePrivate(): Boolean = false + override fun isStatic(): Boolean = node.owner?.kind in listOf(DocumentationNode.Kind.Package, DocumentationNode.Kind.ExternalClass) + override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0 + override fun qualifiedName(): String? = node.qualifiedName + override fun annotations(): Array? = node.annotations.map { AnnotationDescAdapter(module, it) }.toTypedArray() + override fun modifiers(): String? = "public ${if (isStatic) "static" else ""}".trim() + override fun isProtected(): Boolean = false + + override fun isFinal(): Boolean = node.details(DocumentationNode.Kind.Modifier).any { it.name == "final" } + + override fun containingPackage(): PackageDoc? { + var owner: DocumentationNode? = node + while (owner != null) { + if (owner.kind == DocumentationNode.Kind.Package) { + return PackageAdapter(module, owner) + } + owner = owner.owner + } + + return null + } + + override fun containingClass(): ClassDoc? { + var owner = node.owner + while (owner != null) { + when (owner.kind) { + DocumentationNode.Kind.Class -> return ClassDocumentationNodeAdapter(module, owner) + DocumentationNode.Kind.Package -> return PackageFacadeAdapter(module, owner) + else -> owner = owner.owner + } + } + + return null + } + + override fun isPrivate(): Boolean = false + override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true +} + +public fun DocumentationNode.getArrayElementType(): DocumentationNode? = when (name) { + "Array" -> details(DocumentationNode.Kind.Type).singleOrNull()?.let { et -> et.getArrayElementType() ?: et } ?: DocumentationNode("Object", content, DocumentationNode.Kind.ExternalClass) + "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> DocumentationNode(name.removeSuffix("Array").toLowerCase(), content, DocumentationNode.Kind.Type) + else -> null +} + +fun DocumentationNode.getArrayDimension(): Int = when (name) { + "Array" -> 1 + (details(DocumentationNode.Kind.Type).singleOrNull()?.getArrayDimension() ?: 0) + "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> 1 + else -> 0 +} + +//fun DocumentationNode.convertNativeType(): DocumentationNode = when (name) { +// "Unit" -> DocumentationNode("void", content, kind) +// "Int" -> DocumentationNode("int", content, kind) +//} + +open class TypeAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : Type { + override fun qualifiedTypeName(): String = node.getArrayElementType()?.qualifiedName ?: node.qualifiedName + override fun typeName(): String = node.getArrayElementType()?.name ?: node.name + override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName() + + override fun dimension(): String = Collections.nCopies(node.getArrayDimension(), "[]").joinToString("") + override fun isPrimitive(): Boolean = node.name in setOf("Int", "Long", "Short", "Byte", "Char", "Double", "Float", "Boolean", "Unit") + override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else + elementType?.asClassDoc() ?: + when (node.kind) { + DocumentationNode.Kind.Class, + DocumentationNode.Kind.ExternalClass, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Object, + DocumentationNode.Kind.Exception, + DocumentationNode.Kind.Enum -> 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 == DocumentationNode.Kind.TypeParameter) TypeVariableAdapter(module, node) else null + override fun asParameterizedType(): ParameterizedType? = + if (node.details(DocumentationNode.Kind.Type).isNotEmpty()) ParameterizedTypeAdapter(module, node) + else null // TODO it should ignore dimensions + + override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == DocumentationNode.Kind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null + override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null + override fun getElementType(): Type? = node.getArrayElementType()?.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 AnnotatedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), AnnotatedType { + override fun underlyingType(): Type? = this + override fun annotations(): Array = node.annotations.map { AnnotationDescAdapter(module, it) }.toTypedArray() +} + +class WildcardTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), WildcardType { + override fun extendsBounds(): Array = node.details(DocumentationNode.Kind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray() + override fun superBounds(): Array = node.details(DocumentationNode.Kind.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) { + DocumentationNode.Kind.Function, + DocumentationNode.Kind.Constructor -> ExecutableMemberAdapter(module, owner) + + DocumentationNode.Kind.Class, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Enum -> ClassDocumentationNodeAdapter(module, owner) + + else -> ProgramElementAdapter(module, node.owner!!) + } + } + + override fun bounds(): Array? = node.details(DocumentationNode.Kind.UpperBound).map { TypeAdapter(module, it) }.toTypedArray() + override fun annotations(): Array? = node.members(DocumentationNode.Kind.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 + // override fun asClassDoc(): ClassDoc? = null +} + +class ParameterizedTypeAdapter(module: ModuleNodeAdapter, node: DocumentationNode) : TypeAdapter(module, node), ParameterizedType { + override fun typeArguments(): Array = node.details(DocumentationNode.Kind.Type).map { TypeVariableAdapter(module, it) }.toTypedArray() + override fun superclassType(): Type? = + node.lookupSuperClasses(module) + .firstOrNull { it.kind == DocumentationNode.Kind.Class || it.kind == DocumentationNode.Kind.ExternalClass } + ?.let { ClassDocumentationNodeAdapter(module, it) } + + override fun interfaceTypes(): Array = + node.lookupSuperClasses(module) + .filter { it.kind == DocumentationNode.Kind.Interface } + .map { ClassDocumentationNodeAdapter(module, it) } + .toTypedArray() + + override fun containingType(): Type? = when (node.owner?.kind) { + DocumentationNode.Kind.Package -> null + DocumentationNode.Kind.Class, + DocumentationNode.Kind.Interface, + DocumentationNode.Kind.Object, + DocumentationNode.Kind.Enum -> ClassDocumentationNodeAdapter(module, node.owner!!) + + else -> null + } +} + +class ParameterAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), Parameter { + override fun typeName(): String? = JavaLanguageService().renderType(node.detail(DocumentationNode.Kind.Type)) + override fun type(): Type? = TypeAdapter(module, node.detail(DocumentationNode.Kind.Type)) + override fun annotations(): Array? = node.details(DocumentationNode.Kind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray() +} + +class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode) : DocumentationNodeAdapter(module, receiverType), Parameter { + override fun typeName(): String? = receiverType.name + override fun type(): Type? = TypeAdapter(module, receiverType) + override fun annotations(): Array = emptyArray() + override fun name(): String = "receiver" +} + +fun classOf(fqName: String, kind: DocumentationNode.Kind = DocumentationNode.Kind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node -> + val pkg = fqName.substringBeforeLast(".", "") + if (pkg.isNotEmpty()) { + node.append(DocumentationNode(pkg, Content.Empty, DocumentationNode.Kind.Package), DocumentationReference.Kind.Owner) + } + + node +} + +open class ExecutableMemberAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by 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 == "Exceptions" } + .map { it.subjectName } + .filterNotNull() + .map { ThrowsTagAdapter(this, ClassDocumentationNodeAdapter(module, classOf(it, DocumentationNode.Kind.Exception))) } + .toTypedArray() + + override fun isVarArgs(): Boolean = node.details(DocumentationNode.Kind.Parameter).any { false } // TODO + + override fun isSynchronized(): Boolean = node.annotations.any { it.name == "synchronized" } + override fun paramTags(): Array = node.details(DocumentationNode.Kind.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 thrownExceptionTypes(): Array = emptyArray() + override fun receiverType(): Type? = receiverNode()?.let { receiver -> TypeAdapter(module, receiver) } + override fun flatSignature(): String = node.details(DocumentationNode.Kind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") + override fun signature(): String = node.details(DocumentationNode.Kind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types + + override fun parameters(): Array = + ((receiverNode()?.let { receiver -> listOf(ReceiverParameterAdapter(module, receiver)) } ?: emptyList()) + + node.details(DocumentationNode.Kind.Parameter).map { ParameterAdapter(module, it) } + ).toTypedArray() + + override fun typeParameters(): Array = node.details(DocumentationNode.Kind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray() + + override fun typeParamTags(): Array = node.details(DocumentationNode.Kind.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() + + private fun receiverNode() = node.details(DocumentationNode.Kind.Receiver).let { receivers -> + when { + receivers.isNotEmpty() -> receivers.single().detail(DocumentationNode.Kind.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") +} + +class MethodAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ExecutableMemberDoc by 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(DocumentationNode.Kind.Type)) +} + +class FieldAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : DocumentationNodeAdapter(module, node), ProgramElementDoc by ProgramElementAdapter(module, node), FieldDoc { + override fun isSynthetic(): Boolean = false + + override fun constantValueExpression(): String? = null // TODO + override fun constantValue(): Any? = null + + override fun type(): Type = TypeAdapter(module, node.detail(DocumentationNode.Kind.Type)) + override fun isTransient(): Boolean = false // TODO + override fun serialFieldTags(): Array = emptyArray() + + override fun isVolatile(): Boolean = false // TODO +} + +open class ClassDocumentationNodeAdapter(module: ModuleNodeAdapter, val classNode: DocumentationNode) : DocumentationNodeAdapter(module, classNode), Type by TypeAdapter(module, classNode), ProgramElementDoc by ProgramElementAdapter(module, classNode), ClassDoc { + override fun constructors(filter: Boolean): Array = classNode.members(DocumentationNode.Kind.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(DocumentationNode.Kind.TypeParameter).map { TypeVariableAdapter(module, it) }.toTypedArray() + override fun asTypeVariable(): TypeVariable? = if (classNode.kind == DocumentationNode.Kind.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(DocumentationNode.Kind.Function).map { MethodAdapter(module, it) }.toTypedArray() // TODO include get/set methods + override fun methods(): Array = methods(true) + override fun enumConstants(): Array? = classNode.members(DocumentationNode.Kind.EnumItem).map { FieldAdapter(module, it) }.toTypedArray() + override fun isAbstract(): Boolean = classNode.details(DocumentationNode.Kind.Modifier).any { it.name == "abstract" } + override fun interfaceTypes(): Array = classNode.lookupSuperClasses(module) + .filter { it.kind == DocumentationNode.Kind.Interface } + .map { ClassDocumentationNodeAdapter(module, it) } + .toTypedArray() + + override fun interfaces(): Array = classNode.lookupSuperClasses(module) + .filter { it.kind == DocumentationNode.Kind.Interface } + .map { ClassDocumentationNodeAdapter(module, it) } + .toTypedArray() + + override fun typeParamTags(): Array = (classNode.details(DocumentationNode.Kind.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 fields(): Array = emptyArray() + override fun fields(filter: Boolean): Array = emptyArray() + + override fun findClass(className: String?): ClassDoc? = null // TODO !!! + override fun serializableFields(): Array = emptyArray() + override fun superclassType(): Type? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == DocumentationNode.Kind.Class }?.let { ClassDocumentationNodeAdapter(module, it) } + override fun serializationMethods(): Array = emptyArray() // TODO + override fun superclass(): ClassDoc? = classNode.lookupSuperClasses(module).singleOrNull { it.kind == DocumentationNode.Kind.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.remove(types.lastIndex) + val fqName = type.qualifiedName + + if (expectedFQName == fqName) { + return true + } + + visitedTypes.add(fqName) + types.addAll(type.details(DocumentationNode.Kind.Supertype).filter { it.qualifiedName !in visitedTypes }) + } + + return false + } + + override fun innerClasses(): Array = classNode.members(DocumentationNode.Kind.Class).map { ClassDocumentationNodeAdapter(module, it) }.toTypedArray() + override fun innerClasses(filter: Boolean): Array = innerClasses() +} + +class PackageFacadeAdapter(val module: ModuleNodeAdapter, val packageNode: DocumentationNode) : ProgramElementDoc by ProgramElementAdapter(module, packageNode), ClassDoc { + override fun simpleTypeName(): String = packageNode.name.substringAfterLast(".", packageNode.name).capitalize() + "Package" + override fun typeName(): String = simpleTypeName() + override fun qualifiedTypeName(): String = packageNode.name.split(".").let { parts -> parts.take(parts.size() - 1) + parts.takeLast(1).map { it.capitalize() + "Package" } }.joinToString(".") + override fun qualifiedName(): String = qualifiedTypeName() + override fun name(): String = simpleTypeName() + + override fun isPrimitive(): Boolean = false + override fun dimension(): String = "" + override fun getElementType(): Type? = null + override fun asParameterizedType(): ParameterizedType? = null + override fun asClassDoc(): ClassDoc = this + override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = null + override fun asAnnotatedType(): AnnotatedType? = null + override fun asWildcardType(): WildcardType? = null + override fun asTypeVariable(): TypeVariable? = null + override fun importedPackages(): Array = emptyArray() + override fun typeParameters(): Array = emptyArray() + override fun importedClasses(): Array = emptyArray() + override fun isExternalizable(): Boolean = false + override fun definesSerializableFields(): Boolean = false + override fun methods(): Array = members(DocumentationNode.Kind.Function).map { MethodAdapter(module, it) }.toTypedArray() + override fun fields(): Array = members(DocumentationNode.Kind.Property).map { FieldAdapter(module, it) }.toTypedArray() + override fun methods(filter: Boolean): Array = methods() + override fun fields(filter: Boolean): Array = fields() + override fun constructors(): Array = emptyArray() + override fun constructors(filter: Boolean): Array = constructors() + override fun enumConstants(): Array = emptyArray() + override fun isAbstract(): Boolean = false + override fun interfaceTypes(): Array = emptyArray() + override fun interfaces(): Array = emptyArray() + override fun typeParamTags(): Array = emptyArray() + override fun findClass(className: String?): ClassDoc? = null // TODO ??? + override fun serializableFields(): Array = emptyArray() + override fun superclassType(): Type? = null + override fun serializationMethods(): Array = emptyArray() + override fun superclass(): ClassDoc? = null + override fun isSerializable(): Boolean = false + override fun subclassOf(cd: ClassDoc?): Boolean = false + override fun innerClasses(): Array = emptyArray() + override fun innerClasses(filter: Boolean): Array = innerClasses() + override fun isOrdinaryClass(): Boolean = true + override fun isClass(): Boolean = true + + private fun members(kind: DocumentationNode.Kind) = packageNode.members(kind) + packageNode.members(DocumentationNode.Kind.ExternalClass).flatMap { it.members(kind) } +} + +fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) = + details(DocumentationNode.Kind.Supertype) + .map { it.links.firstOrNull() } + .map { module.allTypes[it?.qualifiedName] } + .filterNotNull() + +class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { + val allPackages = module.members(DocumentationNode.Kind.Package).toMap { it.name } + val allTypes = module.members(DocumentationNode.Kind.Package) + .flatMap { it.members(DocumentationNode.Kind.Class) + it.members(DocumentationNode.Kind.Interface) + it.members(DocumentationNode.Kind.Enum) } + .toMap { it.qualifiedName } + val packageFacades = module.members(DocumentationNode.Kind.Package).map { PackageFacadeAdapter(this, it) }.toMap { it.qualifiedName() } + + override fun packageNamed(name: String?): PackageDoc? = allPackages[name]?.let { PackageAdapter(this, it) } + + override fun classes(): Array = + (allTypes.values().map { ClassDocumentationNodeAdapter(this, it) } + packageFacades.values()) + .toTypedArray() + + override fun options(): Array> = arrayOf( + arrayOf("-d", "out/javadoc"), + arrayOf("-docencoding", "UTF-8") + ) + + override fun specifiedPackages(): Array? = module.members(DocumentationNode.Kind.Package).map { PackageAdapter(this, it) }.toTypedArray() + + override fun classNamed(qualifiedName: String?): ClassDoc? = + allTypes[qualifiedName]?.let { ClassDocumentationNodeAdapter(this, it) } + ?: packageFacades[qualifiedName] + + override fun specifiedClasses(): Array = classes() +} diff --git a/javadoc/src/main/kotlin/main.kt b/javadoc/src/main/kotlin/main.kt new file mode 100644 index 00000000..0c3821c3 --- /dev/null +++ b/javadoc/src/main/kotlin/main.kt @@ -0,0 +1,24 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.tools.doclets.formats.html.HtmlDoclet +import org.jetbrains.dokka.DocumentationOptions +import org.jetbrains.dokka.DokkaConsoleLogger +import org.jetbrains.dokka.DokkaGenerator +import org.jetbrains.dokka.buildDocumentationModule +import java.io.File + +/** + * Test me, my friend + */ +public fun main(args: Array) { + val generator = DokkaGenerator(DokkaConsoleLogger, System.getProperty("java.class.path").split(File.pathSeparator), listOf(File("test").absolutePath), emptyList(), emptyList(), "me", "out/dokka", "html", emptyList(), false) + val env = generator.createAnalysisEnvironment() + val module = buildDocumentationModule(env, generator.moduleName, DocumentationOptions(includeNonPublic = true, sourceLinks = emptyList()), emptyList(), { + generator.isSample(it) + }, generator.logger) + + DokkaConsoleLogger.report() + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter)) +} + +public fun String.a(): Int = 1 \ No newline at end of file diff --git a/javadoc/src/main/kotlin/reporter.kt b/javadoc/src/main/kotlin/reporter.kt new file mode 100644 index 00000000..ce80ec7b --- /dev/null +++ b/javadoc/src/main/kotlin/reporter.kt @@ -0,0 +1,30 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.DocErrorReporter +import com.sun.javadoc.SourcePosition + +object StandardReporter : DocErrorReporter { + override fun printWarning(msg: String?) { + System.err?.println("[WARN] $msg") + } + + override fun printWarning(pos: SourcePosition?, msg: String?) { + System.err?.println("[WARN] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + } + + override fun printError(msg: String?) { + System.err?.println("[ERROR] $msg") + } + + override fun printError(pos: SourcePosition?, msg: String?) { + System.err?.println("[ERROR] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + } + + override fun printNotice(msg: String?) { + System.err?.println("[NOTICE] $msg") + } + + override fun printNotice(pos: SourcePosition?, msg: String?) { + System.err?.println("[NOTICE] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + } +} \ No newline at end of file diff --git a/javadoc/src/main/kotlin/source-position.kt b/javadoc/src/main/kotlin/source-position.kt new file mode 100644 index 00000000..0e4c6e3c --- /dev/null +++ b/javadoc/src/main/kotlin/source-position.kt @@ -0,0 +1,18 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.SourcePosition +import org.jetbrains.dokka.DocumentationNode +import java.io.File + +class SourcePositionAdapter(val docNode: DocumentationNode) : SourcePosition { + + private val sourcePositionParts: List by lazy { + docNode.details(DocumentationNode.Kind.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/javadoc/src/main/kotlin/tags.kt b/javadoc/src/main/kotlin/tags.kt new file mode 100644 index 00000000..120154f9 --- /dev/null +++ b/javadoc/src/main/kotlin/tags.kt @@ -0,0 +1,180 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.javadoc.* +import org.jetbrains.dokka.* +import java.util.ArrayList + +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 = "${link.href}" + 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" +} + +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 = "fun ${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()}" // TODO + + override fun inlineTags(): Array = emptyArray() // TODO + override fun firstSentenceTags(): Array = inlineTags() // TODO +} + +class ParamTagAdapter(val module: ModuleNodeAdapter, val holder: Doc, val parameterName: String, val isTypeParameter: 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 ..." + override fun inlineTags(): Array = content.flatMap { buildInlineTags(module, holder, it) }.toTypedArray() + override fun firstSentenceTags(): Array = arrayOf(TextTag(holder, ContentText(text()))) + + override fun isTypeParameter(): Boolean = isTypeParameter + override fun parameterComment(): String = content.toString() // TODO + override fun parameterName(): String = parameterName +} + + +class ThrowsTagAdapter(val holder: Doc, val type: ClassDocumentationNodeAdapter) : 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 = emptyArray() + override fun firstSentenceTags(): Array = emptyArray() + + override fun exceptionComment(): String = "" + override fun exceptionType(): Type = type + override fun exception(): ClassDoc = type + override fun exceptionName(): String = type.qualifiedName() +} + +fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, root: ContentNode): List = ArrayList().let { buildInlineTags(module, holder, root, it); it } + +private fun buildInlineTags(module: ModuleNodeAdapter, holder: Doc, node: ContentNode, result: MutableList) { + when (node) { + is ContentText -> result.add(TextTag(holder, node)) + is ContentNodeLink -> { + when (node.node?.kind) { + DocumentationNode.Kind.Function -> result.add(SeeMethodTagAdapter(holder, MethodAdapter(module, node.node!!), node)) + + DocumentationNode.Kind.Class, + DocumentationNode.Kind.ExternalClass, + DocumentationNode.Kind.Enum -> result.add(SeeClassTagAdapter(holder, ClassDocumentationNodeAdapter(module, node.node!!), node)) + + else -> result.add(TextTag(holder, ContentText("other link: ${node.node}"))) // TODO + } + } + 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) +// node.sections.forEach { +// buildInlineTags(module, holder, it, result) +// } + } + + else -> result.add(TextTag(holder, ContentText("$node"))) + } +} + +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) + node.children.forEach { + buildInlineTags(module, holder, it, result) + } + + if (result.last() === open) { + result.remove(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.remove(result.lastIndex) + } else { + result.add(close) + } + } +} \ No newline at end of file diff --git a/javadoc/src/main/kotlin/utils.kt b/javadoc/src/main/kotlin/utils.kt new file mode 100644 index 00000000..661de0c8 --- /dev/null +++ b/javadoc/src/main/kotlin/utils.kt @@ -0,0 +1,10 @@ +package org.jetbrains.dokka.javadoc + +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.path +import java.util.* + +val DocumentationNode.qualifiedName: String + get() = this.path.filter { it.kind == DocumentationNode.Kind.Package || it.kind in allClassKinds } + .map { it.name } + .joinToString(".") -- cgit From e27fb69817b1417c1bc556a507b14f2700c7a736 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Fri, 31 Jul 2015 15:35:34 +0300 Subject: Use Guice injector and ServiceLocator to load implementations on the fly --- javadoc/src/main/kotlin/docbase.kt | 8 +++--- javadoc/src/main/kotlin/dokka-adapters.kt | 29 ++++++++++++++++++++++ javadoc/src/main/kotlin/main.kt | 24 ------------------ .../resources/dokka/generator/javadoc.properties | 2 ++ .../src/main/resources/format/javadoc.properties | 1 + 5 files changed, 37 insertions(+), 27 deletions(-) create mode 100644 javadoc/src/main/kotlin/dokka-adapters.kt delete mode 100644 javadoc/src/main/kotlin/main.kt create mode 100644 javadoc/src/main/resources/dokka/generator/javadoc.properties create mode 100644 javadoc/src/main/resources/format/javadoc.properties (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index fe66a672..aa1e01a6 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -472,7 +472,7 @@ fun DocumentationNode.lookupSuperClasses(module: ModuleNodeAdapter) = .map { module.allTypes[it?.qualifiedName] } .filterNotNull() -class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { +class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorReporter, val outputPath: String) : DocumentationNodeBareAdapter(module), DocErrorReporter by reporter, RootDoc { val allPackages = module.members(DocumentationNode.Kind.Package).toMap { it.name } val allTypes = module.members(DocumentationNode.Kind.Package) .flatMap { it.members(DocumentationNode.Kind.Class) + it.members(DocumentationNode.Kind.Interface) + it.members(DocumentationNode.Kind.Enum) } @@ -486,8 +486,10 @@ class ModuleNodeAdapter(val module: DocumentationModule, val reporter: DocErrorR .toTypedArray() override fun options(): Array> = arrayOf( - arrayOf("-d", "out/javadoc"), - arrayOf("-docencoding", "UTF-8") + arrayOf("-d", outputPath), + arrayOf("-docencoding", "UTF-8"), + arrayOf("-charset", "UTF-8"), + arrayOf("-keywords") ) override fun specifiedPackages(): Array? = module.members(DocumentationNode.Kind.Package).map { PackageAdapter(this, it) }.toTypedArray() diff --git a/javadoc/src/main/kotlin/dokka-adapters.kt b/javadoc/src/main/kotlin/dokka-adapters.kt new file mode 100644 index 00000000..c9183d50 --- /dev/null +++ b/javadoc/src/main/kotlin/dokka-adapters.kt @@ -0,0 +1,29 @@ +package org.jetbrains.dokka.javadoc + +import com.sun.tools.doclets.formats.html.HtmlDoclet +import org.jetbrains.dokka.* +import org.jetbrains.dokka.Formats.FormatDescriptor + +class JavadocGenerator(val conf: DokkaGenerator) : Generator { + override fun buildPages(nodes: Iterable) { + val module = nodes.single() as DocumentationModule + + DokkaConsoleLogger.report() + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter, conf.outputDir)) + } + + override fun buildOutlines(nodes: Iterable) { + // no outline could be generated separately + } +} + +class JavadocFormatDescriptor : FormatDescriptor { + override val formatServiceClass: Class? + get() = null + override val outlineServiceClass: Class? + get() = null + + override val generatorServiceClass: Class + get() = javaClass() +} + diff --git a/javadoc/src/main/kotlin/main.kt b/javadoc/src/main/kotlin/main.kt deleted file mode 100644 index 0c3821c3..00000000 --- a/javadoc/src/main/kotlin/main.kt +++ /dev/null @@ -1,24 +0,0 @@ -package org.jetbrains.dokka.javadoc - -import com.sun.tools.doclets.formats.html.HtmlDoclet -import org.jetbrains.dokka.DocumentationOptions -import org.jetbrains.dokka.DokkaConsoleLogger -import org.jetbrains.dokka.DokkaGenerator -import org.jetbrains.dokka.buildDocumentationModule -import java.io.File - -/** - * Test me, my friend - */ -public fun main(args: Array) { - val generator = DokkaGenerator(DokkaConsoleLogger, System.getProperty("java.class.path").split(File.pathSeparator), listOf(File("test").absolutePath), emptyList(), emptyList(), "me", "out/dokka", "html", emptyList(), false) - val env = generator.createAnalysisEnvironment() - val module = buildDocumentationModule(env, generator.moduleName, DocumentationOptions(includeNonPublic = true, sourceLinks = emptyList()), emptyList(), { - generator.isSample(it) - }, generator.logger) - - DokkaConsoleLogger.report() - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter)) -} - -public fun String.a(): Int = 1 \ No newline at end of file diff --git a/javadoc/src/main/resources/dokka/generator/javadoc.properties b/javadoc/src/main/resources/dokka/generator/javadoc.properties new file mode 100644 index 00000000..4075704f --- /dev/null +++ b/javadoc/src/main/resources/dokka/generator/javadoc.properties @@ -0,0 +1,2 @@ +class=org.jetbrains.dokka.javadoc.JavadocGenerator +description=Produces output via JDK javadoc tool \ No newline at end of file diff --git a/javadoc/src/main/resources/format/javadoc.properties b/javadoc/src/main/resources/format/javadoc.properties new file mode 100644 index 00000000..a58317fc --- /dev/null +++ b/javadoc/src/main/resources/format/javadoc.properties @@ -0,0 +1 @@ +class=org.jetbrains.dokka.javadoc.JavadocFormatDescriptor \ No newline at end of file -- cgit From e1f7ce7a16954d238345fe0e30257492c0886f37 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Tue, 4 Aug 2015 18:47:25 +0300 Subject: ~ see also --- javadoc/src/main/kotlin/docbase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index aa1e01a6..a513a3e1 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -57,7 +57,7 @@ open class DocumentationNodeAdapter(val module: ModuleNodeAdapter, docNode: Docu override fun firstSentenceTags(): Array = buildInlineTags(module, this, docNode.summary).toTypedArray() override fun tags(): Array = (buildInlineTags(module, this, docNode.content) + docNode.content.sections.flatMap { when (it.tag) { - "See Also" -> buildInlineTags(module, this, it) + ContentTags.SeeAlso -> buildInlineTags(module, this, it) else -> emptyList() } }).toTypedArray() -- cgit From 3097aaae486b952c9a4ca570c6189ce1147aec67 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 11:33:32 +0300 Subject: ~ respect platform static --- javadoc/src/main/kotlin/docbase.kt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index a513a3e1..bafc96eb 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -5,6 +5,7 @@ import org.jetbrains.dokka.* import java.lang.reflect.Modifier import java.util.Collections import java.util.HashSet +import kotlin.platform.platformStatic open class DocumentationNodeBareAdapter(val docNode: DocumentationNode) : Doc { private var rawCommentText_ = rawCommentText @@ -100,6 +101,7 @@ class ProgramElementAdapter(module: ModuleNodeAdapter, val node: DocumentationNo override fun isPublic(): Boolean = true override fun isPackagePrivate(): Boolean = false override fun isStatic(): Boolean = node.owner?.kind in listOf(DocumentationNode.Kind.Package, DocumentationNode.Kind.ExternalClass) + || platformStatic::class.qualifiedName in node.annotations.map { it.qualifiedName } override fun modifierSpecifier(): Int = Modifier.PUBLIC + if (isStatic) Modifier.STATIC else 0 override fun qualifiedName(): String? = node.qualifiedName override fun annotations(): Array? = node.annotations.map { AnnotationDescAdapter(module, it) }.toTypedArray() -- cgit From 6012a2842da93a03c72e6ef6ccc4ed5097801610 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 11:33:53 +0300 Subject: ~ use dokka logger --- javadoc/src/main/kotlin/dokka-adapters.kt | 2 +- javadoc/src/main/kotlin/reporter.kt | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/dokka-adapters.kt b/javadoc/src/main/kotlin/dokka-adapters.kt index c9183d50..0f7c53d7 100644 --- a/javadoc/src/main/kotlin/dokka-adapters.kt +++ b/javadoc/src/main/kotlin/dokka-adapters.kt @@ -9,7 +9,7 @@ class JavadocGenerator(val conf: DokkaGenerator) : Generator { val module = nodes.single() as DocumentationModule DokkaConsoleLogger.report() - HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter, conf.outputDir)) + HtmlDoclet.start(ModuleNodeAdapter(module, StandardReporter(conf.logger), conf.outputDir)) } override fun buildOutlines(nodes: Iterable) { diff --git a/javadoc/src/main/kotlin/reporter.kt b/javadoc/src/main/kotlin/reporter.kt index ce80ec7b..fc38368c 100644 --- a/javadoc/src/main/kotlin/reporter.kt +++ b/javadoc/src/main/kotlin/reporter.kt @@ -2,29 +2,33 @@ package org.jetbrains.dokka.javadoc import com.sun.javadoc.DocErrorReporter import com.sun.javadoc.SourcePosition +import org.jetbrains.dokka.DokkaLogger -object StandardReporter : DocErrorReporter { +class StandardReporter(val logger: DokkaLogger) : DocErrorReporter { override fun printWarning(msg: String?) { - System.err?.println("[WARN] $msg") + logger.warn(msg.toString()) } override fun printWarning(pos: SourcePosition?, msg: String?) { - System.err?.println("[WARN] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + logger.warn(format(pos, msg)) } override fun printError(msg: String?) { - System.err?.println("[ERROR] $msg") + logger.error(msg.toString()) } override fun printError(pos: SourcePosition?, msg: String?) { - System.err?.println("[ERROR] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + logger.error(format(pos, msg)) } override fun printNotice(msg: String?) { - System.err?.println("[NOTICE] $msg") + logger.info(msg.toString()) } override fun printNotice(pos: SourcePosition?, msg: String?) { - System.err?.println("[NOTICE] ${pos?.file()}:${pos?.line()}:${pos?.column()}: $msg") + 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 -- cgit From 9b0c1b9b0d132aba484cafbb7e12d2e132522715 Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 11:52:46 +0300 Subject: ~ move array type conversion to JavaLanguageService --- javadoc/src/main/kotlin/docbase.kt | 27 ++++++--------------------- 1 file changed, 6 insertions(+), 21 deletions(-) (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index bafc96eb..4e822fc8 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -139,29 +139,14 @@ class ProgramElementAdapter(module: ModuleNodeAdapter, val node: DocumentationNo override fun isIncluded(): Boolean = containingPackage()?.isIncluded ?: false && containingClass()?.let { it.isIncluded } ?: true } -public fun DocumentationNode.getArrayElementType(): DocumentationNode? = when (name) { - "Array" -> details(DocumentationNode.Kind.Type).singleOrNull()?.let { et -> et.getArrayElementType() ?: et } ?: DocumentationNode("Object", content, DocumentationNode.Kind.ExternalClass) - "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> DocumentationNode(name.removeSuffix("Array").toLowerCase(), content, DocumentationNode.Kind.Type) - else -> null -} - -fun DocumentationNode.getArrayDimension(): Int = when (name) { - "Array" -> 1 + (details(DocumentationNode.Kind.Type).singleOrNull()?.getArrayDimension() ?: 0) - "IntArray", "LongArray", "ShortArray", "ByteArray", "CharArray", "DoubleArray", "FloatArray", "BooleanArray" -> 1 - else -> 0 -} - -//fun DocumentationNode.convertNativeType(): DocumentationNode = when (name) { -// "Unit" -> DocumentationNode("void", content, kind) -// "Int" -> DocumentationNode("int", content, kind) -//} - open class TypeAdapter(val module: ModuleNodeAdapter, val node: DocumentationNode) : Type { - override fun qualifiedTypeName(): String = node.getArrayElementType()?.qualifiedName ?: node.qualifiedName - override fun typeName(): String = node.getArrayElementType()?.name ?: node.name + private val javaLanguageService = JavaLanguageService() + + override fun qualifiedTypeName(): String = javaLanguageService.getArrayElementType(node)?.qualifiedName ?: node.qualifiedName + override fun typeName(): String = javaLanguageService.getArrayElementType(node)?.name ?: node.name override fun simpleTypeName(): String = typeName() // TODO difference typeName() vs simpleTypeName() - override fun dimension(): String = Collections.nCopies(node.getArrayDimension(), "[]").joinToString("") + override fun dimension(): String = Collections.nCopies(javaLanguageService.getArrayDimension(node), "[]").joinToString("") override fun isPrimitive(): Boolean = node.name in setOf("Int", "Long", "Short", "Byte", "Char", "Double", "Float", "Boolean", "Unit") override fun asClassDoc(): ClassDoc? = if (isPrimitive) null else elementType?.asClassDoc() ?: @@ -186,7 +171,7 @@ open class TypeAdapter(val module: ModuleNodeAdapter, val node: DocumentationNod override fun asAnnotationTypeDoc(): AnnotationTypeDoc? = if (node.kind == DocumentationNode.Kind.AnnotationClass) AnnotationTypeDocAdapter(module, node) else null override fun asAnnotatedType(): AnnotatedType? = if (node.annotations.isNotEmpty()) AnnotatedTypeAdapter(module, node) else null - override fun getElementType(): Type? = node.getArrayElementType()?.let { et -> TypeAdapter(module, et) } + override fun getElementType(): Type? = javaLanguageService.getArrayElementType(node)?.let { et -> TypeAdapter(module, et) } override fun asWildcardType(): WildcardType? = null override fun toString(): String = qualifiedTypeName() + dimension() -- cgit From 325f4f3a29850e12c074e7e7a50d9e950d46d4ef Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 11:59:13 +0300 Subject: ~ avoid possible parameter name clash with "receiver" --- javadoc/src/main/kotlin/docbase.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index 4e822fc8..c6b84059 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -247,11 +247,17 @@ class ParameterAdapter(module: ModuleNodeAdapter, val node: DocumentationNode) : override fun annotations(): Array? = node.details(DocumentationNode.Kind.Annotation).map { AnnotationDescAdapter(module, it) }.toTypedArray() } -class ReceiverParameterAdapter(module: ModuleNodeAdapter, val receiverType: DocumentationNode) : DocumentationNodeAdapter(module, receiverType), Parameter { +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 = emptyArray() - override fun name(): String = "receiver" + override fun name(): String = tryName("receiver") + + tailRecursive + private fun tryName(name: String): String = when (name) { + in parent.parameters().drop(1).map { it.name() } -> tryName("$$name") + else -> name + } } fun classOf(fqName: String, kind: DocumentationNode.Kind = DocumentationNode.Kind.Class) = DocumentationNode(fqName.substringAfterLast(".", fqName), Content.Empty, kind).let { node -> @@ -290,7 +296,7 @@ open class ExecutableMemberAdapter(module: ModuleNodeAdapter, val node: Document override fun signature(): String = node.details(DocumentationNode.Kind.Parameter).map { JavaLanguageService().renderType(it) }.joinToString(", ", "(", ")") // TODO it should be FQ types override fun parameters(): Array = - ((receiverNode()?.let { receiver -> listOf(ReceiverParameterAdapter(module, receiver)) } ?: emptyList()) + ((receiverNode()?.let { receiver -> listOf(ReceiverParameterAdapter(module, receiver, this)) } ?: emptyList()) + node.details(DocumentationNode.Kind.Parameter).map { ParameterAdapter(module, it) } ).toTypedArray() -- cgit From dd4d2fcd3c56ee74709af5e2f4ac14e17b66e60d Mon Sep 17 00:00:00 2001 From: Sergey Mashkov Date: Thu, 6 Aug 2015 12:28:58 +0300 Subject: ~ node annotations refactoring to reduce code duplication, remove unnecessary node field duplication --- javadoc/src/main/kotlin/docbase.kt | 79 ++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 34 deletions(-) (limited to 'javadoc/src') diff --git a/javadoc/src/main/kotlin/docbase.kt b/javadoc/src/main/kotlin/docbase.kt index c6b84059..4528391f 100644 --- a/javadoc/src/main/kotlin/docbase.kt +++ b/javadoc/src/main/kotlin/docbase.kt @@ -7,11 +7,19 @@ import java.util.Collections import java.util.HashSet import kotlin.platform.platformStatic -open class DocumentationNodeBareAdapter(val docNode: DocumentationNode) : Doc { +private interface HasModule { + val module: ModuleNodeAdapter +} + +private interface HasDocumentationNode { + val node: DocumentationNode +} + +open class DocumentationNodeBareAdapter(override val node: DocumentationNode) : Doc, HasDocumentationNode { private var rawCommentText_ = rawCommentText - override fun name(): String = docNode.name - override fun position(): SourcePosition? = SourcePositionAdapter(docNode) + override fun name(): String = node.name + override fun position(): SourcePosition? = SourcePositionAdapter(node) override fun inlineTags(): Array? = emptyArray() override fun firstSentenceTags(): Array? = emptyArray() @@ -27,36 +35,36 @@ open class DocumentationNodeBareAdapter(val docNode: DocumentationNode) : Doc { override fun getRawCommentText(): String = rawCommentText_ override fun isError(): Boolean = false - override fun isException(): Boolean = docNode.kind == DocumentationNode.Kind.Exception - override fun isEnumConstant(): Boolean = docNode.kind == DocumentationNode.Kind.EnumItem - override fun isEnum(): Boolean = docNode.kind == DocumentationNode.Kind.Enum - override fun isMethod(): Boolean = docNode.kind == DocumentationNode.Kind.Function - override fun isInterface(): Boolean = docNode.kind == DocumentationNode.Kind.Interface - override fun isField(): Boolean = docNode.kind == DocumentationNode.Kind.Property - override fun isClass(): Boolean = docN