From 841826d4991687ad725b1547e757ad1c4648d0b4 Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Fri, 4 Oct 2024 01:36:08 +0900 Subject: [PATCH] feat(els): magic completion --- crates/els/completion.rs | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/crates/els/completion.rs b/crates/els/completion.rs index 6f7472c3e..5e31a28d5 100644 --- a/crates/els/completion.rs +++ b/crates/els/completion.rs @@ -21,6 +21,7 @@ use erg_compiler::erg_parser::parse::Parsable; use erg_compiler::erg_parser::token::TokenKind; use erg_compiler::hir::Expr; use erg_compiler::module::SharedCompilerResource; +use erg_compiler::ty::constructors::{poly, ty_tp}; use erg_compiler::ty::{HasType, ParamTy, Type}; use erg_compiler::varinfo::{AbsLocation, Mutability, VarInfo, VarKind}; use TokenKind::*; @@ -639,6 +640,14 @@ impl Server { result.push(item); } } + } else if let Some(receiver_t) = &receiver_t { + result.extend(self.magic_completion_items( + &comp_kind, + receiver_t, + &uri, + pos, + &mod_ctx.context, + )?); } for (name, vi) in contexts.into_iter().flat_map(|ctx| ctx.local_dir()) { if comp_kind.should_be_method() && vi.vis.is_private() { @@ -712,6 +721,54 @@ impl Server { Ok(Some(CompletionResponse::Array(result))) } + fn magic_completion_items( + &self, + comp_kind: &CompletionKind, + receiver_t: &Type, + uri: &NormalizedUrl, + pos: Position, + ctx: &Context, + ) -> ELSResult> { + let mut items = vec![]; + // magic completion + // `expr.if` => `if expr, do:` + // `expr.for!` => `for! expr, i =>` + if comp_kind.should_be_method() { + let Some(receiver) = self.get_receiver(uri, pos)? else { + return Ok(items); + }; + let mut range = loc_to_range(receiver.loc()).unwrap(); + let s_receiver = self.file_cache.get_ranged(uri, range)?.unwrap_or_default(); + // receiver + `.` + range.end.character += 1; + let remove = TextEdit::new(range, "".into()); + if ctx.subtype_of(receiver_t, &Type::Bool) { + let mut item_if = + CompletionItem::new_simple("if".into(), "magic completion".into()); + item_if.insert_text = Some(format!("if {s_receiver}, do:")); + item_if.additional_text_edits = Some(vec![remove.clone()]); + items.push(item_if); + let mut item_if = + CompletionItem::new_simple("if!".into(), "magic completion".into()); + item_if.insert_text = Some(format!("if! {s_receiver}, do!:")); + item_if.additional_text_edits = Some(vec![remove.clone()]); + items.push(item_if); + let mut item_while = + CompletionItem::new_simple("while!".into(), "magic completion".into()); + item_while.insert_text = Some(format!("while! do! {s_receiver}, do!:")); + item_while.additional_text_edits = Some(vec![remove]); + items.push(item_while); + } else if ctx.subtype_of(receiver_t, &poly("Iterable", vec![ty_tp(Type::Obj)])) { + let mut item_for = + CompletionItem::new_simple("for!".into(), "magic completion".into()); + item_for.insert_text = Some(format!("for! {s_receiver}, i =>")); + item_for.additional_text_edits = Some(vec![remove]); + items.push(item_for); + } + } + Ok(items) + } + pub(crate) fn handle_resolve_completion( &mut self, mut item: CompletionItem,