summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan@lightbend.com>2016-10-19 12:56:08 -0700
committerAdriaan Moors <adriaan@lightbend.com>2016-10-19 13:44:05 -0700
commit7c8ef74bd5aeab5694c481832fb8cc42e891f828 (patch)
treebc118aa9d2d00aa910c475865451a0ce121bd975 /src
parent156f7329c4f93a9c2d63785f50a5ca62d097278e (diff)
downloadscala-7c8ef74bd5aeab5694c481832fb8cc42e891f828.tar.gz
scala-7c8ef74bd5aeab5694c481832fb8cc42e891f828.tar.bz2
scala-7c8ef74bd5aeab5694c481832fb8cc42e891f828.zip
Keep `skipBlockComment` tail recursive
Avoid StackOverflow on big comments. Simplify `ScaladocJavaUnitScanner` while in there. TODO: Do same for `ScaladocUnitScanner`?
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala26
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala43
2 files changed, 30 insertions, 39 deletions
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
index e11ac94041..bf944f1eda 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -577,27 +577,37 @@ trait JavaScanners extends ast.parser.ScannersCommon {
}
}
- protected def putCommentChar(): Unit = in.next()
+ // Hooks for ScaladocJavaUnitScanner
+ protected def beginDocComment(): Unit = {}
+ protected def processCommentChar(): Unit = {}
+ protected def finishDocComment(): Unit = {}
- protected def skipBlockComment(isDoc: Boolean): Unit = in.ch match {
- case SU => incompleteInputError("unclosed comment")
- case '*' => putCommentChar() ; if (in.ch == '/') putCommentChar() else skipBlockComment(isDoc)
- case _ => putCommentChar() ; skipBlockComment(isDoc)
+ final protected def putCommentChar(): Unit = { processCommentChar(); in.next() }
+
+ @tailrec final protected def skipBlockComment(isDoc: Boolean): Unit = {
+ if (isDoc) beginDocComment()
+
+ in.ch match {
+ case SU => incompleteInputError("unclosed comment")
+ case '*' => putCommentChar() ; if (in.ch == '/') putCommentChar() else skipBlockComment(isDoc)
+ case _ => putCommentChar() ; skipBlockComment(isDoc)
+ }
}
- protected def skipLineComment(): Unit = in.ch match {
+ @tailrec final protected def skipLineComment(): Unit = in.ch match {
case CR | LF | SU =>
case _ => putCommentChar() ; skipLineComment()
}
- protected def skipComment(): Boolean = in.ch match {
- case '/' => putCommentChar() ; skipLineComment() ; true
+ final protected def skipComment(): Boolean = in.ch match {
+ case '/' => putCommentChar() ; skipLineComment() ; finishDocComment() ; true
case '*' =>
putCommentChar()
in.ch match {
case '*' => skipBlockComment(isDoc = true)
case _ => skipBlockComment(isDoc = false)
}
+ finishDocComment()
true
case _ => false
}
diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
index d8ec7b18fd..f00af9a42f 100644
--- a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
@@ -215,51 +215,32 @@ abstract class ScaladocSyntaxAnalyzer[G <: Global](val global: G) extends Syntax
}
class ScaladocJavaUnitScanner(unit: CompilationUnit) extends JavaUnitScanner(unit) {
-
- private var docBuffer: StringBuilder = _
- private var inDocComment = false
+ // When `docBuffer == null`, we're not in a doc comment.
+ private var docBuffer: StringBuilder = null
private var docStart: Int = 0
private var lastDoc: DocComment = null
- override def init() = {
- docBuffer = new StringBuilder
- super.init()
- }
-
// get last doc comment
def flushDoc(): DocComment = try lastDoc finally lastDoc = null
- override protected def putCommentChar(): Unit = {
- if (inDocComment) docBuffer append in.ch
- in.next
- }
-
- override protected def skipBlockComment(isDoc: Boolean): Unit = {
- // condition is true when comment is entered the first time,
- // i.e. immediately after "/*" and when current character is "*"
- if (!inDocComment && isDoc) {
- docBuffer append "/*"
+ override protected def beginDocComment(): Unit =
+ if (docBuffer == null) {
+ // Comment is entered the first time, i.e. immediately after "/*" and when current character is "*"
+ docBuffer = new StringBuilder("/*")
docStart = currentPos.start
- inDocComment = true
}
- super.skipBlockComment(isDoc)
- }
- override protected def skipComment(): Boolean = {
- val skipped = super.skipComment()
- if (skipped && inDocComment) {
+ override protected def processCommentChar(): Unit =
+ if (docBuffer != null) docBuffer append in.ch
+
+ override protected def finishDocComment(): Unit =
+ if (docBuffer != null) {
val raw = docBuffer.toString
val position = Position.range(unit.source, docStart, docStart, in.cpos)
lastDoc = DocComment(raw, position)
signalParsedDocComment(raw, position)
- docBuffer.setLength(0) // clear buffer
- inDocComment = false
- true
- } else {
- skipped
+ docBuffer = null
}
- }
-
}
class ScaladocJavaUnitParser(unit: CompilationUnit) extends {