Skip to content

Commit 62d715f

Browse files
committed
completion: optimize && add param_list
1 parent 14fb885 commit 62d715f

File tree

3 files changed

+80
-14
lines changed

3 files changed

+80
-14
lines changed

crates/emmylua_code_analysis/src/diagnostic/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ mod lua_diagnostic_code;
44
mod lua_diagnostic_config;
55
mod test;
66

7+
pub use checker::get_closure_expr_comment;
78
pub use lua_diagnostic::LuaDiagnostic;
89
pub use lua_diagnostic_code::DiagnosticCode;

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

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

33
use emmylua_code_analysis::{LuaFlowId, LuaType};
4-
use emmylua_parser::{LuaAst, LuaAstNode, LuaCallArgList};
4+
use emmylua_parser::{LuaAst, LuaAstNode, LuaCallArgList, LuaParamList};
55
use lsp_types::CompletionTriggerKind;
66

77
use crate::handlers::completion::{
@@ -40,17 +40,28 @@ pub fn add_completion(builder: &mut CompletionBuilder) -> Option<()> {
4040
}
4141

4242
fn allow_add_env_completion(builder: &CompletionBuilder) -> Option<()> {
43+
let trigger_text = builder.get_trigger_text();
4344
if builder.trigger_kind == CompletionTriggerKind::TRIGGER_CHARACTER {
44-
let trigger_text = builder.get_trigger_text();
4545
// 由字符触发的空格补全不允许添加
4646
if trigger_text.is_empty() {
4747
return None;
4848
}
49-
// 如果触发字符是`(`且位于`CallArgList`中, 那么不允许添加
50-
if trigger_text == "("
51-
&& LuaCallArgList::can_cast(builder.trigger_token.parent()?.kind().into())
52-
{
53-
return None;
49+
let parent = builder.trigger_token.parent()?;
50+
51+
if trigger_text == "(" {
52+
if LuaCallArgList::can_cast(parent.kind().into())
53+
|| LuaParamList::can_cast(parent.kind().into())
54+
{
55+
return None;
56+
}
57+
}
58+
} else if builder.trigger_kind == CompletionTriggerKind::INVOKED {
59+
let parent = builder.trigger_token.parent()?;
60+
// 即时是主动触发, 也不允许在函数定义的参数列表中添加
61+
if trigger_text == "(" {
62+
if LuaParamList::can_cast(parent.kind().into()) {
63+
return None;
64+
}
5465
}
5566
}
5667

@@ -167,8 +178,8 @@ fn add_global_env(
167178

168179
fn env_check_match_word(trigger_text: &str, name: &str) -> bool {
169180
// 如果首字母是`(`或者`,`则允许, 用于在函数参数调用处触发补全
170-
if trigger_text.starts_with('(') || trigger_text.starts_with(',') {
171-
return true;
181+
match trigger_text.chars().next() {
182+
Some('(') | Some(',') => true,
183+
_ => check_match_word(trigger_text, name),
172184
}
173-
check_match_word(trigger_text, name)
174185
}

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

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use emmylua_code_analysis::{
2-
InferGuard, LuaDeclLocation, LuaFunctionType, LuaMember, LuaMemberKey, LuaMemberOwner,
3-
LuaMultiLineUnion, LuaPropertyOwnerId, LuaType, LuaTypeDeclId, LuaUnionType, RenderLevel,
2+
get_closure_expr_comment, InferGuard, LuaDeclLocation, LuaFunctionType, LuaMember,
3+
LuaMemberKey, LuaMemberOwner, LuaMultiLineUnion, LuaPropertyOwnerId, LuaType, LuaTypeDeclId,
4+
LuaUnionType, RenderLevel,
45
};
56
use emmylua_parser::{
6-
LuaAst, LuaAstNode, LuaAstToken, LuaCallArgList, LuaCallExpr, LuaComment, LuaNameToken,
7-
LuaSyntaxId, LuaSyntaxKind, LuaSyntaxToken, LuaTokenKind, LuaVarExpr,
7+
LuaAst, LuaAstNode, LuaAstToken, LuaCallArgList, LuaCallExpr, LuaClosureExpr, LuaComment,
8+
LuaDocTagParam, LuaNameToken, LuaParamList, LuaSyntaxId, LuaSyntaxKind, LuaSyntaxToken,
9+
LuaTokenKind, LuaVarExpr,
810
};
911
use itertools::Itertools;
1012
use lsp_types::{CompletionItem, Documentation};
@@ -168,6 +170,9 @@ fn get_token_should_type(builder: &mut CompletionBuilder) -> Option<Vec<LuaType>
168170
LuaSyntaxKind::CallArgList => {
169171
return infer_call_arg_list(builder, LuaCallArgList::cast(parent_node)?, token);
170172
}
173+
LuaSyntaxKind::ParamList => {
174+
return infer_param_list(builder, LuaParamList::cast(parent_node)?);
175+
}
171176
LuaSyntaxKind::BinaryExpr => {
172177
// infer_binary_expr(builder, binary_expr)?;
173178
}
@@ -177,6 +182,55 @@ fn get_token_should_type(builder: &mut CompletionBuilder) -> Option<Vec<LuaType>
177182
None
178183
}
179184

185+
fn infer_param_list(
186+
builder: &mut CompletionBuilder,
187+
param_list: LuaParamList,
188+
) -> Option<Vec<LuaType>> {
189+
let closure_expr = param_list.get_parent::<LuaClosureExpr>()?;
190+
191+
let doc_params = get_closure_expr_comment(&closure_expr)?.children::<LuaDocTagParam>();
192+
let mut names = Vec::new();
193+
for doc_param in doc_params {
194+
let name = doc_param.get_name_token()?.get_name_text().to_string();
195+
if !names.contains(&name) {
196+
// 不在这里添加补全项, 拼接的优先级应在单独添加之上
197+
names.push(name.clone());
198+
}
199+
}
200+
let params = param_list
201+
.get_params()
202+
.map(|it| {
203+
if let Some(name_token) = it.get_name_token() {
204+
name_token.get_name_text().to_string()
205+
} else {
206+
"".to_string()
207+
}
208+
})
209+
.filter(|it| !it.is_empty())
210+
.collect::<Vec<_>>();
211+
212+
// names 去掉 params 已有的
213+
names.retain(|name| !params.contains(&name));
214+
if names.len() > 1 {
215+
builder.add_completion_item(CompletionItem {
216+
label: format!("{}", names.iter().join(", ")),
217+
kind: Some(lsp_types::CompletionItemKind::INTERFACE),
218+
..Default::default()
219+
});
220+
}
221+
222+
for name in names {
223+
builder.add_completion_item(CompletionItem {
224+
label: name,
225+
kind: Some(lsp_types::CompletionItemKind::INTERFACE),
226+
..Default::default()
227+
});
228+
}
229+
230+
// 不返回类型, 因为字符串类型会被加上双引号, 但这里需要的是不带双引号的字符串, 我们选择直接在这里添加
231+
None
232+
}
233+
180234
fn infer_call_arg_list(
181235
builder: &mut CompletionBuilder,
182236
call_arg_list: LuaCallArgList,

0 commit comments

Comments
 (0)