@@ -484,46 +484,60 @@ class Namer { typer: Typer =>
484
484
/** Create top-level symbols for statements and enter them into symbol table */
485
485
def index (stats : List [Tree ])(implicit ctx : Context ): Context = {
486
486
487
- val classDef = mutable.Map [TypeName , TypeDef ]()
488
- val moduleDef = mutable.Map [TypeName , TypeDef ]()
487
+ // module name -> (tree, module class) (in the expanded tree of which the module appear)
488
+ val moduleDef = mutable.Map [TypeName , (Tree , TypeDef )]()
489
+ val moduleValDef = mutable.Set [TermName ]()
490
+
491
+ /** Remove the subtree `tree` from the expanded tree of `mdef` */
492
+ def removeInExpanded (mdef : Tree , tree : Tree ): Unit = {
493
+ val Thicket (trees) = expanded(mdef)
494
+ mdef.putAttachment(ExpandedTree , Thicket (trees.filter(_ != tree)))
495
+ }
496
+
497
+ /** Merge the module class `modCls` in the expanded tree of `mdef` with the given stats */
498
+ def mergeModuleClass (mdef : Tree , modCls : TypeDef , stats : List [Tree ]): Unit = {
499
+ val Thicket (trees) = expanded(mdef)
500
+ val merged = trees.map { tree =>
501
+ if (tree == modCls) {
502
+ val impl = modCls.rhs.asInstanceOf [Template ]
503
+ cpy.TypeDef (modCls)(rhs = cpy.Template (impl)(body = stats ++ impl.body))
504
+ }
505
+ else tree
506
+ }
507
+
508
+ mdef.putAttachment(ExpandedTree , Thicket (merged))
509
+ }
489
510
490
511
/** Merge the definitions of a synthetic companion generated by a case class
491
512
* and the real companion, if both exist.
492
513
*/
493
514
def mergeCompanionDefs () = {
494
- for (cdef @ TypeDef (name, _) <- stats)
495
- if (cdef.isClassDef) {
496
- classDef(name) = cdef
497
- cdef.attachmentOrElse(ExpandedTree , cdef) match {
498
- case Thicket (cls :: mval :: (mcls @ TypeDef (mname, _ : Template )) :: crest)
499
- if name.moduleClassName == mname =>
500
- moduleDef(name) = mcls
501
- case _ =>
502
- }
503
- }
504
- for (mdef @ ModuleDef (name, _) <- stats if ! mdef.mods.is(Flags .Package )) {
505
- val typName = name.toTypeName
506
- // Expansion of object is a flattened thicket with the first two elements being:
507
- // module val :: module class :: rest
508
- val Thicket (vdef :: (mcls @ TypeDef (_, impl : Template )) :: rest) = expanded(mdef)
509
- moduleDef(typName) = mcls
510
- classDef get name.toTypeName match {
511
- case Some (cdef) =>
512
- cdef.attachmentOrElse(ExpandedTree , cdef) match {
513
- case Thicket (cls :: mval :: TypeDef (mname, compimpl : Template ) :: crest)
514
- if name.moduleClassName == mname =>
515
- val mcls1 = cpy.TypeDef (mcls)(
516
- rhs = cpy.Template (impl)(body = compimpl.body ++ impl.body))
517
- mdef.putAttachment(ExpandedTree , Thicket (vdef :: mcls1 :: rest))
518
- moduleDef(typName) = mcls1
519
- cdef.putAttachment(ExpandedTree , Thicket (cls :: crest))
515
+ def valid (mdef : MemberDef ): Boolean = ! mdef.mods.is(Flags .Package ) && mdef.mods.is(Flags .Module )
516
+
517
+ for (stat <- stats)
518
+ expanded(stat) match {
519
+ case Thicket (trees) => // companion object always expands to thickets
520
+ trees.map {
521
+ case mcls @ TypeDef (name, impl : Template ) if valid(mcls) =>
522
+ if (moduleDef.contains(name)) {
523
+ val (stat1, modCls) = moduleDef(name)
524
+ removeInExpanded(stat, mcls)
525
+ mergeModuleClass(stat1, modCls, impl.body)
526
+ }
527
+ else moduleDef(name) = (stat, mcls)
528
+
529
+ case vdef @ ValDef (name, _, _) if valid(vdef) =>
530
+ if (moduleValDef.contains(name)) removeInExpanded(stat, vdef)
531
+ else moduleValDef += name
532
+
520
533
case _ =>
521
534
}
522
- case none =>
535
+ case _ =>
536
+
523
537
}
524
- }
525
538
}
526
539
540
+ /** Create links between companion object and companion class */
527
541
def createLinks (classTree : TypeDef , moduleTree : TypeDef )(implicit ctx : Context ) = {
528
542
val claz = ctx.denotNamed(classTree.name.encode).symbol
529
543
val modl = ctx.denotNamed(moduleTree.name.encode).symbol
@@ -532,8 +546,29 @@ class Namer { typer: Typer =>
532
546
}
533
547
534
548
def createCompanionLinks (implicit ctx : Context ): Unit = {
549
+ val classDef = mutable.Map [TypeName , TypeDef ]()
550
+ val moduleDef = mutable.Map [TypeName , TypeDef ]()
551
+
552
+ def updateCache (cdef : TypeDef ): Unit = {
553
+ if (! cdef.isClassDef || cdef.mods.is(Flags .Package )) return
554
+
555
+ if (cdef.mods.is(Flags .ModuleClass )) moduleDef(cdef.name) = cdef
556
+ else classDef(cdef.name) = cdef
557
+ }
558
+
559
+ for (stat <- stats)
560
+ expanded(stat) match {
561
+ case cdef : TypeDef => updateCache(cdef)
562
+ case Thicket (trees) =>
563
+ trees.map {
564
+ case cdef : TypeDef => updateCache(cdef)
565
+ case _ =>
566
+ }
567
+ case _ =>
568
+ }
569
+
535
570
for (cdef @ TypeDef (name, _) <- classDef.values) {
536
- moduleDef.getOrElse(name, EmptyTree ) match {
571
+ moduleDef.getOrElse(name.moduleClassName , EmptyTree ) match {
537
572
case t : TypeDef =>
538
573
createLinks(cdef, t)
539
574
case EmptyTree =>
0 commit comments