Skip to content

Commit a026c68

Browse files
committed
stash
1 parent ecd6a03 commit a026c68

File tree

9 files changed

+227
-237
lines changed

9 files changed

+227
-237
lines changed

crates/emmylua_code_analysis/src/compilation/analyzer/common/member.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
use emmylua_parser::{LuaAstNode, LuaNameExpr};
1+
use emmylua_parser::{LuaAstNode, LuaExpr, LuaIndexExpr, LuaNameExpr};
22

33
use crate::{DbIndex, FileId, GlobalId, LuaDeclId, LuaMemberOwner, LuaType};
44

5-
pub fn get_name_expr_member_owner(db: &DbIndex, file_id: FileId, name_expr: &LuaNameExpr) -> Option<LuaMemberOwner> {
5+
pub fn get_name_expr_member_owner(
6+
db: &DbIndex,
7+
file_id: FileId,
8+
name_expr: &LuaNameExpr,
9+
) -> Option<LuaMemberOwner> {
610
let decl_id = LuaDeclId::new(file_id, name_expr.get_position());
711
if let Some(owner) = get_decl_member_owner(&db, &decl_id) {
812
return Some(owner);
@@ -12,7 +16,19 @@ pub fn get_name_expr_member_owner(db: &DbIndex, file_id: FileId, name_expr: &Lua
1216
let name = name_expr.get_name_text()?;
1317
let prev_decl = decl_tree.find_local_decl(&name, name_expr.get_position())?;
1418

15-
Some(LuaMemberOwner::DeclId(prev_decl.get_id()))
19+
if !prev_decl.is_implicit_self() {
20+
return Some(LuaMemberOwner::DeclId(prev_decl.get_id()));
21+
}
22+
23+
let root = name_expr.get_root();
24+
let syntax_id = prev_decl.get_syntax_id();
25+
let token = syntax_id.to_token_from_root(&root)?;
26+
let index_expr = LuaIndexExpr::cast(token.parent()?)?;
27+
let LuaExpr::NameExpr(prefix_name_expr) = index_expr.get_prefix_expr()? else {
28+
return None;
29+
};
30+
31+
get_name_expr_member_owner(db, file_id, &prefix_name_expr)
1632
}
1733

1834
pub fn get_decl_member_owner(db: &DbIndex, decl_id: &LuaDeclId) -> Option<LuaMemberOwner> {
@@ -28,7 +44,9 @@ pub fn get_decl_member_owner(db: &DbIndex, decl_id: &LuaDeclId) -> Option<LuaMem
2844
LuaType::LocalDecl(decl_id) => {
2945
return Some(LuaMemberOwner::DeclId(decl_id.clone()));
3046
}
31-
47+
LuaType::TableConst(table_const) => {
48+
return Some(LuaMemberOwner::Element(table_const.clone()));
49+
}
3250
_ => return None,
3351
}
3452
}

crates/emmylua_code_analysis/src/compilation/analyzer/common/mod.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,11 @@ mod bind_type;
22
mod member;
33

44
pub use bind_type::{add_member, bind_type};
5-
pub use member::*;
5+
use emmylua_parser::LuaIndexExpr;
6+
pub use member::*;
7+
8+
use crate::{DbIndex, GlobalId};
9+
10+
pub fn get_global_path(_: &DbIndex, _: &LuaIndexExpr) -> Option<GlobalId> {
11+
None
12+
}
Lines changed: 179 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,198 @@
1-
use emmylua_parser::{LuaAstNode, LuaExpr, LuaIndexExpr, PathTrait};
2-
use smol_str::SmolStr;
3-
4-
use crate::{GlobalId, LuaMemberOwner};
5-
6-
use super::DeclAnalyzer;
7-
8-
pub fn find_index_owner(
9-
analyzer: &mut DeclAnalyzer,
10-
index_expr: LuaIndexExpr,
11-
) -> (LuaMemberOwner, Option<GlobalId>) {
12-
if is_in_global_member(analyzer, &index_expr).unwrap_or(false) {
13-
if let Some(prefix_expr) = index_expr.get_prefix_expr() {
14-
match prefix_expr {
15-
LuaExpr::IndexExpr(parent_index_expr) => {
16-
if let Some(parent_access_path) = parent_index_expr.get_access_path() {
17-
if let Some(access_path) = index_expr.get_access_path() {
18-
return (
19-
LuaMemberOwner::GlobalPath(GlobalId(
20-
SmolStr::new(parent_access_path).into(),
21-
)),
22-
Some(GlobalId(SmolStr::new(access_path).into())),
23-
);
24-
}
1+
use emmylua_parser::{
2+
LuaAssignStat, LuaAstNode, LuaExpr, LuaFuncStat, LuaIndexKey, LuaLocalStat, LuaTableField,
3+
LuaVarExpr,
4+
};
5+
6+
use crate::{
7+
LuaDeclId, LuaMember, LuaMemberFeature, LuaMemberId, LuaMemberKey, LuaMemberOwner, LuaType,
8+
compilation::analyzer::{
9+
common::{get_global_path, get_name_expr_member_owner},
10+
member::MemberAnalyzer,
11+
},
12+
};
2513

26-
return (
27-
LuaMemberOwner::GlobalPath(GlobalId(
28-
SmolStr::new(parent_access_path).into(),
29-
)),
30-
None,
31-
);
14+
pub fn analyze_local_stat(analyzer: &mut MemberAnalyzer, local_stat: LuaLocalStat) -> Option<()> {
15+
let local_name_list = local_stat.get_local_name_list().collect::<Vec<_>>();
16+
let local_expr_list = local_stat.get_value_exprs().collect::<Vec<_>>();
17+
for i in 0..local_expr_list.len() {
18+
let local_name = local_name_list.get(i)?;
19+
let local_expr = local_expr_list.get(i)?;
20+
if let LuaExpr::TableExpr(table_expr) = local_expr {
21+
let decl_id = LuaDeclId::new(analyzer.file_id, local_name.get_position());
22+
let owner = LuaMemberOwner::DeclId(decl_id);
23+
if table_expr.is_object() {
24+
for table_field in table_expr.get_fields() {
25+
if let Some(field_key) = table_field.get_field_key() {
26+
let file_id = analyzer.file_id;
27+
let member_id = LuaMemberId::new(table_field.get_syntax_id(), file_id);
28+
add_field_member(analyzer, owner.clone(), field_key, member_id);
3229
}
3330
}
34-
LuaExpr::NameExpr(name) => {
35-
if let Some(parent_path) = name.get_name_text() {
36-
if parent_path == "self" {
37-
return (LuaMemberOwner::LocalUnresolve, None);
38-
}
31+
}
32+
}
33+
}
3934

40-
if let Some(access_path) = index_expr.get_access_path() {
41-
return (
42-
LuaMemberOwner::GlobalPath(GlobalId(
43-
SmolStr::new(parent_path).into(),
44-
)),
45-
Some(GlobalId(SmolStr::new(access_path).into())),
46-
);
47-
}
35+
Some(())
36+
}
4837

49-
return (
50-
LuaMemberOwner::GlobalPath(GlobalId(SmolStr::new(parent_path).into())),
51-
None,
52-
);
38+
pub fn analyze_assign_stat(
39+
analyzer: &mut MemberAnalyzer,
40+
assign_stat: LuaAssignStat,
41+
) -> Option<()> {
42+
let (vars, exprs) = assign_stat.get_var_and_expr_list();
43+
for i in 0..exprs.len() {
44+
let var = vars.get(i)?;
45+
let expr = exprs.get(i)?;
46+
match (var, expr) {
47+
(LuaVarExpr::IndexExpr(index_expr), _) => {
48+
if let Some(prefix_expr) = index_expr.get_prefix_expr() {
49+
match prefix_expr {
50+
LuaExpr::NameExpr(prefix_name_expr) => {
51+
if let Some(owner) = get_name_expr_member_owner(
52+
&analyzer.db,
53+
analyzer.file_id,
54+
&prefix_name_expr,
55+
) {
56+
if let Some(field_key) = index_expr.get_index_key() {
57+
let member_id = LuaMemberId::new(
58+
index_expr.get_syntax_id(),
59+
analyzer.file_id,
60+
);
61+
add_field_member(analyzer, owner.clone(), field_key, member_id);
62+
}
63+
}
64+
}
65+
LuaExpr::IndexExpr(prefix_index_expr) => {
66+
if let Some(global_id) =
67+
get_global_path(&analyzer.db, &prefix_index_expr)
68+
{
69+
if let Some(field_key) = index_expr.get_index_key() {
70+
let member_id = LuaMemberId::new(
71+
index_expr.get_syntax_id(),
72+
analyzer.file_id,
73+
);
74+
let owner = LuaMemberOwner::Global(global_id);
75+
add_field_member(analyzer, owner, field_key, member_id);
76+
}
77+
}
78+
}
79+
_ => {}
5380
}
5481
}
55-
_ => {}
5682
}
57-
} else {
58-
if let Some(access_path) = index_expr.get_access_path() {
59-
return (
60-
LuaMemberOwner::LocalUnresolve,
61-
Some(GlobalId(SmolStr::new(access_path).into())),
62-
);
83+
(LuaVarExpr::NameExpr(name_expr), LuaExpr::TableExpr(table_expr)) => {
84+
if let Some(owner) =
85+
get_name_expr_member_owner(&analyzer.db, analyzer.file_id, &name_expr)
86+
{
87+
if table_expr.is_object() {
88+
for table_field in table_expr.get_fields() {
89+
if let Some(field_key) = table_field.get_field_key() {
90+
let file_id = analyzer.file_id;
91+
let member_id =
92+
LuaMemberId::new(table_field.get_syntax_id(), file_id);
93+
add_field_member(analyzer, owner.clone(), field_key, member_id);
94+
}
95+
}
96+
}
97+
}
6398
}
99+
_ => continue,
64100
}
65101
}
66102

67-
(LuaMemberOwner::LocalUnresolve, None)
103+
Some(())
68104
}
69105

70-
fn is_in_global_member(analyzer: &DeclAnalyzer, index_expr: &LuaIndexExpr) -> Option<bool> {
71-
let prefix = index_expr.get_prefix_expr()?;
72-
match prefix {
73-
LuaExpr::IndexExpr(index_expr) => {
74-
return is_in_global_member(analyzer, &index_expr);
75-
}
76-
LuaExpr::NameExpr(name) => {
77-
let name_text = name.get_name_text()?;
78-
if name_text == "self" {
79-
return Some(false);
106+
pub fn analyze_func_stat(analyzer: &mut MemberAnalyzer, func_stat: LuaFuncStat) -> Option<()> {
107+
let func_name_expr = func_stat.get_func_name()?;
108+
if let LuaVarExpr::IndexExpr(index_expr) = func_name_expr {
109+
if let Some(LuaExpr::NameExpr(prefix_name_expr)) = index_expr.get_prefix_expr() {
110+
if let Some(owner) =
111+
get_name_expr_member_owner(&analyzer.db, analyzer.file_id, &prefix_name_expr)
112+
{
113+
if let Some(field_key) = index_expr.get_index_key() {
114+
let member_id = LuaMemberId::new(index_expr.get_syntax_id(), analyzer.file_id);
115+
add_field_member(analyzer, owner.clone(), field_key, member_id);
116+
}
80117
}
118+
}
119+
}
120+
121+
Some(())
122+
}
123+
124+
pub fn analyze_table_field(
125+
analyzer: &mut MemberAnalyzer,
126+
table_field: LuaTableField,
127+
) -> Option<()> {
128+
if !table_field.is_assign_field() {
129+
return None;
130+
}
131+
132+
let value_expr = table_field.get_value_expr()?;
133+
let LuaExpr::TableExpr(table_value) = value_expr else {
134+
return None;
135+
};
136+
137+
let member_id = LuaMemberId::new(table_field.get_syntax_id(), analyzer.file_id);
138+
let doc_type = analyzer
139+
.db
140+
.get_type_index()
141+
.get_type_cache(&member_id.into())?;
142+
let owner = match doc_type.as_type() {
143+
LuaType::Def(type_id) => LuaMemberOwner::Type(type_id.clone()),
144+
_ => return None,
145+
};
81146

82-
let decl = analyzer.find_decl(&name_text, name.get_position());
83-
return Some(decl.is_none());
147+
for field in table_value.get_fields() {
148+
if let Some(field_key) = field.get_field_key() {
149+
add_field_member(analyzer, owner.clone(), field_key, member_id);
84150
}
85-
_ => {}
86151
}
87-
None
152+
153+
Some(())
154+
}
155+
156+
fn add_field_member(
157+
analyzer: &mut MemberAnalyzer,
158+
member_owner: LuaMemberOwner,
159+
field_key: LuaIndexKey,
160+
member_id: LuaMemberId,
161+
) -> Option<()> {
162+
let decl_feature = if analyzer.is_meta {
163+
LuaMemberFeature::MetaDefine
164+
} else {
165+
LuaMemberFeature::FileDefine
166+
};
167+
168+
let key: LuaMemberKey = match field_key {
169+
LuaIndexKey::Name(name) => LuaMemberKey::Name(name.get_name_text().into()),
170+
LuaIndexKey::String(str) => LuaMemberKey::Name(str.get_value().into()),
171+
LuaIndexKey::Integer(i) => LuaMemberKey::Integer(i.get_int_value()),
172+
LuaIndexKey::Idx(idx) => LuaMemberKey::Integer(idx as i64),
173+
LuaIndexKey::Expr(_) => {
174+
// let unresolve_member = UnResolveTableField {
175+
// file_id: analyzer.get_file_id(),
176+
// table_expr: table_expr.clone(),
177+
// field: field.clone(),
178+
// decl_feature,
179+
// };
180+
// analyzer.context.add_unresolve(
181+
// unresolve_member.into(),
182+
// InferFailReason::UnResolveExpr(InFiled::new(
183+
// analyzer.get_file_id(),
184+
// field_expr.clone(),
185+
// )),
186+
// );
187+
return None;
188+
}
189+
};
190+
191+
let member = LuaMember::new(member_id, key, decl_feature);
192+
analyzer
193+
.db
194+
.get_member_index_mut()
195+
.add_member(member_owner, member);
196+
197+
Some(())
88198
}

crates/emmylua_code_analysis/src/compilation/analyzer/member/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
mod stats;
1+
mod members;
22

33
use emmylua_parser::{LuaAst, LuaAstNode};
44

55
use crate::{
66
DbIndex, FileId, Profile,
77
compilation::analyzer::{
88
AnalysisPipeline, AnalyzeContext,
9-
member::stats::{analyze_assign_stat, analyze_func_stat, analyze_local_stat},
9+
member::members::{
10+
analyze_assign_stat, analyze_func_stat, analyze_local_stat, analyze_table_field,
11+
},
1012
},
1113
};
1214

15+
/// Due to the widespread use of global variables in Lua and the various ways to define members,
16+
/// it is impossible to fully analyze them without knowing their types.
17+
/// Therefore, this only tries to identify as many members as possible in advance.
1318
pub struct MemberAnalysisPipeline;
1419

1520
impl AnalysisPipeline for MemberAnalysisPipeline {
@@ -30,6 +35,9 @@ impl AnalysisPipeline for MemberAnalysisPipeline {
3035
LuaAst::LuaFuncStat(func_stat) => {
3136
analyze_func_stat(&mut analyzer, func_stat);
3237
}
38+
LuaAst::LuaTableField(table_field) => {
39+
analyze_table_field(&mut analyzer, table_field);
40+
}
3341
_ => {}
3442
}
3543
}

0 commit comments

Comments
 (0)