|
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