mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-04 18:58:30 +00:00
feat(pylyzer): pseudo-method completion
This commit is contained in:
parent
1954d27a63
commit
3f61bc5c17
3 changed files with 53 additions and 5 deletions
|
@ -1,6 +1,5 @@
|
|||
use std::path::Path;
|
||||
|
||||
use lsp_types::CompletionResponse;
|
||||
use serde_json::Value;
|
||||
|
||||
use erg_common::config::ErgConfig;
|
||||
|
@ -27,13 +26,13 @@ use erg_compiler::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
|
|||
use TokenKind::*;
|
||||
|
||||
use lsp_types::{
|
||||
CompletionItem, CompletionItemKind, CompletionParams, Documentation, MarkedString,
|
||||
MarkupContent, MarkupKind, Position, Range, TextEdit,
|
||||
CompletionItem, CompletionItemKind, CompletionParams, CompletionResponse, Documentation,
|
||||
MarkedString, MarkupContent, MarkupKind, Position, Range, TextEdit,
|
||||
};
|
||||
|
||||
use crate::_log;
|
||||
use crate::server::{ELSResult, Flags, RedirectableStdout, Server};
|
||||
use crate::util::{self, loc_to_pos, NormalizedUrl};
|
||||
use crate::util::{self, loc_to_pos, loc_to_range, NormalizedUrl};
|
||||
|
||||
fn comp_item_kind(t: &Type, muty: Mutability) -> CompletionItemKind {
|
||||
match t {
|
||||
|
@ -682,6 +681,20 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
.set(&mut item);
|
||||
item.kind = Some(comp_item_kind(&vi.t, vi.muty));
|
||||
item.data = Some(Value::String(vi.def_loc.to_string()));
|
||||
// s.`Function::map` => map(s)
|
||||
if comp_kind.should_be_method() && item.label.starts_with("Function::") {
|
||||
let receiver = self.get_receiver(&uri, pos)?;
|
||||
if let Some(mut range) = receiver.as_ref().and_then(|expr| loc_to_range(expr.loc()))
|
||||
{
|
||||
// FIXME:
|
||||
let s_receiver = self.file_cache.get_ranged(&uri, range)?.unwrap_or_default();
|
||||
range.end.character += 1;
|
||||
let name = item.label.trim_start_matches("Function::");
|
||||
let remove = TextEdit::new(range, "".to_string());
|
||||
item.insert_text = Some(format!("{name}({s_receiver})"));
|
||||
item.additional_text_edits = Some(vec![remove]);
|
||||
}
|
||||
}
|
||||
already_appeared.insert(item.label.clone());
|
||||
result.push(item);
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ use erg_compiler::context::{Context, ModuleContext};
|
|||
use erg_compiler::erg_parser::ast::Module;
|
||||
use erg_compiler::erg_parser::parse::{Parsable, SimpleParser};
|
||||
use erg_compiler::error::CompileWarning;
|
||||
use erg_compiler::hir::HIR;
|
||||
use erg_compiler::hir::{Expr, HIR};
|
||||
use erg_compiler::lower::ASTLowerer;
|
||||
use erg_compiler::module::{IRs, ModuleEntry, SharedCompilerResource};
|
||||
use erg_compiler::ty::{HasType, Type};
|
||||
|
@ -1096,6 +1096,32 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
ctxs
|
||||
}
|
||||
|
||||
pub(crate) fn get_receiver(
|
||||
&self,
|
||||
uri: &NormalizedUrl,
|
||||
attr_marker_pos: Position,
|
||||
) -> ELSResult<Option<Expr>> {
|
||||
let maybe_token = self.file_cache.get_receiver(uri, attr_marker_pos);
|
||||
if let Some(token) = maybe_token {
|
||||
let expr = if let Some(visitor) = self.get_visitor(uri) {
|
||||
if let Some(expr) =
|
||||
loc_to_pos(token.loc()).and_then(|pos| visitor.get_min_expr(pos).cloned())
|
||||
{
|
||||
Some(expr)
|
||||
} else {
|
||||
_log!(self, "expr not found: {token}");
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(expr)
|
||||
} else {
|
||||
self.send_log("token not found")?;
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_receiver_and_ctxs(
|
||||
&self,
|
||||
uri: &NormalizedUrl,
|
||||
|
|
|
@ -91,6 +91,15 @@ pub(crate) fn loc_to_range(loc: erg_common::error::Location) -> Option<Range> {
|
|||
Some(Range::new(start, end))
|
||||
}
|
||||
|
||||
pub(crate) fn _range_to_loc(range: Range) -> erg_common::error::Location {
|
||||
erg_common::error::Location::range(
|
||||
range.start.line + 1,
|
||||
range.start.character,
|
||||
range.end.line + 1,
|
||||
range.end.character,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn loc_to_pos(loc: erg_common::error::Location) -> Option<Position> {
|
||||
// FIXME: should `Position::new(loc.ln_begin()? - 1, loc.col_begin()?)`
|
||||
// but completion doesn't work (because the newline will be included)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue