+// Test dependencies may need an `extern crate` here to ensure that they show up
+// in the depinfo file (otherwise cargo thinks they are unused)
+#[allow(unused_extern_crates)]
+extern crate clippy_utils;
+#[allow(unused_extern_crates)]
+extern crate derive_new;
+#[allow(unused_extern_crates)]
+extern crate if_chain;
+#[allow(unused_extern_crates)]
+extern crate itertools;
+#[allow(unused_extern_crates)]
+extern crate parking_lot;
+#[allow(unused_extern_crates)]
+extern crate quote;
+#[allow(unused_extern_crates)]
+extern crate syn;
+
+/// Produces a string with an `--extern` flag for all UI test crate
+/// dependencies.
+///
+/// The dependency files are located by parsing the depinfo file for this test
+/// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test
+/// dependencies must be added to Cargo.toml at the project root. Test
+/// dependencies that are not *directly* used by this test module require an
+/// `extern crate` declaration.
+fn extern_flags() -> String {
+ let current_exe_depinfo = {
+ let mut path = env::current_exe().unwrap();
+ path.set_extension("d");
+ std::fs::read_to_string(path).unwrap()
+ };
+ let mut crates: HashMap<&str, &str> = HashMap::with_capacity(TEST_DEPENDENCIES.len());
+ for line in current_exe_depinfo.lines() {
+ // each dependency is expected to have a Makefile rule like `/path/to/crate-hash.rlib:`
+ let parse_name_path = || {
+ if line.starts_with(char::is_whitespace) {
+ return None;
+ }
+ let path_str = line.strip_suffix(':')?;
+ let path = Path::new(path_str);
+ if !matches!(path.extension()?.to_str()?, "rlib" | "so" | "dylib" | "dll") {
+ return None;
+ }
+ let (name, _hash) = path.file_stem()?.to_str()?.rsplit_once('-')?;
+ // the "lib" prefix is not present for dll files
+ let name = name.strip_prefix("lib").unwrap_or(name);
+ Some((name, path_str))
+ };
+ if let Some((name, path)) = parse_name_path() {
+ if TEST_DEPENDENCIES.contains(&name) {
+ // A dependency may be listed twice if it is available in sysroot,
+ // and the sysroot dependencies are listed first. As of the writing,
+ // this only seems to apply to if_chain.
+ crates.insert(name, path);
+ }
+ }
+ }
+ let not_found: Vec<&str> = TEST_DEPENDENCIES
+ .iter()
+ .copied()
+ .filter(|n| !crates.contains_key(n))
+ .collect();
+ assert!(
+ not_found.is_empty(),
+ "dependencies not found in depinfo: {:?}\n\
+ help: Make sure the `-Z binary-dep-depinfo` rust flag is enabled\n\
+ help: Try adding to dev-dependencies in Cargo.toml",
+ not_found
+ );
+ crates
+ .into_iter()
+ .map(|(name, path)| format!(" --extern {}={}", name, path))
+ .collect()