4860: Accept relative paths in rust-project.json r=matklad a=tweksteen

If a relative path is found as part of Crate.root_module or Root.path, interpret it as relative to the location of the rust-project.json file.

Fixes: #4816 

Co-authored-by: Thiébaud Weksteen <tweek@google.com>
This commit is contained in:
bors[bot] 2020-06-15 15:03:31 +00:00 committed by GitHub
commit f4f51171ca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 22 deletions

View File

@ -29,13 +29,7 @@ pub enum ProjectWorkspace {
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`. /// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
Cargo { cargo: CargoWorkspace, sysroot: Sysroot }, Cargo { cargo: CargoWorkspace, sysroot: Sysroot },
/// Project workspace was manually specified using a `rust-project.json` file. /// Project workspace was manually specified using a `rust-project.json` file.
Json { project: JsonProject }, Json { project: JsonProject, project_location: PathBuf },
}
impl From<JsonProject> for ProjectWorkspace {
fn from(project: JsonProject) -> ProjectWorkspace {
ProjectWorkspace::Json { project }
}
} }
/// `PackageRoot` describes a package root folder. /// `PackageRoot` describes a package root folder.
@ -164,10 +158,15 @@ impl ProjectWorkspace {
format!("Failed to open json file {}", project_json.display()) format!("Failed to open json file {}", project_json.display())
})?; })?;
let reader = BufReader::new(file); let reader = BufReader::new(file);
let project_location = match project_json.parent() {
Some(parent) => PathBuf::from(parent),
None => PathBuf::new(),
};
ProjectWorkspace::Json { ProjectWorkspace::Json {
project: from_reader(reader).with_context(|| { project: from_reader(reader).with_context(|| {
format!("Failed to deserialize json file {}", project_json.display()) format!("Failed to deserialize json file {}", project_json.display())
})?, })?,
project_location: project_location,
} }
} }
ProjectManifest::CargoToml(cargo_toml) => { ProjectManifest::CargoToml(cargo_toml) => {
@ -200,9 +199,11 @@ impl ProjectWorkspace {
/// the root is a member of the current workspace /// the root is a member of the current workspace
pub fn to_roots(&self) -> Vec<PackageRoot> { pub fn to_roots(&self) -> Vec<PackageRoot> {
match self { match self {
ProjectWorkspace::Json { project } => { ProjectWorkspace::Json { project, project_location } => project
project.roots.iter().map(|r| PackageRoot::new_member(r.path.clone())).collect() .roots
} .iter()
.map(|r| PackageRoot::new_member(project_location.join(&r.path)))
.collect(),
ProjectWorkspace::Cargo { cargo, sysroot } => cargo ProjectWorkspace::Cargo { cargo, sysroot } => cargo
.packages() .packages()
.map(|pkg| PackageRoot { .map(|pkg| PackageRoot {
@ -219,7 +220,7 @@ impl ProjectWorkspace {
pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> { pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> {
match self { match self {
ProjectWorkspace::Json { project } => project ProjectWorkspace::Json { project, .. } => project
.crates .crates
.iter() .iter()
.filter_map(|krate| krate.proc_macro_dylib_path.as_ref()) .filter_map(|krate| krate.proc_macro_dylib_path.as_ref())
@ -235,7 +236,7 @@ impl ProjectWorkspace {
pub fn n_packages(&self) -> usize { pub fn n_packages(&self) -> usize {
match self { match self {
ProjectWorkspace::Json { project } => project.crates.len(), ProjectWorkspace::Json { project, .. } => project.crates.len(),
ProjectWorkspace::Cargo { cargo, sysroot } => { ProjectWorkspace::Cargo { cargo, sysroot } => {
cargo.packages().len() + sysroot.crates().len() cargo.packages().len() + sysroot.crates().len()
} }
@ -251,13 +252,14 @@ impl ProjectWorkspace {
) -> CrateGraph { ) -> CrateGraph {
let mut crate_graph = CrateGraph::default(); let mut crate_graph = CrateGraph::default();
match self { match self {
ProjectWorkspace::Json { project } => { ProjectWorkspace::Json { project, project_location } => {
let crates: FxHashMap<_, _> = project let crates: FxHashMap<_, _> = project
.crates .crates
.iter() .iter()
.enumerate() .enumerate()
.filter_map(|(seq_index, krate)| { .filter_map(|(seq_index, krate)| {
let file_id = load(&krate.root_module)?; let file_path = project_location.join(&krate.root_module);
let file_id = load(&file_path)?;
let edition = match krate.edition { let edition = match krate.edition {
json_project::Edition::Edition2015 => Edition::Edition2015, json_project::Edition::Edition2015 => Edition::Edition2015,
json_project::Edition::Edition2018 => Edition::Edition2018, json_project::Edition::Edition2018 => Edition::Edition2018,
@ -540,7 +542,7 @@ impl ProjectWorkspace {
ProjectWorkspace::Cargo { cargo, .. } => { ProjectWorkspace::Cargo { cargo, .. } => {
Some(cargo.workspace_root()).filter(|root| path.starts_with(root)) Some(cargo.workspace_root()).filter(|root| path.starts_with(root))
} }
ProjectWorkspace::Json { project: JsonProject { roots, .. } } => roots ProjectWorkspace::Json { project: JsonProject { roots, .. }, .. } => roots
.iter() .iter()
.find(|root| path.starts_with(&root.path)) .find(|root| path.starts_with(&root.path))
.map(|root| root.path.as_ref()), .map(|root| root.path.as_ref()),

View File

@ -108,11 +108,11 @@ fn run_server() -> Result<()> {
config.update(value); config.update(value);
} }
config.update_caps(&initialize_params.capabilities); config.update_caps(&initialize_params.capabilities);
let cwd = std::env::current_dir()?;
config.root_path =
initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd);
if config.linked_projects.is_empty() { if config.linked_projects.is_empty() {
let cwd = std::env::current_dir()?;
let root =
initialize_params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd);
let workspace_roots = initialize_params let workspace_roots = initialize_params
.workspace_folders .workspace_folders
.map(|workspaces| { .map(|workspaces| {
@ -122,7 +122,7 @@ fn run_server() -> Result<()> {
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.filter(|workspaces| !workspaces.is_empty()) .filter(|workspaces| !workspaces.is_empty())
.unwrap_or_else(|| vec![root]); .unwrap_or_else(|| vec![config.root_path.clone()]);
config.linked_projects = ProjectManifest::discover_all(&workspace_roots) config.linked_projects = ProjectManifest::discover_all(&workspace_roots)
.into_iter() .into_iter()

View File

@ -38,12 +38,13 @@ pub struct Config {
pub with_sysroot: bool, pub with_sysroot: bool,
pub linked_projects: Vec<LinkedProject>, pub linked_projects: Vec<LinkedProject>,
pub root_path: PathBuf,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum LinkedProject { pub enum LinkedProject {
ProjectManifest(ProjectManifest), ProjectManifest(ProjectManifest),
JsonProject(JsonProject), InlineJsonProject(JsonProject),
} }
impl From<ProjectManifest> for LinkedProject { impl From<ProjectManifest> for LinkedProject {
@ -54,7 +55,7 @@ impl From<ProjectManifest> for LinkedProject {
impl From<JsonProject> for LinkedProject { impl From<JsonProject> for LinkedProject {
fn from(v: JsonProject) -> Self { fn from(v: JsonProject) -> Self {
LinkedProject::JsonProject(v) LinkedProject::InlineJsonProject(v)
} }
} }
@ -167,6 +168,7 @@ impl Default for Config {
lens: LensConfig::default(), lens: LensConfig::default(),
hover: HoverConfig::default(), hover: HoverConfig::default(),
linked_projects: Vec::new(), linked_projects: Vec::new(),
root_path: PathBuf::new(),
} }
} }
} }

View File

@ -121,7 +121,12 @@ pub fn main_loop(config: Config, connection: Connection) -> Result<()> {
}) })
.ok() .ok()
} }
LinkedProject::JsonProject(it) => Some(it.clone().into()), LinkedProject::InlineJsonProject(it) => {
Some(ra_project_model::ProjectWorkspace::Json {
project: it.clone(),
project_location: config.root_path.clone(),
})
}
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()
}; };