Skip to content

Commit

Permalink
Merge pull request #2809 from tgodzik/fix-toplevels
Browse files Browse the repository at this point in the history
Fix duplicate toplevels object definition when using enums
  • Loading branch information
tgodzik committed May 19, 2021
2 parents faa73cf + bd59c08 commit 11d30e3
Show file tree
Hide file tree
Showing 11 changed files with 65 additions and 29 deletions.
15 changes: 15 additions & 0 deletions mtags/src/main/scala/scala/meta/internal/mtags/MtagsIndexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ trait MtagsIndexer {
currentOwner = old
result
}
def ownerCompanion: String = {
import DefinitionAlternatives._
Symbol(currentOwner) match {
case GlobalSymbol(owner, Descriptor.Term(name)) =>
Symbols.Global(
owner.value,
Descriptor.Type(name)
)
case GlobalSymbol(owner, Descriptor.Type(name)) =>
Symbols.Global(
owner.value,
Descriptor.Term(name)
)
}
}
def term(name: String, pos: m.Position, kind: Kind, properties: Int): Unit =
addSignature(Descriptor.Term(name), pos, kind, properties)
def term(name: Term.Name, kind: Kind, properties: Int): Unit =
Expand Down
15 changes: 7 additions & 8 deletions mtags/src/main/scala/scala/meta/internal/mtags/ScalaMtags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,16 @@ class ScalaMtags(val input: Input.VirtualFile, dialect: Dialect)
enterTermParameters(t.ctor.paramss, isPrimaryCtor = true)
continue()
case t: Defn.Enum =>
withOwner(currentOwner) {
tpe(t.name, Kind.CLASS, 0)
enterTypeParameters(t.tparams)
enterTermParameters(t.ctor.paramss, isPrimaryCtor = true)
}
term(t.name.value, t.name.pos, Kind.OBJECT, 0)
tpe(t.name, Kind.CLASS, 0)
enterTypeParameters(t.tparams)
enterTermParameters(t.ctor.paramss, isPrimaryCtor = true)
continue()
case t: Defn.RepeatedEnumCase =>
t.cases.foreach(c => withOwner(currentOwner)(term(c, Kind.OBJECT, 0)))
t.cases.foreach(c =>
withOwner(ownerCompanion)(term(c, Kind.OBJECT, 0))
)
case t: Defn.EnumCase =>
term(t.name, Kind.OBJECT, 0)
withOwner(ownerCompanion)(term(t.name, Kind.OBJECT, 0))
case t: Defn.Trait =>
tpe(t.name, Kind.TRAIT, 0); continue()
enterTypeParameters(t.tparams)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ class ScalaToplevelMtags(
withOwner(owner) {
tpe(name.name, name.pos, Kind.CLASS, 0)
}
term(name.name, name.pos, Kind.OBJECT, 0)
case OBJECT =>
if (isPackageObject) {
currentOwner = symbol(Scala.Descriptor.Package(name.name))
Expand Down
2 changes: 1 addition & 1 deletion tests/cross/src/test/scala/tests/pc/CompletionSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ class CompletionSuite extends BaseCompletionSuite {
"",
compat = Map(
"3.0" -> "Inner a.Outer",
/* TODO
/* TODO
* Seems that changes in 2.13.5 made this pop up and this
* might have been a bug in presentation compiler that we were using
* https://github.com/scalameta/metals/issues/2546
Expand Down
1 change: 1 addition & 0 deletions tests/input3/src/main/scala/example/FooEnum.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ package example

enum FooEnum:
case Bar, Baz
object FooEnum
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ package example

enum FooEnum/*FooEnum.scala*/:
case Bar/*FooEnum.scala*/, Baz/*FooEnum.scala*/
object FooEnum/*FooEnum.scala*/
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/*example(Package):4*/package example
/*example(Package):5*/package example

/*example.FooEnum(Enum):4*/enum FooEnum:
case /*example.FooEnum.Bar(EnumMember):4*/Bar, /*example.FooEnum.Baz(EnumMember):4*/Baz
/*example.FooEnum(Module):5*/object FooEnum
14 changes: 14 additions & 0 deletions tests/unit/src/test/resources/expect/toplevels.expect
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
EmptyPackage.scala -> _empty_/EmptyPackage#
example/AbstractGiven.scala -> example/AbstractGiven#
example/AndOrType.scala -> example/AndOrType$package.
example/AndOrType.scala -> example/Cancelable#
example/AndOrType.scala -> example/Movable#
example/AnonymousClasses.scala -> example/AnonymousClasses#
example/ColorEnum.scala -> example/Color#
example/Comments.scala -> example/Comments#
example/Companion.scala -> example/Companion#
example/Companion.scala -> example/Companion.
example/Definitions.scala -> example/Definitions#
example/EtaExpansion.scala -> example/EtaExpansion#
example/ExampleSuite.scala -> example/ExampleSuite.
example/Extension.scala -> example/AbstractExtension#
example/Extension.scala -> example/Extension$package.
example/FooEnum.scala -> example/FooEnum#
example/FooEnum.scala -> example/FooEnum.
example/ForComprehensions.scala -> example/ForComprehensions#
example/GivenAlias.scala -> example/GivenAlias$package.
example/GivenAlias.scala -> example/X.
example/ImplicitClasses.scala -> example/ImplicitClasses.
example/ImplicitConversions.scala -> example/ImplicitConversions#
example/Imports.scala -> example/Imports#
Expand All @@ -22,10 +33,13 @@ example/MethodOverload.scala -> example/MethodOverload#
example/Miscellaneous.scala -> example/Miscellaneous#
example/NamedArguments.scala -> example/NamedArguments.
example/NamedArguments.scala -> example/User#
example/Ord.scala -> example/Ord#
example/Ord.scala -> example/Ord$package.
example/PatternMatching.scala -> example/PatternMatching#
example/ReflectiveInvocation.scala -> example/ReflectiveInvocation#
example/Scalalib.scala -> example/Scalalib#
example/StructuralTypes.scala -> example/StructuralTypes.
example/ToplevelDefVal.scala -> example/ToplevelDefVal$package.
example/TryCatch.scala -> example/TryCatch#
example/TypeParameters.scala -> example/TypeParameters#
example/VarArgs.scala -> example/VarArgs#
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ package example

enum FooEnum/*example.FooEnum#*/:
case Bar/*example.FooEnum.Bar.*/, Baz/*example.FooEnum.Baz.*/
object FooEnum/*example.FooEnum.*/
11 changes: 4 additions & 7 deletions tests/unit/src/test/scala/tests/ScalaToplevelSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ class ScalaToplevelSuite extends BaseSuite {
"_empty_/A.",
"_empty_/B#",
"_empty_/C#",
"_empty_/D#",
"_empty_/D."
"_empty_/D#"
)
)

Expand All @@ -49,8 +48,7 @@ class ScalaToplevelSuite extends BaseSuite {
"_empty_/A.",
"_empty_/B#",
"_empty_/C#",
"_empty_/D#",
"_empty_/D."
"_empty_/D#"
)
)

Expand Down Expand Up @@ -226,8 +224,7 @@ class ScalaToplevelSuite extends BaseSuite {
"_empty_/A.",
"_empty_/B#",
"_empty_/C#",
"_empty_/D#",
"_empty_/D."
"_empty_/D#"
)
)

Expand Down Expand Up @@ -258,7 +255,7 @@ class ScalaToplevelSuite extends BaseSuite {
expected: List[String],
all: Boolean = false,
dialect: Dialect = dialects.Scala3
): Unit = {
)(implicit location: munit.Location): Unit = {
test(options) {
val input = Input.VirtualFile("Test.scala", code)
val obtained =
Expand Down
30 changes: 19 additions & 11 deletions tests/unit/src/test/scala/tests/ToplevelSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import java.nio.charset.StandardCharsets

import scala.collection.mutable.ListBuffer

import scala.meta.Dialect
import scala.meta.dialects.Scala213
import scala.meta.dialects.Scala3
import scala.meta.inputs.Input
import scala.meta.internal.io.FileIO
import scala.meta.internal.mtags.Mtags
Expand All @@ -15,21 +18,26 @@ class ToplevelSuite extends SingleFileExpectSuite("toplevels.expect") {
override def obtained(): String = {
val toplevels = ListBuffer.empty[String]
val missingSymbols = ListBuffer.empty[String]
input.sourceDirectories.filter(_.isDirectory).foreach { dir =>
val ls = FileIO.listAllFilesRecursively(dir)
ls.files.foreach { relpath =>
val text =
FileIO.slurp(ls.root.resolve(relpath), StandardCharsets.UTF_8)
val input = Input.VirtualFile(relpath.toURI(false).toString, text)
val reluri = relpath.toURI(isDirectory = false).toString
Mtags.toplevels(input).foreach { toplevel =>
if (symtab.info(toplevel).isEmpty) {
missingSymbols += toplevel
def forInput(input: InputProperties, dialect: Dialect) = {
input.sourceDirectories.filter(_.isDirectory).foreach { dir =>
val ls = FileIO.listAllFilesRecursively(dir)
ls.files.foreach { relpath =>
val text =
FileIO.slurp(ls.root.resolve(relpath), StandardCharsets.UTF_8)
val input = Input.VirtualFile(relpath.toURI(false).toString, text)
val reluri = relpath.toURI(isDirectory = false).toString
Mtags.toplevels(input, dialect).foreach { toplevel =>
// do not check symtab for Scala 3 since it's not possible currently
if (symtab.info(toplevel).isEmpty && dialect != Scala3) {
missingSymbols += toplevel
}
toplevels += s"$reluri -> $toplevel"
}
toplevels += s"$reluri -> $toplevel"
}
}
}
forInput(InputProperties.scala2(), Scala213)
forInput(InputProperties.scala3(), Scala3)
if (missingSymbols.nonEmpty) {
fail(s"missing symbols:\n${missingSymbols.mkString("\n")}")
}
Expand Down

0 comments on commit 11d30e3

Please sign in to comment.