aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Formats/HtmlFormatService.kt4
-rw-r--r--src/Formats/MarkdownFormatService.kt9
-rw-r--r--src/Formats/StructuredFormatService.kt29
-rw-r--r--src/Kotlin/DocumentationBuilder.kt101
-rw-r--r--src/Kotlin/KotlinLanguageService.kt54
-rw-r--r--src/Model/Content.kt1
-rw-r--r--src/Model/DocumentationNode.kt10
-rw-r--r--src/Model/DocumentationReference.kt2
-rw-r--r--src/main.kt12
-rw-r--r--test/data/classes/annotatedClass.kt1
-rw-r--r--test/data/classes/annotatedClassWithAnnotationParameters.kt1
-rw-r--r--test/data/classes/javaAnnotationClass.kt5
-rw-r--r--test/data/format/annotationClass.kt1
-rw-r--r--test/data/format/annotationClass.md18
-rw-r--r--test/data/format/annotationParams.kt1
-rw-r--r--test/data/format/annotationParams.md12
-rw-r--r--test/data/format/annotations.kt6
-rw-r--r--test/data/format/annotations.md30
-rw-r--r--test/data/format/classWithClassObject.md6
-rw-r--r--test/data/format/deprecated.class.html46
-rw-r--r--test/data/format/deprecated.kt5
-rw-r--r--test/data/format/deprecated.package.html44
-rw-r--r--test/data/format/extensions.class.md16
-rw-r--r--test/data/format/extensions.kt19
-rw-r--r--test/data/format/extensions.package.md18
-rw-r--r--test/data/functions/annotatedFunction.kt2
-rw-r--r--test/data/functions/annotatedFunctionWithAnnotationParameters.kt1
-rw-r--r--test/data/functions/functionWithAnnotatedParam.kt2
-rw-r--r--test/data/functions/functionWithReceiver.kt8
-rw-r--r--test/data/properties/annotatedProperty.kt1
-rw-r--r--test/data/properties/propertyWithReceiver.kt2
-rw-r--r--test/src/TestAPI.kt11
-rw-r--r--test/src/format/HtmlFormatTest.kt9
-rw-r--r--test/src/format/MarkdownFormatTest.kt27
-rw-r--r--test/src/model/ClassTest.kt56
-rw-r--r--test/src/model/FunctionTest.kt89
-rw-r--r--test/src/model/PropertyTest.kt26
37 files changed, 626 insertions, 59 deletions
diff --git a/src/Formats/HtmlFormatService.kt b/src/Formats/HtmlFormatService.kt
index b23e4a45..f76693dc 100644
--- a/src/Formats/HtmlFormatService.kt
+++ b/src/Formats/HtmlFormatService.kt
@@ -93,6 +93,10 @@ public open class HtmlFormatService(locationService: LocationService,
return "<emph>${text}</emph>"
}
+ override fun formatStrikethrough(text: String): String {
+ return "<s>${text}</s>"
+ }
+
override fun formatCode(code: String): String {
return "<code>${code}</code>"
}
diff --git a/src/Formats/MarkdownFormatService.kt b/src/Formats/MarkdownFormatService.kt
index 96f64eec..a2e3ce55 100644
--- a/src/Formats/MarkdownFormatService.kt
+++ b/src/Formats/MarkdownFormatService.kt
@@ -46,6 +46,10 @@ public open class MarkdownFormatService(locationService: LocationService,
return "*$text*"
}
+ override fun formatStrikethrough(text: String): String {
+ return "~~$text~~"
+ }
+
override public fun formatLink(text: String, location: Location): String {
return "[$text](${location.path})"
}
@@ -106,14 +110,15 @@ public open class MarkdownFormatService(locationService: LocationService,
}
override fun appendTableRow(to: StringBuilder, body: () -> Unit) {
- to.append("| ")
+ to.append("|")
body()
to.appendln()
}
override fun appendTableCell(to: StringBuilder, body: () -> Unit) {
+ to.append(" ")
body()
- to.append(" | ")
+ to.append(" |")
}
var outlineLevel = 0
diff --git a/src/Formats/StructuredFormatService.kt b/src/Formats/StructuredFormatService.kt
index 2d326854..977d81d0 100644
--- a/src/Formats/StructuredFormatService.kt
+++ b/src/Formats/StructuredFormatService.kt
@@ -28,6 +28,7 @@ public abstract class StructuredFormatService(val locationService: LocationServi
public abstract fun formatLink(text: String, href: String): String
public open fun formatLink(link: FormatLink): String = formatLink(formatText(link.text), link.location)
public abstract fun formatStrong(text: String): String
+ public abstract fun formatStrikethrough(text: String): String
public abstract fun formatEmphasis(text: String): String
public abstract fun formatCode(code: String): String
public abstract fun formatList(text: String): String
@@ -46,6 +47,7 @@ public abstract class StructuredFormatService(val locationService: LocationServi
is ContentKeyword -> append(formatKeyword(content.text))
is ContentIdentifier -> append(formatIdentifier(content.text))
is ContentStrong -> append(formatStrong(formatText(location, content.children)))
+ is ContentStrikethrough -> append(formatStrikethrough(formatText(location, content.children)))
is ContentCode -> append(formatCode(formatText(location, content.children)))
is ContentEmphasis -> append(formatEmphasis(formatText(location, content.children)))
is ContentList -> append(formatList(formatText(location, content.children)))
@@ -116,6 +118,17 @@ public abstract class StructuredFormatService(val locationService: LocationServi
for ((summary, items) in breakdownBySummary) {
items.forEach {
appendBlockCode(to, formatText(location, languageService.render(it)))
+ val deprecation = it.deprecation
+ if (deprecation != null) {
+ val deprecationParameter = deprecation.details(DocumentationNode.Kind.Parameter).firstOrNull()
+ val deprecationValue = deprecationParameter?.details(DocumentationNode.Kind.Value)?.firstOrNull()
+ if (deprecationValue != null) {
+ to.append(formatStrong("Deprecated: "))
+ appendLine(to, formatText(deprecationValue.name.trim("\"")))
+ } else {
+ appendLine(to, formatStrong("Deprecated"))
+ }
+ }
}
appendLine(to, summary)
appendLine(to)
@@ -178,18 +191,25 @@ public abstract class StructuredFormatService(val locationService: LocationServi
for ((breadcrumbs, items) in breakdownByLocation) {
appendLine(to, breadcrumbs)
appendLine(to)
- appendLocation(location, to, items)
+ appendLocation(location, to, items.filter { it.kind != DocumentationNode.Kind.ExternalClass })
}
for (node in nodes) {
+ if (node.kind == DocumentationNode.Kind.ExternalClass) {
+ appendSection(location, "Extensions for ${node.name}", node.members, node, to)
+ continue
+ }
+
appendSection(location, "Packages", node.members(DocumentationNode.Kind.Package), node, to)
appendSection(location, "Types", node.members.filter {
it.kind in setOf(
DocumentationNode.Kind.Class,
DocumentationNode.Kind.Interface,
DocumentationNode.Kind.Enum,
- DocumentationNode.Kind.Object)
+ DocumentationNode.Kind.Object,
+ DocumentationNode.Kind.AnnotationClass)
}, node, to)
+ appendSection(location, "Extensions for External Classes", node.members(DocumentationNode.Kind.ExternalClass), node, to)
appendSection(location, "Constructors", node.members(DocumentationNode.Kind.Constructor), node, to)
appendSection(location, "Properties", node.members(DocumentationNode.Kind.Property), node, to)
appendSection(location, "Functions", node.members(DocumentationNode.Kind.Function), node, to)
@@ -200,14 +220,17 @@ public abstract class StructuredFormatService(val locationService: LocationServi
it.kind !in setOf(
DocumentationNode.Kind.Class,
DocumentationNode.Kind.Interface,
+ DocumentationNode.Kind.Enum,
DocumentationNode.Kind.Object,
+ DocumentationNode.Kind.AnnotationClass,
DocumentationNode.Kind.Constructor,
DocumentationNode.Kind.Property,
DocumentationNode.Kind.Package,
DocumentationNode.Kind.Function,
DocumentationNode.Kind.PropertyAccessor,
DocumentationNode.Kind.ClassObjectProperty,
- DocumentationNode.Kind.ClassObjectFunction
+ DocumentationNode.Kind.ClassObjectFunction,
+ DocumentationNode.Kind.ExternalClass
)
}, node, to)
appendSection(location, "Extensions", node.extensions, node, to)
diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt
index af8d0ad6..8b6b19d3 100644
--- a/src/Kotlin/DocumentationBuilder.kt
+++ b/src/Kotlin/DocumentationBuilder.kt
@@ -6,9 +6,21 @@ import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.resolve.lazy.*
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+import org.jetbrains.kotlin.descriptors.annotations.Annotated
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
+import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
+import com.intellij.openapi.util.text.StringUtil
+import org.jetbrains.kotlin.descriptors.impl.EnumEntrySyntheticClassDescriptor
public data class DocumentationOptions(val includeNonPublic: Boolean = false)
+private fun isSamePackage(descriptor1: DeclarationDescriptor, descriptor2: DeclarationDescriptor): Boolean {
+ val package1 = DescriptorUtils.getParentOfType(descriptor1, javaClass<PackageFragmentDescriptor>())
+ val package2 = DescriptorUtils.getParentOfType(descriptor2, javaClass<PackageFragmentDescriptor>())
+ return package1 != null && package2 != null && package1.fqName == package2.fqName
+}
+
class DocumentationBuilder(val session: ResolveSession, val options: DocumentationOptions) {
val visibleToDocumentation = setOf(Visibilities.INTERNAL, Visibilities.PROTECTED, Visibilities.PUBLIC)
val descriptorToNode = hashMapOf<DeclarationDescriptor, DocumentationNode>()
@@ -73,11 +85,20 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
fun DocumentationNode.appendSupertypes(descriptor: ClassDescriptor) {
val superTypes = descriptor.getTypeConstructor().getSupertypes()
for (superType in superTypes) {
- if (superType.toString() != "Any")
+ if (!ignoreSupertype(superType))
appendType(superType, DocumentationNode.Kind.Supertype)
}
}
+ private fun ignoreSupertype(superType: JetType): Boolean {
+ val superClass = superType.getConstructor()?.getDeclarationDescriptor() as? ClassDescriptor
+ if (superClass != null) {
+ val fqName = DescriptorUtils.getFqNameSafe(superClass).asString()
+ return fqName == "kotlin.Annotation" || fqName == "kotlin.Enum" || fqName == "kotlin.Any"
+ }
+ return false
+ }
+
fun DocumentationNode.appendProjection(projection: TypeProjection, kind: DocumentationNode.Kind = DocumentationNode.Kind.Type) {
val prefix = when (projection.getProjectionKind()) {
Variance.IN_VARIANCE -> "in "
@@ -104,6 +125,16 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
node.appendProjection(typeArgument)
}
+ fun DocumentationNode.appendAnnotations(annotated: Annotated) {
+ annotated.getAnnotations().forEach {
+ val annotationNode = it.build()
+ if (annotationNode != null) {
+ append(annotationNode,
+ if (annotationNode.name == "deprecated") DocumentationReference.Kind.Deprecation else DocumentationReference.Kind.Annotation)
+ }
+ }
+ }
+
fun DocumentationNode.appendChild(descriptor: DeclarationDescriptor, kind: DocumentationReference.Kind) {
// do not include generated code
if (descriptor is CallableMemberDescriptor && descriptor.getKind() != CallableMemberDescriptor.Kind.DECLARATION)
@@ -120,15 +151,35 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
descriptors.forEach { descriptor -> appendChild(descriptor, kind) }
}
+ fun DocumentationNode.getParentForPackageMember(descriptor: DeclarationDescriptor,
+ externalClassNodes: MutableMap<FqName, DocumentationNode>): DocumentationNode {
+ if (descriptor is CallableMemberDescriptor) {
+ val extensionClassDescriptor = descriptor.getExtensionClassDescriptor()
+ if (extensionClassDescriptor != null && !isSamePackage(descriptor, extensionClassDescriptor)) {
+ val fqName = DescriptorUtils.getFqNameFromTopLevelClass(extensionClassDescriptor)
+ return externalClassNodes.getOrPut(fqName, {
+ val newNode = DocumentationNode(fqName.asString(), Content.Empty, Kind.ExternalClass)
+ append(newNode, DocumentationReference.Kind.Member)
+ newNode
+ })
+ }
+ }
+ return this
+ }
+
fun DocumentationNode.appendFragments(fragments: Collection<PackageFragmentDescriptor>) {
val descriptors = hashMapOf<String, List<DeclarationDescriptor>>()
for ((name, parts) in fragments.groupBy { it.fqName }) {
descriptors.put(name.asString(), parts.flatMap { it.getMemberScope().getAllDescriptors() })
}
for ((packageName, declarations) in descriptors) {
- println(" package $packageName: ${declarations.count()} nodes")
+ println(" package $packageName: ${declarations.count()} declarations")
val packageNode = DocumentationNode(packageName, Content.Empty, Kind.Package)
- packageNode.appendChildren(declarations, DocumentationReference.Kind.Member)
+ val externalClassNodes = hashMapOf<FqName, DocumentationNode>()
+ declarations.forEach { descriptor ->
+ val parent = packageNode.getParentForPackageMember(descriptor, externalClassNodes)
+ parent.appendChild(descriptor, DocumentationReference.Kind.Member)
+ }
append(packageNode, DocumentationReference.Kind.Member)
}
}
@@ -153,6 +204,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
ClassKind.CLASS_OBJECT -> Kind.Object
ClassKind.TRAIT -> Kind.Interface
ClassKind.ENUM_CLASS -> Kind.Enum
+ ClassKind.ANNOTATION_CLASS -> Kind.AnnotationClass
ClassKind.ENUM_ENTRY -> Kind.EnumItem
else -> Kind.Class
}
@@ -168,6 +220,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
node.appendChildren(classObjectDescriptor.getDefaultType().getMemberScope().getAllDescriptors(),
DocumentationReference.Kind.Member)
}
+ node.appendAnnotations(this)
register(this, node)
return node
}
@@ -182,6 +235,15 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
private fun DeclarationDescriptor.inClassObject() =
getContainingDeclaration().let { it is ClassDescriptor && it.getKind() == ClassKind.CLASS_OBJECT }
+ fun CallableMemberDescriptor.getExtensionClassDescriptor(): ClassifierDescriptor? {
+ val extensionReceiver = getExtensionReceiverParameter()
+ if (extensionReceiver != null) {
+ val type = extensionReceiver.getType()
+ return type.getConstructor().getDeclarationDescriptor() as? ClassDescriptor
+ }
+ return null
+ }
+
fun FunctionDescriptor.build(): DocumentationNode {
val node = DocumentationNode(this, if (inClassObject()) Kind.ClassObjectFunction else Kind.Function)
@@ -189,6 +251,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) }
node.appendChildren(getValueParameters(), DocumentationReference.Kind.Detail)
node.appendType(getReturnType())
+ node.appendAnnotations(this)
register(this, node)
return node
@@ -210,6 +273,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
node.appendChildren(getTypeParameters(), DocumentationReference.Kind.Detail)
getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) }
node.appendType(getReturnType())
+ node.appendAnnotations(this)
getGetter()?.let {
if (!it.isDefault())
node.appendChild(it, DocumentationReference.Kind.Member)
@@ -226,6 +290,7 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
fun ValueParameterDescriptor.build(): DocumentationNode {
val node = DocumentationNode(this, Kind.Parameter)
node.appendType(getType())
+ node.appendAnnotations(this)
register(this, node)
return node
}
@@ -264,6 +329,36 @@ class DocumentationBuilder(val session: ResolveSession, val options: Documentati
return node
}
+ fun AnnotationDescriptor.build(): DocumentationNode? {
+ val annotationClass = getType().getConstructor().getDeclarationDescriptor()
+ if (ErrorUtils.isError(annotationClass)) {
+ return null
+ }
+ val node = DocumentationNode(annotationClass.getName().asString(), Content.Empty, DocumentationNode.Kind.Annotation)
+ val arguments = getAllValueArguments().toList().sortBy { it.first.getIndex() }
+ arguments.forEach {
+ val valueNode = it.second.build()
+ if (valueNode != null) {
+ val paramNode = DocumentationNode(it.first.getName().asString(), Content.Empty, DocumentationNode.Kind.Parameter)
+ paramNode.append(valueNode, DocumentationReference.Kind.Detail)
+ node.append(paramNode, DocumentationReference.Kind.Detail)
+ }
+ }
+ return node
+ }
+
+ fun CompileTimeConstant<out Any?>.build(): DocumentationNode? {
+ val value = getValue()
+ val valueString = when(value) {
+ is String ->
+ "\"" + StringUtil.escapeStringCharacters(value) + "\""
+ is EnumEntrySyntheticClassDescriptor ->
+ value.getContainingDeclaration().getName().asString() + "." + value.getName()
+ else -> value?.toString()
+ }
+ return if (valueString != null) DocumentationNode(valueString, Content.Empty, DocumentationNode.Kind.Value) else null
+ }
+
/**
* Generates cross-references for documentation such as extensions for a type, inheritors, etc
*
diff --git a/src/Kotlin/KotlinLanguageService.kt b/src/Kotlin/KotlinLanguageService.kt
index a4016849..40f47639 100644
--- a/src/Kotlin/KotlinLanguageService.kt
+++ b/src/Kotlin/KotlinLanguageService.kt
@@ -1,28 +1,18 @@
package org.jetbrains.dokka
-import org.jetbrains.dokka.symbol
-import org.jetbrains.dokka.text
-import org.jetbrains.dokka.identifier
-import org.jetbrains.dokka.link
-import org.jetbrains.dokka.keyword
-import org.jetbrains.dokka.LanguageService
-import org.jetbrains.dokka.DocumentationNode
-import org.jetbrains.dokka.ContentNode
-import org.jetbrains.dokka
-import org.jetbrains.dokka.ContentText
-
/**
* Implements [LanguageService] and provides rendering of symbols in Kotlin language
*/
class KotlinLanguageService : LanguageService {
override fun render(node: DocumentationNode): ContentNode {
- return dokka.content {
+ return content {
when (node.kind) {
DocumentationNode.Kind.Package -> renderPackage(node)
DocumentationNode.Kind.Class,
DocumentationNode.Kind.Interface,
DocumentationNode.Kind.Enum,
DocumentationNode.Kind.EnumItem,
+ DocumentationNode.Kind.AnnotationClass,
DocumentationNode.Kind.Object -> renderClass(node)
DocumentationNode.Kind.TypeParameter -> renderTypeParameter(node)
@@ -135,6 +125,7 @@ class KotlinLanguageService : LanguageService {
}
private fun ContentNode.renderParameter(node: DocumentationNode) {
+ renderAnnotationsForNode(node)
identifier(node.name)
symbol(": ")
val parameterType = node.detail(DocumentationNode.Kind.Type)
@@ -171,24 +162,46 @@ class KotlinLanguageService : LanguageService {
}
}
+ private fun ContentNode.renderAnnotationsForNode(node: DocumentationNode) {
+ node.annotations.forEach {
+ renderAnnotation(it)
+ }
+ }
+
+ private fun ContentNode.renderAnnotation(node: DocumentationNode) {
+ identifier(node.name)
+ val parameters = node.details(DocumentationNode.Kind.Parameter)
+ if (!parameters.isEmpty()) {
+ symbol("(")
+ renderList(parameters) {
+ text(it.detail(DocumentationNode.Kind.Value).name)
+ }
+ symbol(")")
+ }
+ text(" ")
+ }
+
private fun ContentNode.renderClass(node: DocumentationNode) {
renderModifiersForNode(node)
+ renderAnnotationsForNode(node)
when (node.kind) {
DocumentationNode.Kind.Class -> keyword("class ")
DocumentationNode.Kind.Interface -> keyword("trait ")
DocumentationNode.Kind.Enum -> keyword("enum class ")
+ DocumentationNode.Kind.AnnotationClass -> keyword("annotation class ")
DocumentationNode.Kind.EnumItem -> keyword("enum val ")
DocumentationNode.Kind.Object -> keyword("object ")
else -> throw IllegalArgumentException("Node $node is not a class-like object")
}
- identifier(node.name)
+ identifierOrDeprecated(node)
renderTypeParametersForNode(node)
renderSupertypesForNode(node)
}
private fun ContentNode.renderFunction(node: DocumentationNode) {
renderModifiersForNode(node)
+ renderAnnotationsForNode(node)
when (node.kind) {
DocumentationNode.Kind.Constructor -> identifier(node.owner!!.name)
DocumentationNode.Kind.Function,
@@ -203,7 +216,7 @@ class KotlinLanguageService : LanguageService {
}
if (node.kind != org.jetbrains.dokka.DocumentationNode.Kind.Constructor)
- identifier(node.name)
+ identifierOrDeprecated(node)
symbol("(")
renderList(node.details(DocumentationNode.Kind.Parameter)) {
@@ -218,6 +231,7 @@ class KotlinLanguageService : LanguageService {
private fun ContentNode.renderProperty(node: DocumentationNode) {
renderModifiersForNode(node)
+ renderAnnotationsForNode(node)
when (node.kind) {
DocumentationNode.Kind.Property,
DocumentationNode.Kind.ClassObjectProperty -> keyword("val ")
@@ -230,8 +244,18 @@ class KotlinLanguageService : LanguageService {
symbol(".")
}
- identifier(node.name)
+ identifierOrDeprecated(node)
symbol(": ")
renderType(node.detail(DocumentationNode.Kind.Type))
}
+
+ fun ContentNode.identifierOrDeprecated(node: DocumentationNode) {
+ if (node.deprecation != null) {
+ val strike = ContentStrikethrough()
+ strike.identifier(node.name)
+ append(strike)
+ } else {
+ identifier(node.name)
+ }
+ }
} \ No newline at end of file
diff --git a/src/Model/Content.kt b/src/Model/Content.kt
index e1c1ef78..8491fd88 100644
--- a/src/Model/Content.kt
+++ b/src/Model/Content.kt
@@ -27,6 +27,7 @@ public class ContentSymbol(val text: String) : ContentNode()
public class ContentParagraph() : ContentBlock()
public class ContentEmphasis() : ContentBlock()
public class ContentStrong() : ContentBlock()
+public class ContentStrikethrough() : ContentBlock()
public class ContentCode() : ContentBlock()
public class ContentBlockCode() : ContentBlock()
public class ContentNodeLink(val node : DocumentationNode) : ContentBlock()
diff --git a/src/Model/DocumentationNode.kt b/src/Model/DocumentationNode.kt
index 86d2ee04..635d1db9 100644
--- a/src/Model/DocumentationNode.kt
+++ b/src/Model/DocumentationNode.kt
@@ -30,6 +30,10 @@ public open class DocumentationNode(val name: String,
get() = references(DocumentationReference.Kind.Inheritor).map { it.to }
public val links: List<DocumentationNode>
get() = references(DocumentationReference.Kind.Link).map { it.to }
+ public val annotations: List<DocumentationNode>
+ get() = references(DocumentationReference.Kind.Annotation).map { it.to }
+ public val deprecation: DocumentationNode?
+ get() = references(DocumentationReference.Kind.Deprecation).singleOrNull()?.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: DocumentationReference.Kind) {
@@ -62,6 +66,7 @@ public open class DocumentationNode(val name: String,
Class
Interface
Enum
+ AnnotationClass
EnumItem
Object
@@ -85,6 +90,11 @@ public open class DocumentationNode(val name: String,
Modifier
Module
+
+ ExternalClass
+ Annotation
+
+ Value
}
}
diff --git a/src/Model/DocumentationReference.kt b/src/Model/DocumentationReference.kt
index 1849fe08..bd40f0f5 100644
--- a/src/Model/DocumentationReference.kt
+++ b/src/Model/DocumentationReference.kt
@@ -9,6 +9,8 @@ public data class DocumentationReference(val from: DocumentationNode, val to: Do
Extension
Inheritor
Override
+ Annotation
+ Deprecation
}
}
diff --git a/src/main.kt b/src/main.kt
index f540e3dc..24853be5 100644
--- a/src/main.kt
+++ b/src/main.kt
@@ -98,17 +98,7 @@ public fun main(args: Array<String>) {
}
val documentationModule = DocumentationModule(arguments.moduleName, moduleContent)
-
- val descriptors = hashMapOf<String, List<DeclarationDescriptor>>()
- for ((name, parts) in fragments.groupBy { it.fqName }) {
- descriptors.put(name.asString(), parts.flatMap { it.getMemberScope().getAllDescriptors() })
- }
- for ((packageName, declarations) in descriptors) {
- println(" package $packageName: ${declarations.count()} nodes")
- val packageNode = DocumentationNode(packageName, Content.Empty, DocumentationNode.Kind.Package)
- packageNode.appendChildren(declarations, DocumentationReference.Kind.Member)
- documentationModule.append(packageNode, DocumentationReference.Kind.Member)
- }
+ documentationModule.appendFragments(fragments)
documentationBuilder.resolveReferences(documentationModule)
documentationModule
}
diff --git a/test/data/classes/annotatedClass.kt b/test/data/classes/annotatedClass.kt
new file mode 100644
index 00000000..62c6f0ec
--- /dev/null
+++ b/test/data/classes/annotatedClass.kt
@@ -0,0 +1 @@
+data class Foo() {}
diff --git a/test/data/classes/annotatedClassWithAnnotationParameters.kt b/test/data/classes/annotatedClassWithAnnotationParameters.kt
new file mode 100644
index 00000000..1af97e75
--- /dev/null
+++ b/test/data/classes/annotatedClassWithAnnotationParameters.kt
@@ -0,0 +1 @@
+deprecated("should no longer be used") class Foo() {}
diff --git a/test/data/classes/javaAnnotationClass.kt b/test/data/classes/javaAnnotationClass.kt
new file mode 100644
index 00000000..c5f5cac4
--- /dev/null
+++ b/test/data/classes/javaAnnotationClass.kt
@@ -0,0 +1,5 @@
+import java.lang.annotation.Retention
+import java.lang.annotation.RetentionPolicy
+
+Retention(RetentionPolicy.SOURCE)
+public annotation class throws()
diff --git a/test/data/format/annotationClass.kt b/test/data/format/annotationClass.kt
new file mode 100644
index 00000000..89d494fb
--- /dev/null
+++ b/test/data/format/annotationClass.kt
@@ -0,0 +1 @@
+annotation class fancy
diff --git a/test/data/format/annotationClass.md b/test/data/format/annotationClass.md
new file mode 100644
index 00000000..301eff08
--- /dev/null
+++ b/test/data/format/annotationClass.md
@@ -0,0 +1,18 @@
+[test](out.md) / [](out.md) / [fancy](out.md)
+
+
+# fancy
+
+
+```
+annotation class fancy
+```
+
+
+
+
+### Constructors
+
+
+| [&lt;init&gt;](out.md) | `public fancy()` |
+
diff --git a/test/data/format/annotationParams.kt b/test/data/format/annotationParams.kt
new file mode 100644
index 00000000..ee5b524a
--- /dev/null
+++ b/test/data/format/annotationParams.kt
@@ -0,0 +1 @@
+inlineOptions(InlineOption.LOCAL_CONTINUE_AND_BREAK) fun f() {}
diff --git a/test/data/format/annotationParams.md b/test/data/format/annotationParams.md
new file mode 100644
index 00000000..6bbdc0e5
--- /dev/null
+++ b/test/data/format/annotationParams.md
@@ -0,0 +1,12 @@
+[test](out.md) / [](out.md) / [f](out.md)
+
+
+# f
+
+
+```
+inlineOptions([InlineOption.LOCAL_CONTINUE_AND_BREAK]) fun f(): Unit
+```
+
+
+
diff --git a/test/data/format/annotations.kt b/test/data/format/annotations.kt
new file mode 100644
index 00000000..9356d4ca
--- /dev/null
+++ b/test/data/format/annotations.kt
@@ -0,0 +1,6 @@
+data class Foo {
+ inline fun bar([noinline] notInlined: () -> Unit) {
+ }
+
+ inline val x: Int
+}
diff --git a/test/data/format/annotations.md b/test/data/format/annotations.md
new file mode 100644
index 00000000..e745213e
--- /dev/null
+++ b/test/data/format/annotations.md
@@ -0,0 +1,30 @@
+[test](out.md) / [](out.md) / [Foo](out.md)
+
+
+# Foo
+
+
+```
+data class Foo
+```
+
+
+
+
+### Constructors
+
+
+| [&lt;init&gt;](out.md) | `public Foo()` |
+
+
+### Properties
+
+
+| [x](out.md) | `inline val x: Int` |
+
+
+### Functions
+
+
+| [bar](out.md) | `inline fun bar(noinline notInlined: () -&gt; Unit): Unit` |
+
diff --git a/test/data/format/classWithClassObject.md b/test/data/format/classWithClassObject.md
index f694a76f..796ecce2 100644
--- a/test/data/format/classWithClassObject.md
+++ b/test/data/format/classWithClassObject.md
@@ -14,17 +14,17 @@ class Klass
### Constructors
-| [&lt;init&gt;](out.md) | `public Klass()` |
+| [&lt;init&gt;](out.md) | `public Klass()` |
### Class Object Properties
-| [x](out.md) | `val x: Int` |
+| [x](out.md) | `val x: Int` |
### Class Object Functions
-| [foo](out.md) | `fun foo(): Unit` |
+| [foo](out.md) | `fun foo(): Unit` |
diff --git a/test/data/format/deprecated.class.html b/test/data/format/deprecated.class.html
new file mode 100644
index 00000000..87599082
--- /dev/null
+++ b/test/data/format/deprecated.class.html
@@ -0,0 +1,46 @@
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+<a href="out.html">test</a>&nbsp;/&nbsp;<a href="out.html"></a>&nbsp;/&nbsp;<a href="out.html">C</a><br/>
+<br/>
+<h1>C</h1>
+<pre><code><span class="keyword">class </span><s><span class="identifier">C</span></s></code></pre><strong>Deprecated: </strong>This class sucks<br/>
+<br/>
+<br/>
+<a href="out.html">test</a>&nbsp;/&nbsp;<a href="out.html"></a>&nbsp;/&nbsp;<a href="out.html">f</a><br/>
+<br/>
+<h1>f</h1>
+<pre><code><span class="keyword">fun </span><s><span class="identifier">f</span></s><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></pre><strong>Deprecated: </strong>This function sucks<br/>
+<br/>
+<br/>
+<a href="out.html">test</a>&nbsp;/&nbsp;<a href="out.html"></a>&nbsp;/&nbsp;<a href="out.html">p</a><br/>
+<br/>
+<h1>p</h1>
+<pre><code><span class="keyword">val </span><s><span class="identifier">p</span></s><span class="symbol">: </span><span class="identifier">Int</span></code></pre><strong>Deprecated: </strong>This property sucks<br/>
+<br/>
+<br/>
+<h3>Constructors</h3>
+<table>
+<tbody>
+<tr>
+<td>
+<a href="out.html">&lt;init&gt;</a></td>
+<td>
+<code><span class="keyword">public</span> <span class="identifier">C</span><span class="symbol">(</span><span class="symbol">)</span></code></td>
+</tr>
+</tbody>
+</table>
+<h3>Accessors</h3>
+<table>
+<tbody>
+<tr>
+<td>
+<a href="out.html">get</a></td>
+<td>
+<code></code></td>
+</tr>
+</tbody>
+</table>
+</BODY>
+</HTML>
diff --git a/test/data/format/deprecated.kt b/test/data/format/deprecated.kt
new file mode 100644
index 00000000..9ee2c1d6
--- /dev/null
+++ b/test/data/format/deprecated.kt
@@ -0,0 +1,5 @@
+deprecated("This class sucks") class C() { }
+
+deprecated("This function sucks") fun f() { }
+
+deprecated("This property sucks") val p: Int get() = 0
diff --git a/test/data/format/deprecated.package.html b/test/data/format/deprecated.package.html
new file mode 100644
index 00000000..cf563a8b
--- /dev/null
+++ b/test/data/format/deprecated.package.html
@@ -0,0 +1,44 @@
+<HTML>
+<HEAD>
+</HEAD>
+<BODY>
+<a href="out.html">test</a>&nbsp;/&nbsp;<a href="out.html"></a><br/>
+<br/>
+<h1></h1>
+<pre><code><span class="keyword">package</span> <span class="identifier"></span></code></pre><br/>
+<br/>
+<h3>Types</h3>
+<table>
+<tbody>
+<tr>
+<td>
+<a href="out.html">C</a></td>
+<td>
+<code><span class="keyword">class </span><s><span class="identifier">C</span></s></code></td>
+</tr>
+</tbody>
+</table>
+<h3>Properties</h3>
+<table>
+<tbody>
+<tr>
+<td>
+<a href="out.html">p</a></td>
+<td>
+<code><span class="keyword">val </span><s><span class="identifier">p</span></s><span class="symbol">: </span><span class="identifier">Int</span></code></td>
+</tr>
+</tbody>
+</table>
+<h3>Functions</h3>
+<table>
+<tbody>
+<tr>
+<td>
+<a href="out.html">f</a></td>
+<td>
+<code><span class="keyword">fun </span><s><span class="identifier">f</span></s><span class="symbol">(</span><span class="symbol">)</span><span class="symbol">: </span><span class="identifier">Unit</span></code></td>
+</tr>
+</tbody>
+</table>
+</BODY>
+</HTML>
diff --git a/test/data/format/extensions.class.md b/test/data/format/extensions.class.md
new file mode 100644
index 00000000..a9747756
--- /dev/null
+++ b/test/data/format/extensions.class.md
@@ -0,0 +1,16 @@
+[test](out.md) / [foo](out.md) / [String](out.md)
+
+
+### Extensions for String
+
+
+| [fn](out.md) | `fun String.fn(): Unit`
+`fun String.fn(x: Int): Unit`
+Function with receiver
+
+ |
+| [foobar](out.md) | `val String.foobar: Int`
+Property with receiver.
+
+ |
+
diff --git a/test/data/format/extensions.kt b/test/data/format/extensions.kt
new file mode 100644
index 00000000..6f2eff9d
--- /dev/null
+++ b/test/data/format/extensions.kt
@@ -0,0 +1,19 @@
+package foo
+
+/**
+ * Function with receiver
+ */
+fun String.fn() {
+}
+
+/**
+ * Function with receiver
+ */
+fun String.fn(x: Int) {
+}
+
+/**
+ * Property with receiver.
+ */
+val String.foobar: Int
+ get() = size() * 2
diff --git a/test/data/format/extensions.package.md b/test/data/format/extensions.package.md
new file mode 100644
index 00000000..13f40457
--- /dev/null
+++ b/test/data/format/extensions.package.md
@@ -0,0 +1,18 @@
+[test](out.md) / [foo](out.md)
+
+
+# foo
+
+
+```
+package foo
+```
+
+
+
+
+### Extensions for External Classes
+
+
+| [String](out.md) | `` |
+
diff --git a/test/data/functions/annotatedFunction.kt b/test/data/functions/annotatedFunction.kt
new file mode 100644
index 00000000..11c19672
--- /dev/null
+++ b/test/data/functions/annotatedFunction.kt
@@ -0,0 +1,2 @@
+inline fun f() {
+}
diff --git a/test/data/functions/annotatedFunctionWithAnnotationParameters.kt b/test/data/functions/annotatedFunctionWithAnnotationParameters.kt
new file mode 100644
index 00000000..ee5b524a
--- /dev/null
+++ b/test/data/functions/annotatedFunctionWithAnnotationParameters.kt
@@ -0,0 +1 @@
+inlineOptions(InlineOption.LOCAL_CONTINUE_AND_BREAK) fun f() {}
diff --git a/test/data/functions/functionWithAnnotatedParam.kt b/test/data/functions/functionWithAnnotatedParam.kt
new file mode 100644
index 00000000..8922f765
--- /dev/null
+++ b/test/data/functions/functionWithAnnotatedParam.kt
@@ -0,0 +1,2 @@
+fun function([noinline] notInlined: () -> Unit) {
+}
diff --git a/test/data/functions/functionWithReceiver.kt b/test/data/functions/functionWithReceiver.kt
index 663c3e56..c8473251 100644
--- a/test/data/functions/functionWithReceiver.kt
+++ b/test/data/functions/functionWithReceiver.kt
@@ -2,4 +2,10 @@
* Function with receiver
*/
fun String.fn() {
-} \ No newline at end of file
+}
+
+/**
+ * Function with receiver
+ */
+fun String.fn(x: Int) {
+}
diff --git a/test/data/properties/annotatedProperty.kt b/test/data/properties/annotatedProperty.kt
new file mode 100644
index 00000000..f70c28b4
--- /dev/null
+++ b/test/data/properties/annotatedProperty.kt
@@ -0,0 +1 @@
+inline val property = "test" \ No newline at end of file
diff --git a/test/data/properties/propertyWithReceiver.kt b/test/data/properties/propertyWithReceiver.kt
new file mode 100644
index 00000000..e282f6bd
--- /dev/null
+++ b/test/data/properties/propertyWithReceiver.kt
@@ -0,0 +1,2 @@
+val String.foobar: Int
+ get() = size() * 2
diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt
index d67254a2..901e78fc 100644
--- a/test/src/TestAPI.kt
+++ b/test/src/TestAPI.kt
@@ -6,7 +6,8 @@ import kotlin.test.fail
import org.jetbrains.dokka.*
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import java.io.File
-import kotlin.test.assertEquals
+import com.intellij.openapi.application.PathManager
+import org.junit.Assert
public fun verifyModel(vararg files: String, verifier: (DocumentationModule) -> Unit) {
val messageCollector = object : MessageCollector {
@@ -27,6 +28,8 @@ public fun verifyModel(vararg files: String, verifier: (DocumentationModule) ->
}
val environment = AnalysisEnvironment(messageCollector) {
+ val stringRoot = PathManager.getResourceRoot(javaClass<String>(), "/java/lang/String.class")
+ addClasspath(File(stringRoot))
addSources(files.toList())
}
@@ -34,10 +37,6 @@ public fun verifyModel(vararg files: String, verifier: (DocumentationModule) ->
val documentation = environment.withContext { environment, session ->
val fragments = environment.getSourceFiles().map { session.getPackageFragment(it.getPackageFqName()) }.filterNotNull().distinct()
- val descriptors = hashMapOf<String, List<DeclarationDescriptor>>()
- for ((name, parts) in fragments.groupBy { it.fqName }) {
- descriptors.put(name.asString(), parts.flatMap { it.getMemberScope().getAllDescriptors() })
- }
val documentationModule = DocumentationModule("test")
val documentationBuilder = DocumentationBuilder(session, options)
@@ -56,7 +55,7 @@ public fun verifyOutput(path: String, outputExtension: String, outputGenerator:
val output = StringBuilder()
outputGenerator(it, output)
val expectedOutput = File(path.replace(".kt", outputExtension)).readText()
- assertEquals(expectedOutput, output.toString())
+ Assert.assertEquals(expectedOutput, output.toString())
}
}
diff --git a/test/src/format/HtmlFormatTest.kt b/test/src/format/HtmlFormatTest.kt
index 881a7828..47fe9c4e 100644
--- a/test/src/format/HtmlFormatTest.kt
+++ b/test/src/format/HtmlFormatTest.kt
@@ -24,4 +24,13 @@ public class HtmlFormatTest {
htmlService.appendNodes(tempLocation, output, model.members)
}
}
+
+ Test fun deprecated() {
+ verifyOutput("test/data/format/deprecated.kt", ".package.html") { model, output ->
+ htmlService.appendNodes(tempLocation, output, model.members)
+ }
+ verifyOutput("test/data/format/deprecated.kt", ".class.html") { model, output ->
+ htmlService.appendNodes(tempLocation, output, model.members.single().members)
+ }
+ }
}
diff --git a/test/src/format/MarkdownFormatTest.kt b/test/src/format/MarkdownFormatTest.kt
index 5cdfb8b5..3d32743f 100644
--- a/test/src/format/MarkdownFormatTest.kt
+++ b/test/src/format/MarkdownFormatTest.kt
@@ -19,4 +19,31 @@ public class MarkdownFormatTest {
markdownService.appendNodes(tempLocation, output, model.members.single().members)
}
}
+
+ Test fun annotations() {
+ verifyOutput("test/data/format/annotations.kt", ".md") { model, output ->
+ markdownService.appendNodes(tempLocation, output, model.members.single().members)
+ }
+ }
+
+ Test fun annotationClass() {
+ verifyOutput("test/data/format/annotationClass.kt", ".md") { model, output ->
+ markdownService.appendNodes(tempLocation, output, model.members.single().members)
+ }
+ }
+
+ Test fun annotationParams() {
+ verifyOutput("test/data/format/annotationParams.kt", ".md") { model, output ->
+ markdownService.appendNodes(tempLocation, output, model.members.single().members)
+ }
+ }
+
+ Test fun extensions() {
+ verifyOutput("test/data/format/extensions.kt", ".package.md") { model, output ->
+ markdownService.appendNodes(tempLocation, output, model.members)
+ }
+ verifyOutput("test/data/format/extensions.kt", ".class.md") { model, output ->
+ markdownService.appendNodes(tempLocation, output, model.members.single().members)
+ }
+ }
}
diff --git a/test/src/model/ClassTest.kt b/test/src/model/ClassTest.kt
index b95a31dc..f21c5c57 100644
--- a/test/src/model/ClassTest.kt
+++ b/test/src/model/ClassTest.kt
@@ -166,4 +166,60 @@ public class ClassTest {
}
}
}
+
+ Test fun annotatedClass() {
+ verifyModel("test/data/classes/annotatedClass.kt") { model ->
+ with(model.members.single().members.single()) {
+ assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ assertEquals("data", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ }
+ }
+ }
+ }
+
+ Test fun annotatedClassWithAnnotationParameters() {
+ verifyModel("test/data/classes/annotatedClassWithAnnotationParameters.kt") { model ->
+ with(model.members.single().members.single()) {
+ with(deprecation!!) {
+ assertEquals("deprecated", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ assertEquals(1, details.count())
+ with(details[0]) {
+ assertEquals(DocumentationNode.Kind.Parameter, kind)
+ assertEquals(1, details.count())
+ with(details[0]) {
+ assertEquals(DocumentationNode.Kind.Value, kind)
+ assertEquals("\"should no longer be used\"", name)
+ }
+ }
+ }
+ }
+ }
+ }
+
+ Test fun javaAnnotationClass() {
+ verifyModel("test/data/classes/javaAnnotationClass.kt") { model ->
+ with(model.members.single().members.single()) {
+ assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ assertEquals("Retention", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ assertEquals(1, details.count())
+ with(details[0]) {
+ assertEquals(DocumentationNode.Kind.Parameter, kind)
+ assertEquals(1, details.count())
+ with(details[0]) {
+ assertEquals(DocumentationNode.Kind.Value, kind)
+ assertEquals("RetentionPolicy.SOURCE", name)
+ }
+ }
+ }
+ }
+ }
+ }
}
diff --git a/test/src/model/FunctionTest.kt b/test/src/model/FunctionTest.kt
index 2a4ad0a5..299f33a8 100644
--- a/test/src/model/FunctionTest.kt
+++ b/test/src/model/FunctionTest.kt
@@ -21,23 +21,32 @@ public class FunctionTest {
Test fun functionWithReceiver() {
verifyModel("test/data/functions/functionWithReceiver.kt") { model ->
with(model.members.single().members.single()) {
- assertEquals("fn", name)
- assertEquals(DocumentationNode.Kind.Function, kind)
- assertEquals("Function with receiver", content.summary.toTestString())
- assertEquals(4, details.count())
- assertEquals("internal", details.elementAt(0).name)
- assertEquals("final", details.elementAt(1).name)
- with(details.elementAt(2)) {
- assertEquals("<this>", name)
- assertEquals(DocumentationNode.Kind.Receiver, kind)
- assertEquals(Content.Empty, content)
- assertEquals("String", details.single().name)
+ assertEquals("String", name)
+ assertEquals(DocumentationNode.Kind.ExternalClass, kind)
+ assertEquals(2, members.count())
+ with(members[0]) {
+ assertEquals("fn", name)
+ assertEquals(DocumentationNode.Kind.Function, kind)
+ assertEquals("Function with receiver", content.summary.toTestString())
+ assertEquals(4, details.count())
+ assertEquals("internal", details.elementAt(0).name)
+ assertEquals("final", details.elementAt(1).name)
+ with(details.elementAt(2)) {
+ assertEquals("<this>", name)
+ assertEquals(DocumentationNode.Kind.Receiver, kind)
+ assertEquals(Content.Empty, content)
+ assertEquals("String", details.single().name)
+ assertTrue(members.none())
+ assertTrue(links.none())
+ }
+ assertEquals("Unit", details.elementAt(3).name)
assertTrue(members.none())
assertTrue(links.none())
}
- assertEquals("Unit", details.elementAt(3).name)
- assertTrue(members.none())
- assertTrue(links.none())
+ with(members[1]) {
+ assertEquals("fn", name)
+ assertEquals(DocumentationNode.Kind.Function, kind)
+ }
}
}
}
@@ -135,4 +144,54 @@ Documentation""", content.description.toTestString())
}
}
}
-} \ No newline at end of file
+
+ Test fun annotatedFunction() {
+ verifyModel("test/data/functions/annotatedFunction.kt") { model ->
+ with(model.members.single().members.single()) {
+ assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ assertEquals("inline", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ }
+ }
+ }
+ }
+
+ Test fun functionWithAnnotatedParam() {
+ verifyModel("test/data/functions/functionWithAnnotatedParam.kt") { model ->
+ with(model.members.single().members.single()) {
+ with(details.elementAt(2)) {
+ assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ assertEquals("noinline", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ }
+ }
+ }
+ }
+ }
+
+ Test fun annotatedFunctionWithAnnotationParameters() {
+ verifyModel("test/data/functions/annotatedFunctionWithAnnotationParameters.kt") { model ->
+ with(model.members.single().members.single()) {
+ assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ assertEquals("inlineOptions", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ assertEquals(1, details.count())
+ with(details[0]) {
+ assertEquals(DocumentationNode.Kind.Parameter, kind)
+ assertEquals(1, details.count())
+ with(details[0]) {
+ assertEquals(DocumentationNode.Kind.Value, kind)
+ assertEquals("[InlineOption.LOCAL_CONTINUE_AND_BREAK]", name)
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/test/src/model/PropertyTest.kt b/test/src/model/PropertyTest.kt
index 103da170..14c43f78 100644
--- a/test/src/model/PropertyTest.kt
+++ b/test/src/model/PropertyTest.kt
@@ -99,4 +99,30 @@ public class PropertyTest {
}
}
}
+
+ Test fun annotatedProperty() {
+ verifyModel("test/data/properties/annotatedProperty.kt") { model ->
+ with(model.members.single().members.single()) {
+ assertEquals(1, annotations.count())
+ with(annotations[0]) {
+ assertEquals("inline", name)
+ assertEquals(Content.Empty, content)
+ assertEquals(DocumentationNode.Kind.Annotation, kind)
+ }
+ }
+ }
+ }
+
+ Test fun propertyWithReceiver() {
+ verifyModel("test/data/properties/propertyWithReceiver.kt") { model ->
+ with(model.members.single().members.single()) {
+ assertEquals("String", name)
+ assertEquals(DocumentationNode.Kind.ExternalClass, kind)
+ with(members.single()) {
+ assertEquals("foobar", name)
+ assertEquals(DocumentationNode.Kind.Property, kind)
+ }
+ }
+ }
+ }
}