diff options
-rw-r--r-- | src/Kotlin/DocumentationBuilder.kt | 2 | ||||
-rw-r--r-- | src/Kotlin/DocumentationBuildingVisitor.kt | 127 | ||||
-rw-r--r-- | src/Kotlin/DocumentationContext.kt | 60 | ||||
-rw-r--r-- | src/Kotlin/DocumentationNodeBuilder.kt | 207 | ||||
-rw-r--r-- | src/Kotlin/ResolveReferences.kt | 75 |
5 files changed, 2 insertions, 469 deletions
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index 211697cd..d8162c44 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -12,6 +12,8 @@ import org.jetbrains.jet.lang.resolve.scopes.JetScope import org.jetbrains.jet.lang.psi.JetFile import org.jetbrains.jet.lang.resolve.name.FqName +public data class DocumentationOptions(val includeNonPublic: Boolean = false) + class DocumentationBuilder(val context: BindingContext, val options: DocumentationOptions) { val descriptorToNode = hashMapOf<DeclarationDescriptor, DocumentationNode>() val nodeToDescriptor = hashMapOf<DocumentationNode, DeclarationDescriptor>() diff --git a/src/Kotlin/DocumentationBuildingVisitor.kt b/src/Kotlin/DocumentationBuildingVisitor.kt deleted file mode 100644 index 81ac2430..00000000 --- a/src/Kotlin/DocumentationBuildingVisitor.kt +++ /dev/null @@ -1,127 +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<DocumentationNode, DocumentationNode>) -: DeclarationDescriptorVisitor<DocumentationNode, DocumentationNode> { - - val visibleToDocumentation = setOf(Visibilities.INTERNAL, Visibilities.PROTECTED, Visibilities.PUBLIC) - - private fun visitChildren(descriptors: Collection<DeclarationDescriptor>, 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() in visibleToDocumentation) { - 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.getExtensionReceiverParameter(), 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 = createDocumentation(descriptor!!, data!!) - visitChildren(descriptor.getValueParameters(), node) - 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 deleted file mode 100644 index b13f08ea..00000000 --- a/src/Kotlin/DocumentationContext.kt +++ /dev/null @@ -1,60 +0,0 @@ -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 - -/** - * Context for documentation generation. - * - * Holds information about relations between [nodes](DocumentationNode) and [descriptors](DeclarationDescriptor) during documentation generation - * - * $bindingContext: symbol resolution context - */ -public class DocumentationContext(val bindingContext: BindingContext) { - val descriptorToNode = hashMapOf<DeclarationDescriptor, DocumentationNode>() - val nodeToDescriptor = hashMapOf<DocumentationNode, DeclarationDescriptor>() - - val relations = hashMapOf<DocumentationNode, DeclarationDescriptor>() - - fun attach(node: DocumentationNode, descriptor: DeclarationDescriptor) { - relations.put(node, descriptor) - } - - 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<FqName>, - options: DocumentationOptions = DocumentationOptions()): DocumentationModule { - val documentationModule = DocumentationModule(name) - val builder = DocumentationBuilder(this, options) - with(builder) { - for (packageName in packages) { - val pkg = module.getPackage(packageName) - if (pkg != null) - documentationModule.appendChild(pkg, DocumentationReference.Kind.Member) - } - } - builder.resolveReferences(documentationModule) - return documentationModule -} diff --git a/src/Kotlin/DocumentationNodeBuilder.kt b/src/Kotlin/DocumentationNodeBuilder.kt deleted file mode 100644 index a2686b00..00000000 --- a/src/Kotlin/DocumentationNodeBuilder.kt +++ /dev/null @@ -1,207 +0,0 @@ -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 -import org.jetbrains.jet.lang.types.TypeProjection -import org.jetbrains.jet.lang.types.Variance -import org.jetbrains.dokka.DocumentationNode.Kind - -class DocumentationNodeBuilder(val context: DocumentationContext) : DeclarationDescriptorVisitorEmptyBodies<DocumentationNode, DocumentationNode>() { - - fun reference(from: DocumentationNode, to: DocumentationNode, kind: DocumentationReference.Kind) { - from.addReferenceTo(to, kind) - when (kind) { - DocumentationReference.Kind.Detail -> to.addReferenceTo(from, DocumentationReference.Kind.Owner) - DocumentationReference.Kind.Member -> to.addReferenceTo(from, DocumentationReference.Kind.Owner) - DocumentationReference.Kind.Owner -> to.addReferenceTo(from, DocumentationReference.Kind.Member) - } - } - - 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 addSupertypes(descriptor: ClassDescriptor, data: DocumentationNode) { - val superTypes = descriptor.getTypeConstructor().getSupertypes() - for (superType in superTypes) { - if (superType.toString() != "Any") - addType(superType, data, DocumentationNode.Kind.Supertype) - } - } - - fun addProjection(projection: TypeProjection, data: DocumentationNode, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type) { - val prefix = when (projection.getProjectionKind()) { - Variance.IN_VARIANCE -> "in " - Variance.OUT_VARIANCE -> "out " - else -> "" - } - addType(projection.getType(), data, kind, prefix) - } - - fun addType(jetType: JetType?, data: DocumentationNode, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type, prefix : String = "") { - if (jetType == null) - return - val classifierDescriptor = jetType.getConstructor().getDeclarationDescriptor() - val name = when (classifierDescriptor) { - is Named -> prefix + classifierDescriptor.getName().asString() + if (jetType.isNullable()) "?" else "" - else -> "<anonymous>" - } - val node = DocumentationNode(name, Content.Empty, kind) - if (classifierDescriptor != null) - context.attach(node, classifierDescriptor) - - reference(data, node, DocumentationReference.Kind.Detail) - for (typeArgument in jetType.getArguments()) - addProjection(typeArgument, 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.Member) - 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.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.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 -> Kind.Object - ClassKind.CLASS_OBJECT -> Kind.Object - ClassKind.TRAIT -> Kind.Interface - ClassKind.ENUM_CLASS -> Kind.Enum - ClassKind.ENUM_ENTRY -> Kind.EnumItem - else -> Kind.Class - }) - reference(data!!, node, DocumentationReference.Kind.Member) - addModality(descriptor, node) - addVisibility(descriptor, node) - addSupertypes(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.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 name = descriptor.getName().asString() - val prefix = when (descriptor.getVariance()) { - Variance.IN_VARIANCE -> "in " - Variance.OUT_VARIANCE -> "out " - else -> "" - } - - val node = DocumentationNode(prefix + name, 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.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("<init>", 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/Kotlin/ResolveReferences.kt b/src/Kotlin/ResolveReferences.kt deleted file mode 100644 index 1349c69e..00000000 --- a/src/Kotlin/ResolveReferences.kt +++ /dev/null @@ -1,75 +0,0 @@ -package org.jetbrains.dokka - -import org.jetbrains.jet.lang.resolve.name.Name - -/** - * Generates cross-references for documentation such as extensions for a type, inheritors, etc - * - * $receiver: [DocumentationContext] for node/descriptor resolutions - * $node: [DocumentationNode] to visit - */ -public fun DocumentationContext.resolveReferences(node: DocumentationNode) { - node.details(DocumentationNode.Kind.Receiver).forEach { detail -> - val receiverType = detail.detail(DocumentationNode.Kind.Type) - val descriptor = relations[receiverType] - if (descriptor != null) { - val typeNode = descriptorToNode[descriptor] - // if typeNode is null, extension is to external type like in a library - // should we create dummy node here? - typeNode?.addReferenceTo(node, DocumentationReference.Kind.Extension) - } - } - node.details(DocumentationNode.Kind.Supertype).forEach { detail -> - val descriptor = relations[detail] - if (descriptor != null) { - val typeNode = descriptorToNode[descriptor] - typeNode?.addReferenceTo(node, DocumentationReference.Kind.Inheritor) - } - } - node.details.forEach { detail -> - val descriptor = relations[detail] - if (descriptor != null) { - val typeNode = descriptorToNode[descriptor] - if (typeNode != null) { - detail.addReferenceTo(typeNode, DocumentationReference.Kind.Link) - } - } - } - - resolveContentLinks(node, node.doc) - - for (child in node.members) { - resolveReferences(child) - } - for (child in node.details) { - resolveReferences(child) - } -} - -fun DocumentationContext.resolveContentLinks(node: DocumentationNode, content: ContentNode) { - val snapshot = content.children.toList() - for (child in snapshot) { - if (child is ContentExternalLink) { - val referenceText = child.href - if (Name.isValidIdentifier(referenceText)) { - val scope = getResolutionScope(node) - val symbolName = Name.guess(referenceText) - val symbol = scope.getLocalVariable(symbolName) ?: - scope.getProperties(symbolName).firstOrNull() ?: - scope.getFunctions(symbolName).firstOrNull() ?: - scope.getClassifier(symbolName) - - if (symbol != null) { - val targetNode = descriptorToNode[symbol] - val contentLink = if (targetNode != null) ContentNodeLink(targetNode) else ContentExternalLink("#") - - val index = content.children.indexOf(child) - content.children.remove(index) - contentLink.children.addAll(child.children) - content.children.add(index, contentLink) - } - } - } - resolveContentLinks(node, child) - } -}
\ No newline at end of file |