From 4de0dc44e862bf0aa5befa1686b794c40afeef3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=93lafur=20P=C3=A1ll=20Geirsson?= Date: Mon, 17 Sep 2018 11:46:18 +0200 Subject: [PATCH] Make variable priting configurable. This commit makes it possible to customize pretty-printing of captured variables. It's possible to tweak pretty-printing based on - runtime type of binder - string representation of static type of binder - position of binder in either enclosing statment or section This change required improving the handling of blank lines so that users that customize pretty-printing don't fiddle with brittle `\n` manipulation. --- docs/readme.md | 2 +- mdoc-docs/src/main/scala/mdoc/docs/Docs.scala | 2 +- mdoc/src/main/scala/mdoc/Main.scala | 2 +- mdoc/src/main/scala/mdoc/MainSettings.scala | 3 + mdoc/src/main/scala/mdoc/Variable.scala | 61 ++++++++ .../scala/mdoc/internal/cli/Settings.scala | 16 ++- .../internal/markdown/MdocPostProcessor.scala | 7 +- .../mdoc/internal/markdown/Renderer.scala | 130 +++++++++--------- .../markdown/ReplVariablePrinter.scala | 47 +++++++ readme.md | 9 +- .../scala/tests/markdown/DefaultSuite.scala | 60 +++++++- .../markdown/MarkdownCompilerSuite.scala | 3 +- .../tests/markdown/VariablePrinterSuite.scala | 61 ++++++++ .../tests/markdown/VariableRegexSuite.scala | 1 - 14 files changed, 317 insertions(+), 87 deletions(-) create mode 100644 mdoc/src/main/scala/mdoc/Variable.scala create mode 100644 mdoc/src/main/scala/mdoc/internal/markdown/ReplVariablePrinter.scala create mode 100644 tests/unit/src/test/scala/tests/markdown/VariablePrinterSuite.scala diff --git a/docs/readme.md b/docs/readme.md index f895c7600..f1e79e77e 100644 --- a/docs/readme.md +++ b/docs/readme.md @@ -118,7 +118,7 @@ object Main { // generate out/readme.md from working directory val exitCode = mdoc.Main.process(settings) // (optional) exit the main function with exit code 0 (success) or 1 (error) - sys.exit(exitCode) + if (exitCode != 0) sys.exit(exitCode) } } ``` diff --git a/mdoc-docs/src/main/scala/mdoc/docs/Docs.scala b/mdoc-docs/src/main/scala/mdoc/docs/Docs.scala index a5c256a17..f86eba891 100644 --- a/mdoc-docs/src/main/scala/mdoc/docs/Docs.scala +++ b/mdoc-docs/src/main/scala/mdoc/docs/Docs.scala @@ -33,6 +33,6 @@ object Docs { ) ) ) - sys.exit(exitCode) + if (exitCode != 0) sys.exit(exitCode) } } diff --git a/mdoc/src/main/scala/mdoc/Main.scala b/mdoc/src/main/scala/mdoc/Main.scala index 6c40b581f..cf714dd2a 100644 --- a/mdoc/src/main/scala/mdoc/Main.scala +++ b/mdoc/src/main/scala/mdoc/Main.scala @@ -14,7 +14,7 @@ object Main { def main(args: Array[String]): Unit = { val code = process(args, System.out, PathIO.workingDirectory.toNIO) - sys.exit(code) + if (code != 0) sys.exit(code) } def process(args: Array[String], out: PrintStream, cwd: Path): Int = { diff --git a/mdoc/src/main/scala/mdoc/MainSettings.scala b/mdoc/src/main/scala/mdoc/MainSettings.scala index 540f069ee..17511224b 100644 --- a/mdoc/src/main/scala/mdoc/MainSettings.scala +++ b/mdoc/src/main/scala/mdoc/MainSettings.scala @@ -78,6 +78,9 @@ final class MainSettings private ( def withHeaderIdGenerator(headerIdGenerator: String => String): MainSettings = { copy(settings.copy(headerIdGenerator = headerIdGenerator)) } + def withVariablePrinter(variablePrinter: Variable => String): MainSettings = { + copy(settings.copy(variablePrinter = variablePrinter)) + } private[this] implicit def cwd: AbsolutePath = settings.cwd private[this] def copy( diff --git a/mdoc/src/main/scala/mdoc/Variable.scala b/mdoc/src/main/scala/mdoc/Variable.scala new file mode 100644 index 000000000..faf866656 --- /dev/null +++ b/mdoc/src/main/scala/mdoc/Variable.scala @@ -0,0 +1,61 @@ +package mdoc + +import mdoc.internal.markdown.ReplVariablePrinter + +/** + * A captured variable in a code fence. + * + * Example, the code fence below has two statements: + * + * - The first statement has a single variable with name `x` + * - The second statement has a two variables with names `y` and `z` + * + * {{{ + * ```scala mdoc + * val x = 1 + * val (y, z) = (2, 3) + * ``` + * }}} + * + * @param name the variable name, for example `x` + * @param staticType the pretty-printed static type of this variable, for example `List[Int]` + * @param runtimeValue the runtime value of this variable. + * @param indexOfVariableInStatement the index of this variable in the enclosing statement. + * For example, in `val (a, b) = ???` the variable `a` has index + * 0 and variable `b` has index `1`. + * @param totalVariablesInStatement The total number of variables in this statements. For example, + * in `val a = N` the total number is 1 and for `val (a, b) = ...` the + * total number is 2. + * @param indexOfStatementInCodeFence the index of the enclosing statement within the enclosing code fence. + * For example, in + * {{{ + * ```scala + * val x = 1 + * val y = 2 + * ``` + * }}} + * The variable `y` has index 1 and variable `x` has index 0. + * @param totalStatementsInCodeFence the total number of statement in the enclosing code fence. + * For example, the total number is 2 for the code fence below. + * {{{ + * ```scala + * val x = 1 + * val y = 2 + * ``` + * }}} + * + */ +final class Variable private[mdoc] ( + val name: String, + val staticType: String, + val runtimeValue: Any, + val indexOfVariableInStatement: Int, + val totalVariablesInStatement: Int, + val indexOfStatementInCodeFence: Int, + val totalStatementsInCodeFence: Int +) { + def isUnit: Boolean = staticType.endsWith("Unit") + override def toString: String = { + ReplVariablePrinter(this) + } +} diff --git a/mdoc/src/main/scala/mdoc/internal/cli/Settings.scala b/mdoc/src/main/scala/mdoc/internal/cli/Settings.scala index 4e1a61fe2..c06853ed5 100644 --- a/mdoc/src/main/scala/mdoc/internal/cli/Settings.scala +++ b/mdoc/src/main/scala/mdoc/internal/cli/Settings.scala @@ -9,6 +9,7 @@ import java.nio.file.FileSystems import java.nio.file.Files import java.nio.file.InvalidPathException import java.nio.file.PathMatcher + import metaconfig.Conf import metaconfig.ConfDecoder import metaconfig.ConfEncoder @@ -18,15 +19,15 @@ import metaconfig.annotation._ import metaconfig.generic import metaconfig.generic.Surface import org.typelevel.paiges.Doc + import scala.annotation.StaticAnnotation import scala.meta.internal.io.PathIO import scala.meta.io.AbsolutePath import scala.meta.io.RelativePath import mdoc.StringModifier +import mdoc.Variable import mdoc.Reporter -import mdoc.internal.BuildInfo -import mdoc.internal.markdown.GitHubIdGenerator -import mdoc.internal.markdown.MarkdownCompiler +import mdoc.internal.markdown.{ReplVariablePrinter, GitHubIdGenerator, MarkdownCompiler} class Section(val name: String) extends StaticAnnotation @@ -102,7 +103,10 @@ case class Settings( inputStream: InputStream = System.in, @Hidden() @Description("The generator for header IDs, defaults to GitHub ID generator") - headerIdGenerator: String => String = GitHubIdGenerator + headerIdGenerator: String => String = GitHubIdGenerator, + @Hidden() + @Description("The pretty printer for variables") + variablePrinter: Variable => String = ReplVariablePrinter ) { def isFileWatching: Boolean = watch && !check @@ -208,6 +212,8 @@ object Settings extends MetaconfigScalametaImplicits { ConfDecoder.stringConfDecoder.map(_ => System.in) implicit val headerIdGeneratorDecoder: ConfDecoder[String => String] = ConfDecoder.stringConfDecoder.flatMap(_ => ConfError.message("unsupported").notOk) + implicit val variablePrinterDecoder: ConfDecoder[Variable => String] = + ConfDecoder.stringConfDecoder.flatMap(_ => ConfError.message("unsupported").notOk) implicit val pathEncoder: ConfEncoder[AbsolutePath] = ConfEncoder.StringEncoder.contramap { path => @@ -222,5 +228,7 @@ object Settings extends MetaconfigScalametaImplicits { ConfEncoder.StringEncoder.contramap(_ => "") implicit val headerIdGeneratorEncoder: ConfEncoder[String => String] = ConfEncoder.StringEncoder.contramap(_ => " String>") + implicit val variablePrinterEncoder: ConfEncoder[Variable => String] = + ConfEncoder.StringEncoder.contramap(_ => " String>") } diff --git a/mdoc/src/main/scala/mdoc/internal/markdown/MdocPostProcessor.scala b/mdoc/src/main/scala/mdoc/internal/markdown/MdocPostProcessor.scala index 03b2bc687..fda194830 100644 --- a/mdoc/src/main/scala/mdoc/internal/markdown/MdocPostProcessor.scala +++ b/mdoc/src/main/scala/mdoc/internal/markdown/MdocPostProcessor.scala @@ -75,7 +75,12 @@ class MdocPostProcessor(implicit ctx: Context) extends DocumentPostProcessor { mod match { case Modifier.Silent => case Modifier.Default | Modifier.Fail => - val str = Renderer.renderEvaluatedSection(rendered, section, ctx.reporter) + val str = Renderer.renderEvaluatedSection( + rendered, + section, + ctx.reporter, + ctx.settings.variablePrinter + ) val content: BasedSequence = CharSubSequence.of(str) block.setContent(List(content).asJava) case Modifier.Passthrough => diff --git a/mdoc/src/main/scala/mdoc/internal/markdown/Renderer.scala b/mdoc/src/main/scala/mdoc/internal/markdown/Renderer.scala index c1dfb4f76..ef8c471d8 100644 --- a/mdoc/src/main/scala/mdoc/internal/markdown/Renderer.scala +++ b/mdoc/src/main/scala/mdoc/internal/markdown/Renderer.scala @@ -2,18 +2,16 @@ package mdoc.internal.markdown import java.io.ByteArrayOutputStream import java.io.PrintStream -import java.nio.ByteBuffer -import java.nio.CharBuffer -import java.nio.charset.StandardCharsets -import scala.meta._ -import scala.meta.inputs.Position import mdoc.Reporter +import mdoc.Variable import mdoc.document.CompileResult import mdoc.document.CrashResult import mdoc.document.CrashResult.Crashed import mdoc.internal.document.MdocExceptions import mdoc.internal.pos.PositionSyntax._ import mdoc.internal.pos.TokenEditDistance +import scala.meta._ +import scala.meta.inputs.Position object Renderer { @@ -21,7 +19,8 @@ object Renderer { sections: List[Input], compiler: MarkdownCompiler, reporter: Reporter, - filename: String + filename: String, + printer: Variable => String ): String = { val inputs = sections.map(s => SectionInput(s, dialects.Sbt1(s).parse[Source].get, Modifier.Default)) @@ -30,7 +29,7 @@ object Renderer { MarkdownCompiler.buildDocument(compiler, reporter, inputs, instrumented, filename) doc.sections .map(s => s"""```scala - |${Renderer.renderEvaluatedSection(doc, s, reporter)} + |${Renderer.renderEvaluatedSection(doc, s, reporter, printer)} |```""".stripMargin) .mkString("\n") } @@ -66,40 +65,47 @@ object Renderer { } def appendMultiline(sb: PrintStream, string: String): Unit = { - val isTrailing = string.endsWith("\n") + appendMultiline(sb, string, string.length) + } + def appendMultiline(sb: PrintStream, string: String, N: Int): Unit = { var i = 0 - val N = if (isTrailing) string.length - 1 else string.length while (i < N) { string.charAt(i) match { case '\n' => sb.append("\n// ") - case ch => sb.append(ch) + case ch => + sb.append(ch) } i += 1 } } def appendFreshMultiline(sb: PrintStream, string: String): Unit = { + val N = string.length - (if (string.endsWith("\n")) 1 else 0) sb.append("// ") - appendMultiline(sb, string) + appendMultiline(sb, string, N) } def renderEvaluatedSection( doc: EvaluatedDocument, section: EvaluatedSection, - reporter: Reporter + reporter: Reporter, + printer: Variable => String ): String = { val baos = new ByteArrayOutputStream() val sb = new PrintStream(baos) - var first = true - section.section.statements.zip(section.source.stats).foreach { - case (statement, tree) => - if (first) { - first = false - } else { - sb.append("\n") - } + val stats = section.source.stats.lift + val totalStats = section.source.stats.length + section.section.statements.zip(section.source.stats).zipWithIndex.foreach { + case ((statement, tree), statementIndex) => val pos = tree.pos + val leadingBlankLines = stats(statementIndex - 1) match { + case None => + 0 + case Some(previousStatement) => + tree.pos.startLine - previousStatement.pos.endLine + } + sb.append("\n" * leadingBlankLines) val endOfLinePosition = Position.Range(pos.input, pos.startLine, pos.startColumn, pos.endLine, Int.MaxValue) sb.append(endOfLinePosition.text) @@ -107,52 +113,46 @@ object Renderer { sb.append("\n") appendFreshMultiline(sb, statement.out) } - sb.append("\n") - - statement.binders.foreach { binder => - section.mod match { - case Modifier.Fail => - binder.value match { - case CompileResult.TypecheckedOK(_, tpe, tpos) => - reporter.error( - tpos.toMeta(section), - s"Expected compile error but statement type-checked successfully" - ) - appendMultiline(sb, tpe) - case CompileResult.ParseError(msg, tpos) => - appendFreshMultiline(sb, tpos.formatMessage(section, msg)) - case CompileResult.TypeError(msg, tpos) => - val mpos = tpos.toMeta(section) - appendFreshMultiline(sb, tpos.formatMessage(section, msg)) - case _ => - val obtained = pprint.PPrinter.BlackWhite.apply(binder).toString() - throw new IllegalArgumentException( - s"Expected Macros.CompileResult." + - s"Obtained $obtained" - ) - } - case Modifier.Default | Modifier.Passthrough => - val lines = pprint.PPrinter.BlackWhite.tokenize(binder.value) - if (binder.name.startsWith("res") && binder.tpe.render == "Unit") { - () // do nothing - } else { - sb.append("// ") - .append(binder.name) - .append(": ") - .append(binder.tpe.render) - .append(" = ") - lines.foreach { lineStr => - val line = lineStr.plainText - appendMultiline(sb, line) + val N = statement.binders.length + statement.binders.zipWithIndex.foreach { + case (binder, i) => + section.mod match { + case Modifier.Fail => + sb.append('\n') + binder.value match { + case CompileResult.TypecheckedOK(_, tpe, tpos) => + reporter.error( + tpos.toMeta(section), + s"Expected compile error but statement type-checked successfully" + ) + appendMultiline(sb, tpe) + case CompileResult.ParseError(msg, tpos) => + appendFreshMultiline(sb, tpos.formatMessage(section, msg)) + case CompileResult.TypeError(msg, tpos) => + appendFreshMultiline(sb, tpos.formatMessage(section, msg)) + case _ => + val obtained = pprint.PPrinter.BlackWhite.apply(binder).toString() + throw new IllegalArgumentException( + s"Expected Macros.CompileResult." + + s"Obtained $obtained" + ) } - sb.append("\n") - } - - case Modifier.Crash => - throw new IllegalArgumentException(Modifier.Crash.toString) - case c @ (Modifier.Str(_, _) | Modifier.Silent) => - throw new IllegalArgumentException(c.toString) - } + case Modifier.Default | Modifier.Passthrough => + val variable = new mdoc.Variable( + binder.name, + binder.tpe.render, + binder.value, + i, + N, + statementIndex, + totalStats + ) + sb.append(printer(variable)) + case Modifier.Crash => + throw new IllegalArgumentException(Modifier.Crash.toString) + case c @ (Modifier.Str(_, _) | Modifier.Silent) => + throw new IllegalArgumentException(c.toString) + } } } baos.toString.trim diff --git a/mdoc/src/main/scala/mdoc/internal/markdown/ReplVariablePrinter.scala b/mdoc/src/main/scala/mdoc/internal/markdown/ReplVariablePrinter.scala new file mode 100644 index 000000000..60dd659ba --- /dev/null +++ b/mdoc/src/main/scala/mdoc/internal/markdown/ReplVariablePrinter.scala @@ -0,0 +1,47 @@ +package mdoc.internal.markdown + +import java.io.ByteArrayOutputStream +import java.io.PrintStream +import mdoc.Variable + +class ReplVariablePrinter( + leadingNewline: Boolean, + width: Int, + height: Int, + indent: Int +) extends (mdoc.Variable => String) { + + override def apply(binder: Variable): String = { + if (binder.isUnit) "" + else { + val baos = new ByteArrayOutputStream() + val sb = new PrintStream(baos) + if (leadingNewline) { + sb.append('\n') + } + val lines = pprint.PPrinter.BlackWhite.tokenize( + binder.runtimeValue, + width = width, + height = height, + indent = 2 + ) + sb.append("// ") + .append(binder.name) + .append(": ") + .append(binder.staticType) + .append(" = ") + lines.foreach { lineStr => + val line = lineStr.plainText + Renderer.appendMultiline(sb, line) + } + baos.toString() + } + } +} +object ReplVariablePrinter + extends ReplVariablePrinter( + leadingNewline = true, + width = 80, + height = 50, + indent = 2 + ) diff --git a/readme.md b/readme.md index d246cd2c3..128d5d2ef 100644 --- a/readme.md +++ b/readme.md @@ -120,7 +120,7 @@ object Main { // generate out/readme.md from working directory val exitCode = mdoc.Main.process(settings) // (optional) exit the main function with exit code 0 (success) or 1 (error) - sys.exit(exitCode) + if (exitCode != 0) sys.exit(exitCode) } } ``` @@ -177,16 +177,13 @@ After: ```scala val x = 1 // x: Int = 1 - val y = 2 // y: Int = 2 - x + y // res0: Int = 3 ``` ```` - ### Silent The `silent` modifier is identical to the default modifier except that it hides @@ -410,7 +407,6 @@ You can choose the Scastie theme when initializing the Scastie modifier: ```scala import mdoc.modifiers.ScastieModifier - new ScastieModifier(theme = "dark") // default is "light" // res0: ScastieModifier = StringModifier(mdoc:scastie) ``` @@ -562,17 +558,14 @@ After: ```` ```scala case class User(name: String) - object User { implicit val ordering: Ordering[User] = Ordering.by(_.name) } - List(User("John"), User("Susan")).sorted // res0: List[User] = List(User("John"), User("Susan")) ``` ```` - ### Variable injection Mdoc renders constants like `0.4.0` in markdown with variables provided at diff --git a/tests/unit/src/test/scala/tests/markdown/DefaultSuite.scala b/tests/unit/src/test/scala/tests/markdown/DefaultSuite.scala index f6175f8a2..582024e54 100644 --- a/tests/unit/src/test/scala/tests/markdown/DefaultSuite.scala +++ b/tests/unit/src/test/scala/tests/markdown/DefaultSuite.scala @@ -58,7 +58,6 @@ class DefaultSuite extends BaseMarkdownSuite { """|```scala |List(1).map(_ + 1) |// res0: List[Int] = List(2) - | |res0.length |// res1: Int = 1 |``` @@ -80,7 +79,6 @@ class DefaultSuite extends BaseMarkdownSuite { """.stripMargin, """|```scala |case class User(name: String, age: Int) - | |User("John", 42) |// res0: User = User("John", 42) |``` @@ -97,7 +95,6 @@ class DefaultSuite extends BaseMarkdownSuite { """.stripMargin, """|```scala |import scala.concurrent.Future - | |Future.successful(1) |// res0: Future[Int] = Future(Success(1)) |``` @@ -119,7 +116,6 @@ class DefaultSuite extends BaseMarkdownSuite { """|```scala |println(1) |// 1 - | |val x = 42 |// x: Int = 42 |``` @@ -131,4 +127,60 @@ class DefaultSuite extends BaseMarkdownSuite { """.stripMargin ) + check( + "blank-line", + """ + |```scala mdoc + |import scala.util._ + |import scala.math._ + | + |import scala.concurrent._ + |Future.successful(Try(1)) + |val (a, b) = Future.successful(Try(1)) -> 2 + | + |Future.successful(Try(1)) + |``` + """.stripMargin, + """|```scala + |import scala.util._ + |import scala.math._ + | + |import scala.concurrent._ + |Future.successful(Try(1)) + |// res0: Future[Try[Int]] = Future(Success(Success(1))) + |val (a, b) = Future.successful(Try(1)) -> 2 + |// a: Future[Try[Int]] = Future(Success(Success(1))) + |// b: Int = 2 + | + |Future.successful(Try(1)) + |// res1: Future[Try[Int]] = Future(Success(Success(1))) + |``` + """.stripMargin + ) + + check( + "large-value", + """ + |```scala mdoc + |Array.tabulate(10, 10)((a, b) => a + b) + |``` + """.stripMargin.replace("'''", "\"\"\""), + """|```scala + |Array.tabulate(10, 10)((a, b) => a + b) + |// res0: Array[Array[Int]] = Array( + |// Array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), + |// Array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + |// Array(2, 3, 4, 5, 6, 7, 8, 9, 10, 11), + |// Array(3, 4, 5, 6, 7, 8, 9, 10, 11, 12), + |// Array(4, 5, 6, 7, 8, 9, 10, 11, 12, 13), + |// Array(5, 6, 7, 8, 9, 10, 11, 12, 13, 14), + |// Array(6, 7, 8, 9, 10, 11, 12, 13, 14, 15), + |// Array(7, 8, 9, 10, 11, 12, 13, 14, 15, 16), + |// Array(8, 9, 10, 11, 12, 13, 14, 15, 16, 17), + |// Array(9, 10, 11, 12, 13, 14, 15, 16, 17, 18) + |// ) + |``` + """.stripMargin + ) + } diff --git a/tests/unit/src/test/scala/tests/markdown/MarkdownCompilerSuite.scala b/tests/unit/src/test/scala/tests/markdown/MarkdownCompilerSuite.scala index a9c15a570..fcffef767 100644 --- a/tests/unit/src/test/scala/tests/markdown/MarkdownCompilerSuite.scala +++ b/tests/unit/src/test/scala/tests/markdown/MarkdownCompilerSuite.scala @@ -6,6 +6,7 @@ import scala.meta.testkit.DiffAssertions import mdoc.internal.io.ConsoleReporter import mdoc.internal.markdown.MarkdownCompiler import mdoc.internal.markdown.Renderer +import mdoc.internal.markdown.ReplVariablePrinter class MarkdownCompilerSuite extends FunSuite with DiffAssertions { @@ -21,7 +22,7 @@ class MarkdownCompilerSuite extends FunSuite with DiffAssertions { def check(name: String, original: List[String], expected: String): Unit = { test(name) { val inputs = original.map(s => Input.String(s)) - val obtained = Renderer.render(inputs, compiler, reporter, name + ".md") + val obtained = Renderer.render(inputs, compiler, reporter, name + ".md", ReplVariablePrinter) assertNoDiff(obtained, expected) } } diff --git a/tests/unit/src/test/scala/tests/markdown/VariablePrinterSuite.scala b/tests/unit/src/test/scala/tests/markdown/VariablePrinterSuite.scala new file mode 100644 index 000000000..009337878 --- /dev/null +++ b/tests/unit/src/test/scala/tests/markdown/VariablePrinterSuite.scala @@ -0,0 +1,61 @@ +package tests.markdown + +class VariablePrinterSuite extends BaseMarkdownSuite { + + val trailingComment = baseSettings.copy(variablePrinter = { variable => + variable.runtimeValue match { + case n: Int if variable.totalVariablesInStatement == 1 => s" // Number($n)" + case _ => variable.toString + } + }) + + check( + "trailing-comment", + """ + |```scala mdoc + |42 + |"message" + |val (a, b) = (1, 2) + |``` + """.stripMargin, + """|```scala + |42 // Number(42) + |"message" + |// res1: String = "message" + |val (a, b) = (1, 2) + |// a: Int = 1 + |// b: Int = 2 + |``` + """.stripMargin, + trailingComment + ) + + val lastStatementOnly = baseSettings.copy(variablePrinter = { variable => + if (variable.indexOfStatementInCodeFence + 1 == variable.totalStatementsInCodeFence) { + variable.toString + } else { + "" + } + }) + check( + "last-statement", + """ + |```scala mdoc + |val x = 12 + |val y = 2 + |x + y + |x + y + |``` + """.stripMargin, + """|```scala + |val x = 12 + |val y = 2 + |x + y + |x + y + |// res1: Int = 14 + |``` + """.stripMargin, + lastStatementOnly + ) + +} diff --git a/tests/unit/src/test/scala/tests/markdown/VariableRegexSuite.scala b/tests/unit/src/test/scala/tests/markdown/VariableRegexSuite.scala index 0301d9776..df610811b 100644 --- a/tests/unit/src/test/scala/tests/markdown/VariableRegexSuite.scala +++ b/tests/unit/src/test/scala/tests/markdown/VariableRegexSuite.scala @@ -42,7 +42,6 @@ class VariableRegexSuite extends BaseMarkdownSuite { |```scala |val x = "1.0" |// x: String = "1.0" - | |x.length // should match "1.0".length |// res0: Int = 3 |```