use crate::prelude::*;
use antlr_rust::rule_context::CustomRuleContext;
use antlr_rust::token::Token;
use antlr_rust::token_factory::TokenFactory;
use std::fmt::{Debug, Display};
use std::ops::Range;
use yarnspinner_core::prelude::*;
use yarnspinner_core::types::Type;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy", derive(Reflect))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "bevy", reflect(Debug, PartialEq))]
#[cfg_attr(
all(feature = "bevy", feature = "serde"),
reflect(Serialize, Deserialize)
)]
pub struct Declaration {
pub name: String,
pub default_value: Option<YarnValue>,
pub description: Option<String>,
pub source_file_name: DeclarationSource,
pub source_node_name: Option<String>,
pub is_implicit: bool,
pub r#type: Type,
pub range: Option<Range<Position>>,
}
impl Declaration {
pub fn source_file_line(&self) -> Option<usize> {
self.range.as_ref()?.start.line.into()
}
#[doc(hidden)]
pub fn new(name: impl Into<String>, r#type: impl Into<Type>) -> Self {
Self {
name: name.into(),
r#type: r#type.into(),
default_value: Default::default(),
description: Default::default(),
source_file_name: Default::default(),
source_node_name: Default::default(),
is_implicit: Default::default(),
range: Default::default(),
}
}
#[doc(hidden)]
pub fn with_type(mut self, r#type: impl Into<Type>) -> Self {
self.r#type = r#type.into();
self
}
#[doc(hidden)]
pub fn with_default_value(mut self, default_value: impl Into<YarnValue>) -> Self {
self.default_value = Some(default_value.into());
self
}
#[doc(hidden)]
pub fn with_name(mut self, name: impl Into<String>) -> Self {
self.name = name.into();
self
}
#[doc(hidden)]
pub fn with_description(mut self, description: impl Into<String>) -> Self {
self.description = Some(description.into());
self
}
#[doc(hidden)]
pub fn with_description_optional(mut self, description: impl Into<Option<String>>) -> Self {
self.description = description.into();
self
}
#[doc(hidden)]
pub fn with_source_file_name(mut self, source_file_name: impl Into<DeclarationSource>) -> Self {
self.source_file_name = source_file_name.into();
self
}
#[doc(hidden)]
pub fn with_source_node_name(mut self, source_node_name: impl Into<String>) -> Self {
self.source_node_name = Some(source_node_name.into());
self
}
#[doc(hidden)]
pub fn with_source_node_name_optional(
mut self,
source_node_name: impl Into<Option<String>>,
) -> Self {
self.source_node_name = source_node_name.into();
self
}
#[doc(hidden)]
pub fn with_implicit(mut self) -> Self {
self.is_implicit = true;
self
}
#[doc(hidden)]
pub fn with_range(mut self, range: impl Into<Range<Position>>) -> Self {
self.range = Some(range.into());
self
}
#[doc(hidden)]
pub fn eq(&self, other: &Self, epsilon: f32) -> bool {
self.name == other.name
&& self.description == other.description
&& self.source_file_name == other.source_file_name
&& self.source_node_name == other.source_node_name
&& self.is_implicit == other.is_implicit
&& self.r#type == other.r#type
&& self.range == other.range
&& match (&self.default_value, &other.default_value) {
(Some(a), Some(b)) => a.eq(b, epsilon),
(None, None) => true,
_ => false,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(feature = "bevy", derive(Reflect))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "bevy", reflect(Debug, PartialEq, Default))]
#[cfg_attr(
all(feature = "bevy", feature = "serde"),
reflect(Serialize, Deserialize)
)]
pub enum DeclarationSource {
#[default]
External,
File(String),
}
impl<T> From<T> for DeclarationSource
where
T: Into<String>,
{
fn from(file_name: T) -> Self {
Self::File(file_name.into())
}
}
pub(crate) trait ParserRuleContextExtRangeSource<'input>:
ParserRuleContextExt<'input>
where
<<<<Self as CustomRuleContext<'input>>::TF as TokenFactory<'input>>::Inner as Token>::Data as ToOwned>::Owned:
Into<String>,
{
fn range(&self) -> Range<Position> {
let start = Position {
line: self.start().get_line_as_usize().saturating_sub(1),
character: self.start().get_column_as_usize(),
};
let text: String = self.stop().get_text().to_owned().into();
let stop = Position {
line: self.stop().get_line_as_usize().saturating_sub(1),
character: self.stop().get_column_as_usize() + text.len(),
};
start..stop
}
}
impl<'input, T: ParserRuleContextExt<'input>> ParserRuleContextExtRangeSource<'input> for T where
<<<<T as CustomRuleContext<'input>>::TF as TokenFactory<'input>>::Inner as Token>::Data as ToOwned>::Owned:
Into<String>
{
}
impl Display for DeclarationSource {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::External => write!(f, "(External)"),
Self::File(file_name) => write!(f, "{}", file_name),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct DeferredTypeDiagnostic {
pub(crate) name: String,
pub(crate) diagnostic: Diagnostic,
}