diff options
| author | bors <bors@rust-lang.org> | 2023-03-15 10:36:50 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-03-15 10:36:50 +0000 |
| commit | 1787c14e725e4ac416828f986b095a23ecd11494 (patch) | |
| tree | 61fc3d87c3bef5429c6c7138f6403b29bca5b513 | |
| parent | 579797f0eca3963f9c9d23c29def3da42e8c944a (diff) | |
| parent | d9c7d28e0d306ef3f259fe06b75385867335906e (diff) | |
| download | rust-1787c14e725e4ac416828f986b095a23ecd11494.tar.gz rust-1787c14e725e4ac416828f986b095a23ecd11494.zip | |
Auto merge of #14358 - Veykril:err-reporting, r=Veykril
Report sysroot and rustc crate loading errors Also aggregates the warnings and errors so we don't discard previous ones. cc https://github.com/rust-lang/rust-analyzer/issues/14327
| -rw-r--r-- | crates/project-model/src/cargo_workspace.rs | 6 | ||||
| -rw-r--r-- | crates/project-model/src/lib.rs | 2 | ||||
| -rw-r--r-- | crates/project-model/src/tests.rs | 6 | ||||
| -rw-r--r-- | crates/project-model/src/workspace.rs | 209 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/cli/analysis_stats.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/cli/diagnostics.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/cli/lsif.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/cli/scip.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/cli/ssr.rs | 4 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/config.rs | 10 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/lsp_utils.rs | 40 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 17 | ||||
| -rw-r--r-- | crates/rust-analyzer/src/reload.rs | 41 |
13 files changed, 194 insertions, 157 deletions
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index 732adc50b50..01162b1a8ba 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -50,7 +50,7 @@ impl ops::Index<Target> for CargoWorkspace { /// Describes how to set the rustc source directory. #[derive(Clone, Debug, PartialEq, Eq)] -pub enum RustcSource { +pub enum RustLibSource { /// Explicit path for the rustc source directory. Path(AbsPathBuf), /// Try to automatically detect where the rustc source directory is. @@ -95,10 +95,10 @@ pub struct CargoConfig { /// rustc target pub target: Option<String>, /// Sysroot loading behavior - pub sysroot: Option<RustcSource>, + pub sysroot: Option<RustLibSource>, pub sysroot_src: Option<AbsPathBuf>, /// rustc private crate source - pub rustc_source: Option<RustcSource>, + pub rustc_source: Option<RustLibSource>, /// crates to disable `#[cfg(test)]` on pub unset_test_crates: UnsetTestCrates, /// Invoke `cargo check` through the RUSTC_WRAPPER. diff --git a/crates/project-model/src/lib.rs b/crates/project-model/src/lib.rs index 9b6a71db811..70cb71ae3bd 100644 --- a/crates/project-model/src/lib.rs +++ b/crates/project-model/src/lib.rs @@ -44,7 +44,7 @@ pub use crate::{ build_scripts::WorkspaceBuildScripts, cargo_workspace::{ CargoConfig, CargoFeatures, CargoWorkspace, Package, PackageData, PackageDependency, - RustcSource, Target, TargetData, TargetKind, UnsetTestCrates, + RustLibSource, Target, TargetData, TargetKind, UnsetTestCrates, }, manifest_path::ManifestPath, project_json::{ProjectJson, ProjectJsonData}, diff --git a/crates/project-model/src/tests.rs b/crates/project-model/src/tests.rs index 749eee531ee..3754accbb03 100644 --- a/crates/project-model/src/tests.rs +++ b/crates/project-model/src/tests.rs @@ -24,8 +24,8 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr let project_workspace = ProjectWorkspace::Cargo { cargo: cargo_workspace, build_scripts: WorkspaceBuildScripts::default(), - sysroot: None, - rustc: None, + sysroot: Err(None), + rustc: Err(None), rustc_cfg: Vec::new(), cfg_overrides, toolchain: None, @@ -37,7 +37,7 @@ fn load_cargo_with_overrides(file: &str, cfg_overrides: CfgOverrides) -> CrateGr fn load_rust_project(file: &str) -> CrateGraph { let data = get_test_json_file(file); let project = rooted_project_json(data); - let sysroot = Some(get_fake_sysroot()); + let sysroot = Ok(get_fake_sysroot()); let project_workspace = ProjectWorkspace::Json { project, sysroot, rustc_cfg: Vec::new() }; to_crate_graph(project_workspace) } diff --git a/crates/project-model/src/workspace.rs b/crates/project-model/src/workspace.rs index 816950b22f4..d1e53e12eeb 100644 --- a/crates/project-model/src/workspace.rs +++ b/crates/project-model/src/workspace.rs @@ -17,7 +17,7 @@ use stdx::{always, hash::NoHashHashMap}; use crate::{ build_scripts::BuildScriptOutput, - cargo_workspace::{DepKind, PackageData, RustcSource}, + cargo_workspace::{DepKind, PackageData, RustLibSource}, cfg_flag::CfgFlag, rustc_cfg, sysroot::SysrootCrate, @@ -69,8 +69,8 @@ pub enum ProjectWorkspace { Cargo { cargo: CargoWorkspace, build_scripts: WorkspaceBuildScripts, - sysroot: Option<Sysroot>, - rustc: Option<(CargoWorkspace, WorkspaceBuildScripts)>, + sysroot: Result<Sysroot, Option<String>>, + rustc: Result<(CargoWorkspace, WorkspaceBuildScripts), Option<String>>, /// Holds cfg flags for the current target. We get those by running /// `rustc --print cfg`. /// @@ -82,7 +82,7 @@ pub enum ProjectWorkspace { target_layout: Result<String, String>, }, /// Project workspace was manually specified using a `rust-project.json` file. - Json { project: ProjectJson, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, + Json { project: ProjectJson, sysroot: Result<Sysroot, Option<String>>, rustc_cfg: Vec<CfgFlag> }, // FIXME: The primary limitation of this approach is that the set of detached files needs to be fixed at the beginning. // That's not the end user experience we should strive for. // Ideally, you should be able to just open a random detached file in existing cargo projects, and get the basic features working. @@ -93,7 +93,11 @@ pub enum ProjectWorkspace { // // /// Project with a set of disjoint files, not belonging to any particular workspace. /// Backed by basic sysroot crates for basic completion and highlighting. - DetachedFiles { files: Vec<AbsPathBuf>, sysroot: Option<Sysroot>, rustc_cfg: Vec<CfgFlag> }, + DetachedFiles { + files: Vec<AbsPathBuf>, + sysroot: Result<Sysroot, Option<String>>, + rustc_cfg: Vec<CfgFlag>, + }, } impl fmt::Debug for ProjectWorkspace { @@ -113,7 +117,7 @@ impl fmt::Debug for ProjectWorkspace { .debug_struct("Cargo") .field("root", &cargo.workspace_root().file_name()) .field("n_packages", &cargo.packages().len()) - .field("sysroot", &sysroot.is_some()) + .field("sysroot", &sysroot.is_ok()) .field( "n_rustc_compiler_crates", &rustc.as_ref().map_or(0, |(rc, _)| rc.packages().len()), @@ -126,7 +130,7 @@ impl fmt::Debug for ProjectWorkspace { ProjectWorkspace::Json { project, sysroot, rustc_cfg } => { let mut debug_struct = f.debug_struct("Json"); debug_struct.field("n_crates", &project.n_crates()); - if let Some(sysroot) = sysroot { + if let Ok(sysroot) = sysroot { debug_struct.field("n_sysroot_crates", &sysroot.crates().len()); } debug_struct.field("n_rustc_cfg", &rustc_cfg.len()); @@ -135,7 +139,7 @@ impl fmt::Debug for ProjectWorkspace { ProjectWorkspace::DetachedFiles { files, sysroot, rustc_cfg } => f .debug_struct("DetachedFiles") .field("n_files", &files.len()) - .field("sysroot", &sysroot.is_some()) + .field("sysroot", &sysroot.is_ok()) .field("n_rustc_cfg", &rustc_cfg.len()) .finish(), } @@ -191,96 +195,81 @@ impl ProjectWorkspace { let cargo = CargoWorkspace::new(meta); let sysroot = match (&config.sysroot, &config.sysroot_src) { - (Some(RustcSource::Path(path)), None) => { - match Sysroot::with_sysroot_dir(path.clone()) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!(%e, "Failed to find sysroot at {}.", path.display()); - None - } - } + (Some(RustLibSource::Path(path)), None) => { + Sysroot::with_sysroot_dir(path.clone()).map_err(|e| { + Some(format!("Failed to find sysroot at {}:{e}", path.display())) + }) } - (Some(RustcSource::Discover), None) => { - match Sysroot::discover(cargo_toml.parent(), &config.extra_env) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!( - %e, - "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?", - cargo_toml.display() - ); - None - } - } + (Some(RustLibSource::Discover), None) => { + Sysroot::discover(cargo_toml.parent(), &config.extra_env).map_err(|e| { + Some(format!("Failed to find sysroot for Cargo.toml file {}. Is rust-src installed? {e}", cargo_toml.display())) + }) } - (Some(RustcSource::Path(sysroot)), Some(sysroot_src)) => { - Some(Sysroot::load(sysroot.clone(), sysroot_src.clone())) + (Some(RustLibSource::Path(sysroot)), Some(sysroot_src)) => { + Ok(Sysroot::load(sysroot.clone(), sysroot_src.clone())) } - (Some(RustcSource::Discover), Some(sysroot_src)) => { - match Sysroot::discover_with_src_override( + (Some(RustLibSource::Discover), Some(sysroot_src)) => { + Sysroot::discover_with_src_override( cargo_toml.parent(), &config.extra_env, sysroot_src.clone(), - ) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!( - %e, - "Failed to find sysroot for Cargo.toml file {}. Is rust-src installed?", - cargo_toml.display() - ); - None - } - } + ).map_err(|e| { + Some(format!("Failed to find sysroot for Cargo.toml file {}. Is rust-src installed? {e}", cargo_toml.display())) + }) } - (None, _) => None, + (None, _) => Err(None), }; - if let Some(sysroot) = &sysroot { + if let Ok(sysroot) = &sysroot { tracing::info!(workspace = %cargo_toml.display(), src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); } let rustc_dir = match &config.rustc_source { - Some(RustcSource::Path(path)) => ManifestPath::try_from(path.clone()).ok(), - Some(RustcSource::Discover) => { - sysroot.as_ref().and_then(Sysroot::discover_rustc) + Some(RustLibSource::Path(path)) => ManifestPath::try_from(path.clone()) + .map_err(|p| { + Some(format!("rustc source path is not absolute: {}", p.display())) + }), + Some(RustLibSource::Discover) => { + sysroot.as_ref().ok().and_then(Sysroot::discover_rustc).ok_or_else(|| { + Some(format!("Failed to discover rustc source for sysroot.")) + }) } - None => None, + None => Err(None), }; - let rustc = match rustc_dir { - Some(rustc_dir) => { - tracing::info!(workspace = %cargo_toml.display(), rustc_dir = %rustc_dir.display(), "Using rustc source"); - match CargoWorkspace::fetch_metadata( - &rustc_dir, - cargo_toml.parent(), - &CargoConfig { - features: crate::CargoFeatures::default(), - ..config.clone() - }, - progress, - ) { - Ok(meta) => { - let workspace = CargoWorkspace::new(meta); - let buildscripts = WorkspaceBuildScripts::rustc_crates( - &workspace, - cargo_toml.parent(), - &config.extra_env, - ); - Some((workspace, buildscripts)) - } - Err(e) => { - tracing::error!( - %e, - "Failed to read Cargo metadata from rustc source at {}", - rustc_dir.display() - ); - None - } + let rustc = rustc_dir.and_then(|rustc_dir| { + tracing::info!(workspace = %cargo_toml.display(), rustc_dir = %rustc_dir.display(), "Using rustc source"); + match CargoWorkspace::fetch_metadata( + &rustc_dir, + cargo_toml.parent(), + &CargoConfig { + features: crate::CargoFeatures::default(), + ..config.clone() + }, + progress, + ) { + Ok(meta) => { + let workspace = CargoWorkspace::new(meta); + let buildscripts = WorkspaceBuildScripts::rustc_crates( + &workspace, + cargo_toml.parent(), + &config.extra_env, + ); + Ok((workspace, buildscripts)) + } + Err(e) => { + tracing::error!( + %e, + "Failed to read Cargo metadata from rustc source at {}", + rustc_dir.display() + ); + Err(Some(format!( + "Failed to read Cargo metadata from rustc source at {}: {e}", + rustc_dir.display()) + )) } } - None => None, - }; + }); let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref(), &config.extra_env); @@ -316,12 +305,12 @@ impl ProjectWorkspace { extra_env: &FxHashMap<String, String>, ) -> ProjectWorkspace { let sysroot = match (project_json.sysroot.clone(), project_json.sysroot_src.clone()) { - (Some(sysroot), Some(sysroot_src)) => Some(Sysroot::load(sysroot, sysroot_src)), + (Some(sysroot), Some(sysroot_src)) => Ok(Sysroot::load(sysroot, sysroot_src)), (Some(sysroot), None) => { // assume sysroot is structured like rustup's and guess `sysroot_src` let sysroot_src = sysroot.join("lib").join("rustlib").join("src").join("rust").join("library"); - Some(Sysroot::load(sysroot, sysroot_src)) + Ok(Sysroot::load(sysroot, sysroot_src)) } (None, Some(sysroot_src)) => { // assume sysroot is structured like rustup's and guess `sysroot` @@ -329,11 +318,11 @@ impl ProjectWorkspace { for _ in 0..5 { sysroot.pop(); } - Some(Sysroot::load(sysroot, sysroot_src)) + Ok(Sysroot::load(sysroot, sysroot_src)) } - (None, None) => None, + (None, None) => Err(None), }; - if let Some(sysroot) = &sysroot { + if let Ok(sysroot) = &sysroot { tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); } @@ -346,33 +335,23 @@ impl ProjectWorkspace { config: &CargoConfig, ) -> Result<ProjectWorkspace> { let sysroot = match &config.sysroot { - Some(RustcSource::Path(path)) => match Sysroot::with_sysroot_dir(path.clone()) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!(%e, "Failed to find sysroot at {}.", path.display()); - None - } - }, - Some(RustcSource::Discover) => { + Some(RustLibSource::Path(path)) => Sysroot::with_sysroot_dir(path.clone()) + .map_err(|e| Some(format!("Failed to find sysroot at {}:{e}", path.display()))), + Some(RustLibSource::Discover) => { let dir = &detached_files .first() .and_then(|it| it.parent()) .ok_or_else(|| format_err!("No detached files to load"))?; - match Sysroot::discover(dir, &config.extra_env) { - Ok(it) => Some(it), - Err(e) => { - tracing::error!( - %e, - "Failed to find sysroot for {}. Is rust-src installed?", - dir.display() - ); - None - } - } + Sysroot::discover(dir, &config.extra_env).map_err(|e| { + Some(format!( + "Failed to find sysroot for {}. Is rust-src installed? {e}", + dir.display() + )) + }) } - None => None, + None => Err(None), }; - if let Some(sysroot) = &sysroot { + if let Ok(sysroot) = &sysroot { tracing::info!(src_root = %sysroot.src_root().display(), root = %sysroot.root().display(), "Using sysroot"); } let rustc_cfg = rustc_cfg::get(None, None, &Default::default()); @@ -463,8 +442,8 @@ impl ProjectWorkspace { pub fn find_sysroot_proc_macro_srv(&self) -> Option<AbsPathBuf> { match self { - ProjectWorkspace::Cargo { sysroot: Some(sysroot), .. } - | ProjectWorkspace::Json { sysroot: Some(sysroot), .. } => { + ProjectWorkspace::Cargo { sysroot: Ok(sysroot), .. } + | ProjectWorkspace::Json { sysroot: Ok(sysroot), .. } => { let standalone_server_name = format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX); ["libexec", "lib"] @@ -480,7 +459,7 @@ impl ProjectWorkspace { /// The return type contains the path and whether or not /// the root is a member of the current workspace pub fn to_roots(&self) -> Vec<PackageRoot> { - let mk_sysroot = |sysroot: Option<&Sysroot>, project_root: Option<&AbsPath>| { + let mk_sysroot = |sysroot: Result<&Sysroot, _>, project_root: Option<&AbsPath>| { sysroot.map(|sysroot| PackageRoot { // mark the sysroot as mutable if it is located inside of the project is_local: project_root @@ -603,7 +582,7 @@ impl ProjectWorkspace { load_proc_macro, load, project, - sysroot.as_ref(), + sysroot.as_ref().ok(), extra_env, Err("rust-project.json projects have no target layout set".into()), ), @@ -619,9 +598,9 @@ impl ProjectWorkspace { } => cargo_to_crate_graph( load_proc_macro, load, - rustc, + rustc.as_ref().ok(), cargo, - sysroot.as_ref(), + sysroot.as_ref().ok(), rustc_cfg.clone(), cfg_overrides, build_scripts, @@ -635,7 +614,7 @@ impl ProjectWorkspace { rustc_cfg.clone(), load, files, - sysroot, + sysroot.as_ref().ok(), Err("detached file projects have no target layout set".into()), ) } @@ -797,7 +776,7 @@ fn project_json_to_crate_graph( fn cargo_to_crate_graph( load_proc_macro: &mut dyn FnMut(&str, &AbsPath) -> ProcMacroLoadResult, load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, - rustc: &Option<(CargoWorkspace, WorkspaceBuildScripts)>, + rustc: Option<&(CargoWorkspace, WorkspaceBuildScripts)>, cargo: &CargoWorkspace, sysroot: Option<&Sysroot>, rustc_cfg: Vec<CfgFlag>, @@ -974,7 +953,7 @@ fn detached_files_to_crate_graph( rustc_cfg: Vec<CfgFlag>, load: &mut dyn FnMut(&AbsPath) -> Option<FileId>, detached_files: &[AbsPathBuf], - sysroot: &Option<Sysroot>, + sysroot: Option<&Sysroot>, target_layout: TargetLayoutLoadResult, ) -> CrateGraph { let _p = profile::span("detached_files_to_crate_graph"); diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 8187b1ba4e9..6ce1de5d32b 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -24,7 +24,7 @@ use ide_db::base_db::{ use itertools::Itertools; use oorandom::Rand32; use profile::{Bytes, StopWatch}; -use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource}; +use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; use rayon::prelude::*; use rustc_hash::FxHashSet; use stdx::format_to; @@ -57,7 +57,7 @@ impl flags::AnalysisStats { let mut cargo_config = CargoConfig::default(); cargo_config.sysroot = match self.no_sysroot { true => None, - false => Some(RustcSource::Discover), + false => Some(RustLibSource::Discover), }; let no_progress = &|_| (); diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs index 0721d486ef1..4006d023def 100644 --- a/crates/rust-analyzer/src/cli/diagnostics.rs +++ b/crates/rust-analyzer/src/cli/diagnostics.rs @@ -1,7 +1,7 @@ //! Analyze all modules in a project for diagnostics. Exits with a non-zero //! status code if any errors are found. -use project_model::{CargoConfig, RustcSource}; +use project_model::{CargoConfig, RustLibSource}; use rustc_hash::FxHashSet; use hir::{db::HirDatabase, Crate, Module}; @@ -16,7 +16,7 @@ use crate::cli::{ impl flags::Diagnostics { pub fn run(self) -> anyhow::Result<()> { let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustcSource::Discover); + cargo_config.sysroot = Some(RustLibSource::Discover); let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: !self.disable_build_scripts, with_proc_macro_server: ProcMacroServerChoice::Sysroot, diff --git a/crates/rust-analyzer/src/cli/lsif.rs b/crates/rust-analyzer/src/cli/lsif.rs index 9b5451496c6..7f5d0844967 100644 --- a/crates/rust-analyzer/src/cli/lsif.rs +++ b/crates/rust-analyzer/src/cli/lsif.rs @@ -13,7 +13,7 @@ use ide_db::LineIndexDatabase; use ide_db::base_db::salsa::{self, ParallelDatabase}; use ide_db::line_index::WideEncoding; use lsp_types::{self, lsif}; -use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource}; +use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; use vfs::{AbsPathBuf, Vfs}; use crate::cli::load_cargo::ProcMacroServerChoice; @@ -290,7 +290,7 @@ impl flags::Lsif { eprintln!("Generating LSIF started..."); let now = Instant::now(); let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustcSource::Discover); + cargo_config.sysroot = Some(RustLibSource::Discover); let no_progress = &|_| (); let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, diff --git a/crates/rust-analyzer/src/cli/scip.rs b/crates/rust-analyzer/src/cli/scip.rs index df5c26cf77a..3e5e40750e9 100644 --- a/crates/rust-analyzer/src/cli/scip.rs +++ b/crates/rust-analyzer/src/cli/scip.rs @@ -15,7 +15,7 @@ use ide::{ TokenStaticData, }; use ide_db::LineIndexDatabase; -use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustcSource}; +use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource}; use scip::types as scip_types; use std::env; @@ -30,7 +30,7 @@ impl flags::Scip { eprintln!("Generating SCIP start..."); let now = Instant::now(); let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustcSource::Discover); + cargo_config.sysroot = Some(RustLibSource::Discover); let no_progress = &|s| (eprintln!("rust-analyzer: Loading {s}")); let load_cargo_config = LoadCargoConfig { diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs index 35a874f8920..82a769347df 100644 --- a/crates/rust-analyzer/src/cli/ssr.rs +++ b/crates/rust-analyzer/src/cli/ssr.rs @@ -1,7 +1,7 @@ //! Applies structured search replace rules from the command line. use ide_ssr::MatchFinder; -use project_model::{CargoConfig, RustcSource}; +use project_model::{CargoConfig, RustLibSource}; use crate::cli::{ flags, @@ -13,7 +13,7 @@ impl flags::Ssr { pub fn run(self) -> Result<()> { use ide_db::base_db::SourceDatabaseExt; let mut cargo_config = CargoConfig::default(); - cargo_config.sysroot = Some(RustcSource::Discover); + cargo_config.sysroot = Some(RustLibSource::Discover); let load_cargo_config = LoadCargoConfig { load_out_dirs_from_check: true, with_proc_macro_server: ProcMacroServerChoice::Sysroot, diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 05ad7ab4c4a..c35cce103fa 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs @@ -22,7 +22,7 @@ use ide_db::{ use itertools::Itertools; use lsp_types::{ClientCapabilities, MarkupKind}; use project_model::{ - CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustcSource, + CargoConfig, CargoFeatures, ProjectJson, ProjectJsonData, ProjectManifest, RustLibSource, UnsetTestCrates, }; use rustc_hash::{FxHashMap, FxHashSet}; @@ -1137,16 +1137,16 @@ impl Config { pub fn cargo(&self) -> CargoConfig { let rustc_source = self.data.rustc_source.as_ref().map(|rustc_src| { if rustc_src == "discover" { - RustcSource::Discover + RustLibSource::Discover } else { - RustcSource::Path(self.root_path.join(rustc_src)) + RustLibSource::Path(self.root_path.join(rustc_src)) } }); let sysroot = self.data.cargo_sysroot.as_ref().map(|sysroot| { if sysroot == "discover" { - RustcSource::Discover + RustLibSource::Discover } else { - RustcSource::Path(self.root_path.join(sysroot)) + RustLibSource::Path(self.root_path.join(sysroot)) } }); let sysroot_src = diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index 30f1c53c198..12e5caf2cc9 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs @@ -36,11 +36,41 @@ impl Progress { } impl GlobalState { - pub(crate) fn show_message(&mut self, typ: lsp_types::MessageType, message: String) { - let message = message; - self.send_notification::<lsp_types::notification::ShowMessage>( - lsp_types::ShowMessageParams { typ, message }, - ) + pub(crate) fn show_message( + &mut self, + typ: lsp_types::MessageType, + message: String, + show_open_log_button: bool, + ) { + match self.config.open_server_logs() && show_open_log_button { + true => self.send_request::<lsp_types::request::ShowMessageRequest>( + lsp_types::ShowMessageRequestParams { + typ, + message, + actions: Some(vec![lsp_types::MessageActionItem { + title: "Open server logs".to_owned(), + properties: Default::default(), + }]), + }, + |this, resp| { + let lsp_server::Response { error: None, result: Some(result), .. } = resp + else { return }; + if let Ok(Some(_item)) = crate::from_json::< + <lsp_types::request::ShowMessageRequest as lsp_types::request::Request>::Result, + >( + lsp_types::request::ShowMessageRequest::METHOD, &result + ) { + this.send_notification::<lsp_ext::OpenServerLogs>(()); + } + }, + ), + false => self.send_notification::<lsp_types::notification::ShowMessage>( + lsp_types::ShowMessageParams { + typ, + message, + }, + ), + } } /// Sends a notification to the client containing the error `message`. diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index dd0804b4398..2752e710342 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs @@ -406,9 +406,19 @@ impl GlobalState { if self.config.server_status_notification() { self.send_notification::<lsp_ext::ServerStatusNotification>(status); - } else if let (lsp_ext::Health::Error, Some(message)) = (status.health, &status.message) - { - self.show_and_log_error(message.clone(), None); + } else if let (health, Some(message)) = (status.health, &status.message) { + let open_log_button = tracing::enabled!(tracing::Level::ERROR) + && (self.fetch_build_data_error().is_err() + || self.fetch_workspace_error().is_err()); + self.show_message( + match health { + lsp_ext::Health::Ok => lsp_types::MessageType::INFO, + lsp_ext::Health::Warning => lsp_types::MessageType::WARNING, + lsp_ext::Health::Error => lsp_types::MessageType::ERROR, + }, + message.clone(), + open_log_button, + ); } } } @@ -919,6 +929,7 @@ impl GlobalState { this.show_message( lsp_types::MessageType::WARNING, error.to_string(), + false, ); } this.update_configuration(config); diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 28d37f5685a..1a6e1af2eb7 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -90,38 +90,55 @@ impl GlobalState { quiescent: self.is_quiescent(), message: None, }; + let mut message = String::new(); if self.proc_macro_changed { status.health = lsp_ext::Health::Warning; - status.message = - Some("Reload required due to source changes of a procedural macro.".into()) + message.push_str("Reload required due to source changes of a procedural macro.\n\n"); } if let Err(_) = self.fetch_build_data_error() { status.health = lsp_ext::Health::Warning; - status.message = - Some("Failed to run build scripts of some packages, check the logs.".to_string()); + message.push_str("Failed to run build scripts of some packages.\n\n"); } if !self.config.cargo_autoreload() && self.is_quiescent() && self.fetch_workspaces_queue.op_requested() { status.health = lsp_ext::Health::Warning; - status.message = Some("Workspace reload required".to_string()) + message.push_str("Auto-reloading is disabled and the workspace has changed, a manual workspace reload is required.\n\n"); } - - if let Err(_) = self.fetch_workspace_error() { - status.health = lsp_ext::Health::Error; - status.message = Some("Failed to load workspaces".to_string()) - } - if self.config.linked_projects().is_empty() && self.config.detached_files().is_empty() && self.config.notifications().cargo_toml_not_found { status.health = lsp_ext::Health::Warning; - status.message = Some("Failed to discover workspace".to_string()) + message.push_str("Failed to discover workspace.\n\n"); + } + + for ws in self.workspaces.iter() { + let (ProjectWorkspace::Cargo { sysroot, .. } + | ProjectWorkspace::Json { sysroot, .. } + | ProjectWorkspace::DetachedFiles { sysroot, .. }) = ws; + if let Err(Some(e)) = sysroot { + status.health = lsp_ext::Health::Warning; + message.push_str(e); + message.push_str("\n\n"); + } + if let ProjectWorkspace::Cargo { rustc: Err(Some(e)), .. } = ws { + status.health = lsp_ext::Health::Warning; + message.push_str(e); + message.push_str("\n\n"); + } } + if let Err(_) = self.fetch_workspace_error() { + status.health = lsp_ext::Health::Error; + message.push_str("Failed to load workspaces.\n\n"); + } + + if !message.is_empty() { + status.message = Some(message.trim_end().to_owned()); + } status } |
