summaryrefslogtreecommitdiff
path: root/src/library/scala/reflect/api/Trees.scala
blob: 2d130daa4ef4f8d8bfd9727660894a9d45313eb1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
/* NSC -- new Scala compiler
 * Copyright 2005-2011 LAMP/EPFL
 * @author  Martin Odersky
 */
package scala.reflect
package api

// Syncnote: Trees are currently not thread-safe.
trait Trees extends base.Trees { self: Universe =>

  override type Tree >: Null <: TreeApi

  /** ... */
  trait TreeApi extends TreeBase { this: Tree =>

    /** ... */
    def pos: Position

    /** ... */
    def tpe: Type

    /** Note that symbol is fixed as null at this level.  In SymTrees,
     *  it is overridden and implemented with a var, initialized to NoSymbol.
     *
     *  Trees which are not SymTrees but which carry symbols do so by
     *  overriding `def symbol` to forward it elsewhere.  Examples:
     *
     *    Super(qual, _)              // has qual's symbol
     *    Apply(fun, args)            // has fun's symbol
     *    TypeApply(fun, args)        // has fun's symbol
     *    AppliedTypeTree(tpt, args)  // has tpt's symbol
     *    TypeTree(tpe)               // has tpe's typeSymbol, if tpe != null
     *
     *  Attempting to set the symbol of a Tree which does not support
     *  it will induce an exception.
     */
    def symbol: Symbol

    /** ... */
    def hasSymbol: Boolean

    /** Provides an alternate if tree is empty
     *  @param  alt  The alternate tree
     *  @return If this tree is non empty, this tree, otherwise `alt`.
     */
    def orElse(alt: => Tree): Tree

    /** Apply `f` to each subtree */
    def foreach(f: Tree => Unit): Unit

    /** Find all subtrees matching predicate `p`. Same as `filter` */
    def withFilter(f: Tree => Boolean): List[Tree]

    /** Find all subtrees matching predicate `p`. Same as `withFilter` */
    def filter(f: Tree => Boolean): List[Tree]

    /** Apply `pf' to each subtree on which the function is defined and collect the results.
     */
    def collect[T](pf: PartialFunction[Tree, T]): List[T]

    /** Returns optionally first tree (in a preorder traversal) which satisfies predicate `p`,
     *  or None if none exists.
     */
    def find(p: Tree => Boolean): Option[Tree]

    /** Is there exists a part of this tree which satisfies predicate `p`? */
    def exists(p: Tree => Boolean): Boolean

    /** Do all parts of this tree satisfy predicate `p`? */
    def forAll(p: Tree => Boolean): Boolean

    /** Tests whether two trees are structurall equal.
     *  Note that `==` on trees is reference equality.
     */
    def equalsStructure(that : Tree): Boolean

    /** The direct child trees of this tree.
     *  EmptyTrees are always omitted.  Lists are flattened.
     */
    def children: List[Tree]

    /** Extracts free term symbols from a tree that is reified or contains reified subtrees.
     */
    def freeTerms: List[FreeTermSymbol]

    /** Extracts free type symbols from a tree that is reified or contains reified subtrees.
     */
    def freeTypes: List[FreeTypeSymbol]

    /** Substitute symbols in `to` for corresponding occurrences of references to
     *  symbols `from` in this type.
     */
    def substituteSymbols(from: List[Symbol], to: List[Symbol]): Tree

    /** Substitute types in `to` for corresponding occurrences of references to
     *  symbols `from` in this tree.
     */
    def substituteTypes(from: List[Symbol], to: List[Type]): Tree

    /** Substitute given tree `to` for occurrences of nodes that represent
     *  `C.this`, where `C` referes to the given class `clazz`.
     */
    def substituteThis(clazz: Symbol, to: Tree): Tree

    /** Make a copy of this tree, keeping all attributes,
     *  except that all positions are focused (so nothing
     *  in this tree will be found when searching by position).
     */
    def duplicate: this.type
  }

  override type TermTree >: Null <: Tree with TermTreeApi

  /** The API that all term trees support */
  trait TermTreeApi extends TreeApi { this: TermTree =>
  }

