diff options
Diffstat (limited to 'testApi')
-rw-r--r-- | testApi/build.gradle | 12 | ||||
-rw-r--r-- | testApi/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt | 41 | ||||
-rw-r--r-- | testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt | 207 |
3 files changed, 260 insertions, 0 deletions
diff --git a/testApi/build.gradle b/testApi/build.gradle new file mode 100644 index 00000000..5425b7bc --- /dev/null +++ b/testApi/build.gradle @@ -0,0 +1,12 @@ +buildscript { + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + } +} +apply plugin: 'kotlin' + +dependencies { + implementation project(':core') + implementation group: 'junit', name: 'junit', version: '4.12' + implementation group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlin_version +}
\ No newline at end of file diff --git a/testApi/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt b/testApi/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt new file mode 100644 index 00000000..50e88f2b --- /dev/null +++ b/testApi/src/main/kotlin/testApi/testRunner/DokkaTestGenerator.kt @@ -0,0 +1,41 @@ +package testApi.testRunner + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.DokkaGenerator +import org.jetbrains.dokka.EnvironmentAndFacade +import org.jetbrains.dokka.pages.PlatformData +import org.jetbrains.dokka.utilities.DokkaLogger + +internal class DokkaTestGenerator( + private val configuration: DokkaConfiguration, + private val logger: DokkaLogger, + private val testMethods: TestMethods +) { + + fun generate() = with(testMethods) { + val dokkaGenerator = DokkaGenerator(configuration, logger) + + val platforms: Map<PlatformData, EnvironmentAndFacade> = dokkaGenerator.setUpAnalysis(configuration) + analysisSetupStage(platforms) + + val context = dokkaGenerator.initializePlugins(configuration, logger, platforms) + pluginsSetupStage(context) + + val modulesFromPlatforms = dokkaGenerator.createDocumentationModels(platforms, context) + documentablesCreationStage(modulesFromPlatforms) + + val documentationModel = dokkaGenerator.mergeDocumentationModels(modulesFromPlatforms, context) + documentablesMergingStage(documentationModel) + + val transformedDocumentation = dokkaGenerator.transformDocumentationModel(documentationModel, context) + documentablesTransformationStage(transformedDocumentation) + + val pages = dokkaGenerator.createPages(transformedDocumentation, context) + pagesGenerationStage(pages) + + val transformedPages = dokkaGenerator.transformPages(pages, context) + pagesTransformationStage(transformedPages) + + dokkaGenerator.render(transformedPages, context) + } +}
\ No newline at end of file diff --git a/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt b/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt new file mode 100644 index 00000000..fdc2d0f7 --- /dev/null +++ b/testApi/src/main/kotlin/testApi/testRunner/TestRunner.kt @@ -0,0 +1,207 @@ +package testApi.testRunner + +import org.jetbrains.dokka.* +import org.jetbrains.dokka.model.Module +import org.jetbrains.dokka.pages.ModulePageNode +import org.jetbrains.dokka.pages.PlatformData +import org.jetbrains.dokka.plugability.DokkaContext +import org.jetbrains.dokka.utilities.DokkaConsoleLogger +import org.junit.rules.TemporaryFolder +import java.io.File +import java.nio.charset.Charset +import java.nio.file.Files +import java.nio.file.InvalidPathException +import java.nio.file.Path +import java.nio.file.Paths + +// TODO: take dokka configuration from file +abstract class AbstractCoreTest { + protected val logger = DokkaConsoleLogger + + protected fun getTestDataDir(name: String) = + File("src/test/resources/$name").takeIf { it.exists() }?.toPath() + ?: throw InvalidPathException(name, "Cannot be found") + + protected fun testFromData( + configuration: DokkaConfigurationImpl, + cleanupOutput: Boolean = true, + block: TestBuilder.() -> Unit + ) { + val testMethods = TestBuilder().apply(block).build() + val tempDir = getTempDir(cleanupOutput) + if (!cleanupOutput) + logger.info("Output generated under: ${tempDir.root.absolutePath}") + val newConfiguration = + configuration.copy( + outputDir = tempDir.root.toPath().toAbsolutePath().toString() + ) + DokkaTestGenerator(newConfiguration, logger, testMethods).generate() + } + + protected fun testInline( + query: String, + configuration: DokkaConfigurationImpl, + cleanupOutput: Boolean = true, + block: TestBuilder.() -> Unit + ) { + val testMethods = TestBuilder().apply(block).build() + val testDirPath = getTempDir(cleanupOutput).root.toPath() + val fileMap = query.toFileMap() + fileMap.materializeFiles(testDirPath.toAbsolutePath()) + if (!cleanupOutput) + logger.info("Output generated under: ${testDirPath.toAbsolutePath()}") + val newConfiguration = + configuration.copy( + outputDir = testDirPath.toAbsolutePath().toString(), + passesConfigurations = configuration.passesConfigurations + .map { it.copy(sourceRoots = it.sourceRoots.map { it.copy(path = "${testDirPath.toAbsolutePath()}/${it.path}") }) } + ) + DokkaTestGenerator(newConfiguration, logger, testMethods).generate() + } + + private fun String.toFileMap(): Map<String, String> = this.trimMargin().removePrefix("|") + .replace("\r\n", "\n") + .split("\n/") + .map { fileString -> + fileString.split("\n", limit = 2) + .let { + it.first().trim().removePrefix("/") to it.last().trim() + } + }.toMap() + + private fun Map<String, String>.materializeFiles( + root: Path = Paths.get("."), + charset: Charset = Charset.forName("utf-8") + ) = this.map { (path, content) -> + val file = root.resolve(path) + Files.createDirectories(file.parent) + Files.write(file, content.toByteArray(charset)) + } + + private fun getTempDir(cleanupOutput: Boolean) = if (cleanupOutput) { + TemporaryFolder().apply { create() } + } else { + object : TemporaryFolder() { + override fun after() {} + }.apply { create() } + } + + protected class TestBuilder { + var analysisSetupStage: (Map<PlatformData, EnvironmentAndFacade>) -> Unit = {} + var pluginsSetupStage: (DokkaContext) -> Unit = {} + var documentablesCreationStage: (List<Module>) -> Unit = {} + var documentablesMergingStage: (Module) -> Unit = {} + var documentablesTransformationStage: (Module) -> Unit = {} + var pagesGenerationStage: (ModulePageNode) -> Unit = {} + var pagesTransformationStage: (ModulePageNode) -> Unit = {} + + fun build() = TestMethods( + analysisSetupStage, + pluginsSetupStage, + documentablesCreationStage, + documentablesMergingStage, + documentablesTransformationStage, + pagesGenerationStage, + pagesTransformationStage + ) + } + + protected fun dokkaConfiguration(block: DokkaConfigurationBuilder.() -> Unit): DokkaConfigurationImpl = + DokkaConfigurationBuilder().apply(block).build() + + @DslMarker + protected annotation class DokkaConfigurationDsl + + @DokkaConfigurationDsl + protected class DokkaConfigurationBuilder { + var outputDir: String = "out" + var format: String = "html" + var generateIndexPages: Boolean = true + var cacheRoot: String? = null + var pluginsClasspath: List<File> = emptyList() + private val passesConfigurations = mutableListOf<PassConfigurationImpl>() + + fun build() = DokkaConfigurationImpl( + outputDir = outputDir, + format = format, + generateIndexPages = generateIndexPages, + cacheRoot = cacheRoot, + impliedPlatforms = emptyList(), + passesConfigurations = passesConfigurations, + pluginsClasspath = pluginsClasspath + ) + + fun passes(block: Passes.() -> Unit) { + passesConfigurations.addAll(Passes().apply(block)) + } + } + + @DokkaConfigurationDsl + protected class Passes : ArrayList<PassConfigurationImpl>() { + fun pass(block: DokkaPassConfigurationBuilder.() -> Unit) = + add(DokkaPassConfigurationBuilder().apply(block).build()) + } + + @DokkaConfigurationDsl + protected class DokkaPassConfigurationBuilder( + var moduleName: String = "root", + var classpath: List<String> = emptyList(), + var sourceRoots: List<String> = emptyList(), + var samples: List<String> = emptyList(), + var includes: List<String> = emptyList(), + var includeNonPublic: Boolean = true, + var includeRootPackage: Boolean = true, + var reportUndocumented: Boolean = false, + var skipEmptyPackages: Boolean = false, + var skipDeprecated: Boolean = false, + var jdkVersion: Int = 6, + var languageVersion: String? = null, + var apiVersion: String? = null, + var noStdlibLink: Boolean = false, + var noJdkLink: Boolean = false, + var suppressedFiles: List<String> = emptyList(), + var collectInheritedExtensionsFromLibraries: Boolean = true, + var analysisPlatform: String = "jvm", + var targets: List<String> = listOf("jvm"), + var sinceKotlin: String? = null, + var perPackageOptions: List<PackageOptionsImpl> = emptyList(), + var externalDocumentationLinks: List<ExternalDocumentationLinkImpl> = emptyList(), + var sourceLinks: List<SourceLinkDefinitionImpl> = emptyList() + ) { + fun build() = PassConfigurationImpl( + moduleName = moduleName, + classpath = classpath, + sourceRoots = sourceRoots.map { SourceRootImpl(it) }, + samples = samples, + includes = includes, + includeNonPublic = includeNonPublic, + includeRootPackage = includeRootPackage, + reportUndocumented = reportUndocumented, + skipEmptyPackages = skipEmptyPackages, + skipDeprecated = skipDeprecated, + jdkVersion = jdkVersion, + languageVersion = languageVersion, + apiVersion = apiVersion, + noStdlibLink = noStdlibLink, + noJdkLink = noJdkLink, + suppressedFiles = suppressedFiles, + collectInheritedExtensionsFromLibraries = collectInheritedExtensionsFromLibraries, + analysisPlatform = Platform.fromString(analysisPlatform), + targets = targets, + sinceKotlin = sinceKotlin, + perPackageOptions = perPackageOptions, + externalDocumentationLinks = externalDocumentationLinks, + sourceLinks = sourceLinks + ) + } +} + +data class TestMethods( + val analysisSetupStage: (Map<PlatformData, EnvironmentAndFacade>) -> Unit, + val pluginsSetupStage: (DokkaContext) -> Unit, + val documentablesCreationStage: (List<Module>) -> Unit, + val documentablesMergingStage: (Module) -> Unit, + val documentablesTransformationStage: (Module) -> Unit, + val pagesGenerationStage: (ModulePageNode) -> Unit, + val pagesTransformationStage: (ModulePageNode) -> Unit +)
\ No newline at end of file |