diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2021-12-15 13:23:43 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-15 13:23:43 -0500 |
commit | 6c324acf2363e88293ab94cf3de6c9d7a264b55d (patch) | |
tree | b0d7c8752bf7e7b471be4a50e65572d501bb8b5a /cli/tools/repl/mod.rs | |
parent | a1f0796fccfafee19b2fe06155efe746da2e9654 (diff) |
feat: REPL import specifier auto-completions (#13078)
Diffstat (limited to 'cli/tools/repl/mod.rs')
-rw-r--r-- | cli/tools/repl/mod.rs | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index 687e8a300..e971d0a7a 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -4,7 +4,10 @@ use crate::ast::transpile; use crate::ast::Diagnostics; use crate::ast::ImportsNotUsedAsValues; use crate::colors; +use crate::lsp::ReplLanguageServer; use crate::proc_state::ProcState; +use crate::tools::repl::channel::RustylineSyncMessage; +use crate::tools::repl::channel::RustylineSyncResponse; use deno_ast::swc::parser::error::SyntaxError; use deno_ast::swc::parser::token::Token; use deno_ast::swc::parser::token::Word; @@ -181,6 +184,15 @@ impl Completer for EditorHelper { pos: usize, _ctx: &Context<'_>, ) -> Result<(usize, Vec<String>), ReadlineError> { + let lsp_completions = self.sync_sender.lsp_completions(line, pos); + if !lsp_completions.is_empty() { + // assumes all lsp completions have the same start position + return Ok(( + lsp_completions[0].span.lo.0 as usize, + lsp_completions.into_iter().map(|c| c.new_text).collect(), + )); + } + let expr = get_expr_from_line_at_pos(line, pos); // check if the expression is in the form `obj.prop` @@ -428,14 +440,21 @@ impl std::fmt::Display for EvaluationOutput { } } +struct TsEvaluateResponse { + ts_code: String, + value: Value, +} + struct ReplSession { worker: MainWorker, session: LocalInspectorSession, pub context_id: u64, + language_server: ReplLanguageServer, } impl ReplSession { pub async fn initialize(mut worker: MainWorker) -> Result<Self, AnyError> { + let language_server = ReplLanguageServer::new_initialized().await?; let mut session = worker.create_inspector_session().await; worker @@ -467,6 +486,7 @@ impl ReplSession { worker, session, context_id, + language_server, }; // inject prelude @@ -520,13 +540,18 @@ impl ReplSession { match self.evaluate_line_with_object_wrapping(line).await { Ok(evaluate_response) => { - let evaluate_result = evaluate_response.get("result").unwrap(); + let evaluate_result = evaluate_response.value.get("result").unwrap(); let evaluate_exception_details = - evaluate_response.get("exceptionDetails"); + evaluate_response.value.get("exceptionDetails"); if evaluate_exception_details.is_some() { self.set_last_thrown_error(evaluate_result).await?; } else { + self + .language_server + .commit_text(&evaluate_response.ts_code) + .await; + self.set_last_eval_result(evaluate_result).await?; } @@ -561,7 +586,7 @@ impl ReplSession { async fn evaluate_line_with_object_wrapping( &mut self, line: &str, - ) -> Result<Value, AnyError> { + ) -> Result<TsEvaluateResponse, AnyError> { // Expressions like { "foo": "bar" } are interpreted as block expressions at the // statement level rather than an object literal so we interpret it as an expression statement // to match the behavior found in a typical prompt including browser developer tools. @@ -582,6 +607,7 @@ impl ReplSession { || evaluate_response .as_ref() .unwrap() + .value .get("exceptionDetails") .is_some()) { @@ -658,7 +684,7 @@ impl ReplSession { async fn evaluate_ts_expression( &mut self, expression: &str, - ) -> Result<Value, AnyError> { + ) -> Result<TsEvaluateResponse, AnyError> { let parsed_module = deno_ast::parse_module(deno_ast::ParseParams { specifier: "repl.ts".to_string(), source: deno_ast::SourceTextInfo::from_string(expression.to_string()), @@ -688,12 +714,17 @@ impl ReplSession { )? .0; - self + let value = self .evaluate_expression(&format!( "'use strict'; void 0;\n{}", transpiled_src )) - .await + .await?; + + Ok(TsEvaluateResponse { + ts_code: expression.to_string(), + value, + }) } async fn evaluate_expression( @@ -727,11 +758,24 @@ async fn read_line_and_poll( return result.unwrap(); } result = message_handler.recv() => { - if let Some((method, params)) = result { - let result = repl_session - .post_message_with_event_loop(&method, params) - .await; - message_handler.send(result).unwrap(); + match result { + Some(RustylineSyncMessage::PostMessage { + method, + params + }) => { + let result = repl_session + .post_message_with_event_loop(&method, params) + .await; + message_handler.send(RustylineSyncResponse::PostMessage(result)).unwrap(); + }, + Some(RustylineSyncMessage::LspCompletions { + line_text, + position, + }) => { + let result = repl_session.language_server.completions(&line_text, position).await; + message_handler.send(RustylineSyncResponse::LspCompletions(result)).unwrap(); + } + None => {}, // channel closed } poll_worker = true; |