Skip to content

Commit f77ac08

Browse files
committed
Test compilation of decompiled code
1 parent 5dc5a7a commit f77ac08

14 files changed

+65
-81
lines changed

compiler/src/dotty/tools/dotc/decompiler/DecompilationPrinter.scala

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class DecompilationPrinter extends Phase {
2424
var os: OutputStream = null
2525
var ps: PrintStream = null
2626
try {
27-
os = File(outputDir + ".decompiled").outputStream(append = true)
27+
os = File(outputDir + "/decompiled.scala").outputStream(append = true)
2828
ps = new PrintStream(os)
2929
printToOutput(ps)
3030
} finally {
@@ -38,21 +38,15 @@ class DecompilationPrinter extends Phase {
3838
val unit = ctx.compilationUnit
3939
val pageWidth = ctx.settings.pageWidth.value
4040
val printLines = ctx.settings.printLines.value
41-
val doubleLine = "=" * pageWidth
42-
val line = "-" * pageWidth
43-
44-
out.println(doubleLine)
45-
out.println(unit.source)
46-
out.println(line)
4741

42+
out.println(s"/** Decompiled from $unit */")
4843
val printer = new DecompilerPrinter(ctx)
49-
5044
out.println(printer.toText(unit.tpdTree).mkString(pageWidth, printLines))
51-
out.println(line)
5245

5346
if (ctx.settings.printTasty.value) {
47+
out.println("/*")
5448
new TastyPrinter(unit.pickled.head._2).printContents()
55-
out.println(line)
49+
out.println("*/")
5650
}
5751
}
5852
}

compiler/src/dotty/tools/dotc/decompiler/Main.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ object Main extends dotc.Driver {
1414
assert(ctx.settings.fromTasty.value)
1515
val outputDir = ctx.settings.outputDir.value
1616
if (outputDir != ".")
17-
Files.deleteIfExists(Paths.get(outputDir + ".decompiled"))
17+
Files.deleteIfExists(Paths.get(outputDir + "/decompiled.scala"))
1818
new TASTYDecompiler
1919
}
2020

2121
override def setup(args0: Array[String], rootCtx: Context): (List[String], Context) = {
2222
var args = args0.filter(a => a != "-decompile")
23-
args = if (args.contains("-from-tasty")) args else "-from-tasty" +: args
23+
if (!args.contains("-from-tasty")) args = "-from-tasty" +: args
24+
if (args.contains("-d")) args = "-color:never" +: args
2425
super.setup(args, rootCtx)
2526
}
2627
}

compiler/src/dotty/tools/dotc/printing/DecompilerPrinter.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ class DecompilerPrinter(_ctx: Context) extends RefinedPrinter(_ctx) {
5555
}
5656

5757
override protected def toTextTemplate(impl: Template, ofNew: Boolean = false): Text = {
58-
val impl1 = impl.copy(parents = impl.parents.filterNot(_.symbol.maybeOwner == defn.ObjectClass))
58+
def filter(sym: Symbol): Boolean = {
59+
sym.maybeOwner == defn.ObjectClass ||
60+
(sym == defn.ProductClass && impl.symbol.owner.is(Case))
61+
}
62+
val impl1 = impl.copy(parents = impl.parents.filterNot(p => filter(p.symbol)))
5963
super.toTextTemplate(impl1, ofNew)
6064
}
6165

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
640640
val tparamsTxt = withEnclosingDef(constr) { tparamsText(tparams) }
641641
val primaryConstrs = if (constr.rhs.isEmpty) Nil else constr :: Nil
642642
val prefix: Text =
643-
if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt
643+
if (constr.symbol.owner.is(Module)) " "
644+
else if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt
644645
else {
645646
var modsText = modText(constr.mods, "")
646647
if (!modsText.isEmpty) modsText = " " ~ modsText

compiler/test/dotty/tools/dotc/FromTastyTests.scala

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ class FromTastyTests extends ParallelTesting {
2626
// > dotc -Ythrough-tasty -Ycheck:all <source>
2727

2828
implicit val testGroup: TestGroup = TestGroup("posTestFromTasty")
29-
val (step1, step2, step3) = compileTastyInDir("tests/pos", defaultOptions,
29+
val (step1, step2, step3, step4) = compileTastyInDir("tests/pos", defaultOptions,
3030
blacklist = Set(
3131
// Wrong number of arguments (only on bootstrapped)
3232
"i3130b.scala",
@@ -36,12 +36,16 @@ class FromTastyTests extends ParallelTesting {
3636

3737
// MatchError in SymDenotation.sourceModule on a ThisType
3838
"t3612.scala",
39+
),
40+
recompileBlacklist = Set(
41+
"simpleCaseObject"
3942
)
4043
)
4144
step1.checkCompile() // Compile all files to generate the class files with tasty
4245
step2.checkCompile() // Compile from tasty
4346
step3.checkCompile() // Decompile from tasty
44-
(step1 + step2 + step3).delete()
47+
step4.checkCompile() // Recompile decompiled code
48+
(step1 + step2 + step3 + step4).delete()
4549
}
4650

4751
@Test def runTestFromTasty: Unit = {
@@ -51,16 +55,20 @@ class FromTastyTests extends ParallelTesting {
5155
// > dotr Test
5256

5357
implicit val testGroup: TestGroup = TestGroup("runTestFromTasty")
54-
val (step1, step2, step3) = compileTastyInDir("tests/run", defaultOptions,
55-
blacklist = Set(
56-
// Closure type miss match
57-
"eff-dependent.scala",
58-
)
58+
val (step1, step2, step3, step4) = compileTastyInDir("tests/run", defaultOptions,
59+
blacklist = Set(
60+
// Closure type miss match
61+
"eff-dependent.scala",
62+
),
63+
recompileBlacklist = Set(
64+
"puzzle"
65+
)
5966
)
6067
step1.checkCompile() // Compile all files to generate the class files with tasty
6168
step2.checkRuns() // Compile from tasty and run the result
6269
step3.checkCompile() // Decompile from tasty
63-
(step1 + step2 + step3).delete()
70+
step4.checkCompile() // Recompile decompiled code
71+
(step1 + step2 + step3 + step4).delete()
6472
}
6573

6674
private implicit class tastyCompilationTuples(tup: (CompilationTest, CompilationTest)) {

compiler/test/dotty/tools/vulpix/ParallelTesting.scala

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -425,16 +425,17 @@ trait ParallelTesting extends RunnerOrchestration { self =>
425425
reporter
426426
}
427427

428-
protected def decompile(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = {
429-
val decompilationOutput = new JFile(targetDir.getPath)
430-
decompilationOutput.mkdir()
428+
protected def decompile(flags0: TestFlags, suppressErrors: Boolean, targetDir0: JFile): TestReporter = {
429+
val targetDir = new JFile(targetDir0.getParent + "_decompiled")
430+
val decompilationOutput = new JFile(targetDir + "/" + targetDir0.getName)
431+
decompilationOutput.mkdirs()
431432
val flags =
432433
flags0 and ("-d", decompilationOutput.getAbsolutePath) and
433434
"-decompile" and "-pagewidth" and "80"
434435

435436
def hasTastyFileToClassName(f: JFile): String =
436-
targetDir.toPath.relativize(f.toPath).toString.dropRight(".hasTasty".length).replace('/', '.')
437-
val classes = flattenFiles(targetDir).filter(isHasTastyFile).map(hasTastyFileToClassName).sorted
437+
targetDir0.toPath.relativize(f.toPath).toString.dropRight(".hasTasty".length).replace('/', '.')
438+
val classes = flattenFiles(targetDir0).filter(isHasTastyFile).map(hasTastyFileToClassName).sorted
438439

439440
val reporter =
440441
TestReporter.reporter(realStdout, logLevel =
@@ -522,7 +523,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
522523
checkFileOpt match {
523524
case Some(checkFile) =>
524525
val stripTrailingWhitespaces = "(.*\\S|)\\s+".r
525-
val output = Source.fromFile(outDir + ".decompiled").getLines().map {line =>
526+
val output = Source.fromFile(outDir.getParent + "_decompiled/" + outDir.getName + "/decompiled.scala").getLines().map {line =>
526527
stripTrailingWhitespaces.unapplySeq(line).map(_.head).getOrElse(line)
527528
}.mkString("\n")
528529

@@ -1257,8 +1258,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
12571258
* Tests in the first part of the tuple must be executed before the second.
12581259
* Both testsRequires explicit delete().
12591260
*/
1260-
def compileTastyInDir(f: String, flags0: TestFlags, blacklist: Set[String] = Set.empty)(
1261-
implicit testGroup: TestGroup): (CompilationTest, CompilationTest, CompilationTest) = {
1261+
def compileTastyInDir(f: String, flags0: TestFlags, blacklist: Set[String], recompileBlacklist: Set[String])(
1262+
implicit testGroup: TestGroup): (CompilationTest, CompilationTest, CompilationTest, CompilationTest) = {
12621263
val outDir = defaultOutputDir + testGroup + "/"
12631264
val flags = flags0 and "-Yretain-trees"
12641265
val sourceDir = new JFile(f)
@@ -1284,10 +1285,15 @@ trait ParallelTesting extends RunnerOrchestration { self =>
12841285
// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
12851286
val generateClassFiles = compileFilesInDir(f, flags0, blacklist)
12861287

1288+
val decompilationDir = outDir + sourceDir.getName + "_decompiled"
1289+
new JFile(decompilationDir).mkdirs()
1290+
val recompileDecompiled = compileFilesInDir(decompilationDir, flags0, recompileBlacklist)
1291+
12871292
(
12881293
generateClassFiles.keepOutput,
12891294
new CompilationTest(targets).keepOutput,
1290-
new CompilationTest(targets2).keepOutput
1295+
new CompilationTest(targets2).keepOutput,
1296+
recompileDecompiled.keepOutput
12911297
)
12921298
}
12931299

tests/pos/lambda.decompiled

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/lambda/foo/Foo.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/lambda/foo/Foo.class */
42
package foo {
53
class Foo() {
64
{
@@ -11,5 +9,4 @@ package foo {
119
}
1210
val a: Int => Int = (x: Int) => x.*(x)
1311
}
14-
}
15-
--------------------------------------------------------------------------------
12+
}

tests/pos/methodTypes.decompiled

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/methodTypes/Foo.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/methodTypes/Foo.class */
42
class Foo() {
53
val x: Int = 1
64
def y: Int = 2
75
def z(): Int = 3
8-
}
9-
--------------------------------------------------------------------------------
6+
}

tests/pos/simpleCaseObject.decompiled

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/simpleCaseObject/foo/Foo.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/simpleCaseObject/foo/Foo.class */
42
package foo {
5-
case object Foo() extends _root_.scala.Product { this: foo.Foo.type =>
3+
case object Foo { this: foo.Foo.type =>
64
override def hashCode(): Int = 1045991777
75
override def toString(): String = "Foo"
86
override def canEqual(that: Any): Boolean =
@@ -15,5 +13,4 @@ package foo {
1513
case _ => throw new IndexOutOfBoundsException(n.toString())
1614
}
1715
}
18-
}
19-
--------------------------------------------------------------------------------
16+
}

tests/pos/simpleClass-2.decompiled

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/simpleClass-2/foo/A.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/simpleClass-2/foo/A.class */
42
package foo {
53
class A() extends foo.B() {}
64
}
7-
--------------------------------------------------------------------------------
8-
================================================================================
9-
out/posTestFromTasty/pos/simpleClass-2/foo/B.class
10-
--------------------------------------------------------------------------------
5+
/** Decompiled from out/posTestFromTasty/pos/simpleClass-2/foo/B.class */
116
package foo {
127
class B() {}
13-
}
14-
--------------------------------------------------------------------------------
8+
}

tests/pos/simpleClass.decompiled

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/simpleClass/foo/A.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/simpleClass/foo/A.class */
42
package foo {
53
class A() {}
64
}
7-
--------------------------------------------------------------------------------
8-
================================================================================
9-
out/posTestFromTasty/pos/simpleClass/foo/B.class
10-
--------------------------------------------------------------------------------
5+
/** Decompiled from out/posTestFromTasty/pos/simpleClass/foo/B.class */
116
package foo {
127
class B() extends foo.A() {}
13-
}
14-
--------------------------------------------------------------------------------
8+
}

tests/pos/simpleDoWhile.decompiled

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/simpleDoWhile/Foo.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/simpleDoWhile/Foo.class */
42
class Foo() {
53
def foo: Unit =
64
{
@@ -11,5 +9,4 @@ class Foo() {
119
}
1210
while (i.!=(0))
1311
}
14-
}
15-
--------------------------------------------------------------------------------
12+
}

tests/pos/simpleWhile.decompiled

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
================================================================================
2-
out/posTestFromTasty/pos/simpleWhile/Foo.class
3-
--------------------------------------------------------------------------------
1+
/** Decompiled from out/posTestFromTasty/pos/simpleWhile/Foo.class */
42
class Foo() {
53
def foo: Unit =
64
{
@@ -10,5 +8,4 @@ class Foo() {
108
i = 0
119
}
1210
}
13-
}
14-
--------------------------------------------------------------------------------
11+
}

tests/run/puzzle.decompiled

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
================================================================================
2-
out/runTestFromTasty/run/puzzle/Test.class
3-
--------------------------------------------------------------------------------
4-
object Test() { this: Test.type =>
1+
/** Decompiled from out/runTestFromTasty/run/puzzle/Test.class */
2+
object Test { this: Test.type =>
53
def main(args: Array[String]): Unit =
64
{
75
println(if false then 5.0 else 53.0)
@@ -11,5 +9,4 @@ object Test() { this: Test.type =>
119
val y: Float = Long.long2float(z)
1210
()
1311
}
14-
}
15-
--------------------------------------------------------------------------------
12+
}

0 commit comments

Comments
 (0)