use std::sync::Arc;
use indexmap::IndexMap;
use mir_types::Union;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum Visibility {
Public,
Protected,
Private,
}
impl Visibility {
pub fn is_at_least(&self, required: Visibility) -> bool {
*self <= required
}
}
impl std::fmt::Display for Visibility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Visibility::Public => write!(f, "public"),
Visibility::Protected => write!(f, "protected"),
Visibility::Private => write!(f, "private"),
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TemplateParam {
pub name: Arc<str>,
pub bound: Option<Union>,
pub defining_entity: Arc<str>,
pub variance: mir_types::Variance,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FnParam {
pub name: Arc<str>,
pub ty: Option<Union>,
pub default: Option<Union>,
pub is_variadic: bool,
pub is_byref: bool,
pub is_optional: bool,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Location {
pub file: Arc<str>,
pub start: u32,
pub end: u32,
pub line: u32,
pub col: u16,
}
impl Location {
pub fn new(file: Arc<str>, start: u32, end: u32) -> Self {
Self {
file,
start,
end,
line: 1,
col: 0,
}
}
pub fn with_line_col(file: Arc<str>, start: u32, end: u32, line: u32, col: u16) -> Self {
Self {
file,
start,
end,
line,
col,
}
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum AssertionKind {
Assert,
AssertIfTrue,
AssertIfFalse,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Assertion {
pub kind: AssertionKind,
pub param: Arc<str>,
pub ty: Union,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct MethodStorage {
pub name: Arc<str>,
pub fqcn: Arc<str>,
pub params: Vec<FnParam>,
pub return_type: Option<Union>,
pub inferred_return_type: Option<Union>,
pub visibility: Visibility,
pub is_static: bool,
pub is_abstract: bool,
pub is_final: bool,
pub is_constructor: bool,
pub template_params: Vec<TemplateParam>,
pub assertions: Vec<Assertion>,
pub throws: Vec<Arc<str>>,
pub is_deprecated: bool,
pub is_internal: bool,
pub is_pure: bool,
pub location: Option<Location>,
}
impl MethodStorage {
pub fn effective_return_type(&self) -> Option<&Union> {
self.return_type
.as_ref()
.or(self.inferred_return_type.as_ref())
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct PropertyStorage {
pub name: Arc<str>,
pub ty: Option<Union>,
pub inferred_ty: Option<Union>,
pub visibility: Visibility,
pub is_static: bool,
pub is_readonly: bool,
pub default: Option<Union>,
pub location: Option<Location>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConstantStorage {
pub name: Arc<str>,
pub ty: Union,
pub visibility: Option<Visibility>,
pub location: Option<Location>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ClassStorage {
pub fqcn: Arc<str>,
pub short_name: Arc<str>,
pub parent: Option<Arc<str>>,
pub interfaces: Vec<Arc<str>>,
pub traits: Vec<Arc<str>>,
pub own_methods: IndexMap<Arc<str>, MethodStorage>,
pub own_properties: IndexMap<Arc<str>, PropertyStorage>,
pub own_constants: IndexMap<Arc<str>, ConstantStorage>,
pub template_params: Vec<TemplateParam>,
pub is_abstract: bool,
pub is_final: bool,
pub is_readonly: bool,
pub all_methods: IndexMap<Arc<str>, MethodStorage>,
pub all_parents: Vec<Arc<str>>,
pub is_deprecated: bool,
pub is_internal: bool,
pub location: Option<Location>,
}
impl ClassStorage {
pub fn get_method(&self, name: &str) -> Option<&MethodStorage> {
if let Some(m) = self
.all_methods
.get(name)
.or_else(|| self.own_methods.get(name))
{
return Some(m);
}
self.all_methods
.iter()
.find(|(k, _)| k.as_ref().eq_ignore_ascii_case(name))
.map(|(_, v)| v)
.or_else(|| {
self.own_methods
.iter()
.find(|(k, _)| k.as_ref().eq_ignore_ascii_case(name))
.map(|(_, v)| v)
})
}
pub fn get_property(&self, name: &str) -> Option<&PropertyStorage> {
self.own_properties.get(name)
}
pub fn implements_or_extends(&self, fqcn: &str) -> bool {
self.fqcn.as_ref() == fqcn || self.all_parents.iter().any(|p| p.as_ref() == fqcn)
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct InterfaceStorage {
pub fqcn: Arc<str>,
pub short_name: Arc<str>,
pub extends: Vec<Arc<str>>,
pub own_methods: IndexMap<Arc<str>, MethodStorage>,
pub own_constants: IndexMap<Arc<str>, ConstantStorage>,
pub template_params: Vec<TemplateParam>,
pub all_parents: Vec<Arc<str>>,
pub location: Option<Location>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct TraitStorage {
pub fqcn: Arc<str>,
pub short_name: Arc<str>,
pub own_methods: IndexMap<Arc<str>, MethodStorage>,
pub own_properties: IndexMap<Arc<str>, PropertyStorage>,
pub own_constants: IndexMap<Arc<str>, ConstantStorage>,
pub template_params: Vec<TemplateParam>,
pub location: Option<Location>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EnumCaseStorage {
pub name: Arc<str>,
pub value: Option<Union>,
pub location: Option<Location>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct EnumStorage {
pub fqcn: Arc<str>,
pub short_name: Arc<str>,
pub scalar_type: Option<Union>,
pub interfaces: Vec<Arc<str>>,
pub cases: IndexMap<Arc<str>, EnumCaseStorage>,
pub own_methods: IndexMap<Arc<str>, MethodStorage>,
pub own_constants: IndexMap<Arc<str>, ConstantStorage>,
pub location: Option<Location>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct FunctionStorage {
pub fqn: Arc<str>,
pub short_name: Arc<str>,
pub params: Vec<FnParam>,
pub return_type: Option<Union>,
pub inferred_return_type: Option<Union>,
pub template_params: Vec<TemplateParam>,
pub assertions: Vec<Assertion>,
pub throws: Vec<Arc<str>>,
pub is_deprecated: bool,
pub is_pure: bool,
pub location: Option<Location>,
}
impl FunctionStorage {
pub fn effective_return_type(&self) -> Option<&Union> {
self.return_type
.as_ref()
.or(self.inferred_return_type.as_ref())
}
}