[prost] includes prost crate infos in rust_analyzer_aspect (#2232)

The change is fairly straightforward, but I did need to move prost
providers up to `prost/providers.bzl` and out of `private/prost.bzl` to
avoid a cyclic dependency.

What we do is:
* change `rust_prost_library` to return the `rust_proto_info` provider
* in the `rust-analyzer` aspect we iterate over transitive dep infos and
  generate the appropriate `RustAnalyzerInfo`
* lastly, we use the `crate_info` from `ProstProtoInfo` if we're
  processing a prost target as the "root" `crate_info`

There are a couple of things I'm not sure are correct:
1. For every prost dep I set `deps` to `[]` - I think that's correct but
   I'm not sure-sure.
2. Similarly I set `proc_macro_dylib_path` to always `None` - again I
   think that's correct, but not sure-sure.

Fixes #2121.

---------

Co-authored-by: UebelAndre <github@uebelandre.com>
diff --git a/docs/flatten.md b/docs/flatten.md
index e089ec5..b0b4d7f 100644
--- a/docs/flatten.md
+++ b/docs/flatten.md
@@ -2147,6 +2147,7 @@
 | proc_macro_deps| String |
 | crate| String |
 | actual| String |
+| proto| String |
 
 
 **ATTRIBUTES**
diff --git a/docs/rust_analyzer.md b/docs/rust_analyzer.md
index 409a307..bd91b0b 100644
--- a/docs/rust_analyzer.md
+++ b/docs/rust_analyzer.md
@@ -119,6 +119,7 @@
 | proc_macro_deps| String |
 | crate| String |
 | actual| String |
+| proto| String |
 
 
 **ATTRIBUTES**
diff --git a/proto/prost/private/prost.bzl b/proto/prost/private/prost.bzl
index b070227..a88357c 100644
--- a/proto/prost/private/prost.bzl
+++ b/proto/prost/private/prost.bzl
@@ -1,6 +1,7 @@
 """Rules for building protos in Rust with Prost and Tonic."""
 
 load("@rules_proto//proto:defs.bzl", "ProtoInfo", "proto_common")
+load("//proto/prost:providers.bzl", "ProstProtoInfo")
 load("//rust:defs.bzl", "rust_common")
 
 # buildifier: disable=bzl-visibility
@@ -13,16 +14,6 @@
 
 TOOLCHAIN_TYPE = "@rules_rust//proto/prost:toolchain_type"
 
-ProstProtoInfo = provider(
-    doc = "Rust Prost provider info",
-    fields = {
-        "dep_variant_info": "DepVariantInfo: For the compiled Rust gencode (also covers its " +
-                            "transitive dependencies)",
-        "package_info": "File: A newline delimited file of `--extern_path` values for protoc.",
-        "transitive_dep_infos": "depset[DepVariantInfo]: Transitive dependencies of the compiled crate.",
-    },
-)
-
 def _create_proto_lang_toolchain(ctx, prost_toolchain):
     proto_lang_toolchain = proto_common.ProtoLangToolchainInfo(
         out_replacement_format_flag = "--prost_out=%s",
@@ -328,6 +319,7 @@
 
     return [
         DefaultInfo(files = depset([dep_variant_info.crate_info.output])),
+        rust_proto_info,
         rust_common.crate_group_info(
             dep_variant_infos = depset(
                 [dep_variant_info],
diff --git a/proto/prost/providers.bzl b/proto/prost/providers.bzl
new file mode 100644
index 0000000..818f9f5
--- /dev/null
+++ b/proto/prost/providers.bzl
@@ -0,0 +1,11 @@
+"""Module containing definitions of all Prost providers."""
+
+ProstProtoInfo = provider(
+    doc = "Rust Prost provider info",
+    fields = {
+        "dep_variant_info": "DepVariantInfo: For the compiled Rust gencode (also covers its " +
+                            "transitive dependencies)",
+        "package_info": "File: A newline delimited file of `--extern_path` values for protoc.",
+        "transitive_dep_infos": "depset[DepVariantInfo]: Transitive dependencies of the compiled crate.",
+    },
+)
diff --git a/rust/private/rust_analyzer.bzl b/rust/private/rust_analyzer.bzl
index 323944d..eaf9c22 100644
--- a/rust/private/rust_analyzer.bzl
+++ b/rust/private/rust_analyzer.bzl
@@ -20,6 +20,7 @@
 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:rustc.bzl", "BuildInfo")
@@ -99,12 +100,32 @@
             dep_infos.append(ctx.rule.attr.actual[RustAnalyzerInfo])
 
         if RustAnalyzerGroupInfo in ctx.rule.attr.actual:
-            dep_infos.extend(ctx.rule.attr.actul[RustAnalyzerGroupInfo])
+            dep_infos.extend(ctx.rule.attr.actual[RustAnalyzerGroupInfo])
 
-    if rust_common.crate_group_info in target:
+    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:
         return [RustAnalyzerGroupInfo(deps = dep_infos)]
-
-    if rust_common.crate_info in target:
+    elif rust_common.crate_info in target:
         crate_info = target[rust_common.crate_info]
     elif rust_common.test_crate_info in target:
         crate_info = target[rust_common.test_crate_info].crate
@@ -163,7 +184,7 @@
     return None
 
 rust_analyzer_aspect = aspect(
-    attr_aspects = ["deps", "proc_macro_deps", "crate", "actual"],
+    attr_aspects = ["deps", "proc_macro_deps", "crate", "actual", "proto"],
     implementation = _rust_analyzer_aspect_impl,
     toolchains = [str(Label("//rust:toolchain_type"))],
     incompatible_use_toolchain_transition = True,