diff options
Diffstat (limited to 'rust/private/rust_analyzer.bzl')
-rw-r--r-- | rust/private/rust_analyzer.bzl | 104 |
1 files changed, 49 insertions, 55 deletions
diff --git a/rust/private/rust_analyzer.bzl b/rust/private/rust_analyzer.bzl index 74b46648..2682d966 100644 --- a/rust/private/rust_analyzer.bzl +++ b/rust/private/rust_analyzer.bzl @@ -20,9 +20,9 @@ given targets. This file can be consumed by rust-analyzer as an alternative to Cargo.toml files. """ -load("//proto/prost:providers.bzl", "ProstProtoInfo") load("//rust/platform:triple_mappings.bzl", "system_to_dylib_ext", "triple_to_system") load("//rust/private:common.bzl", "rust_common") +load("//rust/private:providers.bzl", "RustAnalyzerGroupInfo", "RustAnalyzerInfo") load("//rust/private:rustc.bzl", "BuildInfo") load( "//rust/private:utils.bzl", @@ -32,25 +32,43 @@ load( "find_toolchain", ) -RustAnalyzerInfo = provider( - doc = "RustAnalyzerInfo holds rust crate metadata for targets", - fields = { - "build_info": "BuildInfo: build info for this crate if present", - "cfgs": "List[String]: features or other compilation --cfg settings", - "crate": "rust_common.crate_info", - "crate_specs": "Depset[File]: transitive closure of OutputGroupInfo files", - "deps": "List[RustAnalyzerInfo]: direct dependencies", - "env": "Dict{String: String}: Environment variables, used for the `env!` macro", - "proc_macro_dylib_path": "File: compiled shared library output of proc-macro rule", - }, -) +def write_rust_analyzer_spec_file(ctx, attrs, owner, base_info): + """Write a rust-analyzer spec info file. -RustAnalyzerGroupInfo = provider( - doc = "RustAnalyzerGroupInfo holds multiple RustAnalyzerInfos", - fields = { - "deps": "List[RustAnalyzerInfo]: direct dependencies", - }, -) + Args: + ctx (ctx): The current rule's context object. + attrs (dict): A mapping of attributes. + owner (Label): The label of the owner of the spec info. + base_info (RustAnalyzerInfo): The data the resulting RustAnalyzerInfo is based on. + + Returns: + RustAnalyzerInfo: Info with the embedded spec file. + """ + crate_spec = ctx.actions.declare_file("{}.rust_analyzer_crate_spec.json".format(owner.name)) + + rust_analyzer_info = RustAnalyzerInfo( + crate = base_info.crate, + cfgs = base_info.cfgs, + env = base_info.env, + deps = base_info.deps, + crate_specs = depset(direct = [crate_spec], transitive = [base_info.crate_specs]), + proc_macro_dylib_path = base_info.proc_macro_dylib_path, + build_info = base_info.build_info, + ) + + ctx.actions.write( + output = crate_spec, + content = json.encode_indent( + _create_single_crate( + ctx, + attrs, + rust_analyzer_info, + ), + indent = " " * 4, + ), + ) + + return rust_analyzer_info def _rust_analyzer_aspect_impl(target, ctx): if (rust_common.crate_info not in target and @@ -58,6 +76,9 @@ def _rust_analyzer_aspect_impl(target, ctx): rust_common.crate_group_info not in target): return [] + if RustAnalyzerInfo in target or RustAnalyzerGroupInfo in target: + return [] + toolchain = find_toolchain(ctx) # Always add `test` & `debug_assertions`. See rust-analyzer source code: @@ -102,28 +123,7 @@ def _rust_analyzer_aspect_impl(target, ctx): if RustAnalyzerGroupInfo in ctx.rule.attr.actual: dep_infos.extend(ctx.rule.attr.actual[RustAnalyzerGroupInfo]) - if ProstProtoInfo in target: - for info in target[ProstProtoInfo].transitive_dep_infos.to_list(): - crate_info = info.crate_info - crate_spec = ctx.actions.declare_file(crate_info.owner.name + ".rust_analyzer_crate_spec") - rust_analyzer_info = RustAnalyzerInfo( - crate = crate_info, - cfgs = cfgs, - env = crate_info.rustc_env, - deps = [], - crate_specs = depset(direct = [crate_spec]), - proc_macro_dylib_path = None, - build_info = info.build_info, - ) - ctx.actions.write( - output = crate_spec, - content = json.encode(_create_single_crate(ctx, rust_analyzer_info)), - ) - dep_infos.append(rust_analyzer_info) - - if ProstProtoInfo in target: - crate_info = target[ProstProtoInfo].dep_variant_info.crate_info - elif rust_common.crate_group_info in target: + if rust_common.crate_group_info in target: return [RustAnalyzerGroupInfo(deps = dep_infos)] elif rust_common.crate_info in target: crate_info = target[rust_common.crate_info] @@ -132,22 +132,15 @@ def _rust_analyzer_aspect_impl(target, ctx): else: fail("Unexpected target type: {}".format(target)) - crate_spec = ctx.actions.declare_file(ctx.label.name + ".rust_analyzer_crate_spec") - - rust_analyzer_info = RustAnalyzerInfo( + rust_analyzer_info = write_rust_analyzer_spec_file(ctx, ctx.rule.attr, ctx.label, RustAnalyzerInfo( crate = crate_info, cfgs = cfgs, env = crate_info.rustc_env, deps = dep_infos, - crate_specs = depset(direct = [crate_spec], transitive = [dep.crate_specs for dep in dep_infos]), + crate_specs = depset(transitive = [dep.crate_specs for dep in dep_infos]), proc_macro_dylib_path = find_proc_macro_dylib_path(toolchain, target), build_info = build_info, - ) - - ctx.actions.write( - output = crate_spec, - content = json.encode(_create_single_crate(ctx, rust_analyzer_info)), - ) + )) return [ rust_analyzer_info, @@ -201,12 +194,13 @@ def _crate_id(crate_info): """ return "ID-" + crate_info.root.path -def _create_single_crate(ctx, info): +def _create_single_crate(ctx, attrs, info): """Creates a crate in the rust-project.json format. Args: - ctx (ctx): The rule context - info (RustAnalyzerInfo): RustAnalyzerInfo for the current crate + ctx (ctx): The rule context. + attrs (dict): A mapping of attributes. + info (RustAnalyzerInfo): RustAnalyzerInfo for the current crate. Returns: (dict) The crate rust-project.json representation @@ -240,7 +234,7 @@ def _create_single_crate(ctx, info): # TODO: The only imagined use case is an env var holding a filename in the workspace passed to a # macro like include_bytes!. Other use cases might exist that require more complex logic. - expand_targets = concat([getattr(ctx.rule.attr, attr, []) for attr in ["data", "compile_data"]]) + expand_targets = concat([getattr(attrs, attr, []) for attr in ["data", "compile_data"]]) crate["env"].update({k: dedup_expand_location(ctx, v, expand_targets) for k, v in info.env.items()}) |