Skip to content

Conversation

github-samuel-clarenc
Copy link
Contributor

@github-samuel-clarenc github-samuel-clarenc commented Jun 17, 2021

Fixes #6550

This PR adds an implementation for BSP resource request

When sending the following command to sbt -bsp :

{ "jsonrpc": "2.0", "id": 1, "params": {"targets":[{"uri":"file:/PROJECT_PATH/#module/Compile"}]}, "method": "buildTarget/resources" }

We should now get the following response :

{"jsonrpc":"2.0","id":1,"result":{"items":[{"target":{"uri":"file:/PROJECT_PATH/#module/Compile"},"resources":["file:PROJECT_PATH/module/src/main/resources/"]}]}}

@github-samuel-clarenc
Copy link
Contributor Author

This PR was checked on a sample project : the buildTarget/resources is successfully called during the project import and Intellij Idea can rightly define the resources folders :
image

@adpi2
Copy link
Member

adpi2 commented Jun 18, 2021

I created an example project to show that in some case, the build client lacks some information about the resource file.

The build file is:

val hello = project.in(file("."))
  .settings(
    scalaVersion := "2.13.6",
    Compile / resourceGenerators += Def.task {
      val greeting = (Compile / resourceManaged).value / "assets" / "greeting.txt"
      IO.write(greeting, "Hello, World!")
      Seq(greeting)
    }
  )

This generates a assets/greeting.txt resource file.

The main method read the content of that resource and prints it:

package hello

import scala.io.Source

object Main extends App {
  Source.fromResource("assets/greeting.txt", getClass.getClassLoader)
    .getLines()
    .foreach(println)
}

Note that the resource is assets/greeting.txt and not greeting.txt.

Running the main to check that it works as expected:

sbt:hello> run
[info] running hello.Main 
Hello, World!
[success] Total time: 0 s, completed Jun 18, 2021 10:45:21 AM

When importing the project in IntelliJ the buildTarget/resources response is:

{
  "items": [
    {
      "target": {
        "uri": "file:/home/piquerez/sbt/sbt-6552/#hello/Test"
      },
      "resources": [
        "file:/home/piquerez/sbt/sbt-6552/src/test/resources"
      ]
    },
    {
      "target": {
        "uri": "file:/home/piquerez/sbt/sbt-6552/#hello/Compile"
      },
      "resources": [
        "file:/home/piquerez/sbt/sbt-6552/src/main/resources",
        "file:/home/piquerez/sbt/sbt-6552/target/scala-2.13/resource_managed/main/assets/greeting.txt"
      ]
    }
  ]
}

Here Intellij does not know that the resource file is supposed to be assets/greeting.txt rather than greeting.txt. Or, in other words, that the resource folder should be file:/home/piquerez/sbt/sbt-6552/target/scala-2.13/resource_managed/main/ instead of file:/home/piquerez/sbt/sbt-6552/target/scala-2.13/resource_managed/main/assets/.

Here IntelliJ assumes that the resource folder is file:/home/piquerez/sbt/sbt-6552/target/scala-2.13/resource_managed/main/assets/ which is wrong:
image

Reproduction repo: https://github.com/adpi2/sbt-6552

@adpi2
Copy link
Member

adpi2 commented Jun 18, 2021

I think the solution for now is to send back the managed resource folders rather than the managed resource files:

val id = bspTargetIdentifier.value 
val unmanagedDirs = unmanagedResourceDirectories.value
val managedDirs = managedResourceDirectories.value
ResourcesItem(id, unmanagedDirs.toVector.map(_.toURI) ++ managedDirs.toVector.map(_.toURI))

Or more simply

val id = bspTargetIdentifier.value 
val resourcDirs = resourceDirectories.value
ResourcesItem(id, resourcDirs.toVector.map(_.toURI))

One drawback of this solution is that it does not trigger the resource generation (of the managed resources). We can handle that with:

val id = bspTargetIdentifier.value 
val resourcDirs = resourceDirectories.value
// trigger resource generation
val _ = managedResources.value
ResourcesItem(id, resourcDirs.toVector.map(_.toURI))

@github-samuel-clarenc
Copy link
Contributor Author

github-samuel-clarenc commented Jun 21, 2021

You're right, the main problem comes from the lack of resources kind, like we have with sources

I also tried with BSP importing a project with a src/main/resources but no src/test/resources : I end up with the test folder itself being marked as a resource !
image

I think it comes from BspResolverLogic that creates either a resource from a file or its own parent

Edit : I pushed a modification that adds an extra ending slash when missing on resource directories URIs.

@eed3si9n
Copy link
Member

Thanks for the contribution. I'll trust @adpi2's review and hit merge since it's been approved.

@eed3si9n eed3si9n merged commit 9274a3e into sbt:develop Jun 21, 2021
@eed3si9n eed3si9n added this to the 1.5.5 milestone Jun 21, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[BSP] Implement buildTarget/resources
3 participants