  override type TypTree >: Null <: Tree with TypTreeApi

  /** The API that all typ trees support */
  trait TypTreeApi extends TreeApi { this: TypTree =>
  }

  override type SymTree >: Null <: Tree with SymTreeApi

  /** The API that all sym trees support */
  trait SymTreeApi extends TreeApi { this: SymTree =>
    def symbol: Symbol
  }

  override type NameTree >: Null <: Tree with NameTreeApi

  /** The API that all name trees support */
  trait NameTreeApi extends TreeApi { this: NameTree =>
    def name: Name
  }

  override type RefTree >: Null <: SymTree with NameTree with RefTreeApi

  /** The API that all ref trees support */
  trait RefTreeApi extends SymTreeApi with NameTreeApi { this: RefTree =>
    def qualifier: Tree    // empty for Idents
    def name: Name
  }

  override type DefTree >: Null <: SymTree with NameTree with DefTreeApi

  /** The API that all def trees support */
  trait DefTreeApi extends SymTreeApi with NameTreeApi { this: DefTree =>
    def name: Name
  }

  override type MemberDef >: Null <: DefTree with MemberDefApi

  /** The API that all member defs support */
  trait MemberDefApi extends DefTreeApi { this: MemberDef =>
    def mods: Modifiers
  }

  override type PackageDef >: Null <: MemberDef with PackageDefApi

  /** The API that all package defs support */
  trait PackageDefApi extends MemberDefApi { this: PackageDef =>
    val pid: RefTree
    val stats: List[Tree]
  }

  override type ImplDef >: Null <: MemberDef with ImplDefApi

  /** The API that all impl defs support */
  trait ImplDefApi extends MemberDefApi { this: ImplDef =>
    val impl: Template
  }

  override type ClassDef >: Null <: ImplDef with ClassDefApi

  /** The API that all class defs support */
  trait ClassDefApi extends ImplDefApi { this: ClassDef =>
    val mods: Modifiers
    val name: TypeName
    val tparams: List[TypeDef]
    val impl: Template
  }

  override type ModuleDef >: Null <: ImplDef with ModuleDefApi

  /** The API that all module defs support */
  trait ModuleDefApi extends ImplDefApi { this: ModuleDef =>
    val mods: Modifiers
    val name: TermName
    val impl: Template
  }

  override type ValOrDefDef >: Null <: MemberDef with ValOrDefDefApi

  /** The API that all val defs and def defs support */
  trait ValOrDefDefApi extends MemberDefApi { this: ValOrDefDef =>
    def name: Name // can't be a TermName because macros can be type names.
    def tpt: Tree
    def rhs: Tree
  }

  override type ValDef >: Null <: ValOrDefDef with ValDefApi

  /** The API that all val defs support */
  trait ValDefApi extends ValOrDefDefApi { this: ValDef =>
    val mods: Modifiers
    val name: TermName
    val tpt: Tree
    val rhs: Tree
  }

  override type DefDef >: Null <: ValOrDefDef with DefDefApi

  /** The API that all def defs support */
  trait DefDefApi extends ValOrDefDefApi { this: DefDef =>
    val mods: Modifiers
    val name: Name
    val tparams: List[TypeDef]
    val vparamss: List[List[ValDef]]
    val tpt: Tree
    val rhs: Tree
  }

  override type TypeDef >: Null <: MemberDef with TypeDefApi

  /** The API that all type defs support */
  trait TypeDefApi extends MemberDefApi { this: TypeDef =>
    val mods: Modifiers
    val name: TypeName
    val tparams: List[TypeDef]
    val rhs: Tree
  }

  override type LabelDef >: Null <: DefTree with TermTree with LabelDefApi

  /** The API that all label defs support */
  trait LabelDefApi extends DefTreeApi with TermTreeApi { this: LabelDef =>
    val name: TermName
    val params: List[Ident]
    val rhs: Tree
  }

  override type ImportSelector >: Null <: ImportSelectorApi

  /** The API that all import selectors support */
  trait ImportSelectorApi { this: ImportSelector =>
    val name: Name
    val namePos: Int
    val rename: Name
    val renamePos: Int
  }

  override type Import >: Null <: SymTree with ImportApi

  /** The API that all imports support */
  trait ImportApi extends SymTreeApi { this: Import =>
    val expr: Tree
    val selectors: List[ImportSelector]
  }

  override type Template >: Null <: SymTree with TemplateApi

  /** The API that all templates support */
  trait TemplateApi extends SymTreeApi { this: Template =>
    val parents: List[Tree]
    val self: ValDef
    val body: List[Tree]
  }

  override type Block >: Null <: TermTree with BlockApi

  /** The API that all blocks support */
  trait BlockApi extends TermTreeApi { this: Block =>
    val stats: List[Tree]
    val expr: Tree
  }

  override type CaseDef >: Null <: Tree with CaseDefApi

  /** The API that all case defs support */
  trait CaseDefApi extends TreeApi { this: CaseDef =>
    val pat: Tree
    val guard: Tree
    val body: Tree
  }

  override type Alternative >: Null <: TermTree with AlternativeApi

  /** The API that all alternatives support */
  trait AlternativeApi extends TermTreeApi { this: Alternative =>
    val trees: List[Tree]
  }

  override type Star >: Null <: TermTree with StarApi

  /** The API that all stars support */
  trait StarApi extends TermTreeApi { this: Star =>
    val elem: Tree
  }

  override type Bind >: Null <: DefTree with BindApi

  /** The API that all binds support */
  trait BindApi extends DefTreeApi { this: Bind =>
    val name: Name
    val body: Tree
  }

  override type UnApply >: Null <: TermTree with UnApplyApi

  /** The API that all unapplies support */
  trait UnApplyApi extends TermTreeApi { this: UnApply =>
    val fun: Tree
    val args: List[Tree]
  }

  override type ArrayValue >: Null <: TermTree with ArrayValueApi

  /** The API that all array values support */
  trait ArrayValueApi extends TermTreeApi { this: ArrayValue =>
    val elemtpt: Tree
    val elems: List[Tree]
  }

  override type Function >: Null <: TermTree with SymTree with FunctionApi

  /** The API that all functions support */
  trait FunctionApi extends TermTreeApi with SymTreeApi { this: Function =>
    val vparams: List[ValDef]
    val body: Tree
  }

  override type Assign >: Null <: TermTree with AssignApi

  /** The API that all assigns support */
  trait AssignApi extends TermTreeApi { this: Assign =>
    val lhs: Tree
    val rhs: Tree
  }

  override type AssignOrNamedArg >: Null <: TermTree with AssignOrNamedArgApi

  /** The API that all assigns support */
  trait AssignOrNamedArgApi extends TermTreeApi { this: AssignOrNamedArg =>
    val lhs: Tree
    val rhs: Tree
  }

  override type If >: Null <: TermTree with IfApi

  /** The API that all ifs support */
  trait IfApi extends TermTreeApi { this: If =>
    val cond: Tree
    val thenp: Tree
    val elsep: Tree
  }

  override type Match >: Null <: TermTree with MatchApi

  /** The API that all matches support */
  trait MatchApi extends TermTreeApi { this: Match =>
    val selector: Tree
    val cases: List[CaseDef]
  }

  override type Return >: Null <: TermTree with SymTree with ReturnApi

  /** The API that all returns support */
  trait ReturnApi extends TermTreeApi { this: Return =>
    val expr: Tree
  }

  override type Try >: Null <: TermTree with TryApi

  /** The API that all tries support */
  trait TryApi extends TermTreeApi { this: Try =>
    val block: Tree
    val catches: List[CaseDef]
    val finalizer: Tree
  }

  override type Throw >: Null <: TermTree with ThrowApi

  /** The API that all tries support */
  trait ThrowApi extends TermTreeApi { this: Throw =>
    val expr: Tree
  }

  override type New >: Null <: TermTree with NewApi

  /** The API that all news support */
  trait NewApi extends TermTreeApi { this: New =>
    val tpt: Tree
  }

  override type Typed >: Null <: TermTree with TypedApi

