aboutsummaryrefslogtreecommitdiff
path: root/dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains
diff options
context:
space:
mode:
authorIgnat Beresnev <ignat.beresnev@jetbrains.com>2023-11-21 11:28:45 +0100
committerGitHub <noreply@github.com>2023-11-21 11:28:45 +0100
commit6fbc2221ff309995c605161b51d4d64cbabddd51 (patch)
treea6476838442e47b3bbc03d753c74c84f58f67b1e /dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains
parent9ce37affaa2c1199807c08e13485740ea993994e (diff)
downloaddokka-6fbc2221ff309995c605161b51d4d64cbabddd51.tar.gz
dokka-6fbc2221ff309995c605161b51d4d64cbabddd51.tar.bz2
dokka-6fbc2221ff309995c605161b51d4d64cbabddd51.zip
Stabilize Sample analysis API (#3195)
Diffstat (limited to 'dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains')
-rw-r--r--dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains/dokka/analysis/test/sample/SampleAnalysisTest.kt495
1 files changed, 479 insertions, 16 deletions
diff --git a/dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains/dokka/analysis/test/sample/SampleAnalysisTest.kt b/dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains/dokka/analysis/test/sample/SampleAnalysisTest.kt
index 618e28a8..3b8a2afd 100644
--- a/dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains/dokka/analysis/test/sample/SampleAnalysisTest.kt
+++ b/dokka-subprojects/analysis-kotlin-api/src/test/kotlin/org/jetbrains/dokka/analysis/test/sample/SampleAnalysisTest.kt
@@ -4,52 +4,515 @@
package org.jetbrains.dokka.analysis.test.sample
+import org.jetbrains.dokka.analysis.kotlin.sample.SampleSnippet
import org.jetbrains.dokka.analysis.test.api.kotlinJvmTestProject
+import org.jetbrains.dokka.analysis.test.api.mixedJvmTestProject
import org.jetbrains.dokka.analysis.test.api.useServices
-import kotlin.test.Test
-import kotlin.test.assertEquals
-import kotlin.test.assertNotNull
+import org.jetbrains.dokka.analysis.test.api.util.CollectingDokkaConsoleLogger
+import org.jetbrains.dokka.analysis.test.api.util.singleSourceSet
+import org.junit.jupiter.api.Tag
+import kotlin.test.*
class SampleAnalysisTest {
@Test
- fun `should return sources of a kotlin sample`() {
+ fun `should resolve a valid sample if set via the samples option`() {
val testProject = kotlinJvmTestProject {
dokkaConfiguration {
kotlinSourceSet {
- additionalSourceRoots = setOf("/samples")
+ samples = setOf("/samples/collections.kt")
}
}
- sampleFile("/samples/stringListOf-sample.kt", fqPackageName = "org.jetbrains.dokka.sample.generator") {
+ sampleFile("/samples/collections.kt", fqPackageName = "org.jetbrains.dokka.sample.collections") {
+"""
import org.jetbrains.dokka.DokkaConfiguration
import org.jetbrains.dokka.DokkaGenerator
import org.jetbrains.dokka.utilities.DokkaLogger
- fun runGenerator(configuration: DokkaConfiguration, logger: DokkaLogger) {
- DokkaGenerator(configuration, logger).generate()
+ fun specificPositionOperations() {
+ val numbers = mutableListOf(1, 2, 3, 4)
+ numbers.add(5)
+ numbers.removeAt(1)
+ numbers[0] = 0
+ numbers.shuffle()
+ if (numbers.size > 0) {
+ println(numbers)
+ }
}
"""
}
}
testProject.useServices { context ->
- val sampleSourceSet = context.configuration.sourceSets.single()
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(
+ sourceSet = context.singleSourceSet(),
+ fullyQualifiedLink = "org.jetbrains.dokka.sample.collections.specificPositionOperations"
+ )
+ }
+ assertNotNull(sample)
+
+ val expectedImports = listOf(
+ "org.jetbrains.dokka.DokkaConfiguration",
+ "org.jetbrains.dokka.DokkaGenerator",
+ "org.jetbrains.dokka.utilities.DokkaLogger"
+ )
- val sampleProvider = sampleProviderFactory.build()
- val sample = sampleProvider.getSample(sampleSourceSet, "org.jetbrains.dokka.sample.generator.runGenerator")
+ val expectedBody = """
+ val numbers = mutableListOf(1, 2, 3, 4)
+ numbers.add(5)
+ numbers.removeAt(1)
+ numbers[0] = 0
+ numbers.shuffle()
+ if (numbers.size > 0) {
+ println(numbers)
+ }
+ """.trimIndent()
+
+ assertEquals(expectedImports, sample.imports)
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should resolve a valid sample if set via the additionalSourceRoots option`() {
+ val testProject = kotlinJvmTestProject {
+ dokkaConfiguration {
+ kotlinSourceSet {
+ additionalSourceRoots = setOf("/samples")
+ }
+ }
+ sampleFile("/samples/collections.kt", fqPackageName = "org.jetbrains.dokka.sample.collections") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+ import org.jetbrains.dokka.DokkaGenerator
+ import org.jetbrains.dokka.utilities.DokkaLogger
+
+ fun specificPositionOperations() {
+ val numbers = mutableListOf(1, 2, 3, 4)
+ numbers.add(5)
+ numbers.removeAt(1)
+ numbers[0] = 0
+ numbers.shuffle()
+ if (numbers.size > 0) {
+ println(numbers)
+ }
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(
+ sourceSet = context.singleSourceSet(),
+ fullyQualifiedLink = "org.jetbrains.dokka.sample.collections.specificPositionOperations"
+ )
+ }
assertNotNull(sample)
val expectedImports = listOf(
- "import org.jetbrains.dokka.DokkaConfiguration",
- "import org.jetbrains.dokka.DokkaGenerator",
- "import org.jetbrains.dokka.utilities.DokkaLogger"
- ).joinToString(separator = "\n")
+ "org.jetbrains.dokka.DokkaConfiguration",
+ "org.jetbrains.dokka.DokkaGenerator",
+ "org.jetbrains.dokka.utilities.DokkaLogger"
+ )
+
+ val expectedBody = """
+ val numbers = mutableListOf(1, 2, 3, 4)
+ numbers.add(5)
+ numbers.removeAt(1)
+ numbers[0] = 0
+ numbers.shuffle()
+ if (numbers.size > 0) {
+ println(numbers)
+ }
+ """.trimIndent()
+
+ assertEquals(expectedImports, sample.imports)
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should resolve a valid sample function that exists in the main source set`() {
+ val testProject = kotlinJvmTestProject {
+ ktFile("org/jetbrains/dokka/test/MyKotlinFile.kt") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+
+ fun myAverageTopLevelFunction() {
+ println("hello from the average top level function")
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "org.jetbrains.dokka.test.myAverageTopLevelFunction")
+ }
+ assertNotNull(sample)
+
+ val expectedImports = listOf("org.jetbrains.dokka.DokkaConfiguration")
+ val expectedBody = "println(\"hello from the average top level function\")"
+
+ assertEquals(expectedImports, sample.imports)
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ fun `should resolve a valid sample in the root package`() {
+ val testProject = kotlinJvmTestProject {
+ dokkaConfiguration {
+ kotlinSourceSet {
+ samples = setOf("/samples/TopLevelSample.kt")
+ }
+ }
+
+ sampleFile("/samples/TopLevelSample.kt", fqPackageName = "") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+
+ fun foo() {
+ println("hello from the root")
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "foo")
+ }
+ assertNotNull(sample)
+
+ val expectedImports = listOf("org.jetbrains.dokka.DokkaConfiguration")
+ val expectedBody = "println(\"hello from the root\")"
+
+ assertEquals(expectedImports, sample.imports)
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ fun `should resolve a valid sample function from a class in the root package`() {
+ val testProject = kotlinJvmTestProject {
+ dokkaConfiguration {
+ kotlinSourceSet {
+ samples = setOf("/samples/RootClassSample.kt")
+ }
+ }
+
+ sampleFile("/samples/RootClassSample.kt", fqPackageName = "") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+
+ class RootClass {
+ fun foo() {
+ println("hello from within a root class")
+ }
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "RootClass.foo")
+ }
+ assertNotNull(sample)
+
+ val expectedImports = listOf("org.jetbrains.dokka.DokkaConfiguration")
+ val expectedBody = "println(\"hello from within a root class\")"
+
+ assertEquals(expectedImports, sample.imports)
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ fun `should resolve a valid sample function from a class`() {
+ val testProject = kotlinJvmTestProject {
+ dokkaConfiguration {
+ kotlinSourceSet {
+ samples = setOf("/samples/SampleWithinClass.kt")
+ }
+ }
+
+ sampleFile("/samples/SampleWithinClass.kt", fqPackageName = "samples") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+
+ package samples
+
+ class SampleWithinClass {
+ fun foo() {
+ println("hello from within a class")
+ }
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "samples.SampleWithinClass.foo")
+ }
+ assertNotNull(sample)
+
+ val expectedImports = listOf("org.jetbrains.dokka.DokkaConfiguration")
+ val expectedBody = "println(\"hello from within a class\")"
+
+ assertEquals(expectedImports, sample.imports)
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ fun `should return null for non-existing sample`() {
+ val testProject = kotlinJvmTestProject {
+ // nothing
+ }
+
+ testProject.useServices { context ->
+ val nonExistingSample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "com.example.non.existing.sampleFunction")
+ }
+
+ assertNull(nonExistingSample)
+ }
+ }
+
+ @Test
+ fun `should return null if sample is resolved just by class name`() {
+ val testProject = kotlinJvmTestProject {
+ dokkaConfiguration {
+ kotlinSourceSet {
+ samples = setOf("/samples/FooSampleFile.kt")
+ }
+ }
+ sampleFile("/samples/FooSampleFile.kt", fqPackageName = "org.jetbrains.dokka.sample") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+
+ fun topLevelFunction() {}
+
+ class FooSampleClass {
+ fun foo() {
+ println("foo")
+ }
+ }
+ """
+ }
+ }
+
+ val collectingLogger = CollectingDokkaConsoleLogger()
+ testProject.useServices(collectingLogger) { context ->
+ val sampleByClassName = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "org.jetbrains.dokka.sample.FooSampleClass")
+ }
+ assertNull(sampleByClassName)
+ }
+
+ val containsNonKotlinSampleLinkLog = collectingLogger.collectedLogMessages.contains(
+ "Unable to process a @sample link: \"org.jetbrains.dokka.sample.FooSampleClass\". " +
+ "Only function links allowed."
+ )
+ assertTrue(containsNonKotlinSampleLinkLog)
+ }
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should return null if trying to resolve a non-kotlin sample link`() {
+ val testProject = mixedJvmTestProject {
+ kotlinSourceDirectory {
+ javaFile("org/jetbrains/test/sample/JavaClass.java") {
+ +"""
+ public class JavaClass {
+ public void foo() {
+ System.out.println("foo");
+ }
+ }
+ """
+ }
+ ktFile("org/jetbrains/test/sample/KotlinFile.kt") {
+ +"""
+ fun foo() {}
+ """
+ }
+ }
+ }
+
+ val collectingLogger = CollectingDokkaConsoleLogger()
+ testProject.useServices(collectingLogger) { context ->
+ sampleAnalysisEnvironmentCreator.use {
+ val kotlinSourceSet = context.singleSourceSet()
+
+ val byClassName = resolveSample(kotlinSourceSet, "org.jetbrains.test.sample.JavaClass")
+ assertNull(byClassName)
+
+ val byClassFunctionName = resolveSample(kotlinSourceSet, "org.jetbrains.test.sample.JavaClass.foo")
+ assertNull(byClassFunctionName)
+ }
+ }
+
+ val containsNonKotlinSampleLinkLog = collectingLogger.collectedLogMessages.contains(
+ "Unable to resolve non-Kotlin @sample links: \"org.jetbrains.test.sample.JavaClass\""
+ )
+ assertTrue(containsNonKotlinSampleLinkLog)
+ }
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should filter out empty import statement lines`() {
+ val testProject = kotlinJvmTestProject {
+ ktFile("org/jetbrains/dokka/test/MyKotlinFile.kt") {
+ +"""
+ import org.jetbrains.dokka.DokkaConfiguration
+
+ import org.jetbrains.dokka.DokkaGenerator
+
+ import org.jetbrains.dokka.utilities.DokkaLogger
+
+ fun sample() {
+ println("hello from sample")
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "org.jetbrains.dokka.test.sample")
+ }
+ assertNotNull(sample)
- val expectedBody = "DokkaGenerator(configuration, logger).generate()"
+ val expectedImports = listOf(
+ "org.jetbrains.dokka.DokkaConfiguration",
+ "org.jetbrains.dokka.DokkaGenerator",
+ "org.jetbrains.dokka.utilities.DokkaLogger",
+ )
+ val expectedBody = "println(\"hello from sample\")"
assertEquals(expectedImports, sample.imports)
assertEquals(expectedBody, sample.body)
}
}
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should return an empty list of imports if sample file has none`() {
+ val testProject = kotlinJvmTestProject {
+ ktFile("org/jetbrains/dokka/test/MyKotlinFile.kt") {
+ +"""
+ fun sample() {
+ println("hello from sample")
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "org.jetbrains.dokka.test.sample")
+ }
+ assertNotNull(sample)
+
+ assertTrue(sample.imports.isEmpty())
+
+ val expectedBody = "println(\"hello from sample\")"
+ assertEquals(expectedBody, sample.body)
+
+ }
+ }
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should filter out leading and trailing line breaks`() {
+ val testProject = kotlinJvmTestProject {
+ ktFile("org/jetbrains/dokka/test/MyKotlinFile.kt") {
+ +"""
+ fun sample() {
+
+
+ println("hello from sample")
+
+
+
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "org.jetbrains.dokka.test.sample")
+ }
+ assertNotNull(sample)
+
+ val expectedBody = "println(\"hello from sample\")"
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ @Tag("onlyDescriptors") // TODO #3359
+ fun `should filter out trailing whitespace`() {
+ val testProject = kotlinJvmTestProject {
+ ktFile("org/jetbrains/dokka/test/MyKotlinFile.kt") {
+ +"""
+ fun sample() {
+ println("hello from sample")
+ }
+ """
+ }
+ }
+
+ testProject.useServices { context ->
+ val sample = sampleAnalysisEnvironmentCreator.use {
+ resolveSample(context.singleSourceSet(), "org.jetbrains.dokka.test.sample")
+ }
+ assertNotNull(sample)
+
+ val expectedBody = "println(\"hello from sample\")"
+ assertEquals(expectedBody, sample.body)
+ }
+ }
+
+ @Test
+ fun `should see two identical snippets as equal`() {
+ val firstSnippet = createHardcodedSnippet()
+ val secondSnippet = createHardcodedSnippet()
+
+ assertEquals(firstSnippet, secondSnippet)
+ }
+
+ @Test
+ fun `should return same hashcode for two equal sample snippets`() {
+ val firstSnippet = createHardcodedSnippet()
+ val secondSnippet = createHardcodedSnippet()
+
+ assertEquals(firstSnippet.hashCode(), secondSnippet.hashCode())
+ }
+
+ private fun createHardcodedSnippet(): SampleSnippet {
+ return SampleSnippet(
+ imports = listOf(
+ "org.jetbrains.dokka.DokkaConfiguration",
+ "org.jetbrains.dokka.DokkaConfiguration.DokkaSourceSet",
+ ),
+ body = """
+ class Foo {
+ fun bar(): String = TODO()
+ }
+ """.trimIndent()
+ )
+ }
+
+ @Test
+ @Ignore // TODO [beresnev] should be implemented when there's api for KMP projects
+ fun `should return null for existing sample when resolving with the wrong source set`() {}
}