Skip to content

Commit 4382eae

Browse files
committed
Test compilation of decompiled code
1 parent 2174d04 commit 4382eae

14 files changed

+62
-78
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
@@ -50,7 +50,11 @@ class DecompilerPrinter(_ctx: Context) extends RefinedPrinter(_ctx) {
5050
}
5151

5252
override protected def toTextTemplate(impl: Template, ofNew: Boolean = false): Text = {
53-
val impl1 = impl.copy(parents = impl.parents.filterNot(_.symbol.maybeOwner == defn.ObjectClass))
53+
def filter(sym: Symbol): Boolean = {
54+
sym.maybeOwner == defn.ObjectClass ||
55+
(sym == defn.ProductClass && impl.symbol.owner.is(Case))
56+
}
57+
val impl1 = impl.copy(parents = impl.parents.filterNot(p => filter(p.symbol)))
5458
super.toTextTemplate(impl1, ofNew)
5559
}
5660

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
628628
val tparamsTxt = withEnclosingDef(constr) { tparamsText(tparams) }
629629
val primaryConstrs = if (constr.rhs.isEmpty) Nil else constr :: Nil
630630
val prefix: Text =
631-
if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt
631+
if (constr.symbol.owner.is(Module)) " "
632+
else if (vparamss.isEmpty || primaryConstrs.nonEmpty) tparamsTxt
632633
else {
633634
var modsText = modText(constr.mods, "")
634635
if (!modsText.isEmpty) modsText = " " ~ modsText

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

Lines changed: 13 additions & 5 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
"macro-deprecate-dont-touch-backquotedidents.scala",
3232
"t247.scala",
@@ -62,12 +62,16 @@ class FromTastyTests extends ParallelTesting {
6262

6363
// Infinite compilation
6464
"t3612.scala",
65+
),
66+
recompileBlacklist = Set(
67+
"simpleCaseObject"
6568
)
6669
)
6770
step1.checkCompile() // Compile all files to generate the class files with tasty
6871
step2.checkCompile() // Compile from tasty
6972
step3.checkCompile() // Decompile from tasty
70-
(step1 + step2 + step3).delete()
73+
step4.checkCompile() // Recompile decompiled code
74+
(step1 + step2 + step3 + step4).delete()
7175
}
7276

7377
@Test def runTestFromTasty: Unit = {
@@ -77,7 +81,7 @@ class FromTastyTests extends ParallelTesting {
7781
// > dotr Test
7882

7983
implicit val testGroup: TestGroup = TestGroup("runTestFromTasty")
80-
val (step1, step2, step3) = compileTastyInDir("tests/run", defaultOptions,
84+
val (step1, step2, step3, step4) = compileTastyInDir("tests/run", defaultOptions,
8185
blacklist = Set(
8286

8387
"t7223.scala",
@@ -107,12 +111,16 @@ class FromTastyTests extends ParallelTesting {
107111
"phantom-poly-2.scala",
108112
"phantom-poly-3.scala",
109113
"phantom-poly-4.scala",
110-
)
114+
),
115+
recompileBlacklist = Set(
116+
"puzzle"
117+
)
111118
)
112119
step1.checkCompile() // Compile all files to generate the class files with tasty
113120
step2.checkRuns() // Compile from tasty and run the result
114121
step3.checkCompile() // Decompile from tasty
115-
(step1 + step2 + step3).delete()
122+
step4.checkCompile() // Recompile decompiled code
123+
(step1 + step2 + step3 + step4).delete()
116124
}
117125

118126
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
@@ -422,16 +422,17 @@ trait ParallelTesting extends RunnerOrchestration { self =>
422422
reporter
423423
}
424424

425-
protected def decompile(flags0: TestFlags, suppressErrors: Boolean, targetDir: JFile): TestReporter = {
426-
val decompilationOutput = new JFile(targetDir.getPath)
427-
decompilationOutput.mkdir()
425+
protected def decompile(flags0: TestFlags, suppressErrors: Boolean, targetDir0: JFile): TestReporter = {
426+
val targetDir = new JFile(targetDir0.getParent + "_decompiled")
427+
val decompilationOutput = new JFile(targetDir + "/" + targetDir0.getName)
428+
decompilationOutput.mkdirs()
428429
val flags =
429430
flags0 and ("-d", decompilationOutput.getAbsolutePath) and
430431
"-decompile" and "-pagewidth" and "80"
431432

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

436437
val reporter =
437438
TestReporter.reporter(realStdout, logLevel =
@@ -519,7 +520,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
519520
checkFileOpt match {
520521
case Some(checkFile) =>
521522
val stripTrailingWhitespaces = "(.*\\S|)\\s+".r
522-
val output = Source.fromFile(outDir + ".decompiled").getLines().map {line =>
523+
val output = Source.fromFile(outDir.getParent + "_decompiled/" + outDir.getName + "/decompiled.scala").getLines().map {line =>
523524
stripTrailingWhitespaces.unapplySeq(line).map(_.head).getOrElse(line)
524525
}.mkString("\n")
525526

@@ -1259,8 +1260,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
12591260
* Tests in the first part of the tuple must be executed before the second.
12601261
* Both testsRequires explicit delete().
12611262
*/
1262-
def compileTastyInDir(f: String, flags0: TestFlags, blacklist: Set[String] = Set.empty)(
1263-
implicit testGroup: TestGroup): (CompilationTest, CompilationTest, CompilationTest) = {
1263+
def compileTastyInDir(f: String, flags0: TestFlags, blacklist: Set[String], recompileBlacklist: Set[String])(
1264+
implicit testGroup: TestGroup): (CompilationTest, CompilationTest, CompilationTest, CompilationTest) = {
12641265
val outDir = defaultOutputDir + testGroup + "/"
12651266
val flags = flags0 and "-Yretain-trees"
12661267
val sourceDir = new JFile(f)
@@ -1286,10 +1287,15 @@ trait ParallelTesting extends RunnerOrchestration { self =>
12861287
// Create a CompilationTest and let the user decide whether to execute a pos or a neg test
12871288
val generateClassFiles = compileFilesInDir(f, flags0, blacklist)
12881289

1290+
val decompilationDir = outDir + sourceDir.getName + "_decompiled"
1291+
new JFile(decompilationDir).mkdirs()
1292+
val recompileDecompiled = compileFilesInDir(decompilationDir, flags0, recompileBlacklist)
1293+
12891294
(
12901295
generateClassFiles.keepOutput,
12911296
new CompilationTest(targets).keepOutput,
1292-
new CompilationTest(targets2).keepOutput
1297+
new CompilationTest(targets2).keepOutput,
1298+
recompileDecompiled.keepOutput
12931299
)
12941300
}
12951301

tests/pos/lambda.decompiled

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
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
val a: Int => Int =
75
{
86
(x: Int) => x.*(x)
97
}
108
}
11-
}
12-
--------------------------------------------------------------------------------
9+
}

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)