  /** The API that all typeds support */
  trait TypedApi extends TermTreeApi { this: Typed =>
    val expr: Tree
    val tpt: Tree
  }

  override type GenericApply >: Null <: TermTree with GenericApplyApi

  /** The API that all applies support */
  trait GenericApplyApi extends TermTreeApi { this: GenericApply =>
    val fun: Tree
    val args: List[Tree]
  }

  override type TypeApply >: Null <: GenericApply with TypeApplyApi

  /** The API that all type applies support */
  trait TypeApplyApi extends GenericApplyApi { this: TypeApply =>
  }

  override type Apply >: Null <: GenericApply with ApplyApi

  /** The API that all applies support */
  trait ApplyApi extends GenericApplyApi { this: Apply =>
  }

  override type ApplyDynamic >: Null <: TermTree with SymTree with ApplyDynamicApi

  /** The API that all apply dynamics support */
  trait ApplyDynamicApi extends TermTreeApi with SymTreeApi { this: ApplyDynamic =>
    val qual: Tree
    val args: List[Tree]
  }

  override type Super >: Null <: TermTree with SuperApi

  /** The API that all supers support */
  trait SuperApi extends TermTreeApi { this: Super =>
    val qual: Tree
    val mix: TypeName
  }

  override type This >: Null <: TermTree with SymTree with ThisApi

  /** The API that all thises support */
  trait ThisApi extends TermTreeApi with SymTreeApi { this: This =>
    val qual: TypeName
  }

  override type Select >: Null <: RefTree with SelectApi

  /** The API that all selects support */
  trait SelectApi extends RefTreeApi { this: Select =>
    val qualifier: Tree
    val name: Name
  }

  override type Ident >: Null <: RefTree with IdentApi

  /** The API that all idents support */
  trait IdentApi extends RefTreeApi { this: Ident =>
    val name: Name
  }

  override type ReferenceToBoxed >: Null <: TermTree with ReferenceToBoxedApi

  /** The API that all references support */
  trait ReferenceToBoxedApi extends TermTreeApi { this: ReferenceToBoxed =>
    val ident: Tree
  }

  override type Literal >: Null <: TermTree with LiteralApi

  /** The API that all literals support */
  trait LiteralApi extends TermTreeApi { this: Literal =>
    val value: Constant
  }

  override type Annotated >: Null <: Tree with AnnotatedApi

  /** The API that all annotateds support */
  trait AnnotatedApi extends TreeApi { this: Annotated =>
    val annot: Tree
    val arg: Tree
  }

  override type SingletonTypeTree >: Null <: TypTree with SingletonTypeTreeApi

  /** The API that all singleton type trees support */
  trait SingletonTypeTreeApi extends TypTreeApi { this: SingletonTypeTree =>
    val ref: Tree
  }

  override type SelectFromTypeTree >: Null <: TypTree with RefTree with SelectFromTypeTreeApi

  /** The API that all selects from type trees support */
  trait SelectFromTypeTreeApi extends TypTreeApi with RefTreeApi { this: SelectFromTypeTree =>
    val qualifier: Tree
    val name: TypeName
  }

  override type CompoundTypeTree >: Null <: TypTree with CompoundTypeTreeApi

  /** The API that all compound type trees support */
  trait CompoundTypeTreeApi extends TypTreeApi { this: CompoundTypeTree =>
    val templ: Template
  }

  override type AppliedTypeTree >: Null <: TypTree with AppliedTypeTreeApi

  /** The API that all applied type trees support */
  trait AppliedTypeTreeApi extends TypTreeApi { this: AppliedTypeTree =>
    val tpt: Tree
    val args: List[Tree]
  }

  override type TypeBoundsTree >: Null <: TypTree with TypeBoundsTreeApi

  /** The API that all type bound trees support */
  trait TypeBoundsTreeApi extends TypTreeApi { this: TypeBoundsTree =>
    val lo: Tree
    val hi: Tree
  }

  override type ExistentialTypeTree >: Null <: TypTree with ExistentialTypeTreeApi

  /** The API that all existential type trees support */
  trait ExistentialTypeTreeApi extends TypTreeApi { this: ExistentialTypeTree =>
    val tpt: Tree
    val whereClauses: List[Tree]
  }

