Skip to content

Conversation

@lolgab
Copy link

@lolgab lolgab commented May 31, 2024

"buildTarget/wrappedSources" is a way for build tools to report wrapped Scala sources, which are sources that are wrapped with some text to make them valid Scala code.
This was introduced by scala-cli and metals as a bespoke extension to the build-server-protocol.
This adds it to the official protocol.

"buildTarget/wrappedSources" is a way for build tools to report
wrapped Scala sources, which are sources that are wrapped with
some text to make them valid Scala code.
This was introduced by scala-cli and metals as a bespoke extension
to the build-server-protocol.
This adds it to the official protocol.
* supported or not.
*/
@JsonRequest("buildTarget/wrappedSources")
CompletableFuture<WrappedSourcesResult> buildTargetWrappedSources(WrappedSourcesParams params);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we actually have a ScriptBuildServer as a separate thing?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why should we?
It's a capability that can be declared as supported via normal capabilities. Also, nothing stops someone to write a script wrapper for java which does a similar thing to what scala-cli does.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure, I was just being cautious since we don't have too many server implementing this, but I guess it's totally fine if we add a capability

Copy link
Contributor

@lefou lefou May 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is probably no clear line to cut between an capability and an extension. They mostly differ in how they get enabled. And this story isn't completely written for modularity.

@lolgab What stops us to use the wrapperSources to use for Java files right away. Is there anything Scala specific?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lolgab What stops us to use the wrapperSources to use for Java files right away. Is there anything Scala specific?

I don't think anything stops us, but other than the javadoc maybe, there is nothing Scala specific in this PR, unless I'm wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great.

def buildTargetCompile(params: CompileParams): CompletableFuture[CompileResult] = ???
def buildTargetDependencySources(params: DependencySourcesParams): CompletableFuture[DependencySourcesResult] = ???
def buildTargetDependencyModules(params: DependencyModulesParams): CompletableFuture[DependencyModulesResult] = ???
def buildTargetInverseSources(params: InverseSourcesParams): CompletableFuture[InverseSourcesResult] = ???
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happened to buildTargetInverseSources here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ops, reverting

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added it back


/// The wrapped sources request is sent from the client to the server to query for
/// the list of build targets containing wrapped sources. Wrapped sources are script
/// sources that are wrapped by the build tool with some top and bottom wrappers.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me as uninvolved person the use case is not really clear. Can you explain a bit more what this means and why it warrants a separate request?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basically scala scripts are not "real" scala code, they are text files that can become Scala code only after wrapping them with some code to make them real.

For example:

println("Hello world!")

doesn't compile in Scala.

But if you wrap the code with:

val top = s"""object main {
  def main(args: Array[String]): Unit = {
"""

and

val bottom = """  }
}
"""

it becomes valid Scala code.

Since it's not valid Scala code, IDEs can't parse them correctly, unless you tell them about this processing. scala-cli created this extension to have IDE supports on ammonite and scala-cli scripts.

Of course what I said should be better summarized and added to the documentation as javadcod and smithy comment.

why it warrants a separate request?

This I don't know. I'm just following what's there since this is already used by scala-cli as a bespoke extension. If this can be achieved in a better way, let me know, I'm happy to update the PR.
I'm not very familiar with the BSP protocol other than some bugfixes I did in the Mill's implementation.

Comment on lines +85 to +100
public Boolean getWrappedSourcesProvider() {
return this.wrappedSourcesProvider;
}

public void setWrappedSourcesProvider(final Boolean wrappedSourcesProvider) {
this.wrappedSourcesProvider = wrappedSourcesProvider;
}

public Boolean getWrappedSourcesProvider() {
return this.wrappedSourcesProvider;
}

public void setWrappedSourcesProvider(final Boolean wrappedSourcesProvider) {
this.wrappedSourcesProvider = wrappedSourcesProvider;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These duplicate entries don't look right.

Copy link
Contributor

@lefou lefou Jun 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, boolean would be the better type here, since it can't be null.


private Boolean inverseSourcesProvider;

private Boolean wrappedSourcesProvider;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This value is uninitialized, like all the others. Better use boolean for such simple on/off settings.

Comment on lines +966 to +975
structure WrappedSourceItem {
@required
uri: String
@required
generatedUri: String
@required
topWrapper: String
@required
bottomWrapper: String
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need to add a new request for this? Or should we consider "wrapped sources" as part of buildTarget/sources ?

I would rather go with the second option, and add the optional topWrapper, bottomWrapper to the SourceItem:

structure SourceItem {
  @required  
  uri: URI;
  @required   
  kind: SourceItemKind;
  @required  
  generated: boolean;
  // optional
  topWrapper: String;
  // optional
  bottomWrapper: String
}

Or even better:

structure SourceItem {
  @required  
  uri: URI;
  @required   
  kind: SourceItemKind;
  @required  
  generated: boolean;
  // optional
  wrapper: SourceWrapper;
}

structure SourceWrapper {
  @required  
  prefix: String;
  @required   
  suffix: String;
}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need to add generatedUri to have the link, right?

Copy link
Member

@adpi2 adpi2 Jun 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yes I missed that part.

So it seems a "wrapped source" is the source of a generated source file. And we want to have the support of our IDE in it because it looks a lot like a Scala file.

But this seems to be a special case of something more general which are the source files of source generation. In this case it is an sc file that generates a Scala file, but it could also be a proto, json, smithy or twirl file that generates Scala code.

So can we generalize that request? Something like this maybe:

@jsonRequest("buildTarget/sourceGenerationSources")
operation BuildTargetSourceGenerationSources {
    input: SourceGenerationSourcesParams
    output: SourceGenerationSourcesResult
}

structure SourceGenerationSourcesItem {
  @required
  uri: String
  @required
  generatedUri: String
  // optional
  data: SourceGenerationSourcesItemData
}

// in the scala extension
@dataKind(kind: "wrapped-scala-source", extends: [SourceGenerationSourcesItemData])
structure WrappedScalaSource {
    @required
    prefix: String
   @required
    suffix: String
}

@lefou
Copy link
Contributor

lefou commented Oct 7, 2024

So, what's the status of this PR? There are some unaddressed comments, but besides that, it would be nice to get some general feedback (of someone with merge rights, which I don't have) regarding the direction. Will it get merged eventually? It's an obviously needed feature for tools like Mill or Scala-CLI. It doesn't break compatibility. So it shouldn't really stay for so long in the review queue.

@jastice
Copy link
Member

jastice commented Oct 8, 2024

Sorry for the dragging, it dropped off my radar.
So IMHO it seems like a very particular solution and will increase client and server complexity somewhat. On the other hand, a concrete problem solved now is better than a theoretical problem solved with a theoretical change where we don't know how it will look. So from my perspective it's ok to merge it as "unstable" or "experimental" extension. I would prefer to keep it outside the root spec to not make the apparent complexity there even higher.

@adpi2
Copy link
Member

adpi2 commented Oct 8, 2024

On the other hand, a concrete problem solved now is better than a theoretical problem solved with a theoretical change where we don't know how it will look. So from my perspective it's ok to merge it as "unstable" or "experimental" extension. I would prefer to keep it outside the root spec to not make the apparent complexity there even higher.

👍 This looks like a compromise.

@lolgab
Copy link
Author

lolgab commented Oct 8, 2024

For the Mill use-case I managed to workaround the missing protocol message by parsing the generated sources and get the necessary data from them. Still, Metals doesn't work as expected.
My plan is first to make Metals work. Once both scala-cli and Mill work correctly, we can think about generalizing the protocol and apply the new message to Scala-cli, Mill and Metals. Until that moment I think this can wait.

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.

5 participants