diff options
author | Martin Odersky <odersky@gmail.com> | 2013-10-23 12:21:37 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-10-23 12:21:37 +0200 |
commit | 0661c2e7626adbe23216e89e221a4cda33ef0d85 (patch) | |
tree | 44b680f794dcc2dafcb015def3c3de0f0e3fb97e /src/dotty/tools/dotc/printing | |
parent | 70dc372796aa380efafa1a59bac83e945a191fbf (diff) | |
download | dotty-0661c2e7626adbe23216e89e221a4cda33ef0d85.tar.gz dotty-0661c2e7626adbe23216e89e221a4cda33ef0d85.tar.bz2 dotty-0661c2e7626adbe23216e89e221a4cda33ef0d85.zip |
Refined disambiguating printing
Diffstat (limited to 'src/dotty/tools/dotc/printing')
-rw-r--r-- | src/dotty/tools/dotc/printing/Disambiguation.scala | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/printing/Disambiguation.scala b/src/dotty/tools/dotc/printing/Disambiguation.scala new file mode 100644 index 000000000..196b8f1ae --- /dev/null +++ b/src/dotty/tools/dotc/printing/Disambiguation.scala @@ -0,0 +1,82 @@ +package dotty.tools.dotc +package printing + +import core._ +import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Contexts._ +import collection.mutable +import scala.annotation.switch + +object Disambiguation { + + private class State { + var hasConflicts = false + val symString = new mutable.HashMap[Symbol, String] + val variants = new mutable.HashMap[String, mutable.ListBuffer[Symbol]] + } + + def newPrinter: Context => Printer = { + val state = new State + new Printer(state)(_) + } + + class Printer(state: State)(_ctx: Context) extends RefinedPrinter(_ctx) { + import state._ + + override def simpleNameString(sym: Symbol): String = { + if ((sym is ModuleClass) && sym.sourceModule.exists) simpleNameString(sym.sourceModule) + else symString.getOrElse(sym, recordedNameString(sym)) + } + + private def rawNameString(sym: Symbol) = super.simpleNameString(sym) + + private def recordedNameString(sym: Symbol): String = { + val str = rawNameString(sym) + val existing = variants.getOrElse(str, new mutable.ListBuffer) + if (!(existing contains sym)) { + hasConflicts |= existing.nonEmpty + variants(str) = (existing += sym) + } + str + } + + def disambiguated(): Boolean = { + val res = hasConflicts + while (hasConflicts) disambiguate() + res + } + + private def qualifiers: Stream[String] = + Stream("", "(some other)", "(some 3rd)") ++ (Stream.from(4) map (n => s"(some ${n}th)")) + + private def disambiguate(): Unit = { + def update(sym: Symbol, str: String) = if (!(symString contains sym)) symString(sym) = str + def disambiguated(sym: Symbol, owner: Symbol) = s"${rawNameString(sym)}(in ${simpleNameString(owner)})" + hasConflicts = false + for ((name, vs) <- variants.toList) + if (vs.tail.nonEmpty) { + for ((owner, syms) <- vs.groupBy(_.effectiveOwner)) { + if (syms.tail.isEmpty) update(syms.head, disambiguated(syms.head, owner)) + else + for { + (kind, syms1) <- syms.groupBy(kindString) + (sym, qual) <- syms1 zip qualifiers + } { + update(sym, s"$qual$kind ${disambiguated(sym, owner)}") + } + } + } + } + } + + def disambiguated(op: Context => String)(implicit ctx: Context): String = { + val dctx = ctx.printer match { + case dp: Printer => ctx + case _ => ctx.fresh.withPrinterFn(newPrinter) + } + val res = op(dctx) + dctx.printer match { + case dp: Printer if dp.disambiguated() => op(dctx) + case _ => res + } + } +}
\ No newline at end of file |