Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internal: do not drop errors from cargo metadata/check #8355

Merged
merged 7 commits into from
Apr 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/project_model/src/build_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub struct BuildDataCollector {
configs: FxHashMap<AbsPathBuf, BuildDataConfig>,
}

#[derive(Debug, Default, PartialEq, Eq)]
#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct BuildDataResult {
data: FxHashMap<AbsPathBuf, BuildDataMap>,
}
Expand Down
4 changes: 2 additions & 2 deletions crates/rust-analyzer/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@ impl Config {
pub fn hover_actions(&self) -> bool {
self.experimental("hoverActions")
}
pub fn status_notification(&self) -> bool {
self.experimental("statusNotification")
pub fn server_status_notification(&self) -> bool {
self.experimental("serverStatusNotification")
}

pub fn publish_diagnostics(&self) -> bool {
Expand Down
62 changes: 33 additions & 29 deletions crates/rust-analyzer/src/global_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use crate::{
document::DocumentData,
from_proto,
line_index::{LineEndings, LineIndex},
lsp_ext,
main_loop::Task,
op_queue::OpQueue,
reload::SourceRootConfig,
Expand All @@ -32,20 +33,6 @@ use crate::{
Result,
};

#[derive(Eq, PartialEq, Copy, Clone)]
pub(crate) enum Status {
Loading,
Ready { partial: bool },
Invalid,
NeedsReload,
}

impl Default for Status {
fn default() -> Self {
Status::Loading
}
}

// Enforces drop order
pub(crate) struct Handle<H, C> {
pub(crate) handle: H,
Expand All @@ -67,26 +54,36 @@ pub(crate) struct GlobalState {
req_queue: ReqQueue,
pub(crate) task_pool: Handle<TaskPool<Task>, Receiver<Task>>,
pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
pub(crate) vfs_config_version: u32,
pub(crate) flycheck: Vec<FlycheckHandle>,
pub(crate) flycheck_sender: Sender<flycheck::Message>,
pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
pub(crate) config: Arc<Config>,
pub(crate) analysis_host: AnalysisHost,
pub(crate) diagnostics: DiagnosticCollection,
pub(crate) mem_docs: FxHashMap<VfsPath, DocumentData>,
pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
pub(crate) shutdown_requested: bool,
pub(crate) status: Status,
pub(crate) last_reported_status: Option<lsp_ext::ServerStatusParams>,
pub(crate) source_root_config: SourceRootConfig,
pub(crate) proc_macro_client: Option<ProcMacroClient>,

pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
pub(crate) fetch_workspaces_queue: OpQueue<(), ()>,
pub(crate) flycheck: Vec<FlycheckHandle>,
pub(crate) flycheck_sender: Sender<flycheck::Message>,
pub(crate) flycheck_receiver: Receiver<flycheck::Message>,

pub(crate) vfs: Arc<RwLock<(vfs::Vfs, FxHashMap<FileId, LineEndings>)>>,
pub(crate) vfs_config_version: u32,
pub(crate) vfs_progress_config_version: u32,
pub(crate) vfs_progress_n_total: usize,
pub(crate) vfs_progress_n_done: usize,

/// For both `workspaces` and `workspace_build_data`, the field stores the
/// data we actually use, while the `OpQueue` stores the result of the last
/// fetch.
///
/// If the fetch (partially) fails, we do not update the values.
pub(crate) workspaces: Arc<Vec<ProjectWorkspace>>,
pub(crate) fetch_workspaces_queue: OpQueue<(), Vec<anyhow::Result<ProjectWorkspace>>>,
pub(crate) workspace_build_data: Option<BuildDataResult>,
pub(crate) fetch_build_data_queue: OpQueue<BuildDataCollector, ()>,
pub(crate) fetch_build_data_queue:
OpQueue<BuildDataCollector, Option<anyhow::Result<BuildDataResult>>>,

latest_requests: Arc<RwLock<LatestRequests>>,
}
Expand Down Expand Up @@ -124,25 +121,32 @@ impl GlobalState {
GlobalState {
sender,
req_queue: ReqQueue::default(),
vfs_config_version: 0,
task_pool,
loader,
flycheck: Vec::new(),
flycheck_sender,
flycheck_receiver,
config: Arc::new(config),
analysis_host,
diagnostics: Default::default(),
mem_docs: FxHashMap::default(),
semantic_tokens_cache: Arc::new(Default::default()),
vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
shutdown_requested: false,
status: Status::default(),
last_reported_status: None,
source_root_config: SourceRootConfig::default(),
proc_macro_client: None,

flycheck: Vec::new(),
flycheck_sender,
flycheck_receiver,

vfs: Arc::new(RwLock::new((vfs::Vfs::default(), FxHashMap::default()))),
vfs_config_version: 0,
vfs_progress_config_version: 0,
vfs_progress_n_total: 0,
vfs_progress_n_done: 0,

workspaces: Arc::new(Vec::new()),
fetch_workspaces_queue: OpQueue::default(),
workspace_build_data: None,

fetch_build_data_queue: OpQueue::default(),
latest_requests: Default::default(),
}
Expand Down
30 changes: 15 additions & 15 deletions crates/rust-analyzer/src/lsp_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,26 +241,26 @@ pub struct SsrParams {
pub selections: Vec<lsp_types::Range>,
}

pub enum StatusNotification {}
pub enum ServerStatusNotification {}

#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum Status {
Loading,
ReadyPartial,
Ready,
NeedsReload,
Invalid,
impl Notification for ServerStatusNotification {
type Params = ServerStatusParams;
const METHOD: &'static str = "experimental/serverStatus";
}

#[derive(Deserialize, Serialize)]
pub struct StatusParams {
pub status: Status,
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
pub struct ServerStatusParams {
pub health: Health,
pub quiescent: bool,
pub message: Option<String>,
}

impl Notification for StatusNotification {
type Params = StatusParams;
const METHOD: &'static str = "rust-analyzer/status";
#[derive(Serialize, Deserialize, Clone, Copy, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub enum Health {
Ok,
Warning,
Error,
}

pub enum CodeActionRequest {}
Expand Down
101 changes: 59 additions & 42 deletions crates/rust-analyzer/src/main_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! requests/replies and notifications back to the client.
use std::{
env, fmt,
sync::Arc,
time::{Duration, Instant},
};

Expand All @@ -12,14 +13,15 @@ use ide::{Canceled, FileId};
use ide_db::base_db::VfsPath;
use lsp_server::{Connection, Notification, Request, Response};
use lsp_types::notification::Notification as _;
use project_model::BuildDataCollector;
use vfs::ChangeKind;

use crate::{
config::Config,
dispatch::{NotificationDispatcher, RequestDispatcher},
document::DocumentData,
from_proto,
global_state::{file_id_to_url, url_to_file_id, GlobalState, Status},
global_state::{file_id_to_url, url_to_file_id, GlobalState},
handlers, lsp_ext,
lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress},
reload::{BuildDataProgress, ProjectWorkspaceProgress},
Expand Down Expand Up @@ -187,7 +189,7 @@ impl GlobalState {
log::info!("task queue len: {}", task_queue_len);
}

let mut new_status = self.status;
let was_quiescent = self.is_quiescent();
match event {
Event::Lsp(msg) => match msg {
lsp_server::Message::Request(req) => self.on_request(loop_start, req)?,
Expand Down Expand Up @@ -227,11 +229,24 @@ impl GlobalState {
(Progress::Report, Some(msg))
}
ProjectWorkspaceProgress::End(workspaces) => {
self.fetch_workspaces_completed();
self.switch_workspaces(workspaces, None);
self.fetch_workspaces_completed(workspaces);

let old = Arc::clone(&self.workspaces);
self.switch_workspaces();
let workspaces_updated = !Arc::ptr_eq(&old, &self.workspaces);

if self.config.run_build_scripts() && workspaces_updated {
let mut collector = BuildDataCollector::default();
for ws in self.workspaces.iter() {
ws.collect_build_data_configs(&mut collector);
}
self.fetch_build_data_request(collector)
}

(Progress::End, None)
}
};

self.report_progress("fetching", state, msg, None);
}
Task::FetchBuildData(progress) => {
Expand All @@ -240,19 +255,21 @@ impl GlobalState {
BuildDataProgress::Report(msg) => {
(Some(Progress::Report), Some(msg))
}
BuildDataProgress::End(collector) => {
self.fetch_build_data_completed();
let workspaces =
(*self.workspaces).clone().into_iter().map(Ok).collect();
self.switch_workspaces(workspaces, Some(collector));
BuildDataProgress::End(build_data_result) => {
self.fetch_build_data_completed(build_data_result);

self.switch_workspaces();

(Some(Progress::End), None)
}
};

if let Some(state) = state {
self.report_progress("loading", state, msg, None);
}
}
}

// Coalesce multiple task events into one loop turn
task = match self.task_pool.receiver.try_recv() {
Ok(task) => task,
Expand Down Expand Up @@ -298,30 +315,25 @@ impl GlobalState {
}
vfs::loader::Message::Progress { n_total, n_done, config_version } => {
always!(config_version <= self.vfs_config_version);
if n_total == 0 {
new_status = Status::Invalid;

self.vfs_progress_config_version = config_version;
self.vfs_progress_n_total = n_total;
self.vfs_progress_n_done = n_done;

let state = if n_done == 0 {
Progress::Begin
} else if n_done < n_total {
Progress::Report
} else {
let state = if n_done == 0 {
new_status = Status::Loading;
Progress::Begin
} else if n_done < n_total {
Progress::Report
} else {
assert_eq!(n_done, n_total);
new_status = Status::Ready {
partial: self.config.run_build_scripts()
&& self.workspace_build_data.is_none()
|| config_version < self.vfs_config_version,
};
Progress::End
};
self.report_progress(
"roots scanned",
state,
Some(format!("{}/{}", n_done, n_total)),
Some(Progress::fraction(n_done, n_total)),
)
}
assert_eq!(n_done, n_total);
Progress::End
};
self.report_progress(
"roots scanned",
state,
Some(format!("{}/{}", n_done, n_total)),
Some(Progress::fraction(n_done, n_total)),
)
}
}
// Coalesce many VFS event into a single loop turn
Expand Down Expand Up @@ -397,18 +409,14 @@ impl GlobalState {
}

let state_changed = self.process_changes();
let prev_status = self.status;
if prev_status != new_status {
self.transition(new_status);
}
let is_ready = matches!(self.status, Status::Ready { .. });
if prev_status == Status::Loading && is_ready {

if self.is_quiescent() && !was_quiescent {
for flycheck in &self.flycheck {
flycheck.update();
}
}

if is_ready && (state_changed || prev_status == Status::Loading) {
if self.is_quiescent() && (!was_quiescent || state_changed) {
self.update_file_notifications_on_threadpool();

// Refresh semantic tokens if the client supports it.
Expand Down Expand Up @@ -437,9 +445,13 @@ impl GlobalState {
}
}

self.fetch_workspaces_if_needed();
if self.config.cargo_autoreload() {
self.fetch_workspaces_if_needed();
}
self.fetch_build_data_if_needed();

self.report_new_status_if_needed();

let loop_duration = loop_start.elapsed();
if loop_duration > Duration::from_millis(100) {
log::warn!("overly long loop turn: {:?}", loop_duration);
Expand All @@ -466,7 +478,8 @@ impl GlobalState {
return Ok(());
}

if self.status == Status::Loading && req.method != "shutdown" {
// Avoid flashing a bunch of unresolved references during initial load.
if self.workspaces.is_empty() && !self.is_quiescent() {
self.respond(lsp_server::Response::new_err(
req.id,
// FIXME: i32 should impl From<ErrorCode> (from() guarantees lossless conversion)
Expand All @@ -477,7 +490,11 @@ impl GlobalState {
}

RequestDispatcher { req: Some(req), global_state: self }
.on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| Ok(s.fetch_workspaces_request()))?
.on_sync::<lsp_ext::ReloadWorkspace>(|s, ()| {
s.fetch_workspaces_request();
s.fetch_workspaces_if_needed();
Ok(())
})?
.on_sync::<lsp_ext::JoinLines>(|s, p| handlers::handle_join_lines(s.snapshot(), p))?
.on_sync::<lsp_ext::OnEnter>(|s, p| handlers::handle_on_enter(s.snapshot(), p))?
.on_sync::<lsp_types::request::Shutdown>(|s, ()| {
Expand Down
Loading