Skip to content

Commit 5201d15

Browse files
committed
add completion for function type
1 parent 0f683ca commit 5201d15

File tree

10 files changed

+121
-23
lines changed

10 files changed

+121
-23
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/code_analysis/src/compilation/analyzer/unresolve/resolve_closure_param.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub fn try_resolve_closure_params(
1919
call_expr,
2020
call_expr_type,
2121
&mut InferGuard::new(),
22+
None
2223
)?;
2324

2425
let signature = db

crates/code_analysis/src/semantic/call_func/mod.rs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,41 @@ pub fn infer_call_expr_func(
1717
call_expr: LuaCallExpr,
1818
call_expr_type: LuaType,
1919
infer_guard: &mut InferGuard,
20+
args_count: Option<usize>,
2021
) -> Option<Arc<LuaFunctionType>> {
2122
match call_expr_type {
2223
LuaType::DocFunction(func) => Some(func),
23-
LuaType::Signature(signature_id) => {
24-
infer_signature_doc_function(db, config, signature_id.clone(), call_expr.clone())
25-
}
24+
LuaType::Signature(signature_id) => infer_signature_doc_function(
25+
db,
26+
config,
27+
signature_id.clone(),
28+
call_expr.clone(),
29+
args_count,
30+
),
2631
LuaType::Def(type_def_id) => infer_type_doc_function(
2732
db,
2833
config,
2934
type_def_id.clone(),
3035
call_expr.clone(),
3136
infer_guard,
37+
args_count,
3238
),
3339
LuaType::Ref(type_ref_id) => infer_type_doc_function(
3440
db,
3541
config,
3642
type_ref_id.clone(),
3743
call_expr.clone(),
3844
infer_guard,
45+
args_count,
46+
),
47+
LuaType::Generic(generic) => infer_generic_type_doc_function(
48+
db,
49+
config,
50+
&generic,
51+
call_expr.clone(),
52+
infer_guard,
53+
args_count,
3954
),
40-
LuaType::Generic(generic) => {
41-
infer_generic_type_doc_function(db, config, &generic, call_expr.clone(), infer_guard)
42-
}
4355
_ => return None,
4456
}
4557
}
@@ -49,6 +61,7 @@ fn infer_signature_doc_function(
4961
config: &mut LuaInferConfig,
5062
signature_id: LuaSignatureId,
5163
call_expr: LuaCallExpr,
64+
args_count: Option<usize>,
5265
) -> Option<Arc<LuaFunctionType>> {
5366
let signature = db.get_signature_index().get(&signature_id)?;
5467
let overloads = &signature.overloads;
@@ -89,6 +102,7 @@ fn infer_signature_doc_function(
89102
call_expr.clone(),
90103
signature.is_colon_define,
91104
signature.is_generic(),
105+
args_count,
92106
)?;
93107

94108
Some(doc_func)
@@ -101,12 +115,20 @@ fn infer_type_doc_function(
101115
type_id: LuaTypeDeclId,
102116
call_expr: LuaCallExpr,
103117
infer_guard: &mut InferGuard,
118+
args_count: Option<usize>,
104119
) -> Option<Arc<LuaFunctionType>> {
105120
infer_guard.check(&type_id)?;
106121
let type_decl = db.get_type_index().get_type_decl(&type_id)?;
107122
if type_decl.is_alias() {
108123
let alias_type = type_decl.get_alias_origin()?;
109-
return infer_call_expr_func(db, config, call_expr, alias_type.clone(), infer_guard);
124+
return infer_call_expr_func(
125+
db,
126+
config,
127+
call_expr,
128+
alias_type.clone(),
129+
infer_guard,
130+
args_count,
131+
);
110132
} else if type_decl.is_enum() {
111133
return None;
112134
}
@@ -126,7 +148,15 @@ fn infer_type_doc_function(
126148
}
127149
}
128150

129-
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false)?;
151+
let doc_func = resolve_signature(
152+
db,
153+
config,
154+
overloads,
155+
call_expr.clone(),
156+
false,
157+
false,
158+
args_count,
159+
)?;
130160
Some(doc_func)
131161
}
132162

@@ -136,13 +166,21 @@ fn infer_generic_type_doc_function(
136166
generic: &LuaGenericType,
137167
call_expr: LuaCallExpr,
138168
infer_guard: &mut InferGuard,
169+
args_count: Option<usize>,
139170
) -> Option<Arc<LuaFunctionType>> {
140171
let type_id = generic.get_base_type_id();
141172
infer_guard.check(&type_id)?;
142173
let type_decl = db.get_type_index().get_type_decl(&type_id)?;
143174
if type_decl.is_alias() {
144175
let alias_type = type_decl.get_alias_origin()?;
145-
return infer_call_expr_func(db, config, call_expr, alias_type.clone(), infer_guard);
176+
return infer_call_expr_func(
177+
db,
178+
config,
179+
call_expr,
180+
alias_type.clone(),
181+
infer_guard,
182+
args_count,
183+
);
146184
} else if type_decl.is_enum() {
147185
return None;
148186
}
@@ -164,6 +202,6 @@ fn infer_generic_type_doc_function(
164202
}
165203
}
166204

