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