Skip to content

sourcepath: Fix handling of top-level definitions and user-written package objects #7690

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions compiler/src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,26 @@ object desugar {
flatTree(cdef1 :: companions ::: implicitWrappers)
}.reporting(i"desugared: $result", Printers.desugar)

/** Expand
*
* package object name { body }
*
* to:
*
* package name {
* object `package` { body }
* }
*/
def packageModuleDef(mdef: ModuleDef)(implicit ctx: Context): Tree =
val impl = mdef.impl
val mods = mdef.mods
val moduleName = normalizeName(mdef, impl).asTermName
if (mods.is(Package))
PackageDef(Ident(moduleName),
cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil)
else
mdef

/** Expand
*
* object name extends parents { self => body }
Expand Down Expand Up @@ -854,7 +874,7 @@ object desugar {
ctx.warning(em"${hl("final")} modifier is redundant for objects", flagSourcePos(Final))

if (mods.is(Package))
PackageDef(Ident(moduleName), cpy.ModuleDef(mdef)(nme.PACKAGE, impl).withMods(mods &~ Package) :: Nil)
packageModuleDef(mdef)
else if (isEnumCase) {
typeParamIsReferenced(enumClass.typeParams, Nil, Nil, impl.parents)
// used to check there are no illegal references to enum's type parameters in parents
Expand Down Expand Up @@ -1229,12 +1249,6 @@ object desugar {
case _ =>
false

/** Does this package contains at least one top-level definition
* that will require a wrapping object ?
*/
def hasTopLevelDef(pdef: PackageDef)(given Context): Boolean =
pdef.stats.exists(isTopLevelDef)

/** Assuming `src` contains top-level definition, returns the name that should
* be using for the package object that will wrap them.
*/
Expand Down
15 changes: 11 additions & 4 deletions compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import ast.Trees._
import parsing.JavaParsers.OutlineJavaParser
import parsing.Parsers.OutlineParser
import reporting.trace
import ast.desugar.{ packageObjectName, hasTopLevelDef }
import ast.desugar

object SymbolLoaders {
import ast.untpd._
Expand Down Expand Up @@ -135,11 +135,18 @@ object SymbolLoaders {
ok
}

def traverse(tree: Tree, path: List[TermName]): Unit = tree match {
/** Run the subset of desugaring necessary to record the correct symbols */
def simpleDesugar(tree: Tree): Tree = tree match
case tree: PackageDef =>
desugar.packageDef(tree)
case tree: ModuleDef =>
desugar.packageModuleDef(tree)
case _ =>
tree

def traverse(tree: Tree, path: List[TermName]): Unit = simpleDesugar(tree) match {
case tree @ PackageDef(pid, body) =>
val path1 = addPrefix(pid, path)
if hasTopLevelDef(tree) && checkPathMatches(path1, "package", pid)
enterModule(owner, packageObjectName(unit.source), completer, scope = scope)
for (stat <- body) traverse(stat, path1)
case tree: TypeDef if tree.isClassDef =>
if (checkPathMatches(path, "class", tree))
Expand Down
5 changes: 5 additions & 0 deletions tests/pos-special/sourcepath/outer/nested2/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package outer

package object nested2 {
val x: Int = 1
}
5 changes: 5 additions & 0 deletions tests/pos-special/sourcepath/outer/pkg.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package outer

object pkg {
val y: Int = nested2.x
}