nichlink_run_method/macros/face_external.rs
1//! The external-crate registration-face declaration form.
2//! 外部 crate 的注册面声明形式。
3
4/// `kind` is the handle-marker type this file declares (`pub struct <Kind>;`), so
5/// write that type first and reference it here: an editor cannot complete a name
6/// the author has not written yet, and `kind` is captured as an identifier
7/// rather than an expression, which is also why value completion does not fire
8/// there. Every other field completes normally.
9/// `kind` 就是本文件声明的那个 handle 标记类型(`pub struct <Kind>;`):先写出该类型,
10/// 再在这里引用它。编辑器无法补全一个作者还没写下的名字,而且 `kind` 是以标识符而非
11/// 表达式捕获的——这也是它的值位不会弹候选的原因。其余字段的值都能正常补全。
12/// Declare a registration face: `kind` is the only required field; every other
13/// field is optional and defaults the way the generated compact form defaults
14/// them — `source` to this file, `preset`/`parts` to `NoPreset`/`NoParts`,
15/// `handle` and `params` to `kind`, `name` to the kind's spelling, `summary` to
16/// empty, `exports`/`requires`/`provides`/`runtime_checks` to empty,
17/// `needs_registry` to `false`, `registry_name` to the module's last segment,
18/// `parent` to the package's root, `getting_from_other_registry` to `None`,
19/// `registry_rule_path` to this file, and `registry_rule` to
20/// `RegistrationRule::ANY` (see the comment in the expansion).
21/// 声明一个注册面:只有 `kind` 必填,其余字段都可省略,并按生成的紧凑形式取默认值——
22/// `source` 取本文件、`preset`/`parts` 取 `NoPreset`/`NoParts`、`handle` 取 `kind`、
23/// `handle`/`params` 取 kind、`name` 取 kind 的拼写、`summary` 取空、`exports`/`requires`/`provides`/
24/// `runtime_checks` 取空、`needs_registry` 取 `false`、`registry_name` 取模块名末段、
25/// `parent` 取包根、`getting_from_other_registry` 取 `None`、`registry_rule_path` 取
26/// 本文件、`registry_rule` 取 `RegistrationRule::ANY`(原因见展开处的注释)。
27/// Declare a registration face owned by an external crate.
28/// 声明由外部 crate 所有的注册面。
29///
30/// Unlike generated parent-specific macros, this form receives its source path
31/// explicitly; an external crate is not part of the host's generated tree.
32/// 与生成的父级专属宏不同,此形式显式接收源码路径;外部 crate 不在宿主
33/// 自动生成的模块树中。
34///
35/// An external face is written with braces like every other face, so the editor is
36/// told to insert them.
37/// 外部注册面与其它注册面一样用花括号书写,因此这里告诉编辑器插入花括号。
38#[rust_analyzer::macro_style(braces)]
39#[macro_export]
40macro_rules! external_object {
41 { @tokens collector: $collector:ident, $($tokens:tt)* } => {
42 // The author's fields go through the same front end as a generated
43 // alias, so `;` separators and any order are accepted here too; it
44 // re-dispatches to `__external_object!`, whose matcher names the source
45 // file first.
46 // 作者的字段与生成的别名走同一个前端,因此这里同样接受 `;` 与任意顺序;
47 // 前端会回派到 `__external_object!`——它的 matcher 首要指出源文件。
48 $crate::face_fields! { @external collector: $collector, $($tokens)* }
49 };
50 { @tokens $($tokens:tt)* } => {
51 $crate::face_fields! { @external collector: linked, $($tokens)* }
52 };
53 { $($tokens:tt)* } => {
54 $crate::external_object! { @tokens $($tokens)* }
55 };
56}
57
58#[doc(hidden)]
59#[macro_export]
60macro_rules! __external_object {
61 // One arm: `handle` is not a field, so the marker type the compile-time
62 // interface assertion uses is `kind` itself. The author-facing shape is the
63 // same one the object macro takes — everything after `kind` optional — and
64 // the external form only adds `source`, which the front end fills with this
65 // file's own path when it is omitted.
66 // The second arm that used to sit here existed only to insert
67 // `handle: $kind` for authors who wrote no `handle`. Once `handle` stopped
68 // being a field, the single arm below passes `handle: $kind` itself, so a
69 // `handle`-less face and a `handle`-writing one both reach this matcher.
70 // 一条 arm:`handle` 不是字段,因此编译期接口断言所用的标记类型就是 `kind` 本身。
71 // 作者侧的形状与 object 宏一致——`kind` 之后全部可省——外部形式只多一个 `source`,
72 // 省略时由前端填成本文件自己的路径。
73 // 这里曾有第二条 arm,只为给没写 `handle` 的作者补 `handle: $kind`。`handle` 不再是
74 // 字段之后,下面这条 arm 自己就传 `handle: $kind`,因此不写 handle 的面与写了 handle
75 // 的面都落到这个匹配器。
76 // Pinned by `run_method/tests/external_compact_face.rs`.
77 // 由 `run_method/tests/external_compact_face.rs` 钉住。
78 {
79 collector: $collector:ident,
80 $(source: $source:expr,)?
81 kind: $kind:ident,
82 $(preset: $preset:ty,)?
83 $(parts: $parts:ty,)?
84 $(name: { zh: $name_zh:expr, en: $name_en:expr $(,)? },)?
85 $(summary: { zh: $summary_zh:expr, en: $summary_en:expr $(,)? },)?
86 $(exports: [$($export:expr),* $(,)?],)?
87 $(stable_name: $stable_name:literal,)?
88 $(needs_registry: $needs_registry:expr,)?
89 $(parent: $parent:expr,)?
90 $(getting_from_other_registry: $getting:expr,)?
91 $(registry_rule_path: $rule_path:expr,)?
92 $(registry_rule: $rule:expr,)?
93 $(admission: $admission:expr,)?
94 $(handle_traits: [$($handle_trait:literal),* $(,)?],)?
95 $(handle_contracts: [$($handle_contract:path),* $(,)?],)?
96 $(part_traits: [$($part_trait:literal),* $(,)?],)?
97 $(part_contracts: [$($part_contract:path),* $(,)?],)?
98 $(requires: [$($require:expr => $provider:expr),* $(,)?],)?
99 $(provides: [$($provide:expr),* $(,)?],)?
100 $(flow: $flow:expr,)?
101 $(flow_provider: $flow_provider:path,)?
102 $(plugin: $plugin:expr,)?
103 $(runtime_checks: [$($runtime_check:expr),* $(,)?],)?
104 $(,)?
105 } => {
106 $crate::__registration_face! {
107 source: $crate::__face_expr_or!(
108 $crate::registry_core::manifest_relative_source(env!("CARGO_MANIFEST_DIR"), file!());
109 $($source)?
110 ),
111 collector: $collector,
112 kind: $kind,
113 preset: $crate::__face_ty_or!($crate::NoPreset; $($preset)?),
114 preset_name: $crate::__face_ty_name_or!("NoPreset"; $($preset)?),
115 parts: $crate::__face_ty_or!($crate::NoParts; $($parts)?),
116 parts_name: $crate::__face_ty_name_or!("NoParts"; $($parts)?),
117 name: {
118 zh: $crate::__face_value_or!(stringify!($kind); [$($name_zh)?]),
119 en: $crate::__face_value_or!(stringify!($kind); [$($name_en)?]),
120 },
121 summary: {
122 zh: $crate::__face_value_or!(""; [$($summary_zh)?]),
123 en: $crate::__face_value_or!(""; [$($summary_en)?]),
124 },
125 params: stringify!($kind),
126 exports: [$($($export),*)?],
127 handle: $kind,
128 handle_name: stringify!($kind),
129 $(stable_name: $stable_name,)?
130 needs_registry: $crate::__face_expr_or!(false; $($needs_registry)?),
131 registry_name: $crate::registry_core::last_path_segment(module_path!()),
132 parent: $crate::__face_expr_or!($crate::root_node_id(env!("CARGO_PKG_NAME")); $($parent)?),
133 getting_from_other_registry: $crate::__face_expr_or!(None; $($getting)?),
134 registry_rule_path: $crate::__face_expr_or!($crate::registry_core::manifest_relative_source(env!("CARGO_MANIFEST_DIR"), file!()); $($rule_path)?),
135 // Why the generated compact arm's default is wrong here: that arm
136 // omits the rule on a registry-owning face by resolving
137 // `super::registry_rule::REGISTRATION_RULE`, a *relative* path that
138 // only exists because the build generated a sibling rule module
139 // beside the face. An external crate is outside the host's generated
140 // tree, so that sibling does not exist and the same default would not
141 // compile at all. The boundary is therefore the crate: an external
142 // face that owns a registry and omits the field gets the permissive
143 // `ANY` and must name its rule explicitly to narrow it.
144 // 生成的紧凑 arm 的默认值在这里为什么是错的:那个 arm 对拥有注册机的
145 // 面省略规则时,解析到 `super::registry_rule::REGISTRATION_RULE`——一个
146 // **相对**路径,它成立只因为构建步骤在注册面旁边生成了兄弟规则模块。
147 // 外部 crate 位于宿主生成树之外,这个兄弟模块并不存在,照搬该默认值根本
148 // 编译不过。因此边界就是 crate 本身:拥有注册机却省略该字段的外部面得到
149 // 宽松的 `ANY`,要收窄必须显式写出规则。
150 // Pinned by `run_method/tests/external_compact_face.rs`.
151 // 由 `run_method/tests/external_compact_face.rs` 钉住。
152 registry_rule: $crate::__face_value_or!($crate::RegistrationRule::ANY; [$($rule)?]),
153 $(admission: $admission,)?
154 $(handle_traits: [$($handle_trait),*],)?
155 $(handle_contracts: [$($handle_contract),*],)?
156 $(part_traits: [$($part_trait),*],)?
157 $(part_contracts: [$($part_contract),*],)?
158 requires: [$($($require => $provider),*)?],
159 provides: [$($($provide),*)?],
160 $(flow: $flow,)?
161 $(flow_provider: $flow_provider,)?
162 $(plugin: $plugin,)?
163 runtime_checks: [$($($runtime_check),*)?],
164 }
165 };
166}