aboutsummaryrefslogtreecommitdiff
path: root/src/Model
diff options
context:
space:
mode:
Diffstat (limited to 'src/Model')
-rw-r--r--src/Model/DocumentationBuilder.kt73
-rw-r--r--src/Model/DocumentationBuildingVisitor.kt121
-rw-r--r--src/Model/DocumentationModel.kt67
3 files changed, 261 insertions, 0 deletions
diff --git a/src/Model/DocumentationBuilder.kt b/src/Model/DocumentationBuilder.kt
new file mode 100644
index 00000000..77f74eb2
--- /dev/null
+++ b/src/Model/DocumentationBuilder.kt
@@ -0,0 +1,73 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.resolve.*
+import org.jetbrains.jet.lang.psi.*
+import org.jetbrains.jet.lang.descriptors.*
+import org.jetbrains.jet.lang.descriptors.impl.*
+
+fun BindingContext.createDocumentation(file: JetFile): DocumentationModel {
+ val model = DocumentationModel()
+ val packageFragment = getPackageFragment(file)
+ if (packageFragment == null) throw IllegalArgumentException("File $file should have package fragment")
+
+ val visitor = DocumentationBuilderVisitor(this)
+ visitDescriptor(packageFragment, model, visitor)
+
+ return model
+}
+
+class DocumentationBuilderVisitor(val context: BindingContext) : DeclarationDescriptorVisitorEmptyBodies<DocumentationNode, DocumentationNode>() {
+
+ override fun visitDeclarationDescriptor(descriptor: DeclarationDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val doc = context.getDocumentation(descriptor!!).extractText()
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Unknown)
+ data?.addReferenceTo(node, DocumentationReferenceKind.Member)
+ return node
+ }
+
+ override fun visitValueParameterDescriptor(descriptor: ValueParameterDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val doc = context.getDocumentation(descriptor!!).extractText()
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Parameter)
+ data?.addReferenceTo(node, DocumentationReferenceKind.Detail)
+ return node
+ }
+
+ override fun visitClassDescriptor(descriptor: ClassDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val doc = context.getDocumentation(descriptor!!).extractText()
+ val node = DocumentationNode(descriptor.getName().asString(), doc,
+ when (descriptor.getKind()) {
+ ClassKind.OBJECT -> DocumentationNodeKind.Object
+ else -> DocumentationNodeKind.Class
+ }
+ )
+ data?.addReferenceTo(node, DocumentationReferenceKind.Member)
+ return node
+ }
+
+ override fun visitFunctionDescriptor(descriptor: FunctionDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val doc = context.getDocumentation(descriptor!!).extractText()
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Function)
+ data?.addReferenceTo(node, DocumentationReferenceKind.Member)
+ return node
+ }
+
+ override fun visitPropertyDescriptor(descriptor: PropertyDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val doc = context.getDocumentation(descriptor!!).extractText()
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Property)
+ data?.addReferenceTo(node, DocumentationReferenceKind.Member)
+ return node
+ }
+
+ override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val doc = context.getDocumentation(descriptor!!).extractText()
+ val node = DocumentationNode(descriptor.getName().asString(), doc, DocumentationNodeKind.Constructor)
+ data?.addReferenceTo(node, DocumentationReferenceKind.Member)
+ return node
+ }
+
+ override fun visitPackageFragmentDescriptor(descriptor: PackageFragmentDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = DocumentationNode(descriptor!!.fqName.asString(), "", DocumentationNodeKind.Package)
+ data?.addReferenceTo(node, DocumentationReferenceKind.Member)
+ return node
+ }
+}
diff --git a/src/Model/DocumentationBuildingVisitor.kt b/src/Model/DocumentationBuildingVisitor.kt
new file mode 100644
index 00000000..e7b3fc09
--- /dev/null
+++ b/src/Model/DocumentationBuildingVisitor.kt
@@ -0,0 +1,121 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.descriptors.*
+import org.jetbrains.jet.lang.resolve.name.FqName
+
+class DocumentationBuildingVisitor(private val worker: DeclarationDescriptorVisitor<DocumentationNode, DocumentationNode>)
+: DeclarationDescriptorVisitor<DocumentationNode, DocumentationNode> {
+
+ private fun visitChildren(descriptors: Collection<DeclarationDescriptor>, data: DocumentationNode) {
+ for (descriptor in descriptors) {
+ if (descriptor.isUserCode())
+ descriptor.accept(this, data)
+ }
+ }
+
+ private fun visitChild(descriptor: DeclarationDescriptor?, data: DocumentationNode) {
+ if (descriptor != null && descriptor.isUserCode())
+ 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)
+ }
+ val members = descriptor.getDefaultType().getMemberScope().getAllDescriptors().filter {
+ it !is CallableMemberDescriptor || it.isUserCode()
+ }
+ visitChildren(members, 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(constructorDescriptor: ConstructorDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = visitFunctionDescriptor(constructorDescriptor, data)
+ return node
+ }
+
+ public override fun visitScriptDescriptor(scriptDescriptor: ScriptDescriptor?, data: DocumentationNode?): DocumentationNode? {
+ val node = visitClassDescriptor(scriptDescriptor!!.getClassDescriptor(), 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
+ }
+}
+
+public fun visitDescriptor(descriptor: DeclarationDescriptor, data: DocumentationNode, visitor: DeclarationDescriptorVisitor<DocumentationNode, DocumentationNode>): DocumentationNode {
+ return descriptor.accept(DocumentationBuildingVisitor(visitor), data)
+}
diff --git a/src/Model/DocumentationModel.kt b/src/Model/DocumentationModel.kt
new file mode 100644
index 00000000..0113eb18
--- /dev/null
+++ b/src/Model/DocumentationModel.kt
@@ -0,0 +1,67 @@
+package org.jetbrains.dokka
+
+import org.jetbrains.jet.lang.resolve.BindingContext
+import org.jetbrains.jet.lang.psi.JetFile
+
+public enum class DocumentationNodeKind {
+ Unknown
+
+ Package
+ Class
+ Object
+ Constructor
+ Function
+ Property
+ Parameter
+ TypeParameter
+ Exception
+
+ Page
+ Model
+}
+
+public enum class DocumentationReferenceKind {
+ Member
+ Detail
+ Owner
+ Link
+ Override
+}
+
+public open class DocumentationNode(val name: String, val doc: String, val kind: DocumentationNodeKind) {
+ private val references = arrayListOf<DocumentationReference>()
+
+ public val owner: DocumentationNode
+ get() = references(DocumentationReferenceKind.Owner).single().to
+ public val details: List<DocumentationNode>
+ get() = references(DocumentationReferenceKind.Detail).map { it.to }
+ public val members: List<DocumentationNode>
+ get() = references(DocumentationReferenceKind.Member).map { it.to }
+ public val links: List<DocumentationNode>
+ get() = references(DocumentationReferenceKind.Link).map { it.to }
+
+ // TODO: Should we allow node mutation? Model merge will copy by ref, so references are transparent, which could nice
+ public fun addReferenceTo(to: DocumentationNode, kind: DocumentationReferenceKind) {
+ references.add(DocumentationReference(this, to, kind))
+ }
+
+ public fun addAllReferencesFrom(other: DocumentationNode) {
+ references.addAll(other.references)
+ }
+
+ public fun references(kind: DocumentationReferenceKind): List<DocumentationReference> = references.filter { it.kind == kind }
+}
+
+public class DocumentationModel : DocumentationNode("model", "", DocumentationNodeKind.Model) {
+ fun merge(other: DocumentationModel): DocumentationModel {
+ val model = DocumentationModel()
+ model.addAllReferencesFrom(other)
+ model.addAllReferencesFrom(this)
+ return model
+ }
+
+ public val nodes: List<DocumentationNode>
+ get() = members
+}
+
+public data class DocumentationReference(val from: DocumentationNode, val to: DocumentationNode, val kind: DocumentationReferenceKind)