diff options
author | Martin Odersky <odersky@gmail.com> | 2014-02-07 13:19:58 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-02-07 13:19:58 +0100 |
commit | 5bed5bdd1bb377e9a177a2be635b391bfc0f168e (patch) | |
tree | 155c964126b4b74aa5e0c61d4f9997c2efedbf76 /src/dotty/tools/dotc/core/SymDenotations.scala | |
parent | 5f5a01c4f74a40eb6d387b83302da2d3c413969b (diff) | |
download | dotty-5bed5bdd1bb377e9a177a2be635b391bfc0f168e.tar.gz dotty-5bed5bdd1bb377e9a177a2be635b391bfc0f168e.tar.bz2 dotty-5bed5bdd1bb377e9a177a2be635b391bfc0f168e.zip |
Replace open package module logic by special member lookups in a package class.
Rather than fiddling with scopes, which can lead to race conditions, we now special case member lookup and mamber name filters in ClassDenotations that represent packages.
Diffstat (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 5278a08d2..7b9d4cd48 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -29,7 +29,9 @@ trait SymDenotations { this: Context => initInfo: Type, initPrivateWithin: Symbol = NoSymbol)(implicit ctx: Context): SymDenotation = { val result = - if (symbol.isClass) new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) + if (symbol.isClass) + if (initFlags is Package) new PackageClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) + else new ClassDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) else new SymDenotation(symbol, owner, name, initFlags, initInfo, initPrivateWithin) result.validFor = stablePeriod result @@ -983,7 +985,7 @@ object SymDenotations { } else computeNPMembersNamed(name) } - private def computeNPMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = /*>|>*/ Stats.track("computeNPMembersNamed") /*<|<*/ { + private[core] def computeNPMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = /*>|>*/ Stats.track("computeNPMembersNamed") /*<|<*/ { if (!classSymbol.hasChildren || !Config.useFingerPrints || (memberFingerPrint contains name)) { @@ -1124,6 +1126,51 @@ object SymDenotations { } } + /** The denotation of a package class. + * It overrides ClassDenotation to take account of package objects when looking for members + */ + class PackageClassDenotation private[SymDenotations] ( + symbol: Symbol, + ownerIfExists: Symbol, + name: Name, + initFlags: FlagSet, + initInfo: Type, + initPrivateWithin: Symbol = NoSymbol) + extends ClassDenotation(symbol, ownerIfExists, name, initFlags, initInfo, initPrivateWithin) { + + private[this] var packageObjCache: SymDenotation = _ + private[this] var packageObjRunId: RunId = NoRunId + + /** The package object in this class, of one exists */ + def packageObj(implicit ctx: Context): SymDenotation = { + if (packageObjRunId != ctx.runId) { + packageObjRunId = ctx.runId + packageObjCache = NoDenotation // break cycle in case we are looking for package object itself + packageObjCache = findMember(nme.PACKAGE, thisType, EmptyFlags).asSymDenotation + } + packageObjCache + } + + /** Look first for members in package; if none are found look in package object */ + override def computeNPMembersNamed(name: Name)(implicit ctx: Context): PreDenotation = { + val denots = super.computeNPMembersNamed(name) + if (denots.exists) denots + else packageObj.moduleClass.denot match { + case pcls: ClassDenotation => pcls.computeNPMembersNamed(name) + case _ => denots + } + } + + /** The union of the member names of the package and the package object */ + override def memberNames(keepOnly: NameFilter)(implicit ctx: Context): Set[Name] = { + val ownNames = super.memberNames(keepOnly) + packageObj.moduleClass.denot match { + case pcls: ClassDenotation => ownNames union pcls.memberNames(keepOnly) + case _ => ownNames + } + } + } + object NoDenotation extends SymDenotation( NoSymbol, NoSymbol, "<none>".toTermName, Permanent, NoType) { override def exists = false |