diff options
-rw-r--r-- | .idea/runConfigurations/All_tests.xml | 2 | ||||
-rw-r--r-- | src/Kotlin/DocumentationBuilder.kt | 38 | ||||
-rw-r--r-- | src/Kotlin/KotlinLanguageService.kt | 11 | ||||
-rw-r--r-- | test/data/classes/annotatedClass.kt | 2 | ||||
-rw-r--r-- | test/data/classes/dataClass.kt | 1 | ||||
-rw-r--r-- | test/data/format/annotationParams.kt | 2 | ||||
-rw-r--r-- | test/data/format/annotationParams.md | 2 | ||||
-rw-r--r-- | test/data/functions/annotatedFunction.kt | 2 | ||||
-rw-r--r-- | test/data/functions/functionWithAnnotatedParam.kt | 7 | ||||
-rw-r--r-- | test/data/functions/functionWithNoinlineParam.kt | 2 | ||||
-rw-r--r-- | test/data/functions/functionWithNotDocumentedAnnotation.kt | 2 | ||||
-rw-r--r-- | test/data/functions/inlineFunction.kt | 2 | ||||
-rw-r--r-- | test/data/properties/annotatedProperty.kt | 2 | ||||
-rw-r--r-- | test/src/TestAPI.kt | 5 | ||||
-rw-r--r-- | test/src/format/MarkdownFormatTest.kt | 5 | ||||
-rw-r--r-- | test/src/model/ClassTest.kt | 30 | ||||
-rw-r--r-- | test/src/model/FunctionTest.kt | 54 | ||||
-rw-r--r-- | test/src/model/PropertyTest.kt | 2 |
18 files changed, 115 insertions, 56 deletions
diff --git a/.idea/runConfigurations/All_tests.xml b/.idea/runConfigurations/All_tests.xml index b0528c8f..57e4134d 100644 --- a/.idea/runConfigurations/All_tests.xml +++ b/.idea/runConfigurations/All_tests.xml @@ -8,7 +8,7 @@ <option name="MAIN_CLASS_NAME" value="" /> <option name="METHOD_NAME" value="" /> <option name="TEST_OBJECT" value="package" /> - <option name="VM_PARAMETERS" value="" /> + <option name="VM_PARAMETERS" value="-Xmx256m" /> <option name="PARAMETERS" value="" /> <option name="WORKING_DIRECTORY" value="" /> <option name="ENV_VARIABLES" /> diff --git a/src/Kotlin/DocumentationBuilder.kt b/src/Kotlin/DocumentationBuilder.kt index bf336935..a02717f6 100644 --- a/src/Kotlin/DocumentationBuilder.kt +++ b/src/Kotlin/DocumentationBuilder.kt @@ -15,12 +15,15 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.kdoc.psi.impl.KDocSection import org.jetbrains.kotlin.kdoc.psi.impl.KDocTag import org.jetbrains.kotlin.lexer.JetSingleValueToken +import org.jetbrains.kotlin.lexer.JetTokens import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.psi.JetModifierListOwner import org.jetbrains.kotlin.psi.JetParameter import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.ConstantValue import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant +import org.jetbrains.kotlin.resolve.descriptorUtil.isDocumentedAnnotation import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.source.PsiSourceElement import org.jetbrains.kotlin.resolve.source.getPsi @@ -50,6 +53,10 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, val boringBuiltinClasses = setOf( "kotlin.Unit", "kotlin.Byte", "kotlin.Short", "kotlin.Int", "kotlin.Long", "kotlin.Char", "kotlin.Boolean", "kotlin.Float", "kotlin.Double", "kotlin.String", "kotlin.Array", "kotlin.Any") + val knownModifiers = setOf( + JetTokens.PUBLIC_KEYWORD, JetTokens.PROTECTED_KEYWORD, JetTokens.INTERNAL_KEYWORD, JetTokens.PRIVATE_KEYWORD, + JetTokens.OPEN_KEYWORD, JetTokens.FINAL_KEYWORD, + JetTokens.OVERRIDE_KEYWORD) fun parseDocumentation(descriptor: DeclarationDescriptor): Content { val kdoc = KDocFinder.findKDoc(descriptor) ?: findStdlibKDoc(descriptor) @@ -328,7 +335,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, DescriptorUtils.getFqName(this).asString() in boringBuiltinClasses fun DocumentationNode.appendAnnotations(annotated: Annotated) { - annotated.getAnnotations().forEach { + annotated.annotations.filter { it.source.getPsi() != null && it.mustBeDocumented() }.forEach { val annotationNode = it.build() if (annotationNode != null) { append(annotationNode, @@ -337,6 +344,20 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } + fun AnnotationDescriptor.mustBeDocumented(): Boolean { + val annotationClass = type.constructor.declarationDescriptor as? Annotated ?: return false + return annotationClass.isDocumentedAnnotation() + } + + fun DocumentationNode.appendModifiers(descriptor: DeclarationDescriptor) { + val psi = (descriptor as DeclarationDescriptorWithSource).source.getPsi() as? JetModifierListOwner ?: return + JetTokens.MODIFIER_KEYWORDS_ARRAY.filter { it !in knownModifiers }.forEach { + if (psi.hasModifier(it)) { + appendTextNode(it.value, Kind.Modifier) + } + } + } + fun DocumentationNode.isDeprecation() = name == "Deprecated" || name == "deprecated" fun DocumentationNode.appendSourceLink(sourceElement: SourceElement) { @@ -442,9 +463,6 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, else -> Kind.Class } val node = DocumentationNode(this, kind) - if (isInner()) { - node.appendTextNode("inner", Kind.Modifier) - } node.appendSupertypes(this) if (getKind() != ClassKind.OBJECT && getKind() != ClassKind.ENUM_ENTRY) { node.appendInPageChildren(getTypeConstructor().getParameters(), DocumentationReference.Kind.Detail) @@ -462,6 +480,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, DocumentationReference.Kind.Member) } node.appendAnnotations(this) + node.appendModifiers(this) node.appendSourceLink(getSource()) register(this, node) return node @@ -504,6 +523,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, node.appendInPageChildren(getValueParameters(), DocumentationReference.Kind.Detail) node.appendType(getReturnType()) node.appendAnnotations(this) + node.appendModifiers(this) node.appendSourceLink(getSource()) node.appendOperatorOverloadNote(this) @@ -584,6 +604,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, getExtensionReceiverParameter()?.let { node.appendChild(it, DocumentationReference.Kind.Detail) } node.appendType(getReturnType()) node.appendAnnotations(this) + node.appendModifiers(this) node.appendSourceLink(getSource()) if (isVar()) { node.appendTextNode("var", DocumentationNode.Kind.Modifier) @@ -623,13 +644,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, fun ValueParameterDescriptor.build(): DocumentationNode { val node = DocumentationNode(this, Kind.Parameter) - val varargType = getVarargElementType() - if (varargType != null) { - node.appendTextNode("vararg", Kind.Annotation, DocumentationReference.Kind.Annotation) - node.appendType(varargType) - } else { - node.appendType(getType()) - } + node.appendType(varargElementType ?: type) if (declaresDefaultValue()) { val psi = getSource().getPsi() as? JetParameter if (psi != null) { @@ -640,6 +655,7 @@ class DocumentationBuilder(val resolutionFacade: ResolutionFacade, } } node.appendAnnotations(this) + node.appendModifiers(this) register(this, node) return node } diff --git a/src/Kotlin/KotlinLanguageService.kt b/src/Kotlin/KotlinLanguageService.kt index a22ba8af..d61db546 100644 --- a/src/Kotlin/KotlinLanguageService.kt +++ b/src/Kotlin/KotlinLanguageService.kt @@ -154,8 +154,9 @@ class KotlinLanguageService : LanguageService { } } - private fun ContentBlock.renderParameter(node: DocumentationNode) { + private fun ContentBlock.renderParameter(node: DocumentationNode, renderMode: RenderMode) { renderAnnotationsForNode(node) + renderModifiersForNode(node, renderMode) identifier(node.name, IdentifierKind.ParameterName) symbol(":") nbsp() @@ -212,7 +213,7 @@ class KotlinLanguageService : LanguageService { } private fun ContentBlock.renderAnnotation(node: DocumentationNode) { - identifier(node.name, IdentifierKind.AnnotationName) + identifier("@" + node.name, IdentifierKind.AnnotationName) val parameters = node.details(DocumentationNode.Kind.Parameter) if (!parameters.isEmpty()) { symbol("(") @@ -229,9 +230,9 @@ class KotlinLanguageService : LanguageService { renderAnnotationsForNode(node) when (node.kind) { DocumentationNode.Kind.Class, - DocumentationNode.Kind.AnnotationClass -> keyword("class ") + DocumentationNode.Kind.AnnotationClass, + DocumentationNode.Kind.Enum -> keyword("class ") DocumentationNode.Kind.Interface -> keyword("interface ") - DocumentationNode.Kind.Enum -> keyword("enum class ") DocumentationNode.Kind.EnumItem -> keyword("enum val ") DocumentationNode.Kind.Object -> keyword("object ") else -> throw IllegalArgumentException("Node $node is not a class-like object") @@ -266,7 +267,7 @@ class KotlinLanguageService : LanguageService { symbol("(") renderList(node.details(DocumentationNode.Kind.Parameter)) { - renderParameter(it) + renderParameter(it, renderMode) } symbol(")") if (needReturnType(node)) { diff --git a/test/data/classes/annotatedClass.kt b/test/data/classes/annotatedClass.kt index 62c6f0ec..1b58f56c 100644 --- a/test/data/classes/annotatedClass.kt +++ b/test/data/classes/annotatedClass.kt @@ -1 +1 @@ -data class Foo() {} +@Strictfp class Foo() {} diff --git a/test/data/classes/dataClass.kt b/test/data/classes/dataClass.kt new file mode 100644 index 00000000..62c6f0ec --- /dev/null +++ b/test/data/classes/dataClass.kt @@ -0,0 +1 @@ +data class Foo() {} diff --git a/test/data/format/annotationParams.kt b/test/data/format/annotationParams.kt index ee5b524a..f259a740 100644 --- a/test/data/format/annotationParams.kt +++ b/test/data/format/annotationParams.kt @@ -1 +1 @@ -inlineOptions(InlineOption.LOCAL_CONTINUE_AND_BREAK) fun f() {} +@JvmName("FFF") fun f() {} diff --git a/test/data/format/annotationParams.md b/test/data/format/annotationParams.md index 80fe52cf..8cdd6e96 100644 --- a/test/data/format/annotationParams.md +++ b/test/data/format/annotationParams.md @@ -3,6 +3,6 @@ # f -`inlineOptions([InlineOption.LOCAL_CONTINUE_AND_BREAK]) fun f(): Unit` +`@JvmName("FFF") fun f(): Unit` diff --git a/test/data/functions/annotatedFunction.kt b/test/data/functions/annotatedFunction.kt index 11c19672..f7abbf6c 100644 --- a/test/data/functions/annotatedFunction.kt +++ b/test/data/functions/annotatedFunction.kt @@ -1,2 +1,2 @@ -inline fun f() { +@Strictfp fun f() { } diff --git a/test/data/functions/functionWithAnnotatedParam.kt b/test/data/functions/functionWithAnnotatedParam.kt index 640bec83..f858e671 100644 --- a/test/data/functions/functionWithAnnotatedParam.kt +++ b/test/data/functions/functionWithAnnotatedParam.kt @@ -1,2 +1,7 @@ -fun function(noinline notInlined: () -> Unit) { +@Target(AnnotationTarget.VALUE_PARAMETER) +@Retention(AnnotationRetention.SOURCE) +@MustBeDocumented +public annotation class Fancy + +fun function(@Fancy notInlined: () -> Unit) { } diff --git a/test/data/functions/functionWithNoinlineParam.kt b/test/data/functions/functionWithNoinlineParam.kt new file mode 100644 index 00000000..640bec83 --- /dev/null +++ b/test/data/functions/functionWithNoinlineParam.kt @@ -0,0 +1,2 @@ +fun function(noinline notInlined: () -> Unit) { +} diff --git a/test/data/functions/functionWithNotDocumentedAnnotation.kt b/test/data/functions/functionWithNotDocumentedAnnotation.kt new file mode 100644 index 00000000..3c7e2ff9 --- /dev/null +++ b/test/data/functions/functionWithNotDocumentedAnnotation.kt @@ -0,0 +1,2 @@ +@Suppress("FOO") fun f() { +} diff --git a/test/data/functions/inlineFunction.kt b/test/data/functions/inlineFunction.kt new file mode 100644 index 00000000..11c19672 --- /dev/null +++ b/test/data/functions/inlineFunction.kt @@ -0,0 +1,2 @@ +inline fun f() { +} diff --git a/test/data/properties/annotatedProperty.kt b/test/data/properties/annotatedProperty.kt index f70c28b4..8990af29 100644 --- a/test/data/properties/annotatedProperty.kt +++ b/test/data/properties/annotatedProperty.kt @@ -1 +1 @@ -inline val property = "test"
\ No newline at end of file +@Volatile var property = "test"
\ No newline at end of file diff --git a/test/src/TestAPI.kt b/test/src/TestAPI.kt index 165278f9..88d19036 100644 --- a/test/src/TestAPI.kt +++ b/test/src/TestAPI.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.jetbrains.kotlin.config.ContentRoot import org.jetbrains.kotlin.config.KotlinSourceRoot -import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance import org.junit.Assert import java.io.File import kotlin.test.fail @@ -33,8 +32,10 @@ public fun verifyModel(vararg roots: ContentRoot, verifier: (DocumentationModule } val environment = AnalysisEnvironment(messageCollector) { - val stringRoot = PathManager.getResourceRoot(javaClass<String>(), "/java/lang/String.class") + val stringRoot = PathManager.getResourceRoot(String::class.java, "/java/lang/String.class") addClasspath(File(stringRoot)) + val kotlinPairRoot = PathManager.getResourceRoot(Pair::class.java, "/kotlin/Pair.class") + addClasspath(File(kotlinPairRoot)) addRoots(roots.toList()) } val options = DocumentationOptions(includeNonPublic = true, skipEmptyPackages = false, sourceLinks = listOf<SourceLinkDefinition>()) diff --git a/test/src/format/MarkdownFormatTest.kt b/test/src/format/MarkdownFormatTest.kt index 059b491b..88003051 100644 --- a/test/src/format/MarkdownFormatTest.kt +++ b/test/src/format/MarkdownFormatTest.kt @@ -1,7 +1,8 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.KotlinLanguageService +import org.jetbrains.dokka.MarkdownFormatService import org.junit.Test -import org.jetbrains.dokka.* public class MarkdownFormatTest { private val markdownService = MarkdownFormatService(InMemoryLocationService, KotlinLanguageService()) @@ -30,7 +31,7 @@ public class MarkdownFormatTest { } } - Test fun annotationParams() { + @Test fun annotationParams() { verifyOutput("test/data/format/annotationParams.kt", ".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 05fc2fc3..bcedf49c 100644 --- a/test/src/model/ClassTest.kt +++ b/test/src/model/ClassTest.kt @@ -1,8 +1,11 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.Content +import org.jetbrains.dokka.DocumentationNode +import org.jetbrains.dokka.DocumentationReference import org.junit.Test -import kotlin.test.* -import org.jetbrains.dokka.* +import kotlin.test.assertEquals +import kotlin.test.assertTrue public class ClassTest { Test fun emptyClass() { @@ -148,19 +151,24 @@ 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 annotatedClass() { + verifyPackageMember("test/data/classes/annotatedClass.kt") { cls -> + assertEquals(1, cls.annotations.count()) + with(cls.annotations[0]) { + assertEquals("Strictfp", name) + assertEquals(Content.Empty, content) + assertEquals(DocumentationNode.Kind.Annotation, kind) } } } + @Test fun dataClass() { + verifyPackageMember("test/data/classes/dataClass.kt") { cls -> + val modifiers = cls.details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("data" in modifiers) + } + } + Test fun annotatedClassWithAnnotationParameters() { verifyModel("test/data/classes/annotatedClassWithAnnotationParameters.kt") { model -> with(model.members.single().members.single()) { diff --git a/test/src/model/FunctionTest.kt b/test/src/model/FunctionTest.kt index 80ae223d..734675de 100644 --- a/test/src/model/FunctionTest.kt +++ b/test/src/model/FunctionTest.kt @@ -7,7 +7,7 @@ import kotlin.test.assertEquals import kotlin.test.assertTrue public class FunctionTest { - Test fun function() { + @Test fun function() { verifyModel("test/data/functions/function.kt") { model -> with(model.members.single().members.single()) { assertEquals("fn", name) @@ -20,7 +20,7 @@ public class FunctionTest { } } - Test fun functionWithReceiver() { + @Test fun functionWithReceiver() { verifyModel("test/data/functions/functionWithReceiver.kt") { model -> with(model.members.single().members.single()) { assertEquals("String", name) @@ -52,7 +52,7 @@ public class FunctionTest { } } - Test fun genericFunction() { + @Test fun genericFunction() { verifyModel("test/data/functions/genericFunction.kt") { model -> with(model.members.single().members.single()) { assertEquals("generic", name) @@ -76,7 +76,7 @@ public class FunctionTest { } } } - Test fun genericFunctionWithConstraints() { + @Test fun genericFunctionWithConstraints() { verifyModel("test/data/functions/genericFunctionWithConstraints.kt") { model -> with(model.members.single().members.single()) { assertEquals("generic", name) @@ -115,7 +115,7 @@ public class FunctionTest { } } - Test fun functionWithParams() { + @Test fun functionWithParams() { verifyModel("test/data/functions/functionWithParams.kt") { model -> with(model.members.single().members.single()) { assertEquals("function", name) @@ -141,26 +141,37 @@ Documentation""", content.description.toTestString()) } } - 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 annotatedFunction() { + verifyPackageMember("test/data/functions/annotatedFunction.kt") { func -> + assertEquals(1, func.annotations.count()) + with(func.annotations[0]) { + assertEquals("Strictfp", name) + assertEquals(Content.Empty, content) + assertEquals(DocumentationNode.Kind.Annotation, kind) } } } - Test fun functionWithAnnotatedParam() { + @Test fun functionWithNotDocumentedAnnotation() { + verifyPackageMember("test/data/functions/functionWithNotDocumentedAnnotation.kt") { func -> + assertEquals(0, func.annotations.count()) + } + } + + @Test fun inlineFunction() { + verifyPackageMember("test/data/functions/inlineFunction.kt") { func -> + val modifiers = func.details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("inline" in modifiers) + } + } + + @Test fun functionWithAnnotatedParam() { verifyModel("test/data/functions/functionWithAnnotatedParam.kt") { model -> - with(model.members.single().members.single()) { + with(model.members.single().members.single { it.name == "function"} ) { with(details.elementAt(2)) { assertEquals(1, annotations.count()) with(annotations[0]) { - assertEquals("noinline", name) + assertEquals("Fancy", name) assertEquals(Content.Empty, content) assertEquals(DocumentationNode.Kind.Annotation, kind) } @@ -169,6 +180,15 @@ Documentation""", content.description.toTestString()) } } + @Test fun functionWithNoinlineParam() { + verifyPackageMember("test/data/functions/functionWithNoinlineParam.kt") { func -> + with(func.details.elementAt(2)) { + val modifiers = details(DocumentationNode.Kind.Modifier).map { it.name } + assertTrue("noinline" in modifiers) + } + } + } + Test fun annotatedFunctionWithAnnotationParameters() { verifyModel("test/data/functions/annotatedFunctionWithAnnotationParameters.kt") { model -> with(model.members.single().members.single()) { diff --git a/test/src/model/PropertyTest.kt b/test/src/model/PropertyTest.kt index 405b260f..0853cbc5 100644 --- a/test/src/model/PropertyTest.kt +++ b/test/src/model/PropertyTest.kt @@ -69,7 +69,7 @@ public class PropertyTest { with(model.members.single().members.single()) { assertEquals(1, annotations.count()) with(annotations[0]) { - assertEquals("inline", name) + assertEquals("Volatile", name) assertEquals(Content.Empty, content) assertEquals(DocumentationNode.Kind.Annotation, kind) } |