~ubuntu-branches/debian/sid/scala/sid

« back to all changes in this revision

Viewing changes to src/compiler/scala/tools/nsc/ast/TreePrinters.scala

  • Committer: Package Import Robot
  • Author(s): Emmanuel Bourg, Mehdi Dogguy, Lucas Satabin, Frank S. Thomas, Emmanuel Bourg
  • Date: 2015-06-05 23:52:59 UTC
  • mfrom: (1.2.11)
  • Revision ID: package-import@ubuntu.com-20150605235259-wk00vgk83dh8o19g
Tags: 2.10.5-1
* Team upload.

[ Mehdi Dogguy ]
* New upstream release (Closes: #744278).

[ Lucas Satabin ]
* Update patches
* Update the clean target
* Update paths of elements to install
* Update watch file

[ Frank S. Thomas ]
* Remove myself from Uploaders.

[ Emmanuel Bourg ]
* The package has been adopted by the Java Team (Closes: #754935)
* Patched the build to avoid downloading libraries from the Internet
* Replaced the minified JavaScript files with unobfuscated ones
* No longer build scala-partest.jar until diffutils is packaged or replaced
* debian/watch: Fixed the versions matched (x.y.z instead of x.y.z..z)
* debian/rules:
  - Added the missing get-orig-source target (Closes: #724704)
  - Improved the clean target
* debian/control:
  - Build depend on scala (>= 2.10) and bnd
  - Use canonical URLs for the Vcs-* fields
  - Standards-Version updated to 3.9.6 (no changes)
* Switch to debhelper level 9

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* NSC -- new Scala compiler
2
 
 * Copyright 2005-2011 LAMP/EPFL
3
 
 * @author  Martin Odersky
4
 
 */
5
 
 
6
 
package scala.tools.nsc
7
 
package ast
8
 
 
9
 
import java.io.{ OutputStream, PrintWriter, StringWriter, Writer }
10
 
import symtab.Flags._
11
 
import symtab.SymbolTable
12
 
 
13
 
trait TreePrinters { trees: SymbolTable =>
14
 
 
15
 
  import treeInfo.{ IsTrue, IsFalse }
16
 
 
17
 
  final val showOuterTests = false
18
 
 
19
 
  /** Adds backticks if the name is a scala keyword. */
20
 
  def quotedName(name: Name, decode: Boolean): String = {
21
 
    val s = if (decode) name.decode else name.toString
22
 
    val term = name.toTermName
23
 
    if (nme.keywords(term) && term != nme.USCOREkw) "`%s`" format s
24
 
    else s
25
 
  }
26
 
  def quotedName(name: Name): String = quotedName(name, false)
27
 
 
28
 
  /** Turns a path into a String, introducing backquotes
29
 
   *  as necessary.
30
 
   */
31
 
  def backquotedPath(t: Tree): String = t match {
32
 
    case Select(qual, name) => "%s.%s".format(backquotedPath(qual), quotedName(name))
33
 
    case Ident(name)        => quotedName(name)
34
 
    case _                  => t.toString
35
 
  }
36
 
 
37
 
  class TreePrinter(out: PrintWriter) extends trees.AbsTreePrinter(out) {
38
 
    protected var indentMargin = 0
39
 
    protected val indentStep = 2
40
 
    protected var indentString = "                                        " // 40
41
 
 
42
 
    def flush() = out.flush()
43
 
 
44
 
    def indent() = indentMargin += indentStep
45
 
    def undent() = indentMargin -= indentStep
46
 
 
47
 
    protected def doPrintPositions = settings.Xprintpos.value
48
 
    def printPosition(tree: Tree) = if (doPrintPositions) print(tree.pos.show)
49
 
 
50
 
    def println() {
51
 
      out.println()
52
 
      while (indentMargin > indentString.length())
53
 
        indentString += indentString
54
 
      if (indentMargin > 0)
55
 
        out.write(indentString, 0, indentMargin)
56
 
    }
57
 
 
58
 
    def printSeq[a](ls: List[a])(printelem: a => Unit)(printsep: => Unit) {
59
 
      ls match {
60
 
        case List() =>
61
 
        case List(x) => printelem(x)
62
 
        case x :: rest => printelem(x); printsep; printSeq(rest)(printelem)(printsep)
63
 
      }
64
 
    }
65
 
 
66
 
    def printColumn(ts: List[Tree], start: String, sep: String, end: String) {
67
 
      print(start); indent; println()
68
 
      printSeq(ts){print}{print(sep); println()}; undent; println(); print(end)
69
 
    }
70
 
 
71
 
    def printRow(ts: List[Tree], start: String, sep: String, end: String) {
72
 
      print(start); printSeq(ts){print}{print(sep)}; print(end)
73
 
    }
74
 
 
75
 
    def printRow(ts: List[Tree], sep: String) { printRow(ts, "", sep, "") }
76
 
 
77
 
    def printTypeParams(ts: List[TypeDef]) {
78
 
      if (!ts.isEmpty) {
79
 
        print("["); printSeq(ts){ t =>
80
 
          printAnnotations(t)
81
 
          printParam(t)
82
 
        }{print(", ")}; print("]")
83
 
      }
84
 
    }
85
 
 
86
 
    def printValueParams(ts: List[ValDef]) {
87
 
      print("(")
88
 
      if (!ts.isEmpty) printFlags(ts.head.mods.flags & IMPLICIT, "")
89
 
      printSeq(ts){printParam}{print(", ")}
90
 
      print(")")
91
 
    }
92
 
 
93
 
    def printParam(tree: Tree) {
94
 
      tree match {
95
 
        case ValDef(mods, name, tp, rhs) =>
96
 
          printPosition(tree)
97
 
          printAnnotations(tree)
98
 
          print(symName(tree, name)); printOpt(": ", tp); printOpt(" = ", rhs)
99
 
        case TypeDef(mods, name, tparams, rhs) =>
100
 
          printPosition(tree)
101
 
          print(symName(tree, name))
102
 
          printTypeParams(tparams); print(rhs)
103
 
      }
104
 
    }
105
 
 
106
 
    def printBlock(tree: Tree) {
107
 
      tree match {
108
 
        case Block(_, _) =>
109
 
          print(tree)
110
 
        case _ =>
111
 
          printColumn(List(tree), "{", ";", "}")
112
 
      }
113
 
    }
114
 
 
115
 
    private def symFn[T](tree: Tree, f: Symbol => T, orElse: => T): T = tree.symbol match {
116
 
      case null | NoSymbol  => orElse
117
 
      case sym              => f(sym)
118
 
    }
119
 
    private def ifSym(tree: Tree, p: Symbol => Boolean) = symFn(tree, p, false)
120
 
 
121
 
    private def symNameInternal(tree: Tree, name: Name, decoded: Boolean): String = {
122
 
      def nameFn(sym: Symbol) = {
123
 
        val prefix = if (sym.isMixinConstructor) "/*%s*/".format(quotedName(sym.owner.name, decoded)) else ""
124
 
        prefix + tree.symbol.nameString
125
 
      }
126
 
      symFn(tree, nameFn, quotedName(name, decoded))
127
 
    }
128
 
 
129
 
    def decodedSymName(tree: Tree, name: Name) = symNameInternal(tree, name, true)
130
 
    def symName(tree: Tree, name: Name) = symNameInternal(tree, name, false)
131
 
 
132
 
    def printOpt(prefix: String, tree: Tree) {
133
 
      if (!tree.isEmpty) { print(prefix); print(tree) }
134
 
    }
135
 
 
136
 
    def printModifiers(tree: Tree, mods: Modifiers): Unit = printFlags(
137
 
       if (tree.symbol == NoSymbol) mods.flags else tree.symbol.flags, "" + (
138
 
         if (tree.symbol == NoSymbol) mods.privateWithin
139
 
         else if (tree.symbol.hasAccessBoundary) tree.symbol.privateWithin.name
140
 
         else ""
141
 
      )
142
 
    )
143
 
 
144
 
    def printFlags(flags: Long, privateWithin: String) {
145
 
      var mask: Long = if (settings.debug.value) -1L else PrintableFlags
146
 
      val s = flagsToString(flags & mask, privateWithin)
147
 
      if (s != "") print(s + " ")
148
 
    }
149
 
 
150
 
    def printAnnotations(tree: Tree) {
151
 
      val annots =
152
 
        if (tree.symbol.hasAssignedAnnotations) tree.symbol.annotations
153
 
        else tree.asInstanceOf[MemberDef].mods.annotations
154
 
 
155
 
      annots foreach (annot => print("@"+annot+" "))
156
 
    }
157
 
 
158
 
    def print(str: String) { out.print(str) }
159
 
    def print(name: Name) { print(quotedName(name)) }
160
 
 
161
 
    private var currentOwner: Symbol = NoSymbol
162
 
    private var selectorType: Type = NoType
163
 
 
164
 
    def printRaw(tree: Tree) {
165
 
      tree match {
166
 
        case EmptyTree =>
167
 
          print("<empty>")
168
 
 
169
 
        case ClassDef(mods, name, tparams, impl) =>
170
 
          printAnnotations(tree)
171
 
          printModifiers(tree, mods)
172
 
          val word =
173
 
            if (mods.hasTraitFlag) "trait"
174
 
            else if (ifSym(tree, _.isModuleClass)) "object"
175
 
            else "class"
176
 
 
177
 
          print(word + " " + symName(tree, name))
178
 
          printTypeParams(tparams)
179
 
          print(if (mods.isDeferred) " <: " else " extends "); print(impl)
180
 
 
181
 
        case PackageDef(packaged, stats) =>
182
 
          printAnnotations(tree)
183
 
          print("package "); print(packaged); printColumn(stats, " {", ";", "}")
184
 
 
185
 
        case ModuleDef(mods, name, impl) =>
186
 
          printAnnotations(tree)
187
 
          printModifiers(tree, mods); print("object " + symName(tree, name))
188
 
          print(" extends "); print(impl)
189
 
 
190
 
        case ValDef(mods, name, tp, rhs) =>
191
 
          printAnnotations(tree)
192
 
          printModifiers(tree, mods)
193
 
          print(if (mods.isMutable) "var " else "val ")
194
 
          print(symName(tree, name))
195
 
          printOpt(": ", tp)
196
 
          if (!mods.isDeferred) {
197
 
            print(" = ")
198
 
            if (rhs.isEmpty) print("_") else print(rhs)
199
 
          }
200
 
 
201
 
        case DefDef(mods, name, tparams, vparamss, tp, rhs) =>
202
 
          printAnnotations(tree)
203
 
          printModifiers(tree, mods)
204
 
          print("def " + symName(tree, name))
205
 
          printTypeParams(tparams); vparamss foreach printValueParams
206
 
          printOpt(": ", tp); printOpt(" = ", rhs)
207
 
 
208
 
        case TypeDef(mods, name, tparams, rhs) =>
209
 
          if (mods hasFlag (PARAM | DEFERRED)) {
210
 
            printAnnotations(tree)
211
 
            printModifiers(tree, mods); print("type "); printParam(tree)
212
 
          } else {
213
 
            printAnnotations(tree)
214
 
            printModifiers(tree, mods); print("type " + symName(tree, name))
215
 
            printTypeParams(tparams); printOpt(" = ", rhs)
216
 
          }
217
 
 
218
 
        case LabelDef(name, params, rhs) =>
219
 
          print(symName(tree, name)); printRow(params, "(", ",", ")"); printBlock(rhs)
220
 
 
221
 
        case Import(expr, selectors) =>
222
 
          // Is this selector remapping a name (i.e, {name1 => name2})
223
 
          def isNotRemap(s: ImportSelector) : Boolean = (s.name == nme.WILDCARD || s.name == s.rename)
224
 
          def selectorToString(s: ImportSelector): String = {
225
 
            val from = quotedName(s.name)
226
 
            if (isNotRemap(s)) from
227
 
            else from + "=>" + quotedName(s.rename)
228
 
          }
229
 
          print("import "); print(backquotedPath(expr))
230
 
          print(".")
231
 
          selectors match {
232
 
            case List(s) =>
233
 
              // If there is just one selector and it is not remapping a name, no braces are needed
234
 
              if (isNotRemap(s)) {
235
 
                print(selectorToString(s))
236
 
              } else {
237
 
                print("{"); print(selectorToString(s)); print("}")
238
 
              }
239
 
              // If there is more than one selector braces are always needed
240
 
            case many =>
241
 
              print(many.map(selectorToString).mkString("{", ", ", "}"))
242
 
          }
243
 
 
244
 
        case DocDef(comment, definition) =>
245
 
          print(comment.raw); println(); print(definition)
246
 
 
247
 
        case Template(parents, self, body) =>
248
 
          val currentOwner1 = currentOwner
249
 
          if (tree.symbol != NoSymbol) currentOwner = tree.symbol.owner
250
 
          printRow(parents, " with ")
251
 
          if (!body.isEmpty) {
252
 
            if (self.name != nme.WILDCARD) {
253
 
              print(" { "); print(self.name); printOpt(": ", self.tpt); print(" => ")
254
 
            } else if (!self.tpt.isEmpty) {
255
 
              print(" { _ : "); print(self.tpt); print(" => ")
256
 
            } else {
257
 
              print(" {")
258
 
            }
259
 
            printColumn(body, "", ";", "}")
260
 
          }
261
 
          currentOwner = currentOwner1
262
 
 
263
 
        case Block(stats, expr) =>
264
 
          printColumn(stats ::: List(expr), "{", ";", "}")
265
 
 
266
 
        case Match(selector, cases) =>
267
 
          val selectorType1 = selectorType
268
 
          selectorType = selector.tpe
269
 
          print(selector); printColumn(cases, " match {", "", "}")
270
 
          selectorType = selectorType1
271
 
 
272
 
        case CaseDef(pat, guard, body) =>
273
 
          print("case ")
274
 
          def patConstr(pat: Tree): Tree = pat match {
275
 
            case Apply(fn, args) => patConstr(fn)
276
 
            case _ => pat
277
 
          }
278
 
          if (showOuterTests &&
279
 
              needsOuterTest(
280
 
                patConstr(pat).tpe.finalResultType, selectorType, currentOwner))
281
 
            print("???")
282
 
          print(pat); printOpt(" if ", guard)
283
 
          print(" => "); print(body)
284
 
 
285
 
        case Alternative(trees) =>
286
 
          printRow(trees, "(", "| ", ")")
287
 
 
288
 
        case Star(elem) =>
289
 
          print("("); print(elem); print(")*")
290
 
 
291
 
        case Bind(name, t) =>
292
 
          print("("); print(symName(tree, name)); print(" @ "); print(t); print(")")
293
 
 
294
 
        case UnApply(fun, args) =>
295
 
          print(fun); print(" <unapply> "); printRow(args, "(", ", ", ")")
296
 
 
297
 
        case ArrayValue(elemtpt, trees) =>
298
 
          print("Array["); print(elemtpt); printRow(trees, "]{", ", ", "}")
299
 
 
300
 
        case Function(vparams, body) =>
301
 
          print("("); printValueParams(vparams); print(" => "); print(body); print(")")
302
 
          if (settings.uniqid.value && tree.symbol != null) print("#"+tree.symbol.id)
303
 
 
304
 
        case Assign(lhs, rhs) =>
305
 
          print(lhs); print(" = "); print(rhs)
306
 
 
307
 
        case AssignOrNamedArg(lhs, rhs) =>
308
 
          print(lhs); print(" = "); print(rhs)
309
 
 
310
 
        case If(cond, thenp, elsep) =>
311
 
          print("if ("); print(cond); print(")"); indent; println()
312
 
          print(thenp); undent
313
 
          if (!elsep.isEmpty) {
314
 
            println(); print("else"); indent; println(); print(elsep); undent
315
 
          }
316
 
 
317
 
        case Return(expr) =>
318
 
          print("return "); print(expr)
319
 
 
320
 
        case Try(block, catches, finalizer) =>
321
 
          print("try "); printBlock(block)
322
 
          if (!catches.isEmpty) printColumn(catches, " catch {", "", "}")
323
 
          printOpt(" finally ", finalizer)
324
 
 
325
 
        case Throw(expr) =>
326
 
          print("throw "); print(expr)
327
 
 
328
 
        case New(tpe) =>
329
 
          print("new "); print(tpe)
330
 
 
331
 
        case Typed(expr, tp) =>
332
 
          print("("); print(expr); print(": "); print(tp); print(")")
333
 
 
334
 
        case TypeApply(fun, targs) =>
335
 
          print(fun); printRow(targs, "[", ", ", "]")
336
 
 
337
 
        case Apply(fun, vargs) =>
338
 
          print(fun); printRow(vargs, "(", ", ", ")")
339
 
 
340
 
        case ApplyDynamic(qual, vargs) =>
341
 
          print("<apply-dynamic>("); print(qual); print("#"); print(tree.symbol.nameString)
342
 
          printRow(vargs, ", (", ", ", "))")
343
 
 
344
 
        case Super(This(qual), mix) =>
345
 
          if (!qual.isEmpty || tree.symbol != NoSymbol) print(symName(tree, qual) + ".")
346
 
          print("super")
347
 
          if (!mix.isEmpty)
348
 
            print("[" + mix + "]")
349
 
 
350
 
        case Super(qual, mix) =>
351
 
          print(qual)
352
 
          print(".super")
353
 
          if (!mix.isEmpty)
354
 
            print("[" + mix + "]")
355
 
 
356
 
        case This(qual) =>
357
 
          if (!qual.isEmpty) print(symName(tree, qual) + ".")
358
 
          print("this")
359
 
 
360
 
        case Select(qual @ New(tpe), name) if (!settings.debug.value) =>
361
 
          print(qual)
362
 
 
363
 
        case Select(qualifier, name) =>
364
 
          print(backquotedPath(qualifier)); print("."); print(symName(tree, name))
365
 
 
366
 
        case Ident(name) =>
367
 
          print(symName(tree, name))
368
 
 
369
 
        case Literal(x) =>
370
 
          print(x.escapedStringValue)
371
 
 
372
 
        case tt: TypeTree =>
373
 
          if ((tree.tpe eq null) || (settings.Xprintpos.value && tt.original != null)) {
374
 
            if (tt.original != null) { print("<type: "); print(tt.original); print(">") }
375
 
            else print("<type ?>")
376
 
          } else if ((tree.tpe.typeSymbol ne null) && tree.tpe.typeSymbol.isAnonymousClass) {
377
 
            print(tree.tpe.typeSymbol.toString())
378
 
          } else {
379
 
            print(tree.tpe.toString())
380
 
          }
381
 
 
382
 
        case Annotated(Apply(Select(New(tpt), nme.CONSTRUCTOR), args), tree) =>
383
 
          def printAnnot() {
384
 
            print("@"); print(tpt)
385
 
            if (!args.isEmpty)
386
 
              printRow(args, "(", ",", ")")
387
 
          }
388
 
          if (tree.isType) { print(tree); print(" "); printAnnot() }
389
 
          else { print(tree); print(": "); printAnnot() }
390
 
 
391
 
        case SingletonTypeTree(ref) =>
392
 
          print(ref); print(".type")
393
 
 
394
 
        case SelectFromTypeTree(qualifier, selector) =>
395
 
          print(qualifier); print("#"); print(symName(tree, selector))
396
 
 
397
 
        case CompoundTypeTree(templ) =>
398
 
          print(templ)
399
 
 
400
 
        case AppliedTypeTree(tp, args) =>
401
 
          print(tp); printRow(args, "[", ", ", "]")
402
 
 
403
 
        case TypeBoundsTree(lo, hi) =>
404
 
          printOpt(" >: ", lo); printOpt(" <: ", hi)
405
 
 
406
 
        case ExistentialTypeTree(tpt, whereClauses) =>
407
 
          print(tpt);
408
 
          printColumn(whereClauses, " forSome { ", ";", "}")
409
 
 
410
 
        case SelectFromArray(qualifier, name, _) =>
411
 
          print(qualifier); print(".<arr>"); print(symName(tree, name))
412
 
 
413
 
        case TypeTreeWithDeferredRefCheck() =>
414
 
          print("<tree with deferred refcheck>")
415
 
 
416
 
        case tree =>
417
 
          print("<unknown tree of class "+tree.getClass+">")
418
 
      }
419
 
      if (settings.printtypes.value && tree.isTerm && !tree.isEmpty) {
420
 
        print("{"); print(if (tree.tpe eq null) "<null>" else tree.tpe.toString()); print("}")
421
 
      }
422
 
    }
423
 
 
424
 
    def print(tree: Tree) {
425
 
      printPosition(tree)
426
 
      printRaw(
427
 
        if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) {
428
 
          tree match {
429
 
            case ClassDef(_, _, _, impl @ Template(ps, emptyValDef, body))
430
 
            if (tree.symbol.thisSym != tree.symbol) =>
431
 
              ClassDef(tree.symbol, Template(ps, ValDef(tree.symbol.thisSym), body))
432
 
            case ClassDef(_, _, _, impl)           => ClassDef(tree.symbol, impl)
433
 
            case ModuleDef(_, _, impl)             => ModuleDef(tree.symbol, impl)
434
 
            case ValDef(_, _, _, rhs)              => ValDef(tree.symbol, rhs)
435
 
            case DefDef(_, _, _, vparamss, _, rhs) => DefDef(tree.symbol, vparamss, rhs)
436
 
            case TypeDef(_, _, _, rhs)             => TypeDef(tree.symbol, rhs)
437
 
            case _ => tree
438
 
          }
439
 
        } else tree)
440
 
    }
441
 
 
442
 
    def print(unit: CompilationUnit) {
443
 
      print("// Scala source: " + unit.source + "\n")
444
 
      if (unit.body == null) print("<null>")
445
 
      else { print(unit.body); println() }
446
 
 
447
 
      println()
448
 
      flush()
449
 
    }
450
 
  }
451
 
 
452
 
  /** A tree printer which is stingier about vertical whitespace and unnecessary
453
 
   *  punctuation than the standard one.
454
 
   */
455
 
  class CompactTreePrinter(out: PrintWriter) extends TreePrinter(out) {
456
 
    override def printRow(ts: List[Tree], start: String, sep: String, end: String) {
457
 
      print(start)
458
 
      printSeq(ts)(print)(print(sep))
459
 
      print(end)
460
 
    }
461
 
 
462
 
    // drill down through Blocks and pull out the real statements.
463
 
    def allStatements(t: Tree): List[Tree] = t match {
464
 
      case Block(stmts, expr) => (stmts flatMap allStatements) ::: List(expr)
465
 
      case _                  => List(t)
466
 
    }
467
 
 
468
 
    def printLogicalOr(t1: (Tree, Boolean), t2: (Tree, Boolean)) =
469
 
      printLogicalOp(t1, t2, "||")
470
 
 
471
 
    def printLogicalAnd(t1: (Tree, Boolean), t2: (Tree, Boolean)) =
472
 
      printLogicalOp(t1, t2, "&&")
473
 
 
474
 
    def printLogicalOp(t1: (Tree, Boolean), t2: (Tree, Boolean), op: String) = {
475
 
      def maybenot(tvalue: Boolean) = if (tvalue) "" else "!"
476
 
 
477
 
      print("%s(" format maybenot(t1._2))
478
 
      printRaw(t1._1)
479
 
      print(") %s %s(".format(op, maybenot(t2._2)))
480
 
      printRaw(t2._1)
481
 
      print(")")
482
 
    }
483
 
 
484
 
    override def printRaw(tree: Tree): Unit = {
485
 
      // routing supercalls through this for debugging ease
486
 
      def s() = super.printRaw(tree)
487
 
 
488
 
      tree match {
489
 
        // labels used for jumps - does not map to valid scala code
490
 
        case LabelDef(name, params, rhs) =>
491
 
          print("labeldef %s(%s) = ".format(name, params mkString ","))
492
 
          printRaw(rhs)
493
 
 
494
 
        case Ident(name) =>
495
 
          print(decodedSymName(tree, name))
496
 
 
497
 
        // target.method(arg) ==> target method arg
498
 
        case Apply(Select(target, method), List(arg)) =>
499
 
          if (method.decode.toString == "||")
500
 
            printLogicalOr(target -> true, arg -> true)
501
 
          else if (method.decode.toString == "&&")
502
 
            printLogicalAnd(target -> true, arg -> true)
503
 
          else (target, arg) match {
504
 
            case (_: Ident, _: Literal | _: Ident)  =>
505
 
              printRaw(target)
506
 
              print(" ")
507
 
              printRaw(Ident(method))
508
 
              print(" ")
509
 
              printRaw(arg)
510
 
            case _                        => s()
511
 
          }
512
 
 
513
 
        // target.unary_! ==> !target
514
 
        case Select(qualifier, name) if (name.decode startsWith "unary_") =>
515
 
          print(name.decode drop 6)
516
 
          printRaw(qualifier)
517
 
 
518
 
        case Select(qualifier, name) =>
519
 
          printRaw(qualifier)
520
 
          print(".")
521
 
          print(quotedName(name, true))
522
 
 
523
 
        // target.toString() ==> target.toString
524
 
        case Apply(fn, Nil)   => printRaw(fn)
525
 
 
526
 
        // if a Block only continues one actual statement, just print it.
527
 
        case Block(stats, expr) =>
528
 
          allStatements(tree) match {
529
 
            case List(x)            => printRaw(x)
530
 
            case xs                 => s()
531
 
          }
532
 
 
533
 
        // We get a lot of this stuff
534
 
        case If( IsTrue(), x, _)        => printRaw(x)
535
 
        case If(IsFalse(), _, x)        => printRaw(x)
536
 
 
537
 
        case If(cond,  IsTrue(), elsep)   =>  printLogicalOr(cond -> true, elsep -> true)
538
 
        case If(cond, IsFalse(), elsep)   => printLogicalAnd(cond -> false, elsep -> true)
539
 
        case If(cond,  thenp, IsTrue())   =>  printLogicalOr(cond -> false, thenp -> true)
540
 
        case If(cond,  thenp, IsFalse())  => printLogicalAnd(cond -> true, thenp -> true)
541
 
 
542
 
        // If thenp or elsep has only one statement, it doesn't need more than one line.
543
 
        case If(cond, thenp, elsep) =>
544
 
          def ifIndented(x: Tree) = {
545
 
            indent ; println() ; printRaw(x) ; undent
546
 
          }
547
 
 
548
 
          val List(thenStmts, elseStmts) = List(thenp, elsep) map allStatements
549
 
          print("if ("); print(cond); print(") ")
550
 
 
551
 
          thenStmts match {
552
 
            case List(x: If)  => ifIndented(x)
553
 
            case List(x)      => printRaw(x)
554
 
            case _            => printRaw(thenp)
555
 
          }
556
 
 
557
 
          if (elseStmts.nonEmpty) {
558
 
            print(" else")
559
 
            indent ; println()
560
 
            elseStmts match {
561
 
              case List(x)  => printRaw(x)
562
 
              case _        => printRaw(elsep)
563
 
            }
564
 
            undent ; println()
565
 
          }
566
 
        case _        => s()
567
 
      }
568
 
    }
569
 
  }
570
 
 
571
 
  /** This must guarantee not to force any evaluation, so we can learn
572
 
   *  a little bit about trees in the midst of compilation without altering
573
 
   *  the natural course of events.
574
 
   */
575
 
  class SafeTreePrinter(out: PrintWriter) extends TreePrinter(out) {
576
 
    override def print(tree: Tree) {
577
 
      printPosition(tree)
578
 
      printRaw(tree)
579
 
    }
580
 
    private def default(t: Tree) = t.getClass.getName.reverse.takeWhile(_ != '.').reverse
581
 
    private def params(trees: List[Tree]): String = trees map safe mkString ", "
582
 
 
583
 
    private def safe(name: Name): String = name.decode
584
 
    private def safe(tree: Tree): String = tree match {
585
 
      case Apply(fn, args)        => "%s(%s)".format(safe(fn), params(args))
586
 
      case Select(qual, name)     => safe(qual) + "." + safe(name)
587
 
      case This(qual)             => safe(qual) + ".this"
588
 
      case Ident(name)            => safe(name)
589
 
      case Literal(value)         => value.stringValue
590
 
      case _                      => "(?: %s)".format(default(tree))
591
 
    }
592
 
 
593
 
    override def printRaw(tree: Tree) { print(safe(tree)) }
594
 
  }
595
 
 
596
 
  class TreeMatchTemplate {
597
 
    // non-trees defined in Trees
598
 
    //
599
 
    // case class ImportSelector(name: Name, namePos: Int, rename: Name, renamePos: Int)
600
 
    // case class Modifiers(flags: Long, privateWithin: Name, annotations: List[Tree], positions: Map[Long, Position])
601
 
    //
602
 
    def apply(t: Tree): Unit = t match {
603
 
      // eliminated by typer
604
 
      case Annotated(annot, arg)  =>
605
 
      case AssignOrNamedArg(lhs, rhs) =>
606
 
      case DocDef(comment, definition) =>
607
 
      case Import(expr, selectors) =>
608
 
 
609
 
      // eliminated by refchecks
610
 
      case ModuleDef(mods, name, impl) =>
611
 
      case TypeTreeWithDeferredRefCheck() =>
612
 
 
613
 
      // eliminated by erasure
614
 
      case TypeDef(mods, name, tparams, rhs) =>
615
 
      case Typed(expr, tpt) =>
616
 
 
617
 
      // eliminated by cleanup
618
 
      case ApplyDynamic(qual, args) =>
619
 
 
620
 
      // eliminated by explicitouter
621
 
      case Alternative(trees) =>
622
 
      case Bind(name, body) =>
623
 
      case CaseDef(pat, guard, body) =>
624
 
      case Star(elem) =>
625
 
      case UnApply(fun, args) =>
626
 
 
627
 
      // eliminated by lambdalift
628
 
      case Function(vparams, body) =>
629
 
 
630
 
      // eliminated by uncurry
631
 
      case AppliedTypeTree(tpt, args) =>
632
 
      case CompoundTypeTree(templ) =>
633
 
      case ExistentialTypeTree(tpt, whereClauses) =>
634
 
      case SelectFromTypeTree(qual, selector) =>
635
 
      case SingletonTypeTree(ref) =>
636
 
      case TypeBoundsTree(lo, hi) =>
637
 
 
638
 
      // survivors
639
 
      case Apply(fun, args) =>
640
 
      case ArrayValue(elemtpt, trees) =>
641
 
      case Assign(lhs, rhs) =>
642
 
      case Block(stats, expr) =>
643
 
      case ClassDef(mods, name, tparams, impl) =>
644
 
      case DefDef(mods, name, tparams, vparamss, tpt, rhs)  =>
645
 
      case EmptyTree =>
646
 
      case Ident(name) =>
647
 
      case If(cond, thenp, elsep) =>
648
 
      case LabelDef(name, params, rhs) =>
649
 
      case Literal(value) =>
650
 
      case Match(selector, cases) =>
651
 
      case New(tpt) =>
652
 
      case PackageDef(pid, stats) =>
653
 
      case Return(expr) =>
654
 
      case Select(qualifier, selector) =>
655
 
      case Super(qual, mix) =>
656
 
      case Template(parents, self, body) =>
657
 
      case This(qual) =>
658
 
      case Throw(expr) =>
659
 
      case Try(block, catches, finalizer) =>
660
 
      case TypeApply(fun, args) =>
661
 
      case TypeTree() =>
662
 
      case ValDef(mods, name, tpt, rhs) =>
663
 
 
664
 
      // missing from the Trees comment
665
 
      case Parens(args) =>                          // only used during parsing
666
 
      case SelectFromArray(qual, name, erasure) =>  // only used during erasure
667
 
    }
668
 
  }
669
 
 
670
 
  private def asStringInternal(t: Tree, f: PrintWriter => TreePrinter): String = {
671
 
    val buffer = new StringWriter()
672
 
    val printer = f(new PrintWriter(buffer))
673
 
    printer.print(t)
674
 
    printer.flush()
675
 
    buffer.toString
676
 
  }
677
 
  def asString(t: Tree): String = asStringInternal(t, newStandardTreePrinter)
678
 
  def asCompactString(t: Tree): String = asStringInternal(t, newCompactTreePrinter)
679
 
 
680
 
  def newStandardTreePrinter(writer: PrintWriter): TreePrinter = new TreePrinter(writer)
681
 
  def newStandardTreePrinter(stream: OutputStream): TreePrinter = newStandardTreePrinter(new PrintWriter(stream))
682
 
  def newStandardTreePrinter(): TreePrinter = newStandardTreePrinter(new PrintWriter(ConsoleWriter))
683
 
 
684
 
  def newCompactTreePrinter(writer: PrintWriter): CompactTreePrinter = new CompactTreePrinter(writer)
685
 
  def newCompactTreePrinter(stream: OutputStream): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(stream))
686
 
  def newCompactTreePrinter(): CompactTreePrinter = newCompactTreePrinter(new PrintWriter(ConsoleWriter))
687
 
 
688
 
  def newTreePrinter(writer: PrintWriter): TreePrinter =
689
 
    if (settings.Ycompacttrees.value) newCompactTreePrinter(writer)
690
 
    else newStandardTreePrinter(writer)
691
 
  def newTreePrinter(stream: OutputStream): TreePrinter = newTreePrinter(new PrintWriter(stream))
692
 
  def newTreePrinter(): TreePrinter = newTreePrinter(new PrintWriter(ConsoleWriter))
693
 
 
694
 
  /** A writer that writes to the current Console and
695
 
   * is sensitive to replacement of the Console's
696
 
   * output stream.
697
 
   */
698
 
  object ConsoleWriter extends Writer {
699
 
    override def write(str: String) { Console.print(str) }
700
 
 
701
 
    def write(cbuf: Array[Char], off: Int, len: Int) {
702
 
      write(new String(cbuf, off, len))
703
 
    }
704
 
 
705
 
    def close = { /* do nothing */ }
706
 
    def flush = { /* do nothing */ }
707
 
  }
708
 
}