|
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 | +}; |
25 | 13 |
|
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); |
32 | 29 | }
|
33 | 30 | }
|
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 | + } |
39 | 34 |
|
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 | +} |
48 | 37 |
|
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 | + _ => {} |
53 | 80 | }
|
54 | 81 | }
|
55 |
| - _ => {} |
56 | 82 | }
|
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 | + } |
63 | 98 | }
|
| 99 | + _ => continue, |
64 | 100 | }
|
65 | 101 | }
|
66 | 102 |
|
67 |
| - (LuaMemberOwner::LocalUnresolve, None) |
| 103 | + Some(()) |
68 | 104 | }
|
69 | 105 |
|
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 | + } |
80 | 117 | }
|
| 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 | + }; |
81 | 146 |
|
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); |
84 | 150 | }
|
85 |
| - _ => {} |
86 | 151 | }
|
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(()) |
88 | 198 | }
|
0 commit comments