2
2
3
3
load (":common.bzl" , "rust_common" )
4
4
5
- def _find_rustfmtable_srcs (target , aspect_ctx = None ):
6
- """Parse a target for rustfmt formattable sources .
5
+ def _get_rustfmt_ready_crate_info (target ):
6
+ """Check that a target is suitable for rustfmt and extract the `CrateInfo` provider from it .
7
7
8
8
Args:
9
9
target (Target): The target the aspect is running on.
10
- aspect_ctx (ctx, optional): The aspect's context object.
11
10
12
11
Returns:
13
- list : A list of formattable sources (`File`) .
12
+ CrateInfo, optional : A `CrateInfo` provider if clippy should be run or `None` .
14
13
"""
15
- if rust_common .crate_info not in target :
16
- return []
17
14
18
15
# Ignore external targets
19
16
if target .label .workspace_root .startswith ("external" ):
20
- return []
17
+ return None
18
+
19
+ # Obviously ignore any targets that don't contain `CrateInfo`
20
+ if rust_common .crate_info in target :
21
+ return target [rust_common .crate_info ]
22
+ elif rust_common .test_crate_info in target :
23
+ return target [rust_common .test_crate_info ].crate
24
+ else :
25
+ return None
26
+
27
+ def _find_rustfmtable_srcs (crate_info , aspect_ctx = None ):
28
+ """Parse a `CrateInfo` provider for rustfmt formattable sources.
29
+
30
+ Args:
31
+ crate_info (CrateInfo): A `CrateInfo` provider.
32
+ aspect_ctx (ctx, optional): The aspect's context object.
33
+
34
+ Returns:
35
+ list: A list of formattable sources (`File`).
36
+ """
21
37
38
+ # Targets with specific tags will not be formatted
22
39
if aspect_ctx :
23
- # Targets with specifc tags will not be formatted
24
40
ignore_tags = [
25
41
"no-format" ,
26
42
"no-rustfmt" ,
@@ -31,8 +47,6 @@ def _find_rustfmtable_srcs(target, aspect_ctx = None):
31
47
if tag in aspect_ctx .rule .attr .tags :
32
48
return []
33
49
34
- crate_info = target [rust_common .crate_info ]
35
-
36
50
# Filter out any generated files
37
51
srcs = [src for src in crate_info .srcs .to_list () if src .is_source ]
38
52
@@ -83,21 +97,23 @@ def _perform_check(edition, srcs, ctx):
83
97
return marker
84
98
85
99
def _rustfmt_aspect_impl (target , ctx ):
86
- srcs = _find_rustfmtable_srcs (target , ctx )
100
+ crate_info = _get_rustfmt_ready_crate_info (target )
101
+
102
+ if not crate_info :
103
+ return []
104
+
105
+ srcs = _find_rustfmtable_srcs (crate_info , ctx )
87
106
88
107
# If there are no formattable sources, do nothing.
89
108
if not srcs :
90
109
return []
91
110
92
- # Parse the edition to use for formatting from the target
93
- edition = target [rust_common .crate_info ].edition
111
+ edition = crate_info .edition
94
112
95
- manifest = _generate_manifest (edition , srcs , ctx )
96
113
marker = _perform_check (edition , srcs , ctx )
97
114
98
115
return [
99
116
OutputGroupInfo (
100
- rustfmt_manifest = depset ([manifest ]),
101
117
rustfmt_checks = depset ([marker ]),
102
118
),
103
119
]
@@ -109,7 +125,6 @@ This aspect is used to gather information about a crate for use in rustfmt and p
109
125
110
126
Output Groups:
111
127
112
- - `rustfmt_manifest`: A manifest used by rustfmt binaries to provide crate specific settings.
113
128
- `rustfmt_checks`: Executes `rustfmt --check` on the specified target.
114
129
115
130
The build setting `@rules_rust//:rustfmt.toml` is used to control the Rustfmt [configuration settings][cs]
@@ -134,6 +149,48 @@ generated source files are also ignored by this aspect.
134
149
default = Label ("//util/process_wrapper" ),
135
150
),
136
151
},
152
+ incompatible_use_toolchain_transition = True ,
153
+ required_providers = [
154
+ [rust_common .crate_info ],
155
+ [rust_common .test_crate_info ],
156
+ ],
157
+ fragments = ["cpp" ],
158
+ host_fragments = ["cpp" ],
159
+ toolchains = [
160
+ str (Label ("//rust/rustfmt:toolchain_type" )),
161
+ ],
162
+ )
163
+
164
+ def _rustfmt_test_manifest_aspect_impl (target , ctx ):
165
+ crate_info = _get_rustfmt_ready_crate_info (target )
166
+
167
+ if not crate_info :
168
+ return []
169
+
170
+ # Parse the edition to use for formatting from the target
171
+ edition = crate_info .edition
172
+
173
+ srcs = _find_rustfmtable_srcs (crate_info , ctx )
174
+ manifest = _generate_manifest (edition , srcs , ctx )
175
+
176
+ return [
177
+ OutputGroupInfo (
178
+ rustfmt_manifest = depset ([manifest ]),
179
+ ),
180
+ ]
181
+
182
+ # This aspect contains functionality split out of `rustfmt_aspect` which broke when
183
+ # `required_providers` was added to it. Aspects which have `required_providers` seems
184
+ # to not function with attributes that also require providers.
185
+ _rustfmt_test_manifest_aspect = aspect (
186
+ implementation = _rustfmt_test_manifest_aspect_impl ,
187
+ doc = """\
188
+ This aspect is used to gather information about a crate for use in `rustfmt_test`
189
+
190
+ Output Groups:
191
+
192
+ - `rustfmt_manifest`: A manifest used by rustfmt binaries to provide crate specific settings.
193
+ """ ,
137
194
incompatible_use_toolchain_transition = True ,
138
195
fragments = ["cpp" ],
139
196
host_fragments = ["cpp" ],
@@ -158,8 +215,13 @@ def _rustfmt_test_impl(ctx):
158
215
is_executable = True ,
159
216
)
160
217
161
- manifests = depset (transitive = [target [OutputGroupInfo ].rustfmt_manifest for target in ctx .attr .targets ])
162
- srcs = [depset (_find_rustfmtable_srcs (target )) for target in ctx .attr .targets ]
218
+ crate_infos = [_get_rustfmt_ready_crate_info (target ) for target in ctx .attr .targets ]
219
+ srcs = [depset (_find_rustfmtable_srcs (crate_info )) for crate_info in crate_infos if crate_info ]
220
+
221
+ # Some targets may be included in tests but tagged as "no-format". In this
222
+ # case, there will be no manifest.
223
+ manifests = [getattr (target [OutputGroupInfo ], "rustfmt_manifest" , None ) for target in ctx .attr .targets ]
224
+ manifests = depset (transitive = [manifest for manifest in manifests if manifest ])
163
225
164
226
runfiles = ctx .runfiles (
165
227
transitive_files = depset (transitive = srcs + [manifests ]),
@@ -192,8 +254,11 @@ rustfmt_test = rule(
192
254
attrs = {
193
255
"targets" : attr .label_list (
194
256
doc = "Rust targets to run `rustfmt --check` on." ,
195
- providers = [rust_common .crate_info ],
196
- aspects = [rustfmt_aspect ],
257
+ providers = [
258
+ [rust_common .crate_info ],
259
+ [rust_common .test_crate_info ],
260
+ ],
261
+ aspects = [_rustfmt_test_manifest_aspect ],
197
262
),
198
263
"_runner" : attr .label (
199
264
doc = "The rustfmt test runner" ,
0 commit comments