mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Show workspace info in the status bar
This commit is contained in:
parent
56bee2ddaf
commit
18ca22a98e
15 changed files with 168 additions and 81 deletions
|
@ -6,3 +6,10 @@
|
||||||
|
|
||||||
# prettier format
|
# prettier format
|
||||||
f247090558c9ba3c551566eae5882b7ca865225f
|
f247090558c9ba3c551566eae5882b7ca865225f
|
||||||
|
|
||||||
|
# subtree syncs
|
||||||
|
932d85b52946d917deab2c23ead552f7f713b828
|
||||||
|
3e358a6827d83e8d6473913a5e304734aadfed04
|
||||||
|
9d2cb42a413e51deb50b36794a2e1605381878fc
|
||||||
|
f532576ac53ddcc666bc8d59e0b6437065e2f599
|
||||||
|
c48062fe2ab9a2d913d1985a6b0aec4bf936bfc1
|
||||||
|
|
|
@ -131,7 +131,7 @@ pub struct SemanticsImpl<'db> {
|
||||||
pub db: &'db dyn HirDatabase,
|
pub db: &'db dyn HirDatabase,
|
||||||
s2d_cache: RefCell<SourceToDefCache>,
|
s2d_cache: RefCell<SourceToDefCache>,
|
||||||
/// Rootnode to HirFileId cache
|
/// Rootnode to HirFileId cache
|
||||||
cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
root_to_file_cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
|
||||||
// These 2 caches are mainly useful for semantic highlighting as nothing else descends a lot of tokens
|
// These 2 caches are mainly useful for semantic highlighting as nothing else descends a lot of tokens
|
||||||
// So we might wanna move them out into something specific for semantic highlighting
|
// So we might wanna move them out into something specific for semantic highlighting
|
||||||
expansion_info_cache: RefCell<FxHashMap<MacroFileId, ExpansionInfo>>,
|
expansion_info_cache: RefCell<FxHashMap<MacroFileId, ExpansionInfo>>,
|
||||||
|
@ -294,7 +294,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
SemanticsImpl {
|
SemanticsImpl {
|
||||||
db,
|
db,
|
||||||
s2d_cache: Default::default(),
|
s2d_cache: Default::default(),
|
||||||
cache: Default::default(),
|
root_to_file_cache: Default::default(),
|
||||||
expansion_info_cache: Default::default(),
|
expansion_info_cache: Default::default(),
|
||||||
macro_call_cache: Default::default(),
|
macro_call_cache: Default::default(),
|
||||||
}
|
}
|
||||||
|
@ -690,6 +690,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
exp_info
|
exp_info
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// FIXME: uncached parse
|
||||||
// Create the source analyzer for the macro call scope
|
// Create the source analyzer for the macro call scope
|
||||||
let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file()))
|
let Some(sa) = self.analyze_no_infer(&self.parse_or_expand(expansion_info.call_file()))
|
||||||
else {
|
else {
|
||||||
|
@ -1025,6 +1026,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
None => {
|
None => {
|
||||||
let call_node = file_id.macro_file()?.call_node(db);
|
let call_node = file_id.macro_file()?.call_node(db);
|
||||||
// cache the node
|
// cache the node
|
||||||
|
// FIXME: uncached parse
|
||||||
self.parse_or_expand(call_node.file_id);
|
self.parse_or_expand(call_node.file_id);
|
||||||
Some(call_node)
|
Some(call_node)
|
||||||
}
|
}
|
||||||
|
@ -1397,7 +1399,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
|
|
||||||
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
|
||||||
assert!(root_node.parent().is_none());
|
assert!(root_node.parent().is_none());
|
||||||
let mut cache = self.cache.borrow_mut();
|
let mut cache = self.root_to_file_cache.borrow_mut();
|
||||||
let prev = cache.insert(root_node, file_id);
|
let prev = cache.insert(root_node, file_id);
|
||||||
assert!(prev.is_none() || prev == Some(file_id))
|
assert!(prev.is_none() || prev == Some(file_id))
|
||||||
}
|
}
|
||||||
|
@ -1407,7 +1409,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
|
fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
|
||||||
let cache = self.cache.borrow();
|
let cache = self.root_to_file_cache.borrow();
|
||||||
cache.get(root_node).copied()
|
cache.get(root_node).copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1427,7 +1429,7 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
known nodes: {}\n\n",
|
known nodes: {}\n\n",
|
||||||
node,
|
node,
|
||||||
root_node,
|
root_node,
|
||||||
self.cache
|
self.root_to_file_cache
|
||||||
.borrow()
|
.borrow()
|
||||||
.keys()
|
.keys()
|
||||||
.map(|it| format!("{it:?}"))
|
.map(|it| format!("{it:?}"))
|
||||||
|
|
|
@ -68,9 +68,9 @@ pub fn load_workspace(
|
||||||
let proc_macro_server = match &load_config.with_proc_macro_server {
|
let proc_macro_server = match &load_config.with_proc_macro_server {
|
||||||
ProcMacroServerChoice::Sysroot => ws
|
ProcMacroServerChoice::Sysroot => ws
|
||||||
.find_sysroot_proc_macro_srv()
|
.find_sysroot_proc_macro_srv()
|
||||||
.and_then(|it| ProcMacroServer::spawn(it, extra_env).map_err(Into::into)),
|
.and_then(|it| ProcMacroServer::spawn(&it, extra_env).map_err(Into::into)),
|
||||||
ProcMacroServerChoice::Explicit(path) => {
|
ProcMacroServerChoice::Explicit(path) => {
|
||||||
ProcMacroServer::spawn(path.clone(), extra_env).map_err(Into::into)
|
ProcMacroServer::spawn(path, extra_env).map_err(Into::into)
|
||||||
}
|
}
|
||||||
ProcMacroServerChoice::None => Err(anyhow::format_err!("proc macro server disabled")),
|
ProcMacroServerChoice::None => Err(anyhow::format_err!("proc macro server disabled")),
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,7 @@ mod version;
|
||||||
|
|
||||||
use base_db::Env;
|
use base_db::Env;
|
||||||
use indexmap::IndexSet;
|
use indexmap::IndexSet;
|
||||||
use paths::AbsPathBuf;
|
use paths::{AbsPath, AbsPathBuf};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use span::Span;
|
use span::Span;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -54,6 +54,7 @@ pub struct ProcMacroServer {
|
||||||
///
|
///
|
||||||
/// Therefore, we just wrap the `ProcMacroProcessSrv` in a mutex here.
|
/// Therefore, we just wrap the `ProcMacroProcessSrv` in a mutex here.
|
||||||
process: Arc<Mutex<ProcMacroProcessSrv>>,
|
process: Arc<Mutex<ProcMacroProcessSrv>>,
|
||||||
|
path: AbsPathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MacroDylib {
|
pub struct MacroDylib {
|
||||||
|
@ -113,11 +114,18 @@ pub struct MacroPanic {
|
||||||
impl ProcMacroServer {
|
impl ProcMacroServer {
|
||||||
/// Spawns an external process as the proc macro server and returns a client connected to it.
|
/// Spawns an external process as the proc macro server and returns a client connected to it.
|
||||||
pub fn spawn(
|
pub fn spawn(
|
||||||
process_path: AbsPathBuf,
|
process_path: &AbsPath,
|
||||||
env: &FxHashMap<String, String>,
|
env: &FxHashMap<String, String>,
|
||||||
) -> io::Result<ProcMacroServer> {
|
) -> io::Result<ProcMacroServer> {
|
||||||
let process = ProcMacroProcessSrv::run(process_path, env)?;
|
let process = ProcMacroProcessSrv::run(process_path, env)?;
|
||||||
Ok(ProcMacroServer { process: Arc::new(Mutex::new(process)) })
|
Ok(ProcMacroServer {
|
||||||
|
process: Arc::new(Mutex::new(process)),
|
||||||
|
path: process_path.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> &AbsPath {
|
||||||
|
&self.path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_dylib(&self, dylib: MacroDylib) -> Result<Vec<ProcMacro>, ServerError> {
|
pub fn load_dylib(&self, dylib: MacroDylib) -> Result<Vec<ProcMacro>, ServerError> {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use paths::{AbsPath, AbsPathBuf};
|
use paths::AbsPath;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use stdx::JodChild;
|
use stdx::JodChild;
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ pub(crate) struct ProcMacroProcessSrv {
|
||||||
|
|
||||||
impl ProcMacroProcessSrv {
|
impl ProcMacroProcessSrv {
|
||||||
pub(crate) fn run(
|
pub(crate) fn run(
|
||||||
process_path: AbsPathBuf,
|
process_path: &AbsPath,
|
||||||
env: &FxHashMap<String, String>,
|
env: &FxHashMap<String, String>,
|
||||||
) -> io::Result<ProcMacroProcessSrv> {
|
) -> io::Result<ProcMacroProcessSrv> {
|
||||||
let create_srv = |null_stderr| {
|
let create_srv = |null_stderr| {
|
||||||
let mut process = Process::run(process_path.clone(), env, null_stderr)?;
|
let mut process = Process::run(process_path, env, null_stderr)?;
|
||||||
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
|
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
|
||||||
|
|
||||||
io::Result::Ok(ProcMacroProcessSrv {
|
io::Result::Ok(ProcMacroProcessSrv {
|
||||||
|
@ -153,11 +153,11 @@ struct Process {
|
||||||
|
|
||||||
impl Process {
|
impl Process {
|
||||||
fn run(
|
fn run(
|
||||||
path: AbsPathBuf,
|
path: &AbsPath,
|
||||||
env: &FxHashMap<String, String>,
|
env: &FxHashMap<String, String>,
|
||||||
null_stderr: bool,
|
null_stderr: bool,
|
||||||
) -> io::Result<Process> {
|
) -> io::Result<Process> {
|
||||||
let child = JodChild(mk_child(&path, env, null_stderr)?);
|
let child = JodChild(mk_child(path, env, null_stderr)?);
|
||||||
Ok(Process { child })
|
Ok(Process { child })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@ use serde::{de, Deserialize, Serialize};
|
||||||
use span::Edition;
|
use span::Edition;
|
||||||
|
|
||||||
use crate::cfg::CfgFlag;
|
use crate::cfg::CfgFlag;
|
||||||
|
use crate::ManifestPath;
|
||||||
|
|
||||||
/// Roots and crates that compose this Rust project.
|
/// Roots and crates that compose this Rust project.
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
@ -65,6 +66,7 @@ pub struct ProjectJson {
|
||||||
/// e.g. `path/to/sysroot/lib/rustlib/src/rust`
|
/// e.g. `path/to/sysroot/lib/rustlib/src/rust`
|
||||||
pub(crate) sysroot_src: Option<AbsPathBuf>,
|
pub(crate) sysroot_src: Option<AbsPathBuf>,
|
||||||
project_root: AbsPathBuf,
|
project_root: AbsPathBuf,
|
||||||
|
manifest: Option<ManifestPath>,
|
||||||
crates: Vec<Crate>,
|
crates: Vec<Crate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,12 +98,17 @@ impl ProjectJson {
|
||||||
/// * `base` - The path to the workspace root (i.e. the folder containing `rust-project.json`)
|
/// * `base` - The path to the workspace root (i.e. the folder containing `rust-project.json`)
|
||||||
/// * `data` - The parsed contents of `rust-project.json`, or project json that's passed via
|
/// * `data` - The parsed contents of `rust-project.json`, or project json that's passed via
|
||||||
/// configuration.
|
/// configuration.
|
||||||
pub fn new(base: &AbsPath, data: ProjectJsonData) -> ProjectJson {
|
pub fn new(
|
||||||
|
manifest: Option<ManifestPath>,
|
||||||
|
base: &AbsPath,
|
||||||
|
data: ProjectJsonData,
|
||||||
|
) -> ProjectJson {
|
||||||
let absolutize_on_base = |p| base.absolutize(p);
|
let absolutize_on_base = |p| base.absolutize(p);
|
||||||
ProjectJson {
|
ProjectJson {
|
||||||
sysroot: data.sysroot.map(absolutize_on_base),
|
sysroot: data.sysroot.map(absolutize_on_base),
|
||||||
sysroot_src: data.sysroot_src.map(absolutize_on_base),
|
sysroot_src: data.sysroot_src.map(absolutize_on_base),
|
||||||
project_root: base.to_path_buf(),
|
project_root: base.to_path_buf(),
|
||||||
|
manifest,
|
||||||
crates: data
|
crates: data
|
||||||
.crates
|
.crates
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -159,6 +166,11 @@ impl ProjectJson {
|
||||||
pub fn path(&self) -> &AbsPath {
|
pub fn path(&self) -> &AbsPath {
|
||||||
&self.project_root
|
&self.project_root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the path to the project's manifest or root folder, if no manifest exists.
|
||||||
|
pub fn manifest_or_root(&self) -> &AbsPath {
|
||||||
|
self.manifest.as_ref().map_or(&self.project_root, |manifest| manifest.as_ref())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
|
|
@ -133,6 +133,24 @@ impl Sysroot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn check_has_core(&self) -> Result<(), String> {
|
||||||
|
let Some(Ok(src_root)) = &self.src_root else { return Ok(()) };
|
||||||
|
let has_core = match &self.mode {
|
||||||
|
SysrootMode::Workspace(ws) => ws.packages().any(|p| ws[p].name == "core"),
|
||||||
|
SysrootMode::Stitched(stitched) => stitched.by_name("core").is_some(),
|
||||||
|
};
|
||||||
|
if !has_core {
|
||||||
|
let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
|
||||||
|
" (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
|
||||||
|
} else {
|
||||||
|
" try running `rustup component add rust-src` to possible fix this"
|
||||||
|
};
|
||||||
|
Err(format!("could not find libcore in loaded sysroot at `{}`{var_note}", src_root,))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn num_packages(&self) -> usize {
|
pub fn num_packages(&self) -> usize {
|
||||||
match &self.mode {
|
match &self.mode {
|
||||||
SysrootMode::Workspace(ws) => ws.packages().count(),
|
SysrootMode::Workspace(ws) => ws.packages().count(),
|
||||||
|
|
|
@ -152,7 +152,7 @@ fn rooted_project_json(data: ProjectJsonData) -> ProjectJson {
|
||||||
replace_root(&mut root, true);
|
replace_root(&mut root, true);
|
||||||
let path = Utf8Path::new(&root);
|
let path = Utf8Path::new(&root);
|
||||||
let base = AbsPath::assert(path);
|
let base = AbsPath::assert(path);
|
||||||
ProjectJson::new(base, data)
|
ProjectJson::new(None, base, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacroPaths) {
|
fn to_crate_graph(project_workspace: ProjectWorkspace) -> (CrateGraph, ProcMacroPaths) {
|
||||||
|
|
|
@ -199,7 +199,8 @@ impl ProjectWorkspace {
|
||||||
let data = serde_json::from_str(&file)
|
let data = serde_json::from_str(&file)
|
||||||
.with_context(|| format!("Failed to deserialize json file {project_json}"))?;
|
.with_context(|| format!("Failed to deserialize json file {project_json}"))?;
|
||||||
let project_location = project_json.parent().to_path_buf();
|
let project_location = project_json.parent().to_path_buf();
|
||||||
let project_json: ProjectJson = ProjectJson::new(&project_location, data);
|
let project_json: ProjectJson =
|
||||||
|
ProjectJson::new(Some(project_json.clone()), &project_location, data);
|
||||||
ProjectWorkspace::load_inline(
|
ProjectWorkspace::load_inline(
|
||||||
project_json,
|
project_json,
|
||||||
config.target.as_deref(),
|
config.target.as_deref(),
|
||||||
|
@ -555,7 +556,7 @@ impl ProjectWorkspace {
|
||||||
pub fn manifest_or_root(&self) -> &AbsPath {
|
pub fn manifest_or_root(&self) -> &AbsPath {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
ProjectWorkspaceKind::Cargo { cargo, .. } => cargo.manifest_path(),
|
ProjectWorkspaceKind::Cargo { cargo, .. } => cargo.manifest_path(),
|
||||||
ProjectWorkspaceKind::Json(project) => project.path(),
|
ProjectWorkspaceKind::Json(project) => project.manifest_or_root(),
|
||||||
ProjectWorkspaceKind::DetachedFile { file, .. } => file,
|
ProjectWorkspaceKind::DetachedFile { file, .. } => file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1323,7 +1323,7 @@ impl Config {
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
ManifestOrProjectJson::ProjectJson(it) => {
|
ManifestOrProjectJson::ProjectJson(it) => {
|
||||||
Some(ProjectJson::new(&self.root_path, it.clone()).into())
|
Some(ProjectJson::new(None, &self.root_path, it.clone()).into())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#![allow(clippy::disallowed_types)]
|
#![allow(clippy::disallowed_types)]
|
||||||
|
|
||||||
|
use std::ops;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use ide_db::line_index::WideEncoding;
|
use ide_db::line_index::WideEncoding;
|
||||||
|
@ -494,10 +495,12 @@ impl Notification for ServerStatusNotification {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
|
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ServerStatusParams {
|
pub struct ServerStatusParams {
|
||||||
pub health: Health,
|
pub health: Health,
|
||||||
pub quiescent: bool,
|
pub quiescent: bool,
|
||||||
pub message: Option<String>,
|
pub message: Option<String>,
|
||||||
|
pub workspace_info: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -508,6 +511,16 @@ pub enum Health {
|
||||||
Error,
|
Error,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ops::BitOrAssign for Health {
|
||||||
|
fn bitor_assign(&mut self, rhs: Self) {
|
||||||
|
*self = match (*self, rhs) {
|
||||||
|
(Health::Error, _) | (_, Health::Error) => Health::Error,
|
||||||
|
(Health::Warning, _) | (_, Health::Warning) => Health::Warning,
|
||||||
|
_ => Health::Ok,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub enum CodeActionRequest {}
|
pub enum CodeActionRequest {}
|
||||||
|
|
||||||
impl Request for CodeActionRequest {
|
impl Request for CodeActionRequest {
|
||||||
|
|
|
@ -103,79 +103,48 @@ impl GlobalState {
|
||||||
health: lsp_ext::Health::Ok,
|
health: lsp_ext::Health::Ok,
|
||||||
quiescent: self.is_quiescent(),
|
quiescent: self.is_quiescent(),
|
||||||
message: None,
|
message: None,
|
||||||
|
workspace_info: None,
|
||||||
};
|
};
|
||||||
let mut message = String::new();
|
let mut message = String::new();
|
||||||
|
|
||||||
|
if !self.config.cargo_autoreload()
|
||||||
|
&& self.is_quiescent()
|
||||||
|
&& self.fetch_workspaces_queue.op_requested()
|
||||||
|
{
|
||||||
|
status.health |= lsp_ext::Health::Warning;
|
||||||
|
message.push_str("Auto-reloading is disabled and the workspace has changed, a manual workspace reload is required.\n\n");
|
||||||
|
}
|
||||||
|
|
||||||
if self.build_deps_changed {
|
if self.build_deps_changed {
|
||||||
status.health = lsp_ext::Health::Warning;
|
status.health |= lsp_ext::Health::Warning;
|
||||||
message.push_str(
|
message.push_str(
|
||||||
"Proc-macros and/or build scripts have changed and need to be rebuilt.\n\n",
|
"Proc-macros and/or build scripts have changed and need to be rebuilt.\n\n",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if self.fetch_build_data_error().is_err() {
|
if self.fetch_build_data_error().is_err() {
|
||||||
status.health = lsp_ext::Health::Warning;
|
status.health |= lsp_ext::Health::Warning;
|
||||||
message.push_str("Failed to run build scripts of some packages.\n\n");
|
message.push_str("Failed to run build scripts of some packages.\n\n");
|
||||||
}
|
}
|
||||||
if self.proc_macro_clients.iter().any(|it| it.is_err()) {
|
|
||||||
status.health = lsp_ext::Health::Warning;
|
|
||||||
message.push_str("Failed to spawn one or more proc-macro servers.\n\n");
|
|
||||||
for err in self.proc_macro_clients.iter() {
|
|
||||||
if let Err(err) = err {
|
|
||||||
format_to!(message, "- {err}\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !self.config.cargo_autoreload()
|
|
||||||
&& self.is_quiescent()
|
|
||||||
&& self.fetch_workspaces_queue.op_requested()
|
|
||||||
{
|
|
||||||
status.health = lsp_ext::Health::Warning;
|
|
||||||
message.push_str("Auto-reloading is disabled and the workspace has changed, a manual workspace reload is required.\n\n");
|
|
||||||
}
|
|
||||||
if self.config.linked_or_discovered_projects().is_empty()
|
|
||||||
&& self.config.detached_files().is_empty()
|
|
||||||
&& self.config.notifications().cargo_toml_not_found
|
|
||||||
{
|
|
||||||
status.health = lsp_ext::Health::Warning;
|
|
||||||
message.push_str("Failed to discover workspace.\n");
|
|
||||||
message.push_str("Consider adding the `Cargo.toml` of the workspace to the [`linkedProjects`](https://rust-analyzer.github.io/manual.html#rust-analyzer.linkedProjects) setting.\n\n");
|
|
||||||
}
|
|
||||||
if let Some(err) = &self.config_errors {
|
if let Some(err) = &self.config_errors {
|
||||||
status.health = lsp_ext::Health::Warning;
|
status.health |= lsp_ext::Health::Warning;
|
||||||
format_to!(message, "{err}\n");
|
format_to!(message, "{err}\n");
|
||||||
}
|
}
|
||||||
if let Some(err) = &self.last_flycheck_error {
|
if let Some(err) = &self.last_flycheck_error {
|
||||||
status.health = lsp_ext::Health::Warning;
|
status.health |= lsp_ext::Health::Warning;
|
||||||
message.push_str(err);
|
message.push_str(err);
|
||||||
message.push('\n');
|
message.push('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
for ws in self.workspaces.iter() {
|
if self.config.linked_or_discovered_projects().is_empty()
|
||||||
let sysroot = ws.sysroot.as_ref();
|
&& self.config.detached_files().is_empty()
|
||||||
match sysroot {
|
{
|
||||||
Err(None) => (),
|
status.health |= lsp_ext::Health::Warning;
|
||||||
Err(Some(e)) => {
|
message.push_str("Failed to discover workspace.\n");
|
||||||
status.health = lsp_ext::Health::Warning;
|
message.push_str("Consider adding the `Cargo.toml` of the workspace to the [`linkedProjects`](https://rust-analyzer.github.io/manual.html#rust-analyzer.linkedProjects) setting.\n\n");
|
||||||
message.push_str(e);
|
|
||||||
message.push_str("\n\n");
|
|
||||||
}
|
|
||||||
Ok(s) => {
|
|
||||||
if let Some(e) = s.loading_warning() {
|
|
||||||
status.health = lsp_ext::Health::Warning;
|
|
||||||
message.push_str(&e);
|
|
||||||
message.push_str("\n\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(e)), .. } = &ws.kind {
|
|
||||||
status.health = lsp_ext::Health::Warning;
|
|
||||||
message.push_str(e);
|
|
||||||
message.push_str("\n\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.fetch_workspace_error().is_err() {
|
if self.fetch_workspace_error().is_err() {
|
||||||
status.health = lsp_ext::Health::Error;
|
status.health |= lsp_ext::Health::Error;
|
||||||
message.push_str("Failed to load workspaces.");
|
message.push_str("Failed to load workspaces.");
|
||||||
|
|
||||||
if self.config.has_linked_projects() {
|
if self.config.has_linked_projects() {
|
||||||
|
@ -191,9 +160,63 @@ impl GlobalState {
|
||||||
message.push_str("\n\n");
|
message.push_str("\n\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !self.workspaces.is_empty() {
|
||||||
|
let proc_macro_clients =
|
||||||
|
self.proc_macro_clients.iter().map(Some).chain(iter::repeat_with(|| None));
|
||||||
|
|
||||||
|
let mut workspace_info = "Loaded workspaces:\n".to_owned();
|
||||||
|
for (ws, proc_macro_client) in self.workspaces.iter().zip(proc_macro_clients) {
|
||||||
|
format_to!(workspace_info, "- `{}`\n", ws.manifest_or_root());
|
||||||
|
format_to!(workspace_info, " - sysroot:");
|
||||||
|
|
||||||
|
match ws.sysroot.as_ref() {
|
||||||
|
Err(None) => format_to!(workspace_info, " None"),
|
||||||
|
Err(Some(e)) => {
|
||||||
|
status.health |= lsp_ext::Health::Warning;
|
||||||
|
format_to!(workspace_info, " {e}");
|
||||||
|
}
|
||||||
|
Ok(s) => {
|
||||||
|
format_to!(workspace_info, " `{}`", s.root().to_string());
|
||||||
|
if let Some(err) = s
|
||||||
|
.check_has_core()
|
||||||
|
.err()
|
||||||
|
.inspect(|_| status.health |= lsp_ext::Health::Warning)
|
||||||
|
{
|
||||||
|
format_to!(workspace_info, " ({err})");
|
||||||
|
}
|
||||||
|
if let Some(src_root) = s.src_root() {
|
||||||
|
format_to!(
|
||||||
|
workspace_info,
|
||||||
|
"\n - sysroot source: `{}`",
|
||||||
|
src_root
|
||||||
|
);
|
||||||
|
}
|
||||||
|
format_to!(workspace_info, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let ProjectWorkspaceKind::Cargo { rustc: Err(Some(e)), .. } = &ws.kind {
|
||||||
|
status.health |= lsp_ext::Health::Warning;
|
||||||
|
format_to!(workspace_info, " - rustc workspace: {e}\n");
|
||||||
|
};
|
||||||
|
if let Some(proc_macro_client) = proc_macro_client {
|
||||||
|
format_to!(workspace_info, " - proc-macro server: ");
|
||||||
|
match proc_macro_client {
|
||||||
|
Ok(it) => format_to!(workspace_info, "`{}`\n", it.path()),
|
||||||
|
Err(e) => {
|
||||||
|
status.health |= lsp_ext::Health::Warning;
|
||||||
|
format_to!(workspace_info, "{e}\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
status.workspace_info = Some(workspace_info);
|
||||||
|
}
|
||||||
|
|
||||||
if !message.is_empty() {
|
if !message.is_empty() {
|
||||||
status.message = Some(message.trim_end().to_owned());
|
status.message = Some(message.trim_end().to_owned());
|
||||||
}
|
}
|
||||||
|
|
||||||
status
|
status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -520,7 +543,7 @@ impl GlobalState {
|
||||||
};
|
};
|
||||||
tracing::info!("Using proc-macro server at {path}");
|
tracing::info!("Using proc-macro server at {path}");
|
||||||
|
|
||||||
ProcMacroServer::spawn(path.clone(), &env).map_err(|err| {
|
ProcMacroServer::spawn(&path, &env).map_err(|err| {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
"Failed to run proc-macro server from path {path}, error: {err:?}",
|
"Failed to run proc-macro server from path {path}, error: {err:?}",
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<!---
|
<!---
|
||||||
lsp/ext.rs hash: dd51139b0530147e
|
lsp/ext.rs hash: d8e2aa65fdb48e48
|
||||||
|
|
||||||
If you need to change the above hash to make the test pass, please check if you
|
If you need to change the above hash to make the test pass, please check if you
|
||||||
need to adjust this doc as well and ping this issue:
|
need to adjust this doc as well and ping this issue:
|
||||||
|
|
|
@ -433,7 +433,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
statusBar.tooltip.isTrusted = true;
|
statusBar.tooltip.isTrusted = true;
|
||||||
switch (status.health) {
|
switch (status.health) {
|
||||||
case "ok":
|
case "ok":
|
||||||
statusBar.tooltip.appendText(status.message ?? "Ready");
|
|
||||||
statusBar.color = undefined;
|
statusBar.color = undefined;
|
||||||
statusBar.backgroundColor = undefined;
|
statusBar.backgroundColor = undefined;
|
||||||
if (this.config.statusBarClickAction === "stopServer") {
|
if (this.config.statusBarClickAction === "stopServer") {
|
||||||
|
@ -444,9 +443,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
this.dependencies?.refresh();
|
this.dependencies?.refresh();
|
||||||
break;
|
break;
|
||||||
case "warning":
|
case "warning":
|
||||||
if (status.message) {
|
|
||||||
statusBar.tooltip.appendText(status.message);
|
|
||||||
}
|
|
||||||
statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
|
statusBar.color = new vscode.ThemeColor("statusBarItem.warningForeground");
|
||||||
statusBar.backgroundColor = new vscode.ThemeColor(
|
statusBar.backgroundColor = new vscode.ThemeColor(
|
||||||
"statusBarItem.warningBackground",
|
"statusBarItem.warningBackground",
|
||||||
|
@ -455,9 +451,6 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
icon = "$(warning) ";
|
icon = "$(warning) ";
|
||||||
break;
|
break;
|
||||||
case "error":
|
case "error":
|
||||||
if (status.message) {
|
|
||||||
statusBar.tooltip.appendText(status.message);
|
|
||||||
}
|
|
||||||
statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
|
statusBar.color = new vscode.ThemeColor("statusBarItem.errorForeground");
|
||||||
statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");
|
statusBar.backgroundColor = new vscode.ThemeColor("statusBarItem.errorBackground");
|
||||||
statusBar.command = "rust-analyzer.openLogs";
|
statusBar.command = "rust-analyzer.openLogs";
|
||||||
|
@ -476,6 +469,15 @@ export class Ctx implements RustAnalyzerExtensionApi {
|
||||||
statusBar.text = "$(stop-circle) rust-analyzer";
|
statusBar.text = "$(stop-circle) rust-analyzer";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (status.message) {
|
||||||
|
statusBar.tooltip.appendText(status.message);
|
||||||
|
}
|
||||||
|
if (status.workspaceInfo) {
|
||||||
|
if (statusBar.tooltip.value) {
|
||||||
|
statusBar.tooltip.appendMarkdown("\n\n---\n\n");
|
||||||
|
}
|
||||||
|
statusBar.tooltip.appendMarkdown(status.workspaceInfo);
|
||||||
|
}
|
||||||
if (statusBar.tooltip.value) {
|
if (statusBar.tooltip.value) {
|
||||||
statusBar.tooltip.appendMarkdown("\n\n---\n\n");
|
statusBar.tooltip.appendMarkdown("\n\n---\n\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -241,6 +241,7 @@ export type ServerStatusParams = {
|
||||||
health: "ok" | "warning" | "error";
|
health: "ok" | "warning" | "error";
|
||||||
quiescent: boolean;
|
quiescent: boolean;
|
||||||
message?: string;
|
message?: string;
|
||||||
|
workspaceInfo?: string;
|
||||||
};
|
};
|
||||||
export type SsrParams = {
|
export type SsrParams = {
|
||||||
query: string;
|
query: string;
|
||||||
|
|
Loading…
Reference in a new issue