167-
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false)?;
205+
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false, args_count)?;
168206
Some(doc_func)
169207
}

crates/code_analysis/src/semantic/infer/infer_call.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ fn infer_call_by_signature(
172172
call_expr.clone(),
173173
signature.is_colon_define,
174174
signature.is_generic(),
175+
None,
175176
)?;
176177
return infer_call_by_doc_function(
177178
db,
@@ -253,7 +254,7 @@ fn infer_call_by_custom_type(
253254
}
254255
}
255256

256-
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false)?;
257+
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false, None)?;
257258
return infer_call_by_doc_function(db, config, &doc_func, call_expr, false);
258259
}
259260

@@ -292,7 +293,7 @@ fn infer_call_by_custom_generic_type(
292293
}
293294
}
294295

295-
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false)?;
296+
let doc_func = resolve_signature(db, config, overloads, call_expr.clone(), false, false, None)?;
296297
return infer_call_by_doc_function(db, config, &doc_func, call_expr, false);
297298
}
298299

crates/code_analysis/src/semantic/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ impl<'a> SemanticModel<'a> {
8686
pub fn infer_call_expr_func(
8787
&mut self,
8888
call_expr: LuaCallExpr,
89+
arg_count: Option<usize>,
8990
) -> Option<Arc<LuaFunctionType>> {
9091
let prefix_expr = call_expr.get_prefix_expr()?;
9192
let call_expr_type = infer_expr(self.db, &mut self.infer_config, prefix_expr.into())?;
@@ -95,6 +96,7 @@ impl<'a> SemanticModel<'a> {
9596
call_expr,
9697
call_expr_type,
9798
&mut InferGuard::new(),
99+
arg_count
98100
)
99101
}
100102

crates/code_analysis/src/semantic/overload_resolve/mod.rs

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub fn resolve_signature(
1515
call_expr: LuaCallExpr,
1616
colon_define: bool,
1717
is_generic: bool,
18+
arg_count: Option<usize>,
1819
) -> Option<Arc<LuaFunctionType>> {
1920
let args = call_expr.get_args_list()?;
2021
let mut expr_types = Vec::new();
@@ -44,9 +45,10 @@ pub fn resolve_signature(
4445
colon_define,
4546
call_expr,
4647
expr_types,
48+
arg_count,
4749
);
4850
} else {
49-
return resolve_signature_by_args(db, infer_config, overloads, expr_types);
51+
return resolve_signature_by_args(db, infer_config, overloads, expr_types, arg_count);
5052
}
5153
}
5254

