Skip to content

Commit af3b6ec

Browse files
committed
feat(els): module hover link
1 parent 17b3fbc commit af3b6ec

File tree

5 files changed

+110
-13
lines changed

5 files changed

+110
-13
lines changed

crates/els/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ ELS is a language server for the [Erg](https://github.com/erg-lang/erg) programm
3030
- [x] Workspace symbol
3131
- [x] Document symbol
3232
- [x] Document highlight
33+
- [x] Document link
3334
- [x] Call hierarchy
3435
- [x] Folding range
3536
- [x] Folding imports

crates/els/hover.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ use erg_common::trim_eliminate_top_indent;
44
use erg_compiler::artifact::BuildRunnable;
55
use erg_compiler::erg_parser::parse::Parsable;
66
use erg_compiler::erg_parser::token::{Token, TokenCategory, TokenKind};
7+
use erg_compiler::hir::Expr;
8+
use erg_compiler::ty::HasType;
79
use erg_compiler::varinfo::{AbsLocation, VarInfo};
810

911
use lsp_types::{Hover, HoverContents, HoverParams, MarkedString, Url};
1012

13+
#[allow(unused)]
14+
use crate::_log;
1115
use crate::server::{ELSResult, RedirectableStdout, Server};
1216
use crate::util::{self, NormalizedUrl};
1317

@@ -175,6 +179,48 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
175179
}
176180
}
177181
}
182+
if let Some(visitor) = self.get_visitor(&uri) {
183+
let url = match visitor.get_min_expr(pos) {
184+
Some(Expr::Def(def)) => def
185+
.sig
186+
.ref_t()
187+
.module_path()
188+
.and_then(|path| Url::from_file_path(path).ok()),
189+
Some(Expr::Call(call)) => {
190+
call.call_signature_t().return_t().and_then(|ret_t| {
191+
ret_t
192+
.module_path()
193+
.and_then(|path| Url::from_file_path(path).ok())
194+
})
195+
}
196+
Some(expr) => expr
197+
.ref_t()
198+
.module_path()
199+
.or_else(|| {
200+
expr.ref_t()
201+
.inner_ts()
202+
.into_iter()
203+
.find_map(|t| t.module_path())
204+
})
205+
.and_then(|path| Url::from_file_path(path).ok()),
206+
_ => None,
207+
};
208+
if let Some(url) = url {
209+
let path = url.to_file_path().unwrap().with_extension("");
210+
let name = if path.ends_with("__init__") || path.ends_with("__init__.d") {
211+
path.parent()
212+
.unwrap()
213+
.file_stem()
214+
.unwrap()
215+
.to_string_lossy()
216+
} else {
217+
path.file_stem().unwrap().to_string_lossy()
218+
};
219+
contents.push(MarkedString::from_markdown(format!(
220+
"Go to [{name}]({url})",
221+
)));
222+
}
223+
}
178224
} else {
179225
self.send_log("lex error")?;
180226
}

