From 778e2b3f7ff62971e18a49d81a8825e5dd894c2e Mon Sep 17 00:00:00 2001
From: Ilya Ryzhenkov
Date: Mon, 29 Sep 2014 20:54:59 +0400
Subject: Extract content model, make doc model independent from descriptors,
parse doccomments with custom parser, some tests failing due to hanging new
lines.
---
src/Analysis/CommentsAPI.kt | 2 +-
src/Formats/MarkdownFormatService.kt | 4 -
src/Formats/StructuredFormatService.kt | 24 ++--
src/Formats/TextFormatService.kt | 3 -
src/Kotlin/ContentBuilder.kt | 79 +++++++++++++
src/Kotlin/Diagnostics.kt | 40 +++++++
src/Kotlin/DocumentationBuildingVisitor.kt | 122 ++++++++++++++++++++
src/Kotlin/DocumentationContext.kt | 47 ++++++++
src/Kotlin/DocumentationNodeBuilder.kt | 177 +++++++++++++++++++++++++++++
src/Markdown/MarkdownProcessor.kt | 62 ++++++----
src/Markdown/_MarkdownLexer.flex | 40 -------
src/Markdown/markdown.bnf | 42 +++----
src/Model/Content.kt | 88 ++++++++++++++
src/Model/Diagnostics.kt | 40 -------
src/Model/DocumentationBuildingVisitor.kt | 121 --------------------
src/Model/DocumentationContent.kt | 150 ------------------------
src/Model/DocumentationModule.kt | 23 +---
src/Model/DocumentationNode.kt | 7 +-
src/Model/DocumentationNodeBuilder.kt | 153 -------------------------
19 files changed, 627 insertions(+), 597 deletions(-)
create mode 100644 src/Kotlin/ContentBuilder.kt
create mode 100644 src/Kotlin/Diagnostics.kt
create mode 100644 src/Kotlin/DocumentationBuildingVisitor.kt
create mode 100644 src/Kotlin/DocumentationContext.kt
create mode 100644 src/Kotlin/DocumentationNodeBuilder.kt
delete mode 100644 src/Markdown/_MarkdownLexer.flex
create mode 100644 src/Model/Content.kt
delete mode 100644 src/Model/Diagnostics.kt
delete mode 100644 src/Model/DocumentationBuildingVisitor.kt
delete mode 100644 src/Model/DocumentationContent.kt
delete mode 100644 src/Model/DocumentationNodeBuilder.kt
(limited to 'src')
diff --git a/src/Analysis/CommentsAPI.kt b/src/Analysis/CommentsAPI.kt
index 5df4bd38..a17b6aa4 100644
--- a/src/Analysis/CommentsAPI.kt
+++ b/src/Analysis/CommentsAPI.kt
@@ -31,5 +31,5 @@ fun KDoc?.extractText(): String {
comment.substring(0, comment.length - 2)
else
comment).trim()
- }.filter { it.any() }.join("\n")
+ }.join("\n")
}
\ No newline at end of file
diff --git a/src/Formats/MarkdownFormatService.kt b/src/Formats/MarkdownFormatService.kt
index d7530a25..3b87835f 100644
--- a/src/Formats/MarkdownFormatService.kt
+++ b/src/Formats/MarkdownFormatService.kt
@@ -16,10 +16,6 @@ public open class MarkdownFormatService(locationService: LocationService,
return text.htmlEscape()
}
- override public fun formatText(text: RichString): String {
- return text.toString().htmlEscape()
- }
-
override public fun formatCode(code: String): String {
return "`$code`"
}
diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt
index 0c58f553..b1e614f6 100644
--- a/src/Formats/StructuredFormatService.kt
+++ b/src/Formats/StructuredFormatService.kt
@@ -28,19 +28,17 @@ public abstract class StructuredFormatService(val locationService: LocationServi
public abstract fun formatCode(code: String): String
public abstract fun formatBreadcrumbs(items: Iterable): String
- open fun formatText(text: RichString): String {
+ open fun formatText(nodes: Iterable): String {
+ return nodes.map { formatText(it) }.join("")
+ }
+
+ open fun formatText(text: ContentNode): String {
return StringBuilder {
- for (slice in text.slices) {
- val style = slice.style
- when (style) {
- is NormalStyle -> append(slice.text)
- is BoldStyle -> append(formatBold(slice.text))
- is CodeStyle -> append(formatCode(slice.text))
- is LinkStyle -> {
- val node = resolutionService.resolve(style.link)
- val location = locationService.location(node)
- append(formatLink(slice.text, location))
- }
+ for (node in text.children) {
+ when (node) {
+ is ContentText -> append(node.text)
+ is ContentEmphasis -> append(formatBold(formatText(node.children)))
+ else -> append(formatText(node.children))
}
}
}.toString()
@@ -67,7 +65,7 @@ public abstract class StructuredFormatService(val locationService: LocationServi
if (label.startsWith("$"))
continue
appendLine(to, formatBold(formatText(label)))
- appendLine(to, formatText(section.text))
+ appendLine(to, formatText(section))
appendLine(to)
}
}
diff --git a/src/Formats/TextFormatService.kt b/src/Formats/TextFormatService.kt
index 77a0bb65..8fea5a6a 100644
--- a/src/Formats/TextFormatService.kt
+++ b/src/Formats/TextFormatService.kt
@@ -9,12 +9,9 @@ public class TextFormatService(val signatureGenerator: LanguageService) : Format
appendln(signatureGenerator.render(node))
appendln()
appendln(node.doc.summary)
- for (n in 0..node.doc.summary.length())
- append("=")
for ((label,section) in node.doc.sections) {
appendln(label)
- appendln(section.text)
}
}
}
diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt
new file mode 100644
index 00000000..78bd7eaf
--- /dev/null
+++ b/src/Kotlin/ContentBuilder.kt
@@ -0,0 +1,79 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.markdown.MarkdownElementTypes
+import java.util.ArrayDeque
+
+public fun MarkdownTree.toContent(): Content {
+ val nodeStack = ArrayDeque()
+ nodeStack.push(Content())
+
+ visit {(node, text, processChildren) ->
+ val parent = nodeStack.peek()!!
+ val nodeType = node.getTokenType()
+ val nodeText = getNodeText(node)
+ when (nodeType) {
+ MarkdownElementTypes.BULLET_LIST -> {
+ nodeStack.push(ContentList())
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.ORDERED_LIST -> {
+ nodeStack.push(ContentList()) // TODO: add list kind
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.HORIZONTAL_RULE -> {
+ }
+ MarkdownElementTypes.LIST_BLOCK -> {
+ nodeStack.push(ContentBlock())
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.EMPH -> {
+ nodeStack.push(ContentEmphasis())
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.STRONG -> {
+ nodeStack.push(ContentStrong())
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.ANONYMOUS_SECTION -> {
+ nodeStack.push(ContentSection(""))
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.NAMED_SECTION -> {
+ val label = findChildByType(node, MarkdownElementTypes.SECTION_NAME)?.let { getNodeText(it) } ?: ""
+ nodeStack.push(ContentSection(label))
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.PLAIN_TEXT -> {
+ nodeStack.push(ContentText(nodeText))
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.END_LINE -> {
+ nodeStack.push(ContentText(nodeText))
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ MarkdownElementTypes.BLANK_LINE -> {
+ processChildren()
+ }
+ MarkdownElementTypes.PARA -> {
+ nodeStack.push(ContentBlock())
+ processChildren()
+ parent.children.add(nodeStack.pop())
+ }
+ else -> {
+ processChildren()
+ }
+ }
+ }
+ return nodeStack.pop() as Content
+}
+
+
diff --git a/src/Kotlin/Diagnostics.kt b/src/Kotlin/Diagnostics.kt
new file mode 100644
index 00000000..5548bc01
--- /dev/null
+++ b/src/Kotlin/Diagnostics.kt
@@ -0,0 +1,40 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.descriptors.*
+import org.jetbrains.jet.lang.resolve.name.*
+import org.jetbrains.jet.lang.resolve.BindingContext
+
+fun DocumentationContext.checkResolveChildren(node: DocumentationNode) {
+ if (node.kind != DocumentationNode.Kind.Module && node.kind != DocumentationNode.Kind.Package) {
+ // TODO: we don't resolve packages and modules for now
+
+ val parentScope = getResolutionScope(node)
+ for (item in node.details + node.members) {
+ val symbolName = item.name
+ val symbol: DeclarationDescriptor? = when (item.kind) {
+ DocumentationNode.Kind.Modifier -> continue // do not resolve modifiers, they are not names
+ DocumentationNode.Kind.Receiver -> continue // what is receiver's name in platform?
+ DocumentationNode.Kind.Parameter -> parentScope.getLocalVariable(Name.guess(symbolName))
+ DocumentationNode.Kind.Function -> parentScope.getFunctions(Name.guess(symbolName)).firstOrNull()
+ DocumentationNode.Kind.Property -> parentScope.getProperties(Name.guess(symbolName)).firstOrNull()
+ DocumentationNode.Kind.Constructor -> parentScope.getFunctions(Name.guess(symbolName)).firstOrNull()
+ else -> parentScope.getClassifier(Name.guess(symbolName))
+ }
+
+ if (symbol == null)
+ println("WARNING: Cannot resolve $item in ${path(node)}")
+ }
+ }
+
+ for (reference in node.allReferences().filterNot { it.kind == DocumentationReference.Kind.Owner }) {
+ checkResolveChildren(reference.to)
+ }
+}
+
+fun path(node: DocumentationNode): String {
+ val owner = node.owner
+ if (owner != null)
+ return "$node in ${path(owner)}"
+ else
+ return "$node"
+}
\ No newline at end of file
diff --git a/src/Kotlin/DocumentationBuildingVisitor.kt b/src/Kotlin/DocumentationBuildingVisitor.kt
new file mode 100644
index 00000000..5654903b
--- /dev/null
+++ b/src/Kotlin/DocumentationBuildingVisitor.kt
@@ -0,0 +1,122 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.descriptors.*
+import org.jetbrains.jet.lang.resolve.name.*
+import org.jetbrains.jet.lang.resolve.*
+
+public data class DocumentationOptions(val includeNonPublic : Boolean = false)
+
+class DocumentationBuildingVisitor(val context: BindingContext,
+ val options: DocumentationOptions,
+ private val worker: DeclarationDescriptorVisitor)
+: DeclarationDescriptorVisitor {
+
+ private fun visitChildren(descriptors: Collection, data: DocumentationNode) {
+ for (descriptor in descriptors) {
+ visitChild(descriptor, data)
+ }
+ }
+
+ private fun visitChild(descriptor: DeclarationDescriptor?, data: DocumentationNode) {
+ if (descriptor != null && descriptor.isUserCode()) {
+ if (options.includeNonPublic || descriptor !is MemberDescriptor || descriptor.getVisibility().isPublicAPI()) {
+ descriptor.accept(this, data)
+ }
+ }
+ }
+
+ private fun createDocumentation(descriptor: DeclarationDescriptor, data: DocumentationNode): DocumentationNode {
+ return descriptor.accept(worker, data)
+ }
+
+ private fun processCallable(descriptor: CallableDescriptor, data: DocumentationNode): DocumentationNode {
+ val node = createDocumentation(descriptor, data)
+ visitChildren(descriptor.getTypeParameters(), node)
+ visitChild(descriptor.getReceiverParameter(), node)
+ visitChildren(descriptor.getValueParameters(), node)
+ return node
+ }
+
+ public override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = createDocumentation(descriptor!!, data!!)
+ visitChildren(descriptor.getMemberScope().getAllDescriptors(), node)
+ return node
+ }
+
+ public override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = createDocumentation(descriptor!!, data!!)
+ visitChildren(descriptor.getMemberScope().getAllDescriptors(), node)
+ return node
+ }
+
+ public override fun visitVariableDescriptor(descriptor: VariableDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = processCallable(descriptor!!, data!!)
+ return node
+ }
+
+ public override fun visitPropertyDescriptor(descriptor: PropertyDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = processCallable(descriptor!!, data!!)
+ visitChild(descriptor.getGetter(), node)
+ visitChild(descriptor.getSetter(), node)
+ return node
+ }
+
+ public override fun visitFunctionDescriptor(descriptor: FunctionDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = processCallable(descriptor!!, data!!)
+ return node
+ }
+
+ public override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = createDocumentation(descriptor!!, data!!)
+ return node
+ }
+
+ public override fun visitClassDescriptor(descriptor: ClassDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = createDocumentation(descriptor!!, data!!)
+ if (descriptor.getKind() != ClassKind.OBJECT) {
+ // do not go inside object for class object and constructors, they are generated
+ visitChildren(descriptor.getTypeConstructor().getParameters(), node)
+ visitChildren(descriptor.getConstructors(), node)
+ visitChild(descriptor.getClassObjectDescriptor(), node)
+ }
+ visitChildren(descriptor.getDefaultType().getMemberScope().getAllDescriptors(), node)
+ return node
+ }
+
+ public override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: DocumentationNode): DocumentationNode {
+ val node = createDocumentation(descriptor, data)
+ visitChild(descriptor.getPackage(FqName.ROOT), node)
+ return node
+ }
+
+ public override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = visitFunctionDescriptor(descriptor!!, data)
+ return node
+ }
+
+ public override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val classDescriptor = scriptDescriptor!!.getClassDescriptor()
+ val node = visitClassDescriptor(classDescriptor, data)
+ return node
+ }
+
+ public override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = visitVariableDescriptor(descriptor!!, data)
+ return node
+ }
+
+ public override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = visitFunctionDescriptor(descriptor!!, data)
+ return node
+ }
+
+ public override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = visitFunctionDescriptor(descriptor!!, data)
+ return node
+ }
+
+ public override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = createDocumentation(descriptor!!, data!!)
+ return node
+ }
+}
diff --git a/src/Kotlin/DocumentationContext.kt b/src/Kotlin/DocumentationContext.kt
new file mode 100644
index 00000000..1491aa2d
--- /dev/null
+++ b/src/Kotlin/DocumentationContext.kt
@@ -0,0 +1,47 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
+import org.jetbrains.jet.lang.resolve.BindingContext
+import org.jetbrains.jet.lang.resolve.scopes.JetScope
+import org.jetbrains.jet.lang.descriptors.ModuleDescriptor
+import org.jetbrains.jet.lang.resolve.name.FqName
+
+public class DocumentationContext(val bindingContext: BindingContext) {
+ val descriptorToNode = hashMapOf()
+ val nodeToDescriptor = hashMapOf()
+
+ fun register(descriptor: DeclarationDescriptor, node: DocumentationNode) {
+ descriptorToNode.put(descriptor, node)
+ nodeToDescriptor.put(node, descriptor)
+ }
+
+ fun getResolutionScope(node: DocumentationNode): JetScope {
+ val descriptor = nodeToDescriptor[node] ?: throw IllegalArgumentException("Node is not known to this context")
+ return bindingContext.getResolutionScope(descriptor)
+ }
+
+ fun parseDocumentation(descriptor: DeclarationDescriptor): Content {
+ val docText = bindingContext.getDocumentationElements(descriptor).map { it.extractText() }.join("\n")
+ val tree = MarkdownProcessor.parse(docText)
+ println(tree.toTestString())
+ val content = tree.toContent()
+ return content
+ }
+}
+
+fun BindingContext.createDocumentationModule(name: String,
+ module: ModuleDescriptor,
+ packages: Set,
+ options: DocumentationOptions = DocumentationOptions()): DocumentationModule {
+ val documentationModule = DocumentationModule(name)
+ val context = DocumentationContext(this)
+ val visitor = DocumentationNodeBuilder(context)
+ for (packageName in packages) {
+ val pkg = module.getPackage(packageName)
+ pkg!!.accept(DocumentationBuildingVisitor(this, options, visitor), documentationModule)
+ }
+
+ // TODO: Uncomment for resolve verification
+ // checkResolveChildren(documentationModule)
+ return documentationModule
+}
diff --git a/src/Kotlin/DocumentationNodeBuilder.kt b/src/Kotlin/DocumentationNodeBuilder.kt
new file mode 100644
index 00000000..535f037f
--- /dev/null
+++ b/src/Kotlin/DocumentationNodeBuilder.kt
@@ -0,0 +1,177 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
+import org.jetbrains.jet.lang.descriptors.MemberDescriptor
+import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
+import org.jetbrains.jet.lang.types.JetType
+import org.jetbrains.jet.lang.descriptors.Named
+import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor
+import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
+import org.jetbrains.jet.lang.descriptors.ClassDescriptor
+import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
+import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor
+import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
+import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor
+import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor
+import org.jetbrains.jet.lang.descriptors.PackageFragmentDescriptor
+import org.jetbrains.jet.lang.descriptors.ClassKind
+import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
+
+class DocumentationNodeBuilder(val context: DocumentationContext) : DeclarationDescriptorVisitorEmptyBodies() {
+
+ fun reference(from: DocumentationNode, to: DocumentationNode, kind: DocumentationReference.Kind) {
+ from.addReferenceTo(to, kind)
+ if (kind == DocumentationReference.Kind.Link)
+ to.addReferenceTo(from, DocumentationReference.Kind.Link)
+ else
+ to.addReferenceTo(from, DocumentationReference.Kind.Owner)
+ }
+
+ fun addModality(descriptor: MemberDescriptor, data: DocumentationNode) {
+ val modifier = descriptor.getModality().name().toLowerCase()
+ val node = DocumentationNode(modifier, Content.Empty, DocumentationNode.Kind.Modifier)
+ reference(data, node, DocumentationReference.Kind.Detail)
+ }
+
+ fun addVisibility(descriptor: MemberDescriptor, data: DocumentationNode) {
+ val modifier = descriptor.getVisibility().toString()
+ val node = DocumentationNode(modifier, Content.Empty, DocumentationNode.Kind.Modifier)
+ reference(data, node, DocumentationReference.Kind.Detail)
+ }
+
+ fun addType(descriptor: DeclarationDescriptor, t: JetType?, data: DocumentationNode) {
+ if (t == null)
+ return
+ val typeConstructor = t.getConstructor()
+ val classifierDescriptor = typeConstructor.getDeclarationDescriptor()
+ val name = when (classifierDescriptor) {
+ is Named -> classifierDescriptor.getName().asString()
+ else -> ""
+ }
+ val node = DocumentationNode(name, Content.Empty, DocumentationNode.Kind.Type)
+ reference(data, node, DocumentationReference.Kind.Detail)
+
+ for (param in t.getArguments())
+ addType(descriptor, param.getType(), node)
+ }
+
+ override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNode.Kind.Unknown)
+ reference(data!!, node, DocumentationReference.Kind.Link)
+ context.register(descriptor, node)
+ return node
+ }
+
+ override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val node = DocumentationNode(descriptor.getName().asString(), Content.Empty, DocumentationNode.Kind.Receiver)
+ reference(data!!, node, DocumentationReference.Kind.Detail)
+
+ addType(descriptor, descriptor.getType(), node)
+
+ return node
+ }
+
+ override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNode.Kind.Parameter)
+ reference(data!!, node, DocumentationReference.Kind.Detail)
+
+ addType(descriptor, descriptor.getType(), node)
+
+ return node
+ }
+
+ override fun visitClassDescriptor(descriptor: ClassDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, when (descriptor.getKind()) {
+ ClassKind.OBJECT -> org.jetbrains.dokka.DocumentationNode.Kind.Object
+ ClassKind.CLASS_OBJECT -> org.jetbrains.dokka.DocumentationNode.Kind.Object
+ ClassKind.TRAIT -> org.jetbrains.dokka.DocumentationNode.Kind.Interface
+ ClassKind.ENUM_CLASS -> org.jetbrains.dokka.DocumentationNode.Kind.Enum
+ ClassKind.ENUM_ENTRY -> org.jetbrains.dokka.DocumentationNode.Kind.EnumItem
+ else -> DocumentationNode.Kind.Class
+ })
+ reference(data!!, node, DocumentationReference.Kind.Member)
+ addModality(descriptor, node)
+ addVisibility(descriptor, node)
+ context.register(descriptor, node)
+ return node
+ }
+
+ override fun visitFunctionDescriptor(descriptor: FunctionDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNode.Kind.Function)
+ reference(data!!, node, DocumentationReference.Kind.Member)
+
+ addType(descriptor, descriptor.getReturnType(), node)
+ addModality(descriptor, node)
+ addVisibility(descriptor, node)
+ context.register(descriptor, node)
+ return node
+ }
+
+ override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNode.Kind.TypeParameter)
+ reference(data!!, node, DocumentationReference.Kind.Detail)
+ val builtIns = KotlinBuiltIns.getInstance()
+ for (constraint in descriptor.getUpperBounds()) {
+ if (constraint == builtIns.getDefaultBound())
+ continue
+ val constraintNode = DocumentationNode(constraint.toString(), Content.Empty, DocumentationNode.Kind.UpperBound)
+ reference(node, constraintNode, DocumentationReference.Kind.Detail)
+ }
+ for (constraint in descriptor.getLowerBounds()) {
+ if (builtIns.isNothing(constraint))
+ continue
+ val constraintNode = DocumentationNode(constraint.toString(), Content.Empty, DocumentationNode.Kind.LowerBound)
+ reference(node, constraintNode, DocumentationReference.Kind.Detail)
+ }
+ return node
+ }
+
+ override fun visitPropertyDescriptor(descriptor: PropertyDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNode.Kind.Property)
+ reference(data!!, node, DocumentationReference.Kind.Member)
+
+ addType(descriptor, descriptor.getType(), node)
+ addModality(descriptor, node)
+ addVisibility(descriptor, node)
+ context.register(descriptor, node)
+ return node
+ }
+
+ override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val doc = context.parseDocumentation(descriptor)
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNode.Kind.Constructor)
+ reference(data!!, node, DocumentationReference.Kind.Member)
+
+ addVisibility(descriptor, node)
+ context.register(descriptor, node)
+ return node
+ }
+
+ override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val node = DocumentationNode(descriptor.getFqName().asString(), Content.Empty, DocumentationNode.Kind.Package)
+ reference(data!!, node, DocumentationReference.Kind.Member)
+ return node
+ }
+
+ override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ descriptor!!
+ val node = DocumentationNode(descriptor.fqName.asString(), Content.Empty, DocumentationNode.Kind.Package)
+ reference(data!!, node, DocumentationReference.Kind.Member)
+ return node
+ }
+}
\ No newline at end of file
diff --git a/src/Markdown/MarkdownProcessor.kt b/src/Markdown/MarkdownProcessor.kt
index fe6e8436..19d5a8fb 100644
--- a/src/Markdown/MarkdownProcessor.kt
+++ b/src/Markdown/MarkdownProcessor.kt
@@ -9,12 +9,11 @@ import com.intellij.lang.LighterASTNode
import com.intellij.util.diff.FlyweightCapableTreeStructure
import com.intellij.openapi.util.Ref
import org.jetbrains.markdown.lexer.MarkdownLexer
+import com.intellij.psi.tree.IElementType
-public class MarkdownProcessor {
- class object {
- val EXPR_LANGUAGE = object : Language("MARKDOWN") {}
- val DOCUMENT = IFileElementType("DOCUMENT", EXPR_LANGUAGE);
- }
+public object MarkdownProcessor {
+ val EXPR_LANGUAGE = object : Language("MARKDOWN") {}
+ val DOCUMENT = IFileElementType("DOCUMENT", EXPR_LANGUAGE);
public fun parse(markdown: String): MarkdownTree {
val parser = MarkdownParser()
@@ -30,6 +29,28 @@ public class MarkdownTree(private val text: String, private val structure: Flywe
visit(structure.getRoot(), action)
}
+ fun findChildByType(node: LighterASTNode, findType: IElementType) : LighterASTNode? {
+ val ref = Ref.create?>()
+ val count = structure.getChildren(node, ref)
+ val children = ref.get()
+ if (children != null) {
+ for (index in 0..count - 1) {
+ val child = children[index]
+ val nodeType = child.getTokenType()
+ if (nodeType == findType)
+ return child
+ val nestedChild = findChildByType(child, findType)
+ if (nestedChild != null)
+ return nestedChild
+ }
+ }
+ return null
+ }
+
+ fun getNodeText(node: LighterASTNode) : String {
+ return text.substring(node.getStartOffset(), node.getEndOffset())
+ }
+
fun visit(node: LighterASTNode, action: (LighterASTNode, String, visitChildren: () -> Unit) -> Unit) {
action(node, text) {
val ref = Ref.create?>()
@@ -46,7 +67,7 @@ public class MarkdownTree(private val text: String, private val structure: Flywe
}
-public fun MarkdownTree.dump(): String {
+public fun MarkdownTree.toTestString(): String {
val sb = StringBuilder()
var level = 0
visit {(node, text, visitChildren) ->
@@ -64,29 +85,25 @@ public fun MarkdownTree.dump(): String {
public fun MarkdownTree.toHtml(): String {
val sb = StringBuilder()
- var level = 0
visit {(node, text, processChildren) ->
val nodeType = node.getTokenType()
val nodeText = text.substring(node.getStartOffset(), node.getEndOffset())
- val indent = " ".repeat(level * 2)
when (nodeType) {
MarkdownElementTypes.BULLET_LIST -> {
- sb.appendln("$indent")
- level++
+ sb.appendln("")
processChildren()
- level--
- sb.appendln("$indent
")
+ sb.appendln("
")
}
MarkdownElementTypes.HORIZONTAL_RULE -> {
- sb.appendln("$indent
")
+ sb.appendln("
")
}
MarkdownElementTypes.ORDERED_LIST -> {
- sb.appendln("$indent")
+ sb.appendln("")
processChildren()
- sb.appendln("$indent
")
+ sb.appendln("
")
}
MarkdownElementTypes.LIST_BLOCK -> {
- sb.append("$indent")
+ sb.append("")
processChildren()
sb.appendln("")
}
@@ -110,14 +127,9 @@ public fun MarkdownTree.toHtml(): String {
sb.appendln()
}
MarkdownElementTypes.PARA -> {
- sb.appendln("$indent")
- processChildren()
- sb.appendln("$indent
")
- }
- MarkdownElementTypes.VERBATIM -> {
- sb.appendln("$indent")
+ sb.append("")
processChildren()
- sb.appendln("$indent
")
+ sb.appendln("
")
}
else -> {
processChildren()
@@ -129,8 +141,8 @@ public fun MarkdownTree.toHtml(): String {
fun markdownToHtml(markdown: String): String {
- val markdownTree = MarkdownProcessor().parse(markdown)
- val ast = markdownTree.dump()
+ val markdownTree = MarkdownProcessor.parse(markdown)
+ val ast = markdownTree.toTestString()
return markdownTree.toHtml()
}
diff --git a/src/Markdown/_MarkdownLexer.flex b/src/Markdown/_MarkdownLexer.flex
deleted file mode 100644
index 0a15e41a..00000000
--- a/src/Markdown/_MarkdownLexer.flex
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.jetbrains.markdown.lexer;
-
-import com.intellij.lexer.*;
-import com.intellij.psi.tree.IElementType;
-import static org.jetbrains.markdown.MarkdownElementTypes.*;
-
-%%
-
-%{
- public _MarkdownLexer() {
- this((java.io.Reader)null);
- }
-%}
-
-%public
-%class _MarkdownLexer
-%implements FlexLexer
-%function advance
-%type IElementType
-%unicode
-
-Newline="\r"|"\n"|"\r\n"
-Spacechar=[\ \t\f]
-Number=[0-9]+(\.[0-9]*)?
-String=[^~\*_`&\[\]() {
- {Spacechar} { return SPACECHAR; }
- {Newline} { return NEWLINE; }
- "\\357\\273\\277" { return BOM; }
-
- {Number} { return NUMBER; }
- {String} { return STRING; }
- {AnyChar} { return ANYCHAR; }
-
- [^] { return com.intellij.psi.TokenType.BAD_CHARACTER; }
-}
diff --git a/src/Markdown/markdown.bnf b/src/Markdown/markdown.bnf
index ca254295..79e9e0b4 100644
--- a/src/Markdown/markdown.bnf
+++ b/src/Markdown/markdown.bnf
@@ -21,35 +21,35 @@
}
-Document ::= BOM? ( Block )*
+Document ::= BOM? Whitespace* AnonymousSection? (Whitespace* NamedSection)*
-private OptionalSpace ::= Spacechar*
-private RequiredSpace ::= Spacechar+
-private NonindentSpace ::= (" " | " " | " ")?
+AnonymousSection ::= SectionBody
+NamedSection ::= SectionHeader SectionBody
+private SectionHeader ::= '$' SectionName OptionalSpace ':' OptionalSpace
+SectionName ::= SectionNameStart | '{' OptionalSpace SectionNameStart (Spacechar+ String)* OptionalSpace '}'
+private SectionNameStart ::= '$'? String
+SectionBody::= Block*
BlankLine ::= OptionalSpace Newline
Whitespace ::= Spacechar | Newline
+private OptionalSpace ::= Spacechar*
+private NonindentSpace ::= (" " | " " | " ")?
+
EndLine ::= TerminalEndline | NormalEndline
-private NormalEndline ::= OptionalSpace Newline !BlankLine
-private TerminalEndline ::= (OptionalSpace Newline <>) | (OptionalSpace <>)
+private NormalEndline ::= Newline !BlankLine
+private TerminalEndline ::= OptionalSpace <>
private Indent ::= "\t" | " "
-NonblankIndentedLine ::= !BlankLine IndentedLine
-IndentedLine ::= Indent PlainText
// ---- BLOCKS ----
-private Block ::= BlankLine* (
- Para
- | Verbatim
- | OrderedList
- | BulletList
- | Inlines
- )
-
-Para ::= NonindentSpace Inlines (BlankLine | TerminalEndline)
+Block ::= BlankLine* (
+ OrderedList
+ | BulletList
+ | HorizontalRule
+ | Para
+ )
-Verbatim ::= VerbatimItem+
-VerbatimItem ::= BlankLine* NonblankIndentedLine
+Para ::= Inlines (BlankLine | TerminalEndline)?
HorizontalRule ::= NonindentSpace
( '*' OptionalSpace '*' OptionalSpace '*' (OptionalSpace '*')*
@@ -74,8 +74,8 @@ ListContinuationBlock ::= BlankLine* (Indent ListBlock)+
// ---- INLINES ----
private Inlines ::= (!EndLine Inline | EndLine &Inline )+ EndLine?
-private Inline ::= Strong | Emph | Link | PlainText
-PlainText ::= (String | Number | Spacechar)+
+Inline ::= Strong | Emph | Link | PlainText
+PlainText ::= (String | Number | Spacechar+)+
Emph ::= EmphStar | EmphUnderscore
private EmphStar ::= '*' !Whitespace (!'*' Inline)+ '*'
diff --git a/src/Model/Content.kt b/src/Model/Content.kt
new file mode 100644
index 00000000..eb092cb2
--- /dev/null
+++ b/src/Model/Content.kt
@@ -0,0 +1,88 @@
+package org.jetbrains.dokka
+
+import kotlin.properties.Delegates
+
+public abstract class ContentNode {
+ val children = arrayListOf()
+
+ class object {
+ val empty = ContentEmpty
+ }
+
+ fun isEmpty() = children.isEmpty()
+}
+
+public object ContentEmpty : ContentNode( )
+
+public class ContentText(val text : String) : ContentNode( )
+public class ContentBlock() : ContentNode( )
+public class ContentEmphasis() : ContentNode()
+public class ContentStrong() : ContentNode()
+public class ContentList() : ContentNode()
+public class ContentSection(public val label: String) : ContentNode()
+
+public class Content() : ContentNode() {
+ public val sections: Map by Delegates.lazy {
+ val map = hashMapOf()
+ for (child in children) {
+ if (child is ContentSection)
+ map.put(child.label, child)
+ }
+
+ if ("\$summary" !in map && "\$description" !in map) {
+ // no explicit summary and description, convert anonymous section
+ val anonymous = map[""]
+ if (anonymous != null) {
+ map.remove("")
+ val summary = ContentSection("\$summary")
+ val description = ContentSection("\$description")
+
+ val summaryNodes = anonymous.children.take(1)
+ val descriptionNodes = anonymous.children.drop(1)
+
+ if (summaryNodes.any()) {
+ summary.children.addAll(summaryNodes)
+ map.put("\$summary", summary)
+ }
+
+ if (descriptionNodes.any()) {
+ description.children.addAll(descriptionNodes)
+ map.put("\$description", description)
+ }
+ }
+ }
+ map
+ }
+
+ public val summary: ContentNode get() = sections["\$summary"] ?: ContentNode.empty
+ public val description: ContentNode get() = sections["\$description"] ?: ContentNode.empty
+
+ override fun equals(other: Any?): Boolean {
+ if (other !is Content)
+ return false
+ if (sections.size != other.sections.size)
+ return false
+ for (keys in sections.keySet())
+ if (sections[keys] != other.sections[keys])
+ return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ return sections.map { it.hashCode() }.sum()
+ }
+
+ override fun toString(): String {
+ if (sections.isEmpty())
+ return ""
+ return sections.values().joinToString()
+ }
+
+ val isEmpty: Boolean
+ get() = sections.none()
+
+ class object {
+ val Empty = Content()
+ }
+}
diff --git a/src/Model/Diagnostics.kt b/src/Model/Diagnostics.kt
deleted file mode 100644
index 1077da7c..00000000
--- a/src/Model/Diagnostics.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package org.jetbrains.dokka
-
-import org.jetbrains.jet.lang.descriptors.*
-import org.jetbrains.jet.lang.resolve.name.*
-import org.jetbrains.jet.lang.resolve.BindingContext
-
-fun BindingContext.checkResolveChildren(node: DocumentationNode) {
- if (node.kind != DocumentationNode.Kind.Module && node.kind != DocumentationNode.Kind.Package) {
- // TODO: we don't resolve packages and modules for now
-
- val parentScope = getResolutionScope(node.descriptor)
- for (item in node.details + node.members) {
- val symbolName = item.name
- val symbol: DeclarationDescriptor? = when (item.kind) {
- DocumentationNode.Kind.Modifier -> continue // do not resolve modifiers, they are not names
- DocumentationNode.Kind.Receiver -> continue // what is receiver's name in platform?
- DocumentationNode.Kind.Parameter -> parentScope.getLocalVariable(Name.guess(symbolName))
- DocumentationNode.Kind.Function -> parentScope.getFunctions(Name.guess(symbolName)).firstOrNull()
- DocumentationNode.Kind.Property -> parentScope.getProperties(Name.guess(symbolName)).firstOrNull()
- DocumentationNode.Kind.Constructor -> parentScope.getFunctions(Name.guess(symbolName)).firstOrNull()
- else -> parentScope.getClassifier(Name.guess(symbolName))
- }
-
- if (symbol == null)
- println("WARNING: Cannot resolve $item in ${path(node)}")
- }
- }
-
- for (reference in node.allReferences().filterNot { it.kind == DocumentationReference.Kind.Owner }) {
- checkResolveChildren(reference.to)
- }
-}
-
-fun path(node: DocumentationNode): String {
- val owner = node.owner
- if (owner != null)
- return "$node in ${path(owner)}"
- else
- return "$node"
-}
\ No newline at end of file
diff --git a/src/Model/DocumentationBuildingVisitor.kt b/src/Model/DocumentationBuildingVisitor.kt
deleted file mode 100644
index 6118b0f5..00000000
--- a/src/Model/DocumentationBuildingVisitor.kt
+++ /dev/null
@@ -1,121 +0,0 @@
-package org.jetbrains.dokka
-
-import org.jetbrains.jet.lang.descriptors.*
-import org.jetbrains.jet.lang.resolve.name.*
-import org.jetbrains.jet.lang.resolve.*
-
-public data class DocumentationOptions(val includeNonPublic : Boolean = false)
-class DocumentationBuildingVisitor(val context: BindingContext,
- val options: DocumentationOptions,
- private val worker: DeclarationDescriptorVisitor)
-: DeclarationDescriptorVisitor {
-
- private fun visitChildren(descriptors: Collection, data: DocumentationNode) {
- for (descriptor in descriptors) {
- visitChild(descriptor, data)
- }
- }
-
- private fun visitChild(descriptor: DeclarationDescriptor?, data: DocumentationNode) {
- if (descriptor != null && descriptor.isUserCode()) {
- if (options.includeNonPublic || descriptor !is MemberDescriptor || descriptor.getVisibility().isPublicAPI()) {
- descriptor.accept(this, data)
- }
- }
- }
-
- private fun createDocumentation(descriptor: DeclarationDescriptor, data: DocumentationNode): DocumentationNode {
- return descriptor.accept(worker, data)
- }
-
- private fun processCallable(descriptor: CallableDescriptor, data: DocumentationNode): DocumentationNode {
- val node = createDocumentation(descriptor, data)
- visitChildren(descriptor.getTypeParameters(), node)
- visitChild(descriptor.getReceiverParameter(), node)
- visitChildren(descriptor.getValueParameters(), node)
- return node
- }
-
- public override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = createDocumentation(descriptor!!, data!!)
- visitChildren(descriptor.getMemberScope().getAllDescriptors(), node)
- return node
- }
-
- public override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = createDocumentation(descriptor!!, data!!)
- visitChildren(descriptor.getMemberScope().getAllDescriptors(), node)
- return node
- }
-
- public override fun visitVariableDescriptor(descriptor: VariableDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = processCallable(descriptor!!, data!!)
- return node
- }
-
- public override fun visitPropertyDescriptor(descriptor: PropertyDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = processCallable(descriptor!!, data!!)
- visitChild(descriptor.getGetter(), node)
- visitChild(descriptor.getSetter(), node)
- return node
- }
-
- public override fun visitFunctionDescriptor(descriptor: FunctionDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = processCallable(descriptor!!, data!!)
- return node
- }
-
- public override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = createDocumentation(descriptor!!, data!!)
- return node
- }
-
- public override fun visitClassDescriptor(descriptor: ClassDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = createDocumentation(descriptor!!, data!!)
- if (descriptor.getKind() != ClassKind.OBJECT) {
- // do not go inside object for class object and constructors, they are generated
- visitChildren(descriptor.getTypeConstructor().getParameters(), node)
- visitChildren(descriptor.getConstructors(), node)
- visitChild(descriptor.getClassObjectDescriptor(), node)
- }
- visitChildren(descriptor.getDefaultType().getMemberScope().getAllDescriptors(), node)
- return node
- }
-
- public override fun visitModuleDeclaration(descriptor: ModuleDescriptor, data: DocumentationNode): DocumentationNode {
- val node = createDocumentation(descriptor, data)
- visitChild(descriptor.getPackage(FqName.ROOT), node)
- return node
- }
-
- public override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = visitFunctionDescriptor(descriptor!!, data)
- return node
- }
-
- public override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val classDescriptor = scriptDescriptor!!.getClassDescriptor()
- val node = visitClassDescriptor(classDescriptor, data)
- return node
- }
-
- public override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = visitVariableDescriptor(descriptor!!, data)
- return node
- }
-
- public override fun visitPropertyGetterDescriptor(descriptor: PropertyGetterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = visitFunctionDescriptor(descriptor!!, data)
- return node
- }
-
- public override fun visitPropertySetterDescriptor(descriptor: PropertySetterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = visitFunctionDescriptor(descriptor!!, data)
- return node
- }
-
- public override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = createDocumentation(descriptor!!, data!!)
- return node
- }
-}
diff --git a/src/Model/DocumentationContent.kt b/src/Model/DocumentationContent.kt
deleted file mode 100644
index 77e8c764..00000000
--- a/src/Model/DocumentationContent.kt
+++ /dev/null
@@ -1,150 +0,0 @@
-package org.jetbrains.dokka
-
-import org.jetbrains.jet.lang.descriptors.*
-import org.jetbrains.jet.lang.resolve.BindingContext
-
-public class DocumentationContentSection(public val label: String, public val text: RichString) {
- override fun toString(): String {
- return "$label = $text"
- }
-}
-
-public class DocumentationContent(public val sections: Map) {
-
- public val summary: RichString get() = sections["\$summary"]?.text ?: RichString.empty
- public val description: RichString get() = sections["\$description"]?.text ?: RichString.empty
-
- override fun equals(other: Any?): Boolean {
- if (other !is DocumentationContent)
- return false
- if (sections.size != other.sections.size)
- return false
- for (keys in sections.keySet())
- if (sections[keys] != other.sections[keys])
- return false
-
- return true
- }
-
- override fun hashCode(): Int {
- return sections.map { it.hashCode() }.sum()
- }
-
- override fun toString(): String {
- if (sections.isEmpty())
- return ""
- return sections.values().joinToString()
- }
-
- val isEmpty: Boolean
- get() = description.isEmpty() && sections.none()
-
- class object {
- val Empty = DocumentationContent(mapOf())
- }
-}
-
-
-fun BindingContext.getDocumentation(descriptor: DeclarationDescriptor): DocumentationContent {
- val docText = getDocumentationElements(descriptor).map { it.extractText() }.join("\n")
- val sections = docText.parseSections()
- sections.createSummaryAndDescription()
- return DocumentationContent(sections)
-}
-
-fun MutableMap.createSummaryAndDescription() {
-
- val summary = get("\$summary")
- val description = get("\$description")
- if (summary != null && description == null) {
- return
- }
-
- if (summary == null && description != null) {
- return
- }
-
- val unnamed = get("")
- if (unnamed == null) {
- return
- }
-
- val split = unnamed.text.splitBy("\n")
- remove("")
- if (!split.first.isEmpty())
- put("\$summary", DocumentationContentSection("\$summary", split.first))
- if (!split.second.isEmpty())
- put("\$description", DocumentationContentSection("\$description", split.second))
-}
-
-fun String.parseLabel(index: Int): Pair {
- val c = get(index)
- when {
- Character.isJavaIdentifierStart(c) -> {
- for (end in index + 1..length - 1) {
- if (!Character.isJavaIdentifierPart(get(end))) {
- return substring(index, end) to end
- }
- }
- return substring(index, length) to length
- }
- c == '$' -> {
- for (end in index + 1..length - 1) {
- if (Character.isWhitespace(get(end))) {
- return substring(index, end) to end
- }
- }
- return substring(index, length) to length
- }
- c == '{' -> {
- val end = indexOf('}', index + 1)
- return substring(index + 1, end) to end + 1
- }
- }
- return "" to -1
-}
-
-fun String.parseSections(): MutableMap {
- val sections = hashMapOf()
- var currentLabel = ""
- var currentSectionStart = 0
- var currentIndex = 0
-
- while (currentIndex < length) {
- if (get(currentIndex) == '$') {
- val (label, index) = parseLabel(currentIndex + 1)
- if (index != -1 && index < length() && get(index) == ':') {
- // section starts, add previous section
- val currentContent = substring(currentSectionStart, currentIndex).trim()
- val section = DocumentationContentSection(currentLabel, currentContent.toRichString())
- sections.put(section.label, section)
-
- currentLabel = label
- currentIndex = index + 1
- currentSectionStart = currentIndex
- continue
- }
- }
- currentIndex++
-
- }
-
- val currentContent = substring(currentSectionStart, currentIndex).trim()
- val section = DocumentationContentSection(currentLabel, currentContent.toRichString())
- sections.put(section.label, section)
- return sections
-}
-
-fun String.toRichString() : RichString {
- val content = RichString()
- for(index in indices) {
- val ch = get(index)
- when {
- ch == '\\' -> continue
- ch == '*' && index < length-1 && !get(index + 1).isWhitespace() -> ch
- }
- }
-
- content.addSlice(this, NormalStyle)
- return content
-}
\ No newline at end of file
diff --git a/src/Model/DocumentationModule.kt b/src/Model/DocumentationModule.kt
index 78ebda04..6084ea5e 100644
--- a/src/Model/DocumentationModule.kt
+++ b/src/Model/DocumentationModule.kt
@@ -1,30 +1,11 @@
package org.jetbrains.dokka
-import org.jetbrains.jet.lang.resolve.BindingContext
-import org.jetbrains.jet.lang.descriptors.*
-import org.jetbrains.jet.lang.resolve.name.FqName
-
-public class DocumentationModule(name: String, val module: ModuleDescriptor) : DocumentationNode(module, name, DocumentationContent.Empty, DocumentationNode.Kind.Module) {
+public class DocumentationModule(name: String) : DocumentationNode(name, Content.Empty, DocumentationNode.Kind.Module) {
fun merge(other: DocumentationModule): DocumentationModule {
- val model = DocumentationModule(name, module)
+ val model = DocumentationModule(name)
model.addAllReferencesFrom(other)
model.addAllReferencesFrom(this)
return model
}
}
-fun BindingContext.createDocumentationModule(name: String,
- module: ModuleDescriptor,
- packages: Set,
- options : DocumentationOptions = DocumentationOptions()): DocumentationModule {
- val documentationModule = DocumentationModule(name, module)
- val visitor = DocumentationNodeBuilder(this)
- for (packageName in packages) {
- val pkg = module.getPackage(packageName)
- pkg!!.accept(DocumentationBuildingVisitor(this, options, visitor), documentationModule)
- }
-
- // TODO: Uncomment for resolve verification
- // checkResolveChildren(documentationModule)
- return documentationModule
-}
diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt
index c96c383d..198e549b 100644
--- a/src/Model/DocumentationNode.kt
+++ b/src/Model/DocumentationNode.kt
@@ -1,12 +1,9 @@
package org.jetbrains.dokka
-import org.jetbrains.jet.lang.descriptors.*
import java.util.LinkedHashSet
-
-public open class DocumentationNode(val descriptor: DeclarationDescriptor,
- val name: String,
- val doc: DocumentationContent,
+public open class DocumentationNode(val name: String,
+ val doc: Content,
val kind: DocumentationNode.Kind) {
private val references = LinkedHashSet()
diff --git a/src/Model/DocumentationNodeBuilder.kt b/src/Model/DocumentationNodeBuilder.kt
deleted file mode 100644
index f724c444..00000000
--- a/src/Model/DocumentationNodeBuilder.kt
+++ /dev/null
@@ -1,153 +0,0 @@
-package org.jetbrains.dokka
-
-import org.jetbrains.jet.lang.resolve.*
-import org.jetbrains.jet.lang.descriptors.*
-import org.jetbrains.jet.lang.descriptors.impl.*
-import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
-import org.jetbrains.jet.lang.types.JetType
-
-class DocumentationNodeBuilder(val context: BindingContext) : DeclarationDescriptorVisitorEmptyBodies() {
-
- fun reference(from: DocumentationNode, to: DocumentationNode, kind: DocumentationReference.Kind) {
- from.addReferenceTo(to, kind)
- if (kind == DocumentationReference.Kind.Link)
- to.addReferenceTo(from, DocumentationReference.Kind.Link)
- else
- to.addReferenceTo(from, DocumentationReference.Kind.Owner)
- }
-
- fun addModality(descriptor: MemberDescriptor, data: DocumentationNode) {
- val modifier = descriptor.getModality().name().toLowerCase()
- val node = DocumentationNode(descriptor, modifier, DocumentationContent.Empty, DocumentationNode.Kind.Modifier)
- reference(data, node, DocumentationReference.Kind.Detail)
- }
-
- fun addVisibility(descriptor: MemberDescriptor, data: DocumentationNode) {
- val modifier = descriptor.getVisibility().toString()
- val node = DocumentationNode(descriptor, modifier, DocumentationContent.Empty, DocumentationNode.Kind.Modifier)
- reference(data, node, DocumentationReference.Kind.Detail)
- }
-
- fun addType(descriptor: DeclarationDescriptor, t: JetType?, data: DocumentationNode) {
- if (t == null)
- return
- val typeConstructor = t.getConstructor()
- val classifierDescriptor = typeConstructor.getDeclarationDescriptor()
- val name = when (classifierDescriptor) {
- is Named -> classifierDescriptor.getName().asString()
- else -> ""
- }
- val node = DocumentationNode(descriptor, name, DocumentationContent.Empty, DocumentationNode.Kind.Type)
- reference(data, node, DocumentationReference.Kind.Detail)
-
- for (param in t.getArguments())
- addType(descriptor, param.getType(), node)
- }
-
- override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, DocumentationNode.Kind.Unknown)
- reference(data!!, node, DocumentationReference.Kind.Link)
- return node
- }
-
- override fun visitReceiverParameterDescriptor(descriptor: ReceiverParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = DocumentationNode(descriptor!!, descriptor.getName().asString(), DocumentationContent.Empty, DocumentationNode.Kind.Receiver)
- reference(data!!, node, DocumentationReference.Kind.Detail)
-
- addType(descriptor, descriptor.getType(), node)
-
- return node
- }
-
- override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, DocumentationNode.Kind.Parameter)
- reference(data!!, node, DocumentationReference.Kind.Detail)
-
- addType(descriptor, descriptor.getType(), node)
-
- return node
- }
-
- override fun visitClassDescriptor(descriptor: ClassDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, when (descriptor.getKind()) {
- ClassKind.OBJECT -> DocumentationNode.Kind.Object
- ClassKind.CLASS_OBJECT -> DocumentationNode.Kind.Object
- ClassKind.TRAIT -> DocumentationNode.Kind.Interface
- ClassKind.ENUM_CLASS -> DocumentationNode.Kind.Enum
- ClassKind.ENUM_ENTRY -> DocumentationNode.Kind.EnumItem
- else -> DocumentationNode.Kind.Class
- })
- reference(data!!, node, DocumentationReference.Kind.Member)
- addModality(descriptor, node)
- addVisibility(descriptor, node)
- return node
- }
-
- override fun visitFunctionDescriptor(descriptor: FunctionDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, DocumentationNode.Kind.Function)
- reference(data!!, node, DocumentationReference.Kind.Member)
-
- addType(descriptor, descriptor.getReturnType(), node)
- addModality(descriptor, node)
- addVisibility(descriptor, node)
-
- return node
- }
-
- override fun visitTypeParameterDescriptor(descriptor: TypeParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, DocumentationNode.Kind.TypeParameter)
- reference(data!!, node, DocumentationReference.Kind.Detail)
- val builtIns = KotlinBuiltIns.getInstance()
- for (constraint in descriptor.getUpperBounds()) {
- if (constraint == builtIns.getDefaultBound())
- continue
- val constraintNode = DocumentationNode(descriptor, constraint.toString(), DocumentationContent.Empty, DocumentationNode.Kind.UpperBound)
- reference(node, constraintNode, DocumentationReference.Kind.Detail)
- }
- for (constraint in descriptor.getLowerBounds()) {
- if (builtIns.isNothing(constraint))
- continue
- val constraintNode = DocumentationNode(descriptor, constraint.toString(), DocumentationContent.Empty, DocumentationNode.Kind.LowerBound)
- reference(node, constraintNode, DocumentationReference.Kind.Detail)
- }
- return node
- }
-
- override fun visitPropertyDescriptor(descriptor: PropertyDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, DocumentationNode.Kind.Property)
- reference(data!!, node, DocumentationReference.Kind.Member)
-
- addType(descriptor, descriptor.getType(), node)
- addModality(descriptor, node)
- addVisibility(descriptor, node)
- return node
- }
-
- override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val doc = context.getDocumentation(descriptor!!)
- val node = DocumentationNode(descriptor, descriptor.getName().asString(), doc, DocumentationNode.Kind.Constructor)
- reference(data!!, node, DocumentationReference.Kind.Member)
-
- addVisibility(descriptor, node)
-
- return node
- }
-
- override fun visitPackageViewDescriptor(descriptor: PackageViewDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = DocumentationNode(descriptor!!, descriptor.getFqName().asString(), DocumentationContent.Empty, DocumentationNode.Kind.Package)
- reference(data!!, node, DocumentationReference.Kind.Member)
- return node
- }
-
- override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor?, data: DocumentationNode?): DocumentationNode? {
- val node = DocumentationNode(descriptor!!, descriptor.fqName.asString(), DocumentationContent.Empty, DocumentationNode.Kind.Package)
- reference(data!!, node, DocumentationReference.Kind.Member)
- return node
- }
-}
--
cgit