@@ -57,8 +59,9 @@ fn resolve_signature_by_generic(
5759
colon_define: bool,
5860
call_expr: LuaCallExpr,
5961
expr_types: Vec<LuaType>,
62+
arg_count: Option<usize>,
6063
) -> Option<Arc<LuaFunctionType>> {
61-
let mut max_match = 0;
64+
let mut max_match = -1;
6265
let mut matched_func: Option<Arc<LuaFunctionType>> = None;
6366
let mut instantiate_funcs = Vec::new();
6467
for func in overloads {
@@ -91,13 +94,18 @@ fn resolve_signature_by_generic(
9194
instantiate_funcs.push(new_func);
9295
}
9396

94-
for func in instantiate_funcs {
97+
for func in &instantiate_funcs {
9598
let params = func.get_params();
9699
let mut match_count = 0;
100+
if params.len() < arg_count.unwrap_or(0) {
101+
continue;
102+
}
103+
97104
for (i, param) in params.iter().enumerate() {
98105
if i >= expr_types.len() {
99106
break;
100107
}
108+
101109
let param_type = param.1.clone().unwrap_or(LuaType::Any);
102110
let expr_type = &expr_types[i];
103111
if param_type == LuaType::Any {
@@ -112,6 +120,10 @@ fn resolve_signature_by_generic(
112120
}
113121
}
114122

123+
if matched_func.is_none() && !instantiate_funcs.is_empty() {
124+
matched_func = Some(instantiate_funcs[0].clone());
125+
}
126+
115127
matched_func
116128
}
117129

@@ -120,16 +132,23 @@ fn resolve_signature_by_args(
120132
infer_config: &mut LuaInferConfig,
121133
overloads: Vec<Arc<LuaFunctionType>>,
122134
expr_types: Vec<LuaType>,
135+
arg_count: Option<usize>,
123136
) -> Option<Arc<LuaFunctionType>> {
124137
let mut max_match = -1;
125138
let mut matched_func: Option<Arc<LuaFunctionType>> = None;
126-
for func in overloads {
139+
140+
for func in &overloads {
127141
let params = func.get_params();
128142
let mut match_count = 0;
143+
if params.len() < arg_count.unwrap_or(0) {
144+
continue;
145+
}
146+
129147
for (i, param) in params.iter().enumerate() {
130148
if i >= expr_types.len() {
131149
break;
132150
}
151+
133152
let param_type = param.1.clone().unwrap_or(LuaType::Any);
134153
let expr_type = &expr_types[i];
135154
if param_type == LuaType::Any {
@@ -144,5 +163,9 @@ fn resolve_signature_by_args(
144163
}
145164
}
146165

166+
if matched_func.is_none() && !overloads.is_empty() {
167+
matched_func = Some(overloads[0].clone());
168+
}
169+
147170
matched_func
148171
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
mod alias_or_enum_provider;
1+
mod type_special_provider;
22
mod doc_name_token_provider;
33
mod doc_tag_provider;
44
mod doc_type_provider;
@@ -14,7 +14,7 @@ pub fn add_completions(builder: &mut CompletionBuilder) -> Option<()> {
1414
module_path_provider::add_completion(builder);
1515
file_path_provider::add_completion(builder);
1616
keywords_provider::add_completion(builder);
17-
alias_or_enum_provider::add_completion(builder);
17+
type_special_provider::add_completion(builder);
1818
env_provider::add_completion(builder);
1919
member_provider::add_completion(builder);
2020
doc_tag_provider::add_completion(builder);

crates/emmylua_ls/src/handlers/completion/providers/alias_or_enum_provider.rs renamed to crates/emmylua_ls/src/handlers/completion/providers/type_special_provider.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use code_analysis::{
2-
InferGuard, LuaMemberId, LuaPropertyOwnerId, LuaType, LuaTypeDeclId, LuaUnionType,
2+
InferGuard, LuaFunctionType, LuaMemberId, LuaPropertyOwnerId, LuaType, LuaTypeDeclId,
3+
LuaUnionType,
34
};
45
use emmylua_parser::{
56
LuaAstNode, LuaCallArgList, LuaCallExpr, LuaExpr, LuaSyntaxKind, LuaSyntaxToken, LuaTokenKind,
@@ -35,6 +36,9 @@ fn dispatch_type(
3536
LuaType::Nullable(typ) => {
3637
dispatch_type(builder, (*typ).clone(), infer_guard);
3738
}
39+
LuaType::DocFunction(func) => {
40+
add_lambda_completion(builder, &func);
41+
}
3842
_ => {}
3943
}
4044

@@ -127,10 +131,10 @@ fn infer_call_arg_list(
127131
token: LuaSyntaxToken,
128132
) -> Option<LuaType> {
129133
let call_expr = call_arg_list.get_parent::<LuaCallExpr>()?;
134+
let param_idx = get_current_param_index(&call_expr, &token)?;
130135
let call_expr_func = builder
131136
.semantic_model
132-
.infer_call_expr_func(call_expr.clone())?;
133-
let param_idx = get_current_param_index(&call_expr, &token)?;
137+
.infer_call_expr_func(call_expr.clone(), Some(param_idx + 1))?;
134138

135139
let typ = call_expr_func.get_params().get(param_idx)?.1.clone()?;
136140
Some(typ)
@@ -194,3 +198,25 @@ fn to_enum_label(builder: &CompletionBuilder, str: &str) -> String {
194198
format!("\"{}\"", str)
195199
}
196200
}
201+
202+
fn add_lambda_completion(builder: &mut CompletionBuilder, func: &LuaFunctionType) -> Option<()> {
203+
let params_str = func
204+
.get_params()
205+
.iter()
206+
.map(|p| p.0.clone())
207+
.collect::<Vec<_>>();
208+
let label = format!("function ({}) end", params_str.join(", "));
209+
let insert_text = format!("function ({})\n\t$0\nend", params_str.join(", "));
210+
211+
let completion_item = CompletionItem {
212+
label,
213+
kind: Some(lsp_types::CompletionItemKind::FUNCTION),
214+
sort_text: Some("0".to_string()),
215+
insert_text: Some(insert_text),
216+
insert_text_format: Some(lsp_types::InsertTextFormat::SNIPPET),
217+
..Default::default()
218+
};
219+
220+
builder.add_completion_item(completion_item);
221+
Some(())
222+
}

crates/emmylua_parser/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "emmylua_parser"
3-
version = "0.7.1"
3+
version = "0.8.0"
44
edition = "2021"
55
authors = ["CppCXY"]
66
description = "A parser for EmmyLua and luals"

crates/emmylua_parser/src/grammar/lua/expr.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,13 @@ fn parse_args(p: &mut LuaParser) -> ParseResult {
261261
parse_expr(p)?;
262262
while p.current_token() == LuaTokenKind::TkComma {
263263
p.bump();
264+
if p.current_token() == LuaTokenKind::TkRightParen {
265+
p.push_error(LuaParseError::from_source_range(
266+
&t!("expect expression"),
267+
p.current_token_range(),
268+
));
269+
break;
270+
}
264271
parse_expr(p)?;
265272
}
266273
}

0 commit comments

Comments
 (0)