crates/els/server.rs

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,16 @@ pub enum DefaultFeatures {
8787
Diagnostics,
8888
FindReferences,
8989
GotoDefinition,
90+
GotoTypeDefinition,
9091
Hover,
9192
InlayHint,
9293
Rename,
9394
SemanticTokens,
9495
SignatureHelp,
96+
DocumentHighlight,
97+
DocumentLink,
98+
FoldingRange,
99+
SelectionRange,
95100
/* ELS specific features */
96101
SmartCompletion,
97102
DeepCompletion,
@@ -116,9 +121,20 @@ impl From<&str> for DefaultFeatures {
116121
"gotodefinition" | "gotoDefinition" | "goto-definition" => {
117122
DefaultFeatures::GotoDefinition
118123
}
124+
"gototypedefinition" | "gotoTypeDefinition" | "goto-type-definition" => {
125+
DefaultFeatures::GotoTypeDefinition
126+
}
119127
"signaturehelp" | "signatureHelp" | "signature-help" | "code-signature" => {
120128
DefaultFeatures::SignatureHelp
121129
}
130+
"documenthighlight" | "documentHighlight" | "document-highlight" => {
131+
DefaultFeatures::DocumentHighlight
132+
}
133+
"documentlink" | "documentLink" | "document-link" => DefaultFeatures::DocumentLink,
134+
"foldingrange" | "foldingRange" | "folding-range" => DefaultFeatures::FoldingRange,
135+
"selectionrange" | "selectionRange" | "selection-range" => {
136+
DefaultFeatures::SelectionRange
137+
}
122138
"smartcompletion" | "smartCompletion" | "smart-completion" => {
123139
DefaultFeatures::SmartCompletion
124140
}
@@ -452,7 +468,14 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
452468
let mut comp_options = CompletionOptions::default();
453469
comp_options.trigger_characters = Some(TRIGGER_CHARS.map(String::from).to_vec());
454470
comp_options.resolve_provider = Some(true);
455-
capabilities.completion_provider = Some(comp_options);
471+
capabilities.completion_provider = if self
472+
.disabled_features
473+
.contains(&DefaultFeatures::Completion)
474+
{
475+
None
476+
} else {
477+
Some(comp_options)
478+
};
456479
capabilities.rename_provider = Some(OneOf::Left(true));
457480
capabilities.references_provider = Some(OneOf::Left(true));
458481
capabilities.definition_provider = Some(OneOf::Left(true));
@@ -530,20 +553,40 @@ impl<Checker: BuildRunnable, Parser: Parsable> Server<Checker, Parser> {
530553
work_done_progress: None,
531554
},
532555
});
533-
capabilities.code_lens_provider = Some(CodeLensOptions {
534-
resolve_provider: Some(false),
535-
});
556+
capabilities.code_lens_provider =
557+
if self.disabled_features.contains(&DefaultFeatures::CodeLens) {
558+
None
559+
} else {
560+
Some(CodeLensOptions {
561+
resolve_provider: Some(false),
562+
})
563+
};
536564
capabilities.workspace_symbol_provider = Some(OneOf::Left(true));
537565
capabilities.document_symbol_provider = Some(OneOf::Left(true));
538-
capabilities.document_link_provider = Some(DocumentLinkOptions {
539-
resolve_provider: Some(false),
540-
work_done_progress_options: Default::default(),
541-
});
566+
capabilities.document_link_provider = if self
567+
.disabled_features
568+
.contains(&DefaultFeatures::DocumentLink)
569+
{
570+
None
571+
} else {
572+
Some(DocumentLinkOptions {
573+
resolve_provider: Some(false),
574+
work_done_progress_options: Default::default(),
575+
})
576+
};
542577
capabilities.call_hierarchy_provider = Some(CallHierarchyServerCapability::Simple(true));
543-
capabilities.folding_range_provider = Some(FoldingRangeProviderCapability::Simple(true));
578+
capabilities.folding_range_provider = Some(FoldingRangeProviderCapability::Simple(
579+
self.disabled_features
580+
.contains(&DefaultFeatures::FoldingRange)
581+
.not(),
582+
));
544583
capabilities.selection_range_provider =
545584
Some(SelectionRangeProviderCapability::Simple(true));
546-
capabilities.document_highlight_provider = Some(OneOf::Left(true));
585+
capabilities.document_highlight_provider = Some(OneOf::Left(
586+
self.disabled_features
587+
.contains(&DefaultFeatures::DocumentHighlight)
588+
.not(),
589+
));
547590
capabilities
548591
}
549592

crates/erg_compiler/hir.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,10 +1517,16 @@ impl Call {
15171517
}
15181518
}
15191519

1520+
pub fn call_signature_t(&self) -> &Type {
1521+
if let Some(attr) = self.attr_name.as_ref() {
1522+
attr.ref_t()
1523+
} else {
1524+
self.obj.ref_t()
1525+
}
1526+
}
1527+
15201528
pub fn is_method_call(&self) -> bool {
1521-
self.signature_t()
1522-
.map(|t| t.self_t().is_some())
1523-
.unwrap_or(false)
1529+
self.call_signature_t().self_t().is_some()
15241530
}
15251531

15261532
pub fn additional_operation(&self) -> Option<OperationKind> {

crates/erg_compiler/ty/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,7 @@ impl HasType for Type {
18911891
)
18921892
.chain(sub.var_params.as_deref().map(|pt| pt.typ().clone()))
18931893
.chain(sub.non_default_params.iter().map(|pt| pt.typ().clone()))
1894+
.chain(sub.kw_var_params.as_deref().map(|pt| pt.typ().clone()))
18941895
.chain([*sub.return_t.clone()])
18951896
.collect(),
18961897
Self::Callable { param_ts, .. } => param_ts.clone(),

0 commit comments

Comments
 (0)