mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-09-20 06:22:10 +00:00
internal: make project loading lazy
This commit is contained in:
parent
3723e5910c
commit
491f69abc4
5 changed files with 46 additions and 47 deletions
|
@ -268,13 +268,6 @@ fn run_server() -> anyhow::Result<()> {
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.discover_workspace_config().is_none()
|
|
||||||
&& !config.has_linked_projects()
|
|
||||||
&& config.detached_files().is_empty()
|
|
||||||
{
|
|
||||||
config.rediscover_workspaces();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the io_threads have an error, there's usually an error on the main
|
// If the io_threads have an error, there's usually an error on the main
|
||||||
// loop too because the channels are closed. Ensure we report both errors.
|
// loop too because the channels are closed. Ensure we report both errors.
|
||||||
match (rust_analyzer::main_loop(config, connection), io_threads.join()) {
|
match (rust_analyzer::main_loop(config, connection), io_threads.join()) {
|
||||||
|
|
|
@ -15,7 +15,8 @@ pub(crate) const ARG_PLACEHOLDER: &str = "{arg}";
|
||||||
/// A command wrapper for getting a `rust-project.json`.
|
/// A command wrapper for getting a `rust-project.json`.
|
||||||
///
|
///
|
||||||
/// This is analogous to discovering a cargo project + running `cargo-metadata` on it, but for non-Cargo build systems.
|
/// This is analogous to discovering a cargo project + running `cargo-metadata` on it, but for non-Cargo build systems.
|
||||||
pub(crate) struct DiscoverCommand {
|
#[derive(Debug, Clone)]
|
||||||
|
pub(crate) struct DiscoverProjectJson {
|
||||||
command: Vec<String>,
|
command: Vec<String>,
|
||||||
sender: Sender<DiscoverProjectMessage>,
|
sender: Sender<DiscoverProjectMessage>,
|
||||||
}
|
}
|
||||||
|
@ -27,15 +28,7 @@ pub(crate) enum DiscoverArgument {
|
||||||
Buildfile(#[serde(serialize_with = "serialize_abs_pathbuf")] AbsPathBuf),
|
Buildfile(#[serde(serialize_with = "serialize_abs_pathbuf")] AbsPathBuf),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_abs_pathbuf<S>(path: &AbsPathBuf, se: S) -> Result<S::Ok, S::Error>
|
impl DiscoverProjectJson {
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
let path: &Utf8Path = path.as_ref();
|
|
||||||
se.serialize_str(path.as_str())
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiscoverCommand {
|
|
||||||
/// Create a new [DiscoverCommand].
|
/// Create a new [DiscoverCommand].
|
||||||
pub(crate) fn new(sender: Sender<DiscoverProjectMessage>, command: Vec<String>) -> Self {
|
pub(crate) fn new(sender: Sender<DiscoverProjectMessage>, command: Vec<String>) -> Self {
|
||||||
Self { sender, command }
|
Self { sender, command }
|
||||||
|
@ -126,6 +119,14 @@ impl ParseFromLine for DiscoverProjectMessage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn serialize_abs_pathbuf<S>(path: &AbsPathBuf, se: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: serde::Serializer,
|
||||||
|
{
|
||||||
|
let path: &Utf8Path = path.as_ref();
|
||||||
|
se.serialize_str(path.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialization() {
|
fn test_deserialization() {
|
||||||
let message = r#"
|
let message = r#"
|
||||||
|
|
|
@ -74,14 +74,12 @@ pub(crate) fn handle_did_open_text_document(
|
||||||
|
|
||||||
tracing::info!("New file content set {:?}", params.text_document.text);
|
tracing::info!("New file content set {:?}", params.text_document.text);
|
||||||
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
|
state.vfs.write().0.set_file_contents(path, Some(params.text_document.text.into_bytes()));
|
||||||
if state.config.discover_workspace_config().is_some() {
|
|
||||||
tracing::debug!("queuing task");
|
tracing::debug!("queuing task");
|
||||||
let _ = state
|
let _ = state
|
||||||
.deferred_task_queue
|
.deferred_task_queue
|
||||||
.sender
|
.sender
|
||||||
.send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri));
|
.send(crate::main_loop::QueuedTask::CheckIfIndexed(params.text_document.uri));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -515,7 +515,7 @@ impl Notification for ServerStatusNotification {
|
||||||
const METHOD: &'static str = "experimental/serverStatus";
|
const METHOD: &'static str = "experimental/serverStatus";
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone)]
|
#[derive(Deserialize, Serialize, PartialEq, Eq, Clone, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct ServerStatusParams {
|
pub struct ServerStatusParams {
|
||||||
pub health: Health,
|
pub health: Health,
|
||||||
|
|
|
@ -14,12 +14,13 @@ use lsp_server::{Connection, Notification, Request};
|
||||||
use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
|
use lsp_types::{notification::Notification as _, TextDocumentIdentifier};
|
||||||
use stdx::thread::ThreadIntent;
|
use stdx::thread::ThreadIntent;
|
||||||
use tracing::{error, span, Level};
|
use tracing::{error, span, Level};
|
||||||
|
use triomphe::Arc;
|
||||||
use vfs::{loader::LoadingProgress, AbsPathBuf, FileId};
|
use vfs::{loader::LoadingProgress, AbsPathBuf, FileId};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::Config,
|
config::Config,
|
||||||
diagnostics::{fetch_native_diagnostics, DiagnosticsGeneration, NativeDiagnosticsFetchKind},
|
diagnostics::{fetch_native_diagnostics, DiagnosticsGeneration, NativeDiagnosticsFetchKind},
|
||||||
discover::{DiscoverArgument, DiscoverCommand, DiscoverProjectMessage},
|
discover::{DiscoverArgument, DiscoverProjectJson, DiscoverProjectMessage},
|
||||||
flycheck::{self, FlycheckMessage},
|
flycheck::{self, FlycheckMessage},
|
||||||
global_state::{file_id_to_url, url_to_file_id, FetchWorkspaceRequest, GlobalState},
|
global_state::{file_id_to_url, url_to_file_id, FetchWorkspaceRequest, GlobalState},
|
||||||
hack_recover_crate_name,
|
hack_recover_crate_name,
|
||||||
|
@ -113,6 +114,7 @@ pub(crate) enum Task {
|
||||||
pub(crate) enum DiscoverProjectParam {
|
pub(crate) enum DiscoverProjectParam {
|
||||||
Buildfile(AbsPathBuf),
|
Buildfile(AbsPathBuf),
|
||||||
Path(AbsPathBuf),
|
Path(AbsPathBuf),
|
||||||
|
ClassicOnDisk,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -159,8 +161,6 @@ impl fmt::Debug for Event {
|
||||||
|
|
||||||
impl GlobalState {
|
impl GlobalState {
|
||||||
fn run(mut self, inbox: Receiver<lsp_server::Message>) -> anyhow::Result<()> {
|
fn run(mut self, inbox: Receiver<lsp_server::Message>) -> anyhow::Result<()> {
|
||||||
self.update_status_or_notify();
|
|
||||||
|
|
||||||
if self.config.did_save_text_document_dynamic_registration() {
|
if self.config.did_save_text_document_dynamic_registration() {
|
||||||
let additional_patterns = self
|
let additional_patterns = self
|
||||||
.config
|
.config
|
||||||
|
@ -172,17 +172,7 @@ impl GlobalState {
|
||||||
self.register_did_save_capability(additional_patterns);
|
self.register_did_save_capability(additional_patterns);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.config.discover_workspace_config().is_none() {
|
self.discover_workspace_queue.request_op("startup".to_owned(), ());
|
||||||
self.fetch_workspaces_queue.request_op(
|
|
||||||
"startup".to_owned(),
|
|
||||||
FetchWorkspaceRequest { path: None, force_crate_graph_reload: false },
|
|
||||||
);
|
|
||||||
if let Some((cause, FetchWorkspaceRequest { path, force_crate_graph_reload })) =
|
|
||||||
self.fetch_workspaces_queue.should_start_op()
|
|
||||||
{
|
|
||||||
self.fetch_workspaces(cause, path, force_crate_graph_reload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while let Ok(event) = self.next_event(&inbox) {
|
while let Ok(event) = self.next_event(&inbox) {
|
||||||
let Some(event) = event else {
|
let Some(event) = event else {
|
||||||
|
@ -699,13 +689,14 @@ impl GlobalState {
|
||||||
self.report_progress("Fetching", state, msg, None, None);
|
self.report_progress("Fetching", state, msg, None, None);
|
||||||
}
|
}
|
||||||
Task::DiscoverLinkedProjects(arg) => {
|
Task::DiscoverLinkedProjects(arg) => {
|
||||||
if let Some(cfg) = self.config.discover_workspace_config() {
|
|
||||||
if !self.discover_workspace_queue.op_in_progress() {
|
if !self.discover_workspace_queue.op_in_progress() {
|
||||||
|
if let Some(cfg) = self.config.discover_workspace_config() {
|
||||||
// the clone is unfortunately necessary to avoid a borrowck error when
|
// the clone is unfortunately necessary to avoid a borrowck error when
|
||||||
// `self.report_progress` is called later
|
// `self.report_progress` is called later
|
||||||
let title = &cfg.progress_label.clone();
|
let title = &cfg.progress_label.clone();
|
||||||
let command = cfg.command.clone();
|
let command = cfg.command.clone();
|
||||||
let discover = DiscoverCommand::new(self.discover_sender.clone(), command);
|
let discover =
|
||||||
|
DiscoverProjectJson::new(self.discover_sender.clone(), command);
|
||||||
|
|
||||||
self.report_progress(title, Progress::Begin, None, None, None);
|
self.report_progress(title, Progress::Begin, None, None, None);
|
||||||
self.discover_workspace_queue
|
self.discover_workspace_queue
|
||||||
|
@ -715,10 +706,19 @@ impl GlobalState {
|
||||||
let arg = match arg {
|
let arg = match arg {
|
||||||
DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
|
DiscoverProjectParam::Buildfile(it) => DiscoverArgument::Buildfile(it),
|
||||||
DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
|
DiscoverProjectParam::Path(it) => DiscoverArgument::Path(it),
|
||||||
|
_ => return, // this is a bug; the arg should not be sent if `discover_workspace_config` is set
|
||||||
};
|
};
|
||||||
|
|
||||||
let handle = discover.spawn(arg).unwrap();
|
let handle = discover.spawn(arg).unwrap();
|
||||||
self.discover_handle = Some(handle);
|
self.discover_handle = Some(handle);
|
||||||
|
} else {
|
||||||
|
let config = Arc::make_mut(&mut self.config);
|
||||||
|
config.rediscover_workspaces();
|
||||||
|
|
||||||
|
let req =
|
||||||
|
FetchWorkspaceRequest { path: None, force_crate_graph_reload: false };
|
||||||
|
self.fetch_workspaces_queue
|
||||||
|
.request_op("workspaces have been discovered".to_owned(), req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -829,12 +829,19 @@ impl GlobalState {
|
||||||
let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
|
let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
|
||||||
if let Ok(crates) = &snap.analysis.crates_for(id) {
|
if let Ok(crates) = &snap.analysis.crates_for(id) {
|
||||||
if crates.is_empty() {
|
if crates.is_empty() {
|
||||||
if snap.config.discover_workspace_config().is_some() {
|
match snap.config.discover_workspace_config() {
|
||||||
|
Some(_) => {
|
||||||
let path =
|
let path =
|
||||||
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
|
from_proto::abs_path(&uri).expect("Unable to get AbsPath");
|
||||||
let arg = DiscoverProjectParam::Path(path);
|
let arg = DiscoverProjectParam::Path(path);
|
||||||
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
|
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
|
||||||
}
|
}
|
||||||
|
// default behavior; do standard discovery
|
||||||
|
None => {
|
||||||
|
let arg = DiscoverProjectParam::ClassicOnDisk;
|
||||||
|
sender.send(Task::DiscoverLinkedProjects(arg)).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
tracing::debug!(?uri, "is indexed");
|
tracing::debug!(?uri, "is indexed");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue