diff options
-rw-r--r-- | core/src/main/kotlin/Generation/FileGenerator.kt | 92 |
1 files changed, 65 insertions, 27 deletions
diff --git a/core/src/main/kotlin/Generation/FileGenerator.kt b/core/src/main/kotlin/Generation/FileGenerator.kt index 40348be0..120efc6b 100644 --- a/core/src/main/kotlin/Generation/FileGenerator.kt +++ b/core/src/main/kotlin/Generation/FileGenerator.kt @@ -3,9 +3,9 @@ package org.jetbrains.dokka import com.google.inject.Inject import com.google.inject.name.Named import java.io.File -import java.io.FileOutputStream import java.io.IOException -import java.io.OutputStreamWriter +import java.io.PrintWriter +import java.io.StringWriter class FileGenerator @Inject constructor(@Named("outputDir") override val root: File) : NodeLocationAwareGenerator { @@ -14,6 +14,56 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F @set:Inject(optional = true) lateinit var dokkaConfiguration: DokkaConfiguration @set:Inject(optional = true) var packageListService: PackageListService? = null + private val createdFiles = mutableMapOf<File, List<String>>() + + private fun File.writeFileAndAssert(context: String, action: (File) -> Unit) { + //TODO: there is a possible refactoring to drop FileLocation + //TODO: aad File from API, Location#path. + //TODO: turn [Location] into a final class, + //TODO: Use [Location] all over the place without full + //TODO: reference to the real target path, + //TODO: it opens the way to safely track all files created + //TODO: to make sure no files were overwritten by mistake + //TODO: also, the NodeLocationAwareGenerator should be removed + val stack = "$context\n" + try { + throw Error() + } catch (t: Throwable) { + StringWriter().use { ww -> + PrintWriter(ww).use { + t.printStackTrace(it) + } + ww.toString().replace("\n", "\n ") + } + } + + val writes = createdFiles.getOrDefault(this, listOf()) + stack + createdFiles[this] = writes + if (writes.size > 1) { + println("ERROR. An attempt to write ${this.relativeTo(root)} several times!") + + createdFiles[this] = writes + stack + for (call in writes + stack) { + println(call) + } + println() + return + } + + try { + parentFile?.mkdirsOrFail() + action(this) + } catch (e : Throwable) { + println("Failed to write $this. ${e.message}") + e.printStackTrace() + } + } + + private fun File.mkdirsOrFail() { + if (!mkdirs() && !exists()) { + throw IOException("Failed to create directory $this") + } + } + override fun location(node: DocumentationNode): FileLocation { return FileLocation(fileForNode(node, formatService.linkExtension)) } @@ -29,16 +79,10 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F override fun buildPages(nodes: Iterable<DocumentationNode>) { for ((file, items) in nodes.groupBy { fileForNode(it, formatService.extension) }) { - file.parentFile?.mkdirsOrFail() - try { - FileOutputStream(file).use { - OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(formatService.format(location(items.first()), items)) - } - } - } catch (e: Throwable) { - println(e) + file.writeFileAndAssert("pages") { it -> + it.writeText(formatService.format(location(items.first()), items)) } + buildPages(items.flatMap { it.members }) } } @@ -46,20 +90,18 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F override fun buildOutlines(nodes: Iterable<DocumentationNode>) { val outlineService = this.outlineService ?: return for ((location, items) in nodes.groupBy { locationWithoutExtension(it) }) { - val file = outlineService.getOutlineFileName(location) - file.parentFile?.mkdirsOrFail() - FileOutputStream(file).use { - OutputStreamWriter(it, Charsets.UTF_8).use { - it.write(outlineService.formatOutline(location, items)) - } + outlineService.getOutlineFileName(location).writeFileAndAssert("outlines") { file -> + file.writeText(outlineService.formatOutline(location, items)) } } } override fun buildSupportFiles() { formatService.enumerateSupportFiles { resource, targetPath -> - FileOutputStream(File(root, relativePathToNode(listOf(targetPath), false))).use { - javaClass.getResourceAsStream(resource).copyTo(it) + File(root, relativePathToNode(listOf(targetPath), false)).writeFileAndAssert("support files") { file -> + file.outputStream().use { + javaClass.getResourceAsStream(resource).copyTo(it) + } } } } @@ -72,15 +114,11 @@ class FileGenerator @Inject constructor(@Named("outputDir") override val root: F val moduleRoot = location(module).file.parentFile val packageListFile = File(moduleRoot, "package-list") - packageListFile.writeText("\$dokka.format:${dokkaConfiguration.format}\n" + - packageListService!!.formatPackageList(module as DocumentationModule)) - } - - } + val text = "\$dokka.format:${dokkaConfiguration.format}\n" + packageListService!!.formatPackageList(module as DocumentationModule) - private fun File.mkdirsOrFail() { - if (!mkdirs() && !exists()) { - throw IOException("Failed to create directory $this") + packageListFile.writeFileAndAssert("packages-list") { file -> + file.writeText(text) + } } } } |