Skip to content
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

Make Scala 2 getters appear as fields, to be consistent with Scala 3. #330

Merged
merged 1 commit into from
Jul 20, 2023
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
1 change: 1 addition & 0 deletions tasty-query/shared/src/main/scala/tastyquery/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ private[tastyquery] object Flags:

def |(otherFlags: FlagSet): FlagSet = bits | otherFlags.bits
def &(otherFlags: FlagSet): FlagSet = bits & otherFlags.bits
def &~(otherFlags: FlagSet): FlagSet = bits & ~otherFlags.bits

def show: String =
val result = new java.lang.StringBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,21 @@ private[pickles] class PickleReader {
if storedWhileReadingOwner != null then return storedWhileReadingOwner.asInstanceOf[MaybeExternalSymbol]

val pickleFlags = readPickleFlags(name1.isTypeName)
val flags = pickleFlagsToFlags(pickleFlags)
val flags0 = pickleFlagsToFlags(pickleFlags)
val name =
if pickleFlags.isType && flags.is(Module) then name1.toTermName.withObjectSuffix.toTypeName
else if flags.is(Method) && (name1 == Scala2Constructor || name1 == Scala2TraitConstructor) then nme.Constructor
if pickleFlags.isType && flags0.is(Module) then name1.toTermName.withObjectSuffix.toTypeName
else if flags0.is(Method) && (name1 == Scala2Constructor || name1 == Scala2TraitConstructor) then nme.Constructor
else name1

// Adapt the flags of getters so they become like vals/vars instead
val flags =
if flags0.isAllOf(Method | Accessor) && !name.toString().endsWith("_=") then
val flags1 = flags0 &~ (Method | Accessor)
if flags1.is(StableRealizable) then flags1
else flags1 | Mutable
else flags0
end flags

val (privateWithin, infoRef) = {
val ref = pkl.readNat()
if (!isSymbolRef(ref)) (None, ref)
Expand Down Expand Up @@ -291,10 +300,16 @@ private[pickles] class PickleReader {
cls.withGivenSelfType(givenSelfType)
cls
case VALsym =>
// Discard `$extension` methods, as they should not be seen from a Scala 3 point of view
/* Discard symbols that should not be seen from a Scala 3 point of view:
* - private fields generated for vals/vars (with a trailing ' ' in their name)
* - `$extension` methods
*/
val forceNotDeclaration = name1 match
case SimpleName(str) => flags.is(Method) && str.endsWith("$extension")
case _ => false
case SimpleName(str) =>
if flags.is(Method) then str.endsWith("$extension")
else if flags.isAllOf(Private | Local, butNotAnyOf = Method) then str.endsWith(" ")
else false
case _ => false
val sym =
if pickleFlags.isExistential || forceNotDeclaration then
TermSymbol.createNotDeclaration(name.toTermName, owner)
Expand Down
20 changes: 20 additions & 0 deletions tasty-query/shared/src/test/scala/tastyquery/SymbolSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,24 @@ class SymbolSuite extends RestrictedUnpicklingSuite {
testVisibility("scopedProtectedField", Visibility.ScopedProtected(simpleTreesPkg))
testVisibility("publicField", Visibility.Public)
}

testWithContext("scala-2-getters", "scala.StringContext", "scala.collection.mutable.ArrayBuffer") {
val StringContextClass = ctx.findTopLevelClass("scala.StringContext")

val partsSym = StringContextClass.findDecl(termName("parts"))
assert(clue(partsSym.kind) == TermSymbolKind.Val)
assert(clue(partsSym.visibility) == Visibility.Public)

assert(clue(StringContextClass.getDecl(termName("parts "))).isEmpty)
assert(!clue(StringContextClass.declarations).exists(_.name == termName("parts ")))

val ArrayBufferClass = ctx.findTopLevelClass("scala.collection.mutable.ArrayBuffer")

val size0Sym = ArrayBufferClass.findDecl(termName("size0"))
assert(clue(size0Sym.kind) == TermSymbolKind.Var)
assert(clue(size0Sym.visibility) == Visibility.Protected)

assert(clue(ArrayBufferClass.getDecl(termName("size0 "))).isEmpty)
assert(!clue(ArrayBufferClass.declarations).exists(_.name == termName("size0 ")))
}
}