#![allow(dead_code)]
use crate::common::Span;
use super::resolve_type::{ResolvedElements, RuntimeType};
#[derive(Debug)]
pub struct MacroTypeParams {
pub lt_span: Span,
pub type_span: Span,
pub gt_span: Span,
pub resolved: ResolvedElements,
pub runtime_types: Vec<RuntimeType>,
}
#[derive(Debug)]
pub struct MacroObjectArg<'a> {
pub span: Span,
pub properties: Vec<MacroProperty<'a>>,
}
#[derive(Debug)]
pub struct MacroProperty<'a> {
pub name: &'a str,
pub name_span: Span,
pub value_span: Option<Span>,
}
#[derive(Debug)]
pub struct MacroArrayArg {
pub span: Span,
pub element_spans: Vec<Span>,
}
#[derive(Debug)]
pub struct MacroDeclarator<'a> {
pub name: Option<&'a str>,
pub binding_span: Span,
pub statement_span: Span,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum VueMacroKind {
DefineProps = 0,
DefineEmits = 1,
DefineExpose = 2,
DefineOptions = 3,
DefineModel = 4,
DefineSlots = 5,
WithDefaults = 6,
}
#[derive(Debug)]
pub enum ScriptMacro<'a> {
DefineProps {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
type_params: Option<MacroTypeParams>,
object_arg: Option<MacroObjectArg<'a>>,
array_arg: Option<MacroArrayArg>,
},
DefineEmits {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
type_params: Option<MacroTypeParams>,
object_arg: Option<MacroObjectArg<'a>>,
array_arg: Option<MacroArrayArg>,
},
DefineExpose {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
object_arg: Option<MacroObjectArg<'a>>,
},
DefineOptions {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
object_arg: Option<MacroObjectArg<'a>>,
},
DefineModel {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
type_params: Option<MacroTypeParams>,
name_span: Option<Span>,
options_span: Option<Span>,
},
DefineSlots {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
type_params: Option<MacroTypeParams>,
},
WithDefaults {
span: Span,
declarator: Option<MacroDeclarator<'a>>,
define_props_span: Option<Span>,
define_props_type_params: Option<MacroTypeParams>,
defaults: Option<MacroObjectArg<'a>>,
},
}
impl ScriptMacro<'_> {
pub fn kind(&self) -> VueMacroKind {
match self {
Self::DefineProps { .. } => VueMacroKind::DefineProps,
Self::DefineEmits { .. } => VueMacroKind::DefineEmits,
Self::DefineExpose { .. } => VueMacroKind::DefineExpose,
Self::DefineOptions { .. } => VueMacroKind::DefineOptions,
Self::DefineModel { .. } => VueMacroKind::DefineModel,
Self::DefineSlots { .. } => VueMacroKind::DefineSlots,
Self::WithDefaults { .. } => VueMacroKind::WithDefaults,
}
}
pub fn span(&self) -> Span {
match self {
Self::DefineProps { span, .. }
| Self::DefineEmits { span, .. }
| Self::DefineExpose { span, .. }
| Self::DefineOptions { span, .. }
| Self::DefineModel { span, .. }
| Self::DefineSlots { span, .. }
| Self::WithDefaults { span, .. } => *span,
}
}
}
#[inline]
pub fn detect_macro_kind(name: &[u8]) -> Option<VueMacroKind> {
let len = name.len();
if !(11..=13).contains(&len) {
return None;
}
match name.first()? {
b'd' => match len {
11 => {
if name == b"defineProps" {
Some(VueMacroKind::DefineProps)
} else if name == b"defineEmits" {
Some(VueMacroKind::DefineEmits)
} else if name == b"defineSlots" {
Some(VueMacroKind::DefineSlots)
} else if name == b"defineModel" {
Some(VueMacroKind::DefineModel)
} else {
None
}
}
12 => {
if name == b"defineExpose" {
Some(VueMacroKind::DefineExpose)
} else {
None
}
}
13 => {
if name == b"defineOptions" {
Some(VueMacroKind::DefineOptions)
} else {
None
}
}
_ => None,
},
b'w' => {
if len == 12 && name == b"withDefaults" {
Some(VueMacroKind::WithDefaults)
} else {
None
}
}
_ => None,
}
}
#[inline]
pub fn is_define_component(name: &[u8]) -> bool {
name.len() == 15 && name == b"defineComponent"
}
pub mod names {
pub const DEFINE_PROPS: &[u8] = b"defineProps";
pub const DEFINE_EMITS: &[u8] = b"defineEmits";
pub const DEFINE_EXPOSE: &[u8] = b"defineExpose";
pub const DEFINE_OPTIONS: &[u8] = b"defineOptions";
pub const DEFINE_MODEL: &[u8] = b"defineModel";
pub const DEFINE_SLOTS: &[u8] = b"defineSlots";
pub const WITH_DEFAULTS: &[u8] = b"withDefaults";
pub const DEFINE_COMPONENT: &[u8] = b"defineComponent";
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_detect_macros() {
assert_eq!(
detect_macro_kind(b"defineProps"),
Some(VueMacroKind::DefineProps)
);
assert_eq!(
detect_macro_kind(b"defineEmits"),
Some(VueMacroKind::DefineEmits)
);
assert_eq!(
detect_macro_kind(b"defineExpose"),
Some(VueMacroKind::DefineExpose)
);
assert_eq!(
detect_macro_kind(b"defineOptions"),
Some(VueMacroKind::DefineOptions)
);
assert_eq!(
detect_macro_kind(b"defineModel"),
Some(VueMacroKind::DefineModel)
);
assert_eq!(
detect_macro_kind(b"defineSlots"),
Some(VueMacroKind::DefineSlots)
);
assert_eq!(
detect_macro_kind(b"withDefaults"),
Some(VueMacroKind::WithDefaults)
);
}
#[test]
fn test_non_macros() {
assert_eq!(detect_macro_kind(b"ref"), None);
assert_eq!(detect_macro_kind(b"computed"), None);
assert_eq!(detect_macro_kind(b"defineComponent"), None); assert_eq!(detect_macro_kind(b"define"), None);
assert_eq!(detect_macro_kind(b"definePropsExtra"), None); }
#[test]
fn test_is_define_component() {
assert!(is_define_component(b"defineComponent"));
assert!(!is_define_component(b"defineProps"));
assert!(!is_define_component(b"define"));
}
}