mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-25 03:26:19 +00:00
⬆️ rust-analyzer
This commit is contained in:
parent
61c744d4fd
commit
a2a1d99545
126 changed files with 2098 additions and 904 deletions
|
@ -69,7 +69,7 @@ impl WorkspaceBuildScripts {
|
|||
cmd.args(&["check", "--quiet", "--workspace", "--message-format=json"]);
|
||||
|
||||
// --all-targets includes tests, benches and examples in addition to the
|
||||
// default lib and bins. This is an independent concept from the --targets
|
||||
// default lib and bins. This is an independent concept from the --target
|
||||
// flag below.
|
||||
cmd.arg("--all-targets");
|
||||
|
||||
|
|
|
@ -270,11 +270,7 @@ impl CargoWorkspace {
|
|||
config: &CargoConfig,
|
||||
progress: &dyn Fn(String),
|
||||
) -> Result<cargo_metadata::Metadata> {
|
||||
let target = config
|
||||
.target
|
||||
.clone()
|
||||
.or_else(|| cargo_config_build_target(cargo_toml, &config.extra_env))
|
||||
.or_else(|| rustc_discover_host_triple(cargo_toml, &config.extra_env));
|
||||
let targets = find_list_of_build_targets(config, cargo_toml);
|
||||
|
||||
let mut meta = MetadataCommand::new();
|
||||
meta.cargo_path(toolchain::cargo());
|
||||
|
@ -294,8 +290,12 @@ impl CargoWorkspace {
|
|||
}
|
||||
meta.current_dir(current_dir.as_os_str());
|
||||
|
||||
if let Some(target) = target {
|
||||
meta.other_options(vec![String::from("--filter-platform"), target]);
|
||||
if !targets.is_empty() {
|
||||
let other_options: Vec<_> = targets
|
||||
.into_iter()
|
||||
.flat_map(|target| ["--filter-platform".to_string(), target])
|
||||
.collect();
|
||||
meta.other_options(other_options);
|
||||
}
|
||||
|
||||
// FIXME: Fetching metadata is a slow process, as it might require
|
||||
|
@ -469,6 +469,19 @@ impl CargoWorkspace {
|
|||
}
|
||||
}
|
||||
|
||||
fn find_list_of_build_targets(config: &CargoConfig, cargo_toml: &ManifestPath) -> Vec<String> {
|
||||
if let Some(target) = &config.target {
|
||||
return [target.into()].to_vec();
|
||||
}
|
||||
|
||||
let build_targets = cargo_config_build_target(cargo_toml, &config.extra_env);
|
||||
if !build_targets.is_empty() {
|
||||
return build_targets;
|
||||
}
|
||||
|
||||
rustc_discover_host_triple(cargo_toml, &config.extra_env).into_iter().collect()
|
||||
}
|
||||
|
||||
fn rustc_discover_host_triple(
|
||||
cargo_toml: &ManifestPath,
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
|
@ -499,7 +512,7 @@ fn rustc_discover_host_triple(
|
|||
fn cargo_config_build_target(
|
||||
cargo_toml: &ManifestPath,
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
) -> Option<String> {
|
||||
) -> Vec<String> {
|
||||
let mut cargo_config = Command::new(toolchain::cargo());
|
||||
cargo_config.envs(extra_env);
|
||||
cargo_config
|
||||
|
@ -507,12 +520,21 @@ fn cargo_config_build_target(
|
|||
.args(&["-Z", "unstable-options", "config", "get", "build.target"])
|
||||
.env("RUSTC_BOOTSTRAP", "1");
|
||||
// if successful we receive `build.target = "target-triple"`
|
||||
// or `build.target = ["<target 1>", ..]`
|
||||
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
|
||||
match utf8_stdout(cargo_config) {
|
||||
Ok(stdout) => stdout
|
||||
.strip_prefix("build.target = \"")
|
||||
.and_then(|stdout| stdout.strip_suffix('"'))
|
||||
.map(ToOwned::to_owned),
|
||||
Err(_) => None,
|
||||
}
|
||||
utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
|
||||
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
|
||||
|
||||
if !trimmed.starts_with('[') {
|
||||
return [trimmed.to_string()].to_vec();
|
||||
}
|
||||
|
||||
let res = serde_json::from_str(trimmed);
|
||||
if let Err(e) = &res {
|
||||
tracing::warn!("Failed to parse `build.target` as an array of target: {}`", e);
|
||||
}
|
||||
res.unwrap_or_default()
|
||||
}
|
||||
|
|
|
@ -128,14 +128,18 @@ impl Sysroot {
|
|||
}
|
||||
|
||||
if let Some(alloc) = sysroot.by_name("alloc") {
|
||||
if let Some(core) = sysroot.by_name("core") {
|
||||
sysroot.crates[alloc].deps.push(core);
|
||||
for dep in ALLOC_DEPS.trim().lines() {
|
||||
if let Some(dep) = sysroot.by_name(dep) {
|
||||
sysroot.crates[alloc].deps.push(dep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(proc_macro) = sysroot.by_name("proc_macro") {
|
||||
if let Some(std) = sysroot.by_name("std") {
|
||||
sysroot.crates[proc_macro].deps.push(std);
|
||||
for dep in PROC_MACRO_DEPS.trim().lines() {
|
||||
if let Some(dep) = sysroot.by_name(dep) {
|
||||
sysroot.crates[proc_macro].deps.push(dep)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -239,6 +243,7 @@ fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
|
|||
|
||||
const SYSROOT_CRATES: &str = "
|
||||
alloc
|
||||
backtrace
|
||||
core
|
||||
panic_abort
|
||||
panic_unwind
|
||||
|
@ -246,17 +251,19 @@ proc_macro
|
|||
profiler_builtins
|
||||
std
|
||||
stdarch/crates/std_detect
|
||||
term
|
||||
test
|
||||
unwind";
|
||||
|
||||
const ALLOC_DEPS: &str = "core";
|
||||
|
||||
const STD_DEPS: &str = "
|
||||
alloc
|
||||
core
|
||||
panic_abort
|
||||
panic_unwind
|
||||
panic_abort
|
||||
core
|
||||
profiler_builtins
|
||||
unwind
|
||||
std_detect
|
||||
term
|
||||
test
|
||||
unwind";
|
||||
test";
|
||||
|
||||
const PROC_MACRO_DEPS: &str = "std";
|
||||
|
|
|
@ -1566,10 +1566,10 @@ fn rust_project_hello_world_project_model() {
|
|||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
1,
|
||||
3,
|
||||
),
|
||||
name: CrateName(
|
||||
"core",
|
||||
"panic_unwind",
|
||||
),
|
||||
prelude: true,
|
||||
},
|
||||
|
@ -1584,10 +1584,10 @@ fn rust_project_hello_world_project_model() {
|
|||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
3,
|
||||
1,
|
||||
),
|
||||
name: CrateName(
|
||||
"panic_unwind",
|
||||
"core",
|
||||
),
|
||||
prelude: true,
|
||||
},
|
||||
|
@ -1600,6 +1600,15 @@ fn rust_project_hello_world_project_model() {
|
|||
),
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
9,
|
||||
),
|
||||
name: CrateName(
|
||||
"unwind",
|
||||
),
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
7,
|
||||
|
@ -1613,29 +1622,11 @@ fn rust_project_hello_world_project_model() {
|
|||
crate_id: CrateId(
|
||||
8,
|
||||
),
|
||||
name: CrateName(
|
||||
"term",
|
||||
),
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
9,
|
||||
),
|
||||
name: CrateName(
|
||||
"test",
|
||||
),
|
||||
prelude: true,
|
||||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
10,
|
||||
),
|
||||
name: CrateName(
|
||||
"unwind",
|
||||
),
|
||||
prelude: true,
|
||||
},
|
||||
],
|
||||
proc_macro: Err(
|
||||
"no proc macro loaded for sysroot crate",
|
||||
|
@ -1687,40 +1678,6 @@ fn rust_project_hello_world_project_model() {
|
|||
),
|
||||
edition: Edition2018,
|
||||
version: None,
|
||||
display_name: Some(
|
||||
CrateDisplayName {
|
||||
crate_name: CrateName(
|
||||
"term",
|
||||
),
|
||||
canonical_name: "term",
|
||||
},
|
||||
),
|
||||
cfg_options: CfgOptions(
|
||||
[],
|
||||
),
|
||||
potential_cfg_options: CfgOptions(
|
||||
[],
|
||||
),
|
||||
env: Env {
|
||||
entries: {},
|
||||
},
|
||||
dependencies: [],
|
||||
proc_macro: Err(
|
||||
"no proc macro loaded for sysroot crate",
|
||||
),
|
||||
origin: Lang(
|
||||
Other,
|
||||
),
|
||||
is_proc_macro: false,
|
||||
},
|
||||
CrateId(
|
||||
9,
|
||||
): CrateData {
|
||||
root_file_id: FileId(
|
||||
10,
|
||||
),
|
||||
edition: Edition2018,
|
||||
version: None,
|
||||
display_name: Some(
|
||||
CrateDisplayName {
|
||||
crate_name: CrateName(
|
||||
|
@ -1748,10 +1705,10 @@ fn rust_project_hello_world_project_model() {
|
|||
is_proc_macro: false,
|
||||
},
|
||||
CrateId(
|
||||
10,
|
||||
9,
|
||||
): CrateData {
|
||||
root_file_id: FileId(
|
||||
11,
|
||||
10,
|
||||
),
|
||||
edition: Edition2018,
|
||||
version: None,
|
||||
|
@ -1782,10 +1739,10 @@ fn rust_project_hello_world_project_model() {
|
|||
is_proc_macro: false,
|
||||
},
|
||||
CrateId(
|
||||
11,
|
||||
10,
|
||||
): CrateData {
|
||||
root_file_id: FileId(
|
||||
12,
|
||||
11,
|
||||
),
|
||||
edition: Edition2018,
|
||||
version: None,
|
||||
|
@ -1836,7 +1793,7 @@ fn rust_project_hello_world_project_model() {
|
|||
},
|
||||
Dependency {
|
||||
crate_id: CrateId(
|
||||
9,
|
||||
8,
|
||||
),
|
||||
name: CrateName(
|
||||
"test",
|
||||
|
|
|
@ -377,6 +377,21 @@ impl ProjectWorkspace {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn find_sysroot_proc_macro_srv(&self) -> Option<AbsPathBuf> {
|
||||
match self {
|
||||
ProjectWorkspace::Cargo { sysroot: Some(sysroot), .. }
|
||||
| ProjectWorkspace::Json { sysroot: Some(sysroot), .. } => {
|
||||
let standalone_server_name =
|
||||
format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
|
||||
["libexec", "lib"]
|
||||
.into_iter()
|
||||
.map(|segment| sysroot.root().join(segment).join(&standalone_server_name))
|
||||
.find(|server_path| std::fs::metadata(&server_path).is_ok())
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the roots for the current `ProjectWorkspace`
|
||||
/// The return type contains the path and whether or not
|
||||
/// the root is a member of the current workspace
|
||||
|
@ -509,14 +524,14 @@ impl ProjectWorkspace {
|
|||
build_scripts,
|
||||
toolchain: _,
|
||||
} => cargo_to_crate_graph(
|
||||
rustc_cfg.clone(),
|
||||
cfg_overrides,
|
||||
load_proc_macro,
|
||||
load,
|
||||
cargo,
|
||||
build_scripts,
|
||||
sysroot.as_ref(),
|
||||
rustc,
|
||||
cargo,
|
||||
sysroot.as_ref(),
|
||||
rustc_cfg.clone(),
|
||||
cfg_overrides,
|
||||
build_scripts,
|
||||
),
|
||||
ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => {
|
||||
detached_files_to_crate_graph(rustc_cfg.clone(), load, files, sysroot)
|
||||
|
@ -602,7 +617,7 @@ fn project_json_to_crate_graph(
|
|||
for (from, krate) in project.crates() {
|
||||
if let Some(&from) = crates.get(&from) {
|
||||
if let Some((public_deps, libproc_macro)) = &sysroot_deps {
|
||||
public_deps.add(from, &mut crate_graph);
|
||||
public_deps.add_to_crate_graph(&mut crate_graph, from);
|
||||
if krate.is_proc_macro {
|
||||
if let Some(proc_macro) = libproc_macro {
|
||||
add_dep(
|
||||
|
@ -626,14 +641,14 @@ fn project_json_to_crate_graph(
|
|||
}
|
||||
|
||||
fn cargo_to_crate_graph(
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
override_cfg: &CfgOverrides,
|
||||
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
|
||||
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
|
||||
cargo: &CargoWorkspace,
|
||||
build_scripts: &WorkspaceBuildScripts,
|
||||
sysroot: Option<&Sysroot>,
|
||||
rustc: &Option<CargoWorkspace>,
|
||||
cargo: &CargoWorkspace,
|
||||
sysroot: Option<&Sysroot>,
|
||||
rustc_cfg: Vec<CfgFlag>,
|
||||
override_cfg: &CfgOverrides,
|
||||
build_scripts: &WorkspaceBuildScripts,
|
||||
) -> CrateGraph {
|
||||
let _p = profile::span("cargo_to_crate_graph");
|
||||
let mut crate_graph = CrateGraph::default();
|
||||
|
@ -642,13 +657,15 @@ fn cargo_to_crate_graph(
|
|||
None => (SysrootPublicDeps::default(), None),
|
||||
};
|
||||
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
cfg_options.extend(rustc_cfg);
|
||||
let cfg_options = {
|
||||
let mut cfg_options = CfgOptions::default();
|
||||
cfg_options.extend(rustc_cfg);
|
||||
cfg_options.insert_atom("debug_assertions".into());
|
||||
cfg_options
|
||||
};
|
||||
|
||||
let mut pkg_to_lib_crate = FxHashMap::default();
|
||||
|
||||
cfg_options.insert_atom("debug_assertions".into());
|
||||
|
||||
let mut pkg_crates = FxHashMap::default();
|
||||
// Does any crate signal to rust-analyzer that they need the rustc_private crates?
|
||||
let mut has_private = false;
|
||||
|
@ -723,7 +740,7 @@ fn cargo_to_crate_graph(
|
|||
// Set deps to the core, std and to the lib target of the current package
|
||||
for &(from, kind) in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
// Add sysroot deps first so that a lib target named `core` etc. can overwrite them.
|
||||
public_deps.add(from, &mut crate_graph);
|
||||
public_deps.add_to_crate_graph(&mut crate_graph, from);
|
||||
|
||||
if let Some((to, name)) = lib_tgt.clone() {
|
||||
if to != from && kind != TargetKind::BuildScript {
|
||||
|
@ -767,15 +784,16 @@ fn cargo_to_crate_graph(
|
|||
if let Some(rustc_workspace) = rustc {
|
||||
handle_rustc_crates(
|
||||
&mut crate_graph,
|
||||
rustc_workspace,
|
||||
&mut pkg_to_lib_crate,
|
||||
load,
|
||||
load_proc_macro,
|
||||
rustc_workspace,
|
||||
cargo,
|
||||
&public_deps,
|
||||
libproc_macro,
|
||||
&pkg_crates,
|
||||
&cfg_options,
|
||||
override_cfg,
|
||||
load_proc_macro,
|
||||
&mut pkg_to_lib_crate,
|
||||
&public_deps,
|
||||
cargo,
|
||||
&pkg_crates,
|
||||
build_scripts,
|
||||
);
|
||||
}
|
||||
|
@ -825,28 +843,29 @@ fn detached_files_to_crate_graph(
|
|||
},
|
||||
);
|
||||
|
||||
public_deps.add(detached_file_crate, &mut crate_graph);
|
||||
public_deps.add_to_crate_graph(&mut crate_graph, detached_file_crate);
|
||||
}
|
||||
crate_graph
|
||||
}
|
||||
|
||||
fn handle_rustc_crates(
|
||||
crate_graph: &mut CrateGraph,
|
||||
rustc_workspace: &CargoWorkspace,
|
||||
pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
|
||||
load: &mut dyn FnMut(&AbsPath) -> Option<FileId>,
|
||||
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
|
||||
rustc_workspace: &CargoWorkspace,
|
||||
cargo: &CargoWorkspace,
|
||||
public_deps: &SysrootPublicDeps,
|
||||
libproc_macro: Option<CrateId>,
|
||||
pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>,
|
||||
cfg_options: &CfgOptions,
|
||||
override_cfg: &CfgOverrides,
|
||||
load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult,
|
||||
pkg_to_lib_crate: &mut FxHashMap<Package, CrateId>,
|
||||
public_deps: &SysrootPublicDeps,
|
||||
cargo: &CargoWorkspace,
|
||||
pkg_crates: &FxHashMap<Package, Vec<(CrateId, TargetKind)>>,
|
||||
build_scripts: &WorkspaceBuildScripts,
|
||||
) {
|
||||
let mut rustc_pkg_crates = FxHashMap::default();
|
||||
// The root package of the rustc-dev component is rustc_driver, so we match that
|
||||
let root_pkg =
|
||||
rustc_workspace.packages().find(|package| rustc_workspace[*package].name == "rustc_driver");
|
||||
rustc_workspace.packages().find(|&package| rustc_workspace[package].name == "rustc_driver");
|
||||
// The rustc workspace might be incomplete (such as if rustc-dev is not
|
||||
// installed for the current toolchain) and `rustc_source` is set to discover.
|
||||
if let Some(root_pkg) = root_pkg {
|
||||
|
@ -901,7 +920,16 @@ fn handle_rustc_crates(
|
|||
);
|
||||
pkg_to_lib_crate.insert(pkg, crate_id);
|
||||
// Add dependencies on core / std / alloc for this crate
|
||||
public_deps.add(crate_id, crate_graph);
|
||||
public_deps.add_to_crate_graph(crate_graph, crate_id);
|
||||
if let Some(proc_macro) = libproc_macro {
|
||||
add_dep_with_prelude(
|
||||
crate_graph,
|
||||
crate_id,
|
||||
CrateName::new("proc_macro").unwrap(),
|
||||
proc_macro,
|
||||
rustc_workspace[tgt].is_proc_macro,
|
||||
);
|
||||
}
|
||||
rustc_pkg_crates.entry(pkg).or_insert_with(Vec::new).push(crate_id);
|
||||
}
|
||||
}
|
||||
|
@ -1009,7 +1037,7 @@ struct SysrootPublicDeps {
|
|||
|
||||
impl SysrootPublicDeps {
|
||||
/// Makes `from` depend on the public sysroot crates.
|
||||
fn add(&self, from: CrateId, crate_graph: &mut CrateGraph) {
|
||||
fn add_to_crate_graph(&self, crate_graph: &mut CrateGraph, from: CrateId) {
|
||||
for (name, krate, prelude) in &self.deps {
|
||||
add_dep_with_prelude(crate_graph, from, name.clone(), *krate, *prelude);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue