Skip to content

Commit 1d50c1a

Browse files
committed
允予泛型约束来自前面的泛型
1 parent 0fced68 commit 1d50c1a

File tree

7 files changed

+541
-265
lines changed

7 files changed

+541
-265
lines changed

crates/emmylua_code_analysis/src/compilation/analyzer/doc/file_generic_index.rs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,12 @@ impl FileGenericIndex {
2020
}
2121
}
2222

23-
pub fn add_generic_scope(
24-
&mut self,
25-
ranges: Vec<TextRange>,
26-
params: Vec<GenericParam>,
27-
is_func: bool,
28-
) {
29-
let params_id = self.generic_params.len();
30-
// 由于我们允许 infer 推断出一个虚拟泛型, 因此需要计算已声明的泛型数量确定其位置
23+
pub fn add_generic_scope(&mut self, ranges: Vec<TextRange>, is_func: bool) -> GenericParamId {
24+
let params_index = self.generic_params.len();
3125
let start = self.get_start(&ranges).unwrap_or(0);
3226
self.generic_params
33-
.push(TagGenericParams::new(params, is_func, start));
34-
let params_id = GenericParamId::new(params_id);
27+
.push(TagGenericParams::new(is_func, start));
28+
let params_id = GenericParamId::new(params_index);
3529
let root_node_ids: Vec<_> = self.root_node_ids.clone();
3630
for range in ranges {
3731
let mut added = false;
@@ -53,6 +47,33 @@ impl FileGenericIndex {
5347
self.root_node_ids.push(GenericEffectId::new(child_node_id));
5448
}
5549
}
50+
51+
params_id
52+
}
53+
54+
pub fn append_generic_param(&mut self, scope_id: GenericParamId, param: GenericParam) {
55+
if let Some(scope) = self.generic_params.get_mut(scope_id.id) {
56+
scope.insert_param(param);
57+
}
58+
}
59+
60+
pub fn append_generic_params(&mut self, scope_id: GenericParamId, params: Vec<GenericParam>) {
61+
for param in params {
62+
self.append_generic_param(scope_id, param);
63+
}
64+
}
65+
66+
pub fn set_param_constraint(
67+
&mut self,
68+
scope_id: GenericParamId,
69+
name: &str,
70+
constraint: Option<LuaType>,
71+
) {
72+
if let Some(scope) = self.generic_params.get_mut(scope_id.id)
73+
&& let Some((_idx, stored_param)) = scope.params.get_mut(name)
74+
{
75+
stored_param.type_constraint = constraint;
76+
}
5677
}
5778

5879
fn get_start(&self, ranges: &[TextRange]) -> Option<usize> {
@@ -200,14 +221,22 @@ impl GenericEffectId {
200221
pub struct TagGenericParams {
201222
params: HashMap<String, (usize, GenericParam)>,
202223
is_func: bool,
224+
next_index: usize,
203225
}
204226

205227
impl TagGenericParams {
206-
pub fn new(generic_params: Vec<GenericParam>, is_func: bool, start: usize) -> Self {
207-
let mut params = HashMap::new();
208-
for (i, param) in generic_params.into_iter().enumerate() {
209-
params.insert(param.name.to_string(), (start + i, param));
228+
pub fn new(is_func: bool, start: usize) -> Self {
229+
Self {
230+
params: HashMap::new(),
231+
is_func,
232+
next_index: start,
210233
}
211-
Self { params, is_func }
234+
}
235+
236+
fn insert_param(&mut self, param: GenericParam) {
237+
let current_index = self.next_index;
238+
self.next_index += 1;
239+
self.params
240+
.insert(param.name.to_string(), (current_index, param));
212241
}
213242
}

crates/emmylua_code_analysis/src/compilation/analyzer/doc/infer_type.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -572,9 +572,12 @@ fn register_inline_func_generics(
572572
return;
573573
}
574574

575+
let scope_id = analyzer
576+
.generic_index
577+
.add_generic_scope(vec![func.get_range()], true);
575578
analyzer
576579
.generic_index
577-
.add_generic_scope(vec![func.get_range()], generics, true);
580+
.append_generic_params(scope_id, generics);
578581
}
579582

580583
fn get_colon_define(analyzer: &mut DocAnalyzer) -> Option<bool> {
@@ -739,9 +742,12 @@ fn infer_conditional_type(
739742
if !infer_params.is_empty() {
740743
// 条件表达式中 infer 声明的类型参数只允许在`true`分支中使用
741744
let true_range = when_true.get_range();
745+
let scope_id = analyzer
746+
.generic_index
747+
.add_generic_scope(vec![true_range], false);
742748
analyzer
743749
.generic_index
744-
.add_generic_scope(vec![true_range], infer_params.clone(), false);
750+
.append_generic_params(scope_id, infer_params.clone());
745751
}
746752

747753
// 处理条件和分支类型
@@ -788,11 +794,12 @@ fn infer_mapped_type(
788794
.map(|constraint| infer_type(analyzer, constraint));
789795
let param = GenericParam::new(SmolStr::new(name), constraint, None);
790796

791-
analyzer.generic_index.add_generic_scope(
792-
vec![mapped_type.get_range()],
793-
vec![param.clone()],
794-
false,
795-
);
797+
let scope_id = analyzer
798+
.generic_index
799+
.add_generic_scope(vec![mapped_type.get_range()], false);
800+
analyzer
801+
.generic_index
802+
.append_generic_param(scope_id, param.clone());
796803
let position = mapped_type.get_range().start();
797804
let (id, _) = analyzer.generic_index.find_generic(position, name)?;
798805

crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use crate::{
2020
},
2121
};
2222
use std::sync::Arc;
23+
use std::vec;
2324

2425
pub fn analyze_class(analyzer: &mut DocAnalyzer, tag: LuaDocTagClass) -> Option<()> {
2526
let file_id = analyzer.file_id;
@@ -149,9 +150,10 @@ pub fn analyze_alias(analyzer: &mut DocAnalyzer, tag: LuaDocTagAlias) -> Option<
149150
.get_type_index_mut()
150151
.add_generic_params(alias_decl_id.clone(), generic_params.clone());
151152
let range = analyzer.comment.get_range();
153+
let scope_id = analyzer.generic_index.add_generic_scope(vec![range], false);
152154
analyzer
153155
.generic_index
154-
.add_generic_scope(vec![range], generic_params, false);
156+
.append_generic_params(scope_id, generic_params);
155157
}
156158

157159
let origin_type = infer_type(analyzer, tag.get_type()?);
@@ -240,9 +242,10 @@ fn add_generic_index(
240242
}
241243
}
242244

245+
let scope_id = analyzer.generic_index.add_generic_scope(ranges, false);
243246
analyzer
244247
.generic_index
245-
.add_generic_scope(ranges, generic_params, false);
248+
.append_generic_params(scope_id, generic_params);
246249
}
247250

248251
fn get_local_stat_reference_ranges(
@@ -334,37 +337,40 @@ pub fn analyze_func_generic(analyzer: &mut DocAnalyzer, tag: LuaDocTagGeneric) -
334337
report_orphan_tag(analyzer, &tag);
335338
return None;
336339
};
337-
let mut params_result = vec![];
340+
341+
let scope_id = analyzer.generic_index.add_generic_scope(
342+
vec![analyzer.comment.get_range(), comment_owner.get_range()],
343+
true,
344+
);
345+
338346
let mut param_info = Vec::new();
339347
if let Some(params_list) = tag.get_generic_decl_list() {
340348
for param in params_list.get_generic_decl() {
341-
let name = if let Some(param) = param.get_name_token() {
342-
param.get_name_text().to_string()
343-
} else {
349+
let Some(name_token) = param.get_name_token() else {
344350
continue;
345351
};
352+
let name_text = name_token.get_name_text().to_string();
353+
let smol_name = SmolStr::new(name_text.as_str());
354+
analyzer
355+
.generic_index
356+
.append_generic_param(scope_id, GenericParam::new(smol_name.clone(), None, None));
357+
346358
let type_ref = param
347359
.get_type()
348360
.map(|type_ref| infer_type(analyzer, type_ref));
349361

350-
params_result.push(GenericParam::new(
351-
SmolStr::new(name.as_str()),
362+
analyzer.generic_index.set_param_constraint(
363+
scope_id,
364+
name_text.as_str(),
352365
type_ref.clone(),
353-
None,
354-
));
355-
param_info.push(Arc::new(LuaGenericParamInfo::new(name, type_ref, None)));
366+
);
367+
368+
param_info.push(Arc::new(LuaGenericParamInfo::new(
369+
name_text, type_ref, None,
370+
)));
356371
}
357372
}
358373

359-
let mut ranges = Vec::new();
360-
let range = analyzer.comment.get_range();
361-
ranges.push(range);
362-
let range = comment_owner.get_range();
363-
ranges.push(range);
364-
analyzer
365-
.generic_index
366-
.add_generic_scope(ranges, params_result, true);
367-
368374
let closure = find_owner_closure(analyzer)?;
369375
let signature_id = LuaSignatureId::from_closure(analyzer.file_id, &closure);
370376
let signature = analyzer

0 commit comments

Comments
 (0)