use mago_atom::Atom;
use mago_atom::AtomMap;
use mago_atom::atom;
use mago_names::scope::NamespaceScope;
use mago_span::HasSpan;
use mago_syntax::ast::FunctionLikeParameter;
use crate::metadata::constant::ConstantMetadata;
use crate::metadata::flags::MetadataFlags;
use crate::metadata::parameter::FunctionLikeParameterMetadata;
use crate::metadata::ttype::TypeMetadata;
use crate::misc::VariableIdentifier;
use crate::scanner::Context;
use crate::scanner::attribute::scan_attribute_lists;
use crate::scanner::inference::infer_with_constants;
use crate::scanner::ttype::get_type_metadata_from_hint;
#[inline]
pub fn scan_function_like_parameter<'arena>(
parameter: &'arena FunctionLikeParameter<'arena>,
classname: Option<Atom>,
context: &mut Context<'_, 'arena>,
scope: &NamespaceScope,
) -> FunctionLikeParameterMetadata {
scan_function_like_parameter_with_constants(parameter, classname, context, scope, None)
}
#[inline]
pub fn scan_function_like_parameter_with_constants<'arena>(
parameter: &'arena FunctionLikeParameter<'arena>,
classname: Option<Atom>,
context: &mut Context<'_, 'arena>,
scope: &NamespaceScope,
constants: Option<&AtomMap<ConstantMetadata>>,
) -> FunctionLikeParameterMetadata {
let mut flags = MetadataFlags::empty();
if context.file.file_type.is_host() {
flags |= MetadataFlags::USER_DEFINED;
} else if context.file.file_type.is_builtin() {
flags |= MetadataFlags::BUILTIN;
}
if parameter.ellipsis.is_some() {
flags |= MetadataFlags::VARIADIC;
}
if parameter.ampersand.is_some() {
flags |= MetadataFlags::BY_REFERENCE;
}
if parameter.is_promoted_property() {
flags |= MetadataFlags::PROMOTED_PROPERTY;
}
let mut metadata = FunctionLikeParameterMetadata::new(
VariableIdentifier(atom(parameter.variable.name)),
parameter.span(),
parameter.variable.span,
flags,
)
.with_attributes(scan_attribute_lists(¶meter.attribute_lists, context));
metadata.set_type_declaration_metadata(
parameter.hint.as_ref().map(|hint| get_type_metadata_from_hint(hint, classname, context)),
);
if let Some(default_value) = ¶meter.default_value {
metadata.flags |= MetadataFlags::HAS_DEFAULT;
metadata.default_type = infer_with_constants(context, scope, default_value.value, constants).map(|u| {
let mut type_metadata = TypeMetadata::new(u, default_value.span());
type_metadata.inferred = true;
type_metadata
});
}
metadata
}