use crate::nodes::{Identifier, Token, Trivia};
use super::{StringType, Type};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableIndexerType {
key_type: Box<Type>,
value_type: Box<Type>,
modifier: Option<TablePropertyModifier>,
tokens: Option<TableIndexTypeTokens>,
}
impl TableIndexerType {
pub fn new(key_type: impl Into<Type>, value_type: impl Into<Type>) -> Self {
Self {
key_type: Box::new(key_type.into()),
value_type: Box::new(value_type.into()),
modifier: None,
tokens: None,
}
}
pub fn with_modifier(mut self, modifier: TablePropertyModifier) -> Self {
self.set_modifier(modifier);
self
}
pub fn set_modifier(&mut self, modifier: TablePropertyModifier) {
if self.modifier.as_ref() == Some(&modifier) {
return;
}
self.modifier = Some(modifier);
if let Some(tokens) = self.tokens.as_mut() {
tokens.modifier = None;
}
}
pub fn remove_modifier(&mut self) {
self.modifier = None;
if let Some(tokens) = self.tokens.as_mut() {
tokens.modifier = None;
}
}
pub fn get_modifier(&self) -> Option<&TablePropertyModifier> {
self.modifier.as_ref()
}
#[inline]
pub fn get_key_type(&self) -> &Type {
&self.key_type
}
#[inline]
pub fn mutate_key_type(&mut self) -> &mut Type {
&mut self.key_type
}
#[inline]
pub fn get_value_type(&self) -> &Type {
&self.value_type
}
#[inline]
pub fn mutate_value_type(&mut self) -> &mut Type {
&mut self.value_type
}
pub fn with_tokens(mut self, token: TableIndexTypeTokens) -> Self {
self.tokens = Some(token);
self
}
#[inline]
pub fn set_tokens(&mut self, token: TableIndexTypeTokens) {
self.tokens = Some(token);
}
#[inline]
pub fn get_tokens(&self) -> Option<&TableIndexTypeTokens> {
self.tokens.as_ref()
}
super::impl_token_fns!(iter = [tokens]);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableIndexTypeTokens {
pub opening_bracket: Token,
pub closing_bracket: Token,
pub colon: Token,
pub modifier: Option<Token>,
}
impl TableIndexTypeTokens {
super::impl_token_fns!(
target = [opening_bracket, closing_bracket, colon]
iter = [modifier]
);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TablePropertyType {
property: Identifier,
r#type: Box<Type>,
modifier: Option<TablePropertyModifier>,
tokens: Option<TablePropertyTypeTokens>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TablePropertyTypeTokens {
pub colon: Token,
pub modifier: Option<Token>,
}
impl TablePropertyTypeTokens {
super::impl_token_fns!(
target = [colon]
iter = [modifier]
);
}
impl TablePropertyType {
pub fn new(property: impl Into<Identifier>, r#type: impl Into<Type>) -> Self {
Self {
property: property.into(),
r#type: Box::new(r#type.into()),
modifier: None,
tokens: None,
}
}
pub fn with_modifier(mut self, modifier: TablePropertyModifier) -> Self {
self.set_modifier(modifier);
self
}
pub fn set_modifier(&mut self, modifier: TablePropertyModifier) {
if self.modifier.as_ref() == Some(&modifier) {
return;
}
self.modifier = Some(modifier);
if let Some(tokens) = self.tokens.as_mut() {
tokens.modifier = None;
}
}
pub fn remove_modifier(&mut self) {
self.modifier = None;
if let Some(tokens) = self.tokens.as_mut() {
tokens.modifier = None;
}
}
pub fn get_modifier(&self) -> Option<&TablePropertyModifier> {
self.modifier.as_ref()
}
#[inline]
pub fn get_identifier(&self) -> &Identifier {
&self.property
}
#[inline]
pub fn mutate_identifier(&mut self) -> &mut Identifier {
&mut self.property
}
#[inline]
pub fn get_type(&self) -> &Type {
&self.r#type
}
#[inline]
pub fn mutate_type(&mut self) -> &mut Type {
&mut self.r#type
}
pub fn with_tokens(mut self, tokens: TablePropertyTypeTokens) -> Self {
self.tokens = Some(tokens);
self
}
#[inline]
pub fn set_tokens(&mut self, tokens: TablePropertyTypeTokens) {
self.tokens = Some(tokens);
}
#[inline]
pub fn get_tokens(&self) -> Option<&TablePropertyTypeTokens> {
self.tokens.as_ref()
}
super::impl_token_fns!(target = [property] iter = [tokens]);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableLiteralPropertyType {
string: StringType,
r#type: Box<Type>,
modifier: Option<TablePropertyModifier>,
tokens: Option<TableIndexTypeTokens>,
}
impl TableLiteralPropertyType {
pub fn new(string: StringType, r#type: impl Into<Type>) -> Self {
Self {
string,
r#type: Box::new(r#type.into()),
modifier: None,
tokens: None,
}
}
pub fn with_modifier(mut self, modifier: TablePropertyModifier) -> Self {
self.set_modifier(modifier);
self
}
pub fn set_modifier(&mut self, modifier: TablePropertyModifier) {
if self.modifier.as_ref() == Some(&modifier) {
return;
}
self.modifier = Some(modifier);
if let Some(tokens) = self.tokens.as_mut() {
tokens.modifier = None;
}
}
pub fn remove_modifier(&mut self) {
self.modifier = None;
if let Some(tokens) = self.tokens.as_mut() {
tokens.modifier = None;
}
}
pub fn get_modifier(&self) -> Option<&TablePropertyModifier> {
self.modifier.as_ref()
}
#[inline]
pub fn get_string(&self) -> &StringType {
&self.string
}
#[inline]
pub fn mutate_string(&mut self) -> &mut StringType {
&mut self.string
}
#[inline]
pub fn get_type(&self) -> &Type {
&self.r#type
}
#[inline]
pub fn mutate_type(&mut self) -> &mut Type {
&mut self.r#type
}
pub fn with_tokens(mut self, tokens: TableIndexTypeTokens) -> Self {
self.tokens = Some(tokens);
self
}
#[inline]
pub fn set_tokens(&mut self, tokens: TableIndexTypeTokens) {
self.tokens = Some(tokens);
}
#[inline]
pub fn get_tokens(&self) -> Option<&TableIndexTypeTokens> {
self.tokens.as_ref()
}
super::impl_token_fns!(target = [string] iter = [tokens]);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TablePropertyModifier {
Read,
Write,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TableEntryType {
Property(TablePropertyType),
Literal(TableLiteralPropertyType),
Indexer(TableIndexerType),
}
impl TableEntryType {
pub fn with_modifier(mut self, modifier: TablePropertyModifier) -> Self {
match &mut self {
Self::Property(property) => property.set_modifier(modifier),
Self::Literal(literal) => literal.set_modifier(modifier),
Self::Indexer(indexer) => indexer.set_modifier(modifier),
}
self
}
pub fn set_modifier(&mut self, modifier: TablePropertyModifier) {
match self {
Self::Property(property) => property.set_modifier(modifier),
Self::Literal(literal) => literal.set_modifier(modifier),
Self::Indexer(indexer) => indexer.set_modifier(modifier),
}
}
pub fn remove_modifier(&mut self) {
match self {
Self::Property(property) => property.remove_modifier(),
Self::Literal(literal) => literal.remove_modifier(),
Self::Indexer(indexer) => indexer.remove_modifier(),
}
}
pub fn get_modifier(&self) -> Option<&TablePropertyModifier> {
match self {
Self::Property(property) => property.get_modifier(),
Self::Literal(literal) => literal.get_modifier(),
Self::Indexer(indexer) => indexer.get_modifier(),
}
}
pub fn clear_comments(&mut self) {
match self {
TableEntryType::Property(property) => property.clear_comments(),
TableEntryType::Literal(literal) => literal.clear_comments(),
TableEntryType::Indexer(indexer) => indexer.clear_comments(),
}
}
pub fn clear_whitespaces(&mut self) {
match self {
TableEntryType::Property(property) => property.clear_whitespaces(),
TableEntryType::Literal(literal) => literal.clear_whitespaces(),
TableEntryType::Indexer(indexer) => indexer.clear_whitespaces(),
}
}
pub(crate) fn replace_referenced_tokens(&mut self, code: &str) {
match self {
TableEntryType::Property(property) => property.replace_referenced_tokens(code),
TableEntryType::Literal(literal) => literal.replace_referenced_tokens(code),
TableEntryType::Indexer(indexer) => indexer.replace_referenced_tokens(code),
}
}
pub(crate) fn shift_token_line(&mut self, amount: isize) {
match self {
TableEntryType::Property(property) => property.shift_token_line(amount),
TableEntryType::Literal(literal) => literal.shift_token_line(amount),
TableEntryType::Indexer(indexer) => indexer.shift_token_line(amount),
}
}
pub(crate) fn filter_comments(&mut self, filter: impl Fn(&Trivia) -> bool) {
match self {
TableEntryType::Property(property) => property.filter_comments(filter),
TableEntryType::Literal(literal) => literal.filter_comments(filter),
TableEntryType::Indexer(indexer) => indexer.filter_comments(filter),
}
}
}
impl From<TablePropertyType> for TableEntryType {
fn from(value: TablePropertyType) -> Self {
Self::Property(value)
}
}
impl From<TableLiteralPropertyType> for TableEntryType {
fn from(value: TableLiteralPropertyType) -> Self {
Self::Literal(value)
}
}
impl From<TableIndexerType> for TableEntryType {
fn from(value: TableIndexerType) -> Self {
Self::Indexer(value)
}
}
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct TableType {
entries: Vec<TableEntryType>,
tokens: Option<TableTypeTokens>,
}
impl TableType {
pub fn with_new_property(
mut self,
property: impl Into<Identifier>,
r#type: impl Into<Type>,
) -> Self {
self.entries
.push(TablePropertyType::new(property.into(), r#type.into()).into());
self
}
pub fn with_property(mut self, property: impl Into<TableEntryType>) -> Self {
self.push_property(property.into());
self
}
#[inline]
pub fn push_property(&mut self, property: impl Into<TableEntryType>) {
let property = property.into();
match property {
TableEntryType::Indexer(indexer) => {
self.set_indexer_type(indexer);
}
_ => {
self.entries.push(property);
}
}
}
pub fn with_indexer_type(mut self, indexer_type: TableIndexerType) -> Self {
self.set_indexer_type(indexer_type);
self
}
#[inline]
pub fn set_indexer_type(&mut self, indexer_type: TableIndexerType) -> Option<TableIndexerType> {
match *indexer_type.key_type {
Type::String(string_type) => {
self.entries
.push(TableEntryType::Literal(TableLiteralPropertyType {
string: string_type,
r#type: indexer_type.value_type,
modifier: indexer_type.modifier,
tokens: indexer_type.tokens,
}));
None
}
_ => {
let removed = if let Some((remove_index, _)) = self
.entries
.iter()
.enumerate()
.find(|(_, entry)| matches!(entry, TableEntryType::Indexer(_)))
{
match self.entries.remove(remove_index) {
TableEntryType::Indexer(indexer) => Some(indexer),
TableEntryType::Property(_) | TableEntryType::Literal(_) => unreachable!(),
}
} else {
None
};
self.entries.push(TableEntryType::Indexer(indexer_type));
removed
}
}
}
#[inline]
pub fn has_indexer_type(&self) -> bool {
self.entries
.iter()
.any(|entry| matches!(entry, TableEntryType::Indexer(_)))
}
#[inline]
pub fn len(&self) -> usize {
self.entries.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
#[inline]
pub fn iter_entries(&self) -> impl Iterator<Item = &TableEntryType> {
self.entries.iter()
}
#[inline]
pub fn iter_mut_entries(&mut self) -> impl Iterator<Item = &mut TableEntryType> {
self.entries.iter_mut()
}
pub fn with_tokens(mut self, tokens: TableTypeTokens) -> Self {
self.tokens = Some(tokens);
self
}
#[inline]
pub fn set_tokens(&mut self, tokens: TableTypeTokens) {
self.tokens = Some(tokens);
}
#[inline]
pub fn get_tokens(&self) -> Option<&TableTypeTokens> {
self.tokens.as_ref()
}
pub fn mutate_last_token(&mut self) -> &mut Token {
if self.tokens.is_none() {
self.tokens = Some(TableTypeTokens {
opening_brace: Token::from_content("{"),
closing_brace: Token::from_content("}"),
separators: Vec::new(),
});
}
&mut self.tokens.as_mut().unwrap().closing_brace
}
super::impl_token_fns!(iter = [entries, tokens]);
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TableTypeTokens {
pub opening_brace: Token,
pub closing_brace: Token,
pub separators: Vec<Token>,
}
impl TableTypeTokens {
super::impl_token_fns!(
target = [opening_brace, closing_brace]
iter = [separators]
);
}