Skip to content

Commit 4b39f83

Browse files
committed
completion: add @namespace @using
1 parent 8e6e437 commit 4b39f83

File tree

4 files changed

+127
-1
lines changed

4 files changed

+127
-1
lines changed

crates/emmylua_code_analysis/src/db_index/type/mod.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,15 @@ impl LuaTypeIndex {
207207
self.full_name_type_map.values().collect()
208208
}
209209

210+
pub fn get_file_namespaces(&self) -> Vec<String> {
211+
self.file_namespace
212+
.values()
213+
.cloned()
214+
.collect::<HashSet<_>>()
215+
.into_iter()
216+
.collect()
217+
}
218+
210219
pub fn get_type_decl_mut(&mut self, decl_id: &LuaTypeDeclId) -> Option<&mut LuaTypeDecl> {
211220
self.full_name_type_map.get_mut(decl_id)
212221
}

crates/emmylua_ls/src/handlers/completion/providers/doc_name_token_provider.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ pub fn add_completion(builder: &mut CompletionBuilder) -> Option<()> {
3232
DocCompletionExpected::ClassAttr => {
3333
add_tag_class_attr_completion(builder);
3434
}
35+
DocCompletionExpected::Namespace => {
36+
add_tag_namespace_completion(builder);
37+
}
38+
DocCompletionExpected::Using => {
39+
add_tag_using_completion(builder);
40+
}
3541
}
3642

3743
builder.stop_here();
@@ -66,6 +72,8 @@ fn get_doc_completion_expected(trigger_token: &LuaSyntaxToken) -> Option<DocComp
6672
_ => None,
6773
}
6874
}
75+
LuaTokenKind::TkTagNamespace => Some(DocCompletionExpected::Namespace),
76+
LuaTokenKind::TkTagUsing => Some(DocCompletionExpected::Using),
6977
LuaTokenKind::TkComma => {
7078
let parent = left_token.parent()?;
7179
match parent.kind().into() {
@@ -112,6 +120,8 @@ enum DocCompletionExpected {
112120
DiagnosticAction,
113121
DiagnosticCode,
114122
ClassAttr,
123+
Namespace,
124+
Using,
115125
}
116126

117127
fn add_tag_param_name_completion(builder: &mut CompletionBuilder) -> Option<()> {
@@ -253,3 +263,46 @@ fn add_tag_class_attr_completion(builder: &mut CompletionBuilder) {
253263
builder.add_completion_item(completion_item);
254264
}
255265
}
266+
267+
fn add_tag_namespace_completion(builder: &mut CompletionBuilder) {
268+
let type_index = builder.semantic_model.get_db().get_type_index();
269+
let file_id = builder.semantic_model.get_file_id();
270+
if type_index.get_file_namespace(&file_id).is_some() {
271+
return;
272+
}
273+
let mut namespaces = type_index.get_file_namespaces();
274+
275+
namespaces.sort();
276+
277+
for (sorted_index, namespace) in namespaces.iter().enumerate() {
278+
let completion_item = CompletionItem {
279+
label: namespace.clone(),
280+
kind: Some(lsp_types::CompletionItemKind::MODULE),
281+
sort_text: Some(format!("{:03}", sorted_index)),
282+
..Default::default()
283+
};
284+
builder.add_completion_item(completion_item);
285+
}
286+
}
287+
288+
fn add_tag_using_completion(builder: &mut CompletionBuilder) {
289+
let type_index = builder.semantic_model.get_db().get_type_index();
290+
let file_id = builder.semantic_model.get_file_id();
291+
let current_namespace = type_index.get_file_namespace(&file_id);
292+
let mut namespaces = type_index.get_file_namespaces();
293+
if let Some(current_namespace) = current_namespace {
294+
namespaces.retain(|namespace| namespace != current_namespace);
295+
}
296+
namespaces.sort();
297+
298+
for (sorted_index, namespace) in namespaces.iter().enumerate() {
299+
let completion_item = CompletionItem {
300+
label: format!("using {}", namespace),
301+
kind: Some(lsp_types::CompletionItemKind::MODULE),
302+
sort_text: Some(format!("{:03}", sorted_index)),
303+
insert_text: Some(format!("{}", namespace)),
304+
..Default::default()
305+
};
306+
builder.add_completion_item(completion_item);
307+
}
308+
}

crates/emmylua_ls/src/handlers/completion/providers/env_provider.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use std::collections::HashSet;
22

33
use emmylua_code_analysis::{LuaFlowId, LuaSignatureId, LuaType, LuaVarRefId};
4-
use emmylua_parser::{LuaAst, LuaAstNode, LuaCallArgList, LuaClosureExpr, LuaParamList};
4+
use emmylua_parser::{
5+
LuaAst, LuaAstNode, LuaCallArgList, LuaClosureExpr, LuaParamList, LuaTokenKind,
6+
};
57
use lsp_types::{CompletionItem, CompletionItemKind, CompletionTriggerKind};
68

79
use crate::handlers::completion::{
@@ -56,6 +58,10 @@ fn check_can_add_completion(builder: &CompletionBuilder) -> Option<()> {
5658
}
5759
} else if builder.trigger_kind == CompletionTriggerKind::INVOKED {
5860
let parent = builder.trigger_token.parent()?;
61+
let prev_token = builder.trigger_token.prev_token()?;
62+
if prev_token.kind() == LuaTokenKind::TkTagUsing.into() {
63+
return None;
64+
}
5965
// 即时是主动触发, 也不允许在函数定义的参数列表中添加
6066
if trigger_text == "(" {
6167
if LuaParamList::can_cast(parent.kind().into()) {

crates/emmylua_ls/src/handlers/test/completion_test.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,4 +977,62 @@ mod tests {
977977
CompletionTriggerKind::TRIGGER_CHARACTER,
978978
));
979979
}
980+
981+
#[test]
982+
fn test_namespace_base() {
983+
let mut ws = ProviderVirtualWorkspace::new();
984+
ws.def(
985+
r#"
986+
---@namespace Reactive
987+
"#,
988+
);
989+
ws.def(
990+
r#"
991+
---@namespace AlienSignals
992+
"#,
993+
);
994+
assert!(ws.check_completion_with_kind(
995+
r#"
996+
---@namespace <??>
997+
998+
"#,
999+
vec![
1000+
VirtualCompletionItem {
1001+
label: "AlienSignals".to_string(),
1002+
kind: CompletionItemKind::MODULE,
1003+
..Default::default()
1004+
},
1005+
VirtualCompletionItem {
1006+
label: "Reactive".to_string(),
1007+
kind: CompletionItemKind::MODULE,
1008+
..Default::default()
1009+
},
1010+
],
1011+
CompletionTriggerKind::TRIGGER_CHARACTER,
1012+
));
1013+
1014+
assert!(ws.check_completion_with_kind(
1015+
r#"
1016+
---@namespace Reactive
1017+
---@namespace <??>
1018+
1019+
"#,
1020+
vec![],
1021+
CompletionTriggerKind::TRIGGER_CHARACTER,
1022+
));
1023+
1024+
assert!(ws.check_completion_with_kind(
1025+
r#"
1026+
---@namespace Reactive
1027+
---@using <??>
1028+
1029+
"#,
1030+
vec![VirtualCompletionItem {
1031+
label: "using AlienSignals".to_string(),
1032+
kind: CompletionItemKind::MODULE,
1033+
..Default::default()
1034+
},],
1035+
CompletionTriggerKind::INVOKED,
1036+
));
1037+
}
9801038
}

0 commit comments

Comments
 (0)