mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-02 06:41:48 +00:00
add option to disable notify
This commit is contained in:
parent
007737a0e7
commit
28df377759
13 changed files with 151 additions and 71 deletions
|
@ -15,6 +15,8 @@ pub struct ServerConfig {
|
|||
pub publish_decorations: bool,
|
||||
|
||||
pub exclude_globs: Vec<String>,
|
||||
#[serde(deserialize_with = "nullable_bool_false")]
|
||||
pub use_client_watching: bool,
|
||||
|
||||
pub lru_capacity: Option<usize>,
|
||||
|
||||
|
@ -31,6 +33,7 @@ impl Default for ServerConfig {
|
|||
ServerConfig {
|
||||
publish_decorations: false,
|
||||
exclude_globs: Vec::new(),
|
||||
use_client_watching: false,
|
||||
lru_capacity: None,
|
||||
with_sysroot: true,
|
||||
feature_flags: FxHashMap::default(),
|
||||
|
|
|
@ -9,8 +9,9 @@ use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestI
|
|||
use lsp_types::{ClientCapabilities, NumberOrString};
|
||||
use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData, SourceRootId};
|
||||
use ra_prof::profile;
|
||||
use ra_vfs::VfsTask;
|
||||
use ra_vfs::{VfsTask, Watch};
|
||||
use relative_path::RelativePathBuf;
|
||||
use rustc_hash::FxHashSet;
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use threadpool::ThreadPool;
|
||||
|
||||
|
@ -55,72 +56,96 @@ pub fn main_loop(
|
|||
) -> Result<()> {
|
||||
log::info!("server_config: {:#?}", config);
|
||||
|
||||
// FIXME: support dynamic workspace loading.
|
||||
let workspaces = {
|
||||
let mut loaded_workspaces = Vec::new();
|
||||
for ws_root in &ws_roots {
|
||||
let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot(
|
||||
ws_root.as_path(),
|
||||
config.with_sysroot,
|
||||
);
|
||||
match workspace {
|
||||
Ok(workspace) => loaded_workspaces.push(workspace),
|
||||
Err(e) => {
|
||||
log::error!("loading workspace failed: {}", e);
|
||||
let mut loop_state = LoopState::default();
|
||||
let mut world_state = {
|
||||
// FIXME: support dynamic workspace loading.
|
||||
let workspaces = {
|
||||
let mut loaded_workspaces = Vec::new();
|
||||
for ws_root in &ws_roots {
|
||||
let workspace = ra_project_model::ProjectWorkspace::discover_with_sysroot(
|
||||
ws_root.as_path(),
|
||||
config.with_sysroot,
|
||||
);
|
||||
match workspace {
|
||||
Ok(workspace) => loaded_workspaces.push(workspace),
|
||||
Err(e) => {
|
||||
log::error!("loading workspace failed: {}", e);
|
||||
|
||||
show_message(
|
||||
req::MessageType::Error,
|
||||
format!("rust-analyzer failed to load workspace: {}", e),
|
||||
&connection.sender,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
loaded_workspaces
|
||||
};
|
||||
|
||||
let globs = config
|
||||
.exclude_globs
|
||||
.iter()
|
||||
.map(|glob| ra_vfs_glob::Glob::new(glob))
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
|
||||
if config.use_client_watching {
|
||||
let registration_options = req::DidChangeWatchedFilesRegistrationOptions {
|
||||
watchers: workspaces
|
||||
.iter()
|
||||
.flat_map(|ws| ws.to_roots())
|
||||
.filter(|root| root.is_member())
|
||||
.map(|root| format!("{}/**/*.rs", root.path().display()))
|
||||
.map(|glob_pattern| req::FileSystemWatcher { glob_pattern, kind: None })
|
||||
.collect(),
|
||||
};
|
||||
let registration = req::Registration {
|
||||
id: "file-watcher".to_string(),
|
||||
method: "workspace/didChangeWatchedFiles".to_string(),
|
||||
register_options: Some(serde_json::to_value(registration_options).unwrap()),
|
||||
};
|
||||
let params = req::RegistrationParams { registrations: vec![registration] };
|
||||
let request =
|
||||
request_new::<req::RegisterCapability>(loop_state.next_request_id(), params);
|
||||
connection.sender.send(request.into()).unwrap();
|
||||
}
|
||||
|
||||
let feature_flags = {
|
||||
let mut ff = FeatureFlags::default();
|
||||
for (flag, value) in config.feature_flags {
|
||||
if let Err(_) = ff.set(flag.as_str(), value) {
|
||||
log::error!("unknown feature flag: {:?}", flag);
|
||||
show_message(
|
||||
req::MessageType::Error,
|
||||
format!("rust-analyzer failed to load workspace: {}", e),
|
||||
format!("unknown feature flag: {:?}", flag),
|
||||
&connection.sender,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
loaded_workspaces
|
||||
ff
|
||||
};
|
||||
log::info!("feature_flags: {:#?}", feature_flags);
|
||||
|
||||
WorldState::new(
|
||||
ws_roots,
|
||||
workspaces,
|
||||
config.lru_capacity,
|
||||
&globs,
|
||||
Watch(!config.use_client_watching),
|
||||
Options {
|
||||
publish_decorations: config.publish_decorations,
|
||||
supports_location_link: client_caps
|
||||
.text_document
|
||||
.and_then(|it| it.definition)
|
||||
.and_then(|it| it.link_support)
|
||||
.unwrap_or(false),
|
||||
},
|
||||
feature_flags,
|
||||
)
|
||||
};
|
||||
|
||||
let globs = config
|
||||
.exclude_globs
|
||||
.iter()
|
||||
.map(|glob| ra_vfs_glob::Glob::new(glob))
|
||||
.collect::<std::result::Result<Vec<_>, _>>()?;
|
||||
|
||||
let feature_flags = {
|
||||
let mut ff = FeatureFlags::default();
|
||||
for (flag, value) in config.feature_flags {
|
||||
if let Err(_) = ff.set(flag.as_str(), value) {
|
||||
log::error!("unknown feature flag: {:?}", flag);
|
||||
show_message(
|
||||
req::MessageType::Error,
|
||||
format!("unknown feature flag: {:?}", flag),
|
||||
&connection.sender,
|
||||
);
|
||||
}
|
||||
}
|
||||
ff
|
||||
};
|
||||
log::info!("feature_flags: {:#?}", feature_flags);
|
||||
|
||||
let mut world_state = WorldState::new(
|
||||
ws_roots,
|
||||
workspaces,
|
||||
config.lru_capacity,
|
||||
&globs,
|
||||
Options {
|
||||
publish_decorations: config.publish_decorations,
|
||||
supports_location_link: client_caps
|
||||
.text_document
|
||||
.and_then(|it| it.definition)
|
||||
.and_then(|it| it.link_support)
|
||||
.unwrap_or(false),
|
||||
},
|
||||
feature_flags,
|
||||
);
|
||||
|
||||
let pool = ThreadPool::new(THREADPOOL_SIZE);
|
||||
let (task_sender, task_receiver) = unbounded::<Task>();
|
||||
let (libdata_sender, libdata_receiver) = unbounded::<LibraryData>();
|
||||
let mut loop_state = LoopState::default();
|
||||
|
||||
log::info!("server initialized, serving requests");
|
||||
{
|
||||
|
@ -227,6 +252,8 @@ impl fmt::Debug for Event {
|
|||
|
||||
#[derive(Debug, Default)]
|
||||
struct LoopState {
|
||||
next_request_id: u64,
|
||||
pending_responses: FxHashSet<RequestId>,
|
||||
pending_requests: PendingRequests,
|
||||
subscriptions: Subscriptions,
|
||||
// We try not to index more than MAX_IN_FLIGHT_LIBS libraries at the same
|
||||
|
@ -236,6 +263,16 @@ struct LoopState {
|
|||
workspace_loaded: bool,
|
||||
}
|
||||
|
||||
impl LoopState {
|
||||
fn next_request_id(&mut self) -> RequestId {
|
||||
self.next_request_id += 1;
|
||||
let res: RequestId = self.next_request_id.into();
|
||||
let inserted = self.pending_responses.insert(res.clone());
|
||||
assert!(inserted);
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
fn loop_turn(
|
||||
pool: &ThreadPool,
|
||||
task_sender: &Sender<Task>,
|
||||
|
@ -290,7 +327,12 @@ fn loop_turn(
|
|||
)?;
|
||||
state_changed = true;
|
||||
}
|
||||
Message::Response(resp) => log::error!("unexpected response: {:?}", resp),
|
||||
Message::Response(resp) => {
|
||||
let removed = loop_state.pending_responses.remove(&resp.id);
|
||||
if !removed {
|
||||
log::error!("unexpected response: {:?}", resp)
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -479,6 +521,18 @@ fn on_notification(
|
|||
}
|
||||
Err(not) => not,
|
||||
};
|
||||
let not = match notification_cast::<req::DidChangeWatchedFiles>(not) {
|
||||
Ok(params) => {
|
||||
let mut vfs = state.vfs.write();
|
||||
for change in params.changes {
|
||||
let uri = change.uri;
|
||||
let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
|
||||
vfs.notify_changed(path)
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
Err(not) => not,
|
||||
};
|
||||
log::error!("unhandled notification: {:?}", not);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -682,3 +736,11 @@ where
|
|||
{
|
||||
Notification::new(N::METHOD.to_string(), params)
|
||||
}
|
||||
|
||||
fn request_new<R>(id: RequestId, params: R::Params) -> Request
|
||||
where
|
||||
R: lsp_types::request::Request,
|
||||
R::Params: Serialize,
|
||||
{
|
||||
Request::new(id, R::METHOD.to_string(), params)
|
||||
}
|
||||
|
|
|
@ -5,10 +5,11 @@ use serde::{Deserialize, Serialize};
|
|||
pub use lsp_types::{
|
||||
notification::*, request::*, ApplyWorkspaceEditParams, CodeActionParams, CodeLens,
|
||||
CodeLensParams, CompletionParams, CompletionResponse, DidChangeConfigurationParams,
|
||||
DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse, Hover,
|
||||
InitializeResult, MessageType, PublishDiagnosticsParams, ReferenceParams, ShowMessageParams,
|
||||
SignatureHelp, TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkspaceEdit,
|
||||
WorkspaceSymbolParams,
|
||||
DidChangeWatchedFilesParams, DidChangeWatchedFilesRegistrationOptions,
|
||||
DocumentOnTypeFormattingParams, DocumentSymbolParams, DocumentSymbolResponse,
|
||||
FileSystemWatcher, Hover, InitializeResult, MessageType, PublishDiagnosticsParams,
|
||||
ReferenceParams, Registration, RegistrationParams, ShowMessageParams, SignatureHelp,
|
||||
TextDocumentEdit, TextDocumentPositionParams, TextEdit, WorkspaceEdit, WorkspaceSymbolParams,
|
||||
};
|
||||
|
||||
pub enum AnalyzerStatus {}
|
||||
|
|
|
@ -12,7 +12,7 @@ use ra_ide_api::{
|
|||
SourceRootId,
|
||||
};
|
||||
use ra_project_model::ProjectWorkspace;
|
||||
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask};
|
||||
use ra_vfs::{LineEndings, RootEntry, Vfs, VfsChange, VfsFile, VfsRoot, VfsTask, Watch};
|
||||
use ra_vfs_glob::{Glob, RustPackageFilterBuilder};
|
||||
use relative_path::RelativePathBuf;
|
||||
|
||||
|
@ -60,6 +60,7 @@ impl WorldState {
|
|||
workspaces: Vec<ProjectWorkspace>,
|
||||
lru_capacity: Option<usize>,
|
||||
exclude_globs: &[Glob],
|
||||
watch: Watch,
|
||||
options: Options,
|
||||
feature_flags: FeatureFlags,
|
||||
) -> WorldState {
|
||||
|
@ -85,7 +86,7 @@ impl WorldState {
|
|||
}
|
||||
let (task_sender, task_receiver) = unbounded();
|
||||
let task_sender = Box::new(move |t| task_sender.send(t).unwrap());
|
||||
let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender);
|
||||
let (mut vfs, vfs_roots) = Vfs::new(roots, task_sender, watch);
|
||||
let roots_to_scan = vfs_roots.len();
|
||||
for r in vfs_roots {
|
||||
let vfs_root_path = vfs.root2path(r);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue