Skip to content

Commit

Permalink
Unpickle package-private from TASTy
Browse files Browse the repository at this point in the history
Meaning package private things will be automatically filtered.
  • Loading branch information
dwijnand committed Jan 25, 2022
1 parent 1bc783e commit 859334a
Show file tree
Hide file tree
Showing 30 changed files with 190 additions and 139 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ private[mima] sealed abstract class ClassInfo(val owner: PackageInfo) extends In
final def isInterface: Boolean = ClassfileParser.isInterface(flags) // java interface or trait w/o impl methods
final def isClass: Boolean = !isTrait && !isInterface // class, object or trait's impl class

final def accessModifier: String = if (isProtected) "protected" else if (isPrivate) "private" else ""
final def scopedPrivateSuff: String = if (isScopedPrivate) "[..]" else ""
final def accessModifier: String = if (isProtected) s"protected$scopedPrivateSuff" else if (isPrivate) s"private$scopedPrivateSuff" else ""
final def declarationPrefix: String = if (isModuleClass) "object" else if (isTrait) "trait" else if (isInterface) "interface" else "class"
final lazy val fullName: String = if (owner.isRoot) bytecodeName else s"${owner.fullName}.$bytecodeName"
final def formattedFullName: String = formatClassName(if (isModuleClass) fullName.init else fullName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ sealed abstract class MemberInfo(val owner: ClassInfo, val bytecodeName: String,

final def fullName: String = s"${owner.formattedFullName}.$decodedName"
final def abstractPrefix = if (isDeferred && !owner.isTrait) "abstract " else ""
final def scopedPrivatePrefix = if (scopedPrivate) "private[..] " else ""
final def staticPrefix: String = if (isStatic) "static " else ""
final def tpe: Type = owner.owner.definitions.fromDescriptor(descriptor)
final def hasSyntheticName: Boolean = decodedName.contains('$')
Expand Down Expand Up @@ -43,7 +44,7 @@ private[mima] final class MethodInfo(owner: ClassInfo, bytecodeName: String, fla
def shortMethodString: String = {
val prefix = if (hasSyntheticName) if (isExtensionMethod) "extension " else "synthetic " else ""
val deprecated = if (isDeprecated) "deprecated " else ""
s"${abstractPrefix}$prefix${deprecated}${staticPrefix}method $decodedName$tpe"
s"${scopedPrivatePrefix}${abstractPrefix}$prefix${deprecated}${staticPrefix}method $decodedName$tpe"
}

lazy val paramsCount: Int = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ object MimaUnpickler {
val index = buf.createIndex
val entries = new Array[Entry](index.length)
val classes = new scala.collection.mutable.HashMap[SymInfo, ClassInfo]
def nnSyms = entries.iterator.collect { case s: SymbolInfo => s }
def defnSyms = nnSyms.filter(sym => sym.tag == CLASSsym || sym.tag == MODULEsym)
def methSyms = nnSyms.filter(sym => sym.tag == VALsym)
def syms = entries.iterator.collect { case s: SymbolInfo => s }
def defnSyms = syms.filter(sym => sym.tag == CLASSsym || sym.tag == MODULEsym)
def methSyms = syms.filter(sym => sym.tag == VALsym)

def until[T](end: Int, op: () => T): List[T] =
if (buf.readIndex == end) Nil else op() :: until(end, op)
Expand Down Expand Up @@ -177,7 +177,7 @@ object MimaUnpickler {
.filter(_.name.value != CONSTRUCTOR) // TODO support package private constructors
.toSeq.groupBy(_.name).foreach { case (name, pickleMethods) =>
doMethodOverloads(clazz, name, pickleMethods)
}
}
}

def doMethodOverloads(clazz: ClassInfo, name: Name, pickleMethods: Seq[SymbolInfo]) = {
Expand Down
190 changes: 137 additions & 53 deletions core/src/main/scala/com/typesafe/tools/mima/core/TastyUnpickler.scala

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import java.nio.file.Files
import com.typesafe.tools.mima.core.ProblemFilter

import scala.collection.JavaConverters._
import scala.util.{ Failure, Success, Try }
import scala.util.{Failure, Success, Try}

object CollectProblemsTest {
def testCollectProblems(testCase: TestCase, direction: Direction): Try[Unit] = for {
Expand Down Expand Up @@ -35,15 +35,20 @@ object CollectProblemsTest {
val reported = problems.map(_.description(affectedVersion))

val msg = new StringBuilder("\n")
def pp(start: String, lines: List[String]) =
import scala.io.AnsiColor._
final case class DiffType(sign: Char, colour: String)
val add = DiffType('+', GREEN)
val del = DiffType('-', RED)

def pp(start: String, dt: DiffType, lines: List[String]) =
if (lines.nonEmpty) {
msg.append(s"$start (${lines.size}):")
lines.sorted.distinct.map("\n - " + _).foreach(msg.append(_))
lines.sorted.distinct.map("\n" + dt.colour + dt.sign + _ + RESET).foreach(msg.append)
msg.append("\n")
}

pp("The following problem(s) were expected but not reported", expected.diff(reported))
pp("The following problem(s) were reported but not expected", reported.diff(expected))
pp("The following problem(s) were expected but not reported", del, expected.diff(reported))
pp("The following problem(s) were reported but not expected", add, reported.diff(expected))

msg.mkString match {
case "\n" => Success(())
Expand Down

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
method go11()Int in object foo.l1.x has a different result type in new version, where it is java.lang.String rather than Int
method go12()Int in class foo.l1.x has a different result type in new version, where it is java.lang.String rather than Int
method go21()Int in object foo.l2a.x#y has a different result type in new version, where it is java.lang.String rather than Int
method go22()Int in class foo.l2a.x#y has a different result type in new version, where it is java.lang.String rather than Int
method go23()Int in object foo.l2b.x#y has a different result type in new version, where it is java.lang.String rather than Int
method go24()Int in class foo.l2b.x#y has a different result type in new version, where it is java.lang.String rather than Int
method go31()Int in object foo.l3a.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go32()Int in class foo.l3a.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go33()Int in object foo.l3b.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go34()Int in class foo.l3b.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go35()Int in object foo.l3c.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go36()Int in class foo.l3c.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go37()Int in object foo.l3d.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
method go38()Int in class foo.l3d.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
# privateWithin isn't honoured in static method emission in Scala 3
# https://github.com/lampepfl/dotty/issues/10842
static method go11()Int in class foo.l1.x has a different result type in new version, where it is java.lang.String rather than Int
static method go21()Int in class foo.l2a.x#y has a different result type in new version, where it is java.lang.String rather than Int
static method go31()Int in class foo.l3a.x#y#z has a different result type in new version, where it is java.lang.String rather than Int
Original file line number Diff line number Diff line change
Expand Up @@ -7,63 +7,49 @@ package foo
// Because of scala/bug#2034 we can't put these all in one package (you get "name clash" errors)
// So instead we'll split them in 4 nice and even packages
package l1 { object x { private[foo] def go11() = 11 }; class x { private[foo] def go12() = 12 }}
// l1/x.class:
// 0: MODULEsym x 8
// 1: CLASSsym x 8
// 4: CLASSsym x 8
// MODULEsym + CLASSsym x <module> // x + x$
// VALsym go11 private[foo]
// CLASSsym x // x
// VALsym go12 private[foo]
// l1/x.tasty:
// VALDEF x + TYPEDEF x[ModuleClass] // x + x$
// TYPEDEF x // x

package l2a { object x { object y { private[foo] def go21() = 21 }; class y { private[foo] def go22() = 22 }}}
package l2b { class x { object y { private[foo] def go23() = 23 }; class y { private[foo] def go24() = 24 }}}
// l2a/x.class:
// 0 MODULEsym x 11
// 1 CLASSsym x 11
// 3 MODULEsym y 1
// 4 CLASSsym y 1
// 7 CLASSsym y 1
// MODULEsym + CLASSsym x <module> // x + x$
// MODULEsym + CLASSsym y <module> // x$y$
// CLASSsym y // x$y
// l2a/x.tasty:
// VALDEF x + TYPEDEF x[ModuleClass] // x + x$
// VALDEF y + TYPEDEF y[ModuleClass] // x$y$
// TYPEDEF y // x$y

// l2b/x.class:
// 0 CLASSsym x 10
// 2 MODULEsym y 0
// 3 CLASSsym y 0
// 6 CLASSsym y 0
// CLASSsym x // x
// MODULEsym + CLASSsym y <module> // x$y$
// CLASSsym y // x$y
// l2b/x.tasty:
// TYPEDEF x // x
// VALDEF y + TYPEDEF y[ModuleClass] // x$y$
// TYPEDEF y // x$y

package l3a { object x { object y { object z { private[foo] def go31() = 31 }; class z { private[foo] def go32() = 32 }}}}
package l3b { object x { class y { object z { private[foo] def go33() = 33 }; class z { private[foo] def go34() = 34 }}}}
package l3c { class x { object y { object z { private[foo] def go35() = 35 }; class z { private[foo] def go36() = 36 }}}}
package l3d { class x { class y { object z { private[foo] def go37() = 37 }; class z { private[foo] def go38() = 38 }}}}
// l3a/x.class:
// 0 MODULEsym x 14 + 1 CLASSsym x 14 // x + x$
// 3 MODULEsym y 1 + 4 CLASSsym y 1 // x$y$
// 6 MODULEsym z 4 + 7 CLASSsym z 4 // x$y$z$
// 10 CLASSsym z 4 // x$y$z
// l3a/x.tasty:
// VALDEF x + TYPEDEF x[ModuleClass] // x + x$
// VALDEF y + TYPEDEF y[ModuleClass] // x$y$
// VALDEF z + TYPEDEF z[ModuleClass] // x$y$z$
// TYPEDEF z // x$y$z
//
// l3b/x.class:
// 0 MODULEsym x 13 + 1 CLASSsym x 13 // x + x$
// 3 CLASSsym y 1 // x$y
// 5 MODULEsym z 3 + 6 CLASSsym z 3 // x$y$z$
// 9 CLASSsym z 3 // x$y$z
// l3b/x.tasty:
// VALDEF x + TYPEDEF 5 x[ModuleClass] // x + x$
// TYPEDEF y // x$y
// VALDEF z + TYPEDEF z[ModuleClass] // x$y$z$
// TYPEDEF z // x$y$z
//
// l3c/x.class:
// 0 CLASSsym x 13 // x
// 2 MODULEsym y 0 + 3 CLASSsym y 0 // x$y$
// 5 MODULEsym z 3 + 6 CLASSsym z 3 // x$y$z$
// 9 CLASSsym z 3 // x$y$z$
// l3c/x.tasty:
// TYPEDEF x // x
// VALDEF y + TYPEDEF y[ModuleClass] // x$y$
// VALDEF z + TYPEDEF z[ModuleClass] // x$y$z$
// TYPEDEF z // x$y$z
//
// l3d/x.class:
// 0 CLASSsym x 12 // x
// 2 CLASSsym y 0 // x$y
// 4 MODULEsym z 2 + 5 CLASSsym z 2 // x$y$z$
// 8 CLASSsym z 2 // x$y$z
// l3d/x.tasty:
// TYPEDEF x // x
// TYPEDEF y // x$y
// VALDEF z + TYPEDEF z[ModuleClass] // x$y$z$
// TYPEDEF z // x$y$z

object Lib {
def doIt = { doL1(); doL2(); doL3() }
Expand Down

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.

This file was deleted.

Empty file.
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
method bar(Int)Int in class foo.Foo does not have a correspondent in new version
method baz(Int)Int in object foo.Foo does not have a correspondent in new version
method qux(Int)Int in class foo.Foo does not have a correspondent in new version
method qux(Int)Int in object foo.Foo does not have a correspondent in new version
# I guess privateWithin isn't honoured in static method emission in Scala 3
# https://github.com/lampepfl/dotty/issues/10842
static method baz(Int)Int in class foo.Foo does not have a correspondent in new version

This file was deleted.

Empty file.

This file was deleted.

Empty file.

0 comments on commit 859334a

Please sign in to comment.