rem_extract/startup/
context.rs

1use anyhow::Context;
2use ra_ap_paths::Utf8PathBuf;
3use ra_ap_project_model::{
4    ProjectManifest,
5    RustLibSource,
6    ProjectWorkspace,
7    CargoConfig,
8};
9
10use ra_ap_base_db::{
11    ProcMacroPaths,
12    CrateGraph,
13};
14
15use ra_ap_paths::AbsPath;
16use ra_ap_paths::AbsPathBuf;
17use ra_ap_vfs::FileId;
18
19use super::types::{
20    SingleFileStdContext,
21    SysrootFileMap,
22    TempScriptAnchor,
23};
24
25
26pub(crate) fn build_single_file_std_context() -> anyhow::Result<SingleFileStdContext> {
27    // 1) Create a temporary anchor to act as our CargoScript - in creation we
28    //    also write out a minimal Rust file so RA doesn't choke.
29    let temp_anchor = TempScriptAnchor::new()?;
30
31    // 2) Convert the path to the anchor to a Utf8PathBuf and then AbsPathBuf.
32    let utf8 = Utf8PathBuf::from_path_buf(temp_anchor.path().clone())
33        .map_err(|_| anyhow::anyhow!("Temp path is not valid UTF-8: {:?}", temp_anchor.path()))?;
34    let abs_path = ra_ap_paths::AbsPathBuf::assert(utf8);
35
36    // 3) Treat this file as the "manifest" for a ProjectWorkspace. Construct
37    //    the workspace around it
38    let manifest = ProjectManifest::from_manifest_file(abs_path.clone())
39        .context("Failed to parse temporary Cargo manifest")?;
40
41    // 4) Configure Cargo to scan for sysroot sources.
42    let mut cargo_config = CargoConfig::default();
43    cargo_config.sysroot = Some(RustLibSource::Discover);
44
45    let extra_env = cargo_config.clone().extra_env;
46
47    let progress = |msg: String| {
48        eprintln!("ra_ap_project_model: {msg}");
49    };
50
51    // 5) Load Project Workspace (discovers sysroot, and builds internal model)
52    let ws = ProjectWorkspace::load(manifest, &cargo_config, &progress)
53        .context("Failed to load ProjectWorkspace for single-file std context")?;
54
55    // 6) Convert to a CrateGraph and ProcMacroPaths using a FileLoader.
56    let mut file_map = SysrootFileMap::new();
57
58    // FileLoader<'_> = &mut dyn FnMut(&AbsPath) -> Option<FileId>
59    let mut loader = |path: &AbsPath| -> Option<FileId> {
60        // AbsPathBuf::from(AbsPath) is not directly implemented; use to_path_buf()
61        let owned: AbsPathBuf = path.to_path_buf();
62        Some(file_map.file_id_for(owned))
63    };
64
65    let (base_graph, proc_macros):
66        (CrateGraph, ProcMacroPaths) =
67        ws.to_crate_graph(&mut loader, &extra_env);
68
69    // 7) base_graph now contains: core/std/alloc/etc. + dummy file crate.
70    //    proc_macros contains any proc-macro crates.
71    //    file_map has AbsPathBuf -> FileId for all of those.
72
73    Ok(SingleFileStdContext {
74        base_graph,
75        proc_macros,
76        sysroot_files: file_map,
77    })
78
79
80
81}