From 2425ca4950f766df8db443fe7a9f64d74d354113 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Wed, 21 Oct 2020 15:41:23 +0200 Subject: [PATCH 1/3] handle fake positions in absoluteSourceMapper --- main/src/main/scala/sbt/Defaults.scala | 31 +++++++++++++++++--------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 591169545..97306ae5e 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -21,6 +21,7 @@ import org.apache.logging.log4j.core.{ Appender => XAppender } import org.scalasbt.ipcsocket.Win32SecurityLevel import sbt.Def.{ Initialize, ScopedKey, Setting, SettingsDefinition } import sbt.Keys._ +import sbt.OptionSyntax._ import sbt.Project.{ inConfig, inScope, @@ -91,6 +92,7 @@ import xsbti.{ FileConverter, Position } import scala.collection.immutable.ListMap import scala.concurrent.duration._ +import scala.util.Try import scala.util.control.NonFatal import scala.xml.NodeSeq @@ -415,7 +417,7 @@ object Defaults extends BuildCommon { sourcePositionMappers ++= { val fc = fileConverter.value if (reportAbsolutePath.value) { - List(toAbsoluteSourceMapper(fc)) + List(toAbsoluteSourceMapper(fc) _) } else Nil }, // The virtual file value cache needs to be global or sbt will run out of direct byte buffer memory. @@ -464,13 +466,21 @@ object Defaults extends BuildCommon { }, ) - private[sbt] def toAbsoluteSourceMapper(fc: FileConverter): Position => Option[Position] = { - pos => - val newPath: Optional[String] = pos.sourcePath - .map { id => - fc.toPath(VirtualFileRef.of(id)).toAbsolutePath.toString - } - Some( + private[sbt] def toAbsoluteSourceMapper(fc: FileConverter)(pos: Position): Option[Position] = { + def isValid(path: String): Boolean = { + Try(Paths.get(path)).map(_ => true).getOrElse(false) + } + + val newPath: Option[String] = pos + .sourcePath() + .asScala + .filter(isValid) + .map { path => + fc.toPath(VirtualFileRef.of(path)).toAbsolutePath.toString + } + + newPath + .map { path => new Position { override def line(): Optional[Integer] = pos.line() @@ -482,11 +492,12 @@ object Defaults extends BuildCommon { override def pointerSpace(): Optional[String] = pos.pointerSpace() - override def sourcePath(): Optional[String] = newPath + override def sourcePath(): Optional[String] = Optional.of(path) override def sourceFile(): Optional[File] = pos.sourceFile() } - ) + } + .orElse(Some(pos)) } // csrCacheDirectory is scoped to ThisBuild to allow customization. From d51057db4f8ecc1a0c272801e2bfe8aa5fb685a5 Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 22 Oct 2020 12:22:01 +0200 Subject: [PATCH 2/3] Add tests on sourcePositionMappers --- .../sbt-test/reporter/source-mapper/build.sbt | 46 +++++++++++++++++++ .../source-mapper/src/main/scala/Foo.scala | 0 sbt/src/sbt-test/reporter/source-mapper/test | 2 + 3 files changed, 48 insertions(+) create mode 100644 sbt/src/sbt-test/reporter/source-mapper/build.sbt create mode 100644 sbt/src/sbt-test/reporter/source-mapper/src/main/scala/Foo.scala create mode 100644 sbt/src/sbt-test/reporter/source-mapper/test diff --git a/sbt/src/sbt-test/reporter/source-mapper/build.sbt b/sbt/src/sbt-test/reporter/source-mapper/build.sbt new file mode 100644 index 000000000..3ca4753ed --- /dev/null +++ b/sbt/src/sbt-test/reporter/source-mapper/build.sbt @@ -0,0 +1,46 @@ +import java.util.Optional +import xsbti.Position + +val assertAbsolutePathConversion = taskKey[Unit]("checks source mappers convert to absolute path") + +val assertHandleFakePos = taskKey[Unit]("checks source mappers handle fake position") + +assertAbsolutePathConversion := { + val converter = fileConverter.value + val source = (Compile/sources).value.head + val position = newPosition(converter.toVirtualFile(source.toPath).id, source) + val mappedPos = sourcePositionMappers.value + .foldLeft(Option(position)) { + case (pos, mapper) => pos.flatMap(mapper) + } + assert { + mappedPos.get.sourcePath.asScala.contains(source.getAbsolutePath) + } +} + +assertHandleFakePos := { + val position = newPosition("", new File("")) + val mappedPos = sourcePositionMappers.value + .foldLeft(Option(position)) { + case (pos, mapper) => pos.flatMap(mapper) + } + assert { + mappedPos.get.sourcePath.asScala.get.contains("") + } +} + +def newPosition(path: String, file: File): Position = new Position { + override def line(): Optional[Integer] = Optional.empty() + + override def lineContent() = "" + + override def offset(): Optional[Integer] = Optional.empty() + + override def pointer(): Optional[Integer] = Optional.empty() + + override def pointerSpace(): Optional[String] = Optional.empty() + + override def sourcePath(): Optional[String] = Optional.of(path) + + override def sourceFile(): Optional[File] = Optional.of(file) +} \ No newline at end of file diff --git a/sbt/src/sbt-test/reporter/source-mapper/src/main/scala/Foo.scala b/sbt/src/sbt-test/reporter/source-mapper/src/main/scala/Foo.scala new file mode 100644 index 000000000..e69de29bb diff --git a/sbt/src/sbt-test/reporter/source-mapper/test b/sbt/src/sbt-test/reporter/source-mapper/test new file mode 100644 index 000000000..ced01bedc --- /dev/null +++ b/sbt/src/sbt-test/reporter/source-mapper/test @@ -0,0 +1,2 @@ +> assertAbsolutePathConversion +> assertHandleFakePos \ No newline at end of file From e4b93182baaf1cb296cbcf38817742c8691d53ff Mon Sep 17 00:00:00 2001 From: Adrien Piquerez Date: Thu, 22 Oct 2020 13:28:53 +0200 Subject: [PATCH 3/3] Test Source Mapper on Windows --- .appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.appveyor.yml b/.appveyor.yml index c7fbdcf8b..b068a53f7 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -157,4 +157,4 @@ for: test_script: # The server tests often fail in CI when run together so just run a single test to ensure # that the thin client works on windows - - sbt "-Dsbt.io.virtual=false" "scripted actions/* classloader-cache/* nio/* watch/*" "serverTestProj/testOnly testpkg.ClientTest" + - sbt "-Dsbt.io.virtual=false" "scripted actions/* reporter/source-mapper classloader-cache/* nio/* watch/*" "serverTestProj/testOnly testpkg.ClientTest"