1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-22 15:06:54 -05:00

refactor(cli/tools): reduce cloning (#17309)

This commit is contained in:
Geert-Jan Zwiers 2023-01-13 22:39:19 +01:00 committed by GitHub
parent 225114166a
commit 052bcc62bb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 140 additions and 150 deletions

View file

@ -40,9 +40,9 @@ use std::sync::Arc;
use tokio::sync::mpsc::unbounded_channel;
use tokio::sync::mpsc::UnboundedSender;
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone)]
struct BenchSpecifierOptions {
filter: Option<String>,
filter: TestFilter,
}
#[derive(Debug, Clone, Eq, PartialEq, Deserialize)]
@ -354,12 +354,12 @@ async fn bench_specifier(
channel: UnboundedSender<BenchEvent>,
options: BenchSpecifierOptions,
) -> Result<(), AnyError> {
let filter = TestFilter::from_flag(&options.filter);
let filter = options.filter;
let mut worker = create_main_worker_for_test_or_bench(
&ps,
specifier.clone(),
specifier,
PermissionsContainer::new(permissions),
vec![ops::bench::init(channel.clone(), filter)],
vec![ops::bench::init(channel, filter)],
Default::default(),
)
.await?;
@ -369,8 +369,8 @@ async fn bench_specifier(
/// Test a collection of specifiers with test modes concurrently.
async fn bench_specifiers(
ps: ProcState,
permissions: Permissions,
ps: &ProcState,
permissions: &Permissions,
specifiers: Vec<ModuleSpecifier>,
options: BenchSpecifierOptions,
) -> Result<(), AnyError> {
@ -378,10 +378,10 @@ async fn bench_specifiers(
let (sender, mut receiver) = unbounded_channel::<BenchEvent>();
let join_handles = specifiers.iter().map(move |specifier| {
let join_handles = specifiers.into_iter().map(move |specifier| {
let ps = ps.clone();
let permissions = permissions.clone();
let specifier = specifier.clone();
let specifier = specifier;
let sender = sender.clone();
let options = options.clone();
@ -506,11 +506,11 @@ pub async fn run_benchmarks(
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
bench_specifiers(
ps,
permissions,
&ps,
&permissions,
specifiers,
BenchSpecifierOptions {
filter: bench_options.filter,
filter: TestFilter::from_flag(&bench_options.filter),
},
)
.await?;
@ -529,27 +529,20 @@ pub async fn run_benchmarks_with_watch(
// file would have impact on other files, which is undesirable.
let permissions =
Permissions::from_options(&ps.options.permissions_options())?;
let paths_to_watch: Vec<_> = bench_options
.files
.include
.iter()
.map(PathBuf::from)
.collect();
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
let ps = RefCell::new(ps);
let resolver = |changed: Option<Vec<PathBuf>>| {
let paths_to_watch = paths_to_watch.clone();
let paths_to_watch = bench_options.files.include.clone();
let paths_to_watch_clone = paths_to_watch.clone();
let files_changed = changed.is_some();
let files = bench_options.files.clone();
let ps = ps.borrow().clone();
let bench_options = &bench_options;
let ps = ps.borrow();
async move {
let bench_modules = collect_specifiers(&files, is_supported_bench_path)?;
let bench_modules =
collect_specifiers(&bench_options.files, is_supported_bench_path)?;
let mut paths_to_watch = paths_to_watch_clone;
let mut modules_to_reload = if files_changed {
@ -657,26 +650,28 @@ pub async fn run_benchmarks_with_watch(
};
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
let permissions = permissions.clone();
let permissions = &permissions;
ps.borrow_mut().reset_for_file_watcher();
let ps = ps.borrow().clone();
let filter = bench_options.filter.clone();
let files = bench_options.files.clone();
let ps = ps.borrow();
let bench_options = &bench_options;
async move {
let specifiers = collect_specifiers(&files, is_supported_bench_path)?
.iter()
.filter(|specifier| contains_specifier(&modules_to_reload, specifier))
.cloned()
.collect::<Vec<ModuleSpecifier>>();
let specifiers =
collect_specifiers(&bench_options.files, is_supported_bench_path)?
.iter()
.filter(|specifier| contains_specifier(&modules_to_reload, specifier))
.cloned()
.collect::<Vec<ModuleSpecifier>>();
check_specifiers(&ps, permissions.clone(), specifiers.clone()).await?;
bench_specifiers(
ps,
permissions.clone(),
&ps,
permissions,
specifiers,
BenchSpecifierOptions { filter },
BenchSpecifierOptions {
filter: TestFilter::from_flag(&bench_options.filter),
},
)
.await?;

View file

@ -27,10 +27,10 @@ pub async fn bundle(
let cli_options = Arc::new(CliOptions::from_flags(flags)?);
let resolver = |_| {
let cli_options = cli_options.clone();
let source_file1 = bundle_flags.source_file.clone();
let source_file2 = bundle_flags.source_file.clone();
let source_file1 = &bundle_flags.source_file;
let source_file2 = &bundle_flags.source_file;
async move {
let module_specifier = resolve_url_or_path(&source_file1)?;
let module_specifier = resolve_url_or_path(source_file1)?;
log::debug!(">>>>> bundle START");
let ps = ProcState::from_options(cli_options).await?;
@ -38,9 +38,7 @@ pub async fn bundle(
let mut paths_to_watch: Vec<PathBuf> = graph
.specifiers()
.filter_map(|(_, r)| {
r.as_ref().ok().and_then(|(s, _, _)| s.to_file_path().ok())
})
.filter_map(|(_, r)| r.ok().and_then(|(s, _, _)| s.to_file_path().ok()))
.collect();
if let Ok(Some(import_map_path)) = ps
@ -66,7 +64,7 @@ pub async fn bundle(
};
let operation = |(ps, graph): (ProcState, Arc<deno_graph::ModuleGraph>)| {
let out_file = bundle_flags.out_file.clone();
let out_file = &bundle_flags.out_file;
async move {
// at the moment, we don't support npm specifiers in deno bundle, so show an error
error_for_any_npm_specifier(&graph)?;
@ -74,7 +72,7 @@ pub async fn bundle(
let bundle_output = bundle_module_graph(graph.as_ref(), &ps)?;
log::debug!(">>>>> bundle END");
if let Some(out_file) = out_file.as_ref() {
if let Some(out_file) = out_file {
let output_bytes = bundle_output.code.as_bytes();
let output_len = output_bytes.len();
util::fs::write_file(out_file, output_bytes, 0o644)?;

View file

@ -92,8 +92,7 @@ pub async fn format(
}
}
};
let deno_dir = cli_options.resolve_deno_dir()?;
let deno_dir = &deno_dir;
let deno_dir = &cli_options.resolve_deno_dir()?;
let operation = |(paths, fmt_options): (Vec<PathBuf>, FmtOptionsConfig)| async move {
let incremental_cache = Arc::new(IncrementalCache::new(
&deno_dir.fmt_incremental_cache_db_file_path(),

View file

@ -97,7 +97,6 @@ pub async fn lint(
let has_error = Arc::new(AtomicBool::new(false));
let deno_dir = cli_options.resolve_deno_dir()?;
let operation = |paths: Vec<PathBuf>| async {
let incremental_cache = Arc::new(IncrementalCache::new(
&deno_dir.lint_incremental_cache_db_file_path(),
@ -111,8 +110,9 @@ pub async fn lint(
&paths,
));
let target_files_len = paths.len();
let reporter_kind = reporter_kind.clone();
let reporter_lock = Arc::new(Mutex::new(create_reporter(reporter_kind)));
let reporter_lock =
Arc::new(Mutex::new(create_reporter(reporter_kind.clone())));
run_parallelized(paths, {
let has_error = has_error.clone();
let lint_rules = lint_rules.clone();
@ -126,7 +126,7 @@ pub async fn lint(
return Ok(());
}
let r = lint_file(file_path.clone(), file_text, lint_rules.clone());
let r = lint_file(&file_path, file_text, lint_rules);
if let Ok((file_diagnostics, file_text)) = &r {
if file_diagnostics.is_empty() {
// update the incremental cache if there were no diagnostics
@ -167,8 +167,7 @@ pub async fn lint(
.await?;
} else {
if lint_options.is_stdin {
let reporter_lock =
Arc::new(Mutex::new(create_reporter(reporter_kind.clone())));
let reporter_lock = Arc::new(Mutex::new(create_reporter(reporter_kind)));
let r = lint_stdin(lint_rules);
handle_lint_result(
STDIN_FILE_NAME,
@ -246,12 +245,12 @@ pub fn create_linter(
}
fn lint_file(
file_path: PathBuf,
file_path: &PathBuf,
source_code: String,
lint_rules: Vec<Arc<dyn LintRule>>,
) -> Result<(Vec<LintDiagnostic>, String), AnyError> {
let file_name = file_path.to_string_lossy().to_string();
let media_type = MediaType::from(&file_path);
let media_type = MediaType::from(file_path);
let linter = create_linter(media_type, lint_rules);
@ -334,7 +333,7 @@ impl LintReporter for PrettyLintReporter {
&d.code,
&pretty_message,
&source_lines,
d.range.clone(),
&d.range,
d.hint.as_ref(),
&format_location(&JsStackFrame::from_location(
Some(d.filename.clone()),
@ -417,7 +416,7 @@ pub fn format_diagnostic(
diagnostic_code: &str,
message_line: &str,
source_lines: &[&str],
range: deno_lint::diagnostic::Range,
range: &deno_lint::diagnostic::Range,
maybe_hint: Option<&String>,
formatted_location: &str,
) -> String {

View file

@ -84,7 +84,7 @@ pub async fn run(flags: Flags, repl_flags: ReplFlags) -> Result<i32, AnyError> {
let ps = ProcState::build(flags).await?;
let mut worker = create_main_worker(
&ps,
main_module.clone(),
main_module,
PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?),

View file

@ -59,8 +59,7 @@ To grant permissions, set them before the script argument. For example:
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let mut worker =
create_main_worker(&ps, main_module.clone(), permissions).await?;
let mut worker = create_main_worker(&ps, main_module, permissions).await?;
let exit_code = worker.run().await?;
Ok(exit_code)
@ -70,7 +69,7 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
let ps = ProcState::build(flags).await?;
let main_module = resolve_url_or_path("./$deno$stdin.ts").unwrap();
let mut worker = create_main_worker(
&ps.clone(),
&ps,
main_module.clone(),
PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
@ -86,7 +85,7 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
maybe_types: None,
media_type: MediaType::TypeScript,
source: String::from_utf8(source)?.into(),
specifier: main_module.clone(),
specifier: main_module,
maybe_headers: None,
};
// Save our fake file into file fetcher cache
@ -113,8 +112,7 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<i32, AnyError> {
let permissions = PermissionsContainer::new(Permissions::from_options(
&ps.options.permissions_options(),
)?);
let worker =
create_main_worker(&ps, main_module.clone(), permissions).await?;
let worker = create_main_worker(&ps, main_module, permissions).await?;
worker.run_for_watcher().await?;
Ok(())
@ -162,7 +160,7 @@ pub async fn eval_command(
maybe_types: None,
media_type: MediaType::Unknown,
source: String::from_utf8(source_code)?.into(),
specifier: main_module.clone(),
specifier: main_module,
maybe_headers: None,
};

View file

@ -39,7 +39,7 @@ pub async fn compile(
flags: Flags,
compile_flags: CompileFlags,
) -> Result<(), AnyError> {
let ps = ProcState::build(flags.clone()).await?;
let ps = ProcState::build(flags).await?;
let module_specifier = resolve_url_or_path(&compile_flags.source_file)?;
let deno_dir = &ps.dir;
@ -72,7 +72,7 @@ pub async fn compile(
let final_bin = create_standalone_binary(
original_binary,
eszip,
module_specifier.clone(),
module_specifier,
&compile_flags,
ps,
)

View file

@ -712,7 +712,7 @@ pub fn format_test_error(js_error: &JsError) -> String {
/// Test a single specifier as documentation containing test programs, an executable test module or
/// both.
async fn test_specifier(
ps: ProcState,
ps: &ProcState,
permissions: Permissions,
specifier: ModuleSpecifier,
mode: TestMode,
@ -723,13 +723,13 @@ async fn test_specifier(
let stdout = StdioPipe::File(sender.stdout());
let stderr = StdioPipe::File(sender.stderr());
let mut worker = create_main_worker_for_test_or_bench(
&ps,
specifier.clone(),
ps,
specifier,
PermissionsContainer::new(permissions),
vec![ops::testing::init(
sender,
fail_fast_tracker,
options.filter.clone(),
options.filter,
)],
Stdio {
stdin: StdioPipe::Inherit,
@ -892,7 +892,7 @@ fn extract_files_from_fenced_blocks(
}
async fn fetch_inline_files(
ps: ProcState,
ps: &ProcState,
specifiers: Vec<ModuleSpecifier>,
) -> Result<Vec<File>, AnyError> {
let mut files = Vec::new();
@ -909,7 +909,7 @@ async fn fetch_inline_files(
} else {
extract_files_from_source_comments(
&file.specifier,
file.source.clone(),
file.source,
file.media_type,
)
};
@ -928,7 +928,7 @@ pub async fn check_specifiers(
) -> Result<(), AnyError> {
let lib = ps.options.ts_type_lib_window();
let inline_files = fetch_inline_files(
ps.clone(),
ps,
specifiers
.iter()
.filter_map(|(specifier, mode)| {
@ -963,10 +963,10 @@ pub async fn check_specifiers(
}
let module_specifiers = specifiers
.iter()
.into_iter()
.filter_map(|(specifier, mode)| {
if *mode != TestMode::Documentation {
Some(specifier.clone())
if mode != TestMode::Documentation {
Some(specifier)
} else {
None
}
@ -988,14 +988,14 @@ pub async fn check_specifiers(
/// Test a collection of specifiers with test modes concurrently.
async fn test_specifiers(
ps: ProcState,
permissions: Permissions,
permissions: &Permissions,
specifiers_with_mode: Vec<(ModuleSpecifier, TestMode)>,
options: TestSpecifierOptions,
) -> Result<(), AnyError> {
let log_level = ps.options.log_level();
let specifiers_with_mode = if let Some(seed) = ps.options.shuffle_tests() {
let mut rng = SmallRng::seed_from_u64(seed);
let mut specifiers_with_mode = specifiers_with_mode.clone();
let mut specifiers_with_mode = specifiers_with_mode;
specifiers_with_mode.sort_by_key(|(specifier, _)| specifier.clone());
specifiers_with_mode.shuffle(&mut rng);
specifiers_with_mode
@ -1004,48 +1004,47 @@ async fn test_specifiers(
};
let (sender, mut receiver) = unbounded_channel::<TestEvent>();
let fail_fast_tracker = FailFastTracker::new(options.fail_fast);
let sender = TestEventSender::new(sender);
let concurrent_jobs = options.concurrent_jobs;
let join_handles =
specifiers_with_mode.iter().map(move |(specifier, mode)| {
let ps = ps.clone();
let permissions = permissions.clone();
let specifier = specifier.clone();
let mode = mode.clone();
let mut sender = sender.clone();
let options = options.clone();
let fail_fast_tracker = fail_fast_tracker.clone();
specifiers_with_mode
.into_iter()
.map(move |(specifier, mode)| {
let ps = ps.clone();
let permissions = permissions.clone();
let mut sender = sender.clone();
let options = options.clone();
let fail_fast_tracker = FailFastTracker::new(options.fail_fast);
tokio::task::spawn_blocking(move || {
if fail_fast_tracker.should_stop() {
return Ok(());
}
let origin = specifier.to_string();
let file_result = run_local(test_specifier(
ps,
permissions,
specifier,
mode,
sender.clone(),
fail_fast_tracker,
options,
));
if let Err(error) = file_result {
if error.is::<JsError>() {
sender.send(TestEvent::UncaughtError(
origin,
Box::new(error.downcast::<JsError>().unwrap()),
))?;
} else {
return Err(error);
tokio::task::spawn_blocking(move || {
if fail_fast_tracker.should_stop() {
return Ok(());
}
}
Ok(())
})
});
let origin = specifier.to_string();
let file_result = run_local(test_specifier(
&ps,
permissions,
specifier,
mode,
sender.clone(),
fail_fast_tracker,
options,
));
if let Err(error) = file_result {
if error.is::<JsError>() {
sender.send(TestEvent::UncaughtError(
origin,
Box::new(error.downcast::<JsError>().unwrap()),
))?;
} else {
return Err(error);
}
}
Ok(())
})
});
let join_stream = stream::iter(join_handles)
.buffer_unordered(concurrent_jobs.get())
@ -1093,7 +1092,7 @@ async fn test_specifiers(
TestEvent::Result(id, result, elapsed) => {
if tests_with_result.insert(id) {
let description = tests.get(&id).unwrap().clone();
let description = tests.get(&id).unwrap();
match &result {
TestResult::Ok => {
summary.passed += 1;
@ -1109,7 +1108,7 @@ async fn test_specifiers(
unreachable!("should be handled in TestEvent::UncaughtError");
}
}
reporter.report_result(&description, &result, elapsed);
reporter.report_result(description, &result, elapsed);
}
}
@ -1236,13 +1235,13 @@ fn is_supported_test_ext(path: &Path) -> bool {
/// - Specifiers matching the `is_supported_test_path` are marked as `TestMode::Executable`.
/// - Specifiers matching both predicates are marked as `TestMode::Both`
fn collect_specifiers_with_test_mode(
files: FilesConfig,
include_inline: bool,
files: &FilesConfig,
include_inline: &bool,
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
let module_specifiers = collect_specifiers(&files, is_supported_test_path)?;
let module_specifiers = collect_specifiers(files, is_supported_test_path)?;
if include_inline {
return collect_specifiers(&files, is_supported_test_ext).map(
if *include_inline {
return collect_specifiers(files, is_supported_test_ext).map(
|specifiers| {
specifiers
.into_iter()
@ -1278,10 +1277,11 @@ fn collect_specifiers_with_test_mode(
/// as well.
async fn fetch_specifiers_with_test_mode(
ps: &ProcState,
files: FilesConfig,
doc: bool,
files: &FilesConfig,
doc: &bool,
) -> Result<Vec<(ModuleSpecifier, TestMode)>, AnyError> {
let mut specifiers_with_mode = collect_specifiers_with_test_mode(files, doc)?;
for (specifier, mode) in &mut specifiers_with_mode {
let file = ps
.file_fetcher
@ -1309,9 +1309,12 @@ pub async fn run_tests(
let permissions =
Permissions::from_options(&ps.options.permissions_options())?;
let specifiers_with_mode =
fetch_specifiers_with_test_mode(&ps, test_options.files, test_options.doc)
.await?;
let specifiers_with_mode = fetch_specifiers_with_test_mode(
&ps,
&test_options.files,
&test_options.doc,
)
.await?;
if !test_options.allow_none && specifiers_with_mode.is_empty() {
return Err(generic_error("No test modules found"));
@ -1326,7 +1329,7 @@ pub async fn run_tests(
test_specifiers(
ps,
permissions,
&permissions,
specifiers_with_mode,
TestSpecifierOptions {
concurrent_jobs: test_options.concurrent_jobs,
@ -1349,18 +1352,16 @@ pub async fn run_tests_with_watch(
// file would have impact on other files, which is undesirable.
let permissions =
Permissions::from_options(&ps.options.permissions_options())?;
let paths_to_watch: Vec<_> = test_options.files.include.clone();
let no_check = ps.options.type_check_mode() == TypeCheckMode::None;
let test_options = &test_options;
let ps = RefCell::new(ps);
let resolver = |changed: Option<Vec<PathBuf>>| {
let paths_to_watch = paths_to_watch.clone();
let paths_to_watch = test_options.files.include.clone();
let paths_to_watch_clone = paths_to_watch.clone();
let files_changed = changed.is_some();
let test_options = &test_options;
let ps = ps.borrow().clone();
async move {
@ -1477,16 +1478,16 @@ pub async fn run_tests_with_watch(
};
let operation = |modules_to_reload: Vec<(ModuleSpecifier, ModuleKind)>| {
let permissions = permissions.clone();
let permissions = &permissions;
let test_options = &test_options;
ps.borrow_mut().reset_for_file_watcher();
let ps = ps.borrow().clone();
let test_options = test_options.clone();
async move {
let specifiers_with_mode = fetch_specifiers_with_test_mode(
&ps,
test_options.files,
test_options.doc,
&test_options.files,
&test_options.doc,
)
.await?
.iter()
@ -1505,7 +1506,7 @@ pub async fn run_tests_with_watch(
test_specifiers(
ps,
permissions.clone(),
permissions,
specifiers_with_mode,
TestSpecifierOptions {
concurrent_jobs: test_options.concurrent_jobs,

View file

@ -263,7 +263,7 @@ pub async fn upgrade(
), current_exe_path.display());
}
let client = ps.http_client.clone();
let client = &ps.http_client;
let install_version = match upgrade_flags.version {
Some(passed_version) => {
@ -298,10 +298,10 @@ pub async fn upgrade(
None => {
let latest_version = if upgrade_flags.canary {
log::info!("Looking up latest canary version");
get_latest_canary_version(&client).await?
get_latest_canary_version(client).await?
} else {
log::info!("Looking up latest version");
get_latest_release_version(&client).await?
get_latest_release_version(client).await?
};
let current_is_most_recent = if upgrade_flags.canary {
@ -351,7 +351,7 @@ pub async fn upgrade(
)
};
let archive_data = download_package(&client, &download_url)
let archive_data = download_package(client, &download_url)
.await
.with_context(|| format!("Failed downloading {}", download_url))?;

View file

@ -813,7 +813,7 @@ mod test {
loader.add("https://localhost/mod.ts", "console.log(6);");
loader.add("https://localhost/other.ts", "import './mod.ts';");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.unwrap();
@ -860,7 +860,7 @@ mod test {
loader.add("https://remote/mod.ts", "import 'twind';");
loader.add("https://localhost/twind.ts", "export class Test {}");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.unwrap();
@ -909,7 +909,7 @@ mod test {
&[("content-type", "application/typescript")],
);
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.unwrap();
@ -954,7 +954,7 @@ mod test {
loader.add("https://localhost/mod.ts", "import '/logger.ts?test';");
loader.add("https://localhost/logger.ts?test", "export class Logger {}");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.unwrap();
@ -996,7 +996,7 @@ mod test {
loader.add("/vendor/deno.land/std/mod.ts", "export function f() {}");
loader.add("https://deno.land/std/mod.ts", "export function f() {}");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.err()
@ -1026,7 +1026,7 @@ mod test {
.with_loader(|loader| {
loader.add("/mod.ts", "console.log(5);");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.err()
@ -1056,7 +1056,7 @@ mod test {
.with_loader(|loader| {
loader.add("/mod.ts", "console.log(5);");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.err()
@ -1087,7 +1087,7 @@ mod test {
loader.add("/mod.ts", "import 'http/mod.ts';");
loader.add("https://deno.land/std/http/mod.ts", "console.log(5);");
})
.set_original_import_map(original_import_map.clone())
.set_original_import_map(original_import_map)
.build()
.await
.unwrap();

View file

@ -225,7 +225,7 @@ impl VendorTestBuilder {
let graph = build_test_graph(
roots,
self.original_import_map.clone(),
loader.clone(),
loader,
&*analyzer,
)
.await;