From f4920fc9d067e59a5d843a185e07c5d321c91c6d Mon Sep 17 00:00:00 2001 From: Kamil Doległo Date: Wed, 11 Sep 2019 15:34:55 +0200 Subject: Extract testApi from core --- core/build.gradle | 1 + .../DokkaConfigurationTestImplementations.kt | 81 ----- core/src/test/kotlin/TestAPI.kt | 353 --------------------- core/src/test/kotlin/format/GFMFormatTest.kt | 6 +- core/src/test/kotlin/format/HtmlFormatTest.kt | 3 + .../kotlin/format/KotlinWebSiteHtmlFormatTest.kt | 8 +- core/src/test/kotlin/format/MarkdownFormatTest.kt | 9 +- core/src/test/kotlin/format/PackageDocsTest.kt | 3 +- core/src/test/kotlin/issues/IssuesTest.kt | 4 +- core/src/test/kotlin/model/ClassTest.kt | 4 + core/src/test/kotlin/model/CommentTest.kt | 9 +- core/src/test/kotlin/model/FunctionTest.kt | 5 +- core/src/test/kotlin/model/JavaTest.kt | 3 + core/src/test/kotlin/model/KotlinAsJavaTest.kt | 3 + core/src/test/kotlin/model/LinkTest.kt | 3 + core/src/test/kotlin/model/PackageTest.kt | 5 +- core/src/test/kotlin/model/PropertyTest.kt | 2 + core/src/test/kotlin/model/SourceLinksErrorTest.kt | 4 +- core/src/test/kotlin/model/SourceLinksTest.kt | 4 +- core/src/test/kotlin/model/TypeAliasTest.kt | 2 + core/testApi/build.gradle | 3 + .../DokkaConfigurationTestImplementations.kt | 81 +++++ core/testApi/src/main/kotlin/testApi/TestAPI.kt | 353 +++++++++++++++++++++ 23 files changed, 495 insertions(+), 454 deletions(-) delete mode 100644 core/src/test/kotlin/DokkaConfigurationTestImplementations.kt delete mode 100644 core/src/test/kotlin/TestAPI.kt create mode 100644 core/testApi/src/main/kotlin/testApi/DokkaConfigurationTestImplementations.kt create mode 100644 core/testApi/src/main/kotlin/testApi/TestAPI.kt (limited to 'core') diff --git a/core/build.gradle b/core/build.gradle index 76601901..f3fe35e4 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -50,6 +50,7 @@ dependencies { testImplementation "org.jetbrains.kotlin:kotlin-stdlib-js:$bundled_kotlin_compiler_version" testImplementation "org.jetbrains.kotlin:kotlin-stdlib-common:$bundled_kotlin_compiler_version" + testImplementation project(":core:testApi") testCompile ideaRT() } diff --git a/core/src/test/kotlin/DokkaConfigurationTestImplementations.kt b/core/src/test/kotlin/DokkaConfigurationTestImplementations.kt deleted file mode 100644 index a6f427b1..00000000 --- a/core/src/test/kotlin/DokkaConfigurationTestImplementations.kt +++ /dev/null @@ -1,81 +0,0 @@ -package org.jetbrains.dokka.tests - -import org.jetbrains.dokka.DokkaConfiguration -import org.jetbrains.dokka.Platform -import java.io.File - - -data class SourceLinkDefinitionImpl(override val path: String, - override val url: String, - override val lineSuffix: String?) : DokkaConfiguration.SourceLinkDefinition { - companion object { - fun parseSourceLinkDefinition(srcLink: String): DokkaConfiguration.SourceLinkDefinition { - val (path, urlAndLine) = srcLink.split('=') - return SourceLinkDefinitionImpl( - File(path).canonicalPath, - urlAndLine.substringBefore("#"), - urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" }) - } - } -} - -class SourceRootImpl(path: String) : DokkaConfiguration.SourceRoot { - override val path: String = File(path).absolutePath - - companion object { - fun parseSourceRoot(sourceRoot: String): DokkaConfiguration.SourceRoot = SourceRootImpl(sourceRoot) - } -} - -data class PackageOptionsImpl(override val prefix: String, - override val includeNonPublic: Boolean = false, - override val reportUndocumented: Boolean = true, - override val skipDeprecated: Boolean = false, - override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions - - class DokkaConfigurationImpl( - override val outputDir: String = "", - override val format: String = "html", - override val generateIndexPages: Boolean = false, - override val cacheRoot: String? = null, - override val impliedPlatforms: List = emptyList(), - override val passesConfigurations: List = emptyList() -) : DokkaConfiguration - -class PassConfigurationImpl ( - override val classpath: List = emptyList(), - override val moduleName: String = "", - override val sourceRoots: List = emptyList(), - override val samples: List = emptyList(), - override val includes: List = emptyList(), - override val includeNonPublic: Boolean = false, - override val includeRootPackage: Boolean = false, - override val reportUndocumented: Boolean = false, - override val skipEmptyPackages: Boolean = false, - override val skipDeprecated: Boolean = false, - override val jdkVersion: Int = 6, - override val sourceLinks: List = emptyList(), - override val perPackageOptions: List = emptyList(), - externalDocumentationLinks: List = emptyList(), - override val languageVersion: String? = null, - override val apiVersion: String? = null, - override val noStdlibLink: Boolean = false, - override val noJdkLink: Boolean = false, - override val suppressedFiles: List = emptyList(), - override val collectInheritedExtensionsFromLibraries: Boolean = false, - override val analysisPlatform: Platform = Platform.DEFAULT, - override val targets: List = emptyList(), - override val sinceKotlin: String? = null -): DokkaConfiguration.PassConfiguration { - private val defaultLinks = run { - val links = mutableListOf() - if (!noJdkLink) - links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build() - - if (!noStdlibLink) - links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() - links - } - override val externalDocumentationLinks = defaultLinks + externalDocumentationLinks -} - diff --git a/core/src/test/kotlin/TestAPI.kt b/core/src/test/kotlin/TestAPI.kt deleted file mode 100644 index 4f9af761..00000000 --- a/core/src/test/kotlin/TestAPI.kt +++ /dev/null @@ -1,353 +0,0 @@ -package org.jetbrains.dokka.tests - -import com.google.inject.Guice -import com.intellij.openapi.application.PathManager -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.util.io.FileUtil -import com.intellij.rt.execution.junit.FileComparisonFailure -import org.jetbrains.dokka.* -import org.jetbrains.dokka.Utilities.DokkaAnalysisModule -import org.jetbrains.dokka.Utilities.DokkaRunModule -import org.jetbrains.kotlin.cli.common.config.ContentRoot -import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation -import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity -import org.jetbrains.kotlin.cli.common.messages.MessageCollector -import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.utils.PathUtil -import org.junit.Assert -import org.junit.Assert.fail -import java.io.File - -data class ModelConfig( - val roots: Array = arrayOf(), - val withJdk: Boolean = false, - val withKotlinRuntime: Boolean = false, - val format: String = "html", - val includeNonPublic: Boolean = true, - val perPackageOptions: List = emptyList(), - val analysisPlatform: Platform = Platform.DEFAULT, - val defaultPlatforms: List = emptyList(), - val noStdlibLink: Boolean = true, - val collectInheritedExtensionsFromLibraries: Boolean = false, - val sourceLinks: List = emptyList() -) - -fun verifyModel( - modelConfig: ModelConfig, - verifier: (DocumentationModule) -> Unit -) { - val documentation = DocumentationModule("test") - - val passConfiguration = PassConfigurationImpl( - includeNonPublic = modelConfig.includeNonPublic, - skipEmptyPackages = false, - includeRootPackage = true, - sourceLinks = modelConfig.sourceLinks, - perPackageOptions = modelConfig.perPackageOptions, - noStdlibLink = modelConfig.noStdlibLink, - noJdkLink = false, - languageVersion = null, - apiVersion = null, - collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries - ) - val configuration = DokkaConfigurationImpl( - outputDir = "", - format = modelConfig.format, - generateIndexPages = false, - cacheRoot = "default", - passesConfigurations = listOf(passConfiguration) - ) - - appendDocumentation(documentation, configuration, passConfiguration, modelConfig) - documentation.prepareForGeneration(configuration) - - verifier(documentation) -} - -fun appendDocumentation( - documentation: DocumentationModule, - dokkaConfiguration: DokkaConfiguration, - passConfiguration: DokkaConfiguration.PassConfiguration, - modelConfig: ModelConfig -) { - val messageCollector = object : MessageCollector { - override fun clear() { - - } - - override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { - when (severity) { - CompilerMessageSeverity.STRONG_WARNING, - CompilerMessageSeverity.WARNING, - CompilerMessageSeverity.LOGGING, - CompilerMessageSeverity.OUTPUT, - CompilerMessageSeverity.INFO, - CompilerMessageSeverity.ERROR -> { - println("$severity: $message at $location") - } - CompilerMessageSeverity.EXCEPTION -> { - fail("$severity: $message at $location") - } - } - } - - override fun hasErrors() = false - } - - val environment = AnalysisEnvironment(messageCollector, modelConfig.analysisPlatform) - environment.apply { - if (modelConfig.withJdk || modelConfig.withKotlinRuntime) { - addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) - } - if (modelConfig.withKotlinRuntime) { - if (analysisPlatform == Platform.jvm) { - val kotlinStrictfpRoot = PathManager.getResourceRoot(Strictfp::class.java, "/kotlin/jvm/Strictfp.class") - addClasspath(File(kotlinStrictfpRoot)) - } - if (analysisPlatform == Platform.js) { - val kotlinStdlibJsRoot = PathManager.getResourceRoot(Any::class.java, "/kotlin/jquery") - addClasspath(File(kotlinStdlibJsRoot)) - } - - if (analysisPlatform == Platform.common) { - // TODO: Feels hacky - val kotlinStdlibCommonRoot = ClassLoader.getSystemResource("kotlin/UInt.kotlin_metadata") - addClasspath(File(kotlinStdlibCommonRoot.file.replace("file:", "").replaceAfter(".jar", ""))) - } - } - addRoots(modelConfig.roots.toList()) - - loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) - } - val defaultPlatformsProvider = object : DefaultPlatformsProvider { - override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms - } - - val globalInjector = Guice.createInjector( - DokkaRunModule(dokkaConfiguration) - ) - - val injector = globalInjector.createChildInjector( - DokkaAnalysisModule( - environment, - dokkaConfiguration, - defaultPlatformsProvider, - documentation.nodeRefGraph, - passConfiguration, - DokkaConsoleLogger - ) - ) - - buildDocumentationModule(injector, documentation) - Disposer.dispose(environment) -} - -fun checkSourceExistsAndVerifyModel( - source: String, - modelConfig: ModelConfig = ModelConfig(), - verifier: (DocumentationModule) -> Unit -) { - require(File(source).exists()) { - "Cannot find test data file $source" - } - verifyModel( - ModelConfig( - roots = arrayOf(contentRootFromPath(source)), - withJdk = modelConfig.withJdk, - withKotlinRuntime = modelConfig.withKotlinRuntime, - format = modelConfig.format, - includeNonPublic = modelConfig.includeNonPublic, - sourceLinks = modelConfig.sourceLinks, - analysisPlatform = modelConfig.analysisPlatform - ), - - verifier = verifier - ) -} - -fun verifyPackageMember( - source: String, - modelConfig: ModelConfig = ModelConfig(), - verifier: (DocumentationNode) -> Unit -) { - checkSourceExistsAndVerifyModel( - source, - modelConfig = ModelConfig( - withJdk = modelConfig.withJdk, - withKotlinRuntime = modelConfig.withKotlinRuntime, - analysisPlatform = modelConfig.analysisPlatform - ) - ) { model -> - val pkg = model.members.single() - verifier(pkg.members.single()) - } -} - -fun verifyJavaModel( - source: String, - modelConfig: ModelConfig = ModelConfig(), - verifier: (DocumentationModule) -> Unit -) { - val tempDir = FileUtil.createTempDirectory("dokka", "") - try { - val sourceFile = File(source) - FileUtil.copy(sourceFile, File(tempDir, sourceFile.name)) - verifyModel( - ModelConfig( - roots = arrayOf(JavaSourceRoot(tempDir, null)), - withJdk = true, - withKotlinRuntime = modelConfig.withKotlinRuntime, - analysisPlatform = modelConfig.analysisPlatform - ), - verifier = verifier - ) - } finally { - FileUtil.delete(tempDir) - } -} - -fun verifyJavaPackageMember( - source: String, - modelConfig: ModelConfig = ModelConfig(), - verifier: (DocumentationNode) -> Unit -) { - verifyJavaModel(source, modelConfig) { model -> - val pkg = model.members.single() - verifier(pkg.members.single()) - } -} - -fun verifyOutput( - modelConfig: ModelConfig = ModelConfig(), - outputExtension: String, - outputGenerator: (DocumentationModule, StringBuilder) -> Unit -) { - verifyModel(modelConfig) { - verifyModelOutput(it, outputExtension, modelConfig.roots.first().path, outputGenerator) - } -} - -fun verifyOutput( - path: String, - outputExtension: String, - modelConfig: ModelConfig = ModelConfig(), - outputGenerator: (DocumentationModule, StringBuilder) -> Unit -) { - verifyOutput( - ModelConfig( - roots = arrayOf(contentRootFromPath(path)) + modelConfig.roots, - withJdk = modelConfig.withJdk, - withKotlinRuntime = modelConfig.withKotlinRuntime, - format = modelConfig.format, - includeNonPublic = modelConfig.includeNonPublic, - analysisPlatform = modelConfig.analysisPlatform, - noStdlibLink = modelConfig.noStdlibLink, - collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries - ), - outputExtension, - outputGenerator - ) -} - -fun verifyModelOutput( - it: DocumentationModule, - outputExtension: String, - sourcePath: String, - outputGenerator: (DocumentationModule, StringBuilder) -> Unit -) { - val output = StringBuilder() - outputGenerator(it, output) - val ext = outputExtension.removePrefix(".") - val expectedFile = File(sourcePath.replaceAfterLast(".", ext, sourcePath + "." + ext)) - assertEqualsIgnoringSeparators(expectedFile, output.toString()) -} - -fun verifyJavaOutput( - path: String, - outputExtension: String, - modelConfig: ModelConfig = ModelConfig(), - outputGenerator: (DocumentationModule, StringBuilder) -> Unit -) { - verifyJavaModel(path, modelConfig) { model -> - verifyModelOutput(model, outputExtension, path, outputGenerator) - } -} - -fun assertEqualsIgnoringSeparators(expectedFile: File, output: String) { - if (!expectedFile.exists()) expectedFile.createNewFile() - val expectedText = expectedFile.readText().replace("\r\n", "\n") - val actualText = output.replace("\r\n", "\n") - - if (expectedText != actualText) - throw FileComparisonFailure("", expectedText, actualText, expectedFile.canonicalPath) -} - -fun assertEqualsIgnoringSeparators(expectedOutput: String, output: String) { - Assert.assertEquals(expectedOutput.replace("\r\n", "\n"), output.replace("\r\n", "\n")) -} - -fun StringBuilder.appendChildren(node: ContentBlock): StringBuilder { - for (child in node.children) { - val childText = child.toTestString() - append(childText) - } - return this -} - -fun StringBuilder.appendNode(node: ContentNode): StringBuilder { - when (node) { - is ContentText -> { - append(node.text) - } - is ContentEmphasis -> append("*").appendChildren(node).append("*") - is ContentBlockCode -> { - if (node.language.isNotBlank()) - appendln("[code lang=${node.language}]") - else - appendln("[code]") - appendChildren(node) - appendln() - appendln("[/code]") - } - is ContentNodeLink -> { - append("[") - appendChildren(node) - append(" -> ") - append(node.node.toString()) - append("]") - } - is ContentBlock -> { - appendChildren(node) - } - is NodeRenderContent -> { - append("render(") - append(node.node) - append(",") - append(node.mode) - append(")") - } - is ContentSymbol -> { - append(node.text) - } - is ContentEmpty -> { /* nothing */ - } - else -> throw IllegalStateException("Don't know how to format node $node") - } - return this -} - -fun ContentNode.toTestString(): String { - val node = this - return StringBuilder().apply { - appendNode(node) - }.toString() -} - -val ContentRoot.path: String - get() = when (this) { - is KotlinSourceRoot -> path - is JavaSourceRoot -> file.path - else -> throw UnsupportedOperationException() - } diff --git a/core/src/test/kotlin/format/GFMFormatTest.kt b/core/src/test/kotlin/format/GFMFormatTest.kt index 60de7d29..4807d0f2 100644 --- a/core/src/test/kotlin/format/GFMFormatTest.kt +++ b/core/src/test/kotlin/format/GFMFormatTest.kt @@ -3,6 +3,8 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.GFMFormatService import org.jetbrains.dokka.KotlinLanguageService import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.verifyOutput import org.junit.Test abstract class BaseGFMFormatTest(val analysisPlatform: Platform) : FileGeneratorTestCase() { @@ -23,8 +25,8 @@ abstract class BaseGFMFormatTest(val analysisPlatform: Platform) : FileGenerator private fun verifyGFMNodeByName(fileName: String, name: String, modelConfig: ModelConfig) { verifyOutput("testdata/format/gfm/$fileName.kt", ".md", modelConfig) { model, output -> buildPagesAndReadInto( - model.members.single().members.filter { it.name == name }, - output + model.members.single().members.filter { it.name == name }, + output ) } } diff --git a/core/src/test/kotlin/format/HtmlFormatTest.kt b/core/src/test/kotlin/format/HtmlFormatTest.kt index 60e29006..a1742280 100644 --- a/core/src/test/kotlin/format/HtmlFormatTest.kt +++ b/core/src/test/kotlin/format/HtmlFormatTest.kt @@ -1,6 +1,9 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.verifyJavaOutput +import org.jetbrains.dokka.testApi.verifyOutput import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot import org.junit.Test diff --git a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt index ebab5f36..d8b34394 100644 --- a/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt +++ b/core/src/test/kotlin/format/KotlinWebSiteHtmlFormatTest.kt @@ -2,6 +2,10 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* import org.jetbrains.dokka.Generation.DocumentationMerger +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.appendDocumentation +import org.jetbrains.dokka.testApi.verifyModelOutput +import org.jetbrains.dokka.testApi.verifyOutput import org.junit.Test abstract class BaseKotlinWebSiteHtmlFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() { @@ -65,14 +69,14 @@ abstract class BaseKotlinWebSiteHtmlFormatTest(val analysisPlatform: Platform): private fun buildMultiplePlatforms(path: String): DocumentationModule { val moduleName = "test" - val passConfiguration = PassConfigurationImpl( + val passConfiguration = org.jetbrains.dokka.testApi.PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) - val dokkaConfiguration = DokkaConfigurationImpl( + val dokkaConfiguration = org.jetbrains.dokka.testApi.DokkaConfigurationImpl( outputDir = "", format = "kotlin-website-html", generateIndexPages = false, diff --git a/core/src/test/kotlin/format/MarkdownFormatTest.kt b/core/src/test/kotlin/format/MarkdownFormatTest.kt index 4984e1d5..8900b267 100644 --- a/core/src/test/kotlin/format/MarkdownFormatTest.kt +++ b/core/src/test/kotlin/format/MarkdownFormatTest.kt @@ -2,6 +2,7 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* import org.jetbrains.dokka.Generation.DocumentationMerger +import org.jetbrains.dokka.testApi.* import org.junit.Test abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGeneratorTestCase() { @@ -257,14 +258,14 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener @Test fun packagePlatformsWithExtExtensions() { val path = "multiplatform/packagePlatformsWithExtExtensions" val module = DocumentationModule("test") - val passConfiguration = PassConfigurationImpl( + val passConfiguration = org.jetbrains.dokka.testApi.PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) - val dokkaConfiguration = DokkaConfigurationImpl( + val dokkaConfiguration = org.jetbrains.dokka.testApi.DokkaConfigurationImpl( outputDir = "", format = "html", generateIndexPages = false, @@ -388,13 +389,13 @@ abstract class BaseMarkdownFormatTest(val analysisPlatform: Platform): FileGener private fun buildMultiplePlatforms(path: String): DocumentationModule { val moduleName = "test" - val passConfiguration = PassConfigurationImpl( + val passConfiguration = org.jetbrains.dokka.testApi.PassConfigurationImpl( noStdlibLink = true, noJdkLink = true, languageVersion = null, apiVersion = null ) - val dokkaConfiguration = DokkaConfigurationImpl( + val dokkaConfiguration = org.jetbrains.dokka.testApi.DokkaConfigurationImpl( outputDir = "", format = "html", generateIndexPages = false, diff --git a/core/src/test/kotlin/format/PackageDocsTest.kt b/core/src/test/kotlin/format/PackageDocsTest.kt index 3ff5f123..c5fe7beb 100644 --- a/core/src/test/kotlin/format/PackageDocsTest.kt +++ b/core/src/test/kotlin/format/PackageDocsTest.kt @@ -7,10 +7,9 @@ import com.nhaarman.mockito_kotlin.doAnswer import com.nhaarman.mockito_kotlin.eq import com.nhaarman.mockito_kotlin.mock import org.jetbrains.dokka.* -import org.jetbrains.dokka.tests.assertEqualsIgnoringSeparators +import org.jetbrains.dokka.testApi.assertEqualsIgnoringSeparators import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreProjectEnvironment import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.junit.After diff --git a/core/src/test/kotlin/issues/IssuesTest.kt b/core/src/test/kotlin/issues/IssuesTest.kt index da5acd6e..80370d5e 100644 --- a/core/src/test/kotlin/issues/IssuesTest.kt +++ b/core/src/test/kotlin/issues/IssuesTest.kt @@ -3,8 +3,8 @@ package issues import org.jetbrains.dokka.DocumentationNode import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.Platform -import org.jetbrains.dokka.tests.ModelConfig -import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel import org.junit.Test import kotlin.test.assertEquals diff --git a/core/src/test/kotlin/model/ClassTest.kt b/core/src/test/kotlin/model/ClassTest.kt index 35ec1d09..b479e59e 100644 --- a/core/src/test/kotlin/model/ClassTest.kt +++ b/core/src/test/kotlin/model/ClassTest.kt @@ -4,6 +4,10 @@ import org.jetbrains.dokka.Content import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.Platform import org.jetbrains.dokka.RefKind +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.toTestString +import org.jetbrains.dokka.testApi.verifyPackageMember import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/core/src/test/kotlin/model/CommentTest.kt b/core/src/test/kotlin/model/CommentTest.kt index 08aa3572..b94e9d0c 100644 --- a/core/src/test/kotlin/model/CommentTest.kt +++ b/core/src/test/kotlin/model/CommentTest.kt @@ -1,8 +1,13 @@ package org.jetbrains.dokka.tests +import org.jetbrains.dokka.Content +import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.assertEqualsIgnoringSeparators +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.toTestString +import org.junit.Assert.assertEquals import org.junit.Test -import org.junit.Assert.* -import org.jetbrains.dokka.* abstract class BaseCommentTest(val analysisPlatform: Platform) { val defaultModelConfig = ModelConfig(analysisPlatform = analysisPlatform) diff --git a/core/src/test/kotlin/model/FunctionTest.kt b/core/src/test/kotlin/model/FunctionTest.kt index 4c6bfb74..9900446a 100644 --- a/core/src/test/kotlin/model/FunctionTest.kt +++ b/core/src/test/kotlin/model/FunctionTest.kt @@ -3,7 +3,10 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.Content import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.Platform -import org.jetbrains.kotlin.analyzer.PlatformAnalysisParameters +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.toTestString +import org.jetbrains.dokka.testApi.verifyPackageMember import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/core/src/test/kotlin/model/JavaTest.kt b/core/src/test/kotlin/model/JavaTest.kt index da9da624..018ab089 100644 --- a/core/src/test/kotlin/model/JavaTest.kt +++ b/core/src/test/kotlin/model/JavaTest.kt @@ -3,6 +3,9 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.Platform import org.jetbrains.dokka.RefKind +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.toTestString +import org.jetbrains.dokka.testApi.verifyJavaPackageMember import org.junit.Assert.* import org.junit.Ignore import org.junit.Test diff --git a/core/src/test/kotlin/model/KotlinAsJavaTest.kt b/core/src/test/kotlin/model/KotlinAsJavaTest.kt index 8249dd0f..80ff95bd 100644 --- a/core/src/test/kotlin/model/KotlinAsJavaTest.kt +++ b/core/src/test/kotlin/model/KotlinAsJavaTest.kt @@ -4,6 +4,9 @@ import org.jetbrains.dokka.DocumentationModule import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.Platform import org.jetbrains.dokka.RefKind +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.toTestString import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Test diff --git a/core/src/test/kotlin/model/LinkTest.kt b/core/src/test/kotlin/model/LinkTest.kt index 6526a4db..08e27db8 100644 --- a/core/src/test/kotlin/model/LinkTest.kt +++ b/core/src/test/kotlin/model/LinkTest.kt @@ -4,6 +4,9 @@ import org.jetbrains.dokka.ContentBlock import org.jetbrains.dokka.ContentNodeLazyLink import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.Platform +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.toTestString import org.junit.Assert.assertEquals import org.junit.Test diff --git a/core/src/test/kotlin/model/PackageTest.kt b/core/src/test/kotlin/model/PackageTest.kt index 47c88385..0afbbb5d 100644 --- a/core/src/test/kotlin/model/PackageTest.kt +++ b/core/src/test/kotlin/model/PackageTest.kt @@ -1,6 +1,9 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.verifyModel import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot import org.junit.Assert.* import org.junit.Test @@ -121,7 +124,7 @@ abstract class BasePackageTest(val analysisPlatform: Platform) { ModelConfig( roots = arrayOf(KotlinSourceRoot("testdata/packages/classInPackage.kt", false)), perPackageOptions = listOf( - PackageOptionsImpl(prefix = "simple.name", suppress = true) + org.jetbrains.dokka.testApi.PackageOptionsImpl(prefix = "simple.name", suppress = true) ), analysisPlatform = analysisPlatform ) diff --git a/core/src/test/kotlin/model/PropertyTest.kt b/core/src/test/kotlin/model/PropertyTest.kt index 9f070862..bce3c585 100644 --- a/core/src/test/kotlin/model/PropertyTest.kt +++ b/core/src/test/kotlin/model/PropertyTest.kt @@ -1,6 +1,8 @@ package org.jetbrains.dokka.tests import org.jetbrains.dokka.* +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel import org.junit.Assert import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue diff --git a/core/src/test/kotlin/model/SourceLinksErrorTest.kt b/core/src/test/kotlin/model/SourceLinksErrorTest.kt index 9812569d..2d587856 100644 --- a/core/src/test/kotlin/model/SourceLinksErrorTest.kt +++ b/core/src/test/kotlin/model/SourceLinksErrorTest.kt @@ -2,8 +2,8 @@ package org.jetbrains.dokka.tests.model import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.SourceLinkDefinitionImpl -import org.jetbrains.dokka.tests.ModelConfig -import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel import org.junit.Assert import org.junit.Test import java.io.File diff --git a/core/src/test/kotlin/model/SourceLinksTest.kt b/core/src/test/kotlin/model/SourceLinksTest.kt index a4ba870c..8f7766f6 100644 --- a/core/src/test/kotlin/model/SourceLinksTest.kt +++ b/core/src/test/kotlin/model/SourceLinksTest.kt @@ -2,8 +2,8 @@ package org.jetbrains.dokka.tests.model import org.jetbrains.dokka.NodeKind import org.jetbrains.dokka.SourceLinkDefinitionImpl -import org.jetbrains.dokka.tests.ModelConfig -import org.jetbrains.dokka.tests.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.ModelConfig +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel import org.junit.Assert import org.junit.Test import org.junit.runner.RunWith diff --git a/core/src/test/kotlin/model/TypeAliasTest.kt b/core/src/test/kotlin/model/TypeAliasTest.kt index 71976dc3..6c9b90a8 100644 --- a/core/src/test/kotlin/model/TypeAliasTest.kt +++ b/core/src/test/kotlin/model/TypeAliasTest.kt @@ -3,6 +3,8 @@ package org.jetbrains.dokka.tests import junit.framework.TestCase.assertEquals import org.jetbrains.dokka.Content import org.jetbrains.dokka.NodeKind +import org.jetbrains.dokka.testApi.checkSourceExistsAndVerifyModel +import org.jetbrains.dokka.testApi.toTestString import org.junit.Test class TypeAliasTest { diff --git a/core/testApi/build.gradle b/core/testApi/build.gradle index 3d5bb61a..82d0fd41 100644 --- a/core/testApi/build.gradle +++ b/core/testApi/build.gradle @@ -1,3 +1,6 @@ dependencies { compileOnly project(":core") + implementation group: 'junit', name: 'junit', version: '4.12' + implementation group: 'org.jetbrains.kotlin', name: 'kotlin-test-junit', version: kotlin_version + implementation ideaRT() } \ No newline at end of file diff --git a/core/testApi/src/main/kotlin/testApi/DokkaConfigurationTestImplementations.kt b/core/testApi/src/main/kotlin/testApi/DokkaConfigurationTestImplementations.kt new file mode 100644 index 00000000..58356e27 --- /dev/null +++ b/core/testApi/src/main/kotlin/testApi/DokkaConfigurationTestImplementations.kt @@ -0,0 +1,81 @@ +package org.jetbrains.dokka.testApi + +import org.jetbrains.dokka.DokkaConfiguration +import org.jetbrains.dokka.Platform +import java.io.File + + +data class SourceLinkDefinitionImpl(override val path: String, + override val url: String, + override val lineSuffix: String?) : DokkaConfiguration.SourceLinkDefinition { + companion object { + fun parseSourceLinkDefinition(srcLink: String): DokkaConfiguration.SourceLinkDefinition { + val (path, urlAndLine) = srcLink.split('=') + return SourceLinkDefinitionImpl( + File(path).canonicalPath, + urlAndLine.substringBefore("#"), + urlAndLine.substringAfter("#", "").let { if (it.isEmpty()) null else "#$it" }) + } + } +} + +class SourceRootImpl(path: String) : DokkaConfiguration.SourceRoot { + override val path: String = File(path).absolutePath + + companion object { + fun parseSourceRoot(sourceRoot: String): DokkaConfiguration.SourceRoot = SourceRootImpl(sourceRoot) + } +} + +data class PackageOptionsImpl(override val prefix: String, + override val includeNonPublic: Boolean = false, + override val reportUndocumented: Boolean = true, + override val skipDeprecated: Boolean = false, + override val suppress: Boolean = false) : DokkaConfiguration.PackageOptions + + class DokkaConfigurationImpl( + override val outputDir: String = "", + override val format: String = "html", + override val generateIndexPages: Boolean = false, + override val cacheRoot: String? = null, + override val impliedPlatforms: List = emptyList(), + override val passesConfigurations: List = emptyList() +) : DokkaConfiguration + +class PassConfigurationImpl ( + override val classpath: List = emptyList(), + override val moduleName: String = "", + override val sourceRoots: List = emptyList(), + override val samples: List = emptyList(), + override val includes: List = emptyList(), + override val includeNonPublic: Boolean = false, + override val includeRootPackage: Boolean = false, + override val reportUndocumented: Boolean = false, + override val skipEmptyPackages: Boolean = false, + override val skipDeprecated: Boolean = false, + override val jdkVersion: Int = 6, + override val sourceLinks: List = emptyList(), + override val perPackageOptions: List = emptyList(), + externalDocumentationLinks: List = emptyList(), + override val languageVersion: String? = null, + override val apiVersion: String? = null, + override val noStdlibLink: Boolean = false, + override val noJdkLink: Boolean = false, + override val suppressedFiles: List = emptyList(), + override val collectInheritedExtensionsFromLibraries: Boolean = false, + override val analysisPlatform: Platform = Platform.DEFAULT, + override val targets: List = emptyList(), + override val sinceKotlin: String? = null +): DokkaConfiguration.PassConfiguration { + private val defaultLinks = run { + val links = mutableListOf() + if (!noJdkLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://docs.oracle.com/javase/$jdkVersion/docs/api/").build() + + if (!noStdlibLink) + links += DokkaConfiguration.ExternalDocumentationLink.Builder("https://kotlinlang.org/api/latest/jvm/stdlib/").build() + links + } + override val externalDocumentationLinks = defaultLinks + externalDocumentationLinks +} + diff --git a/core/testApi/src/main/kotlin/testApi/TestAPI.kt b/core/testApi/src/main/kotlin/testApi/TestAPI.kt new file mode 100644 index 00000000..7856591c --- /dev/null +++ b/core/testApi/src/main/kotlin/testApi/TestAPI.kt @@ -0,0 +1,353 @@ +package org.jetbrains.dokka.testApi + +import com.google.inject.Guice +import com.intellij.openapi.application.PathManager +import com.intellij.openapi.util.Disposer +import com.intellij.openapi.util.io.FileUtil +import com.intellij.rt.execution.junit.FileComparisonFailure +import org.jetbrains.dokka.* +import org.jetbrains.dokka.Utilities.DokkaAnalysisModule +import org.jetbrains.dokka.Utilities.DokkaRunModule +import org.jetbrains.kotlin.cli.common.config.ContentRoot +import org.jetbrains.kotlin.cli.common.config.KotlinSourceRoot +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation +import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity +import org.jetbrains.kotlin.cli.common.messages.MessageCollector +import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.utils.PathUtil +import org.junit.Assert +import org.junit.Assert.fail +import java.io.File + +data class ModelConfig( + val roots: Array = arrayOf(), + val withJdk: Boolean = false, + val withKotlinRuntime: Boolean = false, + val format: String = "html", + val includeNonPublic: Boolean = true, + val perPackageOptions: List = emptyList(), + val analysisPlatform: Platform = Platform.DEFAULT, + val defaultPlatforms: List = emptyList(), + val noStdlibLink: Boolean = true, + val collectInheritedExtensionsFromLibraries: Boolean = false, + val sourceLinks: List = emptyList() +) + +fun verifyModel( + modelConfig: ModelConfig, + verifier: (DocumentationModule) -> Unit +) { + val documentation = DocumentationModule("test") + + val passConfiguration = PassConfigurationImpl( + includeNonPublic = modelConfig.includeNonPublic, + skipEmptyPackages = false, + includeRootPackage = true, + sourceLinks = modelConfig.sourceLinks, + perPackageOptions = modelConfig.perPackageOptions, + noStdlibLink = modelConfig.noStdlibLink, + noJdkLink = false, + languageVersion = null, + apiVersion = null, + collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + ) + val configuration = DokkaConfigurationImpl( + outputDir = "", + format = modelConfig.format, + generateIndexPages = false, + cacheRoot = "default", + passesConfigurations = listOf(passConfiguration) + ) + + appendDocumentation(documentation, configuration, passConfiguration, modelConfig) + documentation.prepareForGeneration(configuration) + + verifier(documentation) +} + +fun appendDocumentation( + documentation: DocumentationModule, + dokkaConfiguration: DokkaConfiguration, + passConfiguration: DokkaConfiguration.PassConfiguration, + modelConfig: ModelConfig +) { + val messageCollector = object : MessageCollector { + override fun clear() { + + } + + override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation?) { + when (severity) { + CompilerMessageSeverity.STRONG_WARNING, + CompilerMessageSeverity.WARNING, + CompilerMessageSeverity.LOGGING, + CompilerMessageSeverity.OUTPUT, + CompilerMessageSeverity.INFO, + CompilerMessageSeverity.ERROR -> { + println("$severity: $message at $location") + } + CompilerMessageSeverity.EXCEPTION -> { + fail("$severity: $message at $location") + } + } + } + + override fun hasErrors() = false + } + + val environment = AnalysisEnvironment(messageCollector, modelConfig.analysisPlatform) + environment.apply { + if (modelConfig.withJdk || modelConfig.withKotlinRuntime) { + addClasspath(PathUtil.getJdkClassesRootsFromCurrentJre()) + } + if (modelConfig.withKotlinRuntime) { + if (analysisPlatform == Platform.jvm) { + val kotlinStrictfpRoot = PathManager.getResourceRoot(Strictfp::class.java, "/kotlin/jvm/Strictfp.class") + addClasspath(File(kotlinStrictfpRoot)) + } + if (analysisPlatform == Platform.js) { + val kotlinStdlibJsRoot = PathManager.getResourceRoot(Any::class.java, "/kotlin/jquery") + addClasspath(File(kotlinStdlibJsRoot)) + } + + if (analysisPlatform == Platform.common) { + // TODO: Feels hacky + val kotlinStdlibCommonRoot = ClassLoader.getSystemResource("kotlin/UInt.kotlin_metadata") + addClasspath(File(kotlinStdlibCommonRoot.file.replace("file:", "").replaceAfter(".jar", ""))) + } + } + addRoots(modelConfig.roots.toList()) + + loadLanguageVersionSettings(passConfiguration.languageVersion, passConfiguration.apiVersion) + } + val defaultPlatformsProvider = object : DefaultPlatformsProvider { + override fun getDefaultPlatforms(descriptor: DeclarationDescriptor) = modelConfig.defaultPlatforms + } + + val globalInjector = Guice.createInjector( + DokkaRunModule(dokkaConfiguration) + ) + + val injector = globalInjector.createChildInjector( + DokkaAnalysisModule( + environment, + dokkaConfiguration, + defaultPlatformsProvider, + documentation.nodeRefGraph, + passConfiguration, + DokkaConsoleLogger + ) + ) + + buildDocumentationModule(injector, documentation) + Disposer.dispose(environment) +} + +fun checkSourceExistsAndVerifyModel( + source: String, + modelConfig: ModelConfig = ModelConfig(), + verifier: (DocumentationModule) -> Unit +) { + require(File(source).exists()) { + "Cannot find test data file $source" + } + verifyModel( + ModelConfig( + roots = arrayOf(contentRootFromPath(source)), + withJdk = modelConfig.withJdk, + withKotlinRuntime = modelConfig.withKotlinRuntime, + format = modelConfig.format, + includeNonPublic = modelConfig.includeNonPublic, + sourceLinks = modelConfig.sourceLinks, + analysisPlatform = modelConfig.analysisPlatform + ), + + verifier = verifier + ) +} + +fun verifyPackageMember( + source: String, + modelConfig: ModelConfig = ModelConfig(), + verifier: (DocumentationNode) -> Unit +) { + checkSourceExistsAndVerifyModel( + source, + modelConfig = ModelConfig( + withJdk = modelConfig.withJdk, + withKotlinRuntime = modelConfig.withKotlinRuntime, + analysisPlatform = modelConfig.analysisPlatform + ) + ) { model -> + val pkg = model.members.single() + verifier(pkg.members.single()) + } +} + +fun verifyJavaModel( + source: String, + modelConfig: ModelConfig = ModelConfig(), + verifier: (DocumentationModule) -> Unit +) { + val tempDir = FileUtil.createTempDirectory("dokka", "") + try { + val sourceFile = File(source) + FileUtil.copy(sourceFile, File(tempDir, sourceFile.name)) + verifyModel( + ModelConfig( + roots = arrayOf(JavaSourceRoot(tempDir, null)), + withJdk = true, + withKotlinRuntime = modelConfig.withKotlinRuntime, + analysisPlatform = modelConfig.analysisPlatform + ), + verifier = verifier + ) + } finally { + FileUtil.delete(tempDir) + } +} + +fun verifyJavaPackageMember( + source: String, + modelConfig: ModelConfig = ModelConfig(), + verifier: (DocumentationNode) -> Unit +) { + verifyJavaModel(source, modelConfig) { model -> + val pkg = model.members.single() + verifier(pkg.members.single()) + } +} + +fun verifyOutput( + modelConfig: ModelConfig = ModelConfig(), + outputExtension: String, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit +) { + verifyModel(modelConfig) { + verifyModelOutput(it, outputExtension, modelConfig.roots.first().path, outputGenerator) + } +} + +fun verifyOutput( + path: String, + outputExtension: String, + modelConfig: ModelConfig = ModelConfig(), + outputGenerator: (DocumentationModule, StringBuilder) -> Unit +) { + verifyOutput( + ModelConfig( + roots = arrayOf(contentRootFromPath(path)) + modelConfig.roots, + withJdk = modelConfig.withJdk, + withKotlinRuntime = modelConfig.withKotlinRuntime, + format = modelConfig.format, + includeNonPublic = modelConfig.includeNonPublic, + analysisPlatform = modelConfig.analysisPlatform, + noStdlibLink = modelConfig.noStdlibLink, + collectInheritedExtensionsFromLibraries = modelConfig.collectInheritedExtensionsFromLibraries + ), + outputExtension, + outputGenerator + ) +} + +fun verifyModelOutput( + it: DocumentationModule, + outputExtension: String, + sourcePath: String, + outputGenerator: (DocumentationModule, StringBuilder) -> Unit +) { + val output = StringBuilder() + outputGenerator(it, output) + val ext = outputExtension.removePrefix(".") + val expectedFile = File(sourcePath.replaceAfterLast(".", ext, sourcePath + "." + ext)) + assertEqualsIgnoringSeparators(expectedFile, output.toString()) +} + +fun verifyJavaOutput( + path: String, + outputExtension: String, + modelConfig: ModelConfig = ModelConfig(), + outputGenerator: (DocumentationModule, StringBuilder) -> Unit +) { + verifyJavaModel(path, modelConfig) { model -> + verifyModelOutput(model, outputExtension, path, outputGenerator) + } +} + +fun assertEqualsIgnoringSeparators(expectedFile: File, output: String) { + if (!expectedFile.exists()) expectedFile.createNewFile() + val expectedText = expectedFile.readText().replace("\r\n", "\n") + val actualText = output.replace("\r\n", "\n") + + if (expectedText != actualText) + throw FileComparisonFailure("", expectedText, actualText, expectedFile.canonicalPath) +} + +fun assertEqualsIgnoringSeparators(expectedOutput: String, output: String) { + Assert.assertEquals(expectedOutput.replace("\r\n", "\n"), output.replace("\r\n", "\n")) +} + +fun StringBuilder.appendChildren(node: ContentBlock): StringBuilder { + for (child in node.children) { + val childText = child.toTestString() + append(childText) + } + return this +} + +fun StringBuilder.appendNode(node: ContentNode): StringBuilder { + when (node) { + is ContentText -> { + append(node.text) + } + is ContentEmphasis -> append("*").appendChildren(node).append("*") + is ContentBlockCode -> { + if (node.language.isNotBlank()) + appendln("[code lang=${node.language}]") + else + appendln("[code]") + appendChildren(node) + appendln() + appendln("[/code]") + } + is ContentNodeLink -> { + append("[") + appendChildren(node) + append(" -> ") + append(node.node.toString()) + append("]") + } + is ContentBlock -> { + appendChildren(node) + } + is NodeRenderContent -> { + append("render(") + append(node.node) + append(",") + append(node.mode) + append(")") + } + is ContentSymbol -> { + append(node.text) + } + is ContentEmpty -> { /* nothing */ + } + else -> throw IllegalStateException("Don't know how to format node $node") + } + return this +} + +fun ContentNode.toTestString(): String { + val node = this + return StringBuilder().apply { + appendNode(node) + }.toString() +} + +val ContentRoot.path: String + get() = when (this) { + is KotlinSourceRoot -> path + is JavaSourceRoot -> file.path + else -> throw UnsupportedOperationException() + } -- cgit