diff --git a/Cargo.lock b/Cargo.lock index 9c65b39f76..2f6a132a5f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1008,7 +1008,6 @@ dependencies = [ name = "ra_lsp_server" version = "0.1.0" dependencies = [ - "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "drop_bomb 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1021,6 +1020,7 @@ dependencies = [ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "ra_arena 0.1.0", "ra_ide_api 0.1.0", + "ra_project_model 0.1.0", "ra_syntax 0.1.0", "ra_text_edit 0.1.0", "ra_vfs 0.1.0", @@ -1045,6 +1045,20 @@ dependencies = [ "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ra_project_model" +version = "0.1.0" +dependencies = [ + "cargo_metadata 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ra_arena 0.1.0", + "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "smol_str 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "test_utils 0.1.0", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ra_syntax" version = "0.1.0" diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index bb92747f2f..f46d778930 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml @@ -19,7 +19,6 @@ url_serde = "0.2.0" lsp-types = "0.55.0" walkdir = "2.2.7" im = "12.0.0" -cargo_metadata = "0.7.0" rustc-hash = "1.0" parking_lot = "0.7.0" @@ -30,6 +29,7 @@ ra_ide_api = { path = "../ra_ide_api" } ra_arena = { path = "../ra_arena" } gen_lsp_server = { path = "../gen_lsp_server" } ra_vfs = { path = "../ra_vfs" } +ra_project_model = { path = "../ra_project_model" } [dev-dependencies] tempfile = "3" diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index fd5875a0ab..6800eb1388 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs @@ -1,34 +1,13 @@ -mod cargo_workspace; -mod sysroot; +use std::path::PathBuf; -use std::path::{Path, PathBuf}; - -use failure::bail; use thread_worker::{WorkerHandle, Worker}; use crate::Result; -pub use crate::project_model::{ - cargo_workspace::{CargoWorkspace, Package, Target, TargetKind}, - sysroot::Sysroot, +pub use ra_project_model::{ + ProjectWorkspace, CargoWorkspace, Package, Target, TargetKind, Sysroot, }; -#[derive(Debug, Clone)] -pub struct ProjectWorkspace { - pub(crate) cargo: CargoWorkspace, - pub(crate) sysroot: Sysroot, -} - -impl ProjectWorkspace { - pub fn discover(path: &Path) -> Result { - let cargo_toml = find_cargo_toml(path)?; - let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?; - let sysroot = Sysroot::discover(&cargo_toml)?; - let res = ProjectWorkspace { cargo, sysroot }; - Ok(res) - } -} - pub fn workspace_loader() -> (Worker>, WorkerHandle) { thread_worker::spawn::, _>( "workspace loader", @@ -42,18 +21,3 @@ pub fn workspace_loader() -> (Worker>, WorkerH }, ) } - -fn find_cargo_toml(path: &Path) -> Result { - if path.ends_with("Cargo.toml") { - return Ok(path.to_path_buf()); - } - let mut curr = Some(path); - while let Some(path) = curr { - let candidate = path.join("Cargo.toml"); - if candidate.exists() { - return Ok(candidate); - } - curr = path.parent(); - } - bail!("can't find Cargo.toml at {}", path.display()) -} diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml new file mode 100644 index 0000000000..5215e52326 --- /dev/null +++ b/crates/ra_project_model/Cargo.toml @@ -0,0 +1,30 @@ +[package] +edition = "2018" +name = "ra_project_model" +version = "0.1.0" +authors = ["Aleksey Kladov "] + +[dependencies] +# itertools = "0.8.0" +# join_to_string = "0.1.3" +# log = "0.4.5" +# relative-path = "0.4.0" +# rayon = "1.0.2" +# fst = "0.3.1" +rustc-hash = "1.0" +# parking_lot = "0.7.0" +# unicase = "2.2.0" + +# TODO get rid of these? +failure = "0.1.4" +failure_derive = "0.1.4" + +smol_str = { version = "0.1.9", features = ["serde"] } +walkdir = "2.2.7" + +cargo_metadata = "0.7.0" + +ra_arena = { path = "../ra_arena" } + +[dev-dependencies] +test_utils = { path = "../test_utils" } diff --git a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs similarity index 97% rename from crates/ra_lsp_server/src/project_model/cargo_workspace.rs rename to crates/ra_project_model/src/cargo_workspace.rs index 3b76389d23..f3e67d0e54 100644 --- a/crates/ra_lsp_server/src/project_model/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs @@ -1,17 +1,17 @@ use std::path::{Path, PathBuf}; use cargo_metadata::{MetadataCommand, CargoOpt}; -use ra_syntax::SmolStr; +use smol_str::SmolStr; use ra_arena::{Arena, RawId, impl_arena_id}; use rustc_hash::FxHashMap; use failure::format_err; use crate::Result; -/// `CargoWorksapce` represents the logical structure of, well, a Cargo +/// `CargoWorkspace` represents the logical structure of, well, a Cargo /// workspace. It pretty closely mirrors `cargo metadata` output. /// -/// Note that internally, rust analyzer uses a differnet structure: +/// Note that internally, rust analyzer uses a different structure: /// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates, /// while this knows about `Pacakges` & `Targets`: purely cargo-related /// concepts. @@ -162,9 +162,11 @@ impl CargoWorkspace { Ok(CargoWorkspace { packages, targets }) } + pub fn packages<'a>(&'a self) -> impl Iterator + 'a { self.packages.iter().map(|(id, _pkg)| id) } + pub fn target_by_root(&self, root: &Path) -> Option { self.packages().filter_map(|pkg| pkg.targets(self).find(|it| it.root(self) == root)).next() } diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs new file mode 100644 index 0000000000..3a7bbace75 --- /dev/null +++ b/crates/ra_project_model/src/lib.rs @@ -0,0 +1,45 @@ +mod cargo_workspace; +mod sysroot; + +use std::path::{Path, PathBuf}; + +use failure::bail; + +pub use crate::{ + cargo_workspace::{CargoWorkspace, Package, Target, TargetKind}, + sysroot::Sysroot, +}; + +// TODO use own error enum? +pub type Result = ::std::result::Result; + +#[derive(Debug, Clone)] +pub struct ProjectWorkspace { + pub cargo: CargoWorkspace, + pub sysroot: Sysroot, +} + +impl ProjectWorkspace { + pub fn discover(path: &Path) -> Result { + let cargo_toml = find_cargo_toml(path)?; + let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml)?; + let sysroot = Sysroot::discover(&cargo_toml)?; + let res = ProjectWorkspace { cargo, sysroot }; + Ok(res) + } +} + +fn find_cargo_toml(path: &Path) -> Result { + if path.ends_with("Cargo.toml") { + return Ok(path.to_path_buf()); + } + let mut curr = Some(path); + while let Some(path) = curr { + let candidate = path.join("Cargo.toml"); + if candidate.exists() { + return Ok(candidate); + } + curr = path.parent(); + } + bail!("can't find Cargo.toml at {}", path.display()) +} diff --git a/crates/ra_lsp_server/src/project_model/sysroot.rs b/crates/ra_project_model/src/sysroot.rs similarity index 84% rename from crates/ra_lsp_server/src/project_model/sysroot.rs rename to crates/ra_project_model/src/sysroot.rs index 49210ac7aa..18824dbe57 100644 --- a/crates/ra_lsp_server/src/project_model/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs @@ -3,7 +3,8 @@ use std::{ process::Command, }; -use ra_syntax::SmolStr; +use smol_str::SmolStr; + use ra_arena::{Arena, RawId, impl_arena_id}; use crate::Result; @@ -25,15 +26,15 @@ struct SysrootCrateData { } impl Sysroot { - pub(crate) fn std(&self) -> Option { + pub fn std(&self) -> Option { self.by_name("std") } - pub(crate) fn crates<'a>(&'a self) -> impl Iterator + 'a { + pub fn crates<'a>(&'a self) -> impl Iterator + 'a { self.crates.iter().map(|(id, _data)| id) } - pub(super) fn discover(cargo_toml: &Path) -> Result { + pub fn discover(cargo_toml: &Path) -> Result { let rustc_output = Command::new("rustc") .current_dir(cargo_toml.parent().unwrap()) .args(&["--print", "sysroot"]) @@ -80,16 +81,16 @@ impl Sysroot { } impl SysrootCrate { - pub(crate) fn name(self, sysroot: &Sysroot) -> &SmolStr { + pub fn name(self, sysroot: &Sysroot) -> &SmolStr { &sysroot.crates[self].name } - pub(crate) fn root(self, sysroot: &Sysroot) -> &Path { + pub fn root(self, sysroot: &Sysroot) -> &Path { sysroot.crates[self].root.as_path() } - pub(crate) fn root_dir(self, sysroot: &Sysroot) -> &Path { + pub fn root_dir(self, sysroot: &Sysroot) -> &Path { self.root(sysroot).parent().unwrap() } - pub(crate) fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator + 'a { + pub fn deps<'a>(self, sysroot: &'a Sysroot) -> impl Iterator + 'a { sysroot.crates[self].deps.iter().map(|&it| it) } } diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 0ec8492aa2..7c7a85a75c 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml @@ -15,7 +15,7 @@ drop_bomb = "0.1.4" parking_lot = "0.7.0" rowan = "0.3.3" -# ideally, `serde` should be enabled by `ra_lsp_serder`, but we enable it here +# ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here # to reduce number of compilations text_unit = { version = "0.1.6", features = ["serde"] } smol_str = { version = "0.1.9", features = ["serde"] }