Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 9 additions & 107 deletions modules/build/src/main/scala/scala/build/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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,
Expand All @@ -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] =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package scala.build.internal
package scala.build.postprocessing

import org.objectweb.asm

Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package scala.build.internal
package scala.build.postprocessing

object LineConversion {

Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
}