Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Loading