From 188702aa539e52c14ad42152a5b0bde50ce5571c Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Fri, 10 Sep 2021 18:50:42 +0200 Subject: [PATCH] Move post-processing stuff to its own class hierarchy --- .../src/main/scala/scala/build/Build.scala | 116 ++---------------- .../scala/scala/build/bsp/BspClient.scala | 2 +- .../AsmPositionUpdater.scala | 2 +- .../ByteCodePostProcessor.scala | 14 +++ .../LineConversion.scala | 2 +- .../build/postprocessing/PostProcessor.scala | 13 ++ .../SemanticDbPostProcessor.scala | 69 +++++++++++ .../SemanticdbProcessor.scala | 2 +- .../postprocessing/TastyPostProcessor.scala | 53 ++++++++ 9 files changed, 162 insertions(+), 111 deletions(-) rename modules/build/src/main/scala/scala/build/{internal => postprocessing}/AsmPositionUpdater.scala (98%) create mode 100644 modules/build/src/main/scala/scala/build/postprocessing/ByteCodePostProcessor.scala rename modules/build/src/main/scala/scala/build/{internal => postprocessing}/LineConversion.scala (96%) create mode 100644 modules/build/src/main/scala/scala/build/postprocessing/PostProcessor.scala create mode 100644 modules/build/src/main/scala/scala/build/postprocessing/SemanticDbPostProcessor.scala rename modules/build/src/main/scala/scala/build/{internal => postprocessing}/SemanticdbProcessor.scala (99%) create mode 100644 modules/build/src/main/scala/scala/build/postprocessing/TastyPostProcessor.scala diff --git a/modules/build/src/main/scala/scala/build/Build.scala b/modules/build/src/main/scala/scala/build/Build.scala index 97aea2061a..16f5d393e5 100644 --- a/modules/build/src/main/scala/scala/build/Build.scala +++ b/modules/build/src/main/scala/scala/build/Build.scala @@ -6,17 +6,9 @@ import com.swoval.files.FileTreeViews.Observer import com.swoval.files.{FileTreeRepositories, PathWatcher, PathWatchers} import dependency._ import scala.build.blooprifle.BloopRifleConfig -import scala.build.internal.{ - AsmPositionUpdater, - Constants, - CustomCodeWrapper, - LineConversion, - MainClass, - SemanticdbProcessor, - Util -} +import scala.build.internal.{Constants, CustomCodeWrapper, MainClass, Util} import scala.build.options.BuildOptions -import scala.build.tastylib.TastyData +import scala.build.postprocessing._ import java.io.{File, IOException} import java.lang.{Boolean => JBoolean} @@ -465,20 +457,6 @@ object Build { Failed(inputs, options, sources, artifacts, project, buildClient.diagnostics) } - @tailrec - private def deleteSubPathIfEmpty(base: os.Path, subPath: os.SubPath, logger: Logger): Unit = - if (subPath.segments.nonEmpty) { - val p = base / subPath - if (os.isDir(p) && os.list.stream(p).headOption.isEmpty) { - try os.remove(p) - catch { - case e: FileSystemException => - logger.debug(s"Ignoring $e while cleaning up $p") - } - deleteSubPathIfEmpty(base, subPath / os.up, logger) - } - } - def postProcess( generatedSources: Seq[GeneratedSource], generatedSrcRoot: os.Path, @@ -500,90 +478,14 @@ object Build { (relPath, (reportingPath, lineShift)) } .toMap - AsmPositionUpdater.postProcess(mappings, classesDir, logger) - - if (updateSemanticDbs) { - logger.debug("Moving semantic DBs around") - val semDbRoot = classesDir / "META-INF" / "semanticdb" - for (source <- generatedSources; originalSource <- source.reportingPath) { - val fromSourceRoot = source.generated.relativeTo(workspace) - val actual = originalSource.relativeTo(workspace) - - val semDbSubPath = { - val dirSegments = fromSourceRoot.segments.dropRight(1) - os.sub / dirSegments / s"${fromSourceRoot.last}.semanticdb" - } - val semDbFile = semDbRoot / semDbSubPath - if (os.exists(semDbFile)) { - val finalSemDbFile = { - val dirSegments = actual.segments.dropRight(1) - semDbRoot / dirSegments / s"${actual.last}.semanticdb" - } - SemanticdbProcessor.postProcess( - os.read(originalSource), - originalSource.relativeTo(workspace), - None, - if (source.topWrapperLen == 0) n => Some(n) - else - LineConversion.scalaLineToScLine( - os.read(originalSource), - os.read(source.generated), - source.topWrapperLen - ), - semDbFile, - finalSemDbFile - ) - try os.remove(semDbFile) - catch { - case ex: FileSystemException => - logger.debug(s"Ignoring $ex while removing $semDbFile") - } - deleteSubPathIfEmpty(semDbRoot, semDbSubPath / os.up, logger) - } - } - if (updateTasty) { - val updatedPaths = generatedSources - .flatMap { source => - source.reportingPath.toOption.toSeq.map { originalSource => - val fromSourceRoot = source.generated.relativeTo(workspace) - val actual = originalSource.relativeTo(workspace) - fromSourceRoot.toString -> actual.toString - } - } - .toMap - - if (updatedPaths.nonEmpty) - os.walk(classesDir) - .filter(os.isFile(_)) - .filter(_.last.endsWith(".tasty")) // make that case-insensitive just in case? - .foreach { f => - logger.debug(s"Reading TASTy file $f") - val content = os.read.bytes(f) - val data = TastyData.read(content) - logger.debug(s"Parsed TASTy file $f") - var updatedOne = false - val updatedData = data.mapNames { n => - updatedPaths.get(n) match { - case Some(newName) => - updatedOne = true - newName - case None => - n - } - } - if (updatedOne) { - logger.debug( - s"Overwriting ${if (f.startsWith(os.pwd)) f.relativeTo(os.pwd) else f}" - ) - val updatedContent = TastyData.write(updatedData) - os.write.over(f, updatedContent) - } - } - } - } - else - logger.debug("Custom generated source directory used, not moving semantic DBs around") + val postProcessors = + Seq(ByteCodePostProcessor) ++ + (if (updateSemanticDbs) Seq(SemanticDbPostProcessor) else Nil) ++ + (if (updateTasty) Seq(TastyPostProcessor) else Nil) + + for (p <- postProcessors) + p.postProcess(generatedSources, mappings, workspace, classesDir, logger) } def onChangeBufferedObserver(onEvent: PathWatchers.Event => Unit): Observer[PathWatchers.Event] = diff --git a/modules/build/src/main/scala/scala/build/bsp/BspClient.scala b/modules/build/src/main/scala/scala/build/bsp/BspClient.scala index 5414c2cbe4..16ff893592 100644 --- a/modules/build/src/main/scala/scala/build/bsp/BspClient.scala +++ b/modules/build/src/main/scala/scala/build/bsp/BspClient.scala @@ -7,7 +7,7 @@ import java.nio.file.Paths import java.util.concurrent.ExecutorService import scala.build.{BloopBuildClient, GeneratedSource, Logger} -import scala.build.internal.LineConversion +import scala.build.postprocessing.LineConversion import scala.collection.JavaConverters._ class BspClient( diff --git a/modules/build/src/main/scala/scala/build/internal/AsmPositionUpdater.scala b/modules/build/src/main/scala/scala/build/postprocessing/AsmPositionUpdater.scala similarity index 98% rename from modules/build/src/main/scala/scala/build/internal/AsmPositionUpdater.scala rename to modules/build/src/main/scala/scala/build/postprocessing/AsmPositionUpdater.scala index 052096f21e..afe3527c5d 100644 --- a/modules/build/src/main/scala/scala/build/internal/AsmPositionUpdater.scala +++ b/modules/build/src/main/scala/scala/build/postprocessing/AsmPositionUpdater.scala @@ -1,4 +1,4 @@ -package scala.build.internal +package scala.build.postprocessing import org.objectweb.asm diff --git a/modules/build/src/main/scala/scala/build/postprocessing/ByteCodePostProcessor.scala b/modules/build/src/main/scala/scala/build/postprocessing/ByteCodePostProcessor.scala new file mode 100644 index 0000000000..93c9d9f309 --- /dev/null +++ b/modules/build/src/main/scala/scala/build/postprocessing/ByteCodePostProcessor.scala @@ -0,0 +1,14 @@ +package scala.build.postprocessing + +import scala.build.{GeneratedSource, Logger} + +case object ByteCodePostProcessor extends PostProcessor { + def postProcess( + generatedSources: Seq[GeneratedSource], + mappings: Map[String, (String, Int)], + workspace: os.Path, + output: os.Path, + logger: Logger + ): Unit = + AsmPositionUpdater.postProcess(mappings, output, logger) +} diff --git a/modules/build/src/main/scala/scala/build/internal/LineConversion.scala b/modules/build/src/main/scala/scala/build/postprocessing/LineConversion.scala similarity index 96% rename from modules/build/src/main/scala/scala/build/internal/LineConversion.scala rename to modules/build/src/main/scala/scala/build/postprocessing/LineConversion.scala index 974b5cf302..e279eadbd1 100644 --- a/modules/build/src/main/scala/scala/build/internal/LineConversion.scala +++ b/modules/build/src/main/scala/scala/build/postprocessing/LineConversion.scala @@ -1,4 +1,4 @@ -package scala.build.internal +package scala.build.postprocessing object LineConversion { diff --git a/modules/build/src/main/scala/scala/build/postprocessing/PostProcessor.scala b/modules/build/src/main/scala/scala/build/postprocessing/PostProcessor.scala new file mode 100644 index 0000000000..a437efbf83 --- /dev/null +++ b/modules/build/src/main/scala/scala/build/postprocessing/PostProcessor.scala @@ -0,0 +1,13 @@ +package scala.build.postprocessing + +import scala.build.{GeneratedSource, Logger} + +trait PostProcessor { + def postProcess( + generatedSources: Seq[GeneratedSource], + mappings: Map[String, (String, Int)], + workspace: os.Path, + output: os.Path, + logger: Logger + ): Unit +} diff --git a/modules/build/src/main/scala/scala/build/postprocessing/SemanticDbPostProcessor.scala b/modules/build/src/main/scala/scala/build/postprocessing/SemanticDbPostProcessor.scala new file mode 100644 index 0000000000..9f167583cd --- /dev/null +++ b/modules/build/src/main/scala/scala/build/postprocessing/SemanticDbPostProcessor.scala @@ -0,0 +1,69 @@ +package scala.build.postprocessing + +import java.nio.file.FileSystemException + +import scala.annotation.tailrec +import scala.build.{GeneratedSource, Logger} + +case object SemanticDbPostProcessor extends PostProcessor { + def postProcess( + generatedSources: Seq[GeneratedSource], + mappings: Map[String, (String, Int)], + workspace: os.Path, + output: os.Path, + logger: Logger + ): Unit = { + logger.debug("Moving semantic DBs around") + val semDbRoot = output / "META-INF" / "semanticdb" + for (source <- generatedSources; originalSource <- source.reportingPath) { + val fromSourceRoot = source.generated.relativeTo(workspace) + val actual = originalSource.relativeTo(workspace) + + val semDbSubPath = { + val dirSegments = fromSourceRoot.segments.dropRight(1) + os.sub / dirSegments / s"${fromSourceRoot.last}.semanticdb" + } + val semDbFile = semDbRoot / semDbSubPath + if (os.exists(semDbFile)) { + val finalSemDbFile = { + val dirSegments = actual.segments.dropRight(1) + semDbRoot / dirSegments / s"${actual.last}.semanticdb" + } + SemanticdbProcessor.postProcess( + os.read(originalSource), + originalSource.relativeTo(workspace), + None, + if (source.topWrapperLen == 0) n => Some(n) + else + LineConversion.scalaLineToScLine( + os.read(originalSource), + os.read(source.generated), + source.topWrapperLen + ), + semDbFile, + finalSemDbFile + ) + try os.remove(semDbFile) + catch { + case ex: FileSystemException => + logger.debug(s"Ignoring $ex while removing $semDbFile") + } + deleteSubPathIfEmpty(semDbRoot, semDbSubPath / os.up, logger) + } + } + } + + @tailrec + private def deleteSubPathIfEmpty(base: os.Path, subPath: os.SubPath, logger: Logger): Unit = + if (subPath.segments.nonEmpty) { + val p = base / subPath + if (os.isDir(p) && os.list.stream(p).headOption.isEmpty) { + try os.remove(p) + catch { + case e: FileSystemException => + logger.debug(s"Ignoring $e while cleaning up $p") + } + deleteSubPathIfEmpty(base, subPath / os.up, logger) + } + } +} diff --git a/modules/build/src/main/scala/scala/build/internal/SemanticdbProcessor.scala b/modules/build/src/main/scala/scala/build/postprocessing/SemanticdbProcessor.scala similarity index 99% rename from modules/build/src/main/scala/scala/build/internal/SemanticdbProcessor.scala rename to modules/build/src/main/scala/scala/build/postprocessing/SemanticdbProcessor.scala index 37189bf1fc..2c4c1eb0d0 100644 --- a/modules/build/src/main/scala/scala/build/internal/SemanticdbProcessor.scala +++ b/modules/build/src/main/scala/scala/build/postprocessing/SemanticdbProcessor.scala @@ -1,6 +1,6 @@ // adapted from https://github.com/com-lihaoyi/Ammonite/blob/2da846d2313f1e12e812802babf9c69005f5d44a/amm/interp/src/main/scala/ammonite/interp/script/SemanticdbProcessor.scala -package scala.build.internal +package scala.build.postprocessing import java.math.BigInteger import java.nio.charset.StandardCharsets diff --git a/modules/build/src/main/scala/scala/build/postprocessing/TastyPostProcessor.scala b/modules/build/src/main/scala/scala/build/postprocessing/TastyPostProcessor.scala new file mode 100644 index 0000000000..93d144e924 --- /dev/null +++ b/modules/build/src/main/scala/scala/build/postprocessing/TastyPostProcessor.scala @@ -0,0 +1,53 @@ +package scala.build.postprocessing + +import scala.build.{GeneratedSource, Logger} +import scala.build.tastylib.TastyData + +case object TastyPostProcessor extends PostProcessor { + def postProcess( + generatedSources: Seq[GeneratedSource], + mappings: Map[String, (String, Int)], + workspace: os.Path, + output: os.Path, + logger: Logger + ): Unit = { + + val updatedPaths = generatedSources + .flatMap { source => + source.reportingPath.toOption.toSeq.map { originalSource => + val fromSourceRoot = source.generated.relativeTo(workspace) + val actual = originalSource.relativeTo(workspace) + fromSourceRoot.toString -> actual.toString + } + } + .toMap + + if (updatedPaths.nonEmpty) + os.walk(output) + .filter(os.isFile(_)) + .filter(_.last.endsWith(".tasty")) // make that case-insensitive just in case? + .foreach { f => + logger.debug(s"Reading TASTy file $f") + val content = os.read.bytes(f) + val data = TastyData.read(content) + logger.debug(s"Parsed TASTy file $f") + var updatedOne = false + val updatedData = data.mapNames { n => + updatedPaths.get(n) match { + case Some(newName) => + updatedOne = true + newName + case None => + n + } + } + if (updatedOne) { + logger.debug( + s"Overwriting ${if (f.startsWith(os.pwd)) f.relativeTo(os.pwd) else f}" + ) + val updatedContent = TastyData.write(updatedData) + os.write.over(f, updatedContent) + } + } + } +}