Skip to content

Commit cb79355

Browse files
committed
support visit_type
1 parent 4d3ae01 commit cb79355

7 files changed

Lines changed: 216 additions & 54 deletions

File tree

crates/emmylua_code_analysis/src/compilation/analyzer/lua/for_range_stat.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use emmylua_parser::{LuaAstNode, LuaAstToken, LuaExpr, LuaForRangeStat};
33
use crate::{
44
compilation::analyzer::unresolve::UnResolveIterVar, infer_expr, instantiate_doc_function,
55
tpl_pattern_match_args, DbIndex, InferFailReason, LuaDeclId, LuaInferCache,
6-
LuaOperatorMetaMethod, LuaType, LuaTypeCache, TypeOps, TypeSubstitutor, VariadicType,
6+
LuaOperatorMetaMethod, LuaType, LuaTypeCache, TplContext, TypeOps, TypeSubstitutor,
7+
VariadicType,
78
};
89

910
use super::LuaAnalyzer;
@@ -149,19 +150,19 @@ pub fn infer_for_range_iter_expr_func(
149150
return Ok(doc_function.get_variadic_ret());
150151
}
151152
let mut substitutor = TypeSubstitutor::new();
153+
let mut context = TplContext {
154+
db,
155+
cache,
156+
substitutor: &mut substitutor,
157+
root: root,
158+
};
152159
let params = doc_function
153160
.get_params()
154161
.iter()
155162
.map(|(_, opt_ty)| opt_ty.clone().unwrap_or(LuaType::Any))
156163
.collect::<Vec<_>>();
157-
tpl_pattern_match_args(
158-
db,
159-
cache,
160-
&params,
161-
&vec![status_param.clone().unwrap()],
162-
&root,
163-
&mut substitutor,
164-
)?;
164+
165+
tpl_pattern_match_args(&mut context, &params, &vec![status_param.clone().unwrap()])?;
165166

166167
let instantiate_func = if let LuaType::DocFunction(f) =
167168
instantiate_doc_function(db, &doc_function, &substitutor)

crates/emmylua_code_analysis/src/db_index/type/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ mod test;
33
mod type_decl;
44
mod type_ops;
55
mod type_owner;
6+
mod type_visit_trait;
67
mod types;
78

89
use super::traits::LuaIndex;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
use crate::LuaType;
2+
3+
pub trait TypeVisitTrait {
4+
fn visit_type<F>(&self, f: &mut F)
5+
where
6+
F: FnMut(&LuaType);
7+
}

crates/emmylua_code_analysis/src/db_index/type/types.rs

Lines changed: 174 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use rowan::TextRange;
1010
use smol_str::SmolStr;
1111

1212
use crate::{
13-
db_index::{LuaMemberKey, LuaSignatureId},
13+
db_index::{r#type::type_visit_trait::TypeVisitTrait, LuaMemberKey, LuaSignatureId},
1414
DbIndex, InFiled, SemanticModel,
1515
};
1616

@@ -450,12 +450,50 @@ impl LuaType {
450450
}
451451
}
452452

453+
impl TypeVisitTrait for LuaType {
454+
fn visit_type<F>(&self, f: &mut F)
455+
where
456+
F: FnMut(&LuaType),
457+
{
458+
f(self);
459+
match self {
460+
LuaType::Array(base) => base.visit_type(f),
461+
LuaType::Tuple(base) => base.visit_type(f),
462+
LuaType::DocFunction(base) => base.visit_type(f),
463+
LuaType::Object(base) => base.visit_type(f),
464+
LuaType::Union(base) => base.visit_type(f),
465+
LuaType::Intersection(base) => base.visit_type(f),
466+
LuaType::Generic(base) => base.visit_type(f),
467+
LuaType::Variadic(multi) => multi.visit_type(f),
468+
LuaType::TableGeneric(params) => {
469+
for param in params.iter() {
470+
param.visit_type(f);
471+
}
472+
}
473+
LuaType::MultiLineUnion(inner) => inner.visit_type(f),
474+
LuaType::TypeGuard(inner) => inner.visit_type(f),
475+
_ => {}
476+
}
477+
}
478+
}
479+
453480
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
454481
pub struct LuaTupleType {
455482
types: Vec<LuaType>,
456483
pub status: LuaTupleStatus,
457484
}
458485

