summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2016-04-25 15:00:09 -0700
committerJakob Odersky <jakob@odersky.com>2016-05-24 14:13:14 -0700
commitda1774df8d2921073304481e93278ddfd997aae4 (patch)
tree14c5594fb43799a6e9afc10e0738760eac9f6ef2
parent0a344bd7ba04358cb106ac19a2418205d87905ea (diff)
downloadscala-da1774df8d2921073304481e93278ddfd997aae4.tar.gz
scala-da1774df8d2921073304481e93278ddfd997aae4.tar.bz2
scala-da1774df8d2921073304481e93278ddfd997aae4.zip
Parse java comments in scaladoc
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala4
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaParsers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/javac/JavaScanners.scala38
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala94
-rw-r--r--src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala1
6 files changed, 103 insertions, 49 deletions
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 7417d9c09d..90532666b2 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -411,7 +411,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
override val initial = true
}
- import syntaxAnalyzer.{ UnitScanner, UnitParser }
+ import syntaxAnalyzer.{ UnitScanner, UnitParser, JavaUnitParser }
// !!! I think we're overdue for all these phase objects being lazy vals.
// There's no way for a Global subclass to provide a custom typer
@@ -1042,6 +1042,8 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
def newUnitParser(code: String, filename: String = "<console>"): UnitParser =
newUnitParser(newCompilationUnit(code, filename))
+ def newJavaUnitParser(unit: CompilationUnit): JavaUnitParser = new JavaUnitParser(unit)
+
/** A Run is a single execution of the compiler on a set of units.
*/
class Run extends RunContextApi with RunReporting with RunParsing {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
index df2073785b..e0667b5a3e 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/SyntaxAnalyzer.scala
@@ -82,7 +82,7 @@ abstract class SyntaxAnalyzer extends SubComponent with Parsers with MarkupParse
}
private def initialUnitBody(unit: CompilationUnit): Tree = {
- if (unit.isJava) new JavaUnitParser(unit).parse()
+ if (unit.isJava) newJavaUnitParser(unit).parse()
else if (currentRun.parsing.incompleteHandled) newUnitParser(unit).parse()
else newUnitParser(unit).smartParse()
}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
index cc851b6330..13ffe631f4 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala
@@ -135,6 +135,11 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
DefDef(Modifiers(Flags.JAVA), nme.CONSTRUCTOR, List(), List(vparams), TypeTree(), blankExpr)
}
+ /** A hook for joining the comment associated with a definition.
+ * Overridden by scaladoc.
+ */
+ def joinComment(trees: => List[Tree]): List[Tree] = trees
+
// ------------- general parsing ---------------------------
/** skip parent or brace enclosed sequence of things */
@@ -739,7 +744,7 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
}
val sdefs = statics.toList
val idefs = members.toList ::: (sdefs flatMap forwarders)
- (sdefs, idefs)
+ (sdefs, joinComment(idefs))
}
def annotationParents = List(
gen.scalaAnnotationDot(tpnme.Annotation),
@@ -833,10 +838,10 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners {
}
def typeDecl(mods: Modifiers): List[Tree] = in.token match {
- case ENUM => enumDecl(mods)
- case INTERFACE => interfaceDecl(mods)
+ case ENUM => joinComment(enumDecl(mods))
+ case INTERFACE => joinComment(interfaceDecl(mods))
case AT => annotationDecl(mods)
- case CLASS => classDecl(mods)
+ case CLASS => joinComment(classDecl(mods))
case _ => in.nextToken(); syntaxError("illegal start of type declaration", skipIt = true); List(errorTypeTree)
}
diff --git a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
index ac86dfd665..d2c58ae5f9 100644
--- a/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
+++ b/src/compiler/scala/tools/nsc/javac/JavaScanners.scala
@@ -577,21 +577,29 @@ trait JavaScanners extends ast.parser.ScannersCommon {
}
}
- protected def skipComment(): Boolean = {
- @tailrec def skipLineComment(): Unit = in.ch match {
- case CR | LF | SU =>
- case _ => in.next; skipLineComment()
- }
- @tailrec def skipJavaComment(): Unit = in.ch match {
- case SU => incompleteInputError("unclosed comment")
- case '*' => in.next; if (in.ch == '/') in.next else skipJavaComment()
- case _ => in.next; skipJavaComment()
- }
- in.ch match {
- case '/' => in.next ; skipLineComment() ; true
- case '*' => in.next ; skipJavaComment() ; true
- case _ => false
- }
+ protected def putCommentChar(): Unit = in.next()
+
+ 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)
+ }
+
+ 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
+ case '*' =>
+ putCommentChar()
+ in.ch match {
+ case '*' => skipBlockComment(isDoc = true)
+ case _ => skipBlockComment(isDoc = false)
+ }
+ true
+ case _ => false
}
// Identifiers ---------------------------------------------------------------
diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
index 8ea8c4deff..a16b306322 100644
--- a/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocAnalyzer.scala
@@ -103,48 +103,85 @@ abstract class ScaladocSyntaxAnalyzer[G <: Global](val global: G) extends Syntax
class ScaladocJavaUnitParser(unit: CompilationUnit) extends {
override val in = new ScaladocJavaUnitScanner(unit)
- } with JavaUnitParser(unit) { }
+ } with JavaUnitParser(unit) {
+
+ override def joinComment(trees: => List[Tree]): List[Tree] = {
+ val doc = in.flushDoc()
+
+ if ((doc ne null) && doc.raw.length > 0) {
+ log(s"joinComment(doc=$doc)")
+ val joined = trees map {
+ t =>
+ DocDef(doc, t) setPos {
+ if (t.pos.isDefined) {
+ val pos = doc.pos.withEnd(t.pos.end)
+ // always make the position transparent
+ pos.makeTransparent
+ } else {
+ t.pos
+ }
+ }
+ }
+ joined.find(_.pos.isOpaqueRange) foreach {
+ main =>
+ val mains = List(main)
+ joined foreach { t => if (t ne main) ensureNonOverlapping(t, mains) }
+ }
+ joined
+ }
+ else trees
+
+ // trees
+ }
+
+
+ }
class ScaladocJavaUnitScanner(unit: CompilationUnit) extends JavaUnitScanner(unit) {
+
+ //is the scanner currently in a doc comment
+ var inDocComment = false
+ var docStart: Int = 0
+
/** buffer for the documentation comment
*/
- var docBuffer: StringBuilder = null
+ val docBuffer: StringBuilder = new StringBuilder
+
+ var lastDoc: DocComment = null
+ def flushDoc() = try lastDoc finally lastDoc = null
+
/** add the given character to the documentation buffer
*/
- protected def putDocChar(c: Char) {
- if (docBuffer ne null) docBuffer.append(c)
+ override protected def putCommentChar(): Unit = {
+ if (inDocComment) docBuffer append in.ch
+ in.next
+ }
+
+ override protected def skipBlockComment(isDoc: Boolean): Unit = {
+ if (!inDocComment && isDoc) {
+ docBuffer append "/*" // at this point, in.ch == * and will be appended next
+ docStart = in.cpos
+ inDocComment = true
+ }
+ super.skipBlockComment(isDoc)
}
override protected def skipComment(): Boolean = {
- if (in.ch == '/') {
- do {
- in.next
- } while ((in.ch != CR) && (in.ch != LF) && (in.ch != SU))
- true
- } else if (in.ch == '*') {
- docBuffer = null
- in.next
- val scaladoc = ("/**", "*/")
- if (in.ch == '*')
- docBuffer = new StringBuilder(scaladoc._1)
- do {
- do {
- if (in.ch != '*' && in.ch != SU) {
- in.next; putDocChar(in.ch)
- }
- } while (in.ch != '*' && in.ch != SU)
- while (in.ch == '*') {
- in.next; putDocChar(in.ch)
- }
- } while (in.ch != '/' && in.ch != SU)
- if (in.ch == '/') in.next
- else incompleteInputError("unclosed comment")
+ val skipped = super.skipComment()
+ if (skipped && inDocComment) {
+ val str = docBuffer.toString
+ docBuffer.setLength(0) //clear buffer
+ val p = Position.range(unit.source, docStart - 2, docStart - 2, in.cpos)
+ signalParsedDocComment(str, p)
+ lastDoc = DocComment(str, p)
+ inDocComment = false
true
} else {
- false
+ skipped
}
}
+
}
class ScaladocUnitScanner(unit0: CompilationUnit, patches0: List[BracePatch]) extends UnitScanner(unit0, patches0) {
@@ -230,6 +267,7 @@ abstract class ScaladocSyntaxAnalyzer[G <: Global](val global: G) extends Syntax
}
}
class ScaladocUnitParser(unit: CompilationUnit, patches: List[BracePatch]) extends UnitParser(unit, patches) {
+
override def newScanner() = new ScaladocUnitScanner(unit, patches)
override def withPatches(patches: List[BracePatch]) = new ScaladocUnitParser(unit, patches)
diff --git a/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala b/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala
index 10bfe6f94b..107d81f78a 100644
--- a/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala
+++ b/src/scaladoc/scala/tools/nsc/doc/ScaladocGlobal.scala
@@ -13,6 +13,7 @@ trait ScaladocGlobalTrait extends Global {
override val useOffsetPositions = false
override def newUnitParser(unit: CompilationUnit) = new syntaxAnalyzer.ScaladocUnitParser(unit, Nil)
+ override def newJavaUnitParser(unit: CompilationUnit) = new syntaxAnalyzer.ScaladocJavaUnitParser(unit)
override lazy val syntaxAnalyzer = new ScaladocSyntaxAnalyzer[outer.type](outer) {
val runsAfter = List[String]()