mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
More direct CargoWorkspace
This commit is contained in:
parent
d013a05fee
commit
516fe293a8
3 changed files with 64 additions and 87 deletions
|
@ -1,6 +1,9 @@
|
|||
//! FIXME: write short doc here
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::{
|
||||
ops,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use cargo_metadata::{CargoOpt, Message, MetadataCommand, PackageId};
|
||||
|
@ -24,6 +27,20 @@ pub struct CargoWorkspace {
|
|||
workspace_root: PathBuf,
|
||||
}
|
||||
|
||||
impl ops::Index<Package> for CargoWorkspace {
|
||||
type Output = PackageData;
|
||||
fn index(&self, index: Package) -> &PackageData {
|
||||
&self.packages[index]
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Index<Target> for CargoWorkspace {
|
||||
type Output = TargetData;
|
||||
fn index(&self, index: Target) -> &TargetData {
|
||||
&self.targets[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
|
||||
#[serde(rename_all = "camelCase", default)]
|
||||
pub struct CargoFeatures {
|
||||
|
@ -61,15 +78,15 @@ pub struct Target(RawId);
|
|||
impl_arena_id!(Target);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct PackageData {
|
||||
name: String,
|
||||
manifest: PathBuf,
|
||||
targets: Vec<Target>,
|
||||
is_member: bool,
|
||||
dependencies: Vec<PackageDependency>,
|
||||
edition: Edition,
|
||||
features: Vec<String>,
|
||||
out_dir: Option<PathBuf>,
|
||||
pub struct PackageData {
|
||||
pub name: String,
|
||||
pub manifest: PathBuf,
|
||||
pub targets: Vec<Target>,
|
||||
pub is_member: bool,
|
||||
pub dependencies: Vec<PackageDependency>,
|
||||
pub edition: Edition,
|
||||
pub features: Vec<String>,
|
||||
pub out_dir: Option<PathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -79,12 +96,12 @@ pub struct PackageDependency {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct TargetData {
|
||||
pkg: Package,
|
||||
name: String,
|
||||
root: PathBuf,
|
||||
kind: TargetKind,
|
||||
is_proc_macro: bool,
|
||||
pub struct TargetData {
|
||||
pub package: Package,
|
||||
pub name: String,
|
||||
pub root: PathBuf,
|
||||
pub kind: TargetKind,
|
||||
pub is_proc_macro: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
|
@ -115,52 +132,9 @@ impl TargetKind {
|
|||
}
|
||||
}
|
||||
|
||||
impl Package {
|
||||
pub fn name(self, ws: &CargoWorkspace) -> &str {
|
||||
ws.packages[self].name.as_str()
|
||||
}
|
||||
pub fn root(self, ws: &CargoWorkspace) -> &Path {
|
||||
ws.packages[self].manifest.parent().unwrap()
|
||||
}
|
||||
pub fn edition(self, ws: &CargoWorkspace) -> Edition {
|
||||
ws.packages[self].edition
|
||||
}
|
||||
pub fn features(self, ws: &CargoWorkspace) -> &[String] {
|
||||
&ws.packages[self].features
|
||||
}
|
||||
pub fn targets<'a>(self, ws: &'a CargoWorkspace) -> impl Iterator<Item = Target> + 'a {
|
||||
ws.packages[self].targets.iter().cloned()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn is_member(self, ws: &CargoWorkspace) -> bool {
|
||||
ws.packages[self].is_member
|
||||
}
|
||||
pub fn dependencies<'a>(
|
||||
self,
|
||||
ws: &'a CargoWorkspace,
|
||||
) -> impl Iterator<Item = &'a PackageDependency> + 'a {
|
||||
ws.packages[self].dependencies.iter()
|
||||
}
|
||||
pub fn out_dir(self, ws: &CargoWorkspace) -> Option<&Path> {
|
||||
ws.packages[self].out_dir.as_ref().map(PathBuf::as_path)
|
||||
}
|
||||
}
|
||||
|
||||
impl Target {
|
||||
pub fn package(self, ws: &CargoWorkspace) -> Package {
|
||||
ws.targets[self].pkg
|
||||
}
|
||||
pub fn name(self, ws: &CargoWorkspace) -> &str {
|
||||
ws.targets[self].name.as_str()
|
||||
}
|
||||
pub fn root(self, ws: &CargoWorkspace) -> &Path {
|
||||
ws.targets[self].root.as_path()
|
||||
}
|
||||
pub fn kind(self, ws: &CargoWorkspace) -> TargetKind {
|
||||
ws.targets[self].kind
|
||||
}
|
||||
pub fn is_proc_macro(self, ws: &CargoWorkspace) -> bool {
|
||||
ws.targets[self].is_proc_macro
|
||||
impl PackageData {
|
||||
pub fn root(&self) -> &Path {
|
||||
self.manifest.parent().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -219,7 +193,7 @@ impl CargoWorkspace {
|
|||
for meta_tgt in meta_pkg.targets {
|
||||
let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"];
|
||||
let tgt = targets.alloc(TargetData {
|
||||
pkg,
|
||||
package: pkg,
|
||||
name: meta_tgt.name,
|
||||
root: meta_tgt.src_path.clone(),
|
||||
kind: TargetKind::new(meta_tgt.kind.as_slice()),
|
||||
|
@ -265,7 +239,10 @@ impl CargoWorkspace {
|
|||
}
|
||||
|
||||
pub fn target_by_root(&self, root: &Path) -> Option<Target> {
|
||||
self.packages().filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)).next()
|
||||
self.packages()
|
||||
.filter_map(|pkg| self[pkg].targets.iter().find(|&&it| self[it].root == root))
|
||||
.next()
|
||||
.copied()
|
||||
}
|
||||
|
||||
pub fn workspace_root(&self) -> &Path {
|
||||
|
|
|
@ -138,8 +138,8 @@ impl ProjectWorkspace {
|
|||
ProjectWorkspace::Cargo { cargo, sysroot } => {
|
||||
let mut roots = Vec::with_capacity(cargo.packages().len() + sysroot.crates().len());
|
||||
for pkg in cargo.packages() {
|
||||
let root = pkg.root(&cargo).to_path_buf();
|
||||
let member = pkg.is_member(&cargo);
|
||||
let root = cargo[pkg].root().to_path_buf();
|
||||
let member = cargo[pkg].is_member;
|
||||
roots.push(PackageRoot::new(root, member));
|
||||
}
|
||||
for krate in sysroot.crates() {
|
||||
|
@ -164,7 +164,7 @@ impl ProjectWorkspace {
|
|||
ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => {
|
||||
let mut out_dirs = Vec::with_capacity(cargo.packages().len());
|
||||
for pkg in cargo.packages() {
|
||||
if let Some(out_dir) = pkg.out_dir(&cargo) {
|
||||
if let Some(out_dir) = &cargo[pkg].out_dir {
|
||||
out_dirs.push(out_dir.to_path_buf());
|
||||
}
|
||||
}
|
||||
|
@ -309,18 +309,18 @@ impl ProjectWorkspace {
|
|||
// Next, create crates for each package, target pair
|
||||
for pkg in cargo.packages() {
|
||||
let mut lib_tgt = None;
|
||||
for tgt in pkg.targets(&cargo) {
|
||||
let root = tgt.root(&cargo);
|
||||
for &tgt in cargo[pkg].targets.iter() {
|
||||
let root = cargo[tgt].root.as_path();
|
||||
if let Some(file_id) = load(root) {
|
||||
let edition = pkg.edition(&cargo);
|
||||
let edition = cargo[pkg].edition;
|
||||
let cfg_options = {
|
||||
let mut opts = default_cfg_options.clone();
|
||||
opts.insert_features(pkg.features(&cargo).iter().map(Into::into));
|
||||
opts.insert_features(cargo[pkg].features.iter().map(Into::into));
|
||||
opts
|
||||
};
|
||||
let mut env = Env::default();
|
||||
let mut extern_source = ExternSource::default();
|
||||
if let Some(out_dir) = pkg.out_dir(cargo) {
|
||||
if let Some(out_dir) = &cargo[pkg].out_dir {
|
||||
// FIXME: We probably mangle non UTF-8 paths here, figure out a better solution
|
||||
env.set("OUT_DIR", out_dir.to_string_lossy().to_string());
|
||||
if let Some(&extern_source_id) = extern_source_roots.get(out_dir) {
|
||||
|
@ -330,16 +330,16 @@ impl ProjectWorkspace {
|
|||
let crate_id = crate_graph.add_crate_root(
|
||||
file_id,
|
||||
edition,
|
||||
Some(CrateName::normalize_dashes(pkg.name(&cargo))),
|
||||
Some(CrateName::normalize_dashes(&cargo[pkg].name)),
|
||||
cfg_options,
|
||||
env,
|
||||
extern_source,
|
||||
);
|
||||
if tgt.kind(&cargo) == TargetKind::Lib {
|
||||
if cargo[tgt].kind == TargetKind::Lib {
|
||||
lib_tgt = Some(crate_id);
|
||||
pkg_to_lib_crate.insert(pkg, crate_id);
|
||||
}
|
||||
if tgt.is_proc_macro(&cargo) {
|
||||
if cargo[tgt].is_proc_macro {
|
||||
if let Some(proc_macro) = libproc_macro {
|
||||
if crate_graph
|
||||
.add_dep(
|
||||
|
@ -351,7 +351,7 @@ impl ProjectWorkspace {
|
|||
{
|
||||
log::error!(
|
||||
"cyclic dependency on proc_macro for {}",
|
||||
pkg.name(&cargo)
|
||||
&cargo[pkg].name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ impl ProjectWorkspace {
|
|||
// For root projects with dashes in their name,
|
||||
// cargo metadata does not do any normalization,
|
||||
// so we do it ourselves currently
|
||||
CrateName::normalize_dashes(pkg.name(&cargo)),
|
||||
CrateName::normalize_dashes(&cargo[pkg].name),
|
||||
to,
|
||||
)
|
||||
.is_err()
|
||||
|
@ -379,7 +379,7 @@ impl ProjectWorkspace {
|
|||
{
|
||||
log::error!(
|
||||
"cyclic dependency between targets of {}",
|
||||
pkg.name(&cargo)
|
||||
&cargo[pkg].name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ impl ProjectWorkspace {
|
|||
.add_dep(from, CrateName::new("core").unwrap(), core)
|
||||
.is_err()
|
||||
{
|
||||
log::error!("cyclic dependency on core for {}", pkg.name(&cargo))
|
||||
log::error!("cyclic dependency on core for {}", &cargo[pkg].name)
|
||||
}
|
||||
}
|
||||
if let Some(alloc) = liballoc {
|
||||
|
@ -399,7 +399,7 @@ impl ProjectWorkspace {
|
|||
.add_dep(from, CrateName::new("alloc").unwrap(), alloc)
|
||||
.is_err()
|
||||
{
|
||||
log::error!("cyclic dependency on alloc for {}", pkg.name(&cargo))
|
||||
log::error!("cyclic dependency on alloc for {}", &cargo[pkg].name)
|
||||
}
|
||||
}
|
||||
if let Some(std) = libstd {
|
||||
|
@ -407,7 +407,7 @@ impl ProjectWorkspace {
|
|||
.add_dep(from, CrateName::new("std").unwrap(), std)
|
||||
.is_err()
|
||||
{
|
||||
log::error!("cyclic dependency on std for {}", pkg.name(&cargo))
|
||||
log::error!("cyclic dependency on std for {}", &cargo[pkg].name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ impl ProjectWorkspace {
|
|||
// Now add a dep edge from all targets of upstream to the lib
|
||||
// target of downstream.
|
||||
for pkg in cargo.packages() {
|
||||
for dep in pkg.dependencies(&cargo) {
|
||||
for dep in cargo[pkg].dependencies.iter() {
|
||||
if let Some(&to) = pkg_to_lib_crate.get(&dep.pkg) {
|
||||
for &from in pkg_crates.get(&pkg).into_iter().flatten() {
|
||||
if crate_graph
|
||||
|
@ -425,8 +425,8 @@ impl ProjectWorkspace {
|
|||
{
|
||||
log::error!(
|
||||
"cyclic dependency {} -> {}",
|
||||
pkg.name(&cargo),
|
||||
dep.pkg.name(&cargo)
|
||||
&cargo[pkg].name,
|
||||
&cargo[dep.pkg].name
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,9 +77,9 @@ impl CargoTargetSpec {
|
|||
ProjectWorkspace::Cargo { cargo, .. } => {
|
||||
let tgt = cargo.target_by_root(&path)?;
|
||||
Some(CargoTargetSpec {
|
||||
package: tgt.package(&cargo).name(&cargo).to_string(),
|
||||
target: tgt.name(&cargo).to_string(),
|
||||
target_kind: tgt.kind(&cargo),
|
||||
package: cargo[cargo[tgt].package].name.clone(),
|
||||
target: cargo[tgt].name.clone(),
|
||||
target_kind: cargo[tgt].kind,
|
||||
})
|
||||
}
|
||||
ProjectWorkspace::Json { .. } => None,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue