use crate::enums::ignore_synthetic_name::IgnoreSyntheticName;
use crate::functions::assign_cycle_names::assign_cycle_names;
use crate::functions::find_cyclic_types::find_cyclic_types;
use crate::functions::follow_type::follow;
use crate::functions::get_type_alt_j::get;
use crate::functions::table_type_to_string_detailed::table_type_to_string_detailed;
use crate::records::metatable_type::MetatableType;
use crate::records::stringifier_state::StringifierState;
use crate::records::table_type::TableType;
use crate::records::to_string_options::ToStringOptions;
use crate::records::to_string_result::ToStringResult;
use crate::records::type_pack_stringifier::TypePackStringifier;
use crate::records::type_stringifier::TypeStringifier;
use crate::type_aliases::type_id::TypeId;
use crate::type_aliases::type_pack_id::TypePackId;
use crate::type_aliases::type_pack_variant::TypePackVariant;
use crate::type_aliases::type_variant::TypeVariant;
use alloc::collections::BTreeSet;
use alloc::string::String;
use alloc::vec::Vec;
pub(crate) fn visit_type_arms(tvs: &mut TypeStringifier, cycle_ty: TypeId) {
unsafe {
match &(*cycle_ty).ty {
TypeVariant::Bound(b) => {
let btv = crate::type_aliases::bound_type::BoundType { boundTo: *b };
tvs.operator_call_10(cycle_ty, &btv)
}
TypeVariant::Error(etv) => tvs.operator_call_11(cycle_ty, etv),
TypeVariant::Free(ftv) => tvs.operator_call_2(cycle_ty, ftv),
TypeVariant::Generic(gtv) => tvs.operator_call_3(cycle_ty, gtv),
TypeVariant::Primitive(ptv) => tvs.operator_call_17(cycle_ty, ptv),
TypeVariant::Singleton(stv) => tvs.operator_call_18(cycle_ty, stv),
TypeVariant::Blocked(btv) => tvs.operator_call_9(cycle_ty, btv),
TypeVariant::PendingExpansion(petv) => tvs.operator_call_6(cycle_ty, petv),
TypeVariant::Function(ftv) => tvs.operator_call_12(cycle_ty, ftv),
TypeVariant::Table(ttv) => tvs.operator_call_7(cycle_ty, ttv),
TypeVariant::Metatable(mtv) => tvs.operator_call_5(cycle_ty, mtv),
TypeVariant::Extern(etv) => tvs.operator_call(cycle_ty, etv),
TypeVariant::Any(atv) => tvs.operator_call_8(cycle_ty, atv),
TypeVariant::Union(utv) => tvs.operator_call_20(cycle_ty, utv),
TypeVariant::Intersection(itv) => tvs.operator_call_4(cycle_ty, itv),
TypeVariant::Lazy(ltv) => tvs.operator_call_13(cycle_ty, ltv),
TypeVariant::Unknown(utv) => tvs.operator_call_21(cycle_ty, utv),
TypeVariant::Never(ntv) => tvs.operator_call_15(cycle_ty, ntv),
TypeVariant::Negation(ntv) => tvs.operator_call_14(cycle_ty, ntv),
TypeVariant::NoRefine(nrt) => tvs.operator_call_16(cycle_ty, nrt),
TypeVariant::TypeFunctionInstance(tfitv) => tvs.operator_call_19(cycle_ty, tfitv),
}
}
}
pub(crate) fn visit_pack_arms(tps: &mut TypePackStringifier, cycle_tp: TypePackId) {
unsafe {
match &(*cycle_tp).ty {
TypePackVariant::Bound(b) => {
let btv = crate::type_aliases::bound_type_pack::BoundTypePack { boundTo: *b };
tps.operator_call_4(cycle_tp, &btv)
}
TypePackVariant::Error(_) => {
let etv = crate::type_aliases::error_type_pack::ErrorTypePack {
index: 0,
synthetic: None,
};
tps.operator_call_5(cycle_tp, &etv)
}
TypePackVariant::Free(ftv) => tps.operator_call(cycle_tp, ftv),
TypePackVariant::Generic(gtv) => tps.operator_call_2(cycle_tp, gtv),
TypePackVariant::TypePack(pack) => tps.operator_call_7(cycle_tp, pack),
TypePackVariant::Variadic(vtp) => tps.operator_call_8(cycle_tp, vtp),
TypePackVariant::Blocked(btp) => tps.operator_call_3(cycle_tp, btp),
TypePackVariant::TypeFunctionInstance(tfitp) => tps.operator_call_6(cycle_tp, tfitp),
}
}
}
pub fn to_string_detailed(ty: TypeId, opts: &mut ToStringOptions) -> ToStringResult {
unsafe {
let ty = follow(ty);
let mut result = ToStringResult::default();
let mut state = StringifierState::stringifier_state_stringifier_state(
opts as *mut ToStringOptions,
&mut result as *mut ToStringResult,
);
let mut cycles: BTreeSet<TypeId> = BTreeSet::new();
let mut cycle_tps: BTreeSet<TypePackId> = BTreeSet::new();
find_cyclic_types(&mut cycles, &mut cycle_tps, ty, opts.exhaustive);
assign_cycle_names(
&cycles,
&cycle_tps,
&mut state.cycle_names,
&mut state.cycle_tp_names,
opts.exhaustive,
);
let mut tvs = TypeStringifier {
state: &mut state as *mut StringifierState,
};
if !opts.exhaustive {
if state.ignore_synthetic_name {
let ttv = get::<TableType>(ty);
if !ttv.is_null() && (*ttv).name.is_some() {
let name = (*ttv).name.clone().unwrap();
table_type_to_string_detailed(
ty,
ttv,
IgnoreSyntheticName::Yes,
&mut result,
&opts.scope,
&name,
&mut tvs,
);
return result;
}
} else {
let ttv = get::<TableType>(ty);
if !ttv.is_null() && ((*ttv).name.is_some() || (*ttv).synthetic_name.is_some()) {
let name = match &(*ttv).name {
Some(name) => name.clone(),
None => (*ttv).synthetic_name.clone().unwrap(),
};
table_type_to_string_detailed(
ty,
ttv,
IgnoreSyntheticName::No,
&mut result,
&opts.scope,
&name,
&mut tvs,
);
return result;
}
let mtv = get::<MetatableType>(ty);
if !mtv.is_null() && (*mtv).syntheticName.is_some() {
result.invalid = true;
result.name = (*mtv).syntheticName.clone().unwrap();
return result;
}
}
}
if let Some(p) = state.cycle_names.find(&ty) {
let name = p.clone();
state.emit(name.as_str());
} else {
tvs.stringify_type_id(ty);
}
if !state.cycle_names.empty() || !state.cycle_tp_names.empty() {
result.cycle = true;
state.emit(" where ");
}
state.exhaustive = true;
let mut sorted_cycle_names: Vec<(TypeId, String)> = state
.cycle_names
.iter()
.map(|(k, v)| (*k, v.clone()))
.collect();
sorted_cycle_names.sort_unstable_by(|a, b| a.1.cmp(&b.1));
let mut semi = false;
for (cycle_ty, name) in sorted_cycle_names.iter() {
if semi {
state.emit(" ; ");
}
state.emit(name.as_str());
state.emit(" = ");
visit_type_arms(&mut tvs, *cycle_ty);
semi = true;
}
let mut sorted_cycle_tp_names: Vec<(TypePackId, String)> = state
.cycle_tp_names
.iter()
.map(|(k, v)| (*k, v.clone()))
.collect();
sorted_cycle_tp_names.sort_unstable_by(|a, b| a.1.cmp(&b.1));
let mut tps = TypePackStringifier::type_pack_stringifier_stringifier_state(
&mut state as *mut StringifierState,
);
for (cycle_tp, name) in sorted_cycle_tp_names.iter() {
if semi {
state.emit(" ; ");
}
state.emit(name.as_str());
state.emit(" = ");
visit_pack_arms(&mut tps, *cycle_tp);
semi = true;
}
if opts.max_type_length > 0 && result.name.len() > opts.max_type_length {
result.truncated = true;
result.name.push_str("... *TRUNCATED*");
}
result
}
}
#[allow(unused_imports)]
pub use to_string_detailed as to_string_detailed_type_id_to_string_options;