  override type TypeTree >: Null <: TypTree with TypeTreeApi

  /** The API that all type trees support */
  trait TypeTreeApi extends TypTreeApi { this: TypeTree =>
    def original: Tree
  }

  /** An empty deferred value definition corresponding to:
   *    val _: _
   *  This is used as a placeholder in the `self` parameter Template if there is
   *  no definition of a self value of self type.
   */
  val emptyValDef: ValDef

// ---------------------- copying ------------------------------------------------

  /** The standard (lazy) tree copier
   */
  type TreeCopier <: TreeCopierOps
  val treeCopy: TreeCopier = newLazyTreeCopier

  def newStrictTreeCopier: TreeCopier
  def newLazyTreeCopier: TreeCopier

  /** The API of a tree copier
   *  tree copiers are made available by an implicit conversion in reflect.ops
   */
  abstract class TreeCopierOps {
    def ClassDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], impl: Template): ClassDef
    def PackageDef(tree: Tree, pid: RefTree, stats: List[Tree]): PackageDef
    def ModuleDef(tree: Tree, mods: Modifiers, name: Name, impl: Template): ModuleDef
    def ValDef(tree: Tree, mods: Modifiers, name: Name, tpt: Tree, rhs: Tree): ValDef
    def DefDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], vparamss: List[List[ValDef]], tpt: Tree, rhs: Tree): DefDef
    def TypeDef(tree: Tree, mods: Modifiers, name: Name, tparams: List[TypeDef], rhs: Tree): TypeDef
    def LabelDef(tree: Tree, name: Name, params: List[Ident], rhs: Tree): LabelDef
    def Import(tree: Tree, expr: Tree, selectors: List[ImportSelector]): Import
    def Template(tree: Tree, parents: List[Tree], self: ValDef, body: List[Tree]): Template
    def Block(tree: Tree, stats: List[Tree], expr: Tree): Block
    def CaseDef(tree: Tree, pat: Tree, guard: Tree, body: Tree): CaseDef
    def Alternative(tree: Tree, trees: List[Tree]): Alternative
    def Star(tree: Tree, elem: Tree): Star
    def Bind(tree: Tree, name: Name, body: Tree): Bind
    def UnApply(tree: Tree, fun: Tree, args: List[Tree]): UnApply
    def ArrayValue(tree: Tree, elemtpt: Tree, trees: List[Tree]): ArrayValue
    def Function(tree: Tree, vparams: List[ValDef], body: Tree): Function
    def Assign(tree: Tree, lhs: Tree, rhs: Tree): Assign
    def AssignOrNamedArg(tree: Tree, lhs: Tree, rhs: Tree): AssignOrNamedArg
    def If(tree: Tree, cond: Tree, thenp: Tree, elsep: Tree): If
    def Match(tree: Tree, selector: Tree, cases: List[CaseDef]): Match
    def Return(tree: Tree, expr: Tree): Return
    def Try(tree: Tree, block: Tree, catches: List[CaseDef], finalizer: Tree): Try
    def Throw(tree: Tree, expr: Tree): Throw
    def New(tree: Tree, tpt: Tree): New
    def Typed(tree: Tree, expr: Tree, tpt: Tree): Typed
    def TypeApply(tree: Tree, fun: Tree, args: List[Tree]): TypeApply
    def Apply(tree: Tree, fun: Tree, args: List[Tree]): Apply
    def ApplyDynamic(tree: Tree, qual: Tree, args: List[Tree]): ApplyDynamic
    def Super(tree: Tree, qual: Tree, mix: TypeName): Super
    def This(tree: Tree, qual: Name): This
    def Select(tree: Tree, qualifier: Tree, selector: Name): Select
    def Ident(tree: Tree, name: Name): Ident
    def ReferenceToBoxed(tree: Tree, idt: Ident): ReferenceToBoxed
    def Literal(tree: Tree, value: Constant): Literal
    def TypeTree(tree: Tree): TypeTree
    def Annotated(tree: Tree, annot: Tree, arg: Tree): Annotated
    def SingletonTypeTree(tree: Tree, ref: Tree): SingletonTypeTree
    def SelectFromTypeTree(tree: Tree, qualifier: Tree, selector: Name): SelectFromTypeTree
    def CompoundTypeTree(tree: Tree, templ: Template): CompoundTypeTree
    def AppliedTypeTree(tree: Tree, tpt: Tree, args: List[Tree]): AppliedTypeTree
    def TypeBoundsTree(tree: Tree, lo: Tree, hi: Tree): TypeBoundsTree
    def ExistentialTypeTree(tree: Tree, tpt: Tree, whereClauses: List[Tree]): ExistentialTypeTree
  }

