Skip to content

Commit 95ba21b

Browse files
committed
refactor(generic ): header resolution and defer indexed alias calls
1. 同时移除了对 std.ConstTpl 的兼容性支持
1 parent 71926f0 commit 95ba21b

7 files changed

Lines changed: 503 additions & 319 deletions

File tree

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

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,32 +6,6 @@ use std::sync::Arc;
66

77
use crate::{GenericParam, GenericTpl, GenericTplId};
88

9-
pub trait GenericIndex: std::fmt::Debug {
10-
fn add_generic_scope(&mut self, ranges: Vec<TextRange>, is_func: bool) -> GenericScopeId;
11-
12-
fn append_generic_param(
13-
&mut self,
14-
scope_id: GenericScopeId,
15-
param: GenericParam,
16-
) -> Option<GenericTplId>;
17-
18-
fn append_generic_params(&mut self, scope_id: GenericScopeId, params: Vec<GenericParam>) {
19-
for param in params {
20-
let _ = self.append_generic_param(scope_id, param);
21-
}
22-
}
23-
24-
fn find_generic(&self, position: TextSize, name: &str) -> Option<(GenericTplId, GenericParam)>;
25-
26-
fn generic_param_mut(&mut self, tpl_id: GenericTplId) -> Option<&mut GenericParam>;
27-
28-
fn mark_generic_const(&mut self, tpl_id: GenericTplId) -> Option<GenericParam> {
29-
let param = self.generic_param_mut(tpl_id)?;
30-
param.is_const = true;
31-
Some(param.clone())
32-
}
33-
}
34-
359
#[derive(Debug, Clone)]
3610
pub struct FileGenericIndex {
3711
scopes: Vec<FileGenericScope>,
@@ -61,17 +35,18 @@ impl FileGenericIndex {
6135
.sum(),
6236
)
6337
}
64-
}
65-
66-
impl GenericIndex for FileGenericIndex {
67-
fn add_generic_scope(&mut self, ranges: Vec<TextRange>, is_func: bool) -> GenericScopeId {
38+
pub(super) fn add_generic_scope(
39+
&mut self,
40+
ranges: Vec<TextRange>,
41+
is_func: bool,
42+
) -> GenericScopeId {
6843
let scope_id = GenericScopeId::new(self.scopes.len());
6944
let next_tpl_id = self.next_tpl_id(&ranges, is_func);
7045
self.scopes.push(FileGenericScope::new(ranges, next_tpl_id));
7146
scope_id
7247
}
7348

74-
fn append_generic_param(
49+
pub(super) fn append_generic_param(
7550
&mut self,
7651
scope_id: GenericScopeId,
7752
param: GenericParam,
@@ -82,26 +57,50 @@ impl GenericIndex for FileGenericIndex {
8257
None
8358
}
8459

60+
pub(super) fn append_generic_params(
61+
&mut self,
62+
scope_id: GenericScopeId,
63+
params: Vec<GenericParam>,
64+
) {
65+
for param in params {
66+
let _ = self.append_generic_param(scope_id, param);
67+
}
68+
}
69+
8570
/// Find generic parameter by position and name.
86-
fn find_generic(&self, position: TextSize, name: &str) -> Option<(GenericTplId, GenericParam)> {
71+
pub(super) fn find_generic(
72+
&self,
73+
position: TextSize,
74+
name: &str,
75+
) -> Option<(GenericTplId, GenericParam)> {
8776
for scope in self.scopes.iter().rev() {
8877
if !scope.contains(position) {
8978
continue;
9079
}
9180

92-
if let Some((id, param)) = scope.params.get(name) {
81+
if let Some((id, param)) = scope
82+
.params
83+
.iter()
84+
.rev()
85+
.find(|(_, param)| param.name == name)
86+
{
9387
return Some((*id, param.clone()));
9488
}
9589
}
9690

9791
None
9892
}
9993

100-
fn generic_param_mut(&mut self, tpl_id: GenericTplId) -> Option<&mut GenericParam> {
94+
pub(super) fn update_generic_param(
95+
&mut self,
96+
tpl_id: GenericTplId,
97+
param: GenericParam,
98+
) -> Option<()> {
10199
for scope in self.scopes.iter_mut().rev() {
102-
for (id, param) in scope.params.values_mut() {
100+
for (id, current_param) in &mut scope.params {
103101
if *id == tpl_id {
104-
return Some(param);
102+
*current_param = param;
103+
return Some(());
105104
}
106105
}
107106
}
@@ -124,15 +123,15 @@ impl GenericScopeId {
124123
#[derive(Debug, Clone, PartialEq, Eq)]
125124
struct FileGenericScope {
126125
ranges: Vec<TextRange>,
127-
params: HashMap<String, (GenericTplId, GenericParam)>,
126+
params: Vec<(GenericTplId, GenericParam)>,
128127
next_tpl_id: GenericTplId,
129128
}
130129

131130
impl FileGenericScope {
132131
fn new(ranges: Vec<TextRange>, next_tpl_id: GenericTplId) -> Self {
133132
Self {
134133
ranges,
135-
params: HashMap::new(),
134+
params: Vec::new(),
136135
next_tpl_id,
137136
}
138137
}
@@ -144,7 +143,7 @@ impl FileGenericScope {
144143
fn insert_param(&mut self, param: GenericParam) -> GenericTplId {
145144
let tpl_id = self.next_tpl_id;
146145
self.next_tpl_id = self.next_tpl_id.with_idx((tpl_id.get_idx() + 1) as u32);
147-
self.params.insert(param.name.to_string(), (tpl_id, param));
146+
self.params.push((tpl_id, param));
148147
tpl_id
149148
}
150149

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

Lines changed: 41 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::sync::Arc;
22

33
use emmylua_parser::{
4-
LuaAst, LuaAstNode, LuaClosureExpr, LuaComment, LuaDocBinaryType, LuaDocConditionalType,
4+
LuaAst, LuaAstNode, LuaComment, LuaDocBinaryType, LuaDocConditionalType,
55
LuaDocDescriptionOwner, LuaDocFuncType, LuaDocGenericDecl, LuaDocGenericDeclList,
66
LuaDocGenericType, LuaDocIndexAccessType, LuaDocMappedType, LuaDocMultiLineUnionType,
77
LuaDocObjectFieldKey, LuaDocObjectType, LuaDocStrTplType, LuaDocType, LuaDocUnaryType,
@@ -13,8 +13,8 @@ use smol_str::SmolStr;
1313

1414
use crate::{
1515
AsyncState, DiagnosticCode, FileId, GenericParam, GenericTpl, InFiled, LuaAliasCallKind,
16-
LuaArrayLen, LuaArrayType, LuaMultiLineUnion, LuaSignatureId, LuaTupleStatus, LuaTypeDeclId,
17-
TypeOps, VariadicType, complete_type_generic_args,
16+
LuaArrayLen, LuaArrayType, LuaMultiLineUnion, LuaTupleStatus, LuaTypeDeclId, TypeOps,
17+
VariadicType, complete_type_generic_args,
1818
db_index::{
1919
AnalyzeError, DbIndex, LuaAliasCallType, LuaConditionalType, LuaFunctionType,
2020
LuaGenericType, LuaIndexAccessKey, LuaIntersectionType, LuaMappedType, LuaObjectType,
@@ -23,15 +23,15 @@ use crate::{
2323
};
2424

2525
use super::{
26-
file_generic_index::{ConditionalInferIndex, GenericIndex},
26+
file_generic_index::{ConditionalInferIndex, FileGenericIndex},
2727
preprocess_description,
2828
};
2929

3030
#[derive(Debug)]
3131
pub struct DocTypeAnalyzeContext<'a> {
3232
pub db: &'a mut DbIndex,
3333
pub file_id: FileId,
34-
pub generic_index: &'a mut dyn GenericIndex,
34+
pub generic_index: &'a mut FileGenericIndex,
3535
pub workspace_id: WorkspaceId,
3636
comment: Option<LuaComment>,
3737
options: DocTypeAnalyzeOptions,
@@ -70,7 +70,7 @@ impl<'a> DocTypeAnalyzeContext<'a> {
7070
pub fn new(
7171
db: &'a mut DbIndex,
7272
file_id: FileId,
73-
generic_index: &'a mut dyn GenericIndex,
73+
generic_index: &'a mut FileGenericIndex,
7474
workspace_id: WorkspaceId,
7575
) -> Self {
7676
Self {
@@ -109,70 +109,6 @@ impl<'a> DocTypeAnalyzeContext<'a> {
109109
.add_type_reference(self.file_id, type_id, range);
110110
}
111111
}
112-
113-
// TODO: 为`std.ConstTpl`实现的兼容性代码, 应在下一版本中移除
114-
fn mark_generic_const(&mut self, tpl: &GenericTpl) -> GenericTpl {
115-
let tpl_id = tpl.get_tpl_id();
116-
let param = self
117-
.generic_index
118-
.mark_generic_const(tpl_id)
119-
.unwrap_or_else(|| {
120-
let mut param = tpl.get_param().clone();
121-
param.is_const = true;
122-
param
123-
});
124-
125-
if tpl_id.is_func()
126-
&& let Some(signature_id) = self.current_signature_id()
127-
&& let Some(signature) = self.db.get_signature_index_mut().get_mut(&signature_id)
128-
{
129-
if let Some(signature_param) = signature.generic_params.get_mut(tpl_id.get_idx()) {
130-
signature_param.is_const = true;
131-
}
132-
133-
for overload in &mut signature.overloads {
134-
let mut generic_params = overload.get_generic_params().to_vec();
135-
let mut changed = false;
136-
for generic_param in &mut generic_params {
137-
if generic_param.get_tpl_id() == tpl_id && !generic_param.is_const() {
138-
*generic_param = generic_param.with_const(true);
139-
changed = true;
140-
}
141-
}
142-
143-
if changed {
144-
*overload = Arc::new(LuaFunctionType::new(
145-
overload.get_async_state(),
146-
overload.is_colon_define(),
147-
overload.is_variadic(),
148-
overload.get_params().to_vec(),
149-
overload.get_ret().clone(),
150-
Some(generic_params),
151-
));
152-
}
153-
}
154-
}
155-
156-
GenericTpl::new(
157-
tpl_id,
158-
param.name,
159-
param.constraint,
160-
param.default,
161-
true,
162-
param.attributes,
163-
)
164-
}
165-
166-
fn current_signature_id(&self) -> Option<LuaSignatureId> {
167-
let owner = self.comment.as_ref()?.get_owner()?;
168-
let closure = match owner {
169-
LuaAst::LuaFuncStat(func) => func.get_closure(),
170-
LuaAst::LuaLocalFuncStat(local_func) => local_func.get_closure(),
171-
owner => owner.descendants::<LuaClosureExpr>().next(),
172-
}?;
173-
174-
Some(LuaSignatureId::from_closure(self.file_id, &closure))
175-
}
176112
}
177113

178114
pub fn infer_type(analyzer: &mut DocTypeAnalyzeContext<'_>, node: LuaDocType) -> LuaType {
@@ -541,14 +477,6 @@ fn infer_special_generic_type(
541477

542478
return Some(LuaType::TypeGuard(first_param.into()));
543479
}
544-
"std.ConstTpl" => {
545-
let first_doc_param_type = generic_type.get_generic_types()?.get_types().next()?;
546-
let first_param = infer_type(analyzer, first_doc_param_type);
547-
if let LuaType::TplRef(tpl) = first_param {
548-
let const_tpl = analyzer.mark_generic_const(&tpl);
549-
return Some(LuaType::TplRef(Arc::new(const_tpl)));
550-
}
551-
}
552480
"Language" => {
553481
let first_doc_param_type = generic_type.get_generic_types()?.get_types().next()?;
554482
let first_param = infer_type(analyzer, first_doc_param_type);
@@ -790,35 +718,52 @@ fn register_inline_func_generics(
790718
.generic_index
791719
.add_generic_scope(vec![func.get_range()], true);
792720
let mut generic_params = Vec::new();
793-
for param in generic_list.get_generic_decl() {
794-
let Some(name_token) = param.get_name_token() else {
721+
let mut declared_params = Vec::new();
722+
for generic_decl in generic_list.get_generic_decl() {
723+
let Some(name_token) = generic_decl.get_name_token() else {
795724
continue;
796725
};
797726

798-
let constraint = param
727+
let placeholder = GenericParam::new(
728+
SmolStr::new(name_token.get_name_text()),
729+
None,
730+
None,
731+
generic_decl.has_const_modifier(),
732+
None,
733+
);
734+
if let Some(tpl_id) = analyzer
735+
.generic_index
736+
.append_generic_param(scope_id, placeholder.clone())
737+
{
738+
declared_params.push((tpl_id, generic_decl, placeholder.name));
739+
}
740+
}
741+
742+
for (tpl_id, generic_decl, name) in declared_params {
743+
let constraint = generic_decl
799744
.get_constraint_type()
800745
.map(|ty| infer_type(analyzer, ty));
801-
let default_type = param.get_default_type().map(|ty| infer_type(analyzer, ty));
746+
let default_type = generic_decl
747+
.get_default_type()
748+
.map(|ty| infer_type(analyzer, ty));
802749
let generic_param = GenericParam::new(
803-
SmolStr::new(name_token.get_name_text()),
750+
name,
804751
constraint,
805752
default_type,
806-
param.has_const_modifier(),
753+
generic_decl.has_const_modifier(),
807754
None,
808755
);
809-
if let Some(tpl_id) = analyzer
756+
let _ = analyzer
810757
.generic_index
811-
.append_generic_param(scope_id, generic_param.clone())
812-
{
813-
generic_params.push(GenericTpl::new(
814-
tpl_id,
815-
generic_param.name,
816-
generic_param.constraint,
817-
generic_param.default,
818-
generic_param.is_const,
819-
generic_param.attributes,
820-
));
821-
}
758+
.update_generic_param(tpl_id, generic_param.clone());
759+
generic_params.push(GenericTpl::new(
760+
tpl_id,
761+
generic_param.name,
762+
generic_param.constraint,
763+
generic_param.default,
764+
generic_param.is_const,
765+
generic_param.attributes,
766+
));
822767
}
823768
generic_params
824769
}

0 commit comments

Comments
 (0)