From 3e427a59741a933666036801591534a3eaf97cc9 Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Tue, 1 Apr 2025 20:53:24 +0800 Subject: [PATCH 1/6] refactor member design --- .../src/compilation/analyzer/decl/exprs.rs | 4 +- .../src/compilation/analyzer/decl/members.rs | 38 +++++++++++++++++++ .../src/compilation/analyzer/decl/mod.rs | 1 + .../src/compilation/analyzer/decl/stats.rs | 12 +++--- .../doc/field_or_operator_def_tags.rs | 15 +++----- .../compilation/analyzer/unresolve/resolve.rs | 3 +- .../src/db_index/member/lua_member.rs | 24 ++++++------ .../src/db_index/member/mod.rs | 16 +++++--- 8 files changed, 77 insertions(+), 36 deletions(-) create mode 100644 crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs index ee569f962..0b1342276 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs @@ -219,8 +219,8 @@ pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, table_expr: LuaTableExpr) ); let member_id = LuaMemberId::new(field.get_syntax_id(), file_id); - let member = LuaMember::new(owner_id.clone(), member_id, key, decl_feature, None); - analyzer.db.get_member_index_mut().add_member(member); + let member = LuaMember::new(member_id, key, decl_feature, None); + analyzer.db.get_member_index_mut().add_member(owner_id.clone(), member); } } } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs new file mode 100644 index 000000000..083631013 --- /dev/null +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs @@ -0,0 +1,38 @@ +use emmylua_parser::{LuaAstNode, LuaExpr, LuaIndexExpr, PathTrait}; +use smol_str::SmolStr; + +use crate::LuaMemberOwner; + +use super::DeclAnalyzer; + +pub fn find_index_owner( + analyzer: &mut DeclAnalyzer, + index_expr: LuaIndexExpr, +) -> Option { + if is_in_global_member(analyzer, &index_expr).unwrap_or(false) { + let access_path = index_expr.get_access_path()?; + return Some(LuaMemberOwner::GlobalPath(SmolStr::new(&access_path).into())); + } + + Some(LuaMemberOwner::LocalUnknown) +} + +fn is_in_global_member(analyzer: &DeclAnalyzer, index_expr: &LuaIndexExpr) -> Option { + let prefix = index_expr.get_prefix_expr()?; + match prefix { + LuaExpr::IndexExpr(index_expr) => { + return is_in_global_member(analyzer, &index_expr); + } + LuaExpr::NameExpr(name) => { + let name_text = name.get_name_text()?; + if name_text == "self" { + return Some(false); + } + + let decl = analyzer.find_decl(&name_text, name.get_position()); + return Some(decl.is_none()); + } + _ => {} + } + None +} diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs index 428a44ac0..4a94db108 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs @@ -1,5 +1,6 @@ mod docs; mod exprs; +mod members; mod stats; use crate::{ diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs index b55dd34a6..48460aab1 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs @@ -4,11 +4,11 @@ use emmylua_parser::{ }; use crate::{ - db_index::{LocalAttribute, LuaDecl, LuaMember, LuaMemberKey, LuaMemberOwner}, + db_index::{LocalAttribute, LuaDecl, LuaMember, LuaMemberKey}, LuaDeclExtra, LuaMemberFeature, LuaMemberId, LuaSemanticDeclId, LuaSignatureId, LuaType, }; -use super::DeclAnalyzer; +use super::{members::find_index_owner, DeclAnalyzer}; pub fn analyze_local_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalStat) -> Option<()> { let local_name_list = stat.get_local_name_list().collect::>(); @@ -109,15 +109,15 @@ pub fn analyze_assign_stat(analyzer: &mut DeclAnalyzer, stat: LuaAssignStat) -> LuaMemberFeature::FileDefine }; + let owner = find_index_owner(analyzer, index_expr.clone())?; let member = LuaMember::new( - LuaMemberOwner::None, member_id, key.clone(), decl_feature, None, ); - analyzer.db.get_member_index_mut().add_member(member); + analyzer.db.get_member_index_mut().add_member(owner, member); if let LuaMemberKey::Name(name) = &key { analyze_maybe_global_index_expr( analyzer, @@ -263,14 +263,14 @@ pub fn analyze_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaFuncStat) -> Opti LuaMemberFeature::FileMethodDecl }; + let owner_id = find_index_owner(analyzer, index_expr.clone())?; let member = LuaMember::new( - LuaMemberOwner::None, member_id, key.clone(), decl_feature, None, ); - let member_id = analyzer.db.get_member_index_mut().add_member(member); + let member_id = analyzer.db.get_member_index_mut().add_member(owner_id,member); if let LuaMemberKey::Name(name) = &key { analyze_maybe_global_index_expr(analyzer, &index_expr, &name, None, None); diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs index 5b874b2fc..670daf793 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs @@ -32,7 +32,7 @@ pub fn analyze_field(analyzer: &mut DocAnalyzer, tag: LuaDocTagField) -> Option< } }; - let member_owner = LuaMemberOwner::Type(current_type_id.clone()); + let owner_id = LuaMemberOwner::Type(current_type_id.clone()); let visibility_kind = if let Some(visibility_token) = tag.get_visibility_token() { Some(visibility_token.get_visibility()) } else { @@ -108,13 +108,7 @@ pub fn analyze_field(analyzer: &mut DocAnalyzer, tag: LuaDocTagField) -> Option< LuaMemberFeature::FileFieldDecl }; - let member = LuaMember::new( - member_owner, - member_id, - key.clone(), - decl_feature, - Some(field_type), - ); + let member = LuaMember::new(member_id, key.clone(), decl_feature, Some(field_type)); analyzer.db.get_reference_index_mut().add_index_reference( key, @@ -122,7 +116,10 @@ pub fn analyze_field(analyzer: &mut DocAnalyzer, tag: LuaDocTagField) -> Option< tag.get_syntax_id(), ); - analyzer.db.get_member_index_mut().add_member(member); + analyzer + .db + .get_member_index_mut() + .add_member(owner_id, member); if let Some(visibility_kind) = visibility_kind { analyzer.db.get_property_index_mut().add_visibility( diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs index 9559c7814..f5a7b2bf8 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs @@ -166,13 +166,12 @@ pub fn try_resolve_table_field( let member_id = LuaMemberId::new(field.get_syntax_id(), file_id); let member = LuaMember::new( - owner_id.clone(), member_id, member_key, unresolve_table_field.decl_feature, decl_type, ); - db.get_member_index_mut().add_member(member); + db.get_member_index_mut().add_member(owner_id, member); // 如果是`Def`则更新 let local_name = table_expr diff --git a/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs b/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs index d0e7714db..09451c987 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs @@ -1,4 +1,5 @@ use emmylua_parser::{LuaDocFieldKey, LuaIndexKey, LuaSyntaxId, LuaSyntaxKind}; +use internment::ArcIntern; use rowan::TextRange; use serde::{Deserialize, Serialize}; use smol_str::SmolStr; @@ -12,7 +13,6 @@ use super::lua_member_feature::LuaMemberFeature; #[derive(Debug)] pub struct LuaMember { - owner: LuaMemberOwner, member_id: LuaMemberId, key: LuaMemberKey, feature: LuaMemberFeature, @@ -21,14 +21,12 @@ pub struct LuaMember { impl LuaMember { pub fn new( - owner: LuaMemberOwner, member_id: LuaMemberId, key: LuaMemberKey, decl_feature: LuaMemberFeature, decl_type: Option, ) -> Self { Self { - owner, member_id, key, feature: decl_feature, @@ -37,7 +35,7 @@ impl LuaMember { } pub fn get_owner(&self) -> LuaMemberOwner { - self.owner.clone() + todo!() } pub fn get_key(&self) -> &LuaMemberKey { @@ -76,10 +74,6 @@ impl LuaMember { self.decl_type = Some(decl_type); } - pub(super) fn set_owner(&mut self, owner: LuaMemberOwner) { - self.owner = owner; - } - pub fn get_id(&self) -> LuaMemberId { self.member_id } @@ -111,9 +105,10 @@ impl LuaMemberId { #[derive(Debug, Hash, PartialEq, Eq, Clone)] pub enum LuaMemberOwner { - None, + LocalUnknown, Type(LuaTypeDeclId), Element(InFiled), + GlobalPath(ArcIntern) } impl LuaMemberOwner { @@ -131,8 +126,15 @@ impl LuaMemberOwner { } } - pub fn is_none(&self) -> bool { - matches!(self, LuaMemberOwner::None) + pub fn get_path(&self) -> Option<&ArcIntern> { + match self { + LuaMemberOwner::GlobalPath(path) => Some(path), + _ => None, + } + } + + pub fn is_unknown(&self) -> bool { + matches!(self, LuaMemberOwner::LocalUnknown) } } diff --git a/crates/emmylua_code_analysis/src/db_index/member/mod.rs b/crates/emmylua_code_analysis/src/db_index/member/mod.rs index 879d87e4a..342cd1795 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/mod.rs @@ -17,6 +17,8 @@ pub struct LuaMemberIndex { members: HashMap, in_filed: HashMap>, owner_members: HashMap>, + member_current_owner: HashMap, + member_origin_owner: HashMap, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -31,18 +33,21 @@ impl LuaMemberIndex { members: HashMap::new(), in_filed: HashMap::new(), owner_members: HashMap::new(), + member_current_owner: HashMap::new(), + member_origin_owner: HashMap::new(), } } - pub fn add_member(&mut self, member: LuaMember) -> LuaMemberId { + pub fn add_member(&mut self, owner: LuaMemberOwner, member: LuaMember) -> LuaMemberId { let id = member.get_id(); - let owner = member.get_owner(); let file_id = member.get_file_id(); self.members.insert(id, member); self.add_in_file_object(file_id, MemberOrOwner::Member(id)); - if !owner.is_none() { + if !owner.is_unknown() { + self.member_current_owner.insert(id, owner.clone()); + self.member_origin_owner.insert(id, owner.clone()); self.add_in_file_object(file_id, MemberOrOwner::Owner(owner.clone())); - self.add_member_to_owner(owner, id); + self.add_member_to_owner(owner.clone(), id); } id } @@ -143,8 +148,7 @@ impl LuaMemberIndex { file_id: FileId, id: LuaMemberId, ) -> Option<()> { - let member = self.get_member_mut(&id)?; - member.set_owner(owner.clone()); + self.member_current_owner.insert(id, owner.clone()); self.add_in_file_object(file_id, MemberOrOwner::Owner(owner)); Some(()) From 6260343b40aaf675795ccb2a922cf88892d13e36 Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Wed, 2 Apr 2025 17:15:20 +0800 Subject: [PATCH 2/6] refactor decl --- CHANGELOG.md | 2 +- .../src/compilation/analyzer/decl/exprs.rs | 14 +- .../src/compilation/analyzer/decl/members.rs | 61 ++++- .../src/compilation/analyzer/decl/mod.rs | 2 +- .../src/compilation/analyzer/decl/stats.rs | 43 +-- .../doc/field_or_operator_def_tags.rs | 10 +- .../compilation/analyzer/doc/type_def_tags.rs | 29 +- .../compilation/analyzer/doc/type_ref_tags.rs | 87 ++---- .../src/compilation/analyzer/lua/mod.rs | 15 +- .../src/compilation/analyzer/lua/stats.rs | 255 +++++++----------- .../analyzer/unresolve/check_reason.rs | 25 +- .../analyzer/unresolve/merge_type.rs | 100 +++---- .../analyzer/unresolve/migrate_member.rs | 67 +++++ .../src/compilation/analyzer/unresolve/mod.rs | 3 +- .../compilation/analyzer/unresolve/resolve.rs | 59 ++-- .../src/db_index/declaration/decl.rs | 90 +------ .../src/db_index/declaration/decl_id.rs | 73 +++++ .../src/db_index/declaration/decl_tree.rs | 23 +- .../src/db_index/declaration/mod.rs | 65 +---- .../src/db_index/declaration/scope.rs | 2 +- .../src/db_index/global/global_id.rs | 15 ++ .../src/db_index/global/mod.rs | 57 ++++ .../src/db_index/member/lua_member.rs | 72 +---- .../src/db_index/member/lua_member_item.rs | 143 +++++----- .../src/db_index/member/lua_member_owner.rs | 70 +++++ .../src/db_index/member/migrate_members.rs | 65 ----- .../src/db_index/member/mod.rs | 30 +-- .../emmylua_code_analysis/src/db_index/mod.rs | 15 ++ .../src/db_index/type/humanize_type.rs | 20 +- .../src/db_index/type/mod.rs | 28 +- .../src/db_index/type/type_owner.rs | 62 +++++ 31 files changed, 838 insertions(+), 764 deletions(-) create mode 100644 crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs create mode 100644 crates/emmylua_code_analysis/src/db_index/declaration/decl_id.rs create mode 100644 crates/emmylua_code_analysis/src/db_index/global/global_id.rs create mode 100644 crates/emmylua_code_analysis/src/db_index/global/mod.rs create mode 100644 crates/emmylua_code_analysis/src/db_index/member/lua_member_owner.rs delete mode 100644 crates/emmylua_code_analysis/src/db_index/member/migrate_members.rs create mode 100644 crates/emmylua_code_analysis/src/db_index/type/type_owner.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 25f053fe6..f6fe20595 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # CHANGELOG -# 0.6.1 (unreleased) +# 0.7.0 (unreleased) `CHG` Refactor `type infer` diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs index 0b1342276..5a2b6ded3 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs @@ -219,8 +219,18 @@ pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, table_expr: LuaTableExpr) ); let member_id = LuaMemberId::new(field.get_syntax_id(), file_id); - let member = LuaMember::new(member_id, key, decl_feature, None); - analyzer.db.get_member_index_mut().add_member(owner_id.clone(), member); + let member = match &owner_id { + LuaMemberOwner::GlobalPath(path) => { + LuaMember::new(member_id, key, decl_feature, Some(path.clone())) + } + _ => { + LuaMember::new(member_id, key, decl_feature, None) + } + }; + analyzer + .db + .get_member_index_mut() + .add_member(owner_id.clone(), member); } } } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs index 083631013..814dce08e 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs @@ -1,20 +1,71 @@ use emmylua_parser::{LuaAstNode, LuaExpr, LuaIndexExpr, PathTrait}; +use internment::ArcIntern; use smol_str::SmolStr; -use crate::LuaMemberOwner; +use crate::{GlobalId, LuaMemberOwner}; use super::DeclAnalyzer; pub fn find_index_owner( analyzer: &mut DeclAnalyzer, index_expr: LuaIndexExpr, -) -> Option { +) -> (LuaMemberOwner, Option) { if is_in_global_member(analyzer, &index_expr).unwrap_or(false) { - let access_path = index_expr.get_access_path()?; - return Some(LuaMemberOwner::GlobalPath(SmolStr::new(&access_path).into())); + if let Some(prefix_expr) = index_expr.get_prefix_expr() { + match prefix_expr { + LuaExpr::IndexExpr(parent_index_expr) => { + if let Some(parent_access_path) = parent_index_expr.get_access_path() { + if let Some(access_path) = index_expr.get_access_path() { + return ( + LuaMemberOwner::GlobalPath(GlobalId( + SmolStr::new(parent_access_path).into(), + )), + Some(GlobalId(SmolStr::new(access_path).into())), + ); + } + + return ( + LuaMemberOwner::GlobalPath(GlobalId( + SmolStr::new(parent_access_path).into(), + )), + None, + ); + } + } + LuaExpr::NameExpr(name) => { + if let Some(parent_path) = name.get_name_text() { + if parent_path == "self" { + return (LuaMemberOwner::LocalUnresolve, None); + } + + if let Some(access_path) = index_expr.get_access_path() { + return ( + LuaMemberOwner::GlobalPath(GlobalId( + SmolStr::new(parent_path).into(), + )), + Some(GlobalId(SmolStr::new(access_path).into())), + ); + } + + return ( + LuaMemberOwner::GlobalPath(GlobalId(SmolStr::new(parent_path).into())), + None, + ); + } + } + _ => {} + } + } else { + if let Some(access_path) = index_expr.get_access_path() { + return ( + LuaMemberOwner::LocalUnresolve, + Some(GlobalId(SmolStr::new(access_path).into())), + ); + } + } } - Some(LuaMemberOwner::LocalUnknown) + (LuaMemberOwner::LocalUnresolve, None) } fn is_in_global_member(analyzer: &DeclAnalyzer, index_expr: &LuaIndexExpr) -> Option { diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs index 4a94db108..0bb1a7b99 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/mod.rs @@ -208,7 +208,7 @@ impl<'a> DeclAnalyzer<'a> { self.add_decl_to_current_scope(id); if is_global { - self.db.get_decl_index_mut().add_global_decl(&name, id); + self.db.get_global_index_mut().add_global_decl(&name, id); self.db .get_reference_index_mut() diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs index 48460aab1..c17181ab7 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs @@ -5,7 +5,7 @@ use emmylua_parser::{ use crate::{ db_index::{LocalAttribute, LuaDecl, LuaMember, LuaMemberKey}, - LuaDeclExtra, LuaMemberFeature, LuaMemberId, LuaSemanticDeclId, LuaSignatureId, LuaType, + LuaDeclExtra, LuaMemberFeature, LuaMemberId, LuaMemberOwner, LuaSemanticDeclId, LuaSignatureId, }; use super::{members::find_index_owner, DeclAnalyzer}; @@ -47,7 +47,6 @@ pub fn analyze_local_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalStat) -> Op LuaDeclExtra::Local { kind: local_name.syntax().kind().into(), attrib, - decl_type: None, }, expr_id, ); @@ -86,7 +85,6 @@ pub fn analyze_assign_stat(analyzer: &mut DeclAnalyzer, stat: LuaAssignStat) -> range, LuaDeclExtra::Global { kind: LuaSyntaxKind::NameExpr.into(), - decl_type: None, }, value_expr_id, ); @@ -109,23 +107,12 @@ pub fn analyze_assign_stat(analyzer: &mut DeclAnalyzer, stat: LuaAssignStat) -> LuaMemberFeature::FileDefine }; - let owner = find_index_owner(analyzer, index_expr.clone())?; - let member = LuaMember::new( - member_id, - key.clone(), - decl_feature, - None, - ); + let (owner, global_id) = find_index_owner(analyzer, index_expr.clone()); + let member = LuaMember::new(member_id, key.clone(), decl_feature, global_id); analyzer.db.get_member_index_mut().add_member(owner, member); if let LuaMemberKey::Name(name) = &key { - analyze_maybe_global_index_expr( - analyzer, - index_expr, - &name, - None, - value_expr_id, - ); + analyze_maybe_global_index_expr(analyzer, index_expr, &name, value_expr_id); } } } @@ -138,7 +125,6 @@ fn analyze_maybe_global_index_expr( analyzer: &mut DeclAnalyzer, index_expr: &LuaIndexExpr, index_name: &str, - typ: Option, value_expr_id: Option, ) -> Option<()> { let file_id = analyzer.get_file_id(); @@ -163,7 +149,6 @@ fn analyze_maybe_global_index_expr( range, LuaDeclExtra::Global { kind: LuaSyntaxKind::IndexExpr.into(), - decl_type: typ, }, value_expr_id, ); @@ -188,7 +173,6 @@ pub fn analyze_for_stat(analyzer: &mut DeclAnalyzer, stat: LuaForStat) -> Option LuaDeclExtra::Local { kind: it_var.syntax().kind().into(), attrib: Some(LocalAttribute::IterConst), - decl_type: Some(LuaType::Integer), }, None, ); @@ -212,7 +196,6 @@ pub fn analyze_for_range_stat(analyzer: &mut DeclAnalyzer, stat: LuaForRangeStat LuaDeclExtra::Local { kind: var.syntax().kind().into(), attrib: Some(LocalAttribute::IterConst), - decl_type: None, }, None, ); @@ -237,7 +220,6 @@ pub fn analyze_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaFuncStat) -> Opti range, LuaDeclExtra::Global { kind: LuaSyntaxKind::NameExpr.into(), - decl_type: None, }, None, ); @@ -263,17 +245,15 @@ pub fn analyze_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaFuncStat) -> Opti LuaMemberFeature::FileMethodDecl }; - let owner_id = find_index_owner(analyzer, index_expr.clone())?; - let member = LuaMember::new( - member_id, - key.clone(), - decl_feature, - None, - ); - let member_id = analyzer.db.get_member_index_mut().add_member(owner_id,member); + let (owner_id, global_id) = find_index_owner(analyzer, index_expr.clone()); + let member = LuaMember::new(member_id, key.clone(), decl_feature, global_id); + let member_id = analyzer + .db + .get_member_index_mut() + .add_member(owner_id, member); if let LuaMemberKey::Name(name) = &key { - analyze_maybe_global_index_expr(analyzer, &index_expr, &name, None, None); + analyze_maybe_global_index_expr(analyzer, &index_expr, &name, None); } LuaSemanticDeclId::Member(member_id) } @@ -305,7 +285,6 @@ pub fn analyze_local_func_stat(analyzer: &mut DeclAnalyzer, stat: LuaLocalFuncSt LuaDeclExtra::Local { kind: local_name.syntax().kind().into(), attrib: None, - decl_type: None, }, None, ); diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs index 670daf793..87aaa75a5 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/field_or_operator_def_tags.rs @@ -11,7 +11,7 @@ use crate::{ LuaSemanticDeclId, LuaType, }, AnalyzeError, DiagnosticCode, LuaFunctionType, LuaMemberFeature, LuaMemberId, LuaSignatureId, - OperatorFunction, TypeOps, + LuaTypeCache, OperatorFunction, TypeOps, }; use super::{infer_type::infer_type, DocAnalyzer}; @@ -108,8 +108,7 @@ pub fn analyze_field(analyzer: &mut DocAnalyzer, tag: LuaDocTagField) -> Option< LuaMemberFeature::FileFieldDecl }; - let member = LuaMember::new(member_id, key.clone(), decl_feature, Some(field_type)); - + let member = LuaMember::new(member_id, key.clone(), decl_feature, None); analyzer.db.get_reference_index_mut().add_index_reference( key, analyzer.file_id, @@ -121,6 +120,11 @@ pub fn analyze_field(analyzer: &mut DocAnalyzer, tag: LuaDocTagField) -> Option< .get_member_index_mut() .add_member(owner_id, member); + analyzer.db.get_type_index_mut().bind_type( + member_id.clone().into(), + LuaTypeCache::DocType(field_type.clone()), + ); + if let Some(visibility_kind) = visibility_kind { analyzer.db.get_property_index_mut().add_visibility( analyzer.file_id, diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs index 4ee892913..8dc3578e4 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs @@ -10,7 +10,7 @@ use rowan::TextRange; use crate::{ db_index::{LuaDeclId, LuaMemberId, LuaSemanticDeclId, LuaSignatureId, LuaType}, - LuaTypeDeclId, + LuaTypeCache, LuaTypeDeclId, }; use super::{ @@ -378,34 +378,35 @@ fn bind_def_type(analyzer: &mut DocAnalyzer, type_def: LuaType) -> Option<()> { let file_id = analyzer.file_id; let decl_id = LuaDeclId::new(file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - - decl.set_decl_type(type_def); + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::DocType(type_def)); } LuaAst::LuaAssignStat(assign_stat) => { if let LuaVarExpr::NameExpr(name_expr) = assign_stat.child::()? { let position = name_expr.get_position(); let file_id = analyzer.file_id; let decl_id = LuaDeclId::new(file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(type_def); + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::DocType(type_def)); } else if let LuaVarExpr::IndexExpr(index_expr) = assign_stat.child::()? { let member_id = LuaMemberId::new(index_expr.get_syntax_id(), analyzer.file_id); - let member = analyzer + analyzer .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - member.set_decl_type(type_def); + .get_type_index_mut() + .bind_type(member_id.into(), LuaTypeCache::DocType(type_def)); } } LuaAst::LuaTableField(field) => { let member_id = LuaMemberId::new(field.get_syntax_id(), analyzer.file_id); - let member = analyzer + analyzer .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - member.set_decl_type(type_def); + .get_type_index_mut() + .bind_type(member_id.into(), LuaTypeCache::DocType(type_def)); } _ => {} } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs index 247f4093f..c88a1aa3f 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs @@ -10,7 +10,7 @@ use crate::{ LuaDeclId, LuaDocParamInfo, LuaDocReturnInfo, LuaMemberId, LuaOperator, LuaSemanticDeclId, LuaSignatureId, LuaType, }, - InFiled, LuaOperatorMetaMethod, OperatorFunction, SignatureReturnStatus, TypeOps, + InFiled, LuaOperatorMetaMethod, LuaTypeCache, OperatorFunction, SignatureReturnStatus, TypeOps, }; use super::{ @@ -42,37 +42,18 @@ pub fn analyze_type(analyzer: &mut DocAnalyzer, tag: LuaDocTagType) -> Option<() let position = name_token.get_position(); let file_id = analyzer.file_id; let decl_id = LuaDeclId::new(file_id, position); - if let Some(decl) = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id) - { - decl.set_decl_type(type_ref.clone()); - } else { - analyzer.context.type_flow.insert( - InFiled { - file_id: analyzer.file_id, - value: name_expr.get_syntax_id(), - }, - type_ref.clone(), - ); - } + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::DocType(type_ref.clone())); } LuaVarExpr::IndexExpr(index_expr) => { let member_id = LuaMemberId::new(index_expr.get_syntax_id(), analyzer.file_id); - if let Some(member) = analyzer + analyzer .db - .get_member_index_mut() - .get_member_mut(&member_id) - { - member.set_decl_type(type_ref.clone()); - } else { - analyzer.context.type_flow.insert( - InFiled { - file_id: analyzer.file_id, - value: index_expr.get_syntax_id(), - }, - type_ref.clone(), - ); - } + .get_type_index_mut() + .bind_type(member_id.into(), LuaTypeCache::DocType(type_ref.clone())); } } } @@ -87,19 +68,21 @@ pub fn analyze_type(analyzer: &mut DocAnalyzer, tag: LuaDocTagType) -> Option<() let position = name_token.get_position(); let file_id = analyzer.file_id; let decl_id = LuaDeclId::new(file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(type_ref.clone()); + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::DocType(type_ref.clone())); } } LuaAst::LuaTableField(table_field) => { if let Some(first_type) = type_list.get(0) { let member_id = LuaMemberId::new(table_field.get_syntax_id(), analyzer.file_id); - let member = analyzer + + analyzer .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - member.set_decl_type(first_type.clone()); + .get_type_index_mut() + .bind_type(member_id.into(), LuaTypeCache::DocType(first_type.clone())); } } _ => {} @@ -148,31 +131,16 @@ pub fn analyze_param(analyzer: &mut DocAnalyzer, tag: LuaDocTagParam) -> Option< let idx = signature.find_param_idx(&name)?; signature.param_docs.insert(idx, param_info); - - let param_list = closure.get_params_list()?; - for param in param_list.get_params() { - let param_name = if let Some(name_token) = param.get_name_token() { - name_token.get_name_text().to_string() - } else { - "...".to_string() - }; - - if param_name == name { - let decl_id = LuaDeclId::new(analyzer.file_id, param.get_position()); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - - decl.set_decl_type(type_ref); - break; - } - } } else if let Some(LuaAst::LuaForRangeStat(for_range)) = analyzer.comment.get_owner() { for it_name_token in for_range.get_var_name_list() { let it_name = it_name_token.get_name_text(); if it_name == name { let decl_id = LuaDeclId::new(analyzer.file_id, it_name_token.get_position()); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(type_ref); + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::DocType(type_ref)); break; } } @@ -255,15 +223,16 @@ pub fn analyze_module(analyzer: &mut DocAnalyzer, tag: LuaDocTagModule) -> Optio if let Some(export_type) = export_type { match &owner_id { LuaSemanticDeclId::LuaDecl(decl_id) => { - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(export_type); + analyzer.db.get_type_index_mut().bind_type( + decl_id.clone().into(), + LuaTypeCache::DocType(export_type.clone()), + ); } LuaSemanticDeclId::Member(member_id) => { - let member = analyzer - .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - member.set_decl_type(export_type); + analyzer.db.get_type_index_mut().bind_type( + member_id.clone().into(), + LuaTypeCache::DocType(export_type.clone()), + ); } _ => {} } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/lua/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/lua/mod.rs index 49e324303..306a28156 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/lua/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/lua/mod.rs @@ -21,7 +21,7 @@ use crate::{ db_index::{DbIndex, LuaType}, profile::Profile, semantic::{infer_expr, LuaInferCache}, - CacheOptions, FileId, InferFailReason, LuaAnalysisPhase, LuaMemberId, LuaMemberOwner, + CacheOptions, FileId, InferFailReason, LuaAnalysisPhase, }; use super::{unresolve::UnResolve, AnalyzeContext}; @@ -90,19 +90,6 @@ fn analyze_node(analyzer: &mut LuaAnalyzer, node: LuaAst) { } } -pub fn set_owner_and_add_member( - db: &mut DbIndex, - owner: LuaMemberOwner, - member_id: LuaMemberId, -) -> Option<()> { - db.get_member_index_mut() - .set_member_owner(owner.clone(), member_id.file_id, member_id); - db.get_member_index_mut() - .add_member_to_owner(owner.clone(), member_id); - - Some(()) -} - #[derive(Debug)] struct LuaAnalyzer<'a> { file_id: FileId, diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs index 52122b14c..8f544c9dc 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs @@ -5,13 +5,14 @@ use emmylua_parser::{ use crate::{ compilation::analyzer::unresolve::{ - merge_decl_expr_type, merge_member_type, UnResolveDecl, UnResolveIterVar, UnResolveMember, + merge_type_owner_expr_type, set_owner_and_add_member, UnResolveDecl, UnResolveIterVar, + UnResolveMember, }, db_index::{LuaDeclId, LuaMemberId, LuaMemberOwner, LuaOperatorMetaMethod, LuaType}, - InferFailReason, + InferFailReason, LuaTypeCache, LuaTypeOwner, }; -use super::{set_owner_and_add_member, LuaAnalyzer}; +use super::LuaAnalyzer; pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) -> Option<()> { let name_list: Vec<_> = local_stat.get_local_name_list().collect(); @@ -22,10 +23,10 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) for local_name in name_list { let position = local_name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - if decl.get_type().is_none() { - decl.set_decl_type(LuaType::Nil); - } + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::InferType(LuaType::Nil)); } return Some(()); @@ -62,14 +63,19 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) } } - merge_decl_expr_type(analyzer.db, &mut analyzer.infer_cache, decl_id, expr_type); + merge_type_owner_expr_type( + analyzer.db, + &mut analyzer.infer_cache, + decl_id.into(), + expr_type, + ); } Err(InferFailReason::None) => { let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - if decl.get_type().is_none() { - decl.set_decl_type(LuaType::Unknown); - } + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::InferType(LuaType::Nil)); } Err(reason) => { let decl_id = LuaDeclId::new(analyzer.file_id, position); @@ -97,17 +103,19 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) let name = name_list.get(i)?; let position = name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; let ret_type = multi.get_type(i - expr_count + 1); if let Some(ty) = ret_type { - merge_decl_expr_type( + merge_type_owner_expr_type( analyzer.db, &mut analyzer.infer_cache, - decl_id, + decl_id.into(), ty.clone(), ); } else { - decl.set_decl_type(LuaType::Unknown); + analyzer.db.get_type_index_mut().bind_type( + decl_id.into(), + LuaTypeCache::InferType(LuaType::Unknown), + ); } } return Some(()); @@ -136,14 +144,10 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) let name = name_list.get(i)?; let position = name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - if decl.get_type().is_none() { - if expr_count == 0 { - decl.set_decl_type(LuaType::Unknown); - } else { - decl.set_decl_type(LuaType::Nil); - } - } + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::InferType(LuaType::Nil)); } } @@ -164,19 +168,13 @@ fn call_expr_has_effect_table_arg(expr: &LuaExpr) -> Option<()> { None } -#[derive(Debug, Clone)] -enum TypeOwner { - Decl(LuaDeclId), - Member(LuaMemberId), -} - -fn get_var_owner(analyzer: &mut LuaAnalyzer, var: LuaVarExpr) -> TypeOwner { +fn get_var_owner(analyzer: &mut LuaAnalyzer, var: LuaVarExpr) -> LuaTypeOwner { let file_id = analyzer.file_id; match var { LuaVarExpr::NameExpr(var_name) => { let position = var_name.get_position(); let decl_id = LuaDeclId::new(file_id, position); - TypeOwner::Decl(decl_id) + LuaTypeOwner::Decl(decl_id) } LuaVarExpr::IndexExpr(index_expr) => { let maybe_decl_id = LuaDeclId::new(file_id, index_expr.get_position()); @@ -186,11 +184,11 @@ fn get_var_owner(analyzer: &mut LuaAnalyzer, var: LuaVarExpr) -> TypeOwner { .get_decl(&maybe_decl_id) .is_some() { - return TypeOwner::Decl(maybe_decl_id); + return LuaTypeOwner::Decl(maybe_decl_id); } let member_id = LuaMemberId::new(index_expr.get_syntax_id(), file_id); - TypeOwner::Member(member_id) + LuaTypeOwner::Member(member_id) } } } @@ -275,22 +273,18 @@ pub fn analyze_assign_stat(analyzer: &mut LuaAnalyzer, assign_stat: LuaAssignSta Err(InferFailReason::None) => LuaType::Unknown, Err(reason) => { match type_owner { - TypeOwner::Decl(decl_id) => { - let decl = analyzer.db.get_decl_index().get_decl(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - let unresolve_decl = UnResolveDecl { - file_id: analyzer.file_id, - decl_id, - expr: expr.clone(), - ret_idx: 0, - reason, - }; + LuaTypeOwner::Decl(decl_id) => { + let unresolve_decl = UnResolveDecl { + file_id: analyzer.file_id, + decl_id, + expr: expr.clone(), + ret_idx: 0, + reason, + }; - analyzer.add_unresolved(unresolve_decl.into()); - } + analyzer.add_unresolved(unresolve_decl.into()); } - TypeOwner::Member(member_id) => { + LuaTypeOwner::Member(member_id) => { let unresolve_member = UnResolveMember { file_id: analyzer.file_id, member_id, @@ -334,7 +328,7 @@ pub fn analyze_assign_stat(analyzer: &mut LuaAnalyzer, assign_stat: LuaAssignSta let var = var_list.get(i)?; let type_owner = get_var_owner(analyzer, var.clone()); set_index_expr_owner(analyzer, var.clone()); - merge_type_owner_and_expr( + merge_type_owner_and_unresolve_expr( analyzer, type_owner, last_expr.clone(), @@ -353,7 +347,7 @@ pub fn analyze_assign_stat(analyzer: &mut LuaAnalyzer, assign_stat: LuaAssignSta fn merge_type_owner_and_expr_type( analyzer: &mut LuaAnalyzer, - type_owner: TypeOwner, + type_owner: LuaTypeOwner, expr_type: &LuaType, idx: usize, ) -> Option<()> { @@ -362,55 +356,35 @@ fn merge_type_owner_and_expr_type( expr_type = multi.get_type(idx).unwrap_or(&LuaType::Nil).clone(); } - match type_owner { - TypeOwner::Decl(decl_id) => { - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - decl.set_decl_type(expr_type); - } else { - merge_decl_expr_type(analyzer.db, &mut analyzer.infer_cache, decl_id, expr_type); - } - } - TypeOwner::Member(member_id) => { - let member = analyzer - .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - if member.get_option_decl_type().is_none() { - member.set_decl_type(expr_type); - } else { - merge_member_type(analyzer.db, &mut analyzer.infer_cache, member_id, expr_type); - } - } - } + merge_type_owner_expr_type( + analyzer.db, + &mut analyzer.infer_cache, + type_owner, + expr_type, + ); Some(()) } -fn merge_type_owner_and_expr( +fn merge_type_owner_and_unresolve_expr( analyzer: &mut LuaAnalyzer, - type_owner: TypeOwner, + type_owner: LuaTypeOwner, expr: LuaExpr, idx: usize, ) -> Option<()> { match type_owner { - TypeOwner::Decl(decl_id) => { - let decl = analyzer.db.get_decl_index().get_decl(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - let unresolve_decl = UnResolveDecl { - file_id: analyzer.file_id, - decl_id, - expr: expr.clone(), - ret_idx: idx, - reason: InferFailReason::UnResolveExpr(expr), - }; + LuaTypeOwner::Decl(decl_id) => { + let unresolve_decl = UnResolveDecl { + file_id: analyzer.file_id, + decl_id, + expr: expr.clone(), + ret_idx: idx, + reason: InferFailReason::UnResolveExpr(expr), + }; - analyzer.add_unresolved(unresolve_decl.into()); - } + analyzer.add_unresolved(unresolve_decl.into()); } - TypeOwner::Member(member_id) => { + LuaTypeOwner::Member(member_id) => { let unresolve_member = UnResolveMember { file_id: analyzer.file_id, member_id, @@ -476,15 +450,14 @@ pub fn analyze_for_range_stat( for var_name in var_name_list { let position = var_name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - let ret_type = multi_return - .get_type(idx) - .unwrap_or(&LuaType::Unknown) - .clone(); - decl.set_decl_type(ret_type); - } + let ret_type = multi_return + .get_type(idx) + .unwrap_or(&LuaType::Unknown) + .clone(); + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::InferType(ret_type)); idx += 1; } return Some(()); @@ -492,11 +465,10 @@ pub fn analyze_for_range_stat( for var_name in var_name_list { let position = var_name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - decl.set_decl_type(LuaType::Unknown); - } + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::InferType(LuaType::Unknown)); } return Some(()); } @@ -505,11 +477,10 @@ pub fn analyze_for_range_stat( for var_name in var_name_list { let position = var_name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - decl.set_decl_type(LuaType::Unknown); - } + analyzer + .db + .get_type_index_mut() + .bind_type(decl_id.into(), LuaTypeCache::InferType(LuaType::Unknown)); } return Some(()); } @@ -518,18 +489,14 @@ pub fn analyze_for_range_stat( for var_name in var_name_list { let position = var_name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - let unresolved = UnResolveIterVar { - file_id: analyzer.file_id, - decl_id, - iter_expr: first_iter_expr.clone(), - ret_idx: idx, - reason: reason.clone(), - }; - analyzer.add_unresolved(unresolved.into()); - } + let unresolved = UnResolveIterVar { + file_id: analyzer.file_id, + decl_id, + iter_expr: first_iter_expr.clone(), + ret_idx: idx, + reason: reason.clone(), + }; + analyzer.add_unresolved(unresolved.into()); idx += 1; } } @@ -544,20 +511,10 @@ pub fn analyze_func_stat(analyzer: &mut LuaAnalyzer, func_stat: LuaFuncStat) -> let signature_type = analyzer.infer_expr(&closure.clone().into()).ok()?; let type_owner = get_var_owner(analyzer, func_name.clone()); set_index_expr_owner(analyzer, func_name.clone()); - match type_owner { - TypeOwner::Decl(decl_id) => { - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(signature_type); - } - TypeOwner::Member(member_id) => { - let member = analyzer - .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - - member.set_decl_type(signature_type); - } - } + analyzer + .db + .get_type_index_mut() + .bind_type(type_owner, LuaTypeCache::InferType(signature_type.clone())); Some(()) } @@ -571,8 +528,10 @@ pub fn analyze_local_func_stat( let signature_type = analyzer.infer_expr(&closure.clone().into()).ok()?; let position = func_name.get_position(); let decl_id = LuaDeclId::new(analyzer.file_id, position); - let decl = analyzer.db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(signature_type); + analyzer.db.get_type_index_mut().bind_type( + decl_id.into(), + LuaTypeCache::InferType(signature_type.clone()), + ); Some(()) } @@ -599,31 +558,19 @@ pub fn analyze_table_field(analyzer: &mut LuaAnalyzer, field: LuaTableField) -> } }; - let member = analyzer - .db - .get_member_index_mut() - .get_member_mut(&member_id)?; - - match member.get_option_decl_type() { - Some(_) => { - merge_member_type( - analyzer.db, - &mut analyzer.infer_cache, - member_id, - value_type, - ); - } - None => { - member.set_decl_type(value_type); - } - } + merge_type_owner_expr_type( + analyzer.db, + &mut analyzer.infer_cache, + member_id.into(), + value_type, + ); Some(()) } fn special_assign_pattern( analyzer: &mut LuaAnalyzer, - type_owner: TypeOwner, + type_owner: LuaTypeOwner, var: LuaVarExpr, expr: LuaExpr, ) -> Option<()> { diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/check_reason.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/check_reason.rs index 200e62995..987c92a83 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/check_reason.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/check_reason.rs @@ -2,7 +2,7 @@ use emmylua_parser::LuaAstNode; use crate::{ infer_expr, DbIndex, FileId, InFiled, InferFailReason, LuaDeclExtra, LuaDeclId, - LuaDocParamInfo, LuaDocReturnInfo, LuaInferCache, LuaSemanticDeclId, LuaType, + LuaDocParamInfo, LuaDocReturnInfo, LuaInferCache, LuaSemanticDeclId, LuaType, LuaTypeCache, SignatureReturnStatus, }; @@ -23,12 +23,16 @@ pub fn check_reach_reason( return Some(true); } - Some(decl.get_type().is_some()) + Some( + db.get_type_index() + .get_type_cache(&decl_id.clone().into()) + .is_some(), + ) } InferFailReason::UnResolveMemberType(member_id) => { let member = db.get_member_index().get_member(member_id)?; let key = member.get_key(); - let owner = member.get_owner(); + let owner = db.get_member_index().get_current_owner(member_id)?; let member_item = db.get_member_index().get_member_item(&owner, key)?; Some(member_item.resolve_type(db).is_ok()) } @@ -87,23 +91,22 @@ pub fn resolve_as_any( return set_param_decl_type(db, decl_id, LuaType::Any); } - if decl.get_type().is_none() { - decl.set_decl_type(LuaType::Any); - } + db.get_type_index_mut().bind_type( + decl_id.clone().into(), + LuaTypeCache::InferType(LuaType::Any), + ); } InferFailReason::UnResolveMemberType(member_id) => { let member = db.get_member_index().get_member(member_id)?; let key = member.get_key(); - let owner = member.get_owner(); + let owner = db.get_member_index().get_current_owner(&member_id)?; let member_item = db.get_member_index().get_member_item(&owner, key)?; let opt_type = member_item.resolve_type(db).ok(); if opt_type.is_none() { let semantic_member_id = member_item.resolve_semantic_decl(db)?; if let LuaSemanticDeclId::Member(member_id) = semantic_member_id { - let member = db.get_member_index_mut().get_member_mut(&member_id)?; - if member.get_option_decl_type().is_none() { - member.set_decl_type(LuaType::Any); - } + db.get_type_index_mut() + .bind_type(member_id.into(), LuaTypeCache::InferType(LuaType::Any)); } } } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs index 865e1b15c..e77544fb9 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs @@ -1,81 +1,56 @@ use rowan::TextRange; use crate::{ - compilation::analyzer::lua::set_owner_and_add_member, - db_index::{DbIndex, LuaDeclId, LuaMemberId, LuaMemberOwner, LuaType, LuaTypeDeclId}, - InFiled, LuaInferCache, TypeOps, + db_index::{DbIndex, LuaMemberOwner, LuaType, LuaTypeDeclId}, + InFiled, LuaInferCache, LuaMemberId, LuaTypeCache, LuaTypeOwner, }; -pub fn merge_decl_expr_type( +use super::migrate_member::migrate_member_when_type_resolve; + +pub fn merge_type_owner_expr_type( db: &mut DbIndex, cache: &mut LuaInferCache, - decl_id: LuaDeclId, + type_owner: LuaTypeOwner, expr_type: LuaType, ) -> Option<()> { - let decl = db.get_decl_index().get_decl(&decl_id)?; - let decl_type = decl.get_type(); - if decl_type.is_none() { - let decl = db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(expr_type); + let decl_type_cache = db.get_type_index().get_type_cache(&type_owner); + + if decl_type_cache.is_none() { + db.get_type_index_mut() + .bind_type(type_owner.clone(), LuaTypeCache::InferType(expr_type)); } else { - let decl_type = decl_type.unwrap(); - let new_type = merge_type(db, cache, decl_type.clone(), expr_type); - let decl = db.get_decl_index_mut().get_decl_mut(&decl_id)?; - decl.set_decl_type(new_type); + let decl_type = decl_type_cache.unwrap().as_type(); + merge_def_type(db, cache, decl_type.clone(), expr_type); } - Some(()) -} - -pub fn merge_member_type( - db: &mut DbIndex, - cache: &mut LuaInferCache, - member_id: LuaMemberId, - expr_type: LuaType, -) -> Option<()> { - let member = db.get_member_index().get_member(&member_id)?; - let member_type = member.get_decl_type(); - let new_type = merge_type(db, cache, member_type.clone(), expr_type); - let member = db.get_member_index_mut().get_member_mut(&member_id)?; - member.set_decl_type(new_type); + match &type_owner { + LuaTypeOwner::Member(member_id) => { + migrate_member_when_type_resolve(db, member_id.clone()); + } + _ => {} + } Some(()) } -fn merge_type( +fn merge_def_type( db: &mut DbIndex, cache: &mut LuaInferCache, decl_type: LuaType, expr_type: LuaType, -) -> LuaType { +) { match &decl_type { - LuaType::Unknown => expr_type, - LuaType::Nil => TypeOps::Union.apply(&expr_type, &LuaType::Nil), - LuaType::Def(def) => { - match expr_type { - LuaType::TableConst(in_filed_range) => { - merge_def_type_with_table(db, cache, def.clone(), in_filed_range); - } - LuaType::Instance(instance) => { - let base_ref = instance.get_base(); - match base_ref { - LuaType::TableConst(in_filed_range) => { - merge_def_type_with_table( - db, - cache, - def.clone(), - in_filed_range.clone(), - ); - } - _ => {} - } - } - _ => {} + LuaType::Def(def) => match &expr_type { + LuaType::TableConst(in_filed_range) => { + merge_def_type_with_table(db, cache, def.clone(), in_filed_range.clone()); } - - return LuaType::Def(def.clone()); - } - _ => decl_type, + LuaType::Instance(instance) => { + let base_ref = instance.get_base(); + merge_def_type(db, cache, base_ref.clone(), expr_type); + } + _ => {} + }, + _ => {} } } @@ -99,3 +74,16 @@ fn merge_def_type_with_table( Some(()) } + +pub fn set_owner_and_add_member( + db: &mut DbIndex, + owner: LuaMemberOwner, + member_id: LuaMemberId, +) -> Option<()> { + db.get_member_index_mut() + .set_member_owner(owner.clone(), member_id.file_id, member_id); + db.get_member_index_mut() + .add_member_to_owner(owner.clone(), member_id); + + Some(()) +} diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs new file mode 100644 index 000000000..eef0951f9 --- /dev/null +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs @@ -0,0 +1,67 @@ +use crate::{DbIndex, LuaMemberId, LuaMemberIndex, LuaMemberKey, LuaMemberOwner, LuaType}; + +pub fn migrate_member_when_type_resolve(db: &DbIndex, member_id: LuaMemberId) -> Option<()> { + + Some(()) +} + +// pub fn migrate_members( +// db: &mut DbIndex, +// member_id: LuaMemberId, +// ) -> Option<()> { +// let member_index= db.get_member_index_mut(); +// let member_owner = get_owner_id(member_index, member_id)?; +// let member_item = member_index.get_member_item(&owner, key)?; +// let resolve_member_id = member_item.resolve_member_id(member_index)?; +// if new_add_member_id != resolve_member_id { +// return None; +// } + +// let member_ids = member_item.get_member_ids(); +// for need_migrate_id in member_ids { +// if need_migrate_id == new_add_member_id { +// continue; +// } + +// if let Some(need_migrate_owner) = get_owner_id(member_index, need_migrate_id) { +// if member_owner == need_migrate_owner { +// continue; +// } +// migrate_member_to(member_index, &member_owner, &need_migrate_owner); +// } +// } + +// Some(()) +// } + +// fn get_owner_id( +// member_index: &mut LuaMemberIndex, +// member_id: LuaMemberId, +// ) -> Option { +// let member = member_index.get_member(&member_id)?; +// let typ = member.get_decl_type(); +// match typ { +// LuaType::Ref(type_id) => Some(LuaMemberOwner::Type(type_id)), +// LuaType::TableConst(id) => Some(LuaMemberOwner::Element(id)), +// _ => None, +// } +// } + +// fn migrate_member_to( +// member_index: &mut LuaMemberIndex, +// owner: &LuaMemberOwner, +// need_migrate_owner: &LuaMemberOwner, +// ) -> Option<()> { +// let member_ids = member_index +// .get_members(need_migrate_owner)? +// .iter() +// .map(|member| member.get_id()) +// .collect::>(); + +// for member_id in member_ids { +// member_index.set_member_owner(owner.clone(), member_id.file_id, member_id); +// member_index.add_member_to_owner(owner.clone(), member_id); +// } + +// Some(()) +// } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs index 53b50fdcc..aa5f71446 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs @@ -3,6 +3,7 @@ mod infer_manager; mod merge_type; mod resolve; mod resolve_closure; +mod migrate_member; use crate::{ db_index::{DbIndex, LuaDeclId, LuaMemberId, LuaSignatureId}, @@ -14,7 +15,7 @@ use emmylua_parser::{ LuaAssignStat, LuaCallExpr, LuaExpr, LuaFuncStat, LuaTableExpr, LuaTableField, }; use infer_manager::InferCacheManager; -pub use merge_type::{merge_decl_expr_type, merge_member_type}; +pub use merge_type::{merge_type_owner_expr_type, set_owner_and_add_member}; use resolve::{ try_resolve_decl, try_resolve_iter_var, try_resolve_member, try_resolve_module, try_resolve_module_ref, try_resolve_return_point, try_resolve_table_field, diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs index f5a7b2bf8..66732a335 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs @@ -1,17 +1,18 @@ -use emmylua_parser::{LuaAstNode, LuaExpr, LuaLocalStat}; +use std::ops::Deref; + +use emmylua_parser::{LuaAstNode, LuaExpr, LuaLocalStat, LuaTableExpr}; use crate::{ compilation::analyzer::lua::analyze_return_point, db_index::{DbIndex, LuaMemberOwner, LuaType}, semantic::{infer_expr, LuaInferCache}, InFiled, InferFailReason, LuaDeclId, LuaMember, LuaMemberId, LuaMemberKey, LuaSemanticDeclId, - SignatureReturnStatus, + LuaTypeCache, SignatureReturnStatus, }; use super::{ - check_reason::check_reach_reason, merge_decl_expr_type, merge_member_type, UnResolveDecl, - UnResolveIterVar, UnResolveMember, UnResolveModule, UnResolveModuleRef, UnResolveReturn, - UnResolveTableField, + check_reason::check_reach_reason, merge_type_owner_expr_type, UnResolveDecl, UnResolveIterVar, + UnResolveMember, UnResolveModule, UnResolveModuleRef, UnResolveReturn, UnResolveTableField, }; pub fn try_resolve_decl( @@ -40,7 +41,7 @@ pub fn try_resolve_decl( _ => expr_type, }; - merge_decl_expr_type(db, cache, decl_id, expr_type); + merge_type_owner_expr_type(db, cache, decl_id.into(), expr_type); Some(true) } @@ -106,7 +107,7 @@ pub fn try_resolve_member( }; let member_id = unresolve_member.member_id; - merge_member_type(db, cache, member_id, expr_type); + merge_type_owner_expr_type(db, cache, member_id.into(), expr_type); } Some(true) } @@ -162,31 +163,41 @@ pub fn try_resolve_table_field( let decl_type = field.get_value_expr().map_or(None, |expr| { let expr_type = infer_expr(db, cache, expr).ok()?; Some(expr_type) - }); + })?; let member_id = LuaMemberId::new(field.get_syntax_id(), file_id); - let member = LuaMember::new( - member_id, - member_key, - unresolve_table_field.decl_feature, - decl_type, - ); + let member = LuaMember::new(member_id, member_key, unresolve_table_field.decl_feature, None); db.get_member_index_mut().add_member(owner_id, member); + db.get_type_index_mut().bind_type( + member_id.clone().into(), + LuaTypeCache::InferType(decl_type.clone()), + ); - // 如果是`Def`则更新 + merge_table_field_to_def(db, cache, table_expr, member_id); + Some(true) +} + +fn merge_table_field_to_def( + db: &mut DbIndex, + cache: &mut LuaInferCache, + table_expr: LuaTableExpr, + member_id: LuaMemberId, +) -> Option<()> { + let file_id = cache.get_file_id(); let local_name = table_expr .get_parent::()? .get_value_local_name(LuaExpr::TableExpr(table_expr.clone()))?; let decl_id = LuaDeclId::new(file_id, local_name.get_position()); - let decl_type = db.get_decl_index_mut().get_decl_mut(&decl_id)?.get_type()?; - if let LuaType::Def(id) = decl_type { + let type_cache = db.get_type_index().get_type_cache(&decl_id.into())?; + if let LuaType::Def(id) = type_cache.deref() { let owner = LuaMemberOwner::Type(id.clone()); db.get_member_index_mut() .set_member_owner(owner.clone(), member_id.file_id, member_id); db.get_member_index_mut() .add_member_to_owner(owner.clone(), member_id); } - Some(true) + + Some(()) } pub fn try_resolve_module( @@ -264,7 +275,7 @@ pub fn try_resolve_iter_var( .get_type(iter_var.ret_idx) .unwrap_or(&LuaType::Nil); let decl_id = iter_var.decl_id; - merge_decl_expr_type(db, cache, decl_id, iter_type.clone()); + merge_type_owner_expr_type(db, cache, decl_id.into(), iter_type.clone()); Some(true) } @@ -278,12 +289,14 @@ pub fn try_resolve_module_ref( let export_type = module.export_type.clone()?; match &module_ref.owner_id { LuaSemanticDeclId::LuaDecl(decl_id) => { - let decl = db.get_decl_index_mut().get_decl_mut(decl_id)?; - decl.set_decl_type(export_type); + db.get_type_index_mut() + .bind_type(decl_id.clone().into(), LuaTypeCache::InferType(export_type)); } LuaSemanticDeclId::Member(member_id) => { - let member = db.get_member_index_mut().get_member_mut(member_id)?; - member.set_decl_type(export_type); + db.get_type_index_mut().bind_type( + member_id.clone().into(), + LuaTypeCache::InferType(export_type), + ); } _ => {} } diff --git a/crates/emmylua_code_analysis/src/db_index/declaration/decl.rs b/crates/emmylua_code_analysis/src/db_index/declaration/decl.rs index 28c4f99e3..1eb87dab5 100644 --- a/crates/emmylua_code_analysis/src/db_index/declaration/decl.rs +++ b/crates/emmylua_code_analysis/src/db_index/declaration/decl.rs @@ -1,13 +1,11 @@ -use std::fmt; - -use crate::{db_index::LuaType, FileId}; +use crate::FileId; use crate::{LuaMemberId, LuaSignatureId}; use emmylua_parser::{LuaKind, LuaSyntaxId, LuaSyntaxKind}; use rowan::{TextRange, TextSize}; -use serde::de::{self, Visitor}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; use smol_str::SmolStr; +use super::decl_id::LuaDeclId; + #[derive(Eq, PartialEq, Hash, Debug, Clone)] pub struct LuaDecl { name: SmolStr, @@ -21,7 +19,6 @@ pub struct LuaDecl { pub enum LuaDeclExtra { Local { kind: LuaKind, - decl_type: Option, attrib: Option, }, Param { @@ -31,7 +28,6 @@ pub enum LuaDeclExtra { }, Global { kind: LuaKind, - decl_type: Option, }, } @@ -72,22 +68,6 @@ impl LuaDecl { self.range } - pub fn get_type(&self) -> Option<&LuaType> { - match &self.extra { - LuaDeclExtra::Local { decl_type, .. } => decl_type.as_ref(), - LuaDeclExtra::Global { decl_type, .. } => decl_type.as_ref(), - LuaDeclExtra::Param { .. } => None, - } - } - - pub(crate) fn set_decl_type(&mut self, decl_type: LuaType) { - match &mut self.extra { - LuaDeclExtra::Local { decl_type: dt, .. } => *dt = Some(decl_type), - LuaDeclExtra::Global { decl_type: dt, .. } => *dt = Some(decl_type), - LuaDeclExtra::Param { .. } => {} - } - } - pub fn get_syntax_id(&self) -> LuaSyntaxId { match self.extra { LuaDeclExtra::Local { kind, .. } => LuaSyntaxId::new(kind, self.range), @@ -118,70 +98,6 @@ impl LuaDecl { } } -#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)] -pub struct LuaDeclId { - pub file_id: FileId, - pub position: TextSize, -} - -impl Serialize for LuaDeclId { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - let value = format!("{}|{}", self.file_id.id, u32::from(self.position)); - serializer.serialize_str(&value) - } -} - -impl<'de> Deserialize<'de> for LuaDeclId { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - struct LuaDeclIdVisitor; - - impl<'de> Visitor<'de> for LuaDeclIdVisitor { - type Value = LuaDeclId; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a string with format 'file_id:position'") - } - - fn visit_str(self, value: &str) -> Result - where - E: de::Error, - { - let parts: Vec<&str> = value.split('|').collect(); - if parts.len() != 2 { - return Err(E::custom("expected format 'file_id:position'")); - } - - let file_id = FileId { - id: parts[0] - .parse() - .map_err(|e| E::custom(format!("invalid file_id: {}", e)))?, - }; - let position = TextSize::new( - parts[1] - .parse() - .map_err(|e| E::custom(format!("invalid position: {}", e)))?, - ); - - Ok(LuaDeclId { file_id, position }) - } - } - - deserializer.deserialize_str(LuaDeclIdVisitor) - } -} - -impl LuaDeclId { - pub fn new(file_id: FileId, position: TextSize) -> Self { - Self { file_id, position } - } -} - #[derive(Eq, PartialEq, Hash, Debug, Clone)] pub enum LocalAttribute { Const, diff --git a/crates/emmylua_code_analysis/src/db_index/declaration/decl_id.rs b/crates/emmylua_code_analysis/src/db_index/declaration/decl_id.rs new file mode 100644 index 000000000..97b4a4a95 --- /dev/null +++ b/crates/emmylua_code_analysis/src/db_index/declaration/decl_id.rs @@ -0,0 +1,73 @@ +use std::fmt; + +use rowan::TextSize; +use serde::{ + de::{self, Visitor}, + Deserialize, Deserializer, Serialize, Serializer, +}; + +use crate::FileId; + +#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)] +pub struct LuaDeclId { + pub file_id: FileId, + pub position: TextSize, +} + +impl LuaDeclId { + pub fn new(file_id: FileId, position: TextSize) -> Self { + Self { file_id, position } + } +} + +impl Serialize for LuaDeclId { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let value = format!("{}|{}", self.file_id.id, u32::from(self.position)); + serializer.serialize_str(&value) + } +} + +impl<'de> Deserialize<'de> for LuaDeclId { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct LuaDeclIdVisitor; + + impl<'de> Visitor<'de> for LuaDeclIdVisitor { + type Value = LuaDeclId; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a string with format 'file_id:position'") + } + + fn visit_str(self, value: &str) -> Result + where + E: de::Error, + { + let parts: Vec<&str> = value.split('|').collect(); + if parts.len() != 2 { + return Err(E::custom("expected format 'file_id:position'")); + } + + let file_id = FileId { + id: parts[0] + .parse() + .map_err(|e| E::custom(format!("invalid file_id: {}", e)))?, + }; + let position = TextSize::new( + parts[1] + .parse() + .map_err(|e| E::custom(format!("invalid position: {}", e)))?, + ); + + Ok(LuaDeclId { file_id, position }) + } + } + + deserializer.deserialize_str(LuaDeclIdVisitor) + } +} diff --git a/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs b/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs index 796ae869e..ef531d068 100644 --- a/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs +++ b/crates/emmylua_code_analysis/src/db_index/declaration/decl_tree.rs @@ -1,11 +1,8 @@ use std::collections::HashMap; -use super::{decl, scope}; -use crate::{ - db_index::{DbIndex, LuaMemberId, LuaMemberKey}, - FileId, -}; -use decl::{LuaDecl, LuaDeclId}; +use super::{decl, scope, LuaDeclId}; +use crate::{db_index::LuaMemberId, FileId}; +use decl::LuaDecl; use emmylua_parser::{ LuaAstNode, LuaChunk, LuaExpr, LuaFuncStat, LuaNameExpr, LuaSyntaxId, LuaSyntaxKind, LuaVarExpr, }; @@ -239,11 +236,7 @@ impl LuaDeclarationTree { } } - pub fn find_self_decl( - &self, - db: &DbIndex, - name_expr: LuaNameExpr, - ) -> Option { + pub fn find_self_decl(&self, name_expr: LuaNameExpr) -> Option { let position = name_expr.get_position(); let scope = self.find_scope(position)?; let mut result: Option = None; @@ -263,7 +256,7 @@ impl LuaDeclarationTree { if scope.get_kind() == LuaScopeKind::MethodStat { let range = scope.get_range(); let syntax_id = LuaSyntaxId::new(LuaSyntaxKind::FuncStat.into(), range); - let id = self.find_self_decl_id(db, &root, syntax_id); + let id = self.find_self_decl_id(&root, syntax_id); if id.is_some() { result = id; return true; @@ -280,7 +273,6 @@ impl LuaDeclarationTree { fn find_self_decl_id( &self, - db: &DbIndex, root: &LuaChunk, syntax_id: LuaSyntaxId, ) -> Option { @@ -297,11 +289,6 @@ impl LuaDeclarationTree { if let Some(decl) = decl { return Some(LuaDeclOrMemberId::Decl(decl.get_id())); } - - let id = db - .get_decl_index() - .get_global_decl_id(&LuaMemberKey::Name(name.into()))?; - return Some(LuaDeclOrMemberId::Decl(id)); } LuaExpr::IndexExpr(prefx_index) => { let member_id = LuaMemberId::new(prefx_index.get_syntax_id(), self.file_id); diff --git a/crates/emmylua_code_analysis/src/db_index/declaration/mod.rs b/crates/emmylua_code_analysis/src/db_index/declaration/mod.rs index 820bf6109..652e323f1 100644 --- a/crates/emmylua_code_analysis/src/db_index/declaration/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/declaration/mod.rs @@ -1,40 +1,31 @@ mod decl; +mod decl_id; mod decl_tree; mod scope; pub use decl::LuaDeclExtra; -pub use decl::{LocalAttribute, LuaDecl, LuaDeclId}; +pub use decl::{LocalAttribute, LuaDecl}; +pub use decl_id::LuaDeclId; pub use decl_tree::{LuaDeclOrMemberId, LuaDeclarationTree}; pub use scope::{LuaScope, LuaScopeId, LuaScopeKind, ScopeOrDeclId}; -use smol_str::SmolStr; use std::collections::HashMap; use crate::FileId; -use super::{traits::LuaIndex, LuaMemberKey}; +use super::traits::LuaIndex; #[derive(Debug)] pub struct LuaDeclIndex { decl_trees: HashMap, - global_decl: HashMap>, } impl LuaDeclIndex { pub fn new() -> Self { Self { decl_trees: HashMap::new(), - global_decl: HashMap::new(), } } - pub fn add_global_decl(&mut self, name: &str, decl_id: LuaDeclId) { - let key = SmolStr::new(name); - self.global_decl - .entry(LuaMemberKey::Name(key)) - .or_insert_with(Vec::new) - .push(decl_id); - } - pub fn add_decl_tree(&mut self, tree: LuaDeclarationTree) { self.decl_trees.insert(tree.file_id(), tree); } @@ -52,62 +43,14 @@ impl LuaDeclIndex { let tree = self.decl_trees.get_mut(&decl_id.file_id)?; tree.get_decl_mut(*decl_id) } - - pub fn get_global_decls(&self) -> Vec { - let mut decls = Vec::new(); - for (_, v) in &self.global_decl { - decls.extend(v); - } - - decls - } - - pub fn get_global_decls_by_name(&self, name: &str) -> Vec { - let key = SmolStr::new(name); - self.global_decl - .get(&LuaMemberKey::Name(key)) - .cloned() - .unwrap_or_default() - } - - pub fn get_global_decl_id(&self, key: &LuaMemberKey) -> Option { - let decls = self.global_decl.get(key)?; - if decls.len() == 1 { - return Some(decls[0]); - } - - let mut valid_decl_id = None; - for decl_id in decls { - let decl = self.get_decl(decl_id)?; - let ty = decl.get_type(); - if let Some(ty) = ty { - if ty.is_def() || ty.is_ref() { - return Some(*decl_id); - } - - if valid_decl_id.is_none() { - valid_decl_id = Some(*decl_id); - } else if ty.is_table() { - valid_decl_id = Some(*decl_id); - } - } - } - - valid_decl_id - } } impl LuaIndex for LuaDeclIndex { fn remove(&mut self, file_id: FileId) { self.decl_trees.remove(&file_id); - self.global_decl.retain(|_, v| { - v.retain(|decl_id| decl_id.file_id != file_id); - !v.is_empty() - }); } fn clear(&mut self) { self.decl_trees.clear(); - self.global_decl.clear(); } } diff --git a/crates/emmylua_code_analysis/src/db_index/declaration/scope.rs b/crates/emmylua_code_analysis/src/db_index/declaration/scope.rs index 4845122c0..e2aee12af 100644 --- a/crates/emmylua_code_analysis/src/db_index/declaration/scope.rs +++ b/crates/emmylua_code_analysis/src/db_index/declaration/scope.rs @@ -2,7 +2,7 @@ use rowan::{TextRange, TextSize}; use crate::FileId; -use super::decl::LuaDeclId; +use super::LuaDeclId; #[derive(Debug, Eq, PartialEq, Hash, Clone, Copy)] pub enum LuaScopeKind { diff --git a/crates/emmylua_code_analysis/src/db_index/global/global_id.rs b/crates/emmylua_code_analysis/src/db_index/global/global_id.rs new file mode 100644 index 000000000..cd00d5605 --- /dev/null +++ b/crates/emmylua_code_analysis/src/db_index/global/global_id.rs @@ -0,0 +1,15 @@ +use internment::ArcIntern; +use smol_str::SmolStr; + +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct GlobalId(pub ArcIntern); + +impl GlobalId { + pub fn new(name: &str) -> Self { + Self(ArcIntern::new(SmolStr::new(name))) + } + + pub fn get_name(&self) -> &str { + self.0.as_ref() + } +} diff --git a/crates/emmylua_code_analysis/src/db_index/global/mod.rs b/crates/emmylua_code_analysis/src/db_index/global/mod.rs new file mode 100644 index 000000000..04240262e --- /dev/null +++ b/crates/emmylua_code_analysis/src/db_index/global/mod.rs @@ -0,0 +1,57 @@ +mod global_id; + +use std::collections::HashMap; + +pub use global_id::GlobalId; + +use crate::FileId; + +use super::{LuaDeclId, LuaIndex}; + +#[derive(Debug)] +pub struct LuaGlobalIndex { + global_decl: HashMap>, +} + +impl LuaGlobalIndex { + pub fn new() -> Self { + Self { + global_decl: HashMap::new(), + } + } + + pub fn add_global_decl(&mut self, name: &str, decl_id: LuaDeclId) { + let id = GlobalId::new(name); + self.global_decl + .entry(id) + .or_insert_with(Vec::new) + .push(decl_id); + } + + pub fn get_all_global_decl_ids(&self) -> Vec { + let mut decls = Vec::new(); + for (_, v) in &self.global_decl { + decls.extend(v); + } + + decls + } + + pub fn get_global_decl_ids(&self, name: &str) -> Option<&Vec> { + let id = GlobalId::new(name); + self.global_decl.get(&id) + } +} + +impl LuaIndex for LuaGlobalIndex { + fn remove(&mut self, file_id: FileId) { + self.global_decl.retain(|_, v| { + v.retain(|decl_id| decl_id.file_id != file_id); + !v.is_empty() + }); + } + + fn clear(&mut self) { + self.global_decl.clear(); + } +} diff --git a/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs b/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs index 09451c987..8bd3ad292 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/lua_member.rs @@ -1,22 +1,17 @@ use emmylua_parser::{LuaDocFieldKey, LuaIndexKey, LuaSyntaxId, LuaSyntaxKind}; -use internment::ArcIntern; -use rowan::TextRange; +use rowan::{TextRange, TextSize}; use serde::{Deserialize, Serialize}; use smol_str::SmolStr; -use crate::{ - db_index::{LuaType, LuaTypeDeclId}, - FileId, InFiled, -}; - use super::lua_member_feature::LuaMemberFeature; +use crate::{FileId, GlobalId}; #[derive(Debug)] pub struct LuaMember { member_id: LuaMemberId, key: LuaMemberKey, feature: LuaMemberFeature, - decl_type: Option, + global_id: Option, } impl LuaMember { @@ -24,20 +19,16 @@ impl LuaMember { member_id: LuaMemberId, key: LuaMemberKey, decl_feature: LuaMemberFeature, - decl_type: Option, + global_path: Option, ) -> Self { Self { member_id, key, feature: decl_feature, - decl_type, + global_id: global_path, } } - pub fn get_owner(&self) -> LuaMemberOwner { - todo!() - } - pub fn get_key(&self) -> &LuaMemberKey { &self.key } @@ -60,20 +51,6 @@ impl LuaMember { *self.member_id.get_syntax_id() } - // todo clean all the usage - pub fn get_decl_type(&self) -> LuaType { - self.decl_type.clone().unwrap_or(LuaType::Unknown) - } - - // workaround - pub(crate) fn get_option_decl_type(&self) -> Option { - self.decl_type.clone() - } - - pub(crate) fn set_decl_type(&mut self, decl_type: LuaType) { - self.decl_type = Some(decl_type); - } - pub fn get_id(&self) -> LuaMemberId { self.member_id } @@ -85,6 +62,10 @@ impl LuaMember { pub fn get_feature(&self) -> LuaMemberFeature { self.feature } + + pub fn get_global_id(&self) -> Option<&GlobalId> { + self.global_id.as_ref() + } } #[derive(Debug, Eq, PartialEq, Clone, Copy, Hash, Serialize, Deserialize)] @@ -101,40 +82,9 @@ impl LuaMemberId { pub fn get_syntax_id(&self) -> &LuaSyntaxId { &self.id } -} - -#[derive(Debug, Hash, PartialEq, Eq, Clone)] -pub enum LuaMemberOwner { - LocalUnknown, - Type(LuaTypeDeclId), - Element(InFiled), - GlobalPath(ArcIntern) -} - -impl LuaMemberOwner { - pub fn get_type_id(&self) -> Option<&LuaTypeDeclId> { - match self { - LuaMemberOwner::Type(id) => Some(id), - _ => None, - } - } - - pub fn get_element_range(&self) -> Option<&InFiled> { - match self { - LuaMemberOwner::Element(range) => Some(range), - _ => None, - } - } - - pub fn get_path(&self) -> Option<&ArcIntern> { - match self { - LuaMemberOwner::GlobalPath(path) => Some(path), - _ => None, - } - } - pub fn is_unknown(&self) -> bool { - matches!(self, LuaMemberOwner::LocalUnknown) + pub fn get_position(&self) -> TextSize { + self.id.get_range().start() } } diff --git a/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs b/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs index 92d3589d1..fa9393284 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs @@ -1,6 +1,6 @@ use crate::{DbIndex, InferFailReason, LuaSemanticDeclId, LuaType, TypeOps}; -use super::{LuaMemberId, LuaMemberIndex}; +use super::LuaMemberId; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum LuaMemberIndexItem { @@ -17,10 +17,6 @@ impl LuaMemberIndexItem { resolve_member_semantic_id(db, &self) } - pub(super) fn resolve_member_id(&self, member_index: &LuaMemberIndex) -> Option { - resolve_member_id(member_index, &self) - } - pub fn get_member_ids(&self) -> Vec { match self { LuaMemberIndexItem::One(member_id) => vec![*member_id], @@ -35,13 +31,11 @@ fn resolve_member_type( ) -> Result { match member_item { LuaMemberIndexItem::One(member_id) => { - let member = db - .get_member_index() - .get_member(&member_id) - .ok_or(InferFailReason::None)?; - let member_type = member.get_option_decl_type(); - return match member_type { - Some(typ) => Ok(typ), + let member_type_cache = db + .get_type_index() + .get_type_cache(&member_id.clone().into()); + return match member_type_cache { + Some(cache) => Ok(cache.as_type().clone()), None => Err(InferFailReason::UnResolveMemberType(*member_id)), }; } @@ -71,9 +65,10 @@ fn resolve_member_type( for member in members { typ = TypeOps::Union.apply( &typ, - &member - .get_option_decl_type() - .ok_or(InferFailReason::UnResolveMemberType(member.get_id()))?, + &db.get_type_index() + .get_type_cache(&member.get_id().into()) + .ok_or(InferFailReason::UnResolveMemberType(member.get_id()))? + .as_type(), ); } Ok(typ) @@ -85,9 +80,10 @@ fn resolve_member_type( if feature.is_meta_decl() { typ = TypeOps::Union.apply( &typ, - &member - .get_option_decl_type() - .ok_or(InferFailReason::UnResolveMemberType(member.get_id()))?, + &db.get_type_index() + .get_type_cache(&member.get_id().into()) + .ok_or(InferFailReason::UnResolveMemberType(member.get_id()))? + .as_type(), ); } } @@ -100,9 +96,10 @@ fn resolve_member_type( if feature.is_file_decl() { typ = TypeOps::Union.apply( &typ, - &member - .get_option_decl_type() - .ok_or(InferFailReason::UnResolveMemberType(member.get_id()))?, + &db.get_type_index() + .get_type_cache(&member.get_id().into()) + .ok_or(InferFailReason::UnResolveMemberType(member.get_id()))? + .as_type(), ); } } @@ -113,62 +110,62 @@ fn resolve_member_type( } } -fn resolve_member_id( - member_index: &LuaMemberIndex, - member_item: &LuaMemberIndexItem, -) -> Option { - match member_item { - LuaMemberIndexItem::One(member_id) => Some(*member_id), - LuaMemberIndexItem::Many(member_ids) => { - let mut resolve_state = MemberTypeResolveState::All; - let members = member_ids - .iter() - .map(|id| member_index.get_member(id)) - .collect::>>()?; - for member in &members { - let feature = member.get_feature(); - if feature.is_meta_decl() { - resolve_state = MemberTypeResolveState::Meta; - break; - } else if feature.is_file_decl() { - resolve_state = MemberTypeResolveState::FileDecl; - } - } +// fn resolve_member_id( +// member_index: &LuaMemberIndex, +// member_item: &LuaMemberIndexItem, +// ) -> Option { +// match member_item { +// LuaMemberIndexItem::One(member_id) => Some(*member_id), +// LuaMemberIndexItem::Many(member_ids) => { +// let mut resolve_state = MemberTypeResolveState::All; +// let members = member_ids +// .iter() +// .map(|id| member_index.get_member(id)) +// .collect::>>()?; +// for member in &members { +// let feature = member.get_feature(); +// if feature.is_meta_decl() { +// resolve_state = MemberTypeResolveState::Meta; +// break; +// } else if feature.is_file_decl() { +// resolve_state = MemberTypeResolveState::FileDecl; +// } +// } - match resolve_state { - MemberTypeResolveState::All => { - for member in members { - if member.get_decl_type().is_member_owner() { - return Some(member.get_id()); - } - } +// match resolve_state { +// MemberTypeResolveState::All => { +// for member in members { +// if member.get_decl_type().is_member_owner() { +// return Some(member.get_id()); +// } +// } - None - } - MemberTypeResolveState::Meta => { - for member in &members { - let feature = member.get_feature(); - if feature.is_meta_decl() { - return Some(member.get_id()); - } - } +// None +// } +// MemberTypeResolveState::Meta => { +// for member in &members { +// let feature = member.get_feature(); +// if feature.is_meta_decl() { +// return Some(member.get_id()); +// } +// } - None - } - MemberTypeResolveState::FileDecl => { - for member in &members { - let feature = member.get_feature(); - if feature.is_file_decl() { - return Some(member.get_id()); - } - } +// None +// } +// MemberTypeResolveState::FileDecl => { +// for member in &members { +// let feature = member.get_feature(); +// if feature.is_file_decl() { +// return Some(member.get_id()); +// } +// } - None - } - } - } - } -} +// None +// } +// } +// } +// } +// } #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum MemberTypeResolveState { diff --git a/crates/emmylua_code_analysis/src/db_index/member/lua_member_owner.rs b/crates/emmylua_code_analysis/src/db_index/member/lua_member_owner.rs new file mode 100644 index 000000000..3888ca1d9 --- /dev/null +++ b/crates/emmylua_code_analysis/src/db_index/member/lua_member_owner.rs @@ -0,0 +1,70 @@ +use internment::ArcIntern; +use rowan::TextRange; +use smol_str::SmolStr; + +use crate::{GlobalId, InFiled, LuaTypeDeclId}; + +#[derive(Debug, Hash, PartialEq, Eq, Clone)] +pub enum LuaMemberOwner { + LocalUnresolve, + Type(LuaTypeDeclId), + Element(InFiled), + GlobalPath(GlobalId), +} + +impl From for LuaMemberOwner { + fn from(decl_id: LuaTypeDeclId) -> Self { + Self::Type(decl_id) + } +} + +impl From> for LuaMemberOwner { + fn from(range: InFiled) -> Self { + Self::Element(range) + } +} + +impl From for LuaMemberOwner { + fn from(path: SmolStr) -> Self { + Self::GlobalPath(GlobalId::new(&path)) + } +} + +impl From> for LuaMemberOwner { + fn from(path: ArcIntern) -> Self { + Self::GlobalPath(GlobalId(path.clone())) + } +} + +impl From for LuaMemberOwner { + fn from(global_id: GlobalId) -> Self { + Self::GlobalPath(global_id) + } +} + +impl LuaMemberOwner { + pub fn get_type_id(&self) -> Option<&LuaTypeDeclId> { + match self { + LuaMemberOwner::Type(id) => Some(id), + _ => None, + } + } + + pub fn get_element_range(&self) -> Option<&InFiled> { + match self { + LuaMemberOwner::Element(range) => Some(range), + _ => None, + } + } + + pub fn get_path(&self) -> Option<&GlobalId> { + match self { + LuaMemberOwner::GlobalPath(path) => Some(path), + _ => None, + } + } + + pub fn is_unknown(&self) -> bool { + matches!(self, LuaMemberOwner::LocalUnresolve) + } +} diff --git a/crates/emmylua_code_analysis/src/db_index/member/migrate_members.rs b/crates/emmylua_code_analysis/src/db_index/member/migrate_members.rs deleted file mode 100644 index 1eee07dd3..000000000 --- a/crates/emmylua_code_analysis/src/db_index/member/migrate_members.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::LuaType; - -use super::{LuaMemberId, LuaMemberIndex, LuaMemberKey, LuaMemberOwner}; - -pub fn migrate_members( - member_index: &mut LuaMemberIndex, - owner: LuaMemberOwner, - key: &LuaMemberKey, - new_add_member_id: LuaMemberId, -) -> Option<()> { - let member_owner = get_owner_id(member_index, new_add_member_id)?; - let member_item = member_index.get_member_item(&owner, key)?; - let resolve_member_id = member_item.resolve_member_id(member_index)?; - if new_add_member_id != resolve_member_id { - return None; - } - - let member_ids = member_item.get_member_ids(); - for need_migrate_id in member_ids { - if need_migrate_id == new_add_member_id { - continue; - } - - if let Some(need_migrate_owner) = get_owner_id(member_index, need_migrate_id) { - if member_owner == need_migrate_owner { - continue; - } - migrate_member_to(member_index, &member_owner, &need_migrate_owner); - } - } - - Some(()) -} - -fn get_owner_id( - member_index: &mut LuaMemberIndex, - member_id: LuaMemberId, -) -> Option { - let member = member_index.get_member(&member_id)?; - let typ = member.get_decl_type(); - match typ { - LuaType::Ref(type_id) => Some(LuaMemberOwner::Type(type_id)), - LuaType::TableConst(id) => Some(LuaMemberOwner::Element(id)), - _ => None, - } -} - -fn migrate_member_to( - member_index: &mut LuaMemberIndex, - owner: &LuaMemberOwner, - need_migrate_owner: &LuaMemberOwner, -) -> Option<()> { - let member_ids = member_index - .get_members(need_migrate_owner)? - .iter() - .map(|member| member.get_id()) - .collect::>(); - - for member_id in member_ids { - member_index.set_member_owner(owner.clone(), member_id.file_id, member_id); - member_index.add_member_to_owner(owner.clone(), member_id); - } - - Some(()) -} diff --git a/crates/emmylua_code_analysis/src/db_index/member/mod.rs b/crates/emmylua_code_analysis/src/db_index/member/mod.rs index 342cd1795..bf884ed93 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/mod.rs @@ -1,16 +1,16 @@ mod lua_member; mod lua_member_feature; mod lua_member_item; -mod migrate_members; +mod lua_member_owner; use std::collections::{HashMap, HashSet}; +use super::traits::LuaIndex; use crate::FileId; -pub use lua_member::{LuaMember, LuaMemberId, LuaMemberKey, LuaMemberOwner}; +pub use lua_member::{LuaMember, LuaMemberId, LuaMemberKey}; pub use lua_member_feature::LuaMemberFeature; pub use lua_member_item::LuaMemberIndexItem; - -use super::traits::LuaIndex; +pub use lua_member_owner::LuaMemberOwner; #[derive(Debug)] pub struct LuaMemberIndex { @@ -67,7 +67,6 @@ impl LuaMemberIndex { .owner_members .entry(owner.clone()) .or_insert_with(HashMap::new); - let mut need_check_migrate = false; if feature.is_decl() { if let Some(item) = member_map.get_mut(&key) { match item { @@ -83,8 +82,6 @@ impl LuaMemberIndex { } } } - - need_check_migrate = true; } else { member_map.insert(key.clone(), LuaMemberIndexItem::One(id)); } @@ -113,10 +110,6 @@ impl LuaMemberIndex { .insert(key.clone(), new_items); } - if need_check_migrate { - migrate_members::migrate_members(self, owner, &key, id); - } - Some(()) } @@ -202,6 +195,14 @@ impl LuaMemberIndex { pub fn get_member_len(&self, owner: &LuaMemberOwner) -> usize { self.owner_members.get(owner).map_or(0, |map| map.len()) } + + pub fn get_current_owner(&self, id: &LuaMemberId) -> Option<&LuaMemberOwner> { + self.member_current_owner.get(id) + } + + pub fn get_origin_owner(&self, id: &LuaMemberId) -> Option<&LuaMemberOwner> { + self.member_origin_owner.get(id) + } } impl LuaIndex for LuaMemberIndex { @@ -211,10 +212,9 @@ impl LuaIndex for LuaMemberIndex { for member_id_or_owner in member_ids { match member_id_or_owner { MemberOrOwner::Member(member_id) => { - if let Some(member) = self.members.remove(&member_id) { - let owner = member.get_owner(); - owners.insert(owner); - } + self.members.remove(&member_id); + self.member_current_owner.remove(&member_id); + self.member_origin_owner.remove(&member_id); } MemberOrOwner::Owner(owner) => { owners.insert(owner); diff --git a/crates/emmylua_code_analysis/src/db_index/mod.rs b/crates/emmylua_code_analysis/src/db_index/mod.rs index 81d03ae25..4c0cd3dd8 100644 --- a/crates/emmylua_code_analysis/src/db_index/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/mod.rs @@ -2,6 +2,7 @@ mod declaration; mod dependency; mod diagnostic; mod flow; +mod global; mod member; mod metatable; mod module; @@ -20,6 +21,8 @@ pub use declaration::*; use dependency::LuaDenpendencyIndex; pub use diagnostic::{AnalyzeError, DiagnosticAction, DiagnosticActionKind, DiagnosticIndex}; pub use flow::{LuaFlowChain, LuaFlowId, LuaFlowIndex}; +pub use global::GlobalId; +use global::LuaGlobalIndex; pub use member::{ LuaMember, LuaMemberFeature, LuaMemberId, LuaMemberIndex, LuaMemberIndexItem, LuaMemberKey, LuaMemberOwner, @@ -53,6 +56,7 @@ pub struct DbIndex { vfs: Vfs, file_dependencies_index: LuaDenpendencyIndex, metatable_index: LuaMetatableIndex, + globla_index: LuaGlobalIndex, emmyrc: Arc, } @@ -73,6 +77,7 @@ impl DbIndex { vfs: Vfs::new(), file_dependencies_index: LuaDenpendencyIndex::new(), metatable_index: LuaMetatableIndex::new(), + globla_index: LuaGlobalIndex::new(), emmyrc: Arc::new(Emmyrc::default()), } } @@ -187,6 +192,14 @@ impl DbIndex { &mut self.file_dependencies_index } + pub fn get_global_index(&self) -> &LuaGlobalIndex { + &self.globla_index + } + + pub fn get_global_index_mut(&mut self) -> &mut LuaGlobalIndex { + &mut self.globla_index + } + pub fn update_config(&mut self, config: Arc) { self.vfs.update_config(config.clone()); self.modules_index.update_config(config.clone()); @@ -212,6 +225,7 @@ impl LuaIndex for DbIndex { self.flow_index.remove(file_id); self.file_dependencies_index.remove(file_id); self.metatable_index.remove(file_id); + self.globla_index.remove(file_id); } fn clear(&mut self) { @@ -227,5 +241,6 @@ impl LuaIndex for DbIndex { self.flow_index.clear(); self.file_dependencies_index.clear(); self.metatable_index.clear(); + self.globla_index.clear(); } } diff --git a/crates/emmylua_code_analysis/src/db_index/type/humanize_type.rs b/crates/emmylua_code_analysis/src/db_index/type/humanize_type.rs index e9092aa0f..596ae01b8 100644 --- a/crates/emmylua_code_analysis/src/db_index/type/humanize_type.rs +++ b/crates/emmylua_code_analysis/src/db_index/type/humanize_type.rs @@ -130,9 +130,13 @@ fn humanize_simple_type( let mut member_vec = Vec::new(); for member in members { let member_key = member.get_key(); - let typ = member.get_decl_type(); - if !typ.is_signature() { - member_vec.push((member_key, typ)); + let type_cache = db.get_type_index().get_type_cache(&member.get_id().into()); + let type_cache = match type_cache { + Some(type_cache) => type_cache, + None => &super::LuaTypeCache::InferType(LuaType::Any), + }; + if !type_cache.is_signature() { + member_vec.push((member_key, type_cache.as_type().clone())); } } @@ -453,11 +457,15 @@ fn humanize_table_const_type_detail_and_simple( let mut members_string = String::new(); for member in members { let key = member.get_key(); - let typ = member.get_decl_type(); + let type_cache = db.get_type_index().get_type_cache(&member.get_id().into()); + let type_cache = match type_cache { + Some(type_cache) => type_cache, + None => &super::LuaTypeCache::InferType(LuaType::Any), + }; let member_string = build_table_member_string( key, - &typ, - humanize_type(db, &typ, level.next_level()), + &type_cache.as_type(), + humanize_type(db, &type_cache.as_type(), level.next_level()), level, ); diff --git a/crates/emmylua_code_analysis/src/db_index/type/mod.rs b/crates/emmylua_code_analysis/src/db_index/type/mod.rs index 406bfbfe1..db15398df 100644 --- a/crates/emmylua_code_analysis/src/db_index/type/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/type/mod.rs @@ -3,18 +3,20 @@ mod test; mod type_assert; mod type_decl; mod type_ops; +mod type_owner; mod types; use super::traits::LuaIndex; use crate::{FileId, InFiled}; use emmylua_parser::LuaSyntaxId; pub use humanize_type::{humanize_type, RenderLevel}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; pub use type_assert::TypeAssertion; pub use type_decl::{ LuaDeclLocation, LuaDeclTypeKind, LuaTypeAttribute, LuaTypeDecl, LuaTypeDeclId, }; pub use type_ops::TypeOps; +pub use type_owner::{LuaTypeCache, LuaTypeOwner}; pub use types::*; #[derive(Debug)] @@ -26,6 +28,8 @@ pub struct LuaTypeIndex { generic_params: HashMap)>>, supers: HashMap>>, as_force_type: HashMap, LuaType>, + types: HashMap, + in_filed_type_owner: HashMap>, } impl LuaTypeIndex { @@ -38,6 +42,8 @@ impl LuaTypeIndex { generic_params: HashMap::new(), supers: HashMap::new(), as_force_type: HashMap::new(), + types: HashMap::new(), + in_filed_type_owner: HashMap::new(), } } @@ -206,6 +212,21 @@ impl LuaTypeIndex { pub fn get_as_force_type(&self, syntax_id: &InFiled) -> Option<&LuaType> { self.as_force_type.get(syntax_id) } + + pub fn bind_type(&mut self, owner: LuaTypeOwner, cache: LuaTypeCache) { + if self.types.contains_key(&owner) { + return; + } + self.types.insert(owner.clone(), cache); + self.in_filed_type_owner + .entry(owner.get_file_id()) + .or_insert_with(HashSet::new) + .insert(owner); + } + + pub fn get_type_cache(&self, owner: &LuaTypeOwner) -> Option<&LuaTypeCache> { + self.types.get(owner) + } } impl LuaIndex for LuaTypeIndex { @@ -238,6 +259,11 @@ impl LuaIndex for LuaTypeIndex { } self.as_force_type.retain(|id, _| id.file_id != file_id); + if let Some(type_owners) = self.in_filed_type_owner.remove(&file_id) { + for type_owner in type_owners { + self.types.remove(&type_owner); + } + } } fn clear(&mut self) { diff --git a/crates/emmylua_code_analysis/src/db_index/type/type_owner.rs b/crates/emmylua_code_analysis/src/db_index/type/type_owner.rs new file mode 100644 index 000000000..477e08dcd --- /dev/null +++ b/crates/emmylua_code_analysis/src/db_index/type/type_owner.rs @@ -0,0 +1,62 @@ +use rowan::TextSize; + +use crate::{FileId, LuaDeclId, LuaMemberId}; + +use super::LuaType; + +#[derive(Debug, Eq, PartialEq, Hash, Clone)] +pub enum LuaTypeOwner { + Decl(LuaDeclId), + Member(LuaMemberId), +} + +impl From for LuaTypeOwner { + fn from(decl_id: LuaDeclId) -> Self { + Self::Decl(decl_id) + } +} + +impl From for LuaTypeOwner { + fn from(member_id: LuaMemberId) -> Self { + Self::Member(member_id) + } +} + +impl LuaTypeOwner { + pub fn get_file_id(&self) -> FileId { + match self { + LuaTypeOwner::Decl(id) => id.file_id, + LuaTypeOwner::Member(id) => id.file_id, + } + } + + pub fn get_position(&self) -> TextSize { + match self { + LuaTypeOwner::Decl(id) => id.position, + LuaTypeOwner::Member(id) => id.get_position(), + } + } +} + +#[derive(Debug, Clone)] +pub enum LuaTypeCache { + DocType(LuaType), + InferType(LuaType), +} + +impl LuaTypeCache { + pub fn as_type(&self) -> &LuaType { + match self { + LuaTypeCache::DocType(ty) => ty, + LuaTypeCache::InferType(ty) => ty, + } + } +} + +impl std::ops::Deref for LuaTypeCache { + type Target = LuaType; + + fn deref(&self) -> &Self::Target { + self.as_type() + } +} From 8dc764408ed0e4b2be153e7b4ecab11ded4eb914 Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Thu, 3 Apr 2025 17:26:09 +0800 Subject: [PATCH 3/6] refactor --- .../bind_type/migrate_global_member.rs | 65 ++++++++++ .../src/compilation/analyzer/bind_type/mod.rs | 93 ++++++++++++++ .../src/compilation/analyzer/decl/exprs.rs | 4 +- .../src/compilation/analyzer/decl/members.rs | 1 - .../src/compilation/analyzer/decl/stats.rs | 2 +- .../compilation/analyzer/doc/type_def_tags.rs | 30 ++--- .../compilation/analyzer/doc/type_ref_tags.rs | 2 +- .../compilation/analyzer/flow/cast_analyze.rs | 2 +- .../src/compilation/analyzer/flow/mod.rs | 9 +- .../compilation/analyzer/flow/var_analyze.rs | 20 +-- .../src/compilation/analyzer/lua/stats.rs | 30 ++--- .../src/compilation/analyzer/mod.rs | 5 +- .../analyzer/unresolve/merge_type.rs | 89 ------------- .../analyzer/unresolve/migrate_member.rs | 67 ---------- .../src/compilation/analyzer/unresolve/mod.rs | 3 - .../compilation/analyzer/unresolve/resolve.rs | 34 ++--- .../src/db_index/global/global_id.rs | 10 ++ .../src/db_index/global/mod.rs | 5 + .../src/db_index/member/lua_member_item.rs | 117 ++++++++++-------- .../src/db_index/member/mod.rs | 31 +++-- .../checker/assign_type_mismatch.rs | 25 ++-- .../src/diagnostic/checker/missing_fields.rs | 13 +- .../diagnostic/checker/undefined_global.rs | 10 +- .../src/semantic/infer/infer_index.rs | 16 +-- .../src/semantic/infer/infer_name.rs | 63 ++++------ .../src/semantic/infer/infer_table.rs | 45 ++++--- .../src/semantic/member/infer_members.rs | 36 ++++-- .../emmylua_code_analysis/src/semantic/mod.rs | 11 +- .../src/semantic/reference/mod.rs | 7 +- .../semantic_info/infer_expr_semantic_decl.rs | 63 ++++++---- .../src/semantic/semantic_info/mod.rs | 29 +++-- .../complex_type/table_generic_check.rs | 9 +- .../src/semantic/type_check/ref_type.rs | 35 ++++-- .../src/semantic/visibility/mod.rs | 2 +- .../src/markdown_generator/gen/global_gen.rs | 19 +-- .../src/markdown_generator/gen/mod_gen.rs | 18 +-- .../src/markdown_generator/gen/typ_gen.rs | 16 ++- .../src/markdown_generator/mod.rs | 4 +- .../completion/providers/env_provider.rs | 20 ++- .../providers/type_special_provider.rs | 70 ++++++++--- .../src/handlers/document_symbol/builder.rs | 15 ++- .../src/handlers/document_symbol/expr.rs | 3 +- .../src/handlers/document_symbol/stats.rs | 16 ++- .../src/handlers/hover/build_hover.rs | 10 +- .../src/handlers/hover/hover_builder.rs | 14 ++- .../src/handlers/hover/hover_humanize.rs | 11 +- .../semantic_token/build_semantic_tokens.rs | 80 +++++------- .../build_workspace_symbols.rs | 14 ++- 48 files changed, 718 insertions(+), 575 deletions(-) create mode 100644 crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/migrate_global_member.rs create mode 100644 crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/mod.rs delete mode 100644 crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs delete mode 100644 crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/migrate_global_member.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/migrate_global_member.rs new file mode 100644 index 000000000..7d7c39f1f --- /dev/null +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/migrate_global_member.rs @@ -0,0 +1,65 @@ +use crate::{DbIndex, GlobalId, LuaDeclId, LuaMemberId, LuaMemberOwner, LuaTypeOwner}; + +use super::get_owner_id; + +pub fn migrate_global_members_when_type_resolve( + db: &mut DbIndex, + type_owner: LuaTypeOwner, +) -> Option<()> { + match type_owner { + LuaTypeOwner::Decl(decl_id) => { + migrate_global_member_to_decl(db, decl_id); + } + LuaTypeOwner::Member(member_id) => { + migrate_global_member_to_member(db, member_id); + } + } + Some(()) +} + +fn migrate_global_member_to_decl(db: &mut DbIndex, decl_id: LuaDeclId) -> Option<()> { + let decl = db.get_decl_index().get_decl(&decl_id)?; + if !decl.is_global() { + return None; + } + + let owner_id = get_owner_id(db, &decl_id.clone().into())?; + + let name = decl.get_name(); + let global_id = GlobalId::new(name.into()); + let members = db + .get_member_index() + .get_members(&LuaMemberOwner::GlobalPath(global_id))? + .iter() + .map(|member| member.get_id()) + .collect::>(); + + let member_index = db.get_member_index_mut(); + for member_id in members { + member_index.set_member_owner(owner_id.clone(), member_id.file_id, member_id); + member_index.add_member_to_owner(owner_id.clone(), member_id); + } + + Some(()) +} + +fn migrate_global_member_to_member(db: &mut DbIndex, member_id: LuaMemberId) -> Option<()> { + let member = db.get_member_index().get_member(&member_id)?; + let global_id = member.get_global_id()?; + let owner_id = get_owner_id(db, &member_id.clone().into())?; + + let members = db + .get_member_index() + .get_members(&LuaMemberOwner::GlobalPath(global_id.clone()))? + .iter() + .map(|member| member.get_id()) + .collect::>(); + + let member_index = db.get_member_index_mut(); + for member_id in members { + member_index.set_member_owner(owner_id.clone(), member_id.file_id, member_id); + member_index.add_member_to_owner(owner_id.clone(), member_id); + } + + Some(()) +} diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/mod.rs new file mode 100644 index 000000000..d2472c0af --- /dev/null +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/bind_type/mod.rs @@ -0,0 +1,93 @@ +mod migrate_global_member; + +use migrate_global_member::migrate_global_members_when_type_resolve; +use rowan::TextRange; + +use crate::{ + db_index::{DbIndex, LuaMemberOwner, LuaType, LuaTypeDeclId}, + InFiled, LuaMemberId, LuaTypeCache, LuaTypeOwner, +}; + +pub fn bind_type( + db: &mut DbIndex, + type_owner: LuaTypeOwner, + type_cache: LuaTypeCache, +) -> Option<()> { + let decl_type_cache = db.get_type_index().get_type_cache(&type_owner); + + if decl_type_cache.is_none() { + db.get_type_index_mut() + .bind_type(type_owner.clone(), type_cache); + migrate_global_members_when_type_resolve(db, type_owner); + } else { + let decl_type = decl_type_cache.unwrap().as_type(); + merge_def_type(db, decl_type.clone(), type_cache.as_type().clone()); + } + + Some(()) +} + +fn merge_def_type(db: &mut DbIndex, decl_type: LuaType, expr_type: LuaType) { + match &decl_type { + LuaType::Def(def) => match &expr_type { + LuaType::TableConst(in_filed_range) => { + merge_def_type_with_table(db, def.clone(), in_filed_range.clone()); + } + LuaType::Instance(instance) => { + let base_ref = instance.get_base(); + merge_def_type(db, base_ref.clone(), expr_type); + } + _ => {} + }, + _ => {} + } +} + +fn merge_def_type_with_table( + db: &mut DbIndex, + def_id: LuaTypeDeclId, + table_range: InFiled, +) -> Option<()> { + let expr_member_owner = LuaMemberOwner::Element(table_range); + let member_index = db.get_member_index_mut(); + let expr_member_ids = member_index + .get_members(&expr_member_owner)? + .iter() + .map(|member| member.get_id()) + .collect::>(); + let def_owner = LuaMemberOwner::Type(def_id); + for table_member_id in expr_member_ids { + add_member(db, def_owner.clone(), table_member_id); + } + + Some(()) +} + +pub fn add_member(db: &mut DbIndex, owner: LuaMemberOwner, member_id: LuaMemberId) -> Option<()> { + db.get_member_index_mut() + .set_member_owner(owner.clone(), member_id.file_id, member_id); + db.get_member_index_mut() + .add_member_to_owner(owner.clone(), member_id); + + // let item = db.get_member_index().get_member_item_by_member_id(member_id)?; + // if item.is_one() { + // return Some(()) + // } + + // let resolve_member_id = item.resolve_type_owner_member_id(db)?; + // if resolve_member_id != member_id { + // return None; + // } + + Some(()) +} + +fn get_owner_id(db: &DbIndex, type_owner: &LuaTypeOwner) -> Option { + let type_cache = db.get_type_index().get_type_cache(&type_owner)?; + match type_cache.as_type() { + LuaType::Ref(type_id) => Some(LuaMemberOwner::Type(type_id.clone())), + LuaType::TableConst(id) => Some(LuaMemberOwner::Element(id.clone())), + LuaType::Instance(inst) => Some(LuaMemberOwner::Element(inst.get_range().clone())), + _ => None, + } +} diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs index 5a2b6ded3..93799c2fb 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/exprs.rs @@ -223,9 +223,7 @@ pub fn analyze_table_expr(analyzer: &mut DeclAnalyzer, table_expr: LuaTableExpr) LuaMemberOwner::GlobalPath(path) => { LuaMember::new(member_id, key, decl_feature, Some(path.clone())) } - _ => { - LuaMember::new(member_id, key, decl_feature, None) - } + _ => LuaMember::new(member_id, key, decl_feature, None), }; analyzer .db diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs index 814dce08e..22f435013 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/members.rs @@ -1,5 +1,4 @@ use emmylua_parser::{LuaAstNode, LuaExpr, LuaIndexExpr, PathTrait}; -use internment::ArcIntern; use smol_str::SmolStr; use crate::{GlobalId, LuaMemberOwner}; diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs index c17181ab7..886087a2e 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/decl/stats.rs @@ -5,7 +5,7 @@ use emmylua_parser::{ use crate::{ db_index::{LocalAttribute, LuaDecl, LuaMember, LuaMemberKey}, - LuaDeclExtra, LuaMemberFeature, LuaMemberId, LuaMemberOwner, LuaSemanticDeclId, LuaSignatureId, + LuaDeclExtra, LuaMemberFeature, LuaMemberId, LuaSemanticDeclId, LuaSignatureId, }; use super::{members::find_index_owner, DeclAnalyzer}; diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs index 8dc3578e4..10bff0ae6 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_def_tags.rs @@ -9,6 +9,7 @@ use emmylua_parser::{ use rowan::TextRange; use crate::{ + compilation::analyzer::bind_type::bind_type, db_index::{LuaDeclId, LuaMemberId, LuaSemanticDeclId, LuaSignatureId, LuaType}, LuaTypeCache, LuaTypeDeclId, }; @@ -378,35 +379,30 @@ fn bind_def_type(analyzer: &mut DocAnalyzer, type_def: LuaType) -> Option<()> { let file_id = analyzer.file_id; let decl_id = LuaDeclId::new(file_id, position); - analyzer - .db - .get_type_index_mut() - .bind_type(decl_id.into(), LuaTypeCache::DocType(type_def)); + bind_type(analyzer.db, decl_id.into(), LuaTypeCache::DocType(type_def)); } LuaAst::LuaAssignStat(assign_stat) => { if let LuaVarExpr::NameExpr(name_expr) = assign_stat.child::()? { let position = name_expr.get_position(); let file_id = analyzer.file_id; let decl_id = LuaDeclId::new(file_id, position); - - analyzer - .db - .get_type_index_mut() - .bind_type(decl_id.into(), LuaTypeCache::DocType(type_def)); + bind_type(analyzer.db, decl_id.into(), LuaTypeCache::DocType(type_def)); } else if let LuaVarExpr::IndexExpr(index_expr) = assign_stat.child::()? { let member_id = LuaMemberId::new(index_expr.get_syntax_id(), analyzer.file_id); - analyzer - .db - .get_type_index_mut() - .bind_type(member_id.into(), LuaTypeCache::DocType(type_def)); + bind_type( + analyzer.db, + member_id.into(), + LuaTypeCache::DocType(type_def), + ); } } LuaAst::LuaTableField(field) => { let member_id = LuaMemberId::new(field.get_syntax_id(), analyzer.file_id); - analyzer - .db - .get_type_index_mut() - .bind_type(member_id.into(), LuaTypeCache::DocType(type_def)); + bind_type( + analyzer.db, + member_id.into(), + LuaTypeCache::DocType(type_def), + ); } _ => {} } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs index c88a1aa3f..a836011a4 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/doc/type_ref_tags.rs @@ -282,7 +282,7 @@ pub fn analyze_cast(analyzer: &mut DocAnalyzer, tag: LuaDocTagCast) -> Option<() for op in tag.get_op_types() { if let Some(doc_type) = op.get_type() { let typ = infer_type(analyzer, doc_type.clone()); - analyzer.context.type_flow.insert( + analyzer.context.cast_flow.insert( InFiled { file_id: analyzer.file_id, value: doc_type.get_syntax_id(), diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/flow/cast_analyze.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/flow/cast_analyze.rs index e7225dcb1..ca2185885 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/flow/cast_analyze.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/flow/cast_analyze.rs @@ -54,7 +54,7 @@ pub fn analyze_cast( } } else if let Some(doc_typ) = cast_op_type.get_type() { let key = InFiled::new(file_id, doc_typ.get_syntax_id()); - let typ = match context.type_flow.get(&key) { + let typ = match context.cast_flow.get(&key) { Some(t) => t.clone(), None => continue, }; diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/flow/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/flow/mod.rs index 762e2370d..953b334c1 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/flow/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/flow/mod.rs @@ -162,14 +162,7 @@ fn analyze_flow( FlowRef::IndexExpr(expr) => LuaVarExpr::IndexExpr(expr.clone()), _ => continue, }; - analyze_ref_assign( - db, - &mut flow_chain, - var_expr, - var_path, - file_id, - context, - ); + analyze_ref_assign(db, &mut flow_chain, var_expr, var_path, file_id); } FlowNode::CastRef(ref_node) => { let tag_cast = match ref_node { diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/flow/var_analyze.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/flow/var_analyze.rs index 37a001c3d..62e483907 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/flow/var_analyze.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/flow/var_analyze.rs @@ -7,9 +7,8 @@ use rowan::TextRange; use smol_str::SmolStr; use crate::{ - compilation::analyzer::AnalyzeContext, db_index::{LuaType, TypeAssertion}, - DbIndex, FileId, InFiled, LuaFlowChain, LuaTypeDeclId, + DbIndex, FileId, LuaDeclId, LuaFlowChain, LuaMemberId, LuaTypeDeclId, LuaTypeOwner, }; pub fn analyze_ref_expr( @@ -37,16 +36,21 @@ pub fn analyze_ref_assign( var_expr: LuaVarExpr, path: &str, file_id: FileId, - context: &AnalyzeContext, ) -> Option<()> { let assign_stat = var_expr.get_parent::()?; if is_decl_assign_stat(assign_stat.clone()).unwrap_or(false) { - let key = InFiled { - file_id, - value: var_expr.get_syntax_id(), + let type_owner = match var_expr { + LuaVarExpr::IndexExpr(index_expr) => { + let member_id = LuaMemberId::new(index_expr.get_syntax_id(), file_id); + LuaTypeOwner::Member(member_id) + } + LuaVarExpr::NameExpr(name_expr) => { + let decl_id = LuaDeclId::new(file_id, name_expr.get_position()); + LuaTypeOwner::Decl(decl_id) + } }; - if let Some(typ) = context.type_flow.get(&key) { - let type_assert = TypeAssertion::Narrow(typ.clone()); + if let Some(type_cache) = db.get_type_index().get_type_cache(&type_owner) { + let type_assert = TypeAssertion::Narrow(type_cache.as_type().clone()); broadcast_down( db, flow_chain, diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs index 8f544c9dc..33d3a6d65 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/lua/stats.rs @@ -4,9 +4,9 @@ use emmylua_parser::{ }; use crate::{ - compilation::analyzer::unresolve::{ - merge_type_owner_expr_type, set_owner_and_add_member, UnResolveDecl, UnResolveIterVar, - UnResolveMember, + compilation::analyzer::{ + bind_type::{add_member, bind_type}, + unresolve::{UnResolveDecl, UnResolveIterVar, UnResolveMember}, }, db_index::{LuaDeclId, LuaMemberId, LuaMemberOwner, LuaOperatorMetaMethod, LuaType}, InferFailReason, LuaTypeCache, LuaTypeOwner, @@ -63,11 +63,10 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) } } - merge_type_owner_expr_type( + bind_type( analyzer.db, - &mut analyzer.infer_cache, decl_id.into(), - expr_type, + LuaTypeCache::InferType(expr_type), ); } Err(InferFailReason::None) => { @@ -105,11 +104,10 @@ pub fn analyze_local_stat(analyzer: &mut LuaAnalyzer, local_stat: LuaLocalStat) let decl_id = LuaDeclId::new(analyzer.file_id, position); let ret_type = multi.get_type(i - expr_count + 1); if let Some(ty) = ret_type { - merge_type_owner_expr_type( + bind_type( analyzer.db, - &mut analyzer.infer_cache, decl_id.into(), - ty.clone(), + LuaTypeCache::InferType(ty.clone()), ); } else { analyzer.db.get_type_index_mut().bind_type( @@ -223,7 +221,7 @@ fn set_index_expr_owner(analyzer: &mut LuaAnalyzer, var_expr: LuaVarExpr) -> Opt } }; - set_owner_and_add_member(analyzer.db, member_owner, member_id); + add_member(analyzer.db, member_owner, member_id); } Err(InferFailReason::None) => {} Err(reason) => { @@ -356,12 +354,7 @@ fn merge_type_owner_and_expr_type( expr_type = multi.get_type(idx).unwrap_or(&LuaType::Nil).clone(); } - merge_type_owner_expr_type( - analyzer.db, - &mut analyzer.infer_cache, - type_owner, - expr_type, - ); + bind_type(analyzer.db, type_owner, LuaTypeCache::InferType(expr_type)); Some(()) } @@ -558,11 +551,10 @@ pub fn analyze_table_field(analyzer: &mut LuaAnalyzer, field: LuaTableField) -> } }; - merge_type_owner_expr_type( + bind_type( analyzer.db, - &mut analyzer.infer_cache, member_id.into(), - value_type, + LuaTypeCache::InferType(value_type), ); Some(()) diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/mod.rs index 564ef290a..35cbe7b22 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/mod.rs @@ -1,3 +1,4 @@ +mod bind_type; mod decl; mod doc; mod flow; @@ -79,7 +80,7 @@ pub struct AnalyzeContext { tree_list: Vec>, #[allow(unused)] config: Arc, - type_flow: HashMap, LuaType>, + cast_flow: HashMap, LuaType>, unresolves: Vec, } @@ -88,7 +89,7 @@ impl AnalyzeContext { Self { tree_list: Vec::new(), config: emmyrc, - type_flow: HashMap::new(), + cast_flow: HashMap::new(), unresolves: Vec::new(), } } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs deleted file mode 100644 index e77544fb9..000000000 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/merge_type.rs +++ /dev/null @@ -1,89 +0,0 @@ -use rowan::TextRange; - -use crate::{ - db_index::{DbIndex, LuaMemberOwner, LuaType, LuaTypeDeclId}, - InFiled, LuaInferCache, LuaMemberId, LuaTypeCache, LuaTypeOwner, -}; - -use super::migrate_member::migrate_member_when_type_resolve; - -pub fn merge_type_owner_expr_type( - db: &mut DbIndex, - cache: &mut LuaInferCache, - type_owner: LuaTypeOwner, - expr_type: LuaType, -) -> Option<()> { - let decl_type_cache = db.get_type_index().get_type_cache(&type_owner); - - if decl_type_cache.is_none() { - db.get_type_index_mut() - .bind_type(type_owner.clone(), LuaTypeCache::InferType(expr_type)); - } else { - let decl_type = decl_type_cache.unwrap().as_type(); - merge_def_type(db, cache, decl_type.clone(), expr_type); - } - - match &type_owner { - LuaTypeOwner::Member(member_id) => { - migrate_member_when_type_resolve(db, member_id.clone()); - } - _ => {} - } - - Some(()) -} - -fn merge_def_type( - db: &mut DbIndex, - cache: &mut LuaInferCache, - decl_type: LuaType, - expr_type: LuaType, -) { - match &decl_type { - LuaType::Def(def) => match &expr_type { - LuaType::TableConst(in_filed_range) => { - merge_def_type_with_table(db, cache, def.clone(), in_filed_range.clone()); - } - LuaType::Instance(instance) => { - let base_ref = instance.get_base(); - merge_def_type(db, cache, base_ref.clone(), expr_type); - } - _ => {} - }, - _ => {} - } -} - -fn merge_def_type_with_table( - db: &mut DbIndex, - _: &mut LuaInferCache, - def_id: LuaTypeDeclId, - table_range: InFiled, -) -> Option<()> { - let expr_member_owner = LuaMemberOwner::Element(table_range); - let member_index = db.get_member_index_mut(); - let expr_member_ids = member_index - .get_members(&expr_member_owner)? - .iter() - .map(|member| member.get_id()) - .collect::>(); - let def_owner = LuaMemberOwner::Type(def_id); - for table_member_id in expr_member_ids { - set_owner_and_add_member(db, def_owner.clone(), table_member_id); - } - - Some(()) -} - -pub fn set_owner_and_add_member( - db: &mut DbIndex, - owner: LuaMemberOwner, - member_id: LuaMemberId, -) -> Option<()> { - db.get_member_index_mut() - .set_member_owner(owner.clone(), member_id.file_id, member_id); - db.get_member_index_mut() - .add_member_to_owner(owner.clone(), member_id); - - Some(()) -} diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs deleted file mode 100644 index eef0951f9..000000000 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/migrate_member.rs +++ /dev/null @@ -1,67 +0,0 @@ -use crate::{DbIndex, LuaMemberId, LuaMemberIndex, LuaMemberKey, LuaMemberOwner, LuaType}; - -pub fn migrate_member_when_type_resolve(db: &DbIndex, member_id: LuaMemberId) -> Option<()> { - - Some(()) -} - -// pub fn migrate_members( -// db: &mut DbIndex, -// member_id: LuaMemberId, -// ) -> Option<()> { -// let member_index= db.get_member_index_mut(); -// let member_owner = get_owner_id(member_index, member_id)?; -// let member_item = member_index.get_member_item(&owner, key)?; -// let resolve_member_id = member_item.resolve_member_id(member_index)?; -// if new_add_member_id != resolve_member_id { -// return None; -// } - -// let member_ids = member_item.get_member_ids(); -// for need_migrate_id in member_ids { -// if need_migrate_id == new_add_member_id { -// continue; -// } - -// if let Some(need_migrate_owner) = get_owner_id(member_index, need_migrate_id) { -// if member_owner == need_migrate_owner { -// continue; -// } -// migrate_member_to(member_index, &member_owner, &need_migrate_owner); -// } -// } - -// Some(()) -// } - -// fn get_owner_id( -// member_index: &mut LuaMemberIndex, -// member_id: LuaMemberId, -// ) -> Option { -// let member = member_index.get_member(&member_id)?; -// let typ = member.get_decl_type(); -// match typ { -// LuaType::Ref(type_id) => Some(LuaMemberOwner::Type(type_id)), -// LuaType::TableConst(id) => Some(LuaMemberOwner::Element(id)), -// _ => None, -// } -// } - -// fn migrate_member_to( -// member_index: &mut LuaMemberIndex, -// owner: &LuaMemberOwner, -// need_migrate_owner: &LuaMemberOwner, -// ) -> Option<()> { -// let member_ids = member_index -// .get_members(need_migrate_owner)? -// .iter() -// .map(|member| member.get_id()) -// .collect::>(); - -// for member_id in member_ids { -// member_index.set_member_owner(owner.clone(), member_id.file_id, member_id); -// member_index.add_member_to_owner(owner.clone(), member_id); -// } - -// Some(()) -// } diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs index aa5f71446..9b0a6f535 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/mod.rs @@ -1,9 +1,7 @@ mod check_reason; mod infer_manager; -mod merge_type; mod resolve; mod resolve_closure; -mod migrate_member; use crate::{ db_index::{DbIndex, LuaDeclId, LuaMemberId, LuaSignatureId}, @@ -15,7 +13,6 @@ use emmylua_parser::{ LuaAssignStat, LuaCallExpr, LuaExpr, LuaFuncStat, LuaTableExpr, LuaTableField, }; use infer_manager::InferCacheManager; -pub use merge_type::{merge_type_owner_expr_type, set_owner_and_add_member}; use resolve::{ try_resolve_decl, try_resolve_iter_var, try_resolve_member, try_resolve_module, try_resolve_module_ref, try_resolve_return_point, try_resolve_table_field, diff --git a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs index 66732a335..84f322576 100644 --- a/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs +++ b/crates/emmylua_code_analysis/src/compilation/analyzer/unresolve/resolve.rs @@ -3,7 +3,10 @@ use std::ops::Deref; use emmylua_parser::{LuaAstNode, LuaExpr, LuaLocalStat, LuaTableExpr}; use crate::{ - compilation::analyzer::lua::analyze_return_point, + compilation::analyzer::{ + bind_type::{add_member, bind_type}, + lua::analyze_return_point, + }, db_index::{DbIndex, LuaMemberOwner, LuaType}, semantic::{infer_expr, LuaInferCache}, InFiled, InferFailReason, LuaDeclId, LuaMember, LuaMemberId, LuaMemberKey, LuaSemanticDeclId, @@ -11,8 +14,8 @@ use crate::{ }; use super::{ - check_reason::check_reach_reason, merge_type_owner_expr_type, UnResolveDecl, UnResolveIterVar, - UnResolveMember, UnResolveModule, UnResolveModuleRef, UnResolveReturn, UnResolveTableField, + check_reason::check_reach_reason, UnResolveDecl, UnResolveIterVar, UnResolveMember, + UnResolveModule, UnResolveModuleRef, UnResolveReturn, UnResolveTableField, }; pub fn try_resolve_decl( @@ -41,7 +44,7 @@ pub fn try_resolve_decl( _ => expr_type, }; - merge_type_owner_expr_type(db, cache, decl_id.into(), expr_type); + bind_type(db, decl_id.into(), LuaTypeCache::InferType(expr_type)); Some(true) } @@ -79,13 +82,7 @@ pub fn try_resolve_member( } }; let member_id = unresolve_member.member_id.clone(); - db.get_member_index_mut().set_member_owner( - member_owner.clone(), - cache.get_file_id(), - member_id, - ); - db.get_member_index_mut() - .add_member_to_owner(member_owner, member_id); + add_member(db, member_owner, member_id); unresolve_member.prefix = None; } @@ -107,7 +104,7 @@ pub fn try_resolve_member( }; let member_id = unresolve_member.member_id; - merge_type_owner_expr_type(db, cache, member_id.into(), expr_type); + bind_type(db, member_id.into(), LuaTypeCache::InferType(expr_type)); } Some(true) } @@ -166,7 +163,12 @@ pub fn try_resolve_table_field( })?; let member_id = LuaMemberId::new(field.get_syntax_id(), file_id); - let member = LuaMember::new(member_id, member_key, unresolve_table_field.decl_feature, None); + let member = LuaMember::new( + member_id, + member_key, + unresolve_table_field.decl_feature, + None, + ); db.get_member_index_mut().add_member(owner_id, member); db.get_type_index_mut().bind_type( member_id.clone().into(), @@ -275,7 +277,11 @@ pub fn try_resolve_iter_var( .get_type(iter_var.ret_idx) .unwrap_or(&LuaType::Nil); let decl_id = iter_var.decl_id; - merge_type_owner_expr_type(db, cache, decl_id.into(), iter_type.clone()); + bind_type( + db, + decl_id.into(), + LuaTypeCache::InferType(iter_type.clone()), + ); Some(true) } diff --git a/crates/emmylua_code_analysis/src/db_index/global/global_id.rs b/crates/emmylua_code_analysis/src/db_index/global/global_id.rs index cd00d5605..def155616 100644 --- a/crates/emmylua_code_analysis/src/db_index/global/global_id.rs +++ b/crates/emmylua_code_analysis/src/db_index/global/global_id.rs @@ -12,4 +12,14 @@ impl GlobalId { pub fn get_name(&self) -> &str { self.0.as_ref() } + + pub fn get_prev_id(&self) -> Option { + let name = self.get_name(); + if let Some(pos) = name.rfind('.') { + let new_name = &name[..pos]; + return Some(GlobalId::new(new_name)); + } + + None + } } diff --git a/crates/emmylua_code_analysis/src/db_index/global/mod.rs b/crates/emmylua_code_analysis/src/db_index/global/mod.rs index 04240262e..7cad9c21e 100644 --- a/crates/emmylua_code_analysis/src/db_index/global/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/global/mod.rs @@ -41,6 +41,11 @@ impl LuaGlobalIndex { let id = GlobalId::new(name); self.global_decl.get(&id) } + + pub fn is_exist_global_decl(&self, name: &str) -> bool { + let id = GlobalId::new(name); + self.global_decl.contains_key(&id) + } } impl LuaIndex for LuaGlobalIndex { diff --git a/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs b/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs index fa9393284..f0a55b12d 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/lua_member_item.rs @@ -17,6 +17,15 @@ impl LuaMemberIndexItem { resolve_member_semantic_id(db, &self) } + #[allow(unused)] + pub fn resolve_type_owner_member_id(&self, db: &DbIndex) -> Option { + resolve_type_owner_member_id(db, &self) + } + + pub fn is_one(&self) -> bool { + matches!(self, LuaMemberIndexItem::One(_)) + } + pub fn get_member_ids(&self) -> Vec { match self { LuaMemberIndexItem::One(member_id) => vec![*member_id], @@ -110,62 +119,66 @@ fn resolve_member_type( } } -// fn resolve_member_id( -// member_index: &LuaMemberIndex, -// member_item: &LuaMemberIndexItem, -// ) -> Option { -// match member_item { -// LuaMemberIndexItem::One(member_id) => Some(*member_id), -// LuaMemberIndexItem::Many(member_ids) => { -// let mut resolve_state = MemberTypeResolveState::All; -// let members = member_ids -// .iter() -// .map(|id| member_index.get_member(id)) -// .collect::>>()?; -// for member in &members { -// let feature = member.get_feature(); -// if feature.is_meta_decl() { -// resolve_state = MemberTypeResolveState::Meta; -// break; -// } else if feature.is_file_decl() { -// resolve_state = MemberTypeResolveState::FileDecl; -// } -// } +fn resolve_type_owner_member_id( + db: &DbIndex, + member_item: &LuaMemberIndexItem, +) -> Option { + match member_item { + LuaMemberIndexItem::One(member_id) => Some(*member_id), + LuaMemberIndexItem::Many(member_ids) => { + let member_index = db.get_member_index(); + let mut resolve_state = MemberTypeResolveState::All; + let members = member_ids + .iter() + .map(|id| member_index.get_member(id)) + .collect::>>()?; + for member in &members { + let feature = member.get_feature(); + if feature.is_meta_decl() { + resolve_state = MemberTypeResolveState::Meta; + break; + } else if feature.is_file_decl() { + resolve_state = MemberTypeResolveState::FileDecl; + } + } -// match resolve_state { -// MemberTypeResolveState::All => { -// for member in members { -// if member.get_decl_type().is_member_owner() { -// return Some(member.get_id()); -// } -// } + match resolve_state { + MemberTypeResolveState::All => { + for member in members { + let member_type_cache = db + .get_type_index() + .get_type_cache(&member.get_id().into())?; + if member_type_cache.as_type().is_member_owner() { + return Some(member.get_id()); + } + } -// None -// } -// MemberTypeResolveState::Meta => { -// for member in &members { -// let feature = member.get_feature(); -// if feature.is_meta_decl() { -// return Some(member.get_id()); -// } -// } + None + } + MemberTypeResolveState::Meta => { + for member in &members { + let feature = member.get_feature(); + if feature.is_meta_decl() { + return Some(member.get_id()); + } + } -// None -// } -// MemberTypeResolveState::FileDecl => { -// for member in &members { -// let feature = member.get_feature(); -// if feature.is_file_decl() { -// return Some(member.get_id()); -// } -// } + None + } + MemberTypeResolveState::FileDecl => { + for member in &members { + let feature = member.get_feature(); + if feature.is_file_decl() { + return Some(member.get_id()); + } + } -// None -// } -// } -// } -// } -// } + None + } + } + } + } +} #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum MemberTypeResolveState { diff --git a/crates/emmylua_code_analysis/src/db_index/member/mod.rs b/crates/emmylua_code_analysis/src/db_index/member/mod.rs index bf884ed93..561d9526d 100644 --- a/crates/emmylua_code_analysis/src/db_index/member/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/member/mod.rs @@ -18,7 +18,6 @@ pub struct LuaMemberIndex { in_filed: HashMap>, owner_members: HashMap>, member_current_owner: HashMap, - member_origin_owner: HashMap, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] @@ -34,7 +33,6 @@ impl LuaMemberIndex { in_filed: HashMap::new(), owner_members: HashMap::new(), member_current_owner: HashMap::new(), - member_origin_owner: HashMap::new(), } } @@ -45,7 +43,6 @@ impl LuaMemberIndex { self.add_in_file_object(file_id, MemberOrOwner::Member(id)); if !owner.is_unknown() { self.member_current_owner.insert(id, owner.clone()); - self.member_origin_owner.insert(id, owner.clone()); self.add_in_file_object(file_id, MemberOrOwner::Owner(owner.clone())); self.add_member_to_owner(owner.clone(), id); } @@ -94,8 +91,17 @@ impl LuaMemberIndex { let item = member_map.get(&key)?.clone(); let new_items = if self.is_item_only_meta(&item) { match item { - LuaMemberIndexItem::One(old_id) => LuaMemberIndexItem::Many(vec![id, old_id]), + LuaMemberIndexItem::One(old_id) => { + if old_id == id { + return Some(()); + } + LuaMemberIndexItem::Many(vec![id, old_id]) + } LuaMemberIndexItem::Many(mut ids) => { + if ids.contains(&id) { + return Some(()); + } + ids.push(id); LuaMemberIndexItem::Many(ids) } @@ -178,6 +184,18 @@ impl LuaMemberIndex { Some(members) } + #[allow(unused)] + pub fn get_member_item_by_member_id( + &self, + member_id: LuaMemberId, + ) -> Option<&LuaMemberIndexItem> { + let owner = self.member_current_owner.get(&member_id)?; + let member_key = self.members.get(&member_id)?.get_key(); + let member_items = self.owner_members.get(owner)?; + let item = member_items.get(member_key)?; + Some(item) + } + pub fn get_sorted_members(&self, owner: &LuaMemberOwner) -> Option> { let mut members = self.get_members(owner)?; members.sort_by_key(|member| member.get_sort_key()); @@ -199,10 +217,6 @@ impl LuaMemberIndex { pub fn get_current_owner(&self, id: &LuaMemberId) -> Option<&LuaMemberOwner> { self.member_current_owner.get(id) } - - pub fn get_origin_owner(&self, id: &LuaMemberId) -> Option<&LuaMemberOwner> { - self.member_origin_owner.get(id) - } } impl LuaIndex for LuaMemberIndex { @@ -214,7 +228,6 @@ impl LuaIndex for LuaMemberIndex { MemberOrOwner::Member(member_id) => { self.members.remove(&member_id); self.member_current_owner.remove(&member_id); - self.member_origin_owner.remove(&member_id); } MemberOrOwner::Owner(owner) => { owners.insert(owner); diff --git a/crates/emmylua_code_analysis/src/diagnostic/checker/assign_type_mismatch.rs b/crates/emmylua_code_analysis/src/diagnostic/checker/assign_type_mismatch.rs index 78a7923d0..bad0181ea 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/checker/assign_type_mismatch.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/checker/assign_type_mismatch.rs @@ -77,13 +77,11 @@ fn check_name_expr( SemanticDeclLevel::default(), )?; let origin_type = match semantic_decl { - LuaSemanticDeclId::LuaDecl(decl_id) => { - let decl = semantic_model - .get_db() - .get_decl_index() - .get_decl(&decl_id)?; - decl.get_type().cloned() - } + LuaSemanticDeclId::LuaDecl(decl_id) => semantic_model + .get_db() + .get_type_index() + .get_type_cache(&decl_id.into()) + .map(|cache| cache.as_type().clone()), _ => None, }; check_assign_type_mismatch( @@ -136,15 +134,20 @@ fn check_local_stat( for (idx, var) in vars.iter().enumerate() { let name_token = var.get_name_token()?; let decl_id = LuaDeclId::new(semantic_model.get_file_id(), name_token.get_position()); - let decl = semantic_model + let range = semantic_model .get_db() .get_decl_index() - .get_decl(&decl_id)?; - let name_type = decl.get_type()?; + .get_decl(&decl_id)? + .get_range(); + let name_type = semantic_model + .get_db() + .get_type_index() + .get_type_cache(&decl_id.into()) + .map(|cache| cache.as_type().clone())?; check_assign_type_mismatch( context, semantic_model, - decl.get_range(), + range, Some(name_type.clone()), value_types.get(idx)?.0.clone(), false, diff --git a/crates/emmylua_code_analysis/src/diagnostic/checker/missing_fields.rs b/crates/emmylua_code_analysis/src/diagnostic/checker/missing_fields.rs index 1a3174091..7f55c8029 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/checker/missing_fields.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/checker/missing_fields.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use emmylua_parser::{LuaAstNode, LuaTableExpr}; -use crate::{DiagnosticCode, LuaMemberOwner, LuaType, LuaTypeDeclId, SemanticModel}; +use crate::{DiagnosticCode, LuaMemberOwner, LuaType, LuaTypeCache, LuaTypeDeclId, SemanticModel}; use super::{humanize_lint_type, Checker, DiagnosticContext}; use itertools::Itertools; @@ -91,12 +91,14 @@ fn get_required_fields( for super_type in types { match super_type { LuaType::Ref(type_decl_id) => process_type_decl_id( + &context, member_index, &mut required_fields, &mut optional_type, type_decl_id.clone(), ), LuaType::Generic(generic_type) => process_type_decl_id( + &context, member_index, &mut required_fields, &mut optional_type, @@ -121,6 +123,7 @@ fn get_required_fields( } fn process_type_decl_id( + context: &DiagnosticContext, member_index: &crate::LuaMemberIndex, required_fields: &mut HashSet, optional_type: &mut HashSet, @@ -129,7 +132,13 @@ fn get_required_fields( let members = member_index.get_members(&LuaMemberOwner::Type(type_decl_id))?; for member in members { let name = member.get_key().to_path(); - let decl_type = member.get_decl_type(); + let decl_type = context + .db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)) + .as_type() + .clone(); record_required_fields(required_fields, optional_type, name, decl_type); } diff --git a/crates/emmylua_code_analysis/src/diagnostic/checker/undefined_global.rs b/crates/emmylua_code_analysis/src/diagnostic/checker/undefined_global.rs index be5ef8f28..3c735494e 100644 --- a/crates/emmylua_code_analysis/src/diagnostic/checker/undefined_global.rs +++ b/crates/emmylua_code_analysis/src/diagnostic/checker/undefined_global.rs @@ -3,7 +3,7 @@ use std::collections::HashSet; use emmylua_parser::{LuaAstNode, LuaClosureExpr, LuaNameExpr}; use rowan::TextRange; -use crate::{DiagnosticCode, LuaMemberKey, LuaSignatureId, SemanticModel}; +use crate::{DiagnosticCode, LuaSignatureId, SemanticModel}; use super::{Checker, DiagnosticContext}; @@ -54,9 +54,11 @@ fn check_name_expr( return Some(()); } - let decl_index = semantic_model.get_db().get_decl_index(); - let member_key = LuaMemberKey::Name(name_text.clone().into()); - if decl_index.get_global_decl_id(&member_key).is_some() { + if semantic_model + .get_db() + .get_global_index() + .is_exist_global_decl(&name_text) + { return Some(()); } diff --git a/crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs b/crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs index 525512970..34d4cc315 100644 --- a/crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs +++ b/crates/emmylua_code_analysis/src/semantic/infer/infer_index.rs @@ -16,7 +16,7 @@ use crate::{ InFiled, LuaFlowId, LuaInferCache, LuaInstanceType, LuaMemberOwner, LuaOperatorOwner, TypeOps, }; -use super::{infer_expr, InferFailReason, InferResult}; +use super::{infer_expr, infer_name::infer_global_type, InferFailReason, InferResult}; pub fn infer_index_expr( db: &DbIndex, @@ -753,19 +753,7 @@ fn infer_global_field_member( .get_name() .ok_or(InferFailReason::None)? .get_name_text(); - let global_member = db - .get_decl_index() - .get_global_decl_id(&LuaMemberKey::Name(name.to_string().into())) - .ok_or(InferFailReason::None)?; - - let decl = db - .get_decl_index() - .get_decl(&global_member) - .ok_or(InferFailReason::None)?; - match decl.get_type() { - Some(typ) => Ok(typ.clone()), - None => Err(InferFailReason::UnResolveDeclType(decl.get_id())), - } + infer_global_type(db, name) } fn infer_namespace_member( diff --git a/crates/emmylua_code_analysis/src/semantic/infer/infer_name.rs b/crates/emmylua_code_analysis/src/semantic/infer/infer_name.rs index 184c0c6fb..dd5a4194f 100644 --- a/crates/emmylua_code_analysis/src/semantic/infer/infer_name.rs +++ b/crates/emmylua_code_analysis/src/semantic/infer/infer_name.rs @@ -58,8 +58,8 @@ fn get_decl_type(db: &DbIndex, decl: &LuaDecl) -> InferResult { return infer_global_type(db, name); } - if let Some(typ) = decl.get_type() { - return Ok(typ.clone()); + if let Some(type_cache) = db.get_type_index().get_type_cache(&decl.get_id().into()) { + return Ok(type_cache.as_type().clone()); } if decl.is_param() { @@ -76,7 +76,7 @@ fn infer_self(db: &DbIndex, cache: &mut LuaInferCache, name_expr: LuaNameExpr) - .get_decl_tree(&file_id) .ok_or(InferFailReason::None)?; let id = tree - .find_self_decl(db, name_expr.clone()) + .find_self_decl(name_expr.clone()) .ok_or(InferFailReason::None)?; match id { LuaDeclOrMemberId::Decl(decl_id) => { @@ -104,17 +104,7 @@ fn infer_self(db: &DbIndex, cache: &mut LuaInferCache, name_expr: LuaNameExpr) - Ok(decl_type) } - LuaDeclOrMemberId::Member(member_id) => { - let member = db - .get_member_index() - .get_member(&member_id) - .ok_or(InferFailReason::None)?; - let typ = member.get_option_decl_type(); - match typ { - Some(typ) => Ok(typ), - None => Err(InferFailReason::UnResolveMemberType(member.get_id())), - } - } + LuaDeclOrMemberId::Member(member_id) => find_decl_member_type(db, member_id), } } @@ -154,17 +144,11 @@ pub fn infer_param(db: &DbIndex, decl: &LuaDecl) -> InferResult { } fn find_decl_member_type(db: &DbIndex, member_id: LuaMemberId) -> InferResult { - let member = db + let item = db .get_member_index() - .get_member(&member_id) + .get_member_item_by_member_id(member_id) .ok_or(InferFailReason::None)?; - let key = member.get_key(); - let owner = member.get_owner(); - let member_item = db - .get_member_index() - .get_member_item(&owner, key) - .ok_or(InferFailReason::None)?; - member_item.resolve_type(db) + item.resolve_type(db) } fn find_param_type_from_type( @@ -233,35 +217,36 @@ fn find_param_type_from_type( None } -fn infer_global_type(db: &DbIndex, name: &str) -> InferResult { - let decl_index = db.get_decl_index(); - let decls = decl_index.get_global_decls_by_name(name); - if decls.len() == 1 { - let decl = decl_index - .get_decl(&decls[0]) - .ok_or(InferFailReason::None)?; - return match decl.get_type() { - Some(typ) => Ok(typ.clone()), - None => Err(InferFailReason::UnResolveDeclType(decl.get_id())), +pub fn infer_global_type(db: &DbIndex, name: &str) -> InferResult { + let decl_ids = db + .get_global_index() + .get_global_decl_ids(name) + .ok_or(InferFailReason::None)?; + if decl_ids.len() == 1 { + let id = decl_ids[0]; + return match db.get_type_index().get_type_cache(&id.into()) { + Some(type_cache) => Ok(type_cache.as_type().clone()), + None => Err(InferFailReason::UnResolveDeclType(id)), }; } let mut valid_type = LuaType::Unknown; let mut last_resolve_reason = InferFailReason::None; - for decl_id in decls { - let decl = decl_index.get_decl(&decl_id).ok_or(InferFailReason::None)?; - match decl.get_type() { - Some(typ) => { + for decl_id in decl_ids { + let decl_type_cache = db.get_type_index().get_type_cache(&decl_id.clone().into()); + match decl_type_cache { + Some(type_cache) => { + let typ = type_cache.as_type(); if typ.is_def() || typ.is_ref() || typ.is_function() { return Ok(typ.clone()); } - if typ.is_table() { + if type_cache.is_table() { valid_type = typ.clone(); } } None => { - last_resolve_reason = InferFailReason::UnResolveDeclType(decl.get_id()); + last_resolve_reason = InferFailReason::UnResolveDeclType(*decl_id); } } } diff --git a/crates/emmylua_code_analysis/src/semantic/infer/infer_table.rs b/crates/emmylua_code_analysis/src/semantic/infer/infer_table.rs index d207e8865..7fea49765 100644 --- a/crates/emmylua_code_analysis/src/semantic/infer/infer_table.rs +++ b/crates/emmylua_code_analysis/src/semantic/infer/infer_table.rs @@ -170,12 +170,10 @@ pub fn infer_table_field_value_should_be( } let member_id = LuaMemberId::new(table_field.get_syntax_id(), cache.get_file_id()); - if let Some(member) = db.get_member_index().get_member(&member_id) { - match member.get_option_decl_type() { - Some(typ) => return Ok(typ), - None => {} - } - } + match db.get_type_index().get_type_cache(&member_id.into()) { + Some(type_cache) => return Ok(type_cache.as_type().clone()), + None => {} + }; Err(reason) } @@ -230,12 +228,13 @@ fn infer_table_field_type_by_parent( field: LuaTableField, ) -> InferResult { let member_id = LuaMemberId::new(field.get_syntax_id(), cache.get_file_id()); - if let Some(member) = db.get_member_index().get_member(&member_id) { - match member.get_option_decl_type() { - Some(LuaType::TableConst(_)) => {} - Some(typ) => return Ok(typ), - None => return Err(InferFailReason::UnResolveMemberType(member.get_id())), + if let Some(type_cache) = db.get_type_index().get_type_cache(&member_id.into()) { + match type_cache.as_type() { + LuaType::TableConst(_) => {} + typ => return Ok(typ.clone()), } + } else { + return Err(InferFailReason::UnResolveMemberType(member_id)); } let parnet_table_expr = field @@ -288,14 +287,11 @@ fn infer_table_type_by_local( let local_name = local_names.get(num).ok_or(InferFailReason::None)?; let decl_id = LuaDeclId::new(cache.get_file_id(), local_name.get_position()); - let decl = db - .get_decl_index() - .get_decl(&decl_id) - .ok_or(InferFailReason::None)?; - let typ = decl.get_type(); - match typ { - Some(LuaType::TableConst(_)) => Err(InferFailReason::None), - Some(typ) => Ok(typ.clone()), + match db.get_type_index().get_type_cache(&decl_id.into()) { + Some(type_cache) => match type_cache.as_type() { + LuaType::TableConst(_) => Err(InferFailReason::None), + typ => return Ok(typ.clone()), + }, None => Err(InferFailReason::UnResolveDeclType(decl_id)), } } @@ -316,11 +312,12 @@ fn infer_table_type_by_assign_stat( let name = vars.get(num).ok_or(InferFailReason::None)?; let decl_id = LuaDeclId::new(cache.get_file_id(), name.get_position()); - let decl = db.get_decl_index().get_decl(&decl_id); - if let Some(decl) = decl { - match decl.get_type() { - Some(LuaType::TableConst(_)) => Err(InferFailReason::None), - Some(typ) => Ok(typ.clone()), + if db.get_decl_index().get_decl(&decl_id).is_some() { + match db.get_type_index().get_type_cache(&decl_id.into()) { + Some(type_cache) => match type_cache.as_type() { + LuaType::TableConst(_) => Err(InferFailReason::None), + typ => return Ok(typ.clone()), + }, None => Err(InferFailReason::UnResolveDeclType(decl_id)), } } else { diff --git a/crates/emmylua_code_analysis/src/semantic/member/infer_members.rs b/crates/emmylua_code_analysis/src/semantic/member/infer_members.rs index 10a71e134..973954def 100644 --- a/crates/emmylua_code_analysis/src/semantic/member/infer_members.rs +++ b/crates/emmylua_code_analysis/src/semantic/member/infer_members.rs @@ -57,7 +57,11 @@ fn infer_normal_members(db: &DbIndex, member_owner: LuaMemberOwner) -> InferMemb members.push(LuaMemberInfo { property_owner_id: Some(LuaSemanticDeclId::Member(member.get_id())), key: member.get_key().clone(), - typ: member.get_decl_type(), + typ: db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .map(|t| t.as_type().clone()) + .unwrap_or(LuaType::Unknown), feature: Some(member.get_feature()), overload_index: None, }); @@ -91,7 +95,11 @@ fn infer_custom_type_members( members.push(LuaMemberInfo { property_owner_id: Some(LuaSemanticDeclId::Member(member.get_id())), key: member.get_key().clone(), - typ: member.get_decl_type(), + typ: db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .map(|t| t.as_type().clone()) + .unwrap_or(LuaType::Unknown), feature: Some(member.get_feature()), overload_index: None, }); @@ -220,17 +228,21 @@ fn infer_generic_members( fn infer_global_members(db: &DbIndex) -> InferMembersResult { let mut members = Vec::new(); - let decl_index = db.get_decl_index(); - let global_decls = decl_index.get_global_decls(); + let global_decls = db.get_global_index().get_all_global_decl_ids(); for decl_id in global_decls { - let decl = decl_index.get_decl(&decl_id)?; - members.push(LuaMemberInfo { - property_owner_id: Some(LuaSemanticDeclId::LuaDecl(decl_id)), - key: LuaMemberKey::Name(decl.get_name().to_string().into()), - typ: decl.get_type().cloned().unwrap_or(LuaType::Unknown), - feature: None, - overload_index: None, - }); + if let Some(decl) = db.get_decl_index().get_decl(&decl_id) { + members.push(LuaMemberInfo { + property_owner_id: Some(LuaSemanticDeclId::LuaDecl(decl_id)), + key: LuaMemberKey::Name(decl.get_name().to_string().into()), + typ: db + .get_type_index() + .get_type_cache(&decl_id.into()) + .map(|t| t.as_type().clone()) + .unwrap_or(LuaType::Unknown), + feature: None, + overload_index: None, + }); + } } Some(members) diff --git a/crates/emmylua_code_analysis/src/semantic/mod.rs b/crates/emmylua_code_analysis/src/semantic/mod.rs index 224532c6e..a3151fb6f 100644 --- a/crates/emmylua_code_analysis/src/semantic/mod.rs +++ b/crates/emmylua_code_analysis/src/semantic/mod.rs @@ -37,7 +37,7 @@ use crate::{ db_index::{DbIndex, LuaType}, FileId, }; -use crate::{LuaFunctionType, LuaMemberKey}; +use crate::{LuaFunctionType, LuaMemberKey, LuaTypeOwner}; pub use generic::{instantiate_type_generic, TypeSubstitutor}; pub use infer::InferFailReason; pub(crate) use infer::{infer_call_expr_func, infer_expr}; @@ -248,6 +248,15 @@ impl<'a> SemanticModel<'a> { pub fn get_config(&self) -> &RefCell { &self.infer_cache } + + pub fn get_type(&self, type_owner: LuaTypeOwner) -> LuaType { + self.db + .get_type_index() + .get_type_cache(&type_owner) + .map(|cache| cache.as_type()) + .unwrap_or(&LuaType::Unknown) + .clone() + } } /// Guard to prevent infinite recursion diff --git a/crates/emmylua_code_analysis/src/semantic/reference/mod.rs b/crates/emmylua_code_analysis/src/semantic/reference/mod.rs index c68387f69..7bc207a1c 100644 --- a/crates/emmylua_code_analysis/src/semantic/reference/mod.rs +++ b/crates/emmylua_code_analysis/src/semantic/reference/mod.rs @@ -29,11 +29,8 @@ fn is_member_reference_to( node_member_id: LuaMemberId, member_id: LuaMemberId, ) -> Option { - let node_owner = db - .get_member_index() - .get_member(&node_member_id)? - .get_owner(); - let owner = db.get_member_index().get_member(&member_id)?.get_owner(); + let node_owner = db.get_member_index().get_current_owner(&node_member_id)?; + let owner = db.get_member_index().get_current_owner(&member_id)?; Some(node_owner == owner) } diff --git a/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs b/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs index 23521864b..522971cbe 100644 --- a/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs +++ b/crates/emmylua_code_analysis/src/semantic/semantic_info/infer_expr_semantic_decl.rs @@ -6,7 +6,7 @@ use emmylua_parser::{ use crate::{ semantic::member::get_buildin_type_map_type_id, DbIndex, LuaDeclId, LuaDeclOrMemberId, LuaInferCache, LuaInstanceType, LuaMemberId, LuaMemberKey, LuaMemberOwner, LuaSemanticDeclId, - LuaType, LuaTypeDeclId, LuaUnionType, + LuaType, LuaTypeCache, LuaTypeDeclId, LuaUnionType, }; use super::{ @@ -70,7 +70,11 @@ fn infer_name_expr_semantic_decl( return Some(LuaSemanticDeclId::LuaDecl(decl_id)); } - let is_function = decl.get_type().map_or(false, |typ| typ.is_function()); + let decl_type = db + .get_type_index() + .get_type_cache(&decl_id.into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)); + let is_function = decl_type.is_function(); if decl.is_local() && !is_function { return Some(LuaSemanticDeclId::LuaDecl(decl_id)); } @@ -122,11 +126,38 @@ fn get_name_decl_id( } } - let decl_id = db - .get_decl_index() - .get_global_decl_id(&LuaMemberKey::Name(name.into())); + get_global_decl_id(db, name) +} + +fn get_global_decl_id(db: &DbIndex, name: &str) -> Option { + let decl_ids = db.get_global_index().get_global_decl_ids(name)?; + if decl_ids.len() == 1 { + return Some(decl_ids[0]); + } - decl_id + let mut last_valid_decl_id = None; + for decl_id in decl_ids { + let decl_type_cache = db.get_type_index().get_type_cache(&decl_id.clone().into()); + match decl_type_cache { + Some(type_cache) => { + let typ = type_cache.as_type(); + if typ.is_def() || typ.is_ref() || typ.is_function() { + return Some(*decl_id); + } + + if type_cache.is_table() { + last_valid_decl_id = Some(decl_id) + } + } + None => {} + } + } + + if last_valid_decl_id.is_none() && decl_ids.len() > 0 { + return Some(decl_ids[0]); + } + + last_valid_decl_id.cloned() } fn infer_self_semantic_decl( @@ -136,7 +167,7 @@ fn infer_self_semantic_decl( ) -> Option { let file_id = cache.get_file_id(); let tree = db.get_decl_index().get_decl_tree(&file_id)?; - let id = tree.find_self_decl(db, name_expr)?; + let id = tree.find_self_decl(name_expr)?; match id { LuaDeclOrMemberId::Decl(decl_id) => { return Some(LuaSemanticDeclId::LuaDecl(decl_id)); @@ -250,12 +281,7 @@ fn infer_member_semantic_decl_by_member_key( member_key, semantic_guard.next_level()?, ), - LuaType::Global => infer_global_member_semantic_decl_by_member_key( - db, - cache, - member_key, - semantic_guard.next_level()?, - ), + LuaType::Global => infer_global_member_semantic_decl_by_member_key(db, member_key), _ => None, } } @@ -369,15 +395,8 @@ fn infer_instance_member_semantic_decl_by_member_key( fn infer_global_member_semantic_decl_by_member_key( db: &DbIndex, - _: &LuaInferCache, member_key: &LuaMemberKey, - _: SemanticDeclGuard, ) -> Option { - let decl_id = db.get_decl_index().get_global_decl_id(member_key); - - if decl_id.is_some() { - Some(LuaSemanticDeclId::LuaDecl(decl_id.unwrap())) - } else { - None - } + let name = member_key.get_name()?; + get_global_decl_id(db, name).map(|decl_id| LuaSemanticDeclId::LuaDecl(decl_id)) } diff --git a/crates/emmylua_code_analysis/src/semantic/semantic_info/mod.rs b/crates/emmylua_code_analysis/src/semantic/semantic_info/mod.rs index 4ae291718..e16de5d75 100644 --- a/crates/emmylua_code_analysis/src/semantic/semantic_info/mod.rs +++ b/crates/emmylua_code_analysis/src/semantic/semantic_info/mod.rs @@ -2,7 +2,10 @@ mod infer_expr_semantic_decl; mod semantic_decl_level; mod semantic_guard; -use crate::{DbIndex, LuaDeclExtra, LuaDeclId, LuaMemberId, LuaSemanticDeclId, LuaType, TypeOps}; +use crate::{ + DbIndex, LuaDeclExtra, LuaDeclId, LuaMemberId, LuaSemanticDeclId, LuaType, LuaTypeCache, + TypeOps, +}; use emmylua_parser::{ LuaAstNode, LuaAstToken, LuaDocNameType, LuaDocTag, LuaExpr, LuaLocalName, LuaSyntaxKind, LuaSyntaxNode, LuaSyntaxToken, LuaTableField, @@ -29,10 +32,12 @@ pub fn infer_token_semantic_info( LuaSyntaxKind::ForStat | LuaSyntaxKind::ForRangeStat | LuaSyntaxKind::LocalName => { let file_id = cache.get_file_id(); let decl_id = LuaDeclId::new(file_id, token.text_range().start()); - let decl = db.get_decl_index().get_decl(&decl_id)?; - let typ = decl.get_type().cloned().unwrap_or(LuaType::Unknown); + let type_cache = db + .get_type_index() + .get_type_cache(&decl_id.into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)); Some(SemanticInfo { - typ, + typ: type_cache.as_type().clone(), semantic_decl: Some(LuaSemanticDeclId::LuaDecl(decl_id)), }) } @@ -87,10 +92,12 @@ pub fn infer_node_semantic_info( table_field_node if LuaTableField::can_cast(table_field_node.kind().into()) => { let table_field = LuaTableField::cast(table_field_node)?; let member_id = LuaMemberId::new(table_field.get_syntax_id(), cache.get_file_id()); - let member = db.get_member_index().get_member(&member_id)?; - let typ = member.get_decl_type().clone(); + let type_cache = db + .get_type_index() + .get_type_cache(&member_id.into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)); Some(SemanticInfo { - typ, + typ: type_cache.as_type().clone(), semantic_decl: Some(LuaSemanticDeclId::Member(member_id)), }) } @@ -119,10 +126,12 @@ pub fn infer_node_semantic_info( } LuaDocTag::Field(field) => { let member_id = LuaMemberId::new(field.get_syntax_id(), cache.get_file_id()); - let member = db.get_member_index().get_member(&member_id)?; - let typ = member.get_decl_type(); + let type_cache = db + .get_type_index() + .get_type_cache(&member_id.into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)); Some(SemanticInfo { - typ: typ.clone(), + typ: type_cache.as_type().clone(), semantic_decl: Some(LuaSemanticDeclId::Member(member_id)), }) } diff --git a/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/table_generic_check.rs b/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/table_generic_check.rs index e7d127235..98dd31572 100644 --- a/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/table_generic_check.rs +++ b/crates/emmylua_code_analysis/src/semantic/type_check/complex_type/table_generic_check.rs @@ -1,7 +1,8 @@ use crate::{ check_type_compact, semantic::type_check::{check_general_type_compact, type_check_guard::TypeCheckGuard}, - DbIndex, LuaMemberKey, LuaMemberOwner, LuaType, TypeCheckFailReason, TypeCheckResult, + DbIndex, LuaMemberKey, LuaMemberOwner, LuaType, LuaTypeCache, TypeCheckFailReason, + TypeCheckResult, }; pub fn check_table_generic_type_compact( @@ -131,7 +132,11 @@ fn check_table_generic_compact_member_owner( _ => LuaType::Any, }; - let member_type = member.get_decl_type(); + let member_type = db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)) + .as_type(); if check_general_type_compact(db, source_key, &key_type, check_guard.next_level()?).is_err() || check_general_type_compact(db, source_value, &member_type, check_guard.next_level()?) .is_err() diff --git a/crates/emmylua_code_analysis/src/semantic/type_check/ref_type.rs b/crates/emmylua_code_analysis/src/semantic/type_check/ref_type.rs index a28dd53d0..415fa059d 100644 --- a/crates/emmylua_code_analysis/src/semantic/type_check/ref_type.rs +++ b/crates/emmylua_code_analysis/src/semantic/type_check/ref_type.rs @@ -1,8 +1,8 @@ use std::collections::HashMap; use crate::{ - humanize_type, DbIndex, LuaMemberKey, LuaMemberOwner, LuaType, LuaTypeDeclId, LuaUnionType, - RenderLevel, + humanize_type, DbIndex, LuaMemberKey, LuaMemberOwner, LuaType, LuaTypeCache, LuaTypeDeclId, + LuaUnionType, RenderLevel, }; use super::{ @@ -73,14 +73,17 @@ pub fn check_ref_type_compact( } } else { for member in enum_members { - let member_type = member.get_decl_type(); - let member_fake_type = match member_type { - LuaType::StringConst(s) => &LuaType::DocStringConst(s.clone().into()), - LuaType::IntegerConst(i) => &LuaType::DocIntegerConst(i.clone()), - _ => &member_type, - }; - - union_types.push(member_fake_type.clone()); + if let Some(type_cache) = + db.get_type_index().get_type_cache(&member.get_id().into()) + { + let member_fake_type = match type_cache.as_type() { + LuaType::StringConst(s) => &LuaType::DocStringConst(s.clone().into()), + LuaType::IntegerConst(i) => &LuaType::DocIntegerConst(i.clone()), + _ => &type_cache.as_type(), + }; + + union_types.push(member_fake_type.clone()); + } } } @@ -164,14 +167,22 @@ fn check_ref_type_compact_table( }; for source_member in source_type_members { - let source_member_type = source_member.get_decl_type(); + let source_member_type = db + .get_type_index() + .get_type_cache(&source_member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Any)) + .as_type(); let key = source_member.get_key(); if let Some(table_member_id) = table_member_map.get(key) { let table_member = member_index .get_member(table_member_id) .ok_or(TypeCheckFailReason::TypeNotMatch)?; - let table_member_type = table_member.get_decl_type(); + let table_member_type = db + .get_type_index() + .get_type_cache(&table_member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Any)) + .as_type(); if !check_general_type_compact( db, &source_member_type, diff --git a/crates/emmylua_code_analysis/src/semantic/visibility/mod.rs b/crates/emmylua_code_analysis/src/semantic/visibility/mod.rs index 3db0a8a82..4443a4933 100644 --- a/crates/emmylua_code_analysis/src/semantic/visibility/mod.rs +++ b/crates/emmylua_code_analysis/src/semantic/visibility/mod.rs @@ -52,7 +52,7 @@ fn check_visibility_by_visibility( ) -> Option { let member_owner = match property_owner { LuaSemanticDeclId::Member(member_id) => { - db.get_member_index().get_member(&member_id)?.get_owner() + db.get_member_index().get_current_owner(&member_id)? } _ => return Some(true), }; diff --git a/crates/emmylua_doc_cli/src/markdown_generator/gen/global_gen.rs b/crates/emmylua_doc_cli/src/markdown_generator/gen/global_gen.rs index a5cc19647..52c36aca6 100644 --- a/crates/emmylua_doc_cli/src/markdown_generator/gen/global_gen.rs +++ b/crates/emmylua_doc_cli/src/markdown_generator/gen/global_gen.rs @@ -32,8 +32,11 @@ pub fn generate_global_markdown( doc.name = name.to_string(); doc.property = collect_property(db, LuaSemanticDeclId::LuaDecl(decl.get_id())); + let decl_type = db + .get_type_index() + .get_type_cache(&decl_id.clone().into())?; let mut template_name = "lua_global_template.tl"; - match &decl.get_type()? { + match decl_type.as_type() { LuaType::TableConst(table) => { let member_owner = LuaMemberOwner::Element(table.clone()); generate_member_owner_module(db, member_owner, name, &mut doc)?; @@ -76,11 +79,11 @@ fn check_filter(db: &DbIndex, decl_id: &LuaDeclId) -> Option<()> { let module = db.get_module_index().get_module(file_id)?; if !module.workspace_id.is_main() { return None; - } - - let decl = db.get_decl_index().get_decl(decl_id)?; - let ty = decl.get_type()?; - match ty { + }; + let decl_type = db + .get_type_index() + .get_type_cache(&decl_id.clone().into())?; + match decl_type.as_type() { LuaType::Ref(_) | LuaType::Def(_) => return None, _ => {} } @@ -93,7 +96,9 @@ fn generate_simple_global(db: &DbIndex, decl: &LuaDecl, doc: &mut Doc) -> Option doc.property = collect_property(db, semantic_decl); let name = decl.get_name(); - let ty = decl.get_type().unwrap_or(&LuaType::Unknown); + let ty = db + .get_type_index() + .get_type_cache(&decl.get_id().clone().into())?; if ty.is_function() { let display = render_function_type(db, ty, &name, false); doc.display = Some(display); diff --git a/crates/emmylua_doc_cli/src/markdown_generator/gen/mod_gen.rs b/crates/emmylua_doc_cli/src/markdown_generator/gen/mod_gen.rs index 8b4d6f9d0..4af5080da 100644 --- a/crates/emmylua_doc_cli/src/markdown_generator/gen/mod_gen.rs +++ b/crates/emmylua_doc_cli/src/markdown_generator/gen/mod_gen.rs @@ -2,7 +2,7 @@ use std::path::Path; use emmylua_code_analysis::{ humanize_type, DbIndex, FileId, LuaMemberKey, LuaMemberOwner, LuaSemanticDeclId, LuaType, - ModuleInfo, RenderLevel, + LuaTypeCache, ModuleInfo, RenderLevel, }; use emmylua_parser::VisibilityKind; use tera::Tera; @@ -99,7 +99,11 @@ pub fn generate_member_owner_module( if let Some(members) = members { for member in members { - let member_typ = member.get_decl_type(); + let member_type = db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)) + .as_type(); let member_id = member.get_id(); let member_property_id = LuaSemanticDeclId::Member(member_id.clone()); let member_property = db.get_property_index().get_property(&member_property_id); @@ -119,23 +123,23 @@ pub fn generate_member_owner_module( }; let title_name = format!("{}.{}", owner_name, name); - if member_typ.is_function() { + if member_type.is_function() { let func_name = format!("{}.{}", owner_name, name); - let display = render_function_type(db, &member_typ, &func_name, false); + let display = render_function_type(db, &member_type, &func_name, false); method_members.push(MemberDoc { name: title_name, display, property: member_property, }); - } else if member_typ.is_const() { - let display = render_const_type(db, &member_typ); + } else if member_type.is_const() { + let display = render_const_type(db, &member_type); field_members.push(MemberDoc { name: title_name, display: format!("```lua\n{}.{}: {}\n```\n", owner_name, name, display), property: member_property, }); } else { - let typ_display = humanize_type(db, &member_typ, RenderLevel::Detailed); + let typ_display = humanize_type(db, &member_type, RenderLevel::Detailed); field_members.push(MemberDoc { name: title_name, display: format!("```lua\n{}.{} : {}\n```\n", owner_name, name, typ_display), diff --git a/crates/emmylua_doc_cli/src/markdown_generator/gen/typ_gen.rs b/crates/emmylua_doc_cli/src/markdown_generator/gen/typ_gen.rs index 71c198bea..45bb83544 100644 --- a/crates/emmylua_doc_cli/src/markdown_generator/gen/typ_gen.rs +++ b/crates/emmylua_doc_cli/src/markdown_generator/gen/typ_gen.rs @@ -1,8 +1,8 @@ use std::path::Path; use emmylua_code_analysis::{ - humanize_type, DbIndex, LuaMemberKey, LuaMemberOwner, LuaSemanticDeclId, LuaTypeDecl, - RenderLevel, + humanize_type, DbIndex, LuaMemberKey, LuaMemberOwner, LuaSemanticDeclId, LuaType, LuaTypeCache, + LuaTypeDecl, RenderLevel, }; use emmylua_parser::VisibilityKind; use tera::{Context, Tera}; @@ -85,7 +85,11 @@ fn generate_class_type_markdown( let mut field_members: Vec = Vec::new(); if let Some(members) = members { for member in members { - let member_typ = member.get_decl_type(); + let member_typ = db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)) + .as_type(); let member_id = member.get_id(); let member_property_id = LuaSemanticDeclId::Member(member_id.clone()); let member_property = db.get_property_index().get_property(&member_property_id); @@ -192,7 +196,11 @@ fn generate_enum_type_markdown( let mut field_members: Vec = Vec::new(); if let Some(members) = members { for member in members { - let member_typ = member.get_decl_type(); + let member_typ = db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)) + .as_type(); let member_id = member.get_id(); let member_property_id = LuaSemanticDeclId::Member(member_id.clone()); let member_property = db.get_property_index().get_property(&member_property_id); diff --git a/crates/emmylua_doc_cli/src/markdown_generator/mod.rs b/crates/emmylua_doc_cli/src/markdown_generator/mod.rs index 61ad764da..cb361f841 100644 --- a/crates/emmylua_doc_cli/src/markdown_generator/mod.rs +++ b/crates/emmylua_doc_cli/src/markdown_generator/mod.rs @@ -66,8 +66,8 @@ pub fn generate_markdown( generate_module_markdown(db, &tl, module, &module_out, &mut mkdocs_index); } - let decl_index = db.get_decl_index(); - let globals = decl_index.get_global_decls(); + let global_index = db.get_global_index(); + let globals = global_index.get_all_global_decl_ids(); for global_decl_id in globals { generate_global_markdown(db, &tl, &global_decl_id, &global_out, &mut mkdocs_index); } diff --git a/crates/emmylua_ls/src/handlers/completion/providers/env_provider.rs b/crates/emmylua_ls/src/handlers/completion/providers/env_provider.rs index 09f67e4df..2cd079530 100644 --- a/crates/emmylua_ls/src/handlers/completion/providers/env_provider.rs +++ b/crates/emmylua_ls/src/handlers/completion/providers/env_provider.rs @@ -96,7 +96,13 @@ fn add_local_env( .get_decl(&decl_id)?; ( decl.get_name().to_string(), - decl.get_type().cloned().unwrap_or(LuaType::Unknown), + builder + .semantic_model + .get_db() + .get_type_index() + .get_type_cache(&decl_id.clone().into()) + .map(|cache| cache.as_type().clone()) + .unwrap_or(LuaType::Unknown), ) }; @@ -144,8 +150,8 @@ fn add_global_env( let global_env = builder .semantic_model .get_db() - .get_decl_index() - .get_global_decls(); + .get_global_index() + .get_all_global_decl_ids(); for decl_id in global_env.iter() { let decl = builder .semantic_model @@ -155,7 +161,13 @@ fn add_global_env( let (name, typ) = { ( decl.get_name().to_string(), - decl.get_type().cloned().unwrap_or(LuaType::Unknown), + builder + .semantic_model + .get_db() + .get_type_index() + .get_type_cache(&decl_id.clone().into()) + .map(|cache| cache.as_type().clone()) + .unwrap_or(LuaType::Unknown), ) }; if duplicated_name.contains(&name) { diff --git a/crates/emmylua_ls/src/handlers/completion/providers/type_special_provider.rs b/crates/emmylua_ls/src/handlers/completion/providers/type_special_provider.rs index 7bff5eeef..4fc193618 100644 --- a/crates/emmylua_ls/src/handlers/completion/providers/type_special_provider.rs +++ b/crates/emmylua_ls/src/handlers/completion/providers/type_special_provider.rs @@ -1,7 +1,7 @@ use emmylua_code_analysis::{ - InferGuard, LuaDeclLocation, LuaFunctionType, LuaMember, LuaMemberKey, LuaMemberOwner, - LuaMultiLineUnion, LuaSemanticDeclId, LuaType, LuaTypeDeclId, LuaUnionType, RenderLevel, - SemanticDeclLevel, + DbIndex, InferGuard, LuaDeclLocation, LuaFunctionType, LuaMember, LuaMemberKey, LuaMemberOwner, + LuaMultiLineUnion, LuaSemanticDeclId, LuaType, LuaTypeCache, LuaTypeDeclId, LuaUnionType, + RenderLevel, SemanticDeclLevel, }; use emmylua_parser::{ LuaAst, LuaAstNode, LuaAstToken, LuaCallArgList, LuaCallExpr, LuaClosureExpr, LuaComment, @@ -279,8 +279,9 @@ fn push_function_overloads_param( LuaSemanticDeclId::Member(member_id) => { let member = member_index.get_member(&member_id)?; let key = member.get_key().to_path(); - let members = member_index.get_members(&member.get_owner())?; - let functions = filter_function_members(members, key); + let owner = member_index.get_current_owner(&member_id)?; + let members = member_index.get_members(owner)?; + let functions = filter_function_members(builder.semantic_model.get_db(), members, key); Some(functions) } LuaSemanticDeclId::LuaDecl(decl_id) => { @@ -290,14 +291,24 @@ fn push_function_overloads_param( .get_decl_index() .get_decl(&decl_id)?; - let typ = decl.get_type()?; + let typ = builder + .semantic_model + .get_db() + .get_type_index() + .get_type_cache(&decl_id.into()) + .map(|cache| cache.as_type().clone()) + .unwrap_or(LuaType::Unknown); match typ { LuaType::Signature(_) | LuaType::DocFunction(_) => Some(vec![typ.clone()]), _ => { let key = decl.get_name(); let type_id = LuaTypeDeclId::new(decl.get_name()); let members = member_index.get_members(&LuaMemberOwner::Type(type_id))?; - let functions = filter_function_members(members, key.to_string()); + let functions = filter_function_members( + builder.semantic_model.get_db(), + members, + key.to_string(), + ); Some(functions) } } @@ -338,18 +349,25 @@ fn push_function_overloads_param( } /// 过滤出函数类型的成员 - fn filter_function_members(members: Vec<&LuaMember>, key: String) -> Vec { - members - .into_iter() - .filter(|it| { - it.get_key().to_path() == key - && matches!( - it.get_decl_type(), - LuaType::Signature(_) | LuaType::DocFunction(_) - ) - }) - .map(|it| it.get_decl_type()) - .collect() + fn filter_function_members( + db: &DbIndex, + members: Vec<&LuaMember>, + key: String, + ) -> Vec { + let mut result_members = vec![]; + for member in members { + if member.get_key().to_path() == key { + let member_type = db + .get_type_index() + .get_type_cache(&member.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)); + if let LuaType::Signature(_) | LuaType::DocFunction(_) = member_type.as_type() { + result_members.push(member_type.as_type().clone()); + } + } + } + + result_members } /// 判断前面的参数是否匹配 @@ -467,7 +485,19 @@ fn add_enum_members_completion( .get_member_index() .get_members(&owner_id)? .iter() - .map(|it| (it.get_key().clone(), it.get_decl_type())) + .map(|it| { + ( + it.get_key().clone(), + builder + .semantic_model + .get_db() + .get_type_index() + .get_type_cache(&it.get_id().into()) + .unwrap_or(&LuaTypeCache::InferType(LuaType::Unknown)) + .as_type() + .clone(), + ) + }) .collect::>(); let file_id = builder.semantic_model.get_file_id(); let is_same_file = locations.iter().all(|it| it.file_id == file_id); diff --git a/crates/emmylua_ls/src/handlers/document_symbol/builder.rs b/crates/emmylua_ls/src/handlers/document_symbol/builder.rs index 93b417fad..836de3fa5 100644 --- a/crates/emmylua_ls/src/handlers/document_symbol/builder.rs +++ b/crates/emmylua_ls/src/handlers/document_symbol/builder.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use emmylua_code_analysis::{ - DbIndex, FileId, LuaDecl, LuaDeclId, LuaDeclarationTree, LuaDocument, LuaType, + DbIndex, FileId, LuaDecl, LuaDeclId, LuaDeclarationTree, LuaDocument, LuaType, LuaTypeOwner, }; use emmylua_parser::{LuaAstNode, LuaChunk, LuaSyntaxId, LuaSyntaxNode, LuaSyntaxToken}; use lsp_types::{DocumentSymbol, SymbolKind}; @@ -36,6 +36,19 @@ impl<'a> DocumentSymbolBuilder<'a> { self.decl_tree.get_decl(id) } + pub fn get_db(&self) -> &'a DbIndex { + self.db + } + + pub fn get_type(&self, id: LuaTypeOwner) -> LuaType { + self.db + .get_type_index() + .get_type_cache(&id) + .map(|cache| cache.as_type()) + .unwrap_or(&LuaType::Unknown) + .clone() + } + pub fn add_node_symbol(&mut self, node: LuaSyntaxNode, symbol: LuaSymbol) { let syntax_id = LuaSyntaxId::new(node.kind().into(), node.text_range()); self.document_symbols.insert(syntax_id, Box::new(symbol)); diff --git a/crates/emmylua_ls/src/handlers/document_symbol/expr.rs b/crates/emmylua_ls/src/handlers/document_symbol/expr.rs index ec41988ff..2d678376a 100644 --- a/crates/emmylua_ls/src/handlers/document_symbol/expr.rs +++ b/crates/emmylua_ls/src/handlers/document_symbol/expr.rs @@ -28,7 +28,8 @@ pub fn build_closure_expr_symbol( for param in param_list.get_params() { let decl_id = LuaDeclId::new(file_id, param.get_position()); let decl = builder.get_decl(&decl_id)?; - let desc = builder.get_symbol_kind_and_detail(decl.get_type()); + let typ = builder.get_type(decl_id.into()); + let desc = builder.get_symbol_kind_and_detail(Some(&typ)); let symbol = LuaSymbol::new( decl.get_name().to_string(), desc.1, diff --git a/crates/emmylua_ls/src/handlers/document_symbol/stats.rs b/crates/emmylua_ls/src/handlers/document_symbol/stats.rs index ad1109b13..f51804755 100644 --- a/crates/emmylua_ls/src/handlers/document_symbol/stats.rs +++ b/crates/emmylua_ls/src/handlers/document_symbol/stats.rs @@ -18,7 +18,8 @@ pub fn build_local_stat_symbol( for local_name in local_names { let decl_id = LuaDeclId::new(file_id, local_name.get_position()); let decl = builder.get_decl(&decl_id)?; - let desc = builder.get_symbol_kind_and_detail(decl.get_type()); + let typ = builder.get_type(decl_id.into()); + let desc = builder.get_symbol_kind_and_detail(Some(&typ)); let range = if simple_local { local_stat.get_range() } else { @@ -51,8 +52,8 @@ pub fn build_assign_stat_symbol( } else { decl.get_range() }; - - let desc = builder.get_symbol_kind_and_detail(decl.get_type()); + let typ = builder.get_type(decl_id.into()); + let desc = builder.get_symbol_kind_and_detail(Some(&typ)); let symbol = LuaSymbol::new(decl.get_name().to_string(), desc.1, desc.0, range); builder.add_node_symbol(var.syntax().clone(), symbol); @@ -77,7 +78,8 @@ pub fn build_for_stat_symbol( let iter_token = for_stat.get_var_name()?; let decl_id = LuaDeclId::new(file_id, iter_token.get_position()); let decl = builder.get_decl(&decl_id)?; - let desc = builder.get_symbol_kind_and_detail(decl.get_type()); + let typ = builder.get_type(decl_id.into()); + let desc = builder.get_symbol_kind_and_detail(Some(&typ)); let symbol = LuaSymbol::new( decl.get_name().to_string(), desc.1, @@ -107,7 +109,8 @@ pub fn build_for_range_stat_symbol( for var in vars { let decl_id = LuaDeclId::new(file_id, var.get_position()); let decl = builder.get_decl(&decl_id)?; - let desc = builder.get_symbol_kind_and_detail(decl.get_type()); + let typ = builder.get_type(decl_id.into()); + let desc = builder.get_symbol_kind_and_detail(Some(&typ)); let symbol = LuaSymbol::new( decl.get_name().to_string(), desc.1, @@ -129,7 +132,8 @@ pub fn build_local_func_stat_symbol( let func_name = local_func.get_local_name()?; let decl_id = LuaDeclId::new(file_id, func_name.get_position()); let decl = builder.get_decl(&decl_id)?; - let desc = builder.get_symbol_kind_and_detail(decl.get_type()); + let typ = builder.get_type(decl_id.into()); + let desc = builder.get_symbol_kind_and_detail(Some(&typ)); let symbol = LuaSymbol::new( decl.get_name().to_string(), desc.1, diff --git a/crates/emmylua_ls/src/handlers/hover/build_hover.rs b/crates/emmylua_ls/src/handlers/hover/build_hover.rs index 712e44992..1b74c2c25 100644 --- a/crates/emmylua_ls/src/handlers/hover/build_hover.rs +++ b/crates/emmylua_ls/src/handlers/hover/build_hover.rs @@ -71,20 +71,14 @@ pub fn build_hover_content<'a>( LuaSemanticDeclId::LuaDecl(decl_id) => { let effective_typ = match typ { Some(t) => t, - None => { - let decl = db.get_decl_index().get_decl(&decl_id)?; - decl.get_type()?.clone() - } + None => semantic_model.get_type(decl_id.into()), }; build_decl_hover(&mut builder, db, effective_typ, decl_id); } LuaSemanticDeclId::Member(member_id) => { let effective_typ = match typ { Some(t) => t, - None => { - let member = db.get_member_index().get_member(&member_id)?; - member.get_decl_type().clone() - } + None => semantic_model.get_type(member_id.into()), }; build_member_hover(&mut builder, db, effective_typ, member_id); } diff --git a/crates/emmylua_ls/src/handlers/hover/hover_builder.rs b/crates/emmylua_ls/src/handlers/hover/hover_builder.rs index 6c6e92bd3..b37f0e042 100644 --- a/crates/emmylua_ls/src/handlers/hover/hover_builder.rs +++ b/crates/emmylua_ls/src/handlers/hover/hover_builder.rs @@ -61,7 +61,12 @@ impl<'a> HoverBuilder<'a> { pub fn set_location_path(&mut self, owner_member: Option<&LuaMember>) { if let Some(owner_member) = owner_member { - if let LuaMemberOwner::Type(ty) = &owner_member.get_owner() { + let owner_id = self + .semantic_model + .get_db() + .get_member_index() + .get_current_owner(&owner_member.get_id()); + if let Some(LuaMemberOwner::Type(ty)) = owner_id { if ty.get_name() != ty.get_simple_name() { self.location_path = Some(MarkedString::from_markdown(format!( "{}{} `{}`", @@ -135,7 +140,12 @@ impl<'a> HoverBuilder<'a> { .get_member_index() .get_member(&id) { - if let LuaMemberOwner::Type(ty) = &member.get_owner() { + let owner_id = self + .semantic_model + .get_db() + .get_member_index() + .get_current_owner(&member.get_id()); + if let Some(LuaMemberOwner::Type(ty)) = owner_id { if is_std_by_name(&ty.get_name()) { let std_desc = hover_std_description( ty.get_name(), diff --git a/crates/emmylua_ls/src/handlers/hover/hover_humanize.rs b/crates/emmylua_ls/src/handlers/hover/hover_humanize.rs index 54e04810e..e51ee8ac6 100644 --- a/crates/emmylua_ls/src/handlers/hover/hover_humanize.rs +++ b/crates/emmylua_ls/src/handlers/hover/hover_humanize.rs @@ -99,8 +99,10 @@ fn hover_doc_function_type( let full_name = if let Some(owner_member) = owner_member { let global_name = builder.infer_prefix_global_name(owner_member); let mut name = String::new(); - let parent_owner = owner_member.get_owner(); - if let LuaMemberOwner::Type(ty) = &parent_owner.clone() { + let parent_owner = db + .get_member_index() + .get_current_owner(&owner_member.get_id()); + if let Some(LuaMemberOwner::Type(ty)) = parent_owner { // 如果是全局定义, 则使用定义时的名称 if let Some(global_name) = global_name { name.push_str(global_name); @@ -176,7 +178,10 @@ fn hover_signature_type( let full_name = if let Some(owner_member) = owner_member { let global_name = builder.infer_prefix_global_name(owner_member); let mut name = String::new(); - if let LuaMemberOwner::Type(ty) = &owner_member.get_owner() { + let parent_owner = db + .get_member_index() + .get_current_owner(&owner_member.get_id()); + if let Some(LuaMemberOwner::Type(ty)) = parent_owner { // 如果是全局定义, 则使用定义时的名称 if let Some(global_name) = global_name { name.push_str(global_name); diff --git a/crates/emmylua_ls/src/handlers/semantic_token/build_semantic_tokens.rs b/crates/emmylua_ls/src/handlers/semantic_token/build_semantic_tokens.rs index 932e36abf..d777d8035 100644 --- a/crates/emmylua_ls/src/handlers/semantic_token/build_semantic_tokens.rs +++ b/crates/emmylua_ls/src/handlers/semantic_token/build_semantic_tokens.rs @@ -1,6 +1,5 @@ use emmylua_code_analysis::{ - LuaDeclExtra, LuaMemberId, LuaMemberOwner, LuaSemanticDeclId, LuaType, SemanticDeclLevel, - SemanticModel, + LuaMemberId, LuaMemberOwner, LuaSemanticDeclId, LuaType, SemanticDeclLevel, SemanticModel, }; use emmylua_parser::{ LuaAst, LuaAstNode, LuaAstToken, LuaDocFieldKey, LuaDocObjectFieldKey, LuaExpr, @@ -432,18 +431,17 @@ fn build_node_semantic_token( .find_decl(name.syntax().clone().into(), SemanticDeclLevel::default()); if let Some(property_owner) = semantic_decl { if let LuaSemanticDeclId::Member(member_id) = property_owner { - let member = semantic_model - .get_db() - .get_member_index() - .get_member(&member_id)?; - let decl = member.get_decl_type(); - if decl.is_function() { + let decl_type = semantic_model.get_type(member_id.into()); + if decl_type.is_function() { builder.push(name.syntax(), SemanticTokenType::FUNCTION); return Some(()); } - let owner_id = member.get_owner(); - if let LuaMemberOwner::Type(type_id) = owner_id { + let owner_id = semantic_model + .get_db() + .get_member_index() + .get_current_owner(&member_id); + if let Some(LuaMemberOwner::Type(type_id)) = owner_id { if let Some(type_decl) = semantic_model .get_db() .get_type_index() @@ -467,8 +465,11 @@ fn build_node_semantic_token( .get_member_index() .get_member(&owner_id) { - let owner_id = member.get_owner(); - if let LuaMemberOwner::Type(type_id) = owner_id { + let owner_id = semantic_model + .get_db() + .get_member_index() + .get_current_owner(&member.get_id()); + if let Some(LuaMemberOwner::Type(type_id)) = owner_id { if let Some(type_decl) = semantic_model .get_db() .get_type_index() @@ -517,12 +518,8 @@ fn build_node_semantic_token( fn is_class_def(semantic_model: &SemanticModel, node: LuaSyntaxNode) -> Option<()> { let semantic_decl = semantic_model.find_decl(node.into(), SemanticDeclLevel::default())?; if let LuaSemanticDeclId::LuaDecl(decl_id) = semantic_decl { - let decl = semantic_model - .get_db() - .get_decl_index() - .get_decl(&decl_id)? - .get_type()?; - match decl { + let decl_type = semantic_model.get_type(decl_id.into()); + match decl_type { LuaType::Def(_) => Some(()), _ => None, } @@ -548,45 +545,26 @@ fn handle_name_node( match semantic_decl { LuaSemanticDeclId::Member(member_id) => { - let member = semantic_model - .get_db() - .get_member_index() - .get_member(&member_id)?; - if matches!(member.get_decl_type(), LuaType::Signature(_)) { + let member_type = semantic_model.get_type(member_id.into()); + if matches!(member_type, LuaType::Signature(_)) { builder.push(name_token, SemanticTokenType::FUNCTION); return Some(()); } } LuaSemanticDeclId::LuaDecl(decl_id) => { - let decl = semantic_model - .get_db() - .get_decl_index() - .get_decl(&decl_id)?; - - let (token_type, modifier) = match &decl.extra { - LuaDeclExtra::Local { decl_type, .. } => match decl_type { - Some(LuaType::Signature(_) | LuaType::DocFunction(_)) => { - builder.push(name_token, SemanticTokenType::FUNCTION); - return Some(()); - } - _ => (SemanticTokenType::VARIABLE, None), - }, - - LuaDeclExtra::Global { decl_type, .. } => match decl_type { - Some(LuaType::Signature(signature)) => { - let is_meta = semantic_model - .get_db() - .get_module_index() - .is_meta_file(&signature.get_file_id()); - ( - SemanticTokenType::FUNCTION, - is_meta.then_some(SemanticTokenModifier::DEFAULT_LIBRARY), - ) - } - _ => (SemanticTokenType::VARIABLE, None), - }, - + let decl_type = semantic_model.get_type(decl_id.into()); + let (token_type, modifier) = match decl_type { + LuaType::Signature(signature) => { + let is_meta = semantic_model + .get_db() + .get_module_index() + .is_meta_file(&signature.get_file_id()); + ( + SemanticTokenType::FUNCTION, + is_meta.then_some(SemanticTokenModifier::DEFAULT_LIBRARY), + ) + } _ => (SemanticTokenType::VARIABLE, None), }; diff --git a/crates/emmylua_ls/src/handlers/workspace_symbol/build_workspace_symbols.rs b/crates/emmylua_ls/src/handlers/workspace_symbol/build_workspace_symbols.rs index d7c6f549b..d4c6bfdee 100644 --- a/crates/emmylua_ls/src/handlers/workspace_symbol/build_workspace_symbols.rs +++ b/crates/emmylua_ls/src/handlers/workspace_symbol/build_workspace_symbols.rs @@ -24,16 +24,20 @@ fn add_global_variable_symbols( } let db = compilation.get_db(); - let decl_index = db.get_decl_index(); - let global_decl_id = decl_index.get_global_decls(); - for decl_id in global_decl_id { - let decl = decl_index.get_decl(&decl_id)?; + let global_index = db.get_global_index(); + let global_decl_ids = global_index.get_all_global_decl_ids(); + for decl_id in global_decl_ids { + let decl = db.get_decl_index().get_decl(&decl_id)?; if cancel_token.is_cancelled() { return None; } if decl.get_name().contains(query) { - let typ = decl.get_type().unwrap_or(&LuaType::Unknown); + let typ = db + .get_type_index() + .get_type_cache(&decl_id.clone().into()) + .map(|cache| cache.as_type()) + .unwrap_or(&LuaType::Unknown); let property_owner_id = LuaSemanticDeclId::LuaDecl(decl_id); let document = db.get_vfs().get_document(&decl.get_file_id())?; let location = document.to_lsp_location(decl.get_range())?; From 31210a0454e87d7832eff49ab477ed7f55a076e2 Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Thu, 3 Apr 2025 17:31:25 +0800 Subject: [PATCH 4/6] fix test --- crates/emmylua_code_analysis/src/compilation/test/flow.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/emmylua_code_analysis/src/compilation/test/flow.rs b/crates/emmylua_code_analysis/src/compilation/test/flow.rs index 4bd057a24..18e27720d 100644 --- a/crates/emmylua_code_analysis/src/compilation/test/flow.rs +++ b/crates/emmylua_code_analysis/src/compilation/test/flow.rs @@ -48,8 +48,8 @@ mod test { ); let ty = ws.expr_ty("A"); - let expected = ws.ty("Object | T"); - assert_eq!(ty, expected); + let type_desc = ws.humanize_type(ty); + assert_eq!(type_desc, "T"); } #[test] From f1ae90cb3e89610350abfc2ea369dfa6bb48713d Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Thu, 3 Apr 2025 17:34:05 +0800 Subject: [PATCH 5/6] fix typo and clear some data --- crates/emmylua_code_analysis/src/db_index/mod.rs | 12 ++++++------ .../emmylua_code_analysis/src/db_index/type/mod.rs | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/emmylua_code_analysis/src/db_index/mod.rs b/crates/emmylua_code_analysis/src/db_index/mod.rs index 4c0cd3dd8..f3bec8133 100644 --- a/crates/emmylua_code_analysis/src/db_index/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/mod.rs @@ -56,7 +56,7 @@ pub struct DbIndex { vfs: Vfs, file_dependencies_index: LuaDenpendencyIndex, metatable_index: LuaMetatableIndex, - globla_index: LuaGlobalIndex, + global_index: LuaGlobalIndex, emmyrc: Arc, } @@ -77,7 +77,7 @@ impl DbIndex { vfs: Vfs::new(), file_dependencies_index: LuaDenpendencyIndex::new(), metatable_index: LuaMetatableIndex::new(), - globla_index: LuaGlobalIndex::new(), + global_index: LuaGlobalIndex::new(), emmyrc: Arc::new(Emmyrc::default()), } } @@ -193,11 +193,11 @@ impl DbIndex { } pub fn get_global_index(&self) -> &LuaGlobalIndex { - &self.globla_index + &self.global_index } pub fn get_global_index_mut(&mut self) -> &mut LuaGlobalIndex { - &mut self.globla_index + &mut self.global_index } pub fn update_config(&mut self, config: Arc) { @@ -225,7 +225,7 @@ impl LuaIndex for DbIndex { self.flow_index.remove(file_id); self.file_dependencies_index.remove(file_id); self.metatable_index.remove(file_id); - self.globla_index.remove(file_id); + self.global_index.remove(file_id); } fn clear(&mut self) { @@ -241,6 +241,6 @@ impl LuaIndex for DbIndex { self.flow_index.clear(); self.file_dependencies_index.clear(); self.metatable_index.clear(); - self.globla_index.clear(); + self.global_index.clear(); } } diff --git a/crates/emmylua_code_analysis/src/db_index/type/mod.rs b/crates/emmylua_code_analysis/src/db_index/type/mod.rs index db15398df..fb939dda8 100644 --- a/crates/emmylua_code_analysis/src/db_index/type/mod.rs +++ b/crates/emmylua_code_analysis/src/db_index/type/mod.rs @@ -274,5 +274,7 @@ impl LuaIndex for LuaTypeIndex { self.generic_params.clear(); self.supers.clear(); self.as_force_type.clear(); + self.types.clear(); + self.in_filed_type_owner.clear(); } } From c3bf0966a64ffe4eb4d2914e0b5bfa665b744b3d Mon Sep 17 00:00:00 2001 From: CppCXY <812125110@qq.com> Date: Thu, 3 Apr 2025 17:35:40 +0800 Subject: [PATCH 6/6] remove unused --- crates/emmylua_ls/src/handlers/document_symbol/builder.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/crates/emmylua_ls/src/handlers/document_symbol/builder.rs b/crates/emmylua_ls/src/handlers/document_symbol/builder.rs index 836de3fa5..a401011ec 100644 --- a/crates/emmylua_ls/src/handlers/document_symbol/builder.rs +++ b/crates/emmylua_ls/src/handlers/document_symbol/builder.rs @@ -36,10 +36,6 @@ impl<'a> DocumentSymbolBuilder<'a> { self.decl_tree.get_decl(id) } - pub fn get_db(&self) -> &'a DbIndex { - self.db - } - pub fn get_type(&self, id: LuaTypeOwner) -> LuaType { self.db .get_type_index()