// ---------------------- traversing and transforming ------------------------------

  class Traverser {
    protected[scala] var currentOwner: Symbol = rootMirror.RootClass

    def traverse(tree: Tree): Unit = itraverse(this, tree)

    def traverseTrees(trees: List[Tree]) {
      trees foreach traverse
    }
    def traverseTreess(treess: List[List[Tree]]) {
      treess foreach traverseTrees
    }
    def traverseStats(stats: List[Tree], exprOwner: Symbol) {
      stats foreach (stat =>
        if (exprOwner != currentOwner) atOwner(exprOwner)(traverse(stat))
        else traverse(stat)
      )
    }

    def atOwner(owner: Symbol)(traverse: => Unit) {
      val prevOwner = currentOwner
      currentOwner = owner
      traverse
      currentOwner = prevOwner
    }

    /** Leave apply available in the generic traverser to do something else.
     */
    def apply[T <: Tree](tree: T): T = { traverse(tree); tree }
  }

  protected def itraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree)

  protected def xtraverse(traverser: Traverser, tree: Tree): Unit = throw new MatchError(tree)

  abstract class Transformer {
    val treeCopy: TreeCopier = newLazyTreeCopier
    protected[scala] var currentOwner: Symbol = rootMirror.RootClass
    protected def currentMethod = currentOwner.enclosingMethod
    protected def currentClass = currentOwner.enclosingClass
//    protected def currentPackage = currentOwner.enclosingTopLevelClass.owner
    def transform(tree: Tree): Tree = itransform(this, tree)

    def transformTrees(trees: List[Tree]): List[Tree] =
        trees mapConserve (transform(_))
    def transformTemplate(tree: Template): Template =
      transform(tree: Tree).asInstanceOf[Template]
    def transformTypeDefs(trees: List[TypeDef]): List[TypeDef] =
      trees mapConserve (tree => transform(tree).asInstanceOf[TypeDef])
    def transformValDef(tree: ValDef): ValDef =
      if (tree.isEmpty) tree else transform(tree).asInstanceOf[ValDef]
    def transformValDefs(trees: List[ValDef]): List[ValDef] =
      trees mapConserve (transformValDef(_))
    def transformValDefss(treess: List[List[ValDef]]): List[List[ValDef]] =
      treess mapConserve (transformValDefs(_))
    def transformCaseDefs(trees: List[CaseDef]): List[CaseDef] =
      trees mapConserve (tree => transform(tree).asInstanceOf[CaseDef])
    def transformIdents(trees: List[Ident]): List[Ident] =
      trees mapConserve (tree => transform(tree).asInstanceOf[Ident])
    def transformStats(stats: List[Tree], exprOwner: Symbol): List[Tree] =
      stats mapConserve (stat =>
        if (exprOwner != currentOwner && stat.isTerm) atOwner(exprOwner)(transform(stat))
        else transform(stat)) filter (EmptyTree != _)
    def transformModifiers(mods: Modifiers): Modifiers =
      mods.mapAnnotations(transformTrees)

    def atOwner[A](owner: Symbol)(trans: => A): A = {
      val prevOwner = currentOwner
      currentOwner = owner
      val result = trans
      currentOwner = prevOwner
      result
    }
  }

  protected def itransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree)

  protected def xtransform(transformer: Transformer, tree: Tree): Tree = throw new MatchError(tree)

  type Modifiers >: Null <: ModifiersApi

  abstract class ModifiersApi extends ModifiersBase with HasFlagsApi

}