Skip to content

Commit 89a9289

Browse files
committed
Handle registration and start listening to fs events.
1 parent 8541acb commit 89a9289

File tree

4 files changed

+85
-146
lines changed

4 files changed

+85
-146
lines changed

src/languageclient.rs

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,27 +1567,6 @@ impl State {
15671567
}
15681568
let uri = filename.to_url()?;
15691569

1570-
// TODO: use notify library to generate file event sources.
1571-
let lang_ids = self.get(|state| {
1572-
state
1573-
.method_registrations
1574-
.get_didChangeWatchedFiles_languageIds(&filename)
1575-
})?;
1576-
for lang_id in &lang_ids {
1577-
self.notify(
1578-
Some(lang_id.as_str()),
1579-
lsp::notification::DidChangeWatchedFiles::METHOD,
1580-
DidChangeWatchedFilesParams {
1581-
changes: vec![
1582-
FileEvent {
1583-
uri: uri.clone(),
1584-
typ: FileChangeType::Changed,
1585-
},
1586-
],
1587-
},
1588-
)?;
1589-
}
1590-
15911570
self.notify(
15921571
Some(&languageId),
15931572
lsp::notification::DidSaveTextDocument::METHOD,
@@ -1705,34 +1684,68 @@ impl State {
17051684

17061685
pub fn client_registerCapability(
17071686
&mut self,
1708-
languageId: &str,
1687+
_languageId: &str,
17091688
params: &Option<Params>,
17101689
) -> Result<Value> {
17111690
info!("Begin {}", lsp::request::RegisterCapability::METHOD);
17121691
let params: RegistrationParams = serde_json::from_value(params.clone().to_value())?;
1713-
self.update(|state| {
1714-
for r in &params.registrations {
1715-
state.method_registrations.register(languageId, r)?;
1692+
for r in &params.registrations {
1693+
match r.method.as_str() {
1694+
lsp::notification::DidChangeWatchedFiles::METHOD => {
1695+
let opt: DidChangeWatchedFilesRegistrationOptions =
1696+
serde_json::from_value(r.register_options.clone().unwrap_or_default())?;
1697+
if let Some(ref mut watcher) = self.watcher {
1698+
for w in opt.watchers {
1699+
warn!("Start watching {}", w.glob_pattern);
1700+
watcher.watch(w.glob_pattern, notify::RecursiveMode::NonRecursive)?;
1701+
}
1702+
}
1703+
}
1704+
_ => {
1705+
warn!("Unknown registration: {:?}", r);
1706+
}
17161707
}
1717-
Ok(())
1718-
})?;
1708+
}
1709+
1710+
self.registrations.extend(params.registrations);
17191711
info!("End {}", lsp::request::RegisterCapability::METHOD);
17201712
Ok(Value::Null)
17211713
}
17221714

17231715
pub fn client_unregisterCapability(
17241716
&mut self,
1725-
languageId: &str,
1717+
_languageId: &str,
17261718
params: &Option<Params>,
17271719
) -> Result<Value> {
17281720
info!("Begin {}", lsp::request::UnregisterCapability::METHOD);
17291721
let params: UnregistrationParams = serde_json::from_value(params.clone().to_value())?;
1730-
self.update(|state| {
1731-
for r in params.unregisterations {
1732-
state.method_registrations.unregister(languageId, &r)?;
1722+
let mut regs_removed = vec![];
1723+
for r in &params.unregisterations {
1724+
if let Some(idx) = self.registrations
1725+
.iter()
1726+
.position(|i| i.id == r.id && i.method == r.method)
1727+
{
1728+
regs_removed.push(self.registrations.swap_remove(idx));
17331729
}
1734-
Ok(())
1735-
})?;
1730+
}
1731+
1732+
for r in &regs_removed {
1733+
match r.method.as_str() {
1734+
lsp::notification::DidChangeWatchedFiles::METHOD => {
1735+
let opt: DidChangeWatchedFilesRegistrationOptions =
1736+
serde_json::from_value(r.register_options.clone().unwrap_or_default())?;
1737+
if let Some(ref mut watcher) = self.watcher {
1738+
for w in opt.watchers {
1739+
watcher.unwatch(w.glob_pattern)?;
1740+
}
1741+
}
1742+
}
1743+
_ => {
1744+
warn!("Unknown registration: {:?}", r);
1745+
}
1746+
}
1747+
}
1748+
17361749
info!("End {}", lsp::request::UnregisterCapability::METHOD);
17371750
Ok(Value::Null)
17381751
}
@@ -2365,7 +2378,7 @@ impl State {
23652378
std::thread::Builder::new()
23662379
.name(thread_name.clone())
23672380
.spawn(move || {
2368-
if let Err(err) = loop_reader(reader, &Some(languageId.clone()), &tx) {
2381+
if let Err(err) = vim::loop_reader(reader, &Some(languageId.clone()), &tx) {
23692382
let _ = tx.send(Message::Notification(
23702383
Some(languageId.clone()),
23712384
rpc::Notification {
@@ -2412,4 +2425,23 @@ impl State {
24122425

24132426
Ok(())
24142427
}
2428+
2429+
pub fn check_fs_notify(&mut self) -> () {
2430+
if self.watcher.is_some() {
2431+
loop {
2432+
let result = self.watcher_rx.try_recv();
2433+
let event = match result {
2434+
Ok(event) => event,
2435+
Err(err) => {
2436+
if let TryRecvError::Disconnected = err {
2437+
warn!("File system notification channel disconnected!");
2438+
}
2439+
break;
2440+
}
2441+
};
2442+
2443+
warn!("File system event: {:?}", event);
2444+
}
2445+
}
2446+
}
24152447
}

src/main.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::ops::Deref;
1212
use std::path::{Path, PathBuf};
1313
use std::process::{ChildStdin, ChildStdout, Stdio};
1414
use std::str::FromStr;
15-
use std::sync::mpsc::{channel, Receiver, Sender};
15+
use std::sync::mpsc::{channel, Receiver, Sender, TryRecvError};
1616
use std::thread;
1717
use std::time;
1818

@@ -61,6 +61,8 @@ extern crate glob;
6161
extern crate regex;
6262

6363
extern crate notify;
64+
#[allow(unused_imports)]
65+
use notify::Watcher;
6466

6567
#[macro_use]
6668
extern crate structopt;
@@ -71,11 +73,8 @@ use types::*;
7173
mod utils;
7274
use utils::*;
7375
mod vim;
74-
use vim::*;
7576
mod rpchandler;
7677
mod languageclient;
77-
#[allow(unused_imports)]
78-
use languageclient::*;
7978
mod logger;
8079

8180
#[derive(Debug, StructOpt)]
@@ -91,7 +90,7 @@ fn run() -> Result<()> {
9190
.spawn(move || {
9291
let stdin = std::io::stdin();
9392
let stdin = stdin.lock();
94-
if let Err(err) = loop_reader(stdin, &None, &tx) {
93+
if let Err(err) = vim::loop_reader(stdin, &None, &tx) {
9594
error!("{} exited: {:?}", reader_thread_name, err);
9695
}
9796
})?;

src/types.rs

Lines changed: 10 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ pub struct State {
8888
#[serde(skip_serializing)]
8989
pub writers: HashMap<String, Box<SyncWrite>>,
9090
pub capabilities: HashMap<String, Value>,
91-
pub method_registrations: MethodRegistrations,
91+
pub registrations: Vec<Registration>,
9292
pub roots: HashMap<String, String>,
9393
pub text_documents: HashMap<String, TextDocumentItem>,
9494
pub text_documents_metadata: HashMap<String, TextDocumentItemMetadata>,
@@ -102,7 +102,7 @@ pub struct State {
102102
#[serde(skip_serializing)]
103103
pub watcher_rx: Receiver<notify::DebouncedEvent>,
104104
#[serde(skip_serializing)]
105-
pub watcher: Watcher,
105+
pub watcher: Option<notify::RecommendedWatcher>,
106106

107107
pub is_nvim: bool,
108108
pub last_cursor_line: u64,
@@ -130,21 +130,20 @@ pub struct State {
130130

131131
impl State {
132132
pub fn new() -> Result<State> {
133-
// TODO: move this into LanguageClientStart.
133+
let logger = logger::init()?;
134+
135+
let (tx, rx) = channel();
136+
134137
let (watcher_tx, watcher_rx) = channel();
135138
// TODO: duration configurable.
136139
let watcher = match notify::watcher(watcher_tx, std::time::Duration::from_secs(2)) {
137-
Ok(watcher) => Watcher::Some(watcher),
140+
Ok(watcher) => Some(watcher),
138141
Err(err) => {
139-
error!("{:?}", err);
140-
Watcher::None
142+
warn!("{:?}", err);
143+
None
141144
}
142145
};
143146

144-
let (tx, rx) = channel();
145-
146-
let logger = logger::init()?;
147-
148147
Ok(State {
149148
id: 0,
150149
tx,
@@ -155,7 +154,7 @@ impl State {
155154
child_ids: HashMap::new(),
156155
writers: HashMap::new(),
157156
capabilities: HashMap::new(),
158-
method_registrations: MethodRegistrations::default(),
157+
registrations: vec![],
159158
roots: HashMap::new(),
160159
text_documents: HashMap::new(),
161160
text_documents_metadata: HashMap::new(),
@@ -862,74 +861,3 @@ impl<T: Deref> OptionDeref<T> for Option<T> {
862861
self.as_ref().map(Deref::deref)
863862
}
864863
}
865-
866-
#[derive(Debug, Serialize, Default)]
867-
pub struct MethodRegistrations {
868-
// (languageId, Id) => Options.
869-
pub didChangeWatchedFiles:
870-
HashMap<(String, String), Vec<DidChangeWatchedFilesRegistrationOptions>>,
871-
}
872-
873-
impl MethodRegistrations {
874-
pub fn register(&mut self, languageId: &str, r: &Registration) -> Result<()> {
875-
match r.method.as_str() {
876-
lsp::notification::DidChangeWatchedFiles::METHOD => {
877-
let opt: DidChangeWatchedFilesRegistrationOptions =
878-
serde_json::from_value(r.register_options.clone().unwrap_or_default())?;
879-
self.didChangeWatchedFiles
880-
.entry((languageId.into(), r.id.clone()))
881-
.or_insert_with(|| vec![])
882-
.push(opt);
883-
}
884-
_ => {
885-
warn!("Unknown registration: {:?}", r);
886-
}
887-
}
888-
889-
Ok(())
890-
}
891-
892-
pub fn unregister(&mut self, languageId: &str, r: &Unregistration) -> Result<()> {
893-
match r.method.as_str() {
894-
lsp::notification::DidChangeWatchedFiles::METHOD => {
895-
self.didChangeWatchedFiles
896-
.remove(&(languageId.into(), r.id.clone()));
897-
}
898-
_ => {
899-
warn!("Unknown unregistration: {:?}", r);
900-
}
901-
}
902-
Ok(())
903-
}
904-
905-
pub fn get_didChangeWatchedFiles_languageIds(&self, path: &str) -> Result<Vec<String>> {
906-
let mut lang_ids = vec![];
907-
// TODO: optimize the structure.
908-
for (&(ref lang_id, _), opts) in &self.didChangeWatchedFiles {
909-
for opt in opts {
910-
for watch in &opt.watchers {
911-
// TODO: match event.
912-
if glob::Pattern::new(watch.glob_pattern.as_str())?.matches(path) {
913-
lang_ids.push(lang_id.clone());
914-
}
915-
}
916-
}
917-
}
918-
Ok(lang_ids)
919-
}
920-
}
921-
922-
pub enum Watcher {
923-
None,
924-
Some(notify::RecommendedWatcher),
925-
}
926-
927-
impl std::fmt::Debug for Watcher {
928-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
929-
let msg = match *self {
930-
Watcher::None => "None",
931-
Watcher::Some(_) => "Some Watcher",
932-
};
933-
write!(f, "{}", msg)
934-
}
935-
}

src/vim.rs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ impl State {
5555
if let Err(ref err) = result {
5656
if err.downcast_ref::<LCError>().is_none() {
5757
error!(
58-
"Error handling message: {}\nMessage: {:?}\nError: {:?}",
58+
"Error handling message: {}\n\nMessage: {:?}\n\nError: {:?}",
5959
err, method_call, err
6060
);
6161
}
@@ -69,7 +69,7 @@ impl State {
6969
if let Err(ref err) = result {
7070
if err.downcast_ref::<LCError>().is_none() {
7171
error!(
72-
"Error handling message: {}\nMessage: {:?}\nError: {:?}",
72+
"Error handling message: {}\n\nMessage: {:?}\n\nError: {:?}",
7373
err, notification, err
7474
);
7575
}
@@ -80,6 +80,8 @@ impl State {
8080
}
8181
}
8282
}
83+
84+
self.check_fs_notify();
8385
}
8486
}
8587

@@ -306,7 +308,7 @@ pub fn loop_reader<T: BufRead>(
306308
loop {
307309
let mut message = String::new();
308310
let mut line = String::new();
309-
if let Some(languageId) = languageId.clone() {
311+
if languageId.is_some() {
310312
input.read_line(&mut line)?;
311313
let line = line.trim();
312314
if line.is_empty() {
@@ -361,26 +363,4 @@ pub fn loop_reader<T: BufRead>(
361363
}
362364

363365
Ok(())
364-
365-
// TODO: notify.
366-
// if languageId.is_some() {
367-
// loop {
368-
// let event = self.update(|state| {
369-
// Ok(state
370-
// .watcher_rx
371-
// .lock()
372-
// .map_err(|_| err_msg("Failed to lock watcher_rx"))?
373-
// .try_recv()?)
374-
// });
375-
// let event = match event {
376-
// Ok(event) => event,
377-
// Err(err) => {
378-
// error!("{}", err);
379-
// break;
380-
// }
381-
// };
382-
383-
// warn!("File system event: {:?}", event);
384-
// }
385-
// }
386366
}

0 commit comments

Comments
 (0)