Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# CHANGELOG

# 0.6.1 (unreleased)
# 0.7.0 (unreleased)

`CHG` Refactor `type infer`

Expand Down
Original file line number Diff line number Diff line change
@@ -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::<Vec<_>>();

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::<Vec<_>>();

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(())
}
Original file line number Diff line number Diff line change
@@ -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<TextRange>,
) -> 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::<Vec<_>>();
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<LuaMemberOwner> {
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,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,16 @@ 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 = 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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
use emmylua_parser::{LuaAstNode, LuaExpr, LuaIndexExpr, PathTrait};
use smol_str::SmolStr;

use crate::{GlobalId, LuaMemberOwner};

use super::DeclAnalyzer;

pub fn find_index_owner(
analyzer: &mut DeclAnalyzer,
index_expr: LuaIndexExpr,
) -> (LuaMemberOwner, Option<GlobalId>) {
if is_in_global_member(analyzer, &index_expr).unwrap_or(false) {
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())),
);
}
}
}

(LuaMemberOwner::LocalUnresolve, None)
}

fn is_in_global_member(analyzer: &DeclAnalyzer, index_expr: &LuaIndexExpr) -> Option<bool> {
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
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod docs;
mod exprs;
mod members;
mod stats;

use crate::{
Expand Down Expand Up @@ -207,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()
Expand Down
Loading