-
-
Notifications
You must be signed in to change notification settings - Fork 289
Use a provider for jars2labels #534
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
JarsToLabelsInfo = provider(fields = [ | ||
"jars_to_labels", # dict of path of a jar to a label | ||
]) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,7 @@ | ||
load("@io_bazel_rules_scala//scala:jars_to_labels.bzl", "JarsToLabelsInfo") | ||
|
||
_empty_jars2labels = JarsToLabelsInfo(jars_to_labels = {}) | ||
|
||
def write_manifest(ctx): | ||
main_class = getattr(ctx.attr, "main_class", None) | ||
write_manifest_file(ctx.actions, ctx.outputs.manifest, main_class) | ||
|
@@ -42,7 +46,7 @@ def _collect_jars_when_dependency_analyzer_is_off(dep_targets): | |
return struct( | ||
compile_jars = depset(transitive = compile_jars), | ||
transitive_runtime_jars = depset(transitive = runtime_jars), | ||
jars2labels = {}, | ||
jars2labels = _empty_jars2labels, | ||
transitive_compile_jars = depset()) | ||
|
||
def _collect_jars_when_dependency_analyzer_is_on(dep_targets): | ||
|
@@ -62,6 +66,7 @@ def _collect_jars_when_dependency_analyzer_is_on(dep_targets): | |
|
||
compile_jars.append(current_dep_compile_jars) | ||
transitive_compile_jars.append(current_dep_transitive_compile_jars) | ||
|
||
add_labels_of_jars_to(jars2labels, dep_target, | ||
current_dep_transitive_compile_jars.to_list(), | ||
current_dep_compile_jars.to_list()) | ||
|
@@ -71,7 +76,7 @@ def _collect_jars_when_dependency_analyzer_is_on(dep_targets): | |
return struct( | ||
compile_jars = depset(transitive = compile_jars), | ||
transitive_runtime_jars = depset(transitive = runtime_jars), | ||
jars2labels = jars2labels, | ||
jars2labels = JarsToLabelsInfo(jars_to_labels = jars2labels), | ||
transitive_compile_jars = depset(transitive = transitive_compile_jars)) | ||
|
||
# When import mavan_jar's for scala macros we have to use the jar:file requirement | ||
|
@@ -91,33 +96,23 @@ def filter_not_sources(deps): | |
|
||
def add_labels_of_jars_to(jars2labels, dependency, all_jars, direct_jars): | ||
for jar in direct_jars: | ||
_add_label_of_direct_jar_to(jars2labels, dependency, jar) | ||
jars2labels[jar.path] = dependency.label | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why did you remove the private methods? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so, I found it pretty hard to follow these very tiny methods. They were generally only called one time, and they didn't encapsulate much: they were just rewriting in english what the function was doing. I think we ideally want some logical chunk, which isn't huge, maybe 5-10 lines, or something that is called many times. Here we often had 1 call, and really a lot of methods below the logical grouping, in my view. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm, so I subscribe to a different style. I factor much less how much it's called and the size and much more the readability of the story.
How should we proceed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am kind of liberal in what I accept, so I tend to accept code written by others as long as I don't have strong objections, but at the same time, I have super limited time and for some, probably foolish, reason I have been trying to get this modernization done. I'd rather not sink more time in to write the code in a style I don't agree with, for code we don't use, if no one on your team has the time to help us move forward on this. I would say: let's merge this it is a 80 line change that retires the second to last custom provider. I have sunk a ton of time into this, and Stripe does not even use it at all. If you want to structure it differently, I don't mind, you can follow up with another PR as long as you keep the provider around. I don't think it is really fair for one of us to task the other to implement the style they prefer. The one doing the work should get the lion's share of the say on style questions we don't agree about. @ianoc @andyscott do you have any views on this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good. One more point I'd love for us to be able to agree on is that if we're going to change a style we should probably say up front in case another contributor feels strongly about it (and so avoid rework). WDYT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To be concrete: def _add_label_of_direct_jar_to(jars2labels, dependency, jar):
jars2labels[jar.path] = dependency.label this is not a helpful method in my view. If a reader cannot understand the 1 line you have replaced with a string description, I don't think the strings are going to help. A comment is possibly useful if there is something tricky going on, but using a dict to point to what a jar came from couldn't be a ton clearer. If we take this to the extreme, every line of code is replaced with a function that names what it is doing: def increment_int(x, y):
return x + y
def lookup_from_dict(d, k):
return d[k] etc... |
||
for jar in all_jars: | ||
_add_label_of_indirect_jar_to(jars2labels, dependency, jar) | ||
|
||
def _add_label_of_direct_jar_to(jars2labels, dependency, jar): | ||
jars2labels[jar.path] = dependency.label | ||
|
||
def _add_label_of_indirect_jar_to(jars2labels, dependency, jar): | ||
if _label_already_exists(jars2labels, jar): | ||
return | ||
|
||
# skylark exposes only labels of direct dependencies. | ||
# to get labels of indirect dependencies we collect them from the providers transitively | ||
if _provider_of_dependency_contains_label_of(dependency, jar): | ||
jars2labels[jar.path] = dependency.jars_to_labels[jar.path] | ||
path = jar.path | ||
if path not in jars2labels: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this seems to introduce order dependency: if you find an unknown provider first, but later it is seen as a direct dependency, you'll only see the unknown, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not for direct but if you find an unknown and then another sub graph finds it as direct and afterwards a third target depends on both of these then indeed it can miss the known label.
|
||
# skylark exposes only labels of direct dependencies. | ||
# to get labels of indirect dependencies we collect them from the providers transitively | ||
label = _provider_of_dependency_label_of(dependency, path) | ||
if label == None: | ||
label = "Unknown label of file {jar_path} which came from {dependency_label}".format( | ||
jar_path = path, dependency_label = dependency.label) | ||
jars2labels[path] = label | ||
|
||
def _provider_of_dependency_label_of(dependency, path): | ||
if JarsToLabelsInfo in dependency: | ||
return dependency[JarsToLabelsInfo].jars_to_labels.get(path) | ||
else: | ||
jars2labels[ | ||
jar. | ||
path] = "Unknown label of file {jar_path} which came from {dependency_label}".format( | ||
jar_path = jar.path, dependency_label = dependency.label) | ||
|
||
def _label_already_exists(jars2labels, jar): | ||
return jar.path in jars2labels | ||
|
||
def _provider_of_dependency_contains_label_of(dependency, jar): | ||
return hasattr(dependency, | ||
"jars_to_labels") and jar.path in dependency.jars_to_labels | ||
return None | ||
|
||
# TODO this seems to have limited value now that JavaInfo has everything | ||
def create_java_provider(scalaattr, transitive_compile_time_jars): | ||
|
Uh oh!
There was an error while loading. Please reload this page.
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.
Inlining this seems better for readability, IMHO. Is there a performance benefit to reusing the same empty provider instance?
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.
Well, I don't know, but I to me, I felt the opposite: it appeared clearer to me (here is an empty value) vs inlining
JarsToLabels(jars_to_labels = {})
which someone has to read an understand as an empty value.Next, it also seemed it could be faster.
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.
But if you would strongly prefer the change, I will make it. Please let me know.