mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-11 20:58:54 +00:00
Be more explicit about absolute paths at various places
This commit is contained in:
parent
dff62def2e
commit
154cb8243b
11 changed files with 126 additions and 94 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1174,6 +1174,7 @@ dependencies = [
|
|||
"anyhow",
|
||||
"cargo_metadata",
|
||||
"log",
|
||||
"paths",
|
||||
"ra_arena",
|
||||
"ra_cfg",
|
||||
"ra_db",
|
||||
|
|
|
@ -28,6 +28,12 @@ impl AsRef<Path> for AbsPathBuf {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsRef<AbsPath> for AbsPathBuf {
|
||||
fn as_ref(&self) -> &AbsPath {
|
||||
self.as_path()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<PathBuf> for AbsPathBuf {
|
||||
type Error = PathBuf;
|
||||
fn try_from(path_buf: PathBuf) -> Result<AbsPathBuf, PathBuf> {
|
||||
|
@ -45,9 +51,19 @@ impl TryFrom<&str> for AbsPathBuf {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<AbsPath> for AbsPathBuf {
|
||||
fn eq(&self, other: &AbsPath) -> bool {
|
||||
self.as_path() == other
|
||||
}
|
||||
}
|
||||
|
||||
impl AbsPathBuf {
|
||||
pub fn assert(path: PathBuf) -> AbsPathBuf {
|
||||
AbsPathBuf::try_from(path)
|
||||
.unwrap_or_else(|path| panic!("expected absolute path, got {}", path.display()))
|
||||
}
|
||||
pub fn as_path(&self) -> &AbsPath {
|
||||
AbsPath::new_unchecked(self.0.as_path())
|
||||
AbsPath::assert(self.0.as_path())
|
||||
}
|
||||
pub fn pop(&mut self) -> bool {
|
||||
self.0.pop()
|
||||
|
@ -77,15 +93,19 @@ impl<'a> TryFrom<&'a Path> for &'a AbsPath {
|
|||
if !path.is_absolute() {
|
||||
return Err(path);
|
||||
}
|
||||
Ok(AbsPath::new_unchecked(path))
|
||||
Ok(AbsPath::assert(path))
|
||||
}
|
||||
}
|
||||
|
||||
impl AbsPath {
|
||||
fn new_unchecked(path: &Path) -> &AbsPath {
|
||||
pub fn assert(path: &Path) -> &AbsPath {
|
||||
assert!(path.is_absolute());
|
||||
unsafe { &*(path as *const Path as *const AbsPath) }
|
||||
}
|
||||
|
||||
pub fn parent(&self) -> Option<&AbsPath> {
|
||||
self.0.parent().map(AbsPath::assert)
|
||||
}
|
||||
pub fn join(&self, path: impl AsRef<Path>) -> AbsPathBuf {
|
||||
self.as_ref().join(path).try_into().unwrap()
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ ra_cfg = { path = "../ra_cfg" }
|
|||
ra_db = { path = "../ra_db" }
|
||||
ra_toolchain = { path = "../ra_toolchain" }
|
||||
ra_proc_macro = { path = "../ra_proc_macro" }
|
||||
paths = { path = "../paths" }
|
||||
|
||||
serde = { version = "1.0.106", features = ["derive"] }
|
||||
serde_json = "1.0.48"
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
//! FIXME: write short doc here
|
||||
|
||||
use std::{
|
||||
ffi::OsStr,
|
||||
ops,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
use std::{ffi::OsStr, ops, path::Path, process::Command};
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId};
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
use ra_arena::{Arena, Idx};
|
||||
use ra_db::Edition;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
@ -20,11 +16,14 @@ use rustc_hash::FxHashMap;
|
|||
/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates,
|
||||
/// while this knows about `Packages` & `Targets`: purely cargo-related
|
||||
/// concepts.
|
||||
///
|
||||
/// We use absolute paths here, `cargo metadata` guarantees to always produce
|
||||
/// abs paths.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CargoWorkspace {
|
||||
packages: Arena<PackageData>,
|
||||
targets: Arena<TargetData>,
|
||||
workspace_root: PathBuf,
|
||||
workspace_root: AbsPathBuf,
|
||||
}
|
||||
|
||||
impl ops::Index<Package> for CargoWorkspace {
|
||||
|
@ -80,15 +79,15 @@ pub type Target = Idx<TargetData>;
|
|||
pub struct PackageData {
|
||||
pub version: String,
|
||||
pub name: String,
|
||||
pub manifest: PathBuf,
|
||||
pub manifest: AbsPathBuf,
|
||||
pub targets: Vec<Target>,
|
||||
pub is_member: bool,
|
||||
pub dependencies: Vec<PackageDependency>,
|
||||
pub edition: Edition,
|
||||
pub features: Vec<String>,
|
||||
pub cfgs: Vec<String>,
|
||||
pub out_dir: Option<PathBuf>,
|
||||
pub proc_macro_dylib_path: Option<PathBuf>,
|
||||
pub out_dir: Option<AbsPathBuf>,
|
||||
pub proc_macro_dylib_path: Option<AbsPathBuf>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -101,7 +100,7 @@ pub struct PackageDependency {
|
|||
pub struct TargetData {
|
||||
pub package: Package,
|
||||
pub name: String,
|
||||
pub root: PathBuf,
|
||||
pub root: AbsPathBuf,
|
||||
pub kind: TargetKind,
|
||||
pub is_proc_macro: bool,
|
||||
}
|
||||
|
@ -135,7 +134,7 @@ impl TargetKind {
|
|||
}
|
||||
|
||||
impl PackageData {
|
||||
pub fn root(&self) -> &Path {
|
||||
pub fn root(&self) -> &AbsPath {
|
||||
self.manifest.parent().unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -193,7 +192,7 @@ impl CargoWorkspace {
|
|||
let pkg = packages.alloc(PackageData {
|
||||
name,
|
||||
version: version.to_string(),
|
||||
manifest: manifest_path,
|
||||
manifest: AbsPathBuf::assert(manifest_path),
|
||||
targets: Vec::new(),
|
||||
is_member,
|
||||
edition,
|
||||
|
@ -210,7 +209,7 @@ impl CargoWorkspace {
|
|||
let tgt = targets.alloc(TargetData {
|
||||
package: pkg,
|
||||
name: meta_tgt.name,
|
||||
root: meta_tgt.src_path.clone(),
|
||||
root: AbsPathBuf::assert(meta_tgt.src_path.clone()),
|
||||
kind: TargetKind::new(meta_tgt.kind.as_slice()),
|
||||
is_proc_macro,
|
||||
});
|
||||
|
@ -246,16 +245,17 @@ impl CargoWorkspace {
|
|||
packages[source].features.extend(node.features);
|
||||
}
|
||||
|
||||
Ok(CargoWorkspace { packages, targets, workspace_root: meta.workspace_root })
|
||||
let workspace_root = AbsPathBuf::assert(meta.workspace_root);
|
||||
Ok(CargoWorkspace { packages, targets, workspace_root: workspace_root })
|
||||
}
|
||||
|
||||
pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + ExactSizeIterator + 'a {
|
||||
self.packages.iter().map(|(id, _pkg)| id)
|
||||
}
|
||||
|
||||
pub fn target_by_root(&self, root: &Path) -> Option<Target> {
|
||||
pub fn target_by_root(&self, root: &AbsPath) -> Option<Target> {
|
||||
self.packages()
|
||||
.filter_map(|pkg| self[pkg].targets.iter().find(|&&it| self[it].root == root))
|
||||
.filter_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
|
||||
.next()
|
||||
.copied()
|
||||
}
|
||||
|
@ -279,8 +279,8 @@ impl CargoWorkspace {
|
|||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct ExternResources {
|
||||
out_dirs: FxHashMap<PackageId, PathBuf>,
|
||||
proc_dylib_paths: FxHashMap<PackageId, PathBuf>,
|
||||
out_dirs: FxHashMap<PackageId, AbsPathBuf>,
|
||||
proc_dylib_paths: FxHashMap<PackageId, AbsPathBuf>,
|
||||
cfgs: FxHashMap<PackageId, Vec<String>>,
|
||||
}
|
||||
|
||||
|
@ -308,6 +308,7 @@ pub fn load_extern_resources(
|
|||
if let Ok(message) = message {
|
||||
match message {
|
||||
Message::BuildScriptExecuted(BuildScript { package_id, out_dir, cfgs, .. }) => {
|
||||
let out_dir = AbsPathBuf::assert(out_dir);
|
||||
res.out_dirs.insert(package_id.clone(), out_dir);
|
||||
res.cfgs.insert(package_id, cfgs);
|
||||
}
|
||||
|
@ -317,7 +318,8 @@ pub fn load_extern_resources(
|
|||
// Skip rmeta file
|
||||
if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name))
|
||||
{
|
||||
res.proc_dylib_paths.insert(package_id, filename.clone());
|
||||
let filename = AbsPathBuf::assert(filename.clone());
|
||||
res.proc_dylib_paths.insert(package_id, filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,11 +7,12 @@ mod sysroot;
|
|||
use std::{
|
||||
fs::{read_dir, File, ReadDir},
|
||||
io::{self, BufReader},
|
||||
path::{Path, PathBuf},
|
||||
path::Path,
|
||||
process::{Command, Output},
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
use ra_cfg::CfgOptions;
|
||||
use ra_db::{CrateGraph, CrateName, Edition, Env, FileId};
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
|
@ -29,7 +30,7 @@ pub enum ProjectWorkspace {
|
|||
/// Project workspace was discovered by running `cargo metadata` and `rustc --print sysroot`.
|
||||
Cargo { cargo: CargoWorkspace, sysroot: Sysroot },
|
||||
/// Project workspace was manually specified using a `rust-project.json` file.
|
||||
Json { project: JsonProject, project_location: PathBuf },
|
||||
Json { project: JsonProject, project_location: AbsPathBuf },
|
||||
}
|
||||
|
||||
/// `PackageRoot` describes a package root folder.
|
||||
|
@ -38,22 +39,22 @@ pub enum ProjectWorkspace {
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct PackageRoot {
|
||||
/// Path to the root folder
|
||||
path: PathBuf,
|
||||
path: AbsPathBuf,
|
||||
/// Is a member of the current workspace
|
||||
is_member: bool,
|
||||
out_dir: Option<PathBuf>,
|
||||
out_dir: Option<AbsPathBuf>,
|
||||
}
|
||||
impl PackageRoot {
|
||||
pub fn new_member(path: PathBuf) -> PackageRoot {
|
||||
pub fn new_member(path: AbsPathBuf) -> PackageRoot {
|
||||
Self { path, is_member: true, out_dir: None }
|
||||
}
|
||||
pub fn new_non_member(path: PathBuf) -> PackageRoot {
|
||||
pub fn new_non_member(path: AbsPathBuf) -> PackageRoot {
|
||||
Self { path, is_member: false, out_dir: None }
|
||||
}
|
||||
pub fn path(&self) -> &Path {
|
||||
pub fn path(&self) -> &AbsPath {
|
||||
&self.path
|
||||
}
|
||||
pub fn out_dir(&self) -> Option<&Path> {
|
||||
pub fn out_dir(&self) -> Option<&AbsPath> {
|
||||
self.out_dir.as_deref()
|
||||
}
|
||||
pub fn is_member(&self) -> bool {
|
||||
|
@ -63,12 +64,12 @@ impl PackageRoot {
|
|||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||
pub enum ProjectManifest {
|
||||
ProjectJson(PathBuf),
|
||||
CargoToml(PathBuf),
|
||||
ProjectJson(AbsPathBuf),
|
||||
CargoToml(AbsPathBuf),
|
||||
}
|
||||
|
||||
impl ProjectManifest {
|
||||
pub fn from_manifest_file(path: PathBuf) -> Result<ProjectManifest> {
|
||||
pub fn from_manifest_file(path: AbsPathBuf) -> Result<ProjectManifest> {
|
||||
if path.ends_with("rust-project.json") {
|
||||
return Ok(ProjectManifest::ProjectJson(path));
|
||||
}
|
||||
|
@ -78,7 +79,7 @@ impl ProjectManifest {
|
|||
bail!("project root must point to Cargo.toml or rust-project.json: {}", path.display())
|
||||
}
|
||||
|
||||
pub fn discover_single(path: &Path) -> Result<ProjectManifest> {
|
||||
pub fn discover_single(path: &AbsPath) -> Result<ProjectManifest> {
|
||||
let mut candidates = ProjectManifest::discover(path)?;
|
||||
let res = match candidates.pop() {
|
||||
None => bail!("no projects"),
|
||||
|
@ -91,23 +92,23 @@ impl ProjectManifest {
|
|||
Ok(res)
|
||||
}
|
||||
|
||||
pub fn discover(path: &Path) -> io::Result<Vec<ProjectManifest>> {
|
||||
pub fn discover(path: &AbsPath) -> io::Result<Vec<ProjectManifest>> {
|
||||
if let Some(project_json) = find_in_parent_dirs(path, "rust-project.json") {
|
||||
return Ok(vec![ProjectManifest::ProjectJson(project_json)]);
|
||||
}
|
||||
return find_cargo_toml(path)
|
||||
.map(|paths| paths.into_iter().map(ProjectManifest::CargoToml).collect());
|
||||
|
||||
fn find_cargo_toml(path: &Path) -> io::Result<Vec<PathBuf>> {
|
||||
fn find_cargo_toml(path: &AbsPath) -> io::Result<Vec<AbsPathBuf>> {
|
||||
match find_in_parent_dirs(path, "Cargo.toml") {
|
||||
Some(it) => Ok(vec![it]),
|
||||
None => Ok(find_cargo_toml_in_child_dir(read_dir(path)?)),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_in_parent_dirs(path: &Path, target_file_name: &str) -> Option<PathBuf> {
|
||||
fn find_in_parent_dirs(path: &AbsPath, target_file_name: &str) -> Option<AbsPathBuf> {
|
||||
if path.ends_with(target_file_name) {
|
||||
return Some(path.to_owned());
|
||||
return Some(path.to_path_buf());
|
||||
}
|
||||
|
||||
let mut curr = Some(path);
|
||||
|
@ -123,17 +124,18 @@ impl ProjectManifest {
|
|||
None
|
||||
}
|
||||
|
||||
fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<PathBuf> {
|
||||
fn find_cargo_toml_in_child_dir(entities: ReadDir) -> Vec<AbsPathBuf> {
|
||||
// Only one level down to avoid cycles the easy way and stop a runaway scan with large projects
|
||||
entities
|
||||
.filter_map(Result::ok)
|
||||
.map(|it| it.path().join("Cargo.toml"))
|
||||
.filter(|it| it.exists())
|
||||
.map(AbsPathBuf::assert)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn discover_all(paths: &[impl AsRef<Path>]) -> Vec<ProjectManifest> {
|
||||
pub fn discover_all(paths: &[impl AsRef<AbsPath>]) -> Vec<ProjectManifest> {
|
||||
let mut res = paths
|
||||
.iter()
|
||||
.filter_map(|it| ProjectManifest::discover(it.as_ref()).ok())
|
||||
|
@ -158,15 +160,12 @@ impl ProjectWorkspace {
|
|||
format!("Failed to open json file {}", project_json.display())
|
||||
})?;
|
||||
let reader = BufReader::new(file);
|
||||
let project_location = match project_json.parent() {
|
||||
Some(parent) => PathBuf::from(parent),
|
||||
None => PathBuf::new(),
|
||||
};
|
||||
let project_location = project_json.parent().unwrap().to_path_buf();
|
||||
ProjectWorkspace::Json {
|
||||
project: from_reader(reader).with_context(|| {
|
||||
format!("Failed to deserialize json file {}", project_json.display())
|
||||
})?,
|
||||
project_location: project_location,
|
||||
project_location,
|
||||
}
|
||||
}
|
||||
ProjectManifest::CargoToml(cargo_toml) => {
|
||||
|
@ -218,13 +217,13 @@ impl ProjectWorkspace {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn proc_macro_dylib_paths(&self) -> Vec<PathBuf> {
|
||||
pub fn proc_macro_dylib_paths(&self) -> Vec<AbsPathBuf> {
|
||||
match self {
|
||||
ProjectWorkspace::Json { project, .. } => project
|
||||
ProjectWorkspace::Json { project, project_location } => project
|
||||
.crates
|
||||
.iter()
|
||||
.filter_map(|krate| krate.proc_macro_dylib_path.as_ref())
|
||||
.cloned()
|
||||
.map(|it| project_location.join(it))
|
||||
.collect(),
|
||||
ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => cargo
|
||||
.packages()
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
//! FIXME: write short doc here
|
||||
|
||||
use std::{
|
||||
env, ops,
|
||||
path::{Path, PathBuf},
|
||||
process::Command,
|
||||
};
|
||||
use std::{convert::TryFrom, env, ops, path::Path, process::Command};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use anyhow::{bail, format_err, Result};
|
||||
use ra_arena::{Arena, Idx};
|
||||
|
||||
use crate::output;
|
||||
use paths::{AbsPath, AbsPathBuf};
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
pub struct Sysroot {
|
||||
|
@ -21,7 +18,7 @@ pub type SysrootCrate = Idx<SysrootCrateData>;
|
|||
#[derive(Debug, Clone)]
|
||||
pub struct SysrootCrateData {
|
||||
pub name: String,
|
||||
pub root: PathBuf,
|
||||
pub root: AbsPathBuf,
|
||||
pub deps: Vec<SysrootCrate>,
|
||||
}
|
||||
|
||||
|
@ -53,7 +50,7 @@ impl Sysroot {
|
|||
self.crates.iter().map(|(id, _data)| id)
|
||||
}
|
||||
|
||||
pub fn discover(cargo_toml: &Path) -> Result<Sysroot> {
|
||||
pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
|
||||
let src = get_or_install_rust_src(cargo_toml)?;
|
||||
let mut sysroot = Sysroot { crates: Arena::default() };
|
||||
for name in SYSROOT_CRATES.trim().lines() {
|
||||
|
@ -86,16 +83,18 @@ impl Sysroot {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
|
||||
fn get_or_install_rust_src(cargo_toml: &AbsPath) -> Result<AbsPathBuf> {
|
||||
if let Ok(path) = env::var("RUST_SRC_PATH") {
|
||||
return Ok(path.into());
|
||||
let path = AbsPathBuf::try_from(path.as_str())
|
||||
.map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
|
||||
return Ok(path);
|
||||
}
|
||||
let current_dir = cargo_toml.parent().unwrap();
|
||||
let mut rustc = Command::new(ra_toolchain::rustc());
|
||||
rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
|
||||
let rustc_output = output(rustc)?;
|
||||
let stdout = String::from_utf8(rustc_output.stdout)?;
|
||||
let sysroot_path = Path::new(stdout.trim());
|
||||
let sysroot_path = AbsPath::assert(Path::new(stdout.trim()));
|
||||
let src_path = sysroot_path.join("lib/rustlib/src/rust/src");
|
||||
|
||||
if !src_path.exists() {
|
||||
|
@ -116,7 +115,7 @@ fn get_or_install_rust_src(cargo_toml: &Path) -> Result<PathBuf> {
|
|||
}
|
||||
|
||||
impl SysrootCrateData {
|
||||
pub fn root_dir(&self) -> &Path {
|
||||
pub fn root_dir(&self) -> &AbsPath {
|
||||
self.root.parent().unwrap()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
//! Based on cli flags, either spawns an LSP server, or runs a batch analysis
|
||||
mod args;
|
||||
|
||||
use std::convert::TryFrom;
|
||||
|
||||
use lsp_server::Connection;
|
||||
use rust_analyzer::{
|
||||
cli,
|
||||
|
@ -10,9 +12,11 @@ use rust_analyzer::{
|
|||
from_json, Result,
|
||||
};
|
||||
|
||||
use crate::args::HelpPrinted;
|
||||
use ra_db::AbsPathBuf;
|
||||
use ra_project_model::ProjectManifest;
|
||||
|
||||
use crate::args::HelpPrinted;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
setup_logging()?;
|
||||
let args = match args::Args::parse()? {
|
||||
|
@ -20,6 +24,9 @@ fn main() -> Result<()> {
|
|||
Err(HelpPrinted) => return Ok(()),
|
||||
};
|
||||
match args.command {
|
||||
args::Command::RunServer => run_server()?,
|
||||
args::Command::ProcMacro => ra_proc_macro_srv::cli::run()?,
|
||||
|
||||
args::Command::Parse { no_dump } => cli::parse(no_dump)?,
|
||||
args::Command::Symbols => cli::symbols()?,
|
||||
args::Command::Highlight { rainbow } => cli::highlight(rainbow)?,
|
||||
|
@ -41,7 +48,6 @@ fn main() -> Result<()> {
|
|||
load_output_dirs,
|
||||
with_proc_macro,
|
||||
)?,
|
||||
|
||||
args::Command::Bench { path, what, load_output_dirs, with_proc_macro } => {
|
||||
cli::analysis_bench(
|
||||
args.verbosity,
|
||||
|
@ -51,13 +57,9 @@ fn main() -> Result<()> {
|
|||
with_proc_macro,
|
||||
)?
|
||||
}
|
||||
|
||||
args::Command::Diagnostics { path, load_output_dirs, with_proc_macro, all } => {
|
||||
cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)?
|
||||
}
|
||||
|
||||
args::Command::ProcMacro => run_proc_macro_srv()?,
|
||||
args::Command::RunServer => run_server()?,
|
||||
args::Command::Version => println!("rust-analyzer {}", env!("REV")),
|
||||
}
|
||||
Ok(())
|
||||
|
@ -70,11 +72,6 @@ fn setup_logging() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn run_proc_macro_srv() -> Result<()> {
|
||||
ra_proc_macro_srv::cli::run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run_server() -> Result<()> {
|
||||
log::info!("lifecycle: server started");
|
||||
|
||||
|
@ -103,14 +100,23 @@ fn run_server() -> Result<()> {
|
|||
}
|
||||
|
||||
let config = {
|
||||
let mut config = Config::default();
|
||||
let root_path = match initialize_params
|
||||
.root_uri
|
||||
.and_then(|it| it.to_file_path().ok())
|
||||
.and_then(|it| AbsPathBuf::try_from(it).ok())
|
||||
{
|
||||
Some(it) => it,
|
||||
None => {
|
||||
let cwd = std::env::current_dir()?;
|
||||
AbsPathBuf::assert(cwd)
|
||||
}
|
||||
};
|
||||
|
||||
let mut config = Config::new(root_path);
|
||||
if let Some(value) = &initialize_params.initialization_options {
|
||||
config.update(value);
|
||||
}
|
||||
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() {
|
||||
let workspace_roots = initialize_params
|
||||
|
@ -119,6 +125,7 @@ fn run_server() -> Result<()> {
|
|||
workspaces
|
||||
.into_iter()
|
||||
.filter_map(|it| it.uri.to_file_path().ok())
|
||||
.filter_map(|it| AbsPathBuf::try_from(it).ok())
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.filter(|workspaces| !workspaces.is_empty())
|
||||
|
|
|
@ -16,7 +16,7 @@ pub fn load_cargo(
|
|||
load_out_dirs_from_check: bool,
|
||||
with_proc_macro: bool,
|
||||
) -> Result<(AnalysisHost, vfs::Vfs)> {
|
||||
let root = std::env::current_dir()?.join(root);
|
||||
let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
|
||||
let root = ProjectManifest::discover_single(&root)?;
|
||||
let ws = ProjectWorkspace::load(
|
||||
root,
|
||||
|
|
|
@ -11,6 +11,7 @@ use std::{ffi::OsString, path::PathBuf};
|
|||
|
||||
use crate::diagnostics::DiagnosticsConfig;
|
||||
use lsp_types::ClientCapabilities;
|
||||
use ra_db::AbsPathBuf;
|
||||
use ra_flycheck::FlycheckConfig;
|
||||
use ra_ide::{AssistConfig, CompletionConfig, HoverConfig, InlayHintsConfig};
|
||||
use ra_project_model::{CargoConfig, JsonProject, ProjectManifest};
|
||||
|
@ -40,7 +41,7 @@ pub struct Config {
|
|||
|
||||
pub with_sysroot: bool,
|
||||
pub linked_projects: Vec<LinkedProject>,
|
||||
pub root_path: PathBuf,
|
||||
pub root_path: AbsPathBuf,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -131,8 +132,8 @@ pub struct ClientCapsConfig {
|
|||
pub hover_actions: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
impl Config {
|
||||
pub fn new(root_path: AbsPathBuf) -> Self {
|
||||
Config {
|
||||
client_caps: ClientCapsConfig::default(),
|
||||
|
||||
|
@ -171,18 +172,16 @@ impl Default for Config {
|
|||
lens: LensConfig::default(),
|
||||
hover: HoverConfig::default(),
|
||||
linked_projects: Vec::new(),
|
||||
root_path: PathBuf::new(),
|
||||
root_path,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config {
|
||||
#[rustfmt::skip]
|
||||
pub fn update(&mut self, value: &serde_json::Value) {
|
||||
log::info!("Config::update({:#})", value);
|
||||
|
||||
let client_caps = self.client_caps.clone();
|
||||
*self = Default::default();
|
||||
*self = Config::new(self.root_path.clone());
|
||||
self.client_caps = client_caps;
|
||||
|
||||
set(value, "/withSysroot", &mut self.with_sysroot);
|
||||
|
@ -279,9 +278,12 @@ impl Config {
|
|||
self.linked_projects.clear();
|
||||
for linked_project in linked_projects {
|
||||
let linked_project = match linked_project {
|
||||
ManifestOrJsonProject::Manifest(it) => match ProjectManifest::from_manifest_file(it) {
|
||||
Ok(it) => it.into(),
|
||||
Err(_) => continue,
|
||||
ManifestOrJsonProject::Manifest(it) => {
|
||||
let path = self.root_path.join(it);
|
||||
match ProjectManifest::from_manifest_file(path) {
|
||||
Ok(it) => it.into(),
|
||||
Err(_) => continue,
|
||||
}
|
||||
}
|
||||
ManifestOrJsonProject::JsonProject(it) => it.into(),
|
||||
};
|
||||
|
|
|
@ -310,11 +310,10 @@ impl ProjectFolders {
|
|||
|
||||
let mut file_set_roots: Vec<VfsPath> = vec![];
|
||||
|
||||
let path = AbsPathBuf::try_from(path).unwrap();
|
||||
let entry = if root.is_member() {
|
||||
vfs::loader::Entry::local_cargo_package(path.clone())
|
||||
vfs::loader::Entry::local_cargo_package(path.to_path_buf())
|
||||
} else {
|
||||
vfs::loader::Entry::cargo_package_dependency(path.clone())
|
||||
vfs::loader::Entry::cargo_package_dependency(path.to_path_buf())
|
||||
};
|
||||
res.load.push(entry);
|
||||
if root.is_member() {
|
||||
|
@ -329,7 +328,7 @@ impl ProjectFolders {
|
|||
}
|
||||
file_set_roots.push(out_dir.into());
|
||||
}
|
||||
file_set_roots.push(path.into());
|
||||
file_set_roots.push(path.to_path_buf().into());
|
||||
|
||||
if root.is_member() {
|
||||
local_filesets.push(fsc.len());
|
||||
|
|
|
@ -17,6 +17,7 @@ use serde_json::{to_string_pretty, Value};
|
|||
use tempfile::TempDir;
|
||||
use test_utils::{find_mismatch, Fixture};
|
||||
|
||||
use ra_db::AbsPathBuf;
|
||||
use ra_project_model::ProjectManifest;
|
||||
use rust_analyzer::{
|
||||
config::{ClientCapsConfig, Config, FilesConfig, FilesWatcher, LinkedProject},
|
||||
|
@ -70,10 +71,11 @@ impl<'a> Project<'a> {
|
|||
fs::write(path.as_path(), entry.text.as_bytes()).unwrap();
|
||||
}
|
||||
|
||||
let tmp_dir_path = AbsPathBuf::assert(tmp_dir.path().to_path_buf());
|
||||
let mut roots =
|
||||
self.roots.into_iter().map(|root| tmp_dir.path().join(root)).collect::<Vec<_>>();
|
||||
self.roots.into_iter().map(|root| tmp_dir_path.join(root)).collect::<Vec<_>>();
|
||||
if roots.is_empty() {
|
||||
roots.push(tmp_dir.path().to_path_buf());
|
||||
roots.push(tmp_dir_path.clone());
|
||||
}
|
||||
let linked_projects = roots
|
||||
.into_iter()
|
||||
|
@ -91,7 +93,7 @@ impl<'a> Project<'a> {
|
|||
with_sysroot: self.with_sysroot,
|
||||
linked_projects,
|
||||
files: FilesConfig { watcher: FilesWatcher::Client, exclude: Vec::new() },
|
||||
..Config::default()
|
||||
..Config::new(tmp_dir_path)
|
||||
};
|
||||
if let Some(f) = &self.config {
|
||||
f(&mut config)
|
||||
|
|
Loading…
Reference in a new issue