From 2b5ac5aa5fe46bd3eb3eba3de2eca68a09833703 Mon Sep 17 00:00:00 2001 From: Paweł Wiejacha Date: Fri, 22 Aug 2014 09:15:01 +0200 Subject: SI-8810 scaladoc: fixed code block indentation normalization --- .../tools/nsc/doc/base/CommentFactoryBase.scala | 50 ++++------------------ 1 file changed, 8 insertions(+), 42 deletions(-) (limited to 'src/scaladoc') diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala index 19cc27b40b..a2d4327f8b 100755 --- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala @@ -723,49 +723,15 @@ trait CommentFactoryBase { this: MemberLookupBase => */ def normalizeIndentation(_code: String): String = { - val code = _code.trim - var maxSkip = Integer.MAX_VALUE - var crtSkip = 0 - var wsArea = true - var index = 0 - var firstLine = true - var emptyLine = true - - while (index < code.length) { - code(index) match { - case ' ' => - if (wsArea) - crtSkip += 1 - case c => - wsArea = (c == '\n') - maxSkip = if (firstLine || emptyLine) maxSkip else if (maxSkip <= crtSkip) maxSkip else crtSkip - crtSkip = if (c == '\n') 0 else crtSkip - firstLine = if (c == '\n') false else firstLine - emptyLine = if (c == '\n') true else false - } - index += 1 - } + val code = _code.replaceAll("\\s+$", "").dropWhile(_ == '\n') // right-trim + remove all leading '\n' + val lines = code.split("\n") - if (maxSkip == 0) - code - else { - index = 0 - val builder = new StringBuilder - while (index < code.length) { - builder.append(code(index)) - if (code(index) == '\n') { - // we want to skip as many spaces are available, if there are less spaces (like on empty lines, do not - // over-consume them) - index += 1 - val limit = index + maxSkip - while ((index < code.length) && (code(index) == ' ') && index < limit) - index += 1 - } - else - index += 1 - } - builder.toString - } + // maxSkip - size of the longest common whitespace prefix of non-empty lines + val nonEmptyLines = lines.filter(_.trim.nonEmpty) + val maxSkip = if (nonEmptyLines.isEmpty) 0 else nonEmptyLines.map(line => line.prefixLength(_ == ' ')).min + + // remove common whitespace prefix + lines.map(line => if (line.trim.nonEmpty) line.substring(maxSkip) else line).mkString("\n") } def checkParaEnded(): Boolean = { -- cgit v1.2.3 From d153ceeed133adfefe6c44a56f8ee502c1278e89 Mon Sep 17 00:00:00 2001 From: Antoine Gourlay Date: Wed, 3 Sep 2014 10:39:22 +0200 Subject: SI-8113 allow a newline between a link target and title Parsing "[[http://foo.bar link title]]" stops at the first whitespace. This breaks pretty badly in: [[http://foo.bar link title]] It stops after "link", interprets what it parsed as a link to a member, obviously fails, and then just ouputs "title". It should at least return a proper error, or, even better, just allow a newline between the target and title. I went for the latter. --- .../tools/nsc/doc/base/CommentFactoryBase.scala | 8 +++-- test/scaladoc/run/t8113.check | 1 + test/scaladoc/run/t8113.scala | 36 ++++++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 test/scaladoc/run/t8113.check create mode 100644 test/scaladoc/run/t8113.scala (limited to 'src/scaladoc') diff --git a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala index d5e2f9a2c4..6f81739031 100755 --- a/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala +++ b/src/scaladoc/scala/tools/nsc/doc/base/CommentFactoryBase.scala @@ -681,10 +681,10 @@ trait CommentFactoryBase { this: MemberLookupBase => jump("[[") val parens = 2 + repeatJump('[') val stop = "]" * parens - val target = readUntil { check(stop) || check(" ") } + val target = readUntil { check(stop) || isWhitespaceOrNewLine(char) } val title = if (!check(stop)) Some({ - jump(" ") + jumpWhitespaceOrNewLine() inline(check(stop)) }) else None @@ -899,6 +899,8 @@ trait CommentFactoryBase { this: MemberLookupBase => def jumpWhitespace() = jumpUntil(!isWhitespace(char)) + def jumpWhitespaceOrNewLine() = jumpUntil(!isWhitespaceOrNewLine(char)) + /* READERS */ final def readUntil(c: Char): String = { @@ -938,5 +940,7 @@ trait CommentFactoryBase { this: MemberLookupBase => /* CHARS CLASSES */ def isWhitespace(c: Char) = c == ' ' || c == '\t' + + def isWhitespaceOrNewLine(c: Char) = isWhitespace(c) || c == '\n' } } diff --git a/test/scaladoc/run/t8113.check b/test/scaladoc/run/t8113.check new file mode 100644 index 0000000000..619c56180b --- /dev/null +++ b/test/scaladoc/run/t8113.check @@ -0,0 +1 @@ +Done. diff --git a/test/scaladoc/run/t8113.scala b/test/scaladoc/run/t8113.scala new file mode 100644 index 0000000000..f006213ef2 --- /dev/null +++ b/test/scaladoc/run/t8113.scala @@ -0,0 +1,36 @@ +import scala.tools.nsc.doc.base._ +import scala.tools.nsc.doc.base.comment._ +import scala.tools.nsc.doc.model._ +import scala.tools.partest.ScaladocModelTest + +object Test extends ScaladocModelTest { + + override def code = """ + /** + * Check out [[http://www.scala-lang.org + * this great website]]! + */ + class Test + """ + + def scaladocSettings = "" + + def testModel(rootPackage: Package) = { + import access._ + + val test = rootPackage._class("Test") + + // find Link + def find(body: Any): Option[Link] = body match { + case l: Link => Some(l) + case s: Seq[_] => s.toList.map(find(_)).flatten.headOption + case p: Product => p.productIterator.toList.map(find(_)).flatten.headOption + case _ => None + } + + val link = find(test.comment.get.body).collect { case Link(ta, Text(ti)) => (ta, ti) } + assert(link.isDefined) + val expected = ("http://www.scala-lang.org", "this great website") + link.foreach {l => assert(l == expected, s"$l != $expected")} + } +} -- cgit v1.2.3