@@ -484,46 +484,82 @@ 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 -> (stat, moduleCls / moduleVal)
488
+ val moduleClsDef = mutable.Map [TypeName , (Tree , TypeDef )]()
489
+ val moduleValDef = mutable.Map [TermName , (Tree , ValDef )]()
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 ]): TypeDef = {
499
+ var res : TypeDef = null
500
+ val Thicket (trees) = expanded(mdef)
501
+ val merged = trees.map { tree =>
502
+ if (tree == modCls) {
503
+ val impl = modCls.rhs.asInstanceOf [Template ]
504
+ res = cpy.TypeDef (modCls)(rhs = cpy.Template (impl)(body = stats ++ impl.body))
505
+ res
506
+ }
507
+ else tree
508
+ }
509
+
510
+ mdef.putAttachment(ExpandedTree , Thicket (merged))
511
+
512
+ res
513
+ }
489
514
490
515
/** Merge the definitions of a synthetic companion generated by a case class
491
516
* and the real companion, if both exist.
492
517
*/
493
518
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))
519
+ def valid (mdef : MemberDef ): Boolean = ! mdef.mods.is(Package ) && mdef.mods.is(Module )
520
+
521
+ for (stat <- stats)
522
+ expanded(stat) match {
523
+ case Thicket (trees) => // companion object always expands to thickets
524
+ trees.map {
525
+ case mcls @ TypeDef (name, impl : Template ) if valid(mcls) =>
526
+ if (moduleClsDef.contains(name)) {
527
+ val (stat1, mcls1 @ TypeDef (_, impl1 : Template )) = moduleClsDef(name)
528
+ if (mcls.mods.is(Synthetic )) { // merge synthetic into user-defined module
529
+ removeInExpanded(stat, mcls)
530
+ val mcls2 = mergeModuleClass(stat1, mcls1, impl.body)
531
+ moduleClsDef(name) = (stat1, mcls2)
532
+ }
533
+ else {
534
+ assert(mcls1.mods.is(Synthetic ))
535
+ removeInExpanded(stat1, mcls1)
536
+ val mcls2 = mergeModuleClass(stat, mcls, impl1.body)
537
+ moduleClsDef(name) = (stat, mcls2)
538
+ }
539
+ }
540
+ else moduleClsDef(name) = (stat, mcls)
541
+
542
+ case vdef @ ValDef (name, _, _) if valid(vdef) =>
543
+ if (moduleValDef.contains(name)) {
544
+ val (stat1, vdef1) = moduleValDef(name)
545
+ if (vdef.mods.is(Synthetic )) // merge synthetic into user-defined module
546
+ removeInExpanded(stat, vdef)
547
+ else {
548
+ assert(vdef1.mods.is(Synthetic ))
549
+ removeInExpanded(stat1, vdef1)
550
+ moduleValDef(name) = (stat, vdef)
551
+ }
552
+ }
553
+ else moduleValDef(name) = (stat, vdef)
554
+
520
555
case _ =>
521
556
}
522
- case none =>
557
+ case _ =>
558
+
523
559
}
524
- }
525
560
}
526
561
562
+ /** Create links between companion object and companion class */
527
563
def createLinks (classTree : TypeDef , moduleTree : TypeDef )(implicit ctx : Context ) = {
528
564
val claz = ctx.denotNamed(classTree.name.encode).symbol
529
565
val modl = ctx.denotNamed(moduleTree.name.encode).symbol
@@ -532,8 +568,29 @@ class Namer { typer: Typer =>
532
568
}
533
569
534
570
def createCompanionLinks (implicit ctx : Context ): Unit = {
571
+ val classDef = mutable.Map [TypeName , TypeDef ]()
572
+ val moduleDef = mutable.Map [TypeName , TypeDef ]()
573
+
574
+ def updateCache (cdef : TypeDef ): Unit = {
575
+ if (! cdef.isClassDef || cdef.mods.is(Package )) return
576
+
577
+ if (cdef.mods.is(ModuleClass )) moduleDef(cdef.name) = cdef
578
+ else classDef(cdef.name) = cdef
579
+ }
580
+
581
+ for (stat <- stats)
582
+ expanded(stat) match {
583
+ case cdef : TypeDef => updateCache(cdef)
584
+ case Thicket (trees) =>
585
+ trees.map {
586
+ case cdef : TypeDef => updateCache(cdef)
587
+ case _ =>
588
+ }
589
+ case _ =>
590
+ }
591
+
535
592
for (cdef @ TypeDef (name, _) <- classDef.values) {
536
- moduleDef.getOrElse(name, EmptyTree ) match {
593
+ moduleDef.getOrElse(name.moduleClassName , EmptyTree ) match {
537
594
case t : TypeDef =>
538
595
createLinks(cdef, t)
539
596
case EmptyTree =>
0 commit comments