on master help sign in
Work around the rest of the blocking issues.
commitba970054957238cb682ae3be022b675131beb6f8 authorBlaž Hrastnik <blaz@mxxn.io> dateThu 6 May 2021, 17:15 (5 years ago) parentd00414f
5 files changed+197−131
Cargo.lock+12 helix-lsp/Cargo.toml+1 helix-lsp/src/client.rs+19−45 helix-lsp/src/lib.rs+1−2 helix-term/src/commands.rs+164−84
Cargo.lock+12
@@ -191,6 +191,17 @@ version = "0.3.14"
191191source = "registry+https://github.com/rust-lang/crates.io-index"
192192checksum = "098cd1c6dda6ca01650f1a37a794245eb73181d0d4d4e955e2f3c37db7af1815"
193193
194+[[package]]
195+name = "futures-executor"
196+version = "0.3.14"
197+source = "registry+https://github.com/rust-lang/crates.io-index"
198+checksum = "10f6cb7042eda00f0049b1d2080aa4b93442997ee507eb3828e8bd7577f94c9d"
199+dependencies = [
200+ "futures-core",
201+ "futures-task",
202+ "futures-util",
203+]
204+
194205[[package]]
195206name = "futures-macro"
196207version = "0.3.14"
@@ -293,6 +304,7 @@ name = "helix-lsp"
293304version = "0.1.0"
294305dependencies = [
295306 "anyhow",
307+ "futures-executor",
296308 "futures-util",
297309 "glob",
298310 "helix-core",
helix-lsp/Cargo.toml+1
@@ -14,6 +14,7 @@ once_cell = "1.4"
1414lsp-types = { version = "0.89", features = ["proposed"] }
1515tokio = { version = "1", features = ["full"] }
1616tokio-stream = "0.1.5"
17+futures-executor = { version = "0.3" }
1718url = "2"
1819pathdiff = "0.2"
1920shellexpand = "2.0"
helix-lsp/src/client.rs+19−45
@@ -152,7 +152,7 @@ impl Client {
152152
153153 timeout(Duration::from_secs(2), rx.recv())
154154 .await
155− .map_err(|e| Error::Timeout)? // return Timeout
155+ .map_err(|_| Error::Timeout)? // return Timeout
156156 .unwrap() // TODO: None if channel closed
157157 }
158158 }
@@ -500,11 +500,11 @@ impl Client {
500500 self.call::<lsp::request::Completion>(params)
501501 }
502502
503− pub async fn text_document_signature_help(
503+ pub fn text_document_signature_help(
504504 &self,
505505 text_document: lsp::TextDocumentIdentifier,
506506 position: lsp::Position,
507− ) -> anyhow::Result<Option<lsp::SignatureHelp>> {
507+ ) -> impl Future<Output = Result<Value>> {
508508 let params = lsp::SignatureHelpParams {
509509 text_document_position_params: lsp::TextDocumentPositionParams {
510510 text_document,
@@ -517,18 +517,14 @@ impl Client {
517517 // lsp::SignatureHelpContext
518518 };
519519
520− let response = self
521− .request::<lsp::request::SignatureHelpRequest>(params)
522− .await?;
523−
524− Ok(response)
520+ self.call::<lsp::request::SignatureHelpRequest>(params)
525521 }
526522
527− pub async fn text_document_hover(
523+ pub fn text_document_hover(
528524 &self,
529525 text_document: lsp::TextDocumentIdentifier,
530526 position: lsp::Position,
531− ) -> anyhow::Result<Option<lsp::Hover>> {
527+ ) -> impl Future<Output = Result<Value>> {
532528 let params = lsp::HoverParams {
533529 text_document_position_params: lsp::TextDocumentPositionParams {
534530 text_document,
@@ -540,9 +536,7 @@ impl Client {
540536 // lsp::SignatureHelpContext
541537 };
542538
543− let response = self.request::<lsp::request::HoverRequest>(params).await?;
544−
545− Ok(response)
539+ self.call::<lsp::request::HoverRequest>(params)
546540 }
547541
548542 // formatting
@@ -607,7 +601,7 @@ impl Client {
607601 Ok(response.unwrap_or_default())
608602 }
609603
610− async fn goto_request<
604+ fn goto_request<
611605 T: lsp::request::Request<
612606 Params = lsp::GotoDefinitionParams,
613607 Result = Option<lsp::GotoDefinitionResponse>,
@@ -616,7 +610,7 @@ impl Client {
616610 &self,
617611 text_document: lsp::TextDocumentIdentifier,
618612 position: lsp::Position,
619− ) -> anyhow::Result<Vec<lsp::Location>> {
613+ ) -> impl Future<Output = Result<Value>> {
620614 let params = lsp::GotoDefinitionParams {
621615 text_document_position_params: lsp::TextDocumentPositionParams {
622616 text_document,
@@ -630,56 +624,38 @@ impl Client {
630624 },
631625 };
632626
633− let response = self.request::<T>(params).await?;
634−
635− let items = match response {
636− Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location],
637− Some(lsp::GotoDefinitionResponse::Array(locations)) => locations,
638− Some(lsp::GotoDefinitionResponse::Link(locations)) => locations
639− .into_iter()
640− .map(|location_link| lsp::Location {
641− uri: location_link.target_uri,
642− range: location_link.target_range,
643− })
644− .collect(),
645− None => Vec::new(),
646− };
647−
648− Ok(items)
627+ self.call::<T>(params)
649628 }
650629
651− pub async fn goto_definition(
630+ pub fn goto_definition(
652631 &self,
653632 text_document: lsp::TextDocumentIdentifier,
654633 position: lsp::Position,
655− ) -> anyhow::Result<Vec<lsp::Location>> {
634+ ) -> impl Future<Output = Result<Value>> {
656635 self.goto_request::<lsp::request::GotoDefinition>(text_document, position)
657− .await
658636 }
659637
660− pub async fn goto_type_definition(
638+ pub fn goto_type_definition(
661639 &self,
662640 text_document: lsp::TextDocumentIdentifier,
663641 position: lsp::Position,
664− ) -> anyhow::Result<Vec<lsp::Location>> {
642+ ) -> impl Future<Output = Result<Value>> {
665643 self.goto_request::<lsp::request::GotoTypeDefinition>(text_document, position)
666− .await
667644 }
668645
669− pub async fn goto_implementation(
646+ pub fn goto_implementation(
670647 &self,
671648 text_document: lsp::TextDocumentIdentifier,
672649 position: lsp::Position,
673− ) -> anyhow::Result<Vec<lsp::Location>> {
650+ ) -> impl Future<Output = Result<Value>> {
674651 self.goto_request::<lsp::request::GotoImplementation>(text_document, position)
675− .await
676652 }
677653
678− pub async fn goto_reference(
654+ pub fn goto_reference(
679655 &self,
680656 text_document: lsp::TextDocumentIdentifier,
681657 position: lsp::Position,
682− ) -> anyhow::Result<Vec<lsp::Location>> {
658+ ) -> impl Future<Output = Result<Value>> {
683659 let params = lsp::ReferenceParams {
684660 text_document_position: lsp::TextDocumentPositionParams {
685661 text_document,
@@ -696,8 +672,6 @@ impl Client {
696672 },
697673 };
698674
699− let response = self.request::<lsp::request::References>(params).await?;
700−
701− Ok(response.unwrap_or_default())
675+ self.call::<lsp::request::References>(params)
702676 }
703677}
helix-lsp/src/lib.rs+1−2
@@ -203,8 +203,7 @@ impl Registry {
203203 Client::start(&config.command, &config.args).ok()?;
204204
205205 // TODO: run this async without blocking
206− let rt = tokio::runtime::Handle::current();
207− rt.block_on(client.initialize()).unwrap();
206+ futures_executor::block_on(client.initialize()).unwrap();
208207
209208 s_incoming.push(UnboundedReceiverStream::new(incoming));
210209
helix-term/src/commands.rs+164−84
@@ -108,16 +108,6 @@ impl<'a> Context<'a> {
108108/// state (usually by creating and applying a transaction).
109109pub type Command = fn(cx: &mut Context);
110110
111−#[inline]
112−fn block_on<T>(future: impl Future<Output = T>) -> T {
113− use tokio::runtime::Runtime;
114− // let rt = Runtime::new().unwrap();
115− let rt = tokio::runtime::Handle::current();
116− // let local = LocalSet::new();
117− // local.block_on(&rt, future)
118− rt.block_on(future)
119−}
120−
121111pub fn move_char_left(cx: &mut Context) {
122112 let count = cx.count;
123113 let (view, doc) = cx.current();
@@ -260,13 +250,13 @@ pub fn move_next_word_end(cx: &mut Context) {
260250}
261251
262252pub fn move_file_start(cx: &mut Context) {
263− push_jump(cx);
253+ push_jump(cx.editor);
264254 let (view, doc) = cx.current();
265255 doc.set_selection(view.id, Selection::point(0));
266256}
267257
268258pub fn move_file_end(cx: &mut Context) {
269− push_jump(cx);
259+ push_jump(cx.editor);
270260 let (view, doc) = cx.current();
271261 let text = doc.text();
272262 let last_line = text.line_to_char(text.len_lines().saturating_sub(2));
@@ -880,7 +870,7 @@ pub fn command_mode(cx: &mut Context) {
880870 // TODO: non-blocking via save() command
881871 let id = editor.view().doc;
882872 let doc = &mut editor.documents[id];
883− block_on(doc.save());
873+ tokio::spawn(doc.save());
884874 }
885875
886876 _ => (),
@@ -1079,8 +1069,8 @@ pub fn normal_mode(cx: &mut Context) {
10791069}
10801070
10811071// Store a jump on the jumplist.
1082−fn push_jump(cx: &mut Context) {
1083− let (view, doc) = cx.current();
1072+fn push_jump(editor: &mut Editor) {
1073+ let (view, doc) = editor.current();
10841074 let jump = { (doc.id(), doc.selection(view.id).clone()) };
10851075 view.jumps.push(jump);
10861076}
@@ -1089,7 +1079,7 @@ pub fn goto_mode(cx: &mut Context) {
10891079 let count = cx.count;
10901080
10911081 if count > 1 {
1092− push_jump(cx);
1082+ push_jump(cx.editor);
10931083
10941084 // TODO: can't go to line 1 since we can't distinguish between g and 1g, g gets converted
10951085 // to 1g
@@ -1127,10 +1117,15 @@ pub fn exit_select_mode(cx: &mut Context) {
11271117 cx.doc().mode = Mode::Normal;
11281118}
11291119
1130−fn _goto(cx: &mut Context, locations: Vec<lsp::Location>, offset_encoding: OffsetEncoding) {
1120+fn _goto(
1121+ editor: &mut Editor,
1122+ compositor: &mut Compositor,
1123+ locations: Vec<lsp::Location>,
1124+ offset_encoding: OffsetEncoding,
1125+) {
11311126 use helix_view::editor::Action;
11321127
1133− push_jump(cx);
1128+ push_jump(editor);
11341129
11351130 fn jump_to(
11361131 editor: &mut Editor,
@@ -1152,7 +1147,7 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>, offset_encoding: Offse
11521147
11531148 match locations.as_slice() {
11541149 [location] => {
1155− jump_to(cx.editor, location, offset_encoding, Action::Replace);
1150+ jump_to(editor, location, offset_encoding, Action::Replace);
11561151 }
11571152 [] => (), // maybe show user message that no definition was found?
11581153 _locations => {
@@ -1167,7 +1162,7 @@ fn _goto(cx: &mut Context, locations: Vec<lsp::Location>, offset_encoding: Offse
11671162 jump_to(editor, location, offset_encoding, action)
11681163 },
11691164 );
1170− cx.push_layer(Box::new(picker));
1165+ compositor.push(Box::new(picker));
11711166 }
11721167 }
11731168}
@@ -1184,8 +1179,29 @@ pub fn goto_definition(cx: &mut Context) {
11841179 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
11851180
11861181 // TODO: handle fails
1187− let res = block_on(language_server.goto_definition(doc.identifier(), pos)).unwrap_or_default();
1188− _goto(cx, res, offset_encoding);
1182+ let future = language_server.goto_definition(doc.identifier(), pos);
1183+
1184+ cx.callback(
1185+ future,
1186+ move |editor: &mut Editor,
1187+ compositor: &mut Compositor,
1188+ response: Option<lsp::GotoDefinitionResponse>| {
1189+ let items = match response {
1190+ Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location],
1191+ Some(lsp::GotoDefinitionResponse::Array(locations)) => locations,
1192+ Some(lsp::GotoDefinitionResponse::Link(locations)) => locations
1193+ .into_iter()
1194+ .map(|location_link| lsp::Location {
1195+ uri: location_link.target_uri,
1196+ range: location_link.target_range,
1197+ })
1198+ .collect(),
1199+ None => Vec::new(),
1200+ };
1201+
1202+ _goto(editor, compositor, items, offset_encoding);
1203+ },
1204+ );
11891205}
11901206
11911207pub fn goto_type_definition(cx: &mut Context) {
@@ -1200,9 +1216,29 @@ pub fn goto_type_definition(cx: &mut Context) {
12001216 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
12011217
12021218 // TODO: handle fails
1203− let res =
1204− block_on(language_server.goto_type_definition(doc.identifier(), pos)).unwrap_or_default();
1205− _goto(cx, res, offset_encoding);
1219+ let future = language_server.goto_type_definition(doc.identifier(), pos);
1220+
1221+ cx.callback(
1222+ future,
1223+ move |editor: &mut Editor,
1224+ compositor: &mut Compositor,
1225+ response: Option<lsp::GotoDefinitionResponse>| {
1226+ let items = match response {
1227+ Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location],
1228+ Some(lsp::GotoDefinitionResponse::Array(locations)) => locations,
1229+ Some(lsp::GotoDefinitionResponse::Link(locations)) => locations
1230+ .into_iter()
1231+ .map(|location_link| lsp::Location {
1232+ uri: location_link.target_uri,
1233+ range: location_link.target_range,
1234+ })
1235+ .collect(),
1236+ None => Vec::new(),
1237+ };
1238+
1239+ _goto(editor, compositor, items, offset_encoding);
1240+ },
1241+ );
12061242}
12071243
12081244pub fn goto_implementation(cx: &mut Context) {
@@ -1217,9 +1253,29 @@ pub fn goto_implementation(cx: &mut Context) {
12171253 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
12181254
12191255 // TODO: handle fails
1220− let res =
1221− block_on(language_server.goto_implementation(doc.identifier(), pos)).unwrap_or_default();
1222− _goto(cx, res, offset_encoding);
1256+ let future = language_server.goto_implementation(doc.identifier(), pos);
1257+
1258+ cx.callback(
1259+ future,
1260+ move |editor: &mut Editor,
1261+ compositor: &mut Compositor,
1262+ response: Option<lsp::GotoDefinitionResponse>| {
1263+ let items = match response {
1264+ Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location],
1265+ Some(lsp::GotoDefinitionResponse::Array(locations)) => locations,
1266+ Some(lsp::GotoDefinitionResponse::Link(locations)) => locations
1267+ .into_iter()
1268+ .map(|location_link| lsp::Location {
1269+ uri: location_link.target_uri,
1270+ range: location_link.target_range,
1271+ })
1272+ .collect(),
1273+ None => Vec::new(),
1274+ };
1275+
1276+ _goto(editor, compositor, items, offset_encoding);
1277+ },
1278+ );
12231279}
12241280
12251281pub fn goto_reference(cx: &mut Context) {
@@ -1234,8 +1290,21 @@ pub fn goto_reference(cx: &mut Context) {
12341290 let pos = pos_to_lsp_pos(doc.text(), doc.selection(view.id).cursor(), offset_encoding);
12351291
12361292 // TODO: handle fails
1237− let res = block_on(language_server.goto_reference(doc.identifier(), pos)).unwrap_or_default();
1238− _goto(cx, res, offset_encoding);
1293+ let future = language_server.goto_reference(doc.identifier(), pos);
1294+
1295+ cx.callback(
1296+ future,
1297+ move |editor: &mut Editor,
1298+ compositor: &mut Compositor,
1299+ items: Option<Vec<lsp::Location>>| {
1300+ _goto(
1301+ editor,
1302+ compositor,
1303+ items.unwrap_or_default(),
1304+ offset_encoding,
1305+ );
1306+ },
1307+ );
12391308}
12401309
12411310pub fn signature_help(cx: &mut Context) {
@@ -1253,23 +1322,28 @@ pub fn signature_help(cx: &mut Context) {
12531322 );
12541323
12551324 // TODO: handle fails
1325+ let future = language_server.text_document_signature_help(doc.identifier(), pos);
12561326
1257− let res = block_on(language_server.text_document_signature_help(doc.identifier(), pos))
1258− .unwrap_or_default();
1259−
1260− if let Some(signature_help) = res {
1261− log::info!("{:?}", signature_help);
1262− // signatures
1263− // active_signature
1264− // active_parameter
1265− // render as:
1266−
1267− // signature
1268− // ----------
1269− // doc
1270−
1271− // with active param highlighted
1272− }
1327+ cx.callback(
1328+ future,
1329+ move |editor: &mut Editor,
1330+ compositor: &mut Compositor,
1331+ response: Option<lsp::SignatureHelp>| {
1332+ if let Some(signature_help) = response {
1333+ log::info!("{:?}", signature_help);
1334+ // signatures
1335+ // active_signature
1336+ // active_parameter
1337+ // render as:
1338+
1339+ // signature
1340+ // ----------
1341+ // doc
1342+
1343+ // with active param highlighted
1344+ }
1345+ },
1346+ );
12731347}
12741348
12751349// NOTE: Transactions in this module get appended to history when we switch back to normal mode.
@@ -1643,20 +1717,22 @@ pub fn format_selections(cx: &mut Context) {
16431717 };
16441718 // TODO: handle fails
16451719 // TODO: concurrent map
1646− let edits = block_on(language_server.text_document_range_formatting(
1647− doc.identifier(),
1648− range,
1649− lsp::FormattingOptions::default(),
1650− ))
1651− .unwrap_or_default();
1652−
1653− let transaction = helix_lsp::util::generate_transaction_from_edits(
1654− doc.text(),
1655− edits,
1656− language_server.offset_encoding(),
1657− );
1658−
1659− doc.apply(&transaction, view.id);
1720+ unimplemented!(); // neeed to block to get the formatting
1721+
1722+ // let edits = block_on(language_server.text_document_range_formatting(
1723+ // doc.identifier(),
1724+ // range,
1725+ // lsp::FormattingOptions::default(),
1726+ // ))
1727+ // .unwrap_or_default();
1728+
1729+ // let transaction = helix_lsp::util::generate_transaction_from_edits(
1730+ // doc.text(),
1731+ // edits,
1732+ // language_server.offset_encoding(),
1733+ // );
1734+
1735+ // doc.apply(&transaction, view.id);
16601736 }
16611737
16621738 doc.append_changes_to_history(view.id);
@@ -1734,7 +1810,7 @@ pub fn save(cx: &mut Context) {
17341810
17351811 // TODO: handle save errors somehow?
17361812 // TODO: don't block
1737− block_on(cx.doc().save());
1813+ tokio::spawn(cx.doc().save());
17381814}
17391815
17401816pub fn completion(cx: &mut Context) {
@@ -1847,30 +1923,34 @@ pub fn hover(cx: &mut Context) {
18471923 );
18481924
18491925 // TODO: handle fails
1850− let res =
1851− block_on(language_server.text_document_hover(doc.identifier(), pos)).unwrap_or_default();
1852−
1853− if let Some(hover) = res {
1854− // hover.contents / .range <- used for visualizing
1855− let contents = match hover.contents {
1856− lsp::HoverContents::Scalar(contents) => {
1857− // markedstring(string/languagestring to be highlighted)
1858− // TODO
1859− unimplemented!("{:?}", contents)
1860− }
1861− lsp::HoverContents::Array(contents) => {
1862− unimplemented!("{:?}", contents)
1863− }
1864− // TODO: render markdown
1865− lsp::HoverContents::Markup(contents) => contents.value,
1866− };
1926+ let future = language_server.text_document_hover(doc.identifier(), pos);
18671927
1868− // skip if contents empty
1928+ cx.callback(
1929+ future,
1930+ move |editor: &mut Editor, compositor: &mut Compositor, response: Option<lsp::Hover>| {
1931+ if let Some(hover) = response {
1932+ // hover.contents / .range <- used for visualizing
1933+ let contents = match hover.contents {
1934+ lsp::HoverContents::Scalar(contents) => {
1935+ // markedstring(string/languagestring to be highlighted)
1936+ // TODO
1937+ unimplemented!("{:?}", contents)
1938+ }
1939+ lsp::HoverContents::Array(contents) => {
1940+ unimplemented!("{:?}", contents)
1941+ }
1942+ // TODO: render markdown
1943+ lsp::HoverContents::Markup(contents) => contents.value,
1944+ };
18691945
1870− let contents = ui::Markdown::new(contents);
1871− let mut popup = Popup::new(contents);
1872− cx.push_layer(Box::new(popup));
1873− }
1946+ // skip if contents empty
1947+
1948+ let contents = ui::Markdown::new(contents);
1949+ let mut popup = Popup::new(contents);
1950+ compositor.push(Box::new(popup));
1951+ }
1952+ },
1953+ );
18741954}
18751955
18761956// view movements
@@ -1971,7 +2051,7 @@ pub fn space_mode(cx: &mut Context) {
19712051 'w' => {
19722052 // save current buffer
19732053 let doc = cx.doc();
1974− block_on(doc.save());
2054+ tokio::spawn(doc.save());
19752055 }
19762056 'c' => {
19772057 // close current split