@@ -60,12 +60,13 @@ fun main(args: Array<String>) {
60
60
fun knit (markdownFileName : String ) {
61
61
println (" *** Reading $markdownFileName " )
62
62
val markdownFile = File (markdownFileName)
63
- val toc = arrayListOf<String >()
63
+ val tocLines = arrayListOf<String >()
64
64
var knitRegex: Regex ? = null
65
65
val includes = arrayListOf<Include >()
66
- val code = arrayListOf<String >()
67
- val test = arrayListOf<String >()
68
- var testOut: PrintWriter ? = null
66
+ val codeLines = arrayListOf<String >()
67
+ val testLines = arrayListOf<String >()
68
+ var testOut: String? = null
69
+ val testOutLines = arrayListOf<String >()
69
70
var lastPgk: String? = null
70
71
val files = mutableSetOf<File >()
71
72
val allApiRefs = arrayListOf<ApiRef >()
@@ -98,46 +99,47 @@ fun knit(markdownFileName: String) {
98
99
continue @mainLoop
99
100
}
100
101
INCLUDE_DIRECTIVE -> {
101
- require(! directive.param.isEmpty()) { " $INCLUDE_DIRECTIVE directive must include regex parameter" }
102
- val include = Include (Regex (directive.param))
103
- if (directive.singleLine) {
104
- include.lines + = code
105
- code.clear()
102
+ if (directive.param.isEmpty()) {
103
+ require(! directive.singleLine) { " $INCLUDE_DIRECTIVE directive without parameters must not be single line" }
104
+ readUntilTo(DIRECTIVE_END , codeLines)
106
105
} else {
107
- readUntilTo(DIRECTIVE_END , include.lines)
106
+ val include = Include (Regex (directive.param))
107
+ if (directive.singleLine) {
108
+ include.lines + = codeLines
109
+ codeLines.clear()
110
+ } else {
111
+ readUntilTo(DIRECTIVE_END , include.lines)
112
+ }
113
+ includes + = include
108
114
}
109
- includes + = include
110
115
continue @mainLoop
111
116
}
112
117
CLEAR_DIRECTIVE -> {
113
118
requireSingleLine(directive)
114
119
require(directive.param.isEmpty()) { " $CLEAR_DIRECTIVE directive must not have parameters" }
115
- code .clear()
120
+ codeLines .clear()
116
121
continue @mainLoop
117
122
}
118
123
TEST_OUT_DIRECTIVE -> {
119
124
require(! directive.param.isEmpty()) { " $TEST_OUT_DIRECTIVE directive must include file name parameter" }
120
- val file = File (directive.param)
121
- file.parentFile?.mkdirs()
122
- closeTestOut(testOut)
123
- println (" Writing tests to ${directive.param} " )
124
- testOut = PrintWriter (file)
125
- readUntil(DIRECTIVE_END ).forEach { testOut!! .println (it) }
125
+ flushTestOut(markdownFile.parentFile, testOut, testOutLines)
126
+ testOut = directive.param
127
+ readUntil(DIRECTIVE_END ).forEach { testOutLines + = it }
126
128
}
127
129
TEST_DIRECTIVE -> {
128
130
require(lastPgk != null ) { " '$PACKAGE_PREFIX ' prefix was not found in emitted code" }
129
131
require(testOut != null ) { " $TEST_OUT_DIRECTIVE directive was not specified" }
130
132
var predicate = directive.param
131
- if (test .isEmpty()) {
133
+ if (testLines .isEmpty()) {
132
134
if (directive.singleLine) {
133
135
require(! predicate.isEmpty()) { " $TEST_OUT_DIRECTIVE must be preceded by $TEST_START block or contain test predicate" }
134
136
} else
135
- test + = readUntil(DIRECTIVE_END )
137
+ testLines + = readUntil(DIRECTIVE_END )
136
138
} else {
137
139
requireSingleLine(directive)
138
140
}
139
- writeTest(testOut !! , lastPgk!! , test , predicate)
140
- test .clear()
141
+ makeTest(testOutLines , lastPgk!! , testLines , predicate)
142
+ testLines .clear()
141
143
}
142
144
SITE_ROOT_DIRECTIVE -> {
143
145
requireSingleLine(directive)
@@ -166,21 +168,21 @@ fun knit(markdownFileName: String) {
166
168
}
167
169
}
168
170
if (inLine.startsWith(CODE_START )) {
169
- require(test .isEmpty()) { " Previous test was not emitted with $TEST_DIRECTIVE " }
170
- code + = " "
171
- readUntilTo(CODE_END , code )
171
+ require(testLines .isEmpty()) { " Previous test was not emitted with $TEST_DIRECTIVE " }
172
+ codeLines + = " "
173
+ readUntilTo(CODE_END , codeLines )
172
174
continue @mainLoop
173
175
}
174
176
if (inLine.startsWith(TEST_START )) {
175
- require(test .isEmpty()) { " Previous test was not emitted with $TEST_DIRECTIVE " }
176
- readUntilTo(TEST_END , test )
177
+ require(testLines .isEmpty()) { " Previous test was not emitted with $TEST_DIRECTIVE " }
178
+ readUntilTo(TEST_END , testLines )
177
179
continue @mainLoop
178
180
}
179
181
if (inLine.startsWith(SECTION_START ) && markdownPart == MarkdownPart .POST_TOC ) {
180
182
val i = inLine.indexOf(' ' )
181
183
require(i >= 2 ) { " Invalid section start" }
182
184
val name = inLine.substring(i + 1 ).trim()
183
- toc + = " " .repeat(i - 2 ) + " * [$name ](#${makeSectionRef(name)} )"
185
+ tocLines + = " " .repeat(i - 2 ) + " * [$name ](#${makeSectionRef(name)} )"
184
186
continue @mainLoop
185
187
}
186
188
for (match in API_REF_REGEX .findAll(inLine)) {
@@ -203,21 +205,18 @@ fun knit(markdownFileName: String) {
203
205
outLines + = line
204
206
}
205
207
}
206
- outLines + = code
207
- code.clear()
208
- val oldLines = try { file.readLines() } catch (e: IOException ) { emptyList<String >() }
209
- if (outLines != oldLines) writeLines(file, outLines)
208
+ outLines + = codeLines
209
+ codeLines.clear()
210
+ writeLinesIfNeeded(file, outLines)
210
211
}
211
212
}
212
213
}
213
- // close test output
214
- closeTestOut(testOut)
215
214
// update markdown file with toc
216
215
val newLines = buildList<String > {
217
216
addAll(markdown.preTocText)
218
- if (! toc .isEmpty()) {
217
+ if (! tocLines .isEmpty()) {
219
218
add(" " )
220
- addAll(toc )
219
+ addAll(tocLines )
221
220
add(" " )
222
221
}
223
222
addAll(markdown.postTocText)
@@ -229,9 +228,11 @@ fun knit(markdownFileName: String) {
229
228
println (" WARNING: $markdownFile : ${apiRef.line} : Broken reference to [${apiRef.name} ]" )
230
229
}
231
230
}
231
+ // write test output
232
+ flushTestOut(markdownFile.parentFile, testOut, testOutLines)
232
233
}
233
234
234
- fun writeTest ( testOut : PrintWriter , pgk : String , test : List <String >, predicate : String ) {
235
+ fun makeTest ( testOutLines : MutableList < String > , pgk : String , test : List <String >, predicate : String ) {
235
236
val funName = buildString {
236
237
var cap = true
237
238
for (c in pgk) {
@@ -243,37 +244,35 @@ fun writeTest(testOut: PrintWriter, pgk: String, test: List<String>, predicate:
243
244
}
244
245
}
245
246
}
246
- with (testOut) {
247
- println ()
248
- println (" @Test" )
249
- println (" fun test$funName () {" )
250
- print (" test { $pgk .main(emptyArray()) }" )
251
- when (predicate) {
252
- " " -> writeTestLines(" verifyLines" , test)
253
- STARTS_WITH_PREDICATE -> writeTestLines(" verifyLinesStartWith" , test)
254
- ARBITRARY_TIME_PREDICATE -> writeTestLines(" verifyLinesArbitraryTime" , test)
255
- FLEXIBLE_TIME_PREDICATE -> writeTestLines(" verifyLinesFlexibleTime" , test)
256
- FLEXIBLE_THREAD_PREDICATE -> writeTestLines(" verifyLinesFlexibleThread" , test)
257
- LINES_START_UNORDERED_PREDICATE -> writeTestLines(" verifyLinesStartUnordered" , test)
258
- LINES_START_PREDICATE -> writeTestLines(" verifyLinesStart" , test)
259
- else -> {
260
- println (" .also { lines ->" )
261
- println (" check($predicate )" )
262
- println (" }" )
263
- }
247
+ testOutLines + = " "
248
+ testOutLines + = " @Test"
249
+ testOutLines + = " fun test$funName () {"
250
+ val prefix = " test { $pgk .main(emptyArray()) }"
251
+ when (predicate) {
252
+ " " -> makeTestLines(testOutLines, prefix, " verifyLines" , test)
253
+ STARTS_WITH_PREDICATE -> makeTestLines(testOutLines, prefix, " verifyLinesStartWith" , test)
254
+ ARBITRARY_TIME_PREDICATE -> makeTestLines(testOutLines, prefix, " verifyLinesArbitraryTime" , test)
255
+ FLEXIBLE_TIME_PREDICATE -> makeTestLines(testOutLines, prefix, " verifyLinesFlexibleTime" , test)
256
+ FLEXIBLE_THREAD_PREDICATE -> makeTestLines(testOutLines, prefix, " verifyLinesFlexibleThread" , test)
257
+ LINES_START_UNORDERED_PREDICATE -> makeTestLines(testOutLines, prefix, " verifyLinesStartUnordered" , test)
258
+ LINES_START_PREDICATE -> makeTestLines(testOutLines, prefix, " verifyLinesStart" , test)
259
+ else -> {
260
+ testOutLines + = prefix + " .also { lines ->"
261
+ testOutLines + = " check($predicate )"
262
+ testOutLines + = " }"
264
263
}
265
- println (" }" )
266
264
}
265
+ testOutLines + = " }"
267
266
}
268
267
269
- private fun PrintWriter. writeTestLines ( method : String , test : List <String >) {
270
- println ( " .$method (" )
268
+ private fun makeTestLines ( testOutLines : MutableList < String >, prefix : String , method : String , test : List <String >) {
269
+ testOutLines + = " $prefix .$method ("
271
270
for ((index, testLine) in test.withIndex()) {
272
271
val commaOpt = if (index < test.size - 1 ) " ," else " "
273
272
val escapedLine = testLine.replace(" \" " , " \\\" " )
274
- println ( " \" $escapedLine \" $commaOpt " )
273
+ testOutLines + = " \" $escapedLine \" $commaOpt "
275
274
}
276
- println ( " )" )
275
+ testOutLines + = " )"
277
276
}
278
277
279
278
private fun makeReplacements (line : String , match : MatchResult ): String {
@@ -285,11 +284,12 @@ private fun makeReplacements(line: String, match: MatchResult): String {
285
284
return result
286
285
}
287
286
288
- private fun closeTestOut (testOut : PrintWriter ? ) {
289
- if (testOut != null ) {
290
- testOut.println (" }" )
291
- testOut.close()
292
- }
287
+ private fun flushTestOut (parentDir : File ? , testOut : String? , testOutLines : MutableList <String >) {
288
+ if (testOut == null ) return
289
+ val file = File (parentDir, testOut)
290
+ testOutLines + = " }"
291
+ writeLinesIfNeeded(file, testOutLines)
292
+ testOutLines.clear()
293
293
}
294
294
295
295
private fun MarkdownTextReader.readUntil (marker : String ): List <String > =
@@ -375,6 +375,15 @@ fun <T : LineNumberReader> File.withLineNumberReader(factory: (Reader) -> T, blo
375
375
fun File.withMarkdownTextReader (block : MarkdownTextReader .() -> Unit ): MarkdownTextReader =
376
376
withLineNumberReader<MarkdownTextReader >(::MarkdownTextReader , block)
377
377
378
+ fun writeLinesIfNeeded (file : File , outLines : List <String >) {
379
+ val oldLines = try {
380
+ file.readLines()
381
+ } catch (e: IOException ) {
382
+ emptyList<String >()
383
+ }
384
+ if (outLines != oldLines) writeLines(file, outLines)
385
+ }
386
+
378
387
fun writeLines (file : File , lines : List <String >) {
379
388
println (" Writing $file ..." )
380
389
file.parentFile?.mkdirs()
@@ -431,7 +440,7 @@ fun processApiIndex(
431
440
): List <String > {
432
441
val key = ApiIndexKey (docsRoot, pkg)
433
442
val map = apiIndexCache.getOrPut(key, {
434
- print (" Parsing API docs at $docsRoot : " )
443
+ print (" Parsing API docs at $docsRoot / $pkg : " )
435
444
val result = loadApiIndex(docsRoot, pkg, pkg)
436
445
println (" ${result.size} definitions" )
437
446
result
0 commit comments