diff options
Diffstat (limited to 'src/scaladoc/scala/tools/nsc/doc/DocParser.scala')
-rw-r--r-- | src/scaladoc/scala/tools/nsc/doc/DocParser.scala | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/scaladoc/scala/tools/nsc/doc/DocParser.scala b/src/scaladoc/scala/tools/nsc/doc/DocParser.scala new file mode 100644 index 0000000000..6dc3e5a62b --- /dev/null +++ b/src/scaladoc/scala/tools/nsc/doc/DocParser.scala @@ -0,0 +1,69 @@ +/* NSC -- new Scala compiler + * Copyright 2005-2013 LAMP/EPFL + * @author Paul Phillips + */ + +package scala.tools +package nsc +package doc + +import reporters._ +import scala.reflect.internal.util._ +import DocParser.Parsed + +/** A very minimal global customized for extracting `DocDefs`. It stops + * right after parsing so it can read `DocDefs` from source code which would + * otherwise cause the compiler to go haywire. + */ +class DocParser(settings: nsc.Settings, reporter: Reporter) extends Global(settings, reporter) { + def this(settings: Settings) = this(settings, new ConsoleReporter(settings)) + def this() = this(new Settings(Console println _)) + + // the usual global initialization + locally { new Run() } + + override protected def computeInternalPhases() { + phasesSet += syntaxAnalyzer + } + + /** Returns a list of `DocParser.Parseds`, which hold the DocDefs found + * in the given code along with the surrounding trees. + */ + def docDefs(code: String) = { + def loop(enclosing: List[Tree], tree: Tree): List[Parsed] = tree match { + case x: PackageDef => x.stats flatMap (t => loop(enclosing :+ x, t)) + case x: DocDef => new Parsed(enclosing, x) :: loop(enclosing :+ x.definition, x.definition) + case x => x.children flatMap (t => loop(enclosing, t)) + } + loop(Nil, docUnit(code)) + } + + /** A compilation unit containing parsed source. + */ + def docUnit(code: String) = { + val unit = new CompilationUnit(new BatchSourceFile("<console>", code)) + val scanner = newUnitParser(unit) + + scanner.compilationUnit() + } +} + +/** Since the DocParser's whole reason for existing involves trashing a + * global, it is designed to bottle up general `Global#Tree` types rather + * than path dependent ones. The recipient will have to deal. + */ +object DocParser { + type Tree = Global#Tree + type DefTree = Global#DefTree + type DocDef = Global#DocDef + type Name = Global#Name + + class Parsed(val enclosing: List[Tree], val docDef: DocDef) { + def nameChain: List[Name] = (enclosing :+ docDef.definition) collect { case x: DefTree => x.name } + def raw: String = docDef.comment.raw + + override def toString = ( + nameChain.init.map(x => if (x.isTypeName) x + "#" else x + ".").mkString + nameChain.last + ) + } +} |