aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/printing
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-10-23 12:21:37 +0200
committerMartin Odersky <odersky@gmail.com>2013-10-23 12:21:37 +0200
commit0661c2e7626adbe23216e89e221a4cda33ef0d85 (patch)
tree44b680f794dcc2dafcb015def3c3de0f0e3fb97e /src/dotty/tools/dotc/printing
parent70dc372796aa380efafa1a59bac83e945a191fbf (diff)
downloaddotty-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.scala82
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