486+
impl TypeVisitTrait for LuaTupleType {
487+
fn visit_type<F>(&self, f: &mut F)
488+
where
489+
F: FnMut(&LuaType),
490+
{
491+
for ty in &self.types {
492+
ty.visit_type(f);
493+
}
494+
}
495+
}
496+
459497
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
460498
pub enum LuaTupleStatus {
461499
DocResolve,
@@ -538,6 +576,20 @@ pub struct LuaFunctionType {
538576
ret: LuaType,
539577
}
540578

579+
impl TypeVisitTrait for LuaFunctionType {
580+
fn visit_type<F>(&self, f: &mut F)
581+
where
582+
F: FnMut(&LuaType),
583+
{
584+
for (_, t) in &self.params {
585+
if let Some(t) = t {
586+
t.visit_type(f);
587+
}
588+
}
589+
self.ret.visit_type(f);
590+
}
591+
}
592+
541593
impl LuaFunctionType {
542594
pub fn new(
543595
is_async: bool,
@@ -628,6 +680,18 @@ impl LuaFunctionType {
628680
false
629681
}
630682
}
683+
684+
pub fn collect_generic_tpls(&self, tpls: &mut HashSet<GenericTplId>) {
685+
self.visit_type(&mut |t| match t {
686+
LuaType::TplRef(generic_tpl) | LuaType::ConstTplRef(generic_tpl) => {
687+
tpls.insert(generic_tpl.get_tpl_id());
688+
}
689+
LuaType::StrTplRef(str_tpl) => {
690+
tpls.insert(str_tpl.get_tpl_id());
691+
}
692+
_ => {}
693+
});
694+
}
631695
}
632696

633697
impl From<LuaFunctionType> for LuaType {
@@ -649,6 +713,21 @@ pub struct LuaObjectType {
649713
index_access: Vec<(LuaType, LuaType)>,
650714
}
651715

716+
impl TypeVisitTrait for LuaObjectType {
717+
fn visit_type<F>(&self, f: &mut F)
718+
where
719+
F: FnMut(&LuaType),
720+
{
721+
for t in self.fields.values() {
722+
t.visit_type(f);
723+
}
724+
for (key, value_type) in &self.index_access {
725+
key.visit_type(f);
726+
value_type.visit_type(f);
727+
}
728+
}
729+
}
730+
652731
impl LuaObjectType {
653732
pub fn new(object_fields: Vec<(LuaIndexAccessKey, LuaType)>) -> Self {
654733
let mut fields = HashMap::new();
@@ -757,6 +836,22 @@ pub enum LuaUnionType {
757836
Multi(Vec<LuaType>),
758837
}
759838

839+
impl TypeVisitTrait for LuaUnionType {
840+
fn visit_type<F>(&self, f: &mut F)
841+
where
842+
F: FnMut(&LuaType),
843+
{
844+
match self {
845+
LuaUnionType::Nullable(ty) => ty.visit_type(f),
846+
LuaUnionType::Multi(types) => {
847+
for ty in types {
848+
ty.visit_type(f);
849+
}
850+
}
851+
}
852+
}
853+
}
854+
760855
impl LuaUnionType {
761856
pub fn from_set(mut set: HashSet<LuaType>) -> Self {
762857
if set.len() == 2 && set.contains(&LuaType::Nil) {
@@ -872,6 +967,17 @@ pub struct LuaIntersectionType {
872967
types: Vec<LuaType>,
873968
}
874969

970+
impl TypeVisitTrait for LuaIntersectionType {
971+
fn visit_type<F>(&self, f: &mut F)
972+
where
973+
F: FnMut(&LuaType),
974+
{
975+
for ty in &self.types {
976+
ty.visit_type(f);
977+
}
978+
}
979+
}
980+
875981
impl LuaIntersectionType {
876982
pub fn new(types: Vec<LuaType>) -> Self {
877983
Self { types }
@@ -914,6 +1020,17 @@ pub struct LuaAliasCallType {
9141020
operand: Vec<LuaType>,
9151021
}
9161022

1023+
impl TypeVisitTrait for LuaAliasCallType {
1024+
fn visit_type<F>(&self, f: &mut F)
1025+
where
1026+
F: FnMut(&LuaType),
1027+
{
1028+
for t in &self.operand {
1029+
t.visit_type(f);
1030+
}
1031+
}
1032+
}
1033+
9171034
impl LuaAliasCallType {
9181035
pub fn new(call_kind: LuaAliasCallKind, operand: Vec<LuaType>) -> Self {
9191036
Self { call_kind, operand }
@@ -938,6 +1055,17 @@ pub struct LuaGenericType {
9381055
params: Vec<LuaType>,
9391056
}
9401057

1058+
impl TypeVisitTrait for LuaGenericType {
1059+
fn visit_type<F>(&self, f: &mut F)
1060+
where
1061+
F: FnMut(&LuaType),
1062+
{
1063+
for param in &self.params {
1064+
param.visit_type(f);
1065+
}
1066+
}
1067+
}
1068+
9411069
impl LuaGenericType {
9421070
pub fn new(base: LuaTypeDeclId, params: Vec<LuaType>) -> Self {
9431071
Self { base, params }
@@ -976,6 +1104,22 @@ pub enum VariadicType {
9761104
Base(LuaType),
9771105
}
9781106

1107+
impl TypeVisitTrait for VariadicType {
1108+
fn visit_type<F>(&self, f: &mut F)
1109+
where
1110+
F: FnMut(&LuaType),
1111+
{
1112+
match self {
1113+
VariadicType::Multi(types) => {
1114+
for ty in types {
1115+
ty.visit_type(f);
1116+
}
1117+
}
1118+
VariadicType::Base(t) => t.visit_type(f),
1119+
}
1120+
}
1121+
}
1122+
9791123
impl VariadicType {
9801124
pub fn get_type(&self, idx: usize) -> Option<&LuaType> {
9811125
match self {
@@ -1105,6 +1249,15 @@ pub struct LuaInstanceType {
11051249
range: InFiled<TextRange>,
11061250
}
11071251

1252+
impl TypeVisitTrait for LuaInstanceType {
1253+
fn visit_type<F>(&self, f: &mut F)
1254+
where
1255+
F: FnMut(&LuaType),
1256+
{
1257+
self.base.visit_type(f);
1258+
}
1259+
}
1260+
11081261
impl LuaInstanceType {
11091262
pub fn new(base: LuaType, range: InFiled<TextRange>) -> Self {
11101263
Self { base, range }
@@ -1202,6 +1355,17 @@ pub struct LuaMultiLineUnion {
12021355
unions: Vec<(LuaType, Option<String>)>,
12031356
}
12041357

1358+
impl TypeVisitTrait for LuaMultiLineUnion {
1359+
fn visit_type<F>(&self, f: &mut F)
1360+
where
1361+
F: FnMut(&LuaType),
1362+
{
1363+
for (t, _) in &self.unions {
1364+
t.visit_type(f);
1365+
}
1366+
}
1367+
}
1368+
12051369
impl LuaMultiLineUnion {
12061370
pub fn new(unions: Vec<(LuaType, Option<String>)>) -> Self {
12071371
Self { unions }
@@ -1231,6 +1395,15 @@ pub struct LuaArrayType {
12311395
len: LuaArrayLen,
12321396
}
12331397

1398+
impl TypeVisitTrait for LuaArrayType {
1399+
fn visit_type<F>(&self, f: &mut F)
1400+
where
1401+
F: FnMut(&LuaType),
1402+
{
1403+
self.base.visit_type(f);
1404+
}
1405+
}
1406+
12341407
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
12351408
pub enum LuaArrayLen {
12361409
None,

crates/emmylua_code_analysis/src/semantic/generic/instantiate_func_generic.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use std::ops::Deref;
1+
use std::{collections::HashSet, ops::Deref};
22

33
use emmylua_parser::{LuaAstNode, LuaCallExpr, LuaExpr};
44

55
use crate::{
66
db_index::{DbIndex, LuaType},
7-
semantic::{infer::InferFailReason, infer_expr, LuaInferCache},
7+
semantic::{
8+
generic::tpl_context::TplContext, infer::InferFailReason, infer_expr, LuaInferCache,
9+
},
810
LuaFunctionType,
911
};
1012

@@ -24,13 +26,23 @@ pub fn instantiate_func_generic(
2426
.iter()
2527
.map(|(_, t)| t.clone().unwrap_or(LuaType::Unknown))
2628
.collect();
29+
let func_return_type = func.get_ret();
30+
31+
let mut generic_tpls = HashSet::new();
32+
func.collect_generic_tpls(&mut generic_tpls);
2733

2834
let mut arg_types = collect_arg_types(db, cache, &call_expr)?;
35+
let mut substitutor = TypeSubstitutor::new();
36+
let mut context = TplContext {
37+
db,
38+
cache,
39+
substitutor: &mut substitutor,
40+
root: call_expr.get_root(),
41+
};
2942

3043
let colon_call = call_expr.is_colon_call();
3144
let colon_define = func.is_colon_define();
3245
match (colon_define, colon_call) {
33-
(true, true) | (false, false) => {}
3446
(true, false) => {
3547
if !arg_types.is_empty() {
3648
arg_types.remove(0);
@@ -39,17 +51,10 @@ pub fn instantiate_func_generic(
3951
(false, true) => {
4052
arg_types.insert(0, LuaType::Any);
4153
}
54+
_ => {}
4255
}
4356

44-
let mut substitutor = TypeSubstitutor::new();
45-
tpl_pattern_match_args(
46-
db,
47-
cache,
48-
&func_param_types,
49-
&arg_types,
50-
&call_expr.get_root(),
51-
&mut substitutor,
52-
)?;
57+
tpl_pattern_match_args(&mut context, &func_param_types, &arg_types)?;
5358

5459
if func.contain_self() {
5560
infer_self_type(db, cache, &call_expr, &mut substitutor)?;

crates/emmylua_code_analysis/src/semantic/generic/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@ mod type_substitutor;
99
pub use instantiate_func_generic::instantiate_func_generic;
1010
pub use instantiate_type_generic::instantiate_doc_function;
1111
pub use instantiate_type_generic::instantiate_type_generic;
12+
pub use tpl_context::TplContext;
1213
pub use tpl_pattern::tpl_pattern_match_args;
1314
pub use type_substitutor::TypeSubstitutor;

0 commit comments

Comments
 (0)