diff --git a/modules/build/src/main/scala/scala/build/CrossSources.scala b/modules/build/src/main/scala/scala/build/CrossSources.scala index f9c917d49b..c7e731752a 100644 --- a/modules/build/src/main/scala/scala/build/CrossSources.scala +++ b/modules/build/src/main/scala/scala/build/CrossSources.scala @@ -273,8 +273,19 @@ object CrossSources { ) }).flatten + val resourceDirectoriesFromDirectives = { + val resourceDirsFromCli = + allInputs.elements.flatMap { case rd: ResourceDirectory => Some(rd.path); case _ => None } + val resourceDirsFromBuildOptions: Seq[os.Path] = + buildOptions.flatMap(_.value.classPathOptions.resourcesDir).distinct + resourceDirsFromBuildOptions + .filter(!resourceDirsFromCli.contains(_)) + .map(ResourceDirectory(_)) + } + val finalInputs = allInputs.add(resourceDirectoriesFromDirectives) + val defaultMainElemPath = for { - defaultMainElem <- allInputs.defaultMainClassElement + defaultMainElem <- finalInputs.defaultMainClassElement } yield defaultMainElem.path val pathsWithDirectivePositions @@ -284,7 +295,7 @@ object CrossSources { val baseReqs0 = baseReqs(d.scopePath) WithBuildRequirements( d.requirements.fold(baseReqs0)(_ orElse baseReqs0), - (d.path, d.path.relativeTo(allInputs.workspace)) + (d.path, d.path.relativeTo(finalInputs.workspace)) ) -> d.directivesPositions } val inMemoryWithDirectivePositions @@ -309,7 +320,7 @@ object CrossSources { } val resourceDirs: Seq[WithBuildRequirements[os.Path]] = - resolveResourceDirs(allInputs, preprocessedSources) + resolveResourceDirs(finalInputs, preprocessedSources) lazy val allPathsWithDirectivesByScope: Map[Scope, Seq[(os.Path, Position.File)]] = (pathsWithDirectivePositions ++ inMemoryWithDirectivePositions ++ unwrappedScriptsWithDirectivePositions) @@ -362,17 +373,15 @@ object CrossSources { val paths = pathsWithDirectivePositions.map(_._1) val inMemory = inMemoryWithDirectivePositions.map(_._1) val unwrappedScripts = unwrappedScriptsWithDirectivePositions.map(_._1) - ( - CrossSources( - paths, - inMemory, - defaultMainElemPath, - resourceDirs, - buildOptions, - unwrappedScripts - ), - allInputs + val crossSources = CrossSources( + paths, + inMemory, + defaultMainElemPath, + resourceDirs, + buildOptions, + unwrappedScripts ) + crossSources -> finalInputs } /** @return diff --git a/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala b/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala index 61ccd1e5ed..47423da68c 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/RunTestDefinitions.scala @@ -560,8 +560,10 @@ abstract class RunTestDefinitions forbiddenDirTest() } - private def resourcesInputs(directive: String = "") = { - val resourceContent = "Hello from resources" + protected def resourcesInputs( + directive: String = "", + resourceContent: String = "Hello from resources" + ): TestInputs = TestInputs( os.rel / "src" / "proj" / "resources" / "test" / "data" -> resourceContent, os.rel / "src" / "proj" / "Test.scala" -> @@ -571,24 +573,30 @@ abstract class RunTestDefinitions | val cl = Thread.currentThread().getContextClassLoader | val is = cl.getResourceAsStream("test/data") | val content = scala.io.Source.fromInputStream(is)(scala.io.Codec.UTF8).mkString - | assert(content == "$resourceContent") + | println(content) | } |} |""".stripMargin ) - } - test("resources") { - resourcesInputs().fromRoot { root => - os.proc(TestUtil.cli, "run", "src", "--resource-dirs", "./src/proj/resources").call(cwd = - root - ) + test("resources via command line") { + val expectedMessage = "hello" + resourcesInputs(resourceContent = expectedMessage).fromRoot { root => + val res = os.proc(TestUtil.cli, "run", "src", "--resource-dirs", "./src/proj/resources") + .call(cwd = root) + expect(res.out.trim() == expectedMessage) } } test("resources via directive") { - resourcesInputs("//> using resourceDirs \"./resources\"").fromRoot { root => - os.proc(TestUtil.cli, "run", ".").call(cwd = root) - } + val expectedMessage = "hello" + resourcesInputs( + directive = "//> using resourceDirs \"./resources\"", + resourceContent = expectedMessage + ) + .fromRoot { root => + val res = os.proc(TestUtil.cli, "run", ".").call(cwd = root) + expect(res.out.trim() == expectedMessage) + } } def argsAsIsTest(): Unit = { diff --git a/modules/integration/src/test/scala/scala/cli/integration/RunWithWatchTestDefinitions.scala b/modules/integration/src/test/scala/scala/cli/integration/RunWithWatchTestDefinitions.scala index 6021aa3e9e..5034c06932 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/RunWithWatchTestDefinitions.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/RunWithWatchTestDefinitions.scala @@ -42,6 +42,18 @@ trait RunWithWatchTestDefinitions { _: RunTestDefinitions => TestInputs(inputPath -> code(expectedMessage1)), code(expectedMessage2) ) + }, { + val inputPath = os.rel / "Main.java" + def code(message: String) = s"""public class Main { + | public static void main(String[] args) { + | System.out.println("$message"); + | } + |}""".stripMargin + ( + inputPath, + TestInputs(inputPath -> code(expectedMessage1)), + code(expectedMessage2) + ) }, { val inputPath = os.rel / "markdown.md" def code(message: String) = @@ -296,4 +308,34 @@ trait RunWithWatchTestDefinitions { _: RunTestDefinitions => } } } + + for { + useDirective <- Seq(false, true) + // TODO make this pass reliably on Mac CI + if !Properties.isMac || !TestUtil.isCI + directive = if (useDirective) "//> using resourceDirs ./resources" else "" + resourceOptions = if (useDirective) Nil else Seq("--resource-dirs", "./src/proj/resources") + title = if (useDirective) "directive" else "command line" + } test(s"resources via $title with --watch") { + val expectedMessage1 = "Hello" + val expectedMessage2 = "world" + resourcesInputs(directive = directive, resourceContent = expectedMessage1) + .fromRoot { root => + TestUtil.withProcessWatching( + os.proc(TestUtil.cli, "run", "src", "--watch", resourceOptions, extraOptions) + .spawn(cwd = root, stderr = os.Pipe) + ) { (proc, timeout, ec) => + val output1 = TestUtil.readLine(proc.stdout, ec, timeout) + expect(output1 == expectedMessage1) + proc.printStderrUntilRerun(timeout)(ec) + val Some((resourcePath, newResourceContent)) = + resourcesInputs(directive = directive, resourceContent = expectedMessage2) + .files + .find(_._1.toString.contains("resources")) + os.write.over(root / resourcePath, newResourceContent) + val output2 = TestUtil.readLine(proc.stdout, ec, timeout) + expect(output2 == expectedMessage2) + } + } + } }