diff options
author | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-05 10:35:10 -0800 |
---|---|---|
committer | Adriaan Moors <adriaan.moors@typesafe.com> | 2013-03-05 10:35:10 -0800 |
commit | 93c2a5bc8a363c09ba6024a5ab6fda99012e0b0b (patch) | |
tree | 898750c801ef5faeaa9feb4393fa9f8b06fee08b /src | |
parent | 1176035f271821021c36d1b3cab6b2888e99524d (diff) | |
parent | 53c499bec28ccbc7695c79f56e40f98e7732aeb7 (diff) | |
download | scala-93c2a5bc8a363c09ba6024a5ab6fda99012e0b0b.tar.gz scala-93c2a5bc8a363c09ba6024a5ab6fda99012e0b0b.tar.bz2 scala-93c2a5bc8a363c09ba6024a5ab6fda99012e0b0b.zip |
Merge pull request #2156 from vigdorchik/hierarchy
SI-7109 SI-7153 Generalize the API to get docComments: allow to force do...
Diffstat (limited to 'src')
5 files changed, 65 insertions, 61 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/DocComments.scala b/src/compiler/scala/tools/nsc/ast/DocComments.scala index e635c5e87d..6e39fc9aa1 100755 --- a/src/compiler/scala/tools/nsc/ast/DocComments.scala +++ b/src/compiler/scala/tools/nsc/ast/DocComments.scala @@ -56,6 +56,11 @@ trait DocComments { self: Global => else sym.owner.ancestors map (sym overriddenSymbol _) filter (_ != NoSymbol) } + def fillDocComment(sym: Symbol, comment: DocComment) { + docComments(sym) = comment + comment.defineVariables(sym) + } + /** The raw doc comment of symbol `sym`, minus usecase and define sections, augmented by * missing sections of an inherited doc comment. * If a symbol does not have a doc comment but some overridden version of it does, diff --git a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala index 73738ebd21..af82957a2e 100644 --- a/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala +++ b/src/compiler/scala/tools/nsc/interactive/CompilerControl.scala @@ -164,17 +164,22 @@ trait CompilerControl { self: Global => /** Sets sync var `response` to doc comment information for a given symbol. * - * @param sym The symbol whose doc comment should be retrieved (might come from a classfile) - * @param site The place where sym is observed. - * @param source The source file that's supposed to contain the definition - * @param response A response that will be set to the following: - * If `source` contains a definition of a given symbol that has a doc comment, - * the (expanded, raw, position) triplet for a comment, otherwise ("", "", NoPosition). - * Note: This operation does not automatically load `source`. If `source` - * is unloaded, it stays that way. + * @param sym The symbol whose doc comment should be retrieved (might come from a classfile) + * @param source The source file that's supposed to contain the definition + * @param site The symbol where 'sym' is observed + * @param fragments All symbols that can contribute to the generated documentation + * together with their source files. + * @param response A response that will be set to the following: + * If `source` contains a definition of a given symbol that has a doc comment, + * the (expanded, raw, position) triplet for a comment, otherwise ("", "", NoPosition). + * Note: This operation does not automatically load sources that are not yet loaded. */ - def askDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]) = - postWorkItem(new AskDocCommentItem(sym, site, source, response)) + def askDocComment(sym: Symbol, source: SourceFile, site: Symbol, fragments: List[(Symbol,SourceFile)], response: Response[(String, String, Position)]): Unit = + postWorkItem(new AskDocCommentItem(sym, source, site, fragments, response)) + + @deprecated("Use method that accepts fragments", "2.10.2") + def askDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]): Unit = + askDocComment(sym, source, site, (sym,source)::Nil, response) /** Sets sync var `response` to list of members that are visible * as members of the tree enclosing `pos`, possibly reachable by an implicit. @@ -390,9 +395,9 @@ trait CompilerControl { self: Global => response raise new MissingResponse } - case class AskDocCommentItem(val sym: Symbol, val site: Symbol, val source: SourceFile, response: Response[(String, String, Position)]) extends WorkItem { - def apply() = self.getDocComment(sym, site, source, response) - override def toString = "doc comment "+sym+" in "+source + case class AskDocCommentItem(val sym: Symbol, val source: SourceFile, val site: Symbol, val fragments: List[(Symbol,SourceFile)], response: Response[(String, String, Position)]) extends WorkItem { + def apply() = self.getDocComment(sym, source, site, fragments, response) + override def toString = "doc comment "+sym+" in "+source+" with fragments:"+fragments.mkString("(", ",", ")") def raiseMissing() = response raise new MissingResponse diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala index 4c2c3e35f8..1f2245abb5 100644 --- a/src/compiler/scala/tools/nsc/interactive/Global.scala +++ b/src/compiler/scala/tools/nsc/interactive/Global.scala @@ -704,8 +704,8 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") * If we do just removeUnit, some problems with default parameters can ensue. * Calls to this method could probably be replaced by removeUnit once default parameters are handled more robustly. */ - private def afterRunRemoveUnitOf(source: SourceFile) { - toBeRemovedAfterRun += source.file + private def afterRunRemoveUnitsOf(sources: List[SourceFile]) { + toBeRemovedAfterRun ++= sources map (_.file) } /** A fully attributed tree located at position `pos` */ @@ -713,7 +713,7 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") case None => reloadSources(List(pos.source)) try typedTreeAt(pos) - finally afterRunRemoveUnitOf(pos.source) + finally afterRunRemoveUnitsOf(List(pos.source)) case Some(unit) => informIDE("typedTreeAt " + pos) parseAndEnter(unit) @@ -763,14 +763,23 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") respond(response)(typedTree(source, forceReload)) } + private def withTempUnits[T](sources: List[SourceFile])(f: (SourceFile => RichCompilationUnit) => T): T = { + val unitOfSrc: SourceFile => RichCompilationUnit = src => unitOfFile(src.file) + sources filterNot (getUnit(_).isDefined) match { + case Nil => + f(unitOfSrc) + case unknown => + reloadSources(unknown) + try { + f(unitOfSrc) + } finally + afterRunRemoveUnitsOf(unknown) + } + } + private def withTempUnit[T](source: SourceFile)(f: RichCompilationUnit => T): T = - getUnit(source) match { - case None => - reloadSources(List(source)) - try f(getUnit(source).get) - finally afterRunRemoveUnitOf(source) - case Some(unit) => - f(unit) + withTempUnits(List(source)){ srcToUnit => + f(srcToUnit(source)) } /** Find a 'mirror' of symbol `sym` in unit `unit`. Pre: `unit is loaded. */ @@ -834,50 +843,36 @@ class Global(settings: Settings, _reporter: Reporter, projectName: String = "") } } + private def forceDocComment(sym: Symbol, unit: RichCompilationUnit) { + unit.body foreachPartial { + case DocDef(comment, defn) if defn.symbol == sym => + fillDocComment(defn.symbol, comment) + EmptyTree + case _: ValOrDefDef => + EmptyTree + } + } + /** Implements CompilerControl.askDocComment */ - private[interactive] def getDocComment(sym: Symbol, site: Symbol, source: SourceFile, response: Response[(String, String, Position)]) { - informIDE("getDocComment "+sym+" "+source) + private[interactive] def getDocComment(sym: Symbol, source: SourceFile, site: Symbol, fragments: List[(Symbol,SourceFile)], + response: Response[(String, String, Position)]) { + informIDE(s"getDocComment $sym at $source site $site") respond(response) { - withTempUnit(source){ u => - val mirror = findMirrorSymbol(sym, u) + withTempUnits(fragments.toList.unzip._2){ units => + for((sym, src) <- fragments) { + val mirror = findMirrorSymbol(sym, units(src)) + if (mirror ne NoSymbol) forceDocComment(mirror, units(src)) + } + val mirror = findMirrorSymbol(sym, units(source)) if (mirror eq NoSymbol) ("", "", NoPosition) else { - forceDocComment(mirror, u) - (expandedDocComment(mirror), rawDocComment(mirror), docCommentPos(mirror)) + (expandedDocComment(mirror, site), rawDocComment(mirror), docCommentPos(mirror)) } } } } - private def forceDocComment(sym: Symbol, unit: RichCompilationUnit) { - // Either typer has been run and we don't find DocDef, - // or we force the targeted typecheck here. - // In both cases doc comment maps should be filled for the subject symbol. - val docTree = - unit.body find { - case DocDef(_, defn) if defn.symbol eq sym => true - case _ => false - } - - for (t <- docTree) { - debugLog("Found DocDef tree for "+sym) - // Cannot get a typed tree at position since DocDef range is transparent. - val prevPos = unit.targetPos - val prevInterruptsEnabled = interruptsEnabled - try { - unit.targetPos = t.pos - interruptsEnabled = true - typeCheck(unit) - } catch { - case _: TyperResult => // ignore since we are after the side effect. - } finally { - unit.targetPos = prevPos - interruptsEnabled = prevInterruptsEnabled - } - } - } - def stabilizedType(tree: Tree): Type = tree match { case Ident(_) if tree.symbol.isStable => singleType(NoPrefix, tree.symbol) diff --git a/src/compiler/scala/tools/nsc/interactive/Picklers.scala b/src/compiler/scala/tools/nsc/interactive/Picklers.scala index 84cb03c140..2b389158c3 100644 --- a/src/compiler/scala/tools/nsc/interactive/Picklers.scala +++ b/src/compiler/scala/tools/nsc/interactive/Picklers.scala @@ -166,8 +166,8 @@ trait Picklers { self: Global => .asClass (classOf[AskLinkPosItem]) implicit def askDocCommentItem: CondPickler[AskDocCommentItem] = - (pkl[Symbol] ~ pkl[Symbol] ~ pkl[SourceFile]) - .wrapped { case sym ~ site ~ source => new AskDocCommentItem(sym, site, source, new Response) } { item => item.sym ~ item.site ~ item.source } + (pkl[Symbol] ~ pkl[SourceFile] ~ pkl[Symbol] ~ pkl[List[(Symbol,SourceFile)]]) + .wrapped { case sym ~ source ~ site ~ fragments => new AskDocCommentItem(sym, source, site, fragments, new Response) } { item => item.sym ~ item.source ~ item.site ~ item.fragments } .asClass (classOf[AskDocCommentItem]) implicit def askLoadedTypedItem: CondPickler[AskLoadedTypedItem] = diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 60e50b517e..fcf7ba6efb 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -5292,8 +5292,7 @@ trait Typers extends Modes with Adaptations with Tags { def typedDocDef(docdef: DocDef) = { if (forScaladoc && (sym ne null) && (sym ne NoSymbol)) { val comment = docdef.comment - docComments(sym) = comment - comment.defineVariables(sym) + fillDocComment(sym, comment) val typer1 = newTyper(context.makeNewScope(tree, context.owner)) for (useCase <- comment.useCases) { typer1.silent(_.typedUseCase(useCase)) match { |