@@ -5,7 +5,7 @@ package core
5
5
import Periods ._ , Contexts ._ , Symbols ._ , Denotations ._ , Names ._ , NameOps ._ , Annotations ._
6
6
import Types ._ , Flags ._ , Decorators ._ , DenotTransformers ._ , StdNames ._ , Scopes ._
7
7
import NameOps ._ , NameKinds ._
8
- import Phases .{Phase , typerPhase , unfusedPhases }
8
+ import Phases .{Phase , typerPhase , flattenPhase , unfusedPhases }
9
9
import Constants .Constant
10
10
import TypeApplications .TypeParamInfo
11
11
import Scopes .Scope
@@ -17,7 +17,7 @@ import Trees.Literal
17
17
import Variances .Variance
18
18
import annotation .tailrec
19
19
import util .SimpleIdentityMap
20
- import util .{SrcPos , SourcePosition , Stats }
20
+ import util .{SrcPos , SourcePosition , SourceFile , NoSource , Stats }
21
21
import util .Spans .*
22
22
import java .util .WeakHashMap
23
23
import scala .util .control .NonFatal
@@ -31,11 +31,37 @@ import scala.annotation.internal.sharable
31
31
32
32
object SymDenotations {
33
33
34
+ type TreeOrProvider = tpd.TreeProvider | tpd.Tree
35
+
36
+ class SymCommon (
37
+ // private[SymDenotations]
38
+ var coord : Coord ,
39
+ // private[SymDenotations]
40
+ val id : Int ,
41
+ // private[SymDenotations]
42
+ val nestingLevel : Int ):
43
+
44
+ // private[SymDenotations]
45
+ var defTree : tpd.Tree | Null = null
46
+ // private[SymDenotations]
47
+ def asClass : ClassCommon = asInstanceOf [ClassCommon ]
48
+ end SymCommon
49
+
50
+ class ClassCommon (coord : Coord , id : Int , nestingLevel : Int ,
51
+ // private[SymDenotations]
52
+ val assocFile : AbstractFile | Null = null )
53
+ extends SymCommon (coord, id, nestingLevel):
54
+ // private[SymDenotations]
55
+ var treeOrProvider : TreeOrProvider = tpd.EmptyTree
56
+ // private[SymDenotations]
57
+ var source : SourceFile = NoSource
58
+
34
59
/** A sym-denotation represents the contents of a definition
35
60
* during a period.
36
61
*/
37
62
class SymDenotation private [SymDenotations ] (
38
63
symbol : Symbol ,
64
+ final val common : SymCommon ,
39
65
final val maybeOwner : Symbol ,
40
66
final val name : Name ,
41
67
initFlags : FlagSet ,
@@ -576,6 +602,55 @@ object SymDenotations {
576
602
577
603
myTargetName.nn
578
604
605
+ // ----- Symbol ops --------------------------------------------
606
+ /*
607
+ def coord: Coord = common.coord
608
+ def id: Int = common.id
609
+ def nestingLevel: Int = common.nestingLevel
610
+
611
+ /** Set the coordinate of this class, this is only useful when the coordinate is
612
+ * not known at symbol creation. This is the case for root symbols
613
+ * unpickled from TASTY.
614
+ *
615
+ * @pre coord == NoCoord
616
+ */
617
+ private[core] def coord_=(c: Coord): Unit =
618
+ // assert(myCoord == NoCoord)
619
+ // This assertion fails for CommentPickling test.
620
+ // TODO: figure out what's wrong in the setup of CommentPicklingTest and re-enable assertion.
621
+ common.coord = c
622
+ */
623
+ /** The source or class file from which this class or
624
+ * the class containing this symbol was generated, null if not applicable.
625
+ * Note that this the returned classfile might be the top-level class
626
+ * containing this symbol instead of the directly enclosing class.
627
+ * Overridden in ClassSymbol
628
+ */
629
+ def associatedFile (using Context ): AbstractFile | Null =
630
+ topLevelClass.associatedFile
631
+ /*
632
+ /** The tree defining the symbol at pickler time, EmptyTree if none was retained
633
+ * Only valid for initial denotations.
634
+ */
635
+ private[core] def defTree: tpd.Tree =
636
+ if common.defTree == null then tpd.EmptyTree else common.defTree.nn
637
+
638
+ /** Set defining tree if this symbol retains its definition tree
639
+ * Only valid for initial denotations.
640
+ */
641
+ private[core] def defTree_=(tree: tpd.Tree)(using Context): Unit =
642
+ if retainsDefTree then common.defTree = tree
643
+
644
+ /** Does this symbol retain its definition tree?
645
+ * A good policy for this needs to balance costs and benefits, where
646
+ * costs are mainly memoty leaks, in particular across runs.
647
+ */
648
+ def retainsDefTree(using Context): Boolean =
649
+ ctx.settings.YretainTrees.value ||
650
+ owner.isTerm || // no risk of leaking memory after a run for these
651
+ isOneOf(InlineOrProxy) || // need to keep inline info
652
+ ctx.settings.YcheckInit.value // initialization check
653
+ */
579
654
// ----- Tests -------------------------------------------------
580
655
581
656
/** Is this denotation a class? */
@@ -1606,7 +1681,7 @@ object SymDenotations {
1606
1681
val privateWithin1 = if (privateWithin != null ) privateWithin else this .privateWithin
1607
1682
val annotations1 = if (annotations != null ) annotations else this .annotations
1608
1683
val rawParamss1 = if rawParamss != null then rawParamss else this .rawParamss
1609
- val d = SymDenotation (symbol, owner, name, initFlags1, info1, privateWithin1)
1684
+ val d = SymDenotation (symbol, symbol.lastKnownDenotation.common, owner, name, initFlags1, info1, privateWithin1)
1610
1685
d.annotations = annotations1
1611
1686
d.rawParamss = rawParamss1
1612
1687
d.registeredCompanion = registeredCompanion
@@ -1777,12 +1852,13 @@ object SymDenotations {
1777
1852
*/
1778
1853
class ClassDenotation private [SymDenotations ] (
1779
1854
symbol : Symbol ,
1855
+ common : ClassCommon ,
1780
1856
maybeOwner : Symbol ,
1781
1857
name : Name ,
1782
1858
initFlags : FlagSet ,
1783
1859
initInfo : Type ,
1784
1860
initPrivateWithin : Symbol )
1785
- extends SymDenotation (symbol, maybeOwner, name, initFlags, initInfo, initPrivateWithin) {
1861
+ extends SymDenotation (symbol, common, maybeOwner, name, initFlags, initInfo, initPrivateWithin) {
1786
1862
1787
1863
import util .EqHashMap
1788
1864
@@ -2422,19 +2498,100 @@ object SymDenotations {
2422
2498
2423
2499
override def registeredCompanion_= (c : Symbol ) =
2424
2500
myCompanion = c
2501
+
2502
+ // ------ Symbol ops --------------------------------------------------------
2503
+
2504
+ // def assocFile: AbstractFile | Null = common.assocFile
2505
+
2506
+ /** The source or class file from which this class was generated, null if not applicable. */
2507
+ override def associatedFile (using Context ): AbstractFile | Null =
2508
+ val af = common.assocFile
2509
+ if af != null || this .is(Package ) || this .owner.is(Package ) then af
2510
+ else super .associatedFile
2511
+
2512
+ /*
2513
+ /** If this is a top-level class and `-Yretain-trees` (or `-from-tasty`) is set.
2514
+ * Returns the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree.
2515
+ * This will force the info of the class.
2516
+ */
2517
+ private[core] def rootTree(using Context): tpd.Tree =
2518
+ rootTreeContaining("")
2519
+
2520
+ /** Same as `tree` but load tree only if `id == ""` or the tree might contain `id`.
2521
+ * For Tasty trees this means consulting whether the name table defines `id`.
2522
+ * For already loaded trees, we maintain the referenced ids in an attachment.
2523
+ */
2524
+ private[core] def rootTreeContaining(id: String)(using Context): tpd.Tree =
2525
+ infoOrCompleter match
2526
+ case _: NoCompleter =>
2527
+ case _ => ensureCompleted()
2528
+ common.treeOrProvider match
2529
+ case fn: tpd.TreeProvider =>
2530
+ if id.isEmpty || fn.mightContain(id) then
2531
+ val tree = fn.tree
2532
+ common.treeOrProvider = tree
2533
+ tree
2534
+ else tpd.EmptyTree
2535
+ case tree: tpd.Tree @ unchecked =>
2536
+ if id.isEmpty || mightContain(tree, id) then tree else tpd.EmptyTree
2537
+
2538
+ private[core] def rootTreeOrProvider: TreeOrProvider = common.treeOrProvider
2539
+
2540
+ private[core] def rootTreeOrProvider_=(t: TreeOrProvider)(using Context): Unit =
2541
+ common.treeOrProvider = t
2542
+
2543
+ private def mightContain(tree: tpd.Tree, id: String)(using Context): Boolean = {
2544
+ val ids = tree.getAttachment(Ids) match {
2545
+ case Some(ids) => ids
2546
+ case None =>
2547
+ import tpd.TreeOps
2548
+ val idSet = mutable.SortedSet[String]()
2549
+ tree.foreachSubTree {
2550
+ case tree: tpd.NameTree if tree.name.toTermName.isInstanceOf[SimpleName] =>
2551
+ idSet += tree.name.toString
2552
+ case _ =>
2553
+ }
2554
+ val ids = idSet.toArray
2555
+ tree.putAttachment(Ids, ids)
2556
+ ids
2557
+ }
2558
+ ids.binarySearch(id) >= 0
2559
+ }
2560
+
2561
+ final def sourceOfClass(using Context): SourceFile = {
2562
+ assert(this eq initial)
2563
+ if !common.source.exists && !is(Package) then
2564
+ // this allows sources to be added in annotations after `sourceOfClass` is first called
2565
+ val file = associatedFile
2566
+ if file != null && file.extension != "class" then
2567
+ common.source = ctx.getSource(file)
2568
+ else
2569
+ common.source = defn.patchSource(symbol)
2570
+ if !common.source.exists then
2571
+ common.source = atPhaseNoLater(flattenPhase) {
2572
+ topLevelClass.unforcedAnnotation(defn.SourceFileAnnot) match
2573
+ case Some(sourceAnnot) => sourceAnnot.argumentConstant(0) match
2574
+ case Some(Constant(path: String)) => ctx.getSource(path)
2575
+ case none => NoSource
2576
+ case none => NoSource
2577
+ }
2578
+ common.source
2579
+ }
2580
+ */
2425
2581
}
2426
2582
2427
2583
/** The denotation of a package class.
2428
2584
* It overrides ClassDenotation to take account of package objects when looking for members
2429
2585
*/
2430
2586
final class PackageClassDenotation private [SymDenotations ] (
2431
2587
symbol : Symbol ,
2588
+ common : ClassCommon ,
2432
2589
ownerIfExists : Symbol ,
2433
2590
name : Name ,
2434
2591
initFlags : FlagSet ,
2435
2592
initInfo : Type ,
2436
2593
initPrivateWithin : Symbol )
2437
- extends ClassDenotation (symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) {
2594
+ extends ClassDenotation (symbol, common, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) {
2438
2595
2439
2596
private var packageObjsCache : List [ClassDenotation ] = _
2440
2597
private var packageObjsRunId : RunId = NoRunId
@@ -2595,7 +2752,7 @@ object SymDenotations {
2595
2752
}
2596
2753
2597
2754
@ sharable object NoDenotation
2598
- extends SymDenotation (NoSymbol , NoSymbol , " <none>" .toTermName, Permanent , NoType ) {
2755
+ extends SymDenotation (NoSymbol , SymCommon ( NoCoord , 0 , 0 ), NoSymbol , " <none>" .toTermName, Permanent , NoType ) {
2599
2756
override def isTerm : Boolean = false
2600
2757
override def exists : Boolean = false
2601
2758
override def owner : Symbol = throw new AssertionError (" NoDenotation.owner" )
@@ -2609,6 +2766,7 @@ object SymDenotations {
2609
2766
override def filterWithPredicate (p : SingleDenotation => Boolean ): SingleDenotation = this
2610
2767
override def filterDisjoint (denots : PreDenotation )(using Context ): SingleDenotation = this
2611
2768
override def filterWithFlags (required : FlagSet , excluded : FlagSet )(using Context ): SingleDenotation = this
2769
+ override def associatedFile (using Context ): AbstractFile | Null = NoSource .file
2612
2770
2613
2771
NoSymbol .denot = this
2614
2772
validFor = Period .allInRun(NoRunId )
@@ -2630,16 +2788,20 @@ object SymDenotations {
2630
2788
*/
2631
2789
def SymDenotation (
2632
2790
symbol : Symbol ,
2791
+ common : SymCommon ,
2633
2792
owner : Symbol ,
2634
2793
name : Name ,
2635
2794
initFlags : FlagSet ,
2636
2795
initInfo : Type ,
2637
2796
initPrivateWithin : Symbol = NoSymbol )(using Context ): SymDenotation = {
2638
2797
val result =
2639
- if (symbol.isClass)
2640
- if (initFlags.is(Package )) new PackageClassDenotation (symbol, owner, name, initFlags, initInfo, initPrivateWithin)
2641
- else new ClassDenotation (symbol, owner, name, initFlags, initInfo, initPrivateWithin)
2642
- else new SymDenotation (symbol, owner, name, initFlags, initInfo, initPrivateWithin)
2798
+ if symbol.isClass then
2799
+ if initFlags.is(Package ) then
2800
+ new PackageClassDenotation (symbol, common.asClass, owner, name, initFlags, initInfo, initPrivateWithin)
2801
+ else
2802
+ new ClassDenotation (symbol, common.asClass, owner, name, initFlags, initInfo, initPrivateWithin)
2803
+ else
2804
+ new SymDenotation (symbol, common, owner, name, initFlags, initInfo, initPrivateWithin)
2643
2805
result.validFor = currentStablePeriod
2644
2806
result
2645
2807
}
0 commit comments