| """Bespoke rules_testing subject for the Java compilation action""" | |
| load("@rules_testing//lib:truth.bzl", "subjects") | |
| load("@rules_testing//lib:util.bzl", "TestingAspectInfo") | |
| def _new_javac_action_subject(env, target, output = None, desc = ""): | |
| target_subject = env.expect.that_target(target) | |
| if output: | |
| action_subject = target_subject.action_generating(output) | |
| else: | |
| action_subject = target_subject.action_named("Javac") | |
| self = struct( | |
| actual = action_subject.actual, | |
| parsed_flags = _parse_flags(action_subject.actual.argv), | |
| meta = target_subject.meta.derive( | |
| desc + ".Javac", | |
| format_str_kwargs = { | |
| "name": target.label.name, | |
| "package": target.label.package, | |
| "bin_path": target[TestingAspectInfo].bin_path, | |
| }, | |
| ), | |
| ) | |
| public = struct( | |
| direct_dependencies = lambda: _create_subject_for_flag("--direct_dependencies", self.parsed_flags, self.meta, default = []), | |
| deps_artifacts = lambda: _create_subject_for_flag("--deps_artifacts", self.parsed_flags, self.meta), | |
| javacopts = lambda: _create_subject_for_flag("--javacopts", self.parsed_flags, self.meta), | |
| jar = lambda: _create_subject_for_flag("-jar", self.parsed_flags, self.meta), | |
| # An unset --strict_java_deps is equivalent to "OFF". | |
| strict_java_deps = lambda: _create_subject_for_flag("--strict_java_deps", self.parsed_flags, self.meta, default = ["OFF"]).offset(0, factory = subjects.str), | |
| sources = lambda: _create_subject_for_flag("--sources", self.parsed_flags, self.meta), | |
| resources = lambda: _create_subject_for_flag("--resources", self.parsed_flags, self.meta), | |
| classpath = lambda: _create_subject_for_flag("--classpath", self.parsed_flags, self.meta), | |
| bootclasspath = lambda: _create_subject_for_flag("--bootclasspath", self.parsed_flags, self.meta), | |
| system = lambda: _create_subject_for_flag("--system", self.parsed_flags, self.meta), | |
| generated_sources_output = lambda: _create_subject_for_flag("--generated_sources_output", self.parsed_flags, self.meta), | |
| processorpath = lambda: _create_subject_for_flag("--processorpath", self.parsed_flags, self.meta), | |
| processors = lambda: _create_subject_for_flag("--processors", self.parsed_flags, self.meta, default = []), | |
| target_label = lambda: _create_subject_for_flag("--target_label", self.parsed_flags, self.meta), | |
| executable_file_name = lambda: subjects.str(action_subject.actual.argv[0], self.meta), | |
| inputs = action_subject.inputs, | |
| outputs = lambda: subjects.collection([o.short_path for o in action_subject.actual.outputs.to_list()], self.meta.derive("outputs()"), format = True), | |
| argv = action_subject.argv, | |
| mnemonic = action_subject.mnemonic, | |
| native_header_output = lambda: _create_subject_for_flag("--native_header_output", self.parsed_flags, self.meta), | |
| fix_deps_tool = lambda: _create_subject_for_flag("--experimental_fix_deps_tool", self.parsed_flags, self.meta).offset(0, factory = subjects.str), | |
| ) | |
| return public | |
| def _parse_flags(argv): | |
| flag_values = {} | |
| current_flag_name = None | |
| for idx, arg in enumerate(argv): | |
| if idx == 0: | |
| continue # java command | |
| if current_flag_name == "--javacopts" and arg == "--": | |
| current_flag_name = None | |
| continue | |
| if arg.startswith("-") and current_flag_name != "--javacopts": | |
| if "=" in arg: | |
| parts = arg.split("=", 1) | |
| flag_values.setdefault(parts[0], []).append(parts[1]) | |
| current_flag_name = None | |
| else: | |
| flag_values.setdefault(arg, []) | |
| current_flag_name = arg | |
| else: | |
| if not current_flag_name: | |
| fail("No preceding flag for value:", arg, "at index:", idx, "\nargv:\n", argv) | |
| flag_values[current_flag_name].append(arg) | |
| return flag_values | |
| def _create_subject_for_flag(flag_name, parsed_flags, meta, default = None): | |
| """Helper to create a collection subject for a given flag.""" | |
| return subjects.collection(parsed_flags.get(flag_name, default), meta.derive(flag_name), format = True) | |
| javac_action_subject = struct( | |
| of = _new_javac_action_subject, | |
| parse_flags = _parse_flags, # exposed for testing this method itself | |
| ) |