From cedaeb48615cf6f9aae3cbcd3917e9827ca5e67f Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 29 Dec 2014 20:50:26 +0100 Subject: put class object functions and properties in main class block --- src/Kotlin/DocumentationBuilder.kt | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src/Kotlin') diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index d2c07200..aeea4a55 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -161,11 +161,13 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati if (getKind() != ClassKind.OBJECT) { node.appendChildren(getTypeConstructor().getParameters(), DocumentationReference.Kind.Detail) node.appendChildren(getConstructors(), DocumentationReference.Kind.Member) - val classObjectDescriptor = getClassObjectDescriptor() - if (classObjectDescriptor != null) - node.appendChild(classObjectDescriptor, DocumentationReference.Kind.Member) } node.appendChildren(getDefaultType().getMemberScope().getAllDescriptors(), DocumentationReference.Kind.Member) + val classObjectDescriptor = getClassObjectDescriptor() + if (classObjectDescriptor != null) { + node.appendChildren(classObjectDescriptor.getDefaultType().getMemberScope().getAllDescriptors(), + DocumentationReference.Kind.Member) + } register(this, node) return node } @@ -177,8 +179,11 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati return node } + private fun DeclarationDescriptor.inClassObject() = + getContainingDeclaration().let { it is ClassDescriptor && it.getKind() == ClassKind.CLASS_OBJECT } + fun FunctionDescriptor.build(): DocumentationNode { - val node = DocumentationNode(this, Kind.Function) + val node = DocumentationNode(this, if (inClassObject()) Kind.ClassObjectFunction else Kind.Function) node.appendChildren(getTypeParameters(), DocumentationReference.Kind.Detail) getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } @@ -201,7 +206,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati } fun PropertyDescriptor.build(): DocumentationNode { - val node = DocumentationNode(this, Kind.Property) + val node = DocumentationNode(this, if (inClassObject()) Kind.ClassObjectProperty else Kind.Property) node.appendChildren(getTypeParameters(), DocumentationReference.Kind.Detail) getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } node.appendType(getReturnType()) -- cgit From 2016ba9a4c6fbd1cc1644eff6d7ac606d624bd23 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Mon, 29 Dec 2014 21:05:53 +0100 Subject: render class object properties and functions --- src/Kotlin/KotlinLanguageService.kt | 12 +++++--- test/data/format/classWithClassObject.kt | 7 +++++ test/data/format/classWithClassObject.md | 53 ++++++++++++++++++++++++++++++++ test/src/TestAPI.kt | 3 +- test/src/format/MarkdownFormatTest.kt | 6 ++++ 5 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 test/data/format/classWithClassObject.kt create mode 100644 test/data/format/classWithClassObject.md (limited to 'src/Kotlin') diff --git a/src/Kotlin/KotlinLanguageService.kt b/src/Kotlin/KotlinLanguageService.kt index c9275879..a4016849 100644 --- a/src/Kotlin/KotlinLanguageService.kt +++ b/src/Kotlin/KotlinLanguageService.kt @@ -31,8 +31,10 @@ class KotlinLanguageService : LanguageService { DocumentationNode.Kind.Modifier -> renderModifier(node) DocumentationNode.Kind.Constructor, - DocumentationNode.Kind.Function -> renderFunction(node) - DocumentationNode.Kind.Property -> renderProperty(node) + DocumentationNode.Kind.Function, + DocumentationNode.Kind.ClassObjectFunction -> renderFunction(node) + DocumentationNode.Kind.Property, + DocumentationNode.Kind.ClassObjectProperty -> renderProperty(node) else -> ContentText("${node.kind}: ${node.name}") } } @@ -189,7 +191,8 @@ class KotlinLanguageService : LanguageService { renderModifiersForNode(node) when (node.kind) { DocumentationNode.Kind.Constructor -> identifier(node.owner!!.name) - DocumentationNode.Kind.Function -> keyword("fun ") + DocumentationNode.Kind.Function, + DocumentationNode.Kind.ClassObjectFunction -> keyword("fun ") else -> throw IllegalArgumentException("Node $node is not a function-like object") } renderTypeParametersForNode(node) @@ -216,7 +219,8 @@ class KotlinLanguageService : LanguageService { private fun ContentNode.renderProperty(node: DocumentationNode) { renderModifiersForNode(node) when (node.kind) { - DocumentationNode.Kind.Property -> keyword("val ") + DocumentationNode.Kind.Property, + DocumentationNode.Kind.ClassObjectProperty -> keyword("val ") else -> throw IllegalArgumentException("Node $node is not a property") } renderTypeParametersForNode(node) diff --git a/test/data/format/classWithClassObject.kt b/test/data/format/classWithClassObject.kt new file mode 100644 index 00000000..459efad6 --- /dev/null +++ b/test/data/format/classWithClassObject.kt @@ -0,0 +1,7 @@ +class Klass() { + class object { + val x = 1 + + fun foo() {} + } +} diff --git a/test/data/format/classWithClassObject.md b/test/data/format/classWithClassObject.md new file mode 100644 index 00000000..10cac365 --- /dev/null +++ b/test/data/format/classWithClassObject.md @@ -0,0 +1,53 @@ +[test](out.md) / [](out.md) / [Klass](out.md) + + +# Klass + + +``` +class Klass +``` + + + + +### Constructors + + +| +[<init>](out.md) + + | +``` +public Klass() +``` + + | + + +### Class Object Properties + + +| +[x](out.md) + + | +``` +val x: Int +``` + + | + + +### Class Object Functions + + +| +[foo](out.md) + + | +``` +fun foo(): Unit +``` + + | diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt index a16a0b57..6f4e34c2 100644 --- a/test/src/TestAPI.kt +++ b/test/src/TestAPI.kt @@ -55,8 +55,9 @@ public fun verifyOutput(path: String, outputGenerator: (DocumentationModule, Str verifyModel(path) { val output = StringBuilder() outputGenerator(it, output) + val trimmedOutput = output.toString().split('\n').map { it.trimTrailing() }.join("\n") val expectedOutput = File(path.replace(".kt", ".md")).readText() - assertEquals(expectedOutput, output.toString()) + assertEquals(expectedOutput.trimTrailing(), trimmedOutput) } } diff --git a/test/src/format/MarkdownFormatTest.kt b/test/src/format/MarkdownFormatTest.kt index beb727da..ea501c53 100644 --- a/test/src/format/MarkdownFormatTest.kt +++ b/test/src/format/MarkdownFormatTest.kt @@ -13,4 +13,10 @@ public class MarkdownFormatTest { markdownService.appendNodes(tempLocation, output, model.members.single().members) } } + + Test fun classWithClassObject() { + verifyOutput("test/data/format/classWithClassObject.kt") { model, output -> + markdownService.appendNodes(tempLocation, output, model.members.single().members) + } + } } -- cgit From feca80b65581e688b1e9a3e807dfce2e17fd4a13 Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Tue, 30 Dec 2014 13:41:02 +0100 Subject: add test for html escaping; fix special characters eaten from output --- src/Kotlin/ContentBuilder.kt | 19 ++++++++++++++++++- test/data/format/htmlEscaping.html | 12 ++++++++++++ test/data/format/htmlEscaping.kt | 4 ++++ test/src/format/HtmlFormatTest.kt | 6 ++++++ 4 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 test/data/format/htmlEscaping.html create mode 100644 test/data/format/htmlEscaping.kt (limited to 'src/Kotlin') diff --git a/src/Kotlin/ContentBuilder.kt b/src/Kotlin/ContentBuilder.kt index 0c82a522..0143feed 100644 --- a/src/Kotlin/ContentBuilder.kt +++ b/src/Kotlin/ContentBuilder.kt @@ -101,6 +101,17 @@ public fun DocumentationBuilder.buildContent(tree: MarkdownNode, descriptor: Dec processChildren() parent.append(nodeStack.pop()) } + MarkdownTokenTypes.COLON -> { + // TODO fix markdown parser + if (!isColonAfterSectionLabel(node)) { + parent.append(ContentText(node.text)) + } + } + MarkdownTokenTypes.DOUBLE_QUOTE, + MarkdownTokenTypes.LT, + MarkdownTokenTypes.GT -> { + parent.append(ContentText(node.text)) + } else -> { processChildren() } @@ -147,4 +158,10 @@ private fun DocumentationBuilder.resolveInScope(functionName: String, scope: Jet } return symbol -} \ No newline at end of file +} + +private fun isColonAfterSectionLabel(node: MarkdownNode): Boolean { + val parent = node.parent + return parent != null && parent.type == MarkdownElementTypes.SECTION && parent.children.size() >= 2 && + node == parent.children[1]; +} diff --git a/test/data/format/htmlEscaping.html b/test/data/format/htmlEscaping.html new file mode 100644 index 00000000..4f1409c4 --- /dev/null +++ b/test/data/format/htmlEscaping.html @@ -0,0 +1,12 @@ + + + + +test /  / x
+
+

x

+
fun <T> x(): T?

Special characters: < is "less than", > is "greater than", & is "ampersand"

+
+
+ + diff --git a/test/data/format/htmlEscaping.kt b/test/data/format/htmlEscaping.kt new file mode 100644 index 00000000..8778d8a5 --- /dev/null +++ b/test/data/format/htmlEscaping.kt @@ -0,0 +1,4 @@ +/** + * Special characters: < is "less than", > is "greater than", & is "ampersand" + */ +fun x(): T? = null diff --git a/test/src/format/HtmlFormatTest.kt b/test/src/format/HtmlFormatTest.kt index 758c6e7b..a47b5774 100644 --- a/test/src/format/HtmlFormatTest.kt +++ b/test/src/format/HtmlFormatTest.kt @@ -12,4 +12,10 @@ public class HtmlFormatTest { htmlService.appendNodes(tempLocation, output, model.members.single().members) } } + + Test fun htmlEscaping() { + verifyOutput("test/data/format/htmlEscaping.kt", ".html") { model, output -> + htmlService.appendNodes(tempLocation, output, model.members.single().members) + } + } } -- cgit