-
-
Notifications
You must be signed in to change notification settings - Fork 286
Fix Intellij Bazel Plugin support for scrooge_scala_library rule #562
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix Intellij Bazel Plugin support for scrooge_scala_library rule #562
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add anything to the intellij test to make sure we don’t backslide here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
source_jar = scrooge_jar, | ||
deps = deps_java_info + implicit_deps, | ||
runtime_deps = deps_java_info + implicit_deps, | ||
exports = deps_java_info + implicit_deps, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
May I ask why do you export everything? Doesn’t sound like the right behavior (though I agree that it looks like the existing code does the same)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does seem odd. @johnynek: do you know if this is necessary?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@johnynek wdyt? As far as I'm concerned we can merge as is but just want to make sure this is indeed what you need
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment to the ticket (schemas don't have implementations that users control, so the data types are generally needed by downstream, more-over if any transitive schema changes you will need a recomputation in most cases).
We can revisit if this intuition is wrong.
runtime_deps = deps_java_info + implicit_deps, | ||
exports = deps_java_info + implicit_deps, | ||
output_jar = output, | ||
compile_jar = output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just making sure you intentionally don’t want ijar here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment on line 164:
# this only compiles scala, not the ijar, but we don't
# want the ijar for generated code anyway: any change
# in the thrift generally will change the interface and
# method bodies
twitter_scrooge/twitter_scrooge.bzl
Outdated
] | ||
|
||
return struct( | ||
scala = _create_scala_struct(ctx), # For IntelliJ support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We’re trying to kill this integration in favor of JavaInfo. Is there a specific issue this solves and which JavaInfo doesn’t solve?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, yes. In order to use JavaInfo
here, I need a way of setting multiple output jars on a JavaInfo
, but neither the JavaInfo
constructor nor the java_common.create_provider
allow me to do this.
Once this fix is released, we can ditch the scala
field and go back to just returning a JavaInfo
with multiple output jars.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good. WDYT about adding a TODO and an issue to track this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! Created #564 and added a todo comment.
@johnynek: A splendid idea: bazelbuild/intellij#366 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick feedback @ittaiz! Much appreciated!
twitter_scrooge/twitter_scrooge.bzl
Outdated
] | ||
|
||
return struct( | ||
scala = _create_scala_struct(ctx), # For IntelliJ support |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, yes. In order to use JavaInfo
here, I need a way of setting multiple output jars on a JavaInfo
, but neither the JavaInfo
constructor nor the java_common.create_provider
allow me to do this.
Once this fix is released, we can ditch the scala
field and go back to just returning a JavaInfo
with multiple output jars.
runtime_deps = deps_java_info + implicit_deps, | ||
exports = deps_java_info + implicit_deps, | ||
output_jar = output, | ||
compile_jar = output) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See this comment on line 164:
# this only compiles scala, not the ijar, but we don't
# want the ijar for generated code anyway: any change
# in the thrift generally will change the interface and
# method bodies
source_jar = scrooge_jar, | ||
deps = deps_java_info + implicit_deps, | ||
runtime_deps = deps_java_info + implicit_deps, | ||
exports = deps_java_info + implicit_deps, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That does seem odd. @johnynek: do you know if this is necessary?
Regarding exports, my thinking is: for schemas, all dependencies should are things that show up on the API: if schema foo depends on schema bar, the user of foo is going to need bar to use foo, pretty much 100% of the time. Requiring explicit dependencies, seems like just adding more toil. Secondly: the motivation for thin dependencies is so you can avoid recomputation, but when a schema changes, almost always the API changes, so you don't get to avoid a recomputation, so the motivation from a caching perspective also disappears. So, that's why I put the transitive dependencies into exports. |
@@ -314,6 +318,31 @@ scrooge_scala_library = rule( | |||
provides = [DefaultInfo, ScroogeInfo, JavaInfo], | |||
) | |||
|
|||
def _create_scala_struct(ctx): | |||
"""Create a scala provider in the shape expected by the IntelliJ bazel plugin.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we are transitively putting things here?
This part is confusing to me because it seems some jars will end up in many targets.
Why doesn't this work to just put class_jar
from the current target? Why do we need the transitive part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's transitive in the sense that it pulls jars from the scrooge_scala_library's deps. Is that what you mean? I'm not sure I understand the question. Let me explain my understanding and see if that clears it up or if I'm mistaken:
My understanding is, suppose we have some scrooge target:
scrooge_scala_library(
name = "my_scrooge",
exports = [":some_export"],
deps = [":thrift1", ":thrift2"]
)
The aspect will traverse the deps, call scrooge against each target's sources, produce a jar for each, and store a reference to those jars in each dep's ScroogeAspectInfo.java_info
. So the result is :thrift1
and :thrift2
have jars that I need to return to IJ stored in their ScroogeAspectInfo.java_info.outputs
.
This function gathers up all those jars by iterating through :thrift1
and :thrift2
, pulls the jars out of ScroogeAspectInfo.java_info.outputs
and puts them in a place IJ can find them.
It also gets the jars for :some_export
since those symbols might be used in the editor.
twitter_scrooge/twitter_scrooge.bzl
Outdated
"""Create a scala provider in the shape expected by the IntelliJ bazel plugin.""" | ||
output_jars = [] | ||
|
||
if ctx.attr.exports: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see why we want the exports here. The exports should be another target, so can't the intellij plugin see those? I don't even think we are using exports in scrooge anywhere internally.
Can we remove this part?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup I think you're right. Removed.
twitter_scrooge/twitter_scrooge.bzl
Outdated
source_jar = None, | ||
source_jars = [])) | ||
|
||
for dep in ctx.attr.deps: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, I guess this is correct, since the deps are actually the thrifts that we are going to trigger generation of, so pretending that this target created them, I guess is okay (rather than the aspect generating them).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having the aspects generate a Java/Scala provider is an interesting idea. I tried implementing this, but it doesn't seem like aspects support returning an old style struct provider. I tried returning a struct with a scala
field from the scrooge aspect, but it wasn't visible in the IJ plugin.
Once the java_common.merge
fix is released, the scrooge aspect could attach a JavaInfo with multiple outputs to the thrift_library
targets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
always a yak stack....
next year in Jerusalem.
Overview
This fixes intelliJ support for
scrooge_scala_library
targets using the new aspect based implementation (#524). Without this fix, symbol resolution and jump-to-def support does not work.Previously, the
scrooge_scala_library
rule would return ascala
field on its provider struct, which contained output jars (full path: scala -> outputs -> [].jars -> class_jar). This IJ plugin would inspect this field and collect the jars for IDE support.The new
scrooge_scala_library
does not return ascala
field, breaking IJ support. It does return aJavaInfo
provider, which the IJ plugin does pick up, but it lacks anoutputs
field. One seemingly straightforward solution would be to simply set theoutputs
field on the existingJavaInfo
provider. There are two reasons this doesn't work:JavaInfo
s need to be merged together, and the current implementation ofjava_common.merge
strips theoutputs
field. There is a fix forthcoming for this, but it's not landing until 0.16.0.JavaInfo
. TheJavaInfo
constructor only accepts one output jar andjava_common.create_provider
doesn't set theoutputs
field at all.The solution in this PR threads the output jars through and puts them in the
scala
field that the IJ plugin expects. Concretely, this means using theJavaInfo
constructor to setoutput_jar
explicitly, and going back to old style providers, where the rule implementation returns a struct rather than a list of providers.I believe this is an acceptable fix because once the
java_common.merge
fix is released in 0.16.0, thescala
field can be removed in favor of putting the jarsJavaInfo
s outputs, and we can go back to new-style providers (returning a list rather than a struct).Testing
Tests pass (
./test_all.sh
) and I've verified the fix works with the IJ plugin on our repos at Stripe.That said, this is my first bazel rules PR and would appreciate extra scrutiny, in particular in making sure I've constructed all the
JavaInfo
s correctly.