mirror of
https://github.com/erg-lang/erg.git
synced 2025-08-03 10:23:20 +00:00
feat(els): support inlay hint resolve
This commit is contained in:
parent
a292d2e3d7
commit
efbad81475
5 changed files with 200 additions and 107 deletions
|
@ -5,13 +5,13 @@ use erg_compiler::erg_parser::parse::Parsable;
|
|||
|
||||
use lsp_types::request::{
|
||||
CodeActionRequest, CodeActionResolveRequest, CodeLensRequest, Completion, ExecuteCommand,
|
||||
GotoDefinition, HoverRequest, InlayHintRequest, References, ResolveCompletionItem,
|
||||
SemanticTokensFullRequest, SignatureHelpRequest, WillRenameFiles,
|
||||
GotoDefinition, HoverRequest, InlayHintRequest, InlayHintResolveRequest, References,
|
||||
ResolveCompletionItem, SemanticTokensFullRequest, SignatureHelpRequest, WillRenameFiles,
|
||||
};
|
||||
use lsp_types::{
|
||||
CodeAction, CodeActionParams, CodeLensParams, CompletionItem, CompletionParams,
|
||||
ExecuteCommandParams, GotoDefinitionParams, HoverParams, InlayHintParams, ReferenceParams,
|
||||
RenameFilesParams, SemanticTokensParams, SignatureHelpParams,
|
||||
ExecuteCommandParams, GotoDefinitionParams, HoverParams, InlayHint, InlayHintParams,
|
||||
ReferenceParams, RenameFilesParams, SemanticTokensParams, SignatureHelpParams,
|
||||
};
|
||||
|
||||
use crate::server::Server;
|
||||
|
@ -23,6 +23,7 @@ pub struct SendChannels {
|
|||
goto_definition: mpsc::Sender<(i64, GotoDefinitionParams)>,
|
||||
semantic_tokens_full: mpsc::Sender<(i64, SemanticTokensParams)>,
|
||||
inlay_hint: mpsc::Sender<(i64, InlayHintParams)>,
|
||||
inlay_hint_resolve: mpsc::Sender<(i64, InlayHint)>,
|
||||
hover: mpsc::Sender<(i64, HoverParams)>,
|
||||
references: mpsc::Sender<(i64, ReferenceParams)>,
|
||||
code_lens: mpsc::Sender<(i64, CodeLensParams)>,
|
||||
|
@ -40,6 +41,7 @@ impl SendChannels {
|
|||
let (tx_goto_definition, rx_goto_definition) = mpsc::channel();
|
||||
let (tx_semantic_tokens_full, rx_semantic_tokens_full) = mpsc::channel();
|
||||
let (tx_inlay_hint, rx_inlay_hint) = mpsc::channel();
|
||||
let (tx_inlay_hint_resolve, rx_inlay_hint_resolve) = mpsc::channel();
|
||||
let (tx_hover, rx_hover) = mpsc::channel();
|
||||
let (tx_references, rx_references) = mpsc::channel();
|
||||
let (tx_code_lens, rx_code_lens) = mpsc::channel();
|
||||
|
@ -55,6 +57,7 @@ impl SendChannels {
|
|||
goto_definition: tx_goto_definition,
|
||||
semantic_tokens_full: tx_semantic_tokens_full,
|
||||
inlay_hint: tx_inlay_hint,
|
||||
inlay_hint_resolve: tx_inlay_hint_resolve,
|
||||
hover: tx_hover,
|
||||
references: tx_references,
|
||||
code_lens: tx_code_lens,
|
||||
|
@ -70,6 +73,7 @@ impl SendChannels {
|
|||
goto_definition: rx_goto_definition,
|
||||
semantic_tokens_full: rx_semantic_tokens_full,
|
||||
inlay_hint: rx_inlay_hint,
|
||||
inlay_hint_resolve: rx_inlay_hint_resolve,
|
||||
hover: rx_hover,
|
||||
references: rx_references,
|
||||
code_lens: rx_code_lens,
|
||||
|
@ -90,6 +94,7 @@ pub struct ReceiveChannels {
|
|||
pub(crate) goto_definition: mpsc::Receiver<(i64, GotoDefinitionParams)>,
|
||||
pub(crate) semantic_tokens_full: mpsc::Receiver<(i64, SemanticTokensParams)>,
|
||||
pub(crate) inlay_hint: mpsc::Receiver<(i64, InlayHintParams)>,
|
||||
pub(crate) inlay_hint_resolve: mpsc::Receiver<(i64, InlayHint)>,
|
||||
pub(crate) hover: mpsc::Receiver<(i64, HoverParams)>,
|
||||
pub(crate) references: mpsc::Receiver<(i64, ReferenceParams)>,
|
||||
pub(crate) code_lens: mpsc::Receiver<(i64, CodeLensParams)>,
|
||||
|
@ -130,6 +135,7 @@ impl_sendable!(
|
|||
semantic_tokens_full
|
||||
);
|
||||
impl_sendable!(InlayHintRequest, InlayHintParams, inlay_hint);
|
||||
impl_sendable!(InlayHintResolveRequest, InlayHint, inlay_hint_resolve);
|
||||
impl_sendable!(HoverRequest, HoverParams, hover);
|
||||
impl_sendable!(References, ReferenceParams, references);
|
||||
impl_sendable!(CodeLensRequest, CodeLensParams, code_lens);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#![allow(unused_imports)]
|
||||
|
||||
use erg_compiler::erg_parser::parse::Parsable;
|
||||
use erg_compiler::varinfo::AbsLocation;
|
||||
use lsp_types::InlayHintLabelPart;
|
||||
use serde::Deserialize;
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
|
@ -12,97 +14,99 @@ use erg_common::traits::{Locational, Runnable, Stream};
|
|||
use erg_compiler::artifact::{BuildRunnable, IncompleteArtifact};
|
||||
use erg_compiler::hir::{Block, Call, ClassDef, Def, Expr, Lambda, Params, PatchDef, Signature};
|
||||
use erg_compiler::ty::HasType;
|
||||
use lsp_types::{InlayHint, InlayHintKind, InlayHintLabel, InlayHintParams, Position};
|
||||
use lsp_types::{
|
||||
InlayHint, InlayHintKind, InlayHintLabel, InlayHintParams, InlayHintTooltip, Position,
|
||||
};
|
||||
|
||||
use crate::_log;
|
||||
use crate::server::{send, send_log, ELSResult, Server};
|
||||
use crate::util::abs_loc_to_lsp_loc;
|
||||
use crate::util::{self, loc_to_range, NormalizedUrl};
|
||||
|
||||
fn anot(ln: u32, col: u32, cont: String) -> InlayHint {
|
||||
let position = Position::new(ln - 1, col);
|
||||
let label = InlayHintLabel::String(cont);
|
||||
let kind = Some(InlayHintKind::TYPE);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(false),
|
||||
padding_right: Some(false),
|
||||
data: None,
|
||||
}
|
||||
pub struct InlayHintGenerator<'s, C: BuildRunnable, P: Parsable> {
|
||||
_server: &'s Server<C, P>,
|
||||
uri: Value,
|
||||
}
|
||||
|
||||
fn type_anot<D: std::fmt::Display>(ln_end: u32, col_end: u32, ty: D, return_t: bool) -> InlayHint {
|
||||
let position = Position::new(ln_end - 1, col_end);
|
||||
let string = if return_t {
|
||||
format!("): {ty}")
|
||||
} else {
|
||||
format!(": {ty}")
|
||||
};
|
||||
let label = InlayHintLabel::String(string);
|
||||
let kind = Some(InlayHintKind::TYPE);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(return_t),
|
||||
padding_right: Some(false),
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn type_bounds_anot(ln_end: u32, col_end: u32, ty_bounds: String) -> InlayHint {
|
||||
let position = Position::new(ln_end - 1, col_end);
|
||||
let label = InlayHintLabel::String(ty_bounds);
|
||||
let kind = Some(InlayHintKind::TYPE);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(false),
|
||||
padding_right: Some(false),
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn param_anot<D: std::fmt::Display>(ln_begin: u32, col_begin: u32, name: D) -> InlayHint {
|
||||
let position = Position::new(ln_begin - 1, col_begin);
|
||||
let label = InlayHintLabel::String(format!("{name}:= "));
|
||||
let kind = Some(InlayHintKind::PARAMETER);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(false),
|
||||
padding_right: Some(false),
|
||||
data: None,
|
||||
}
|
||||
}
|
||||
|
||||
impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
||||
pub(crate) fn handle_inlay_hint(
|
||||
&mut self,
|
||||
params: InlayHintParams,
|
||||
) -> ELSResult<Option<Vec<InlayHint>>> {
|
||||
send_log(format!("inlay hint request: {params:?}"))?;
|
||||
let uri = NormalizedUrl::new(params.text_document.uri);
|
||||
let mut result = vec![];
|
||||
if let Some(IncompleteArtifact {
|
||||
object: Some(hir), ..
|
||||
}) = self.analysis_result.get_artifact(&uri).as_deref()
|
||||
{
|
||||
for chunk in hir.module.iter() {
|
||||
result.extend(self.get_expr_hint(chunk));
|
||||
}
|
||||
impl<'s, C: BuildRunnable, P: Parsable> InlayHintGenerator<'s, C, P> {
|
||||
fn anot(&self, ln: u32, col: u32, cont: String) -> InlayHint {
|
||||
let position = Position::new(ln - 1, col);
|
||||
let label = InlayHintLabel::String(cont);
|
||||
let kind = Some(InlayHintKind::TYPE);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(false),
|
||||
padding_right: Some(false),
|
||||
data: Some(self.uri.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_anot<D: std::fmt::Display>(
|
||||
&self,
|
||||
ln_end: u32,
|
||||
col_end: u32,
|
||||
ty: D,
|
||||
return_t: bool,
|
||||
) -> InlayHint {
|
||||
let position = Position::new(ln_end - 1, col_end);
|
||||
let string = if return_t {
|
||||
format!("): {ty}")
|
||||
} else {
|
||||
format!(": {ty}")
|
||||
};
|
||||
let label = InlayHintLabel::String(string);
|
||||
let kind = Some(InlayHintKind::TYPE);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(return_t),
|
||||
padding_right: Some(false),
|
||||
data: Some(self.uri.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn type_bounds_anot(&self, ln_end: u32, col_end: u32, ty_bounds: String) -> InlayHint {
|
||||
let position = Position::new(ln_end - 1, col_end);
|
||||
let label = InlayHintLabel::String(ty_bounds);
|
||||
let kind = Some(InlayHintKind::TYPE);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(false),
|
||||
padding_right: Some(false),
|
||||
data: Some(self.uri.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn param_anot<D: std::fmt::Display>(
|
||||
&self,
|
||||
ln_begin: u32,
|
||||
col_begin: u32,
|
||||
name: D,
|
||||
) -> InlayHint {
|
||||
let position = Position::new(ln_begin - 1, col_begin);
|
||||
let label = InlayHintLabel::String(format!("{name}:= "));
|
||||
let kind = Some(InlayHintKind::PARAMETER);
|
||||
InlayHint {
|
||||
position,
|
||||
label,
|
||||
kind,
|
||||
text_edits: None,
|
||||
tooltip: None,
|
||||
padding_left: Some(false),
|
||||
padding_right: Some(false),
|
||||
data: Some(self.uri.clone()),
|
||||
}
|
||||
Ok(Some(result))
|
||||
}
|
||||
|
||||
fn get_expr_hint(&self, expr: &Expr) -> Vec<InlayHint> {
|
||||
|
@ -126,7 +130,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
let (Some(ln_end), Some(col_end)) = (nd_param.ln_end(), nd_param.col_end()) else {
|
||||
continue;
|
||||
};
|
||||
let hint = type_anot(ln_end, col_end, &nd_param.vi.t, false);
|
||||
let hint = self.type_anot(ln_end, col_end, &nd_param.vi.t, false);
|
||||
result.push(hint);
|
||||
}
|
||||
if let Some(var_params) = ¶ms.var_params {
|
||||
|
@ -134,7 +138,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
return result;
|
||||
}
|
||||
if let (Some(ln_end), Some(col_end)) = (var_params.ln_end(), var_params.col_end()) {
|
||||
let hint = type_anot(ln_end, col_end, &var_params.vi.t, false);
|
||||
let hint = self.type_anot(ln_end, col_end, &var_params.vi.t, false);
|
||||
result.push(hint);
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +149,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
let (Some(ln_end), Some(col_end)) = (d_param.sig.ln_end(), d_param.sig.col_end()) else {
|
||||
continue;
|
||||
};
|
||||
let hint = type_anot(ln_end, col_end, &d_param.sig.vi.t, false);
|
||||
let hint = self.type_anot(ln_end, col_end, &d_param.sig.vi.t, false);
|
||||
result.push(hint);
|
||||
}
|
||||
result
|
||||
|
@ -160,7 +164,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
let ty_bounds = format!("|{}|", subr.split('|').nth(1).unwrap_or(""));
|
||||
let ident = def.sig.ident();
|
||||
if let Some((ln, col)) = ident.ln_end().zip(ident.col_end()) {
|
||||
let hint = type_bounds_anot(ln, col, ty_bounds);
|
||||
let hint = self.type_bounds_anot(ln, col, ty_bounds);
|
||||
result.push(hint);
|
||||
}
|
||||
}
|
||||
|
@ -170,12 +174,12 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
return result;
|
||||
};
|
||||
if let Some((ln, col)) = def.sig.ln_end().zip(def.sig.col_end()) {
|
||||
let hint = type_anot(ln, col, return_t, subr.params.parens.is_none());
|
||||
let hint = self.type_anot(ln, col, return_t, subr.params.parens.is_none());
|
||||
result.push(hint);
|
||||
}
|
||||
if subr.params.parens.is_none() {
|
||||
if let Some((ln, col)) = subr.params.ln_begin().zip(subr.params.col_begin()) {
|
||||
let hint = anot(ln, col, "(".to_string());
|
||||
let hint = self.anot(ln, col, "(".to_string());
|
||||
result.push(hint);
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +192,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
// don't show hints for compiler internal variables
|
||||
if def.sig.t_spec().is_none() && !def.sig.ident().inspect().starts_with(['%']) {
|
||||
if let Some((ln, col)) = def.sig.ln_begin().zip(def.sig.col_end()) {
|
||||
let hint = type_anot(ln, col, def.sig.ident().ref_t(), false);
|
||||
let hint = self.type_anot(ln, col, def.sig.ident().ref_t(), false);
|
||||
result.push(hint);
|
||||
}
|
||||
}
|
||||
|
@ -201,7 +205,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
result.extend(self.get_param_hint(&lambda.params));
|
||||
if lambda.params.parens.is_none() {
|
||||
if let Some((ln, col)) = lambda.params.ln_begin().zip(lambda.params.col_begin()) {
|
||||
let hint = anot(ln, col, "(".to_string());
|
||||
let hint = self.anot(ln, col, "(".to_string());
|
||||
result.push(hint);
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +215,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
.zip(lambda.params.col_end())
|
||||
.zip(lambda.ref_t().return_t())
|
||||
{
|
||||
let hint = type_anot(ln, col, return_t, lambda.params.parens.is_none());
|
||||
let hint = self.type_anot(ln, col, return_t, lambda.params.parens.is_none());
|
||||
result.push(hint);
|
||||
}
|
||||
result
|
||||
|
@ -266,7 +270,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
} else {
|
||||
(name.to_string(), col_begin)
|
||||
};
|
||||
let hint = param_anot(ln_begin, col_begin, name);
|
||||
let hint = self.param_anot(ln_begin, col_begin, name);
|
||||
result.push(hint);
|
||||
}
|
||||
}
|
||||
|
@ -280,3 +284,56 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
||||
pub(crate) fn handle_inlay_hint(
|
||||
&mut self,
|
||||
params: InlayHintParams,
|
||||
) -> ELSResult<Option<Vec<InlayHint>>> {
|
||||
send_log(format!("inlay hint request: {params:?}"))?;
|
||||
let uri = NormalizedUrl::new(params.text_document.uri);
|
||||
let mut result = vec![];
|
||||
let gen = InlayHintGenerator {
|
||||
_server: self,
|
||||
uri: uri.clone().raw().to_string().into(),
|
||||
};
|
||||
if let Some(IncompleteArtifact {
|
||||
object: Some(hir), ..
|
||||
}) = self.analysis_result.get_artifact(&uri).as_deref()
|
||||
{
|
||||
for chunk in hir.module.iter() {
|
||||
result.extend(gen.get_expr_hint(chunk));
|
||||
}
|
||||
}
|
||||
Ok(Some(result))
|
||||
}
|
||||
|
||||
pub(crate) fn handle_inlay_hint_resolve(
|
||||
&mut self,
|
||||
mut hint: InlayHint,
|
||||
) -> ELSResult<InlayHint> {
|
||||
send_log(format!("inlay hint resolve request: {hint:?}"))?;
|
||||
if let Some(data) = &hint.data {
|
||||
let Ok(uri) = data.as_str().unwrap().parse::<NormalizedUrl>() else {
|
||||
return Ok(hint);
|
||||
};
|
||||
if let Some(module) = self.modules.get(&uri) {
|
||||
let InlayHintLabel::String(label) = &hint.label else {
|
||||
return Ok(hint);
|
||||
};
|
||||
let name = label.trim_start_matches("): ").trim_start_matches(": ");
|
||||
if let Some((_, vi)) = module.context.get_type_info_by_str(name) {
|
||||
let location = abs_loc_to_lsp_loc(&vi.def_loc);
|
||||
let parts = InlayHintLabelPart {
|
||||
value: label.clone(),
|
||||
tooltip: None,
|
||||
location,
|
||||
command: None,
|
||||
};
|
||||
hint.label = InlayHintLabel::LabelParts(vec![parts]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(hint)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,16 +27,17 @@ use erg_compiler::ty::HasType;
|
|||
|
||||
use lsp_types::request::{
|
||||
CodeActionRequest, CodeActionResolveRequest, CodeLensRequest, Completion, ExecuteCommand,
|
||||
GotoDefinition, HoverRequest, InlayHintRequest, References, Rename, Request,
|
||||
ResolveCompletionItem, SemanticTokensFullRequest, SignatureHelpRequest, WillRenameFiles,
|
||||
GotoDefinition, HoverRequest, InlayHintRequest, InlayHintResolveRequest, References, Rename,
|
||||
Request, ResolveCompletionItem, SemanticTokensFullRequest, SignatureHelpRequest,
|
||||
WillRenameFiles,
|
||||
};
|
||||
use lsp_types::{
|
||||
ClientCapabilities, CodeActionKind, CodeActionOptions, CodeActionProviderCapability,
|
||||
CodeLensOptions, CompletionOptions, DidChangeTextDocumentParams, DidOpenTextDocumentParams,
|
||||
ExecuteCommandOptions, HoverProviderCapability, InitializeResult, OneOf, Position,
|
||||
SemanticTokenType, SemanticTokensFullOptions, SemanticTokensLegend, SemanticTokensOptions,
|
||||
SemanticTokensServerCapabilities, ServerCapabilities, SignatureHelpOptions,
|
||||
WorkDoneProgressOptions,
|
||||
ExecuteCommandOptions, HoverProviderCapability, InitializeResult, InlayHintOptions,
|
||||
InlayHintServerCapabilities, OneOf, Position, SemanticTokenType, SemanticTokensFullOptions,
|
||||
SemanticTokensLegend, SemanticTokensOptions, SemanticTokensServerCapabilities,
|
||||
ServerCapabilities, SignatureHelpOptions, WorkDoneProgressOptions,
|
||||
};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -421,7 +422,12 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
.disabled_features
|
||||
.contains(&DefaultFeatures::InlayHint)
|
||||
.not()
|
||||
.then_some(OneOf::Left(true));
|
||||
.then_some(OneOf::Right(InlayHintServerCapabilities::Options(
|
||||
InlayHintOptions {
|
||||
resolve_provider: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
)));
|
||||
let mut sema_options = SemanticTokensOptions::default();
|
||||
sema_options.range = Some(false);
|
||||
sema_options.full = Some(SemanticTokensFullOptions::Bool(true));
|
||||
|
@ -506,6 +512,10 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
Self::handle_semantic_tokens_full,
|
||||
);
|
||||
self.start_service::<InlayHintRequest>(receivers.inlay_hint, Self::handle_inlay_hint);
|
||||
self.start_service::<InlayHintResolveRequest>(
|
||||
receivers.inlay_hint_resolve,
|
||||
Self::handle_inlay_hint_resolve,
|
||||
);
|
||||
self.start_service::<HoverRequest>(receivers.hover, Self::handle_hover);
|
||||
self.start_service::<References>(receivers.references, Self::handle_references);
|
||||
self.start_service::<CodeLensRequest>(receivers.code_lens, Self::handle_code_lens);
|
||||
|
@ -669,6 +679,7 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
|
|||
self.parse_send::<SemanticTokensFullRequest>(id, msg)
|
||||
}
|
||||
InlayHintRequest::METHOD => self.parse_send::<InlayHintRequest>(id, msg),
|
||||
InlayHintResolveRequest::METHOD => self.parse_send::<InlayHintResolveRequest>(id, msg),
|
||||
CodeActionRequest::METHOD => self.parse_send::<CodeActionRequest>(id, msg),
|
||||
CodeActionResolveRequest::METHOD => {
|
||||
self.parse_send::<CodeActionResolveRequest>(id, msg)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::fmt;
|
||||
use std::fs::{metadata, Metadata};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::str::FromStr;
|
||||
|
||||
use erg_common::consts::CASE_SENSITIVE;
|
||||
use erg_common::normalize_path;
|
||||
|
@ -8,6 +9,7 @@ use erg_common::traits::{DequeStream, Locational};
|
|||
|
||||
use erg_compiler::erg_parser::token::{Token, TokenStream};
|
||||
|
||||
use erg_compiler::varinfo::AbsLocation;
|
||||
use lsp_types::{Position, Range, Url};
|
||||
|
||||
use crate::server::ELSResult;
|
||||
|
@ -22,6 +24,13 @@ impl fmt::Display for NormalizedUrl {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromStr for NormalizedUrl {
|
||||
type Err = Box<dyn std::error::Error>;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
NormalizedUrl::parse(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Deref for NormalizedUrl {
|
||||
type Target = Url;
|
||||
|
||||
|
@ -156,3 +165,9 @@ pub(crate) fn uri_to_path(uri: &NormalizedUrl) -> PathBuf {
|
|||
pub(crate) fn denormalize(uri: Url) -> Url {
|
||||
Url::parse(&uri.as_str().replace("c:", "file:///c%3A")).unwrap()
|
||||
}
|
||||
|
||||
pub(crate) fn abs_loc_to_lsp_loc(loc: &AbsLocation) -> Option<lsp_types::Location> {
|
||||
let uri = Url::from_file_path(loc.module.as_ref()?).ok()?;
|
||||
let range = loc_to_range(loc.loc)?;
|
||||
Some(lsp_types::Location::new(uri, range))
|
||||
}
|
||||
|
|
|
@ -2671,7 +2671,7 @@ impl Context {
|
|||
pub(crate) fn get_namespace(&self, namespace: &Str) -> Option<&Context> {
|
||||
if &namespace[..] == "global" {
|
||||
return self.get_builtins();
|
||||
} else if &namespace[..] == "module" {
|
||||
} else if &namespace[..] == "module" || namespace.is_empty() {
|
||||
return self.get_module();
|
||||
}
|
||||
self.get_mod_with_path(self.get_namespace_path(namespace)?.as_path())
|
||||
|
@ -2777,7 +2777,7 @@ impl Context {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_type(&self, name: &Str) -> Option<(&Type, &Context)> {
|
||||
pub(crate) fn get_type(&self, name: &str) -> Option<(&Type, &Context)> {
|
||||
if let Some((t, ctx)) = self.rec_local_get_type(name) {
|
||||
return Some((t, ctx));
|
||||
}
|
||||
|
@ -2795,6 +2795,10 @@ impl Context {
|
|||
None
|
||||
}
|
||||
|
||||
pub fn get_type_info_by_str(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
|
||||
self.get_type(name).and_then(|(t, _)| self.get_type_info(t))
|
||||
}
|
||||
|
||||
/// you should use `get_type` instead of this
|
||||
pub(crate) fn rec_local_get_type(&self, name: &str) -> Option<(&Type, &Context)> {
|
||||
#[cfg(feature = "py_compat")]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue