@@ -132,7 +132,8 @@ trait ParallelTesting extends RunnerOrchestration { self =>
132132 name : String ,
133133 files : Array [JFile ],
134134 flags : TestFlags ,
135- outDir : JFile
135+ outDir : JFile ,
136+ fromTasty : Boolean = false
136137 ) extends TestSource {
137138 def sourceFiles : Array [JFile ] = files.filter(isSourceFile)
138139
@@ -213,7 +214,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
213214 private val filteredSources =
214215 if (! testFilter.isDefined) testSources
215216 else testSources.filter {
216- case JointCompilationSource (_, files, _, _) =>
217+ case JointCompilationSource (_, files, _, _, _ ) =>
217218 files.exists(file => file.getAbsolutePath.contains(testFilter.get))
218219 case SeparateCompilationSource (_, dir, _, _) =>
219220 dir.getAbsolutePath.contains(testFilter.get)
@@ -336,15 +337,6 @@ trait ParallelTesting extends RunnerOrchestration { self =>
336337
337338 val files : Array [JFile ] = files0.flatMap(flattenFiles)
338339
339- def addOutDir (xs : Array [String ]): Array [String ] = {
340- val (beforeCp, cpAndAfter) = xs.toList.span(_ != " -classpath" )
341- if (cpAndAfter.nonEmpty) {
342- val (cp :: cpArg :: rest) = cpAndAfter
343- (beforeCp ++ (cp :: (cpArg + s " : ${targetDir.getAbsolutePath}" ) :: rest)).toArray
344- }
345- else (beforeCp ++ (" -classpath" :: targetDir.getAbsolutePath :: Nil )).toArray
346- }
347-
348340 def compileWithJavac (fs : Array [String ]) = if (fs.nonEmpty) {
349341 val fullArgs = Array (
350342 " javac" ,
@@ -379,7 +371,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
379371 }
380372 }
381373
382- val allArgs = addOutDir( flags.all)
374+ val allArgs = flags.withClasspath(targetDir.getAbsolutePath).all
383375
384376 // Compile with a try to catch any StackTrace generated by the compiler:
385377 try {
@@ -400,6 +392,30 @@ trait ParallelTesting extends RunnerOrchestration { self =>
400392 reporter
401393 }
402394
395+ protected def compileFromTasty (flags0 : TestFlags , suppressErrors : Boolean , targetDir : JFile ): TestReporter = {
396+ val tastyOutput = new JFile (targetDir.getPath + " _from-tasty" )
397+ tastyOutput.mkdir()
398+ val flags = flags0 and (" -d" , tastyOutput.getAbsolutePath)
399+
400+ def hasTastyFileToClassName (f : JFile ): String =
401+ targetDir.toPath.relativize(f.toPath).toString.dropRight(" .hasTasty" .length).replace('/' , '.' )
402+ val classes = flattenFiles(targetDir).filter(isHasTastyFile).map(hasTastyFileToClassName)
403+
404+ val reporter =
405+ TestReporter .reporter(realStdout, logLevel =
406+ if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR )
407+
408+ // Compile with a try to catch any StackTrace generated by the compiler:
409+ try {
410+ dotc.FromTasty .process(flags.all ++ classes, reporter = reporter)
411+ }
412+ catch {
413+ case NonFatal (ex) => reporter.logStackTrace(ex)
414+ }
415+
416+ reporter
417+ }
418+
403419 private [ParallelTesting ] def executeTestSuite (): this .type = {
404420 assert(_testSourcesCompleted == 0 , " not allowed to re-use a `CompileRun`" )
405421
@@ -440,24 +456,30 @@ trait ParallelTesting extends RunnerOrchestration { self =>
440456
441457 this
442458 }
459+
460+ /** Returns all files in directory or the file if not a directory */
461+ private def flattenFiles (f : JFile ): Array [JFile ] =
462+ if (f.isDirectory) f.listFiles.flatMap(flattenFiles)
463+ else Array (f)
443464 }
444465
445466 private final class PosTest (testSources : List [TestSource ], times : Int , threadLimit : Option [Int ], suppressAllOutput : Boolean )(implicit summaryReport : SummaryReporting )
446467 extends Test (testSources, times, threadLimit, suppressAllOutput) {
447468 protected def encapsulatedCompilation (testSource : TestSource ) = new LoggedRunnable {
448469 def checkTestSource (): Unit = tryCompile(testSource) {
449470 testSource match {
450- case testSource @ JointCompilationSource (_, files, flags, outDir) => {
451- val reporter = compile(testSource.sourceFiles, flags, false , outDir)
471+ case testSource @ JointCompilationSource (_, files, flags, outDir, fromTasty) =>
472+ val reporter =
473+ if (fromTasty) compileFromTasty(flags, false , outDir)
474+ else compile(testSource.sourceFiles, flags, false , outDir)
452475 registerCompletion(reporter.errorCount)
453476
454477 if (reporter.compilerCrashed || reporter.errorCount > 0 ) {
455478 logReporterContents(reporter)
456479 logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount)
457480 }
458- }
459481
460- case testSource @ SeparateCompilationSource (_, dir, flags, outDir) => {
482+ case testSource @ SeparateCompilationSource (_, dir, flags, outDir) =>
461483 val reporters = testSource.compilationGroups.map(files => compile(files, flags, false , outDir))
462484 val compilerCrashed = reporters.exists(_.compilerCrashed)
463485 val errorCount = reporters.foldLeft(0 ) { (acc, reporter) =>
@@ -475,7 +497,6 @@ trait ParallelTesting extends RunnerOrchestration { self =>
475497 reporters.foreach(logReporterContents)
476498 logBuildInstructions(reporters.head, testSource, errorCount, warningCount)
477499 }
478- }
479500 }
480501 }
481502 }
@@ -546,7 +567,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
546567 protected def encapsulatedCompilation (testSource : TestSource ) = new LoggedRunnable {
547568 def checkTestSource (): Unit = tryCompile(testSource) {
548569 val (compilerCrashed, errorCount, warningCount, verifier : Function0 [Unit ]) = testSource match {
549- case testSource @ JointCompilationSource (_, files, flags, outDir) => {
570+ case testSource @ JointCompilationSource (_, files, flags, outDir, fromTasty ) =>
550571 val checkFile = files.flatMap { file =>
551572 if (file.isDirectory) Nil
552573 else {
@@ -556,17 +577,18 @@ trait ParallelTesting extends RunnerOrchestration { self =>
556577 else Nil
557578 }
558579 }.headOption
559- val reporter = compile(testSource.sourceFiles, flags, false , outDir)
580+ val reporter =
581+ if (fromTasty) compileFromTasty(flags, false , outDir)
582+ else compile(testSource.sourceFiles, flags, false , outDir)
560583
561584 if (reporter.compilerCrashed || reporter.errorCount > 0 ) {
562585 logReporterContents(reporter)
563586 logBuildInstructions(reporter, testSource, reporter.errorCount, reporter.warningCount)
564587 }
565588
566589 (reporter.compilerCrashed, reporter.errorCount, reporter.warningCount, () => verifyOutput(checkFile, outDir, testSource, reporter.warningCount))
567- }
568590
569- case testSource @ SeparateCompilationSource (_, dir, flags, outDir) => {
591+ case testSource @ SeparateCompilationSource (_, dir, flags, outDir) =>
570592 val checkFile = new JFile (dir.getAbsolutePath.reverse.dropWhile(_ == '/' ).reverse + " .check" )
571593 val reporters = testSource.compilationGroups.map(compile(_, flags, false , outDir))
572594 val compilerCrashed = reporters.exists(_.compilerCrashed)
@@ -584,7 +606,6 @@ trait ParallelTesting extends RunnerOrchestration { self =>
584606 }
585607
586608 (compilerCrashed, errorCount, warningCount, () => verifyOutput(Some (checkFile), outDir, testSource, warningCount))
587- }
588609 }
589610
590611 if (! compilerCrashed && errorCount == 0 ) verifier()
@@ -655,7 +676,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
655676 }
656677
657678 val (compilerCrashed, expectedErrors, actualErrors, hasMissingAnnotations, errorMap) = testSource match {
658- case testSource @ JointCompilationSource (_, files, flags, outDir) => {
679+ case testSource @ JointCompilationSource (_, files, flags, outDir, fromTasty ) =>
659680 val sourceFiles = testSource.sourceFiles
660681 val (errorMap, expectedErrors) = getErrorMapAndExpectedCount(sourceFiles)
661682 val reporter = compile(sourceFiles, flags, true , outDir)
@@ -665,7 +686,6 @@ trait ParallelTesting extends RunnerOrchestration { self =>
665686 logReporterContents(reporter)
666687
667688 (reporter.compilerCrashed, expectedErrors, actualErrors, () => getMissingExpectedErrors(errorMap, reporter.errors), errorMap)
668- }
669689
670690 case testSource @ SeparateCompilationSource (_, dir, flags, outDir) => {
671691 val compilationGroups = testSource.compilationGroups
@@ -941,7 +961,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>
941961 */
942962 def copyToTarget (): CompilationTest = new CompilationTest (
943963 targets.map {
944- case target @ JointCompilationSource (_, files, _, outDir) =>
964+ case target @ JointCompilationSource (_, files, _, outDir, _ ) =>
945965 target.copy(files = files.map(copyToDir(outDir,_)))
946966 case target @ SeparateCompilationSource (_, dir, _, outDir) =>
947967 target.copy(dir = copyToDir(outDir, dir))
@@ -1056,6 +1076,30 @@ trait ParallelTesting extends RunnerOrchestration { self =>
10561076 new CompilationTest (target)
10571077 }
10581078
1079+ /** Compiles a single file from the string path `f` using the supplied flags */
1080+ def compileTasty (f : String , flags : TestFlags )(implicit testGroup : TestGroup ): (CompilationTest , CompilationTest ) = {
1081+ val sourceFile = new JFile (f)
1082+ val parent = sourceFile.getParentFile
1083+ val outDir =
1084+ defaultOutputDir + testGroup + " /" +
1085+ sourceFile.getName.substring(0 , sourceFile.getName.lastIndexOf('.' )) + " /"
1086+
1087+ require(
1088+ sourceFile.exists && ! sourceFile.isDirectory &&
1089+ (parent ne null ) && parent.exists && parent.isDirectory,
1090+ s " Source file: $f, didn't exist "
1091+ )
1092+ val tastySource = createOutputDirsForFile(sourceFile, parent, outDir)
1093+ val target = JointCompilationSource (
1094+ testGroup.name,
1095+ Array (sourceFile),
1096+ flags.withClasspath(tastySource.getPath) and " -Yretain-trees" ,
1097+ tastySource,
1098+ fromTasty = true
1099+ )
1100+ (compileFile(f, flags), new CompilationTest (target))
1101+ }
1102+
10591103 /** Compiles a directory `f` using the supplied `flags`. This method does
10601104 * deep compilation, that is - it compiles all files and subdirectories
10611105 * contained within the directory `f`.
@@ -1137,6 +1181,44 @@ trait ParallelTesting extends RunnerOrchestration { self =>
11371181 new CompilationTest (targets)
11381182 }
11391183
1184+ /** This function compiles the files and folders contained within directory
1185+ * `f` in a specific way. Once compiled, they are recompiled/run from tasty as sources.
1186+ *
1187+ * - Each file is compiled separately as a single compilation run
1188+ * - Each directory is compiled as a `SeparateCompilationTaret`, in this
1189+ * target all files are grouped according to the file suffix `_X` where `X`
1190+ * is a number. These groups are then ordered in ascending order based on
1191+ * the value of `X` and each group is compiled one after the other.
1192+ *
1193+ * For this function to work as expected, we use the same convention for
1194+ * directory layout as the old partest. That is:
1195+ *
1196+ * - Single files can have an associated check-file with the same name (but
1197+ * with file extension `.check`)
1198+ * - Directories can have an associated check-file, where the check file has
1199+ * the same name as the directory (with the file extension `.check`)
1200+ */
1201+ def compileTastyInDir (f : String , flags0 : TestFlags )(implicit testGroup : TestGroup ): (CompilationTest , CompilationTest ) = {
1202+ val outDir = defaultOutputDir + testGroup + " /"
1203+ val flags = flags0 and " -Yretain-trees"
1204+ val sourceDir = new JFile (f)
1205+ checkRequirements(f, sourceDir, outDir)
1206+
1207+ val (dirs, files) = compilationTargets(sourceDir)
1208+
1209+ val targets =
1210+ files.map { f =>
1211+ val classpath = createOutputDirsForFile(f, sourceDir, outDir)
1212+ JointCompilationSource (testGroup.name, Array (f), flags.withClasspath(classpath.getPath), classpath, fromTasty = true )
1213+ }
1214+ // TODO add SeparateCompilationSource from tasty?
1215+
1216+ // Create a CompilationTest and let the user decide whether to execute a pos or a neg test
1217+ val generateClassFiles = compileFilesInDir(f, flags0)
1218+ (generateClassFiles, new CompilationTest (targets))
1219+ }
1220+
1221+
11401222 /** This function behaves similar to `compileFilesInDir` but it ignores
11411223 * sub-directories and as such, does **not** perform separate compilation
11421224 * tests.
@@ -1165,4 +1247,7 @@ object ParallelTesting {
11651247 val name = f.getName
11661248 name.endsWith(" .scala" ) || name.endsWith(" .java" )
11671249 }
1250+
1251+ def isHasTastyFile (f : JFile ): Boolean =
1252+ f.getName.endsWith(" .hasTasty" )
11681253}
0 commit comments