Skip to content

Commit bf0e5b8

Browse files
committed
Fix exclusions in gen_rust_project target pattern
Signed-off-by: Patrick Steadman <ptsteadman@gmail.com>
1 parent 59a507e commit bf0e5b8

1 file changed

Lines changed: 48 additions & 0 deletions

File tree

tools/rust_analyzer/lib.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ fn generate_crate_info(
112112
"--aspects={rules_rust}//rust:defs.bzl%rust_analyzer_aspect"
113113
))
114114
.arg("--output_groups=rust_analyzer_crate_spec,rust_generated_srcs,rust_analyzer_proc_macro_dylib,rust_analyzer_src")
115+
.arg("--")
115116
.args(targets)
116117
.output()?;
117118

@@ -166,6 +167,53 @@ where
166167
serde_json::from_str(&content).with_context(|| format!("failed to deserialize file: {path}"))
167168
}
168169

170+
/// Returns the bazel build args that `generate_crate_info` would pass, for testing.
171+
#[cfg(test)]
172+
fn build_crate_info_args(rules_rust: &str, targets: &[String]) -> Vec<String> {
173+
let mut args = vec![
174+
"build".to_owned(),
175+
"--norun_validations".to_owned(),
176+
"--remote_download_all".to_owned(),
177+
format!("--aspects={rules_rust}//rust:defs.bzl%rust_analyzer_aspect"),
178+
"--output_groups=rust_analyzer_crate_spec,rust_generated_srcs,rust_analyzer_proc_macro_dylib,rust_analyzer_src".to_owned(),
179+
"--".to_owned(),
180+
];
181+
args.extend_from_slice(targets);
182+
args
183+
}
184+
185+
#[cfg(test)]
186+
mod tests {
187+
use super::*;
188+
189+
/// Without `--` before targets, Bazel treats exclusion patterns like `-//foo:bar`
190+
/// as unknown flags and exits with "unrecognized option". This test replicates
191+
/// that failure mode and verifies the separator is in the correct position.
192+
#[test]
193+
fn exclusion_targets_preceded_by_double_dash() {
194+
let targets = vec![
195+
"//...".to_owned(),
196+
"-//some/excluded:target".to_owned(),
197+
];
198+
let args = build_crate_info_args("rules_rust", &targets);
199+
200+
let dash_pos = args.iter().position(|a| a == "--").expect("-- must be present");
201+
let targets_start = dash_pos + 1;
202+
assert_eq!(
203+
&args[targets_start..],
204+
targets.as_slice(),
205+
"all targets must appear after --"
206+
);
207+
// Exclusion pattern must not appear before --
208+
for arg in &args[..dash_pos] {
209+
assert!(
210+
!arg.starts_with('-') || arg.starts_with("--"),
211+
"target exclusion {arg:?} appeared before -- and would be parsed as a flag"
212+
);
213+
}
214+
}
215+
}
216+
169217
/// `rust-analyzer` associates workspaces with buildfiles. Therefore, when it passes in a
170218
/// source file path, we use this function to identify the buildfile the file belongs to.
171219
fn source_file_to_buildfile(file: &Utf8Path) -> anyhow::Result<Utf8PathBuf> {

0 commit comments

Comments
 (0)