1
1
use emmylua_code_analysis:: {
2
2
enum_variable_is_param, DbIndex , LuaMemberInfo , LuaSemanticDeclId , LuaType , LuaTypeDeclId ,
3
+ SemanticModel ,
3
4
} ;
4
5
use emmylua_parser:: { LuaAstNode , LuaAstToken , LuaIndexExpr , LuaStringToken } ;
5
6
@@ -40,7 +41,11 @@ pub fn add_completion(builder: &mut CompletionBuilder) -> Option<()> {
40
41
}
41
42
42
43
let member_info_map = builder. semantic_model . get_member_info_map ( & prefix_type) ?;
43
- for ( _, member_infos) in member_info_map. iter ( ) {
44
+ // 排序
45
+ let mut sorted_entries: Vec < _ > = member_info_map. iter ( ) . collect ( ) ;
46
+ sorted_entries. sort_unstable_by ( |( name1, _) , ( name2, _) | name1. cmp ( name2) ) ;
47
+
48
+ for ( _, member_infos) in sorted_entries {
44
49
add_resolve_member_infos ( builder, & member_infos, completion_status) ;
45
50
}
46
51
@@ -53,11 +58,28 @@ fn add_resolve_member_infos(
53
58
completion_status : CompletionTriggerStatus ,
54
59
) -> Option < ( ) > {
55
60
if member_infos. len ( ) == 1 {
56
- let overload_count = count_function_overloads (
57
- builder. semantic_model . get_db ( ) ,
58
- & member_infos. iter ( ) . map ( |info| info) . collect :: < Vec < _ > > ( ) ,
59
- ) ;
60
61
let member_info = & member_infos[ 0 ] ;
62
+ let overload_count = match & member_info. typ {
63
+ LuaType :: DocFunction ( _) => None ,
64
+ LuaType :: Signature ( id) => {
65
+ if let Some ( signature) = builder
66
+ . semantic_model
67
+ . get_db ( )
68
+ . get_signature_index ( )
69
+ . get ( & id)
70
+ {
71
+ let count = signature. overloads . len ( ) ;
72
+ if count == 0 {
73
+ None
74
+ } else {
75
+ Some ( count)
76
+ }
77
+ } else {
78
+ None
79
+ }
80
+ }
81
+ _ => None ,
82
+ } ;
61
83
add_member_completion (
62
84
builder,
63
85
member_info. clone ( ) ,
@@ -67,46 +89,12 @@ fn add_resolve_member_infos(
67
89
return Some ( ( ) ) ;
68
90
}
69
91
70
- let mut resolve_state = MemberResolveState :: All ;
71
- if builder
72
- . semantic_model
73
- . get_db ( )
74
- . get_emmyrc ( )
75
- . strict
76
- . meta_override_file_define
77
- {
78
- for member_info in member_infos {
79
- match member_info. feature {
80
- Some ( feature) => {
81
- if feature. is_meta_decl ( ) {
82
- resolve_state = MemberResolveState :: Meta ;
83
- break ;
84
- } else if feature. is_file_decl ( ) {
85
- resolve_state = MemberResolveState :: FileDecl ;
86
- }
87
- }
88
- None => { }
89
- }
90
- }
91
- }
92
-
93
- // 屏蔽掉父类成员
94
- let first_owner = get_owner_type_id ( builder. semantic_model . get_db ( ) , member_infos. first ( ) ?) ;
95
- let member_infos: Vec < & LuaMemberInfo > = member_infos
96
- . iter ( )
97
- . filter ( |member_info| {
98
- get_owner_type_id ( builder. semantic_model . get_db ( ) , member_info) == first_owner
99
- } )
100
- . collect ( ) ;
101
-
102
- // 当全为`DocFunction`时, 只取第一个作为补全项
103
- let limit_doc_function = member_infos
104
- . iter ( )
105
- . all ( |info| matches ! ( info. typ, LuaType :: DocFunction ( _) ) ) ;
92
+ let ( filtered_member_infos, overload_count) =
93
+ filter_member_infos ( & builder. semantic_model , member_infos) ?;
106
94
107
- let overload_count = count_function_overloads ( builder. semantic_model . get_db ( ) , & member_infos ) ;
95
+ let resolve_state = get_resolve_state ( builder. semantic_model . get_db ( ) , & filtered_member_infos ) ;
108
96
109
- for member_info in member_infos {
97
+ for member_info in filtered_member_infos {
110
98
match resolve_state {
111
99
MemberResolveState :: All => {
112
100
add_member_completion (
@@ -115,9 +103,6 @@ fn add_resolve_member_infos(
115
103
completion_status,
116
104
overload_count,
117
105
) ;
118
- if limit_doc_function {
119
- break ;
120
- }
121
106
}
122
107
MemberResolveState :: Meta => {
123
108
if let Some ( feature) = member_info. feature {
@@ -128,9 +113,6 @@ fn add_resolve_member_infos(
128
113
completion_status,
129
114
overload_count,
130
115
) ;
131
- if limit_doc_function {
132
- break ;
133
- }
134
116
}
135
117
}
136
118
}
@@ -143,9 +125,6 @@ fn add_resolve_member_infos(
143
125
completion_status,
144
126
overload_count,
145
127
) ;
146
- if limit_doc_function {
147
- break ;
148
- }
149
128
}
150
129
}
151
130
}
@@ -155,30 +134,105 @@ fn add_resolve_member_infos(
155
134
Some ( ( ) )
156
135
}
157
136
158
- fn count_function_overloads ( db : & DbIndex , member_infos : & Vec < & LuaMemberInfo > ) -> Option < usize > {
159
- let mut count = 0 ;
137
+ /// 过滤成员信息,返回需要的成员列表和重载数量
138
+ fn filter_member_infos < ' a > (
139
+ semantic_model : & SemanticModel ,
140
+ member_infos : & ' a Vec < LuaMemberInfo > ,
141
+ ) -> Option < ( Vec < & ' a LuaMemberInfo > , Option < usize > ) > {
142
+ if member_infos. is_empty ( ) {
143
+ return None ;
144
+ }
145
+
146
+ let mut file_decl_member: Option < & LuaMemberInfo > = None ;
147
+ let mut member_with_owners: Vec < ( & LuaMemberInfo , Option < LuaTypeDeclId > ) > =
148
+ Vec :: with_capacity ( member_infos. len ( ) ) ;
149
+ let mut all_doc_function = true ;
150
+ let mut overload_count = 0 ;
151
+
152
+ // 一次遍历收集所有信息
160
153
for member_info in member_infos {
154
+ let owner_id = get_owner_type_id ( semantic_model. get_db ( ) , member_info) ;
155
+ member_with_owners. push ( ( member_info, owner_id. clone ( ) ) ) ;
156
+
157
+ // 寻找第一个 file_decl 作为参考,如果没有则使用第一个
158
+ if file_decl_member. is_none ( ) {
159
+ if let Some ( feature) = member_info. feature {
160
+ if feature. is_file_decl ( ) {
161
+ file_decl_member = Some ( member_info) ;
162
+ }
163
+ }
164
+ }
165
+
166
+ // 检查是否全为 DocFunction,同时计算重载数量
161
167
match & member_info. typ {
162
168
LuaType :: DocFunction ( _) => {
163
- count += 1 ;
169
+ overload_count += 1 ;
164
170
}
165
171
LuaType :: Signature ( id) => {
166
- count += 1 ;
167
- if let Some ( signature) = db. get_signature_index ( ) . get ( & id) {
168
- count += signature. overloads . len ( ) ;
172
+ all_doc_function = false ;
173
+ overload_count += 1 ;
174
+ if let Some ( signature) = semantic_model. get_db ( ) . get_signature_index ( ) . get ( & id) {
175
+ overload_count += signature. overloads . len ( ) ;
169
176
}
170
177
}
171
- _ => { }
178
+ _ => {
179
+ all_doc_function = false ;
180
+ }
172
181
}
173
182
}
174
- if count >= 1 {
175
- count -= 1 ;
176
- }
177
- if count == 0 {
178
- None
183
+
184
+ // 确定最终使用的参考 owner
185
+ let final_reference_owner = if let Some ( file_decl_member_info) = file_decl_member {
186
+ // 与第一个成员进行类型检查, 确保子类成员的类型与父类成员的类型一致
187
+ if let Some ( ( first_member, first_owner) ) = member_with_owners. first ( ) {
188
+ let type_check_result =
189
+ semantic_model. type_check ( & file_decl_member_info. typ , & first_member. typ ) ;
190
+ if type_check_result. is_ok ( ) {
191
+ get_owner_type_id ( semantic_model. get_db ( ) , file_decl_member_info)
192
+ } else {
193
+ first_owner. clone ( )
194
+ }
195
+ } else {
196
+ get_owner_type_id ( semantic_model. get_db ( ) , file_decl_member_info)
197
+ }
198
+ } else {
199
+ // 没有找到 file_decl,使用第一个成员作为参考
200
+ member_with_owners
201
+ . first ( )
202
+ . map ( |( _, owner) | owner. clone ( ) )
203
+ . flatten ( )
204
+ } ;
205
+
206
+ // 过滤出相同 owner_type_id 的成员
207
+ let mut filtered_member_infos: Vec < & LuaMemberInfo > = member_with_owners
208
+ . into_iter ( )
209
+ . filter_map ( |( member_info, owner_id) | {
210
+ if owner_id == final_reference_owner {
211
+ Some ( member_info)
212
+ } else {
213
+ None
214
+ }
215
+ } )
216
+ . collect ( ) ;
217
+
218
+ // 处理重载计数
219
+ let final_overload_count = if overload_count >= 1 {
220
+ let count = overload_count - 1 ;
221
+ if count == 0 {
222
+ None
223
+ } else {
224
+ Some ( count)
225
+ }
179
226
} else {
180
- Some ( count)
227
+ None
228
+ } ;
229
+
230
+ // 如果全为 DocFunction, 只保留第一个
231
+ if all_doc_function && !filtered_member_infos. is_empty ( ) {
232
+ filtered_member_infos. truncate ( 1 ) ;
181
233
}
234
+
235
+ Some ( ( filtered_member_infos, final_overload_count) )
182
236
}
183
237
184
238
enum MemberResolveState {
@@ -198,3 +252,23 @@ fn get_owner_type_id(db: &DbIndex, info: &LuaMemberInfo) -> Option<LuaTypeDeclId
198
252
_ => None ,
199
253
}
200
254
}
255
+
256
+ fn get_resolve_state ( db : & DbIndex , member_infos : & Vec < & LuaMemberInfo > ) -> MemberResolveState {
257
+ let mut resolve_state = MemberResolveState :: All ;
258
+ if db. get_emmyrc ( ) . strict . meta_override_file_define {
259
+ for member_info in member_infos. iter ( ) {
260
+ match member_info. feature {
261
+ Some ( feature) => {
262
+ if feature. is_meta_decl ( ) {
263
+ resolve_state = MemberResolveState :: Meta ;
264
+ break ;
265
+ } else if feature. is_file_decl ( ) {
266
+ resolve_state = MemberResolveState :: FileDecl ;
267
+ }
268
+ }
269
+ None => { }
270
+ }
271
+ }
272
+ }
273
+ resolve_state
274
+ }
0 commit comments