backyard_nodes/
lib.rs

1pub mod macros;
2pub mod utils;
3
4#[cfg(feature = "walker")]
5pub mod walker;
6
7#[cfg(feature = "builder")]
8pub mod builder;
9
10#[cfg(feature = "printer")]
11pub mod printer;
12
13use std::{ collections::VecDeque, fmt::{ self, Display, Formatter } };
14
15use bstr::BString;
16use bumpalo::Bump;
17use serde::Serialize;
18
19use crate::utils::CloneIn;
20
21#[cfg(feature = "builder")]
22use crate::builder::{ Blueprint, BlueprintBuildable, BlueprintWrapper, Builder };
23
24#[cfg(feature = "walker")]
25use crate::walker::{ Walkable, WalkerItem };
26
27#[cfg(feature = "printer")]
28use crate::printer::{ PrintBuilder, Printable, PrintType, PrintConfig };
29
30#[derive(Debug, PartialEq, Clone, Serialize)]
31pub enum BodyType {
32  Basic,
33  Short,
34  Empty,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize)]
38pub struct RangeLocation {
39  pub start: Location,
40  pub end: Location,
41}
42
43#[derive(Debug, Clone, PartialEq, Serialize)]
44pub struct Location {
45  pub line: u32,
46  pub column: u32,
47  pub offset: u32,
48}
49
50#[derive(Debug, PartialEq, Serialize)]
51pub struct Node<'a> {
52  pub node_type: NodeType,
53  #[serde(flatten)]
54  pub wrapper: NodeWrapper<'a>,
55  pub loc: Option<RangeLocation>,
56  pub leadings: Option<bumpalo::collections::Vec<'a, Node<'a>>>,
57  pub trailings: Option<bumpalo::collections::Vec<'a, Node<'a>>>,
58}
59
60impl<'a> Node<'a> {
61  pub fn new(node_type: NodeType, wrapper: NodeWrapper<'a>, loc: Option<RangeLocation>) -> Self {
62    Self { node_type, wrapper, loc, leadings: None, trailings: None }
63  }
64
65  pub fn leadings_shift(&mut self, arena: &'a Bump, node: Node<'a>) {
66    if let Some(leadings) = &mut self.leadings {
67      leadings.insert(0, node);
68    } else {
69      self.leadings = Some(bumpalo::vec![in arena; node]);
70    }
71  }
72
73  pub fn leadings_push(&mut self, arena: &'a Bump, node: Node<'a>) {
74    if let Some(leadings) = &mut self.leadings {
75      leadings.push(node);
76    } else {
77      self.leadings = Some(bumpalo::vec![in arena; node]);
78    }
79  }
80
81  pub fn trailings_push(&mut self, arena: &'a Bump, node: Node<'a>) {
82    if let Some(trailings) = &mut self.trailings {
83      trailings.push(node);
84    } else {
85      self.trailings = Some(bumpalo::vec![in arena; node]);
86    }
87  }
88}
89
90#[derive(Debug, PartialEq, Serialize)]
91#[serde(untagged)]
92pub enum NodeWrapper<'a> {
93  AnonymousClass(AnonymousClassNode<'a>),
94  AnonymousFunction(AnonymousFunctionNode<'a>),
95  CallArgument(CallArgumentNode<'a>),
96  Array(ArrayNode<'a>),
97  ArrayItem(ArrayItemNode<'a>),
98  ArrayLookup(ArrayLookupNode<'a>),
99  ArrowFunction(ArrowFunctionNode<'a>),
100  Assignment(AssignmentNode<'a>),
101  Attribute(AttributeNode<'a>),
102  AttributeItem(AttributeItemNode<'a>),
103  Bin(BinNode<'a>),
104  Block(BlockNode<'a>),
105  Boolean(BooleanNode),
106  Break(BreakNode<'a>),
107  Call(CallNode<'a>),
108  Case(CaseNode<'a>),
109  Cast(CastNode<'a>),
110  Catch(CatchNode<'a>),
111  Class(ClassNode<'a>),
112  ClassKeyword(ClassKeywordNode),
113  Clone(CloneNode<'a>),
114  CommentBlock(CommentBlockNode),
115  CommentDoc(CommentDocNode),
116  CommentLine(CommentLineNode),
117  Const(ConstNode<'a>),
118  ConstProperty(ConstPropertyNode<'a>),
119  ConstructorParameter(ConstructorParameterNode<'a>),
120  Continue(ContinueNode<'a>),
121  Declare(DeclareNode<'a>),
122  DeclareArgument(DeclareArgumentNode<'a>),
123  DoWhile(DoWhileNode<'a>),
124  DoWhileCondition(DoWhileConditionNode<'a>),
125  Echo(EchoNode<'a>),
126  Else(ElseNode<'a>),
127  Encapsed(EncapsedNode<'a>),
128  EncapsedPart(EncapsedPartNode<'a>),
129  Enum(EnumNode<'a>),
130  EnumItem(EnumItemNode<'a>),
131  Eval(EvalNode<'a>),
132  Exit(ExitNode<'a>),
133  Finally(FinallyNode<'a>),
134  For(ForNode<'a>),
135  Foreach(ForeachNode<'a>),
136  Function(FunctionNode<'a>),
137  Global(GlobalNode<'a>),
138  Goto(GotoNode<'a>),
139  HereDoc(HereDocNode<'a>),
140  Identifier(IdentifierNode),
141  If(IfNode<'a>),
142  Include(IncludeNode<'a>),
143  Inline(InlineNode),
144  Interface(InterfaceNode<'a>),
145  IntersectionType(IntersectionTypeNode<'a>),
146  Label(LabelNode<'a>),
147  List(ListNode<'a>),
148  Magic(MagicNode),
149  MagicMethod(MagicMethodNode),
150  Match(MatchNode<'a>),
151  MatchArm(MatchArmNode<'a>),
152  Method(MethodNode<'a>),
153  Namespace(NamespaceNode<'a>),
154  Negate(NegateNode<'a>),
155  New(NewNode<'a>),
156  NowDoc(NowDocNode),
157  Null(NullNode),
158  Number(NumberNode),
159  ObjectAccess(ObjectAccessNode<'a>),
160  Parameter(ParameterNode<'a>),
161  Parent(ParentNode),
162  Parenthesis(ParenthesisNode<'a>),
163  Post(PostNode<'a>),
164  Pre(PreNode<'a>),
165  Print(PrintNode<'a>),
166  Program(ProgramNode<'a>),
167  Property(PropertyNode<'a>),
168  PropertyHook(PropertyHookNode<'a>),
169  PropertyItem(PropertyItemNode<'a>),
170  Reference(ReferenceNode<'a>),
171  Return(ReturnNode<'a>),
172  SelfKeyword(SelfNode),
173  Silent(SilentNode<'a>),
174  Static(StaticNode<'a>),
175  StaticKeyword(StaticKeywordNode),
176  StaticLookup(StaticLookupNode<'a>),
177  String(StringNode),
178  Switch(SwitchNode<'a>),
179  Ternary(TernaryNode<'a>),
180  This(ThisNode),
181  Trait(TraitNode<'a>),
182  TraitUse(TraitUseNode<'a>),
183  TraitUseAlias(TraitUseAliasNode<'a>),
184  TraitUsePrecedence(TraitUsePrecedenceNode<'a>),
185  Throw(ThrowNode<'a>),
186  Try(TryNode<'a>),
187  Type(TypeNode),
188  UnionType(UnionTypeNode<'a>),
189  Use(UseNode<'a>),
190  UseItem(UseItemNode<'a>),
191  Variable(VariableNode<'a>),
192  Variadic(VariadicNode<'a>),
193  While(WhileNode<'a>),
194  Yield(YieldNode<'a>),
195  YieldFrom(YieldFromNode<'a>),
196}
197
198#[derive(Debug, Clone, PartialEq, Serialize)]
199#[serde(rename_all = "snake_case")]
200pub enum NodeType {
201  AnonymousClass,
202  AnonymousFunction,
203  CallArgument,
204  Array,
205  ArrayItem,
206  ArrayLookup,
207  ArrowFunction,
208  Assignment,
209  Attribute,
210  AttributeItem,
211  Bin,
212  Block,
213  Boolean,
214  Break,
215  Call,
216  Case,
217  Cast,
218  Catch,
219  Class,
220  ClassKeyword,
221  Clone,
222  CommentBlock,
223  CommentDoc,
224  CommentLine,
225  Const,
226  ConstProperty,
227  ConstructorParameter,
228  Continue,
229  Declare,
230  DeclareArgument,
231  DoWhile,
232  DoWhileCondition,
233  Echo,
234  Else,
235  Encapsed,
236  EncapsedPart,
237  Enum,
238  EnumItem,
239  Eval,
240  Exit,
241  Finally,
242  For,
243  Foreach,
244  Function,
245  Global,
246  Goto,
247  HereDoc,
248  Identifier,
249  If,
250  Include,
251  Inline,
252  Interface,
253  IntersectionType,
254  Label,
255  List,
256  Magic,
257  MagicMethod,
258  Match,
259  MatchArm,
260  Method,
261  Namespace,
262  Negate,
263  New,
264  NowDoc,
265  Null,
266  Number,
267  ObjectAccess,
268  Parameter,
269  Parent,
270  Parenthesis,
271  Post,
272  Pre,
273  Print,
274  Program,
275  Property,
276  PropertyHook,
277  PropertyItem,
278  Reference,
279  Return,
280  SelfKeyword,
281  Silent,
282  Static,
283  StaticKeyword,
284  StaticLookup,
285  String,
286  Switch,
287  Ternary,
288  This,
289  Trait,
290  TraitUse,
291  TraitUseAlias,
292  TraitUsePrecedence,
293  Throw,
294  Try,
295  Type,
296  UnionType,
297  Use,
298  UseItem,
299  Variable,
300  Variadic,
301  While,
302  Yield,
303  YieldFrom,
304}
305
306macro_rules! new_node {
307  (
308    $node_type:ident,
309    $struct_name:ident < $lt:lifetime > { $($field_name:ident: $field_type:ty),* $(,)? },
310    $blueprint_name:ident < $blt:lifetime > {
311      $($blueprint_field_name:ident: $blueprint_field_type:ty),* $(,)?
312    }
313  ) => {
314    #[derive(Debug, PartialEq, Serialize)]
315    pub struct $struct_name<$lt> {
316      $(pub $field_name: $field_type),*
317    }
318
319    impl<$lt> $struct_name<$lt> {
320      pub fn loc($($field_name: $field_type,)* loc: Option<RangeLocation>) -> Node<$lt> {
321        Node {
322          leadings: None,
323          trailings: None,
324          node_type: NodeType::$node_type,
325          wrapper: NodeWrapper::$node_type(
326            Self { $($field_name),* }
327          ),
328          loc
329        }
330      }
331    }
332
333    impl<'arena> CloneIn<'arena> for $struct_name<'_> {
334      type Cloned = $struct_name<'arena>;
335
336      #[inline]
337      fn clone_in(&self, arena: &'arena Bump) -> Self::Cloned {
338        $struct_name {
339          $($field_name: self.$field_name.clone_in(arena)),*
340        }
341      }
342    }
343
344    #[cfg(feature = "walker")]
345    impl<'arena> Walkable<'arena> for $struct_name<'arena> {
346      fn populate_walks<'a>(&'a self, stack: &mut VecDeque<WalkerItem<'arena, 'a>>, level: u16) {
347        let next_level = level + 1;
348        let mut scoped_stack = VecDeque::new();
349        $(self.$field_name.populate_walks(&mut scoped_stack, next_level);)*
350        scoped_stack.into_iter().rev().for_each(|x| stack.push_back(x))
351      }
352    }
353
354    #[cfg(feature = "builder")]
355    #[derive(Debug)]
356    pub struct $blueprint_name<$blt> {
357      $(pub $blueprint_field_name: $blueprint_field_type),*
358    }
359
360    #[cfg(feature = "builder")]
361    impl Builder {
362      #[allow(non_snake_case)]
363      pub fn $node_type<$blt>(&self, $($blueprint_field_name: $blueprint_field_type,)*) -> std::boxed::Box<Blueprint<$blt>> {
364        std::boxed::Box::new(
365          Blueprint {
366            leadings: vec![],
367            trailings: vec![],
368            node_type: NodeType::$node_type,
369            wrapper: BlueprintWrapper::$node_type(
370              $blueprint_name {
371                $($blueprint_field_name: $blueprint_field_name),*
372              }
373            )
374          }
375        )
376      }
377    }
378
379    #[cfg(feature = "builder")]
380    impl<'arena, $blt> BlueprintBuildable<'arena> for $blueprint_name<$blt> {
381      type Result = Node<'arena>;
382
383      fn build(&self, arena: &'arena Bump) -> Self::Result {
384        $struct_name::loc(
385          $(self.$field_name.build(arena),)*
386          None
387        )
388      }
389    }
390
391    #[cfg(feature = "printer")]
392    impl<$lt> Printable for $struct_name<$lt> {
393      fn build_print(&self, config: &PrintConfig) -> PrintBuilder {
394        let mut builder = PrintBuilder::new(PrintType::Object);
395        builder.push_props(!(config.with_leading_trailing || config.with_location), &mut [
396          $((stringify!($field_name), self.$field_name.build_print(config)),)*
397        ]);
398        builder.shift_new_line(stringify!($struct_name));
399        builder
400      }
401    }
402  };
403
404  (
405    $node_type:ident,
406    $struct_name:ident { $($field_name:ident: $field_type:ty),* $(,)? },
407    $blueprint_name:ident < $blt:lifetime > {
408      $($blueprint_field_name:ident: $blueprint_field_type:ty),* $(,)?
409    }
410  ) => {
411    #[derive(Debug, PartialEq, Serialize)]
412    pub struct $struct_name {
413      $(pub $field_name: $field_type),*
414    }
415
416    impl $struct_name {
417      pub fn loc<'a>($($field_name: $field_type,)* loc: Option<RangeLocation>) -> Node<'a> {
418        Node::new(
419          NodeType::$node_type,
420          NodeWrapper::$node_type(
421            Self { $($field_name),* }
422          ),
423          loc
424        )
425      }
426    }
427
428    impl<'arena> CloneIn<'arena> for $struct_name {
429      type Cloned = $struct_name;
430
431      #[inline]
432      fn clone_in(&self, _: &'arena Bump) -> Self::Cloned {
433        $struct_name {
434          $($field_name: self.$field_name.clone()),*
435        }
436      }
437    }
438
439    #[cfg(feature = "walker")]
440    impl<'arena> Walkable<'arena> for $struct_name {
441      fn populate_walks<'a>(&'a self, stack: &mut VecDeque<WalkerItem<'arena, 'a>>, level: u16) {
442        let next_level = level + 1;
443        let mut scoped_stack = VecDeque::new();
444        $(self.$field_name.populate_walks(&mut scoped_stack, next_level);)*
445        scoped_stack.into_iter().rev().for_each(|x| stack.push_back(x))
446      }
447    }
448
449    #[cfg(feature = "builder")]
450    #[derive(Debug)]
451    pub struct $blueprint_name<$blt> {
452      $(pub $blueprint_field_name: $blueprint_field_type),*
453    }
454
455    #[cfg(feature = "builder")]
456    impl Builder {
457      #[allow(non_snake_case)]
458      pub fn $node_type<$blt>(&self, $($blueprint_field_name: $blueprint_field_type,)*) -> std::boxed::Box<Blueprint<$blt>> {
459        std::boxed::Box::new(
460          Blueprint {
461            leadings: vec![],
462            trailings: vec![],
463            node_type: NodeType::$node_type,
464            wrapper: BlueprintWrapper::$node_type(
465              $blueprint_name {
466                $($blueprint_field_name: $blueprint_field_name),*
467              }
468            )
469          }
470        )
471      }
472    }
473
474    #[cfg(feature = "builder")]
475    impl<'arena, $blt> BlueprintBuildable<'arena> for $blueprint_name<$blt> {
476      type Result = Node<'arena>;
477
478      fn build(&self, arena: &'arena Bump) -> Self::Result {
479        $struct_name::loc(
480          $(self.$field_name.build(arena),)*
481          None
482        )
483      }
484    }
485
486    #[cfg(feature = "printer")]
487    impl Printable for $struct_name {
488      fn build_print(&self, config: &PrintConfig) -> PrintBuilder {
489        let mut builder = PrintBuilder::new(PrintType::Object);
490        builder.push_props(!(config.with_leading_trailing || config.with_location), &mut [
491          $((stringify!($field_name), self.$field_name.build_print(config)),)*
492        ]);
493        builder.shift_new_line(stringify!($struct_name));
494        builder
495      }
496    }
497  };
498
499  (
500    $node_type:ident,
501    $struct_name:ident { $($field_name:ident: $field_type:ty),* $(,)? },
502    $blueprint_name:ident { $($blueprint_field_name:ident: $blueprint_field_type:ty),* $(,)? }
503  ) => {
504    #[derive(Debug, PartialEq, Serialize)]
505    pub struct $struct_name {
506      $(pub $field_name: $field_type),*
507    }
508
509    impl $struct_name {
510      pub fn loc<'a>($($field_name: $field_type,)* loc: Option<RangeLocation>) -> Node<'a> {
511        Node::new(
512          NodeType::$node_type,
513          NodeWrapper::$node_type(
514            Self { $($field_name),* }
515          ),
516          loc
517        )
518      }
519    }
520
521    impl<'arena> CloneIn<'arena> for $struct_name {
522      type Cloned = $struct_name;
523
524      #[inline]
525      fn clone_in(&self, _: &'arena Bump) -> Self::Cloned {
526        $struct_name {
527          $($field_name: self.$field_name.clone()),*
528        }
529      }
530    }
531
532    #[cfg(feature = "walker")]
533    impl<'arena> Walkable<'arena> for $struct_name {
534
535      #[allow(unused_variables, unused_mut)]
536      fn populate_walks<'a>(&'a self, stack: &mut VecDeque<WalkerItem<'arena, 'a>>, level: u16) {
537        let next_level = level + 1;
538        let mut scoped_stack = VecDeque::new();
539        $(self.$field_name.populate_walks(&mut scoped_stack, next_level);)*
540        scoped_stack.into_iter().rev().for_each(|x| stack.push_back(x))
541      }
542    }
543
544    #[cfg(feature = "builder")]
545    #[derive(Debug)]
546    pub struct $blueprint_name {
547      $(pub $blueprint_field_name: $blueprint_field_type),*
548    }
549
550    #[cfg(feature = "builder")]
551    impl Builder {
552      #[allow(non_snake_case)]
553      pub fn $node_type<'a>(&self, $($blueprint_field_name: $blueprint_field_type,)*) -> std::boxed::Box<Blueprint<'a>> {
554        std::boxed::Box::new(
555          Blueprint {
556            leadings: vec![],
557            trailings: vec![],
558            node_type: NodeType::$node_type,
559            wrapper: BlueprintWrapper::$node_type(
560              $blueprint_name {
561                $($blueprint_field_name: $blueprint_field_name),*
562              }
563            )
564          }
565        )
566      }
567    }
568
569    #[cfg(feature = "builder")]
570    impl<'arena> BlueprintBuildable<'arena> for $blueprint_name {
571      type Result = Node<'arena>;
572
573      #[allow(unused_variables)]
574      fn build(&self, arena: &'arena Bump) -> Self::Result {
575        $struct_name::loc(
576          $(self.$field_name.build(arena),)*
577          None
578        )
579      }
580    }
581
582    #[cfg(feature = "printer")]
583    impl Printable for $struct_name {
584
585      #[allow(unused_variables)]
586      fn build_print(&self, config: &PrintConfig) -> PrintBuilder {
587        let mut builder = PrintBuilder::new(PrintType::Object);
588        builder.push_props(!(config.with_leading_trailing || config.with_location), &mut [
589          $((stringify!($field_name), self.$field_name.build_print(config)),)*
590        ]);
591        builder.shift_new_line(stringify!($struct_name));
592        builder
593      }
594    }
595  };
596}
597
598new_node!(AnonymousClass, AnonymousClassNode<'a> { parameters: bumpalo::collections::Vec<'a, Node<'a>>, extends: Option<bumpalo::boxed::Box<'a, Node<'a>>>, implements: bumpalo::collections::Vec<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, AnonymousClassBlueprint<'b> { parameters: &'b [Box<Blueprint<'b>>], extends: Option<Box<Blueprint<'b>>>, implements: &'b [Box<Blueprint<'b>>], body: Box<Blueprint<'b>>, });
599new_node!(AnonymousFunction, AnonymousFunctionNode<'a> { is_ref: bool, parameters: bumpalo::collections::Vec<'a, Node<'a>>, uses: bumpalo::collections::Vec<'a, Node<'a>>, return_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, AnonymousFunctionBlueprint<'b> { is_ref: bool, parameters: &'b [Box<Blueprint<'b>>], uses: &'b [Box<Blueprint<'b>>], return_type: Option<Box<Blueprint<'b>>>, body: Box<Blueprint<'b>>, });
600new_node!(CallArgument, CallArgumentNode<'a> { name: Option<bumpalo::boxed::Box<'a, Node<'a>>>, value: bumpalo::boxed::Box<'a, Node<'a>>, }, CallArgumentBlueprint<'b> { name: Option<Box<Blueprint<'b>>>, value: Box<Blueprint<'b>>, });
601new_node!(Array, ArrayNode<'a> { is_short: bool, items: bumpalo::collections::Vec<'a, Node<'a>>, }, ArrayBlueprint<'b> { is_short: bool, items: &'b [Box<Blueprint<'b>>], });
602new_node!(ArrayItem, ArrayItemNode<'a> { key: Option<bumpalo::boxed::Box<'a, Node<'a>>>, value: bumpalo::boxed::Box<'a, Node<'a>>, }, ArrayItemBlueprint<'b> { key: Option<Box<Blueprint<'b>>>, value: Box<Blueprint<'b>>, });
603new_node!(ArrayLookup, ArrayLookupNode<'a> { left: bumpalo::boxed::Box<'a, Node<'a>>, right: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, ArrayLookupBlueprint<'b> { left: Box<Blueprint<'b>>, right: Option<Box<Blueprint<'b>>>, });
604new_node!(ArrowFunction, ArrowFunctionNode<'a> { is_ref: bool, parameters: bumpalo::collections::Vec<'a, Node<'a>>, return_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, ArrowFunctionBlueprint<'b> { is_ref: bool, parameters: &'b [Box<Blueprint<'b>>], return_type: Option<Box<Blueprint<'b>>>, body: Box<Blueprint<'b>>, });
605new_node!(Assignment, AssignmentNode<'a> { left: bumpalo::boxed::Box<'a, Node<'a>>, operator: AssignmentType, right: bumpalo::boxed::Box<'a, Node<'a>>, }, AssignmentBlueprint<'b> { left: Box<Blueprint<'b>>, operator: AssignmentType, right: Box<Blueprint<'b>>, });
606new_node!(Attribute, AttributeNode<'a> { items: bumpalo::collections::Vec<'a, Node<'a>>, }, AttributeBlueprint<'b> { items: &'b [Box<Blueprint<'b>>], });
607new_node!(AttributeItem, AttributeItemNode<'a> { name: BString, arguments: bumpalo::collections::Vec<'a, Node<'a>>, }, AttributeItemBlueprint<'b> { name: &'b str, arguments: &'b [Box<Blueprint<'b>>], });
608new_node!(Bin, BinNode<'a> { left: bumpalo::boxed::Box<'a, Node<'a>>, operator: BinaryType, right: bumpalo::boxed::Box<'a, Node<'a>>, }, BinBlueprint<'b> { left: Box<Blueprint<'b>>, operator: BinaryType, right: Box<Blueprint<'b>>, });
609new_node!(Block, BlockNode<'a> { statements: bumpalo::collections::Vec<'a, Node<'a>>, }, BlockBlueprint<'b> { statements: &'b [Box<Blueprint<'b>>], });
610new_node!(Boolean, BooleanNode { is_true: bool }, BooleanBlueprint { is_true: bool });
611new_node!(Break, BreakNode<'a> { statement: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, BreakBlueprint<'b> { statement: Option<Box<Blueprint<'b>>>, });
612new_node!(Call, CallNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, arguments: bumpalo::collections::Vec<'a, Node<'a>>, }, CallBlueprint<'b> { name: Box<Blueprint<'b>>, arguments: &'b [Box<Blueprint<'b>>], });
613new_node!(Case, CaseNode<'a> { condition: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, CaseBlueprint<'b> { condition: Option<Box<Blueprint<'b>>>, body: Box<Blueprint<'b>>, });
614new_node!(Cast, CastNode<'a> { cast_type: CastType, expression: bumpalo::boxed::Box<'a, Node<'a>>, }, CastBlueprint<'b> { cast_type: CastType, expression: Box<Blueprint<'b>>, });
615new_node!(Catch, CatchNode<'a> { types: bumpalo::collections::Vec<'a, Node<'a>>, variable: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, CatchBlueprint<'b> { types: &'b [Box<Blueprint<'b>>], variable: Option<Box<Blueprint<'b>>>, body: Box<Blueprint<'b>>, });
616new_node!(Class, ClassNode<'a> { inheritance: Option<Inheritance>, name: Option<bumpalo::boxed::Box<'a, Node<'a>>>, extends: Option<bumpalo::boxed::Box<'a, Node<'a>>>, implements: bumpalo::collections::Vec<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, is_readonly: bool, }, ClassBlueprint<'b> { inheritance: Option<Inheritance>, name: Option<Box<Blueprint<'b>>>, extends: Option<Box<Blueprint<'b>>>, implements: &'b [Box<Blueprint<'b>>], body: Box<Blueprint<'b>>, is_readonly: bool, });
617new_node!(ClassKeyword, ClassKeywordNode {}, ClassKeywordBlueprint {});
618new_node!(Clone, CloneNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, CloneBlueprint<'b> { statement: Box<Blueprint<'b>>, });
619new_node!(CommentBlock, CommentBlockNode { comment: BString, }, CommentBlockBlueprint<'b> { comment: &'b str, });
620new_node!(CommentDoc, CommentDocNode { comment: BString, }, CommentDocBlueprint<'b> { comment: &'b str, });
621new_node!(CommentLine, CommentLineNode { comment: BString, }, CommentLineBlueprint<'b> { comment: &'b str, });
622new_node!(Const, ConstNode<'a> { items: bumpalo::collections::Vec<'a, Node<'a>>, }, ConstBlueprint<'b> { items: &'b [Box<Blueprint<'b>>], });
623new_node!(ConstProperty, ConstPropertyNode<'a> { const_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, visibilities: Vec<Visibility>, items: bumpalo::collections::Vec<'a, Node<'a>>, }, ConstPropertyBlueprint<'b> { const_type: Option<Box<Blueprint<'b>>>, visibilities: Vec<Visibility>, items: &'b [Box<Blueprint<'b>>], });
624new_node!(ConstructorParameter, ConstructorParameterNode<'a> { visibilities: Vec<Visibility>, modifier: Option<Modifier>, parameter: bumpalo::boxed::Box<'a, Node<'a>>, }, ConstructorParameterBlueprint<'b> { visibilities: Vec<Visibility>, modifier: Option<Modifier>, parameter: Box<Blueprint<'b>>, });
625new_node!(Continue, ContinueNode<'a> { statement: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, ContinueBlueprint<'b> { statement: Option<Box<Blueprint<'b>>>, });
626new_node!(Declare, DeclareNode<'a> { arguments: bumpalo::collections::Vec<'a, Node<'a>>, body: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body_type: BodyType, }, DeclareBlueprint<'b> { arguments: &'b [Box<Blueprint<'b>>], body: Option<Box<Blueprint<'b>>>, body_type: BodyType, });
627new_node!(DeclareArgument, DeclareArgumentNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, value: bumpalo::boxed::Box<'a, Node<'a>>, }, DeclareArgumentBlueprint<'b> { name: Box<Blueprint<'b>>, value: Box<Blueprint<'b>>, });
628new_node!(DoWhile, DoWhileNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, DoWhileBlueprint<'b> { condition: Box<Blueprint<'b>>, body: Box<Blueprint<'b>>, });
629new_node!(DoWhileCondition, DoWhileConditionNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, }, DoWhileConditionBlueprint<'b> { condition: Box<Blueprint<'b>>, });
630new_node!(Echo, EchoNode<'a> { items: bumpalo::collections::Vec<'a, Node<'a>>, }, EchoBlueprint<'b> { items: &'b [Box<Blueprint<'b>>], });
631new_node!(Else, ElseNode<'a> { body: bumpalo::boxed::Box<'a, Node<'a>>, is_short: bool, }, ElseBlueprint<'b> { body: Box<Blueprint<'b>>, is_short: bool, });
632new_node!(Encapsed, EncapsedNode<'a> { quote: Quote, values: bumpalo::collections::Vec<'a, Node<'a>>, }, EncapsedBlueprint<'b> { quote: Quote, values: &'b [Box<Blueprint<'b>>], });
633new_node!(EncapsedPart, EncapsedPartNode<'a> { is_advanced: bool, value: bumpalo::boxed::Box<'a, Node<'a>>, }, EncapsedPartBlueprint<'b> { is_advanced: bool, value: Box<Blueprint<'b>>, });
634new_node!(Enum, EnumNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, enum_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, implements: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body: bumpalo::collections::Vec<'a, Node<'a>>, }, EnumBlueprint<'b> { name: Box<Blueprint<'b>>, enum_type: Option<Box<Blueprint<'b>>>, implements: Option<Box<Blueprint<'b>>>, body: &'b [Box<Blueprint<'b>>], });
635new_node!(EnumItem, EnumItemNode<'a> { value: bumpalo::boxed::Box<'a, Node<'a>>, }, EnumItemBlueprint<'b> { value: Box<Blueprint<'b>>, });
636new_node!(Eval, EvalNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, EvalBlueprint<'b> { statement: Box<Blueprint<'b>>, });
637new_node!(Exit, ExitNode<'a> { statement: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, ExitBlueprint<'b> { statement: Option<Box<Blueprint<'b>>>, });
638new_node!(Finally, FinallyNode<'a> { body: bumpalo::boxed::Box<'a, Node<'a>>, }, FinallyBlueprint<'b> { body: Box<Blueprint<'b>>, });
639new_node!(For, ForNode<'a> { inits: bumpalo::collections::Vec<'a, Node<'a>>, tests: bumpalo::collections::Vec<'a, Node<'a>>, increments: bumpalo::collections::Vec<'a, Node<'a>>, body: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body_type: BodyType, }, ForBlueprint<'b> { inits: &'b [Box<Blueprint<'b>>], tests: &'b [Box<Blueprint<'b>>], increments: &'b [Box<Blueprint<'b>>], body: Option<Box<Blueprint<'b>>>, body_type: BodyType, });
640new_node!(Foreach, ForeachNode<'a> { source: bumpalo::boxed::Box<'a, Node<'a>>, key: Option<bumpalo::boxed::Box<'a, Node<'a>>>, value: bumpalo::boxed::Box<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, is_short: bool, }, ForeachBlueprint<'b> { source: Box<Blueprint<'b>>, key: Option<Box<Blueprint<'b>>>, value: Box<Blueprint<'b>>, body: Box<Blueprint<'b>>, is_short: bool, });
641new_node!(Function, FunctionNode<'a> { is_ref: bool, name: bumpalo::boxed::Box<'a, Node<'a>>, parameters: bumpalo::collections::Vec<'a, Node<'a>>, return_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, body: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, FunctionBlueprint<'b> { is_ref: bool, name: Box<Blueprint<'b>>, parameters: &'b [Box<Blueprint<'b>>], return_type: Option<Box<Blueprint<'b>>>, body: Option<Box<Blueprint<'b>>>, });
642new_node!(Global, GlobalNode<'a> { items: bumpalo::collections::Vec<'a, Node<'a>>, }, GlobalBlueprint<'b> { items: &'b [Box<Blueprint<'b>>], });
643new_node!(Goto, GotoNode<'a> { label: bumpalo::boxed::Box<'a, Node<'a>>, }, GotoBlueprint<'b> { label: Box<Blueprint<'b>>, });
644new_node!(HereDoc, HereDocNode<'a> { label: BString, values: bumpalo::collections::Vec<'a, Node<'a>>, }, HereDocBlueprint<'b> { label: &'b str, values: &'b [Box<Blueprint<'b>>], });
645new_node!(Identifier, IdentifierNode { name: BString, }, IdentifierBlueprint<'b> { name: &'b str, });
646new_node!(If, IfNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, valid: bumpalo::boxed::Box<'a, Node<'a>>, invalid: Option<bumpalo::boxed::Box<'a, Node<'a>>>, is_short: bool, }, IfBlueprint<'b> { condition: Box<Blueprint<'b>>, valid: Box<Blueprint<'b>>, invalid: Option<Box<Blueprint<'b>>>, is_short: bool, });
647new_node!(Include, IncludeNode<'a> { use_parenthesis: bool, is_require: bool, is_once: bool, argument: bumpalo::boxed::Box<'a, Node<'a>>, }, IncludeBlueprint<'b> { use_parenthesis: bool, is_require: bool, is_once: bool, argument: Box<Blueprint<'b>>, });
648new_node!(Inline, InlineNode { text: BString, }, InlineBlueprint<'b> { text: &'b str, });
649new_node!(Interface, InterfaceNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, extends: bumpalo::collections::Vec<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, InterfaceBlueprint<'b> { name: Box<Blueprint<'b>>, extends: &'b [Box<Blueprint<'b>>], body: Box<Blueprint<'b>>, });
650new_node!(IntersectionType, IntersectionTypeNode<'a> { types: bumpalo::collections::Vec<'a, Node<'a>>, }, IntersectionTypeBlueprint<'b> { types: &'b [Box<Blueprint<'b>>], });
651new_node!(Label, LabelNode<'a> { label: bumpalo::boxed::Box<'a, Node<'a>>, }, LabelBlueprint<'b> { label: Box<Blueprint<'b>>, });
652new_node!(List, ListNode<'a> { items: bumpalo::collections::Vec<'a, Node<'a>>, }, ListBlueprint<'b> { items: &'b [Box<Blueprint<'b>>], });
653new_node!(Magic, MagicNode { name: MagicName }, MagicBlueprint { name: MagicName });
654new_node!(
655  MagicMethod,
656  MagicMethodNode { name: MagicMethodName },
657  MagicMethodBlueprint { name: MagicMethodName }
658);
659new_node!(Match, MatchNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, arms: bumpalo::collections::Vec<'a, Node<'a>>, }, MatchBlueprint<'b> { condition: Box<Blueprint<'b>>, arms: &'b [Box<Blueprint<'b>>], });
660new_node!(MatchArm, MatchArmNode<'a> { conditions: bumpalo::collections::Vec<'a, Node<'a>>, expr: bumpalo::boxed::Box<'a, Node<'a>>, }, MatchArmBlueprint<'b> { conditions: &'b [Box<Blueprint<'b>>], expr: Box<Blueprint<'b>>, });
661new_node!(Method, MethodNode<'a> { visibility: Option<Visibility>, inheritance: Option<Inheritance>, is_static: bool, function: bumpalo::boxed::Box<'a, Node<'a>>, }, MethodBlueprint<'b> { visibility: Option<Visibility>, inheritance: Option<Inheritance>, is_static: bool, function: Box<Blueprint<'b>>, });
662new_node!(Namespace, NamespaceNode<'a> { name: BString, body: bumpalo::boxed::Box<'a, Node<'a>>, is_bracket: bool, }, NamespaceBlueprint<'b> { name: &'b str, body: Box<Blueprint<'b>>, is_bracket: bool, });
663new_node!(Negate, NegateNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, NegateBlueprint<'b> { statement: Box<Blueprint<'b>>, });
664new_node!(New, NewNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, NewBlueprint<'b> { statement: Box<Blueprint<'b>>, });
665new_node!(NowDoc, NowDocNode { label: BString, value: BString, }, NowDocBlueprint<'b> { label: &'b str, value: &'b str, });
666new_node!(Null, NullNode {}, NullBlueprint {});
667new_node!(Number, NumberNode { value: BString, }, NumberBlueprint<'b> { value: &'b str, });
668new_node!(ObjectAccess, ObjectAccessNode<'a> { object: bumpalo::boxed::Box<'a, Node<'a>>, property: bumpalo::boxed::Box<'a, Node<'a>>, use_bracket: bool, is_nullsafe: bool, }, ObjectAccessBlueprint<'b> { object: Box<Blueprint<'b>>, property: Box<Blueprint<'b>>, use_bracket: bool, is_nullsafe: bool, });
669new_node!(Parameter, ParameterNode<'a> { variable_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, is_ref: bool, is_ellipsis: bool, name: bumpalo::boxed::Box<'a, Node<'a>>, value: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, ParameterBlueprint<'b> { variable_type: Option<Box<Blueprint<'b>>>, is_ref: bool, is_ellipsis: bool, name: Box<Blueprint<'b>>, value: Option<Box<Blueprint<'b>>>, });
670new_node!(Parent, ParentNode {}, ParentBlueprint {});
671new_node!(Parenthesis, ParenthesisNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, ParenthesisBlueprint<'b> { statement: Box<Blueprint<'b>>, });
672new_node!(Post, PostNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, operator: PostType, }, PostBlueprint<'b> { statement: Box<Blueprint<'b>>, operator: PostType, });
673new_node!(Pre, PreNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, operator: PreType, }, PreBlueprint<'b> { statement: Box<Blueprint<'b>>, operator: PreType, });
674new_node!(Print, PrintNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, PrintBlueprint<'b> { statement: Box<Blueprint<'b>>, });
675new_node!(Program, ProgramNode<'a> { children: bumpalo::collections::Vec<'a, Node<'a>>, }, ProgramBlueprint<'b> { children: &'b [Box<Blueprint<'b>>], });
676new_node!(Property, PropertyNode<'a> { visibilities: Vec<Visibility>, modifier: Option<Modifier>, hooks: bumpalo::collections::Vec<'a, Node<'a>>, items: bumpalo::collections::Vec<'a, Node<'a>>, }, PropertyBlueprint<'b> { visibilities: Vec<Visibility>, modifier: Option<Modifier>, hooks: &'b [Box<Blueprint<'b>>], items: &'b [Box<Blueprint<'b>>], });
677new_node!(PropertyHook, PropertyHookNode<'a> { is_get: bool, is_ref: bool, parameters: bumpalo::collections::Vec<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, PropertyHookBlueprint<'b> { is_get: bool, is_ref: bool, parameters: &'b [Box<Blueprint<'b>>], body: Box<Blueprint<'b>>, });
678new_node!(PropertyItem, PropertyItemNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, variable_type: Option<bumpalo::boxed::Box<'a, Node<'a>>>, value: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, PropertyItemBlueprint<'b> { name: Box<Blueprint<'b>>, variable_type: Option<Box<Blueprint<'b>>>, value: Option<Box<Blueprint<'b>>>, });
679new_node!(Reference, ReferenceNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, ReferenceBlueprint<'b> { statement: Box<Blueprint<'b>>, });
680new_node!(Return, ReturnNode<'a> { statement: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, ReturnBlueprint<'b> { statement: Option<Box<Blueprint<'b>>>, });
681new_node!(SelfKeyword, SelfNode {}, SelfBlueprint {});
682new_node!(Silent, SilentNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, SilentBlueprint<'b> { statement: Box<Blueprint<'b>>, });
683new_node!(Static, StaticNode<'a> { items: bumpalo::collections::Vec<'a, Node<'a>>, }, StaticBlueprint<'b> { items: &'b [Box<Blueprint<'b>>], });
684new_node!(StaticKeyword, StaticKeywordNode {}, StaticKeywordBlueprint {});
685new_node!(StaticLookup, StaticLookupNode<'a> { left: bumpalo::boxed::Box<'a, Node<'a>>, right: bumpalo::boxed::Box<'a, Node<'a>>, use_bracket: bool, }, StaticLookupBlueprint<'b> { left: Box<Blueprint<'b>>, right: Box<Blueprint<'b>>, use_bracket: bool, });
686new_node!(String, StringNode { quote: Quote, value: BString, }, StringBlueprint<'b> { quote: Quote, value: &'b str, });
687new_node!(Switch, SwitchNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, is_short: bool, }, SwitchBlueprint<'b> { condition: Box<Blueprint<'b>>, body: Box<Blueprint<'b>>, is_short: bool, });
688new_node!(Ternary, TernaryNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, valid: bumpalo::boxed::Box<'a, Node<'a>>, invalid: bumpalo::boxed::Box<'a, Node<'a>>, }, TernaryBlueprint<'b> { condition: Box<Blueprint<'b>>, valid: Box<Blueprint<'b>>, invalid: Box<Blueprint<'b>>, });
689new_node!(This, ThisNode {}, ThisBlueprint {});
690new_node!(Throw, ThrowNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, ThrowBlueprint<'b> { statement: Box<Blueprint<'b>>, });
691new_node!(Trait, TraitNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, }, TraitBlueprint<'b> { name: Box<Blueprint<'b>>, body: Box<Blueprint<'b>>, });
692new_node!(TraitUse, TraitUseNode<'a> { traits: bumpalo::collections::Vec<'a, Node<'a>>, adaptations: bumpalo::collections::Vec<'a, Node<'a>>, }, TraitUseBlueprint<'b> { traits: &'b [Box<Blueprint<'b>>], adaptations: &'b [Box<Blueprint<'b>>], });
693new_node!(TraitUseAlias, TraitUseAliasNode<'a> { trait_name: Option<bumpalo::boxed::Box<'a, Node<'a>>>, method: bumpalo::boxed::Box<'a, Node<'a>>, alias: Option<bumpalo::boxed::Box<'a, Node<'a>>>, visibility: Option<Visibility>, }, TraitUseAliasBlueprint<'b> { trait_name: Option<Box<Blueprint<'b>>>, method: Box<Blueprint<'b>>, alias: Option<Box<Blueprint<'b>>>, visibility: Option<Visibility>, });
694new_node!(TraitUsePrecedence, TraitUsePrecedenceNode<'a> { trait_name: Option<bumpalo::boxed::Box<'a, Node<'a>>>, method: bumpalo::boxed::Box<'a, Node<'a>>, instead: bumpalo::boxed::Box<'a, Node<'a>>, }, TraitUsePrecedenceBlueprint<'b> { trait_name: Option<Box<Blueprint<'b>>>, method: Box<Blueprint<'b>>, instead: Box<Blueprint<'b>>, });
695new_node!(Try, TryNode<'a> { body: bumpalo::boxed::Box<'a, Node<'a>>, catches: bumpalo::collections::Vec<'a, Node<'a>>, }, TryBlueprint<'b> { body: Box<Blueprint<'b>>, catches: &'b [Box<Blueprint<'b>>], });
696new_node!(Type, TypeNode { is_nullable: bool, name: BString, }, TypeBlueprint<'b> { is_nullable: bool, name: &'b str, });
697new_node!(UnionType, UnionTypeNode<'a> { types: bumpalo::collections::Vec<'a, Node<'a>>, }, UnionTypeBlueprint<'b> { types: &'b [Box<Blueprint<'b>>], });
698new_node!(Use, UseNode<'a> { name: Option<BString>, items: bumpalo::collections::Vec<'a, Node<'a>>, }, UseBlueprint<'b> { name: Option<&'b str>, items: &'b [Box<Blueprint<'b>>], });
699new_node!(UseItem, UseItemNode<'a> { modifier: Option<UseItemModifier>, name: BString, alias: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, UseItemBlueprint<'b> { modifier: Option<UseItemModifier>, name: &'b str, alias: Option<Box<Blueprint<'b>>>, });
700new_node!(Variable, VariableNode<'a> { name: bumpalo::boxed::Box<'a, Node<'a>>, }, VariableBlueprint<'b> { name: Box<Blueprint<'b>>, });
701new_node!(Variadic, VariadicNode<'a> { statement: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, VariadicBlueprint<'b> { statement: Option<Box<Blueprint<'b>>>, });
702new_node!(While, WhileNode<'a> { condition: bumpalo::boxed::Box<'a, Node<'a>>, body: bumpalo::boxed::Box<'a, Node<'a>>, is_short: bool, }, WhileBlueprint<'b> { condition: Box<Blueprint<'b>>, body: Box<Blueprint<'b>>, is_short: bool, });
703new_node!(Yield, YieldNode<'a> { key: Option<bumpalo::boxed::Box<'a, Node<'a>>>, value: Option<bumpalo::boxed::Box<'a, Node<'a>>>, }, YieldBlueprint<'b> { key: Option<Box<Blueprint<'b>>>, value: Option<Box<Blueprint<'b>>>, });
704new_node!(YieldFrom, YieldFromNode<'a> { statement: bumpalo::boxed::Box<'a, Node<'a>>, }, YieldFromBlueprint<'b> { statement: Box<Blueprint<'b>>, });
705
706#[derive(Debug, PartialEq, Clone, Serialize)]
707pub enum MagicMethodName {
708  Construct,
709  Destruct,
710  Call,
711  CallStatic,
712  Get,
713  Set,
714  Isset,
715  Unset,
716  Sleep,
717  Wakeup,
718  Serialize,
719  Unserialize,
720  ToString,
721  Invoke,
722  SetState,
723  Clone,
724  DebugInfo,
725}
726
727impl TryFrom<&BString> for MagicMethodName {
728  type Error = String;
729
730  fn try_from(value: &BString) -> Result<Self, Self::Error> {
731    match value.as_slice() {
732      b"__construct" => Ok(MagicMethodName::Construct),
733      b"__destruct" => Ok(MagicMethodName::Destruct),
734      b"__call" => Ok(MagicMethodName::Call),
735      b"__callStatic" => Ok(MagicMethodName::CallStatic),
736      b"__get" => Ok(MagicMethodName::Get),
737      b"__set" => Ok(MagicMethodName::Set),
738      b"__isset" => Ok(MagicMethodName::Isset),
739      b"__unset" => Ok(MagicMethodName::Unset),
740      b"__sleep" => Ok(MagicMethodName::Sleep),
741      b"__wakeup" => Ok(MagicMethodName::Wakeup),
742      b"__serialize" => Ok(MagicMethodName::Serialize),
743      b"__unserialize" => Ok(MagicMethodName::Unserialize),
744      b"__toString" => Ok(MagicMethodName::ToString),
745      b"__invoke" => Ok(MagicMethodName::Invoke),
746      b"__set_state" => Ok(MagicMethodName::SetState),
747      b"__clone" => Ok(MagicMethodName::Clone),
748      b"__debugInfo" => Ok(MagicMethodName::DebugInfo),
749      _ => Err(format!("Invalid magic method name: {}", value)),
750    }
751  }
752}
753
754impl Display for MagicMethodName {
755  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
756    write!(f, "{}", match self {
757      MagicMethodName::Construct => "__construct",
758      MagicMethodName::Destruct => "__destruct",
759      MagicMethodName::Call => "__call",
760      MagicMethodName::CallStatic => "__callStatic",
761      MagicMethodName::Get => "__get",
762      MagicMethodName::Set => "__set",
763      MagicMethodName::Isset => "__isset",
764      MagicMethodName::Unset => "__unset",
765      MagicMethodName::Sleep => "__sleep",
766      MagicMethodName::Wakeup => "__wakeup",
767      MagicMethodName::Serialize => "__serialize",
768      MagicMethodName::Unserialize => "__unserialize",
769      MagicMethodName::ToString => "__toString",
770      MagicMethodName::Invoke => "__invoke",
771      MagicMethodName::SetState => "__set_state",
772      MagicMethodName::Clone => "__clone",
773      MagicMethodName::DebugInfo => "__debugInfo",
774    })
775  }
776}
777
778#[derive(Debug, PartialEq, Clone, Serialize)]
779pub enum MagicName {
780  Class,
781  Dir,
782  File,
783  Function,
784  Line,
785  Method,
786  Namespace,
787  Trait,
788  Property,
789}
790
791impl TryFrom<&BString> for MagicName {
792  type Error = String;
793
794  fn try_from(value: &BString) -> Result<Self, Self::Error> {
795    match value.as_slice() {
796      b"__CLASS__" => Ok(MagicName::Class),
797      b"__DIR__" => Ok(MagicName::Dir),
798      b"__FILE__" => Ok(MagicName::File),
799      b"__FUNCTION__" => Ok(MagicName::Function),
800      b"__LINE__" => Ok(MagicName::Line),
801      b"__METHOD__" => Ok(MagicName::Method),
802      b"__NAMESPACE__" => Ok(MagicName::Namespace),
803      b"__TRAIT__" => Ok(MagicName::Trait),
804      b"__PROPERTY__" => Ok(MagicName::Property),
805      _ => Err(format!("Invalid magic name: {}", value)),
806    }
807  }
808}
809
810impl Display for MagicName {
811  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
812    write!(f, "{}", match self {
813      MagicName::Class => "__CLASS__",
814      MagicName::Dir => "__DIR__",
815      MagicName::File => "__FILE__",
816      MagicName::Function => "__FUNCTION__",
817      MagicName::Line => "__LINE__",
818      MagicName::Method => "__METHOD__",
819      MagicName::Namespace => "__NAMESPACE__",
820      MagicName::Trait => "__TRAIT__",
821      MagicName::Property => "__PROPERTY__",
822    })
823  }
824}
825#[derive(Debug, PartialEq, Clone, Serialize)]
826pub enum PreType {
827  Increment,
828  Decrement,
829  Addition,
830  Subtraction,
831}
832
833impl TryFrom<&BString> for PreType {
834  type Error = String;
835
836  fn try_from(value: &BString) -> Result<Self, Self::Error> {
837    match value.as_slice() {
838      b"++" => Ok(PreType::Increment),
839      b"--" => Ok(PreType::Decrement),
840      b"+" => Ok(PreType::Addition),
841      b"-" => Ok(PreType::Subtraction),
842      _ => Err(format!("Invalid pre type: {}", value)),
843    }
844  }
845}
846
847impl Display for PreType {
848  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
849    write!(f, "{}", match self {
850      PreType::Increment => "++",
851      PreType::Decrement => "--",
852      PreType::Addition => "+",
853      PreType::Subtraction => "-",
854    })
855  }
856}
857
858#[derive(Debug, PartialEq, Clone, Serialize)]
859pub enum PostType {
860  Increment,
861  Decrement,
862}
863
864impl TryFrom<&BString> for PostType {
865  type Error = String;
866
867  fn try_from(value: &BString) -> Result<Self, Self::Error> {
868    match value.as_slice() {
869      b"++" => Ok(PostType::Increment),
870      b"--" => Ok(PostType::Decrement),
871      _ => Err(format!("Invalid post type: {}", value)),
872    }
873  }
874}
875
876impl Display for PostType {
877  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
878    write!(f, "{}", match self {
879      PostType::Increment => "++",
880      PostType::Decrement => "--",
881    })
882  }
883}
884
885#[derive(Debug, PartialEq, Clone, Serialize)]
886pub enum CastType {
887  Int,
888  Integer,
889  Bool,
890  Boolean,
891  Float,
892  Double,
893  Real,
894  String,
895  Binary,
896  Array,
897  Object,
898  Unset,
899}
900
901impl TryFrom<&BString> for CastType {
902  type Error = String;
903
904  fn try_from(value: &BString) -> Result<Self, Self::Error> {
905    match value.as_slice() {
906      b"int" => Ok(CastType::Int),
907      b"integer" => Ok(CastType::Integer),
908      b"bool" => Ok(CastType::Bool),
909      b"boolean" => Ok(CastType::Boolean),
910      b"float" => Ok(CastType::Float),
911      b"double" => Ok(CastType::Double),
912      b"real" => Ok(CastType::Real),
913      b"string" => Ok(CastType::String),
914      b"binary" => Ok(CastType::Binary),
915      b"array" => Ok(CastType::Array),
916      b"object" => Ok(CastType::Object),
917      b"unset" => Ok(CastType::Unset),
918      _ => Err(format!("Invalid cast type: {}", value)),
919    }
920  }
921}
922
923impl Display for CastType {
924  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
925    write!(f, "{}", match self {
926      CastType::Int => "int",
927      CastType::Integer => "integer",
928      CastType::Bool => "bool",
929      CastType::Boolean => "boolean",
930      CastType::Float => "float",
931      CastType::Double => "double",
932      CastType::Real => "real",
933      CastType::String => "string",
934      CastType::Binary => "binary",
935      CastType::Array => "array",
936      CastType::Object => "object",
937      CastType::Unset => "unset",
938    })
939  }
940}
941
942#[derive(Debug, PartialEq, Clone, Serialize)]
943pub enum BinaryType {
944  Addition,
945  Subtraction,
946  Multiplication,
947  Division,
948  Modulus,
949  Exponentiation,
950  BitwiseAnd,
951  BitwiseOr,
952  BitwiseXor,
953  BitwiseShiftLeft,
954  BitwiseShiftRight,
955  IsEqual,
956  IsIdentical,
957  IsNotEqual,
958  IsNotIdentical,
959  IsLesser,
960  IsGreater,
961  IsLesserOrEqual,
962  IsGreaterOrEqual,
963  Spaceship,
964  Concatenation,
965  BooleanAnd,
966  BooleanOr,
967  BooleanXor,
968  Elvis,
969  Coalesce,
970  InstanceOf,
971}
972
973impl TryFrom<&BString> for BinaryType {
974  type Error = String;
975
976  fn try_from(value: &BString) -> Result<Self, Self::Error> {
977    match value.as_slice() {
978      b"+" => Ok(BinaryType::Addition),
979      b"-" => Ok(BinaryType::Subtraction),
980      b"*" => Ok(BinaryType::Multiplication),
981      b"/" => Ok(BinaryType::Division),
982      b"%" => Ok(BinaryType::Modulus),
983      b"**" => Ok(BinaryType::Exponentiation),
984      b"&" => Ok(BinaryType::BitwiseAnd),
985      b"|" => Ok(BinaryType::BitwiseOr),
986      b"^" => Ok(BinaryType::BitwiseXor),
987      b"<<" => Ok(BinaryType::BitwiseShiftLeft),
988      b">>" => Ok(BinaryType::BitwiseShiftRight),
989      b"==" => Ok(BinaryType::IsEqual),
990      b"===" => Ok(BinaryType::IsIdentical),
991      b"!=" => Ok(BinaryType::IsNotEqual),
992      b"!==" => Ok(BinaryType::IsNotIdentical),
993      b"<" => Ok(BinaryType::IsLesser),
994      b">" => Ok(BinaryType::IsGreater),
995      b"<=" => Ok(BinaryType::IsLesserOrEqual),
996      b">=" => Ok(BinaryType::IsGreaterOrEqual),
997      b"<=>" => Ok(BinaryType::Spaceship),
998      b"." => Ok(BinaryType::Concatenation),
999      b"&&" | b"and" => Ok(BinaryType::BooleanAnd),
1000      b"||" | b"or" => Ok(BinaryType::BooleanOr),
1001      b"xor" => Ok(BinaryType::BooleanXor),
1002      b"?:" => Ok(BinaryType::Elvis),
1003      b"??" => Ok(BinaryType::Coalesce),
1004      b"instanceof" => Ok(BinaryType::InstanceOf),
1005      _ => Err(format!("Invalid binary type: {}", value)),
1006    }
1007  }
1008}
1009
1010impl Display for BinaryType {
1011  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1012    write!(f, "{}", match self {
1013      BinaryType::Addition => "+",
1014      BinaryType::Subtraction => "-",
1015      BinaryType::Multiplication => "*",
1016      BinaryType::Division => "/",
1017      BinaryType::Modulus => "%",
1018      BinaryType::Exponentiation => "**",
1019      BinaryType::BitwiseAnd => "&",
1020      BinaryType::BitwiseOr => "|",
1021      BinaryType::BitwiseXor => "^",
1022      BinaryType::BitwiseShiftLeft => "<<",
1023      BinaryType::BitwiseShiftRight => ">>",
1024      BinaryType::IsEqual => "==",
1025      BinaryType::IsIdentical => "===",
1026      BinaryType::IsNotEqual => "!=",
1027      BinaryType::IsNotIdentical => "!==",
1028      BinaryType::IsLesser => "<",
1029      BinaryType::IsGreater => ">",
1030      BinaryType::IsLesserOrEqual => "<=",
1031      BinaryType::IsGreaterOrEqual => ">=",
1032      BinaryType::Spaceship => "<=>",
1033      BinaryType::Concatenation => ".",
1034      BinaryType::BooleanAnd => "&&",
1035      BinaryType::BooleanOr => "||",
1036      BinaryType::BooleanXor => "xor",
1037      BinaryType::Elvis => "?:",
1038      BinaryType::Coalesce => "??",
1039      BinaryType::InstanceOf => "instanceof",
1040    })
1041  }
1042}
1043
1044#[derive(Debug, PartialEq, Clone, Serialize)]
1045pub enum AssignmentType {
1046  Default,
1047  Reference,
1048  Coalesce,
1049  Concatenation,
1050  Addition,
1051  Subtraction,
1052  Multiplication,
1053  Division,
1054  Exponentiation,
1055  Modulus,
1056  BitwiseAnd,
1057  BitwiseOr,
1058  BitwiseXor,
1059  BitwiseShiftRight,
1060  BitwiseShiftLeft,
1061}
1062
1063impl TryFrom<&BString> for AssignmentType {
1064  type Error = String;
1065
1066  fn try_from(value: &BString) -> Result<Self, Self::Error> {
1067    match value.as_slice() {
1068      b"=" => Ok(AssignmentType::Default),
1069      b"=&" => Ok(AssignmentType::Reference),
1070      b"??=" => Ok(AssignmentType::Coalesce),
1071      b".=" => Ok(AssignmentType::Concatenation),
1072      b"+=" => Ok(AssignmentType::Addition),
1073      b"-=" => Ok(AssignmentType::Subtraction),
1074      b"*=" => Ok(AssignmentType::Multiplication),
1075      b"/=" => Ok(AssignmentType::Division),
1076      b"**=" => Ok(AssignmentType::Exponentiation),
1077      b"%=" => Ok(AssignmentType::Modulus),
1078      b"&=" => Ok(AssignmentType::BitwiseAnd),
1079      b"|=" => Ok(AssignmentType::BitwiseOr),
1080      b"^=" => Ok(AssignmentType::BitwiseXor),
1081      b">>=" => Ok(AssignmentType::BitwiseShiftRight),
1082      b"<<=" => Ok(AssignmentType::BitwiseShiftLeft),
1083      _ => Err(format!("Invalid assignment type: {}", value)),
1084    }
1085  }
1086}
1087
1088impl Display for AssignmentType {
1089  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1090    write!(f, "{}", match self {
1091      AssignmentType::Default => "=",
1092      AssignmentType::Reference => "=&",
1093      AssignmentType::Coalesce => "??=",
1094      AssignmentType::Concatenation => ".=",
1095      AssignmentType::Addition => "+=",
1096      AssignmentType::Subtraction => "-=",
1097      AssignmentType::Multiplication => "*=",
1098      AssignmentType::Division => "/=",
1099      AssignmentType::Exponentiation => "**=",
1100      AssignmentType::Modulus => "%=",
1101      AssignmentType::BitwiseAnd => "&=",
1102      AssignmentType::BitwiseOr => "|=",
1103      AssignmentType::BitwiseXor => "^=",
1104      AssignmentType::BitwiseShiftRight => ">>=",
1105      AssignmentType::BitwiseShiftLeft => "<<=",
1106    })
1107  }
1108}
1109
1110#[derive(Debug, PartialEq, Clone, Serialize)]
1111pub enum UseItemModifier {
1112  Function,
1113  Const,
1114}
1115
1116impl TryFrom<&BString> for UseItemModifier {
1117  type Error = String;
1118
1119  fn try_from(value: &BString) -> Result<Self, Self::Error> {
1120    match value.as_slice() {
1121      b"function" => Ok(UseItemModifier::Function),
1122      b"const" => Ok(UseItemModifier::Const),
1123      _ => Err(format!("Invalid use item modifier: {}", value)),
1124    }
1125  }
1126}
1127
1128impl Display for UseItemModifier {
1129  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1130    write!(f, "{}", match self {
1131      UseItemModifier::Function => "function",
1132      UseItemModifier::Const => "const",
1133    })
1134  }
1135}
1136
1137#[derive(Debug, PartialEq, Clone, Serialize)]
1138pub enum Modifier {
1139  Static,
1140  Readonly,
1141}
1142
1143impl TryFrom<&BString> for Modifier {
1144  type Error = String;
1145
1146  fn try_from(value: &BString) -> Result<Self, Self::Error> {
1147    match value.as_slice() {
1148      b"static" => Ok(Modifier::Static),
1149      b"readonly" => Ok(Modifier::Readonly),
1150      _ => Err(format!("Invalid modifier: {}", value)),
1151    }
1152  }
1153}
1154
1155impl Display for Modifier {
1156  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1157    write!(f, "{}", match self {
1158      Modifier::Static => "static",
1159      Modifier::Readonly => "readonly",
1160    })
1161  }
1162}
1163
1164#[derive(Debug, PartialEq, Clone, Serialize)]
1165pub enum Quote {
1166  Single,
1167  Double,
1168  Backtick,
1169}
1170
1171impl TryFrom<&BString> for Quote {
1172  type Error = String;
1173
1174  fn try_from(value: &BString) -> Result<Self, Self::Error> {
1175    match value.as_slice() {
1176      b"'" => Ok(Quote::Single),
1177      b"\"" => Ok(Quote::Double),
1178      b"`" => Ok(Quote::Backtick),
1179      _ => Err(format!("Invalid quote: {}", value)),
1180    }
1181  }
1182}
1183
1184impl Display for Quote {
1185  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1186    write!(f, "{}", match self {
1187      Quote::Single => "'",
1188      Quote::Double => "\"",
1189      Quote::Backtick => "`",
1190    })
1191  }
1192}
1193
1194#[derive(Debug, PartialEq, Clone, Serialize)]
1195pub enum Inheritance {
1196  Abstract,
1197  Final,
1198}
1199
1200impl TryFrom<&BString> for Inheritance {
1201  type Error = String;
1202
1203  fn try_from(value: &BString) -> Result<Self, Self::Error> {
1204    match value.as_slice() {
1205      b"abstract" => Ok(Inheritance::Abstract),
1206      b"final" => Ok(Inheritance::Final),
1207      _ => Err(format!("Invalid inheritance: {}", value)),
1208    }
1209  }
1210}
1211
1212impl Display for Inheritance {
1213  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1214    write!(f, "{}", match self {
1215      Inheritance::Abstract => "abstract",
1216      Inheritance::Final => "final",
1217    })
1218  }
1219}
1220
1221#[derive(Debug, PartialEq, Clone, Serialize)]
1222pub enum Visibility {
1223  Public,
1224  PublicGet,
1225  PublicSet,
1226  Private,
1227  PrivateGet,
1228  PrivateSet,
1229  Protected,
1230  ProtectedGet,
1231  ProtectedSet,
1232}
1233
1234impl TryFrom<&BString> for Visibility {
1235  type Error = String;
1236
1237  fn try_from(value: &BString) -> Result<Self, Self::Error> {
1238    match value.as_slice() {
1239      b"public" => Ok(Visibility::Public),
1240      b"public(get)" => Ok(Visibility::PublicGet),
1241      b"public(set)" => Ok(Visibility::PublicSet),
1242      b"private" => Ok(Visibility::Private),
1243      b"private(get)" => Ok(Visibility::PrivateGet),
1244      b"private(set)" => Ok(Visibility::PrivateSet),
1245      b"protected" => Ok(Visibility::Protected),
1246      b"protected(get)" => Ok(Visibility::ProtectedGet),
1247      b"protected(set)" => Ok(Visibility::ProtectedSet),
1248      _ => Err(format!("Invalid visibility: {}", value)),
1249    }
1250  }
1251}
1252
1253impl Display for Visibility {
1254  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
1255    write!(f, "{}", match self {
1256      Visibility::Public => "public",
1257      Visibility::PublicGet => "public(get)",
1258      Visibility::PublicSet => "public(set)",
1259      Visibility::Private => "private",
1260      Visibility::PrivateGet => "private(get)",
1261      Visibility::PrivateSet => "private(set)",
1262      Visibility::Protected => "protected",
1263      Visibility::ProtectedGet => "protected(get)",
1264      Visibility::ProtectedSet => "protected(set)",
1265    })
1266  }
1267}
1268
1269#[cfg(test)]
1270mod tests {
1271  use bstr::BString;
1272
1273  use crate::{
1274    AssignmentType,
1275    BinaryType,
1276    CastType,
1277    Inheritance,
1278    MagicMethodName,
1279    MagicName,
1280    Modifier,
1281    PostType,
1282    PreType,
1283    Quote,
1284    UseItemModifier,
1285    Visibility,
1286  };
1287
1288  #[test]
1289  fn magic_name() {
1290    assert_eq!(
1291      MagicName::try_from(&BString::new("__CLASS__".as_bytes().to_vec())),
1292      Ok(MagicName::Class)
1293    );
1294    assert_eq!(
1295      MagicName::try_from(&BString::new("__DIR__".as_bytes().to_vec())),
1296      Ok(MagicName::Dir)
1297    );
1298    assert_eq!(
1299      MagicName::try_from(&BString::new("__FILE__".as_bytes().to_vec())),
1300      Ok(MagicName::File)
1301    );
1302    assert_eq!(
1303      MagicName::try_from(&BString::new("__FUNCTION__".as_bytes().to_vec())),
1304      Ok(MagicName::Function)
1305    );
1306    assert_eq!(
1307      MagicName::try_from(&BString::new("__LINE__".as_bytes().to_vec())),
1308      Ok(MagicName::Line)
1309    );
1310    assert_eq!(
1311      MagicName::try_from(&BString::new("__METHOD__".as_bytes().to_vec())),
1312      Ok(MagicName::Method)
1313    );
1314    assert_eq!(
1315      MagicName::try_from(&BString::new("__NAMESPACE__".as_bytes().to_vec())),
1316      Ok(MagicName::Namespace)
1317    );
1318    assert_eq!(
1319      MagicName::try_from(&BString::new("__TRAIT__".as_bytes().to_vec())),
1320      Ok(MagicName::Trait)
1321    );
1322    assert_eq!(
1323      MagicName::try_from(&BString::new("__PROPERTY__".as_bytes().to_vec())),
1324      Ok(MagicName::Property)
1325    );
1326    assert!(MagicName::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1327
1328    assert_eq!("__CLASS__", format!("{}", MagicName::Class));
1329    assert_eq!("__DIR__", format!("{}", MagicName::Dir));
1330    assert_eq!("__FILE__", format!("{}", MagicName::File));
1331    assert_eq!("__FUNCTION__", format!("{}", MagicName::Function));
1332    assert_eq!("__LINE__", format!("{}", MagicName::Line));
1333    assert_eq!("__METHOD__", format!("{}", MagicName::Method));
1334    assert_eq!("__NAMESPACE__", format!("{}", MagicName::Namespace));
1335    assert_eq!("__TRAIT__", format!("{}", MagicName::Trait));
1336    assert_eq!("__PROPERTY__", format!("{}", MagicName::Property));
1337  }
1338
1339  #[test]
1340  fn magic_method_name() {
1341    assert_eq!(
1342      MagicMethodName::try_from(&BString::new("__construct".as_bytes().to_vec())),
1343      Ok(MagicMethodName::Construct)
1344    );
1345    assert_eq!(
1346      MagicMethodName::try_from(&BString::new("__destruct".as_bytes().to_vec())),
1347      Ok(MagicMethodName::Destruct)
1348    );
1349    assert_eq!(
1350      MagicMethodName::try_from(&BString::new("__call".as_bytes().to_vec())),
1351      Ok(MagicMethodName::Call)
1352    );
1353    assert_eq!(
1354      MagicMethodName::try_from(&BString::new("__callStatic".as_bytes().to_vec())),
1355      Ok(MagicMethodName::CallStatic)
1356    );
1357    assert_eq!(
1358      MagicMethodName::try_from(&BString::new("__get".as_bytes().to_vec())),
1359      Ok(MagicMethodName::Get)
1360    );
1361    assert_eq!(
1362      MagicMethodName::try_from(&BString::new("__set".as_bytes().to_vec())),
1363      Ok(MagicMethodName::Set)
1364    );
1365    assert_eq!(
1366      MagicMethodName::try_from(&BString::new("__isset".as_bytes().to_vec())),
1367      Ok(MagicMethodName::Isset)
1368    );
1369    assert_eq!(
1370      MagicMethodName::try_from(&BString::new("__unset".as_bytes().to_vec())),
1371      Ok(MagicMethodName::Unset)
1372    );
1373    assert_eq!(
1374      MagicMethodName::try_from(&BString::new("__sleep".as_bytes().to_vec())),
1375      Ok(MagicMethodName::Sleep)
1376    );
1377    assert_eq!(
1378      MagicMethodName::try_from(&BString::new("__wakeup".as_bytes().to_vec())),
1379      Ok(MagicMethodName::Wakeup)
1380    );
1381    assert_eq!(
1382      MagicMethodName::try_from(&BString::new("__serialize".as_bytes().to_vec())),
1383      Ok(MagicMethodName::Serialize)
1384    );
1385    assert_eq!(
1386      MagicMethodName::try_from(&BString::new("__unserialize".as_bytes().to_vec())),
1387      Ok(MagicMethodName::Unserialize)
1388    );
1389    assert_eq!(
1390      MagicMethodName::try_from(&BString::new("__toString".as_bytes().to_vec())),
1391      Ok(MagicMethodName::ToString)
1392    );
1393    assert_eq!(
1394      MagicMethodName::try_from(&BString::new("__invoke".as_bytes().to_vec())),
1395      Ok(MagicMethodName::Invoke)
1396    );
1397    assert_eq!(
1398      MagicMethodName::try_from(&BString::new("__set_state".as_bytes().to_vec())),
1399      Ok(MagicMethodName::SetState)
1400    );
1401    assert_eq!(
1402      MagicMethodName::try_from(&BString::new("__clone".as_bytes().to_vec())),
1403      Ok(MagicMethodName::Clone)
1404    );
1405    assert_eq!(
1406      MagicMethodName::try_from(&BString::new("__debugInfo".as_bytes().to_vec())),
1407      Ok(MagicMethodName::DebugInfo)
1408    );
1409    assert!(MagicMethodName::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1410
1411    assert_eq!("__construct", format!("{}", MagicMethodName::Construct));
1412    assert_eq!("__destruct", format!("{}", MagicMethodName::Destruct));
1413    assert_eq!("__call", format!("{}", MagicMethodName::Call));
1414    assert_eq!("__callStatic", format!("{}", MagicMethodName::CallStatic));
1415    assert_eq!("__get", format!("{}", MagicMethodName::Get));
1416    assert_eq!("__set", format!("{}", MagicMethodName::Set));
1417    assert_eq!("__isset", format!("{}", MagicMethodName::Isset));
1418    assert_eq!("__unset", format!("{}", MagicMethodName::Unset));
1419    assert_eq!("__sleep", format!("{}", MagicMethodName::Sleep));
1420    assert_eq!("__wakeup", format!("{}", MagicMethodName::Wakeup));
1421    assert_eq!("__serialize", format!("{}", MagicMethodName::Serialize));
1422    assert_eq!("__unserialize", format!("{}", MagicMethodName::Unserialize));
1423    assert_eq!("__toString", format!("{}", MagicMethodName::ToString));
1424    assert_eq!("__invoke", format!("{}", MagicMethodName::Invoke));
1425    assert_eq!("__set_state", format!("{}", MagicMethodName::SetState));
1426    assert_eq!("__clone", format!("{}", MagicMethodName::Clone));
1427    assert_eq!("__debugInfo", format!("{}", MagicMethodName::DebugInfo));
1428  }
1429
1430  #[test]
1431  fn pre_type() {
1432    assert_eq!(PreType::try_from(&BString::new("++".as_bytes().to_vec())), Ok(PreType::Increment));
1433    assert_eq!(PreType::try_from(&BString::new("--".as_bytes().to_vec())), Ok(PreType::Decrement));
1434    assert_eq!(PreType::try_from(&BString::new("+".as_bytes().to_vec())), Ok(PreType::Addition));
1435    assert_eq!(PreType::try_from(&BString::new("-".as_bytes().to_vec())), Ok(PreType::Subtraction));
1436    assert!(PreType::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1437
1438    assert_eq!("++", format!("{}", PreType::Increment));
1439    assert_eq!("--", format!("{}", PreType::Decrement));
1440    assert_eq!("+", format!("{}", PreType::Addition));
1441    assert_eq!("-", format!("{}", PreType::Subtraction));
1442  }
1443
1444  #[test]
1445  fn post_type() {
1446    assert_eq!(
1447      PostType::try_from(&BString::new("++".as_bytes().to_vec())),
1448      Ok(PostType::Increment)
1449    );
1450    assert_eq!(
1451      PostType::try_from(&BString::new("--".as_bytes().to_vec())),
1452      Ok(PostType::Decrement)
1453    );
1454    assert!(PostType::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1455
1456    assert_eq!("++", format!("{}", PostType::Increment));
1457    assert_eq!("--", format!("{}", PostType::Decrement));
1458  }
1459
1460  #[test]
1461  fn cast_type() {
1462    assert_eq!(CastType::try_from(&BString::new("int".as_bytes().to_vec())), Ok(CastType::Int));
1463    assert_eq!(
1464      CastType::try_from(&BString::new("integer".as_bytes().to_vec())),
1465      Ok(CastType::Integer)
1466    );
1467    assert_eq!(CastType::try_from(&BString::new("bool".as_bytes().to_vec())), Ok(CastType::Bool));
1468    assert_eq!(
1469      CastType::try_from(&BString::new("boolean".as_bytes().to_vec())),
1470      Ok(CastType::Boolean)
1471    );
1472    assert_eq!(CastType::try_from(&BString::new("float".as_bytes().to_vec())), Ok(CastType::Float));
1473    assert_eq!(
1474      CastType::try_from(&BString::new("double".as_bytes().to_vec())),
1475      Ok(CastType::Double)
1476    );
1477    assert_eq!(CastType::try_from(&BString::new("real".as_bytes().to_vec())), Ok(CastType::Real));
1478    assert_eq!(
1479      CastType::try_from(&BString::new("string".as_bytes().to_vec())),
1480      Ok(CastType::String)
1481    );
1482    assert_eq!(
1483      CastType::try_from(&BString::new("binary".as_bytes().to_vec())),
1484      Ok(CastType::Binary)
1485    );
1486    assert_eq!(CastType::try_from(&BString::new("array".as_bytes().to_vec())), Ok(CastType::Array));
1487    assert_eq!(
1488      CastType::try_from(&BString::new("object".as_bytes().to_vec())),
1489      Ok(CastType::Object)
1490    );
1491    assert_eq!(CastType::try_from(&BString::new("unset".as_bytes().to_vec())), Ok(CastType::Unset));
1492    assert!(CastType::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1493
1494    assert_eq!("int", format!("{}", CastType::Int));
1495    assert_eq!("integer", format!("{}", CastType::Integer));
1496    assert_eq!("bool", format!("{}", CastType::Bool));
1497    assert_eq!("boolean", format!("{}", CastType::Boolean));
1498    assert_eq!("float", format!("{}", CastType::Float));
1499    assert_eq!("double", format!("{}", CastType::Double));
1500    assert_eq!("real", format!("{}", CastType::Real));
1501    assert_eq!("string", format!("{}", CastType::String));
1502    assert_eq!("binary", format!("{}", CastType::Binary));
1503    assert_eq!("array", format!("{}", CastType::Array));
1504    assert_eq!("object", format!("{}", CastType::Object));
1505    assert_eq!("unset", format!("{}", CastType::Unset));
1506  }
1507
1508  #[test]
1509  fn binary_type() {
1510    assert_eq!(
1511      BinaryType::try_from(&BString::new("+".as_bytes().to_vec())),
1512      Ok(BinaryType::Addition)
1513    );
1514    assert_eq!(
1515      BinaryType::try_from(&BString::new("-".as_bytes().to_vec())),
1516      Ok(BinaryType::Subtraction)
1517    );
1518    assert_eq!(
1519      BinaryType::try_from(&BString::new("*".as_bytes().to_vec())),
1520      Ok(BinaryType::Multiplication)
1521    );
1522    assert_eq!(
1523      BinaryType::try_from(&BString::new("/".as_bytes().to_vec())),
1524      Ok(BinaryType::Division)
1525    );
1526    assert_eq!(
1527      BinaryType::try_from(&BString::new("%".as_bytes().to_vec())),
1528      Ok(BinaryType::Modulus)
1529    );
1530    assert_eq!(
1531      BinaryType::try_from(&BString::new("**".as_bytes().to_vec())),
1532      Ok(BinaryType::Exponentiation)
1533    );
1534    assert_eq!(
1535      BinaryType::try_from(&BString::new("&".as_bytes().to_vec())),
1536      Ok(BinaryType::BitwiseAnd)
1537    );
1538    assert_eq!(
1539      BinaryType::try_from(&BString::new("|".as_bytes().to_vec())),
1540      Ok(BinaryType::BitwiseOr)
1541    );
1542    assert_eq!(
1543      BinaryType::try_from(&BString::new("^".as_bytes().to_vec())),
1544      Ok(BinaryType::BitwiseXor)
1545    );
1546    assert_eq!(
1547      BinaryType::try_from(&BString::new("<<".as_bytes().to_vec())),
1548      Ok(BinaryType::BitwiseShiftLeft)
1549    );
1550    assert_eq!(
1551      BinaryType::try_from(&BString::new(">>".as_bytes().to_vec())),
1552      Ok(BinaryType::BitwiseShiftRight)
1553    );
1554    assert_eq!(
1555      BinaryType::try_from(&BString::new("==".as_bytes().to_vec())),
1556      Ok(BinaryType::IsEqual)
1557    );
1558    assert_eq!(
1559      BinaryType::try_from(&BString::new("===".as_bytes().to_vec())),
1560      Ok(BinaryType::IsIdentical)
1561    );
1562    assert_eq!(
1563      BinaryType::try_from(&BString::new("!=".as_bytes().to_vec())),
1564      Ok(BinaryType::IsNotEqual)
1565    );
1566    assert_eq!(
1567      BinaryType::try_from(&BString::new("!==".as_bytes().to_vec())),
1568      Ok(BinaryType::IsNotIdentical)
1569    );
1570    assert_eq!(
1571      BinaryType::try_from(&BString::new("<".as_bytes().to_vec())),
1572      Ok(BinaryType::IsLesser)
1573    );
1574    assert_eq!(
1575      BinaryType::try_from(&BString::new(">".as_bytes().to_vec())),
1576      Ok(BinaryType::IsGreater)
1577    );
1578    assert_eq!(
1579      BinaryType::try_from(&BString::new("<=".as_bytes().to_vec())),
1580      Ok(BinaryType::IsLesserOrEqual)
1581    );
1582    assert_eq!(
1583      BinaryType::try_from(&BString::new(">=".as_bytes().to_vec())),
1584      Ok(BinaryType::IsGreaterOrEqual)
1585    );
1586    assert_eq!(
1587      BinaryType::try_from(&BString::new("<=>".as_bytes().to_vec())),
1588      Ok(BinaryType::Spaceship)
1589    );
1590    assert_eq!(
1591      BinaryType::try_from(&BString::new(".".as_bytes().to_vec())),
1592      Ok(BinaryType::Concatenation)
1593    );
1594    assert_eq!(
1595      BinaryType::try_from(&BString::new("&&".as_bytes().to_vec())),
1596      Ok(BinaryType::BooleanAnd)
1597    );
1598    assert_eq!(
1599      BinaryType::try_from(&BString::new("and".as_bytes().to_vec())),
1600      Ok(BinaryType::BooleanAnd)
1601    );
1602    assert_eq!(
1603      BinaryType::try_from(&BString::new("||".as_bytes().to_vec())),
1604      Ok(BinaryType::BooleanOr)
1605    );
1606    assert_eq!(
1607      BinaryType::try_from(&BString::new("or".as_bytes().to_vec())),
1608      Ok(BinaryType::BooleanOr)
1609    );
1610    assert_eq!(
1611      BinaryType::try_from(&BString::new("xor".as_bytes().to_vec())),
1612      Ok(BinaryType::BooleanXor)
1613    );
1614    assert_eq!(
1615      BinaryType::try_from(&BString::new("?:".as_bytes().to_vec())),
1616      Ok(BinaryType::Elvis)
1617    );
1618    assert_eq!(
1619      BinaryType::try_from(&BString::new("??".as_bytes().to_vec())),
1620      Ok(BinaryType::Coalesce)
1621    );
1622    assert_eq!(
1623      BinaryType::try_from(&BString::new("instanceof".as_bytes().to_vec())),
1624      Ok(BinaryType::InstanceOf)
1625    );
1626    assert!(BinaryType::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1627
1628    assert_eq!("+", format!("{}", BinaryType::Addition));
1629    assert_eq!("-", format!("{}", BinaryType::Subtraction));
1630    assert_eq!("*", format!("{}", BinaryType::Multiplication));
1631    assert_eq!("/", format!("{}", BinaryType::Division));
1632    assert_eq!("%", format!("{}", BinaryType::Modulus));
1633    assert_eq!("**", format!("{}", BinaryType::Exponentiation));
1634    assert_eq!("&", format!("{}", BinaryType::BitwiseAnd));
1635    assert_eq!("|", format!("{}", BinaryType::BitwiseOr));
1636    assert_eq!("^", format!("{}", BinaryType::BitwiseXor));
1637    assert_eq!("<<", format!("{}", BinaryType::BitwiseShiftLeft));
1638    assert_eq!(">>", format!("{}", BinaryType::BitwiseShiftRight));
1639    assert_eq!("==", format!("{}", BinaryType::IsEqual));
1640    assert_eq!("===", format!("{}", BinaryType::IsIdentical));
1641    assert_eq!("!=", format!("{}", BinaryType::IsNotEqual));
1642    assert_eq!("!==", format!("{}", BinaryType::IsNotIdentical));
1643    assert_eq!("<", format!("{}", BinaryType::IsLesser));
1644    assert_eq!(">", format!("{}", BinaryType::IsGreater));
1645    assert_eq!("<=", format!("{}", BinaryType::IsLesserOrEqual));
1646    assert_eq!(">=", format!("{}", BinaryType::IsGreaterOrEqual));
1647    assert_eq!("<=>", format!("{}", BinaryType::Spaceship));
1648    assert_eq!(".", format!("{}", BinaryType::Concatenation));
1649    assert_eq!("&&", format!("{}", BinaryType::BooleanAnd));
1650    assert_eq!("||", format!("{}", BinaryType::BooleanOr));
1651    assert_eq!("xor", format!("{}", BinaryType::BooleanXor));
1652    assert_eq!("?:", format!("{}", BinaryType::Elvis));
1653    assert_eq!("??", format!("{}", BinaryType::Coalesce));
1654    assert_eq!("instanceof", format!("{}", BinaryType::InstanceOf));
1655  }
1656
1657  #[test]
1658  fn assignment_type() {
1659    assert_eq!(
1660      AssignmentType::try_from(&BString::new("=".as_bytes().to_vec())),
1661      Ok(AssignmentType::Default)
1662    );
1663    assert_eq!(
1664      AssignmentType::try_from(&BString::new("=&".as_bytes().to_vec())),
1665      Ok(AssignmentType::Reference)
1666    );
1667    assert_eq!(
1668      AssignmentType::try_from(&BString::new("??=".as_bytes().to_vec())),
1669      Ok(AssignmentType::Coalesce)
1670    );
1671    assert_eq!(
1672      AssignmentType::try_from(&BString::new("**=".as_bytes().to_vec())),
1673      Ok(AssignmentType::Exponentiation)
1674    );
1675    assert_eq!(
1676      AssignmentType::try_from(&BString::new("*=".as_bytes().to_vec())),
1677      Ok(AssignmentType::Multiplication)
1678    );
1679    assert_eq!(
1680      AssignmentType::try_from(&BString::new("/=".as_bytes().to_vec())),
1681      Ok(AssignmentType::Division)
1682    );
1683    assert_eq!(
1684      AssignmentType::try_from(&BString::new("+=".as_bytes().to_vec())),
1685      Ok(AssignmentType::Addition)
1686    );
1687    assert_eq!(
1688      AssignmentType::try_from(&BString::new("-=".as_bytes().to_vec())),
1689      Ok(AssignmentType::Subtraction)
1690    );
1691    assert_eq!(
1692      AssignmentType::try_from(&BString::new("%=".as_bytes().to_vec())),
1693      Ok(AssignmentType::Modulus)
1694    );
1695    assert_eq!(
1696      AssignmentType::try_from(&BString::new("&=".as_bytes().to_vec())),
1697      Ok(AssignmentType::BitwiseAnd)
1698    );
1699    assert_eq!(
1700      AssignmentType::try_from(&BString::new("|=".as_bytes().to_vec())),
1701      Ok(AssignmentType::BitwiseOr)
1702    );
1703    assert_eq!(
1704      AssignmentType::try_from(&BString::new("^=".as_bytes().to_vec())),
1705      Ok(AssignmentType::BitwiseXor)
1706    );
1707    assert_eq!(
1708      AssignmentType::try_from(&BString::new(">>=".as_bytes().to_vec())),
1709      Ok(AssignmentType::BitwiseShiftRight)
1710    );
1711    assert_eq!(
1712      AssignmentType::try_from(&BString::new("<<=".as_bytes().to_vec())),
1713      Ok(AssignmentType::BitwiseShiftLeft)
1714    );
1715    assert!(AssignmentType::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1716
1717    assert_eq!("=", format!("{}", AssignmentType::Default));
1718    assert_eq!("=&", format!("{}", AssignmentType::Reference));
1719    assert_eq!("??=", format!("{}", AssignmentType::Coalesce));
1720    assert_eq!("**=", format!("{}", AssignmentType::Exponentiation));
1721    assert_eq!("*=", format!("{}", AssignmentType::Multiplication));
1722    assert_eq!("/=", format!("{}", AssignmentType::Division));
1723    assert_eq!("+=", format!("{}", AssignmentType::Addition));
1724    assert_eq!("-=", format!("{}", AssignmentType::Subtraction));
1725    assert_eq!("%=", format!("{}", AssignmentType::Modulus));
1726    assert_eq!("&=", format!("{}", AssignmentType::BitwiseAnd));
1727    assert_eq!("|=", format!("{}", AssignmentType::BitwiseOr));
1728    assert_eq!("^=", format!("{}", AssignmentType::BitwiseXor));
1729    assert_eq!(">>=", format!("{}", AssignmentType::BitwiseShiftRight));
1730    assert_eq!("<<=", format!("{}", AssignmentType::BitwiseShiftLeft));
1731  }
1732
1733  #[test]
1734  fn use_item_modifier() {
1735    assert_eq!(
1736      UseItemModifier::try_from(&BString::new("const".as_bytes().to_vec())),
1737      Ok(UseItemModifier::Const)
1738    );
1739    assert_eq!(
1740      UseItemModifier::try_from(&BString::new("function".as_bytes().to_vec())),
1741      Ok(UseItemModifier::Function)
1742    );
1743    assert!(UseItemModifier::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1744
1745    assert_eq!("const", format!("{}", UseItemModifier::Const));
1746    assert_eq!("function", format!("{}", UseItemModifier::Function));
1747  }
1748
1749  #[test]
1750  fn modifier() {
1751    assert_eq!(
1752      Modifier::try_from(&BString::new("static".as_bytes().to_vec())),
1753      Ok(Modifier::Static)
1754    );
1755    assert_eq!(
1756      Modifier::try_from(&BString::new("readonly".as_bytes().to_vec())),
1757      Ok(Modifier::Readonly)
1758    );
1759    assert!(Modifier::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1760
1761    assert_eq!("static", format!("{}", Modifier::Static));
1762    assert_eq!("readonly", format!("{}", Modifier::Readonly));
1763  }
1764
1765  #[test]
1766  fn quote() {
1767    assert_eq!(Quote::try_from(&BString::new("'".as_bytes().to_vec())), Ok(Quote::Single));
1768    assert_eq!(Quote::try_from(&BString::new("\"".as_bytes().to_vec())), Ok(Quote::Double));
1769    assert_eq!(Quote::try_from(&BString::new("`".as_bytes().to_vec())), Ok(Quote::Backtick));
1770    assert!(Quote::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1771
1772    assert_eq!("'", format!("{}", Quote::Single));
1773    assert_eq!("\"", format!("{}", Quote::Double));
1774    assert_eq!("`", format!("{}", Quote::Backtick));
1775  }
1776
1777  #[test]
1778  fn inheritance() {
1779    assert_eq!(
1780      Inheritance::try_from(&BString::new("abstract".as_bytes().to_vec())),
1781      Ok(Inheritance::Abstract)
1782    );
1783    assert_eq!(
1784      Inheritance::try_from(&BString::new("final".as_bytes().to_vec())),
1785      Ok(Inheritance::Final)
1786    );
1787    assert!(Inheritance::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1788
1789    assert_eq!("abstract", format!("{}", Inheritance::Abstract));
1790    assert_eq!("final", format!("{}", Inheritance::Final));
1791  }
1792
1793  #[test]
1794  fn visibility() {
1795    assert_eq!(
1796      Visibility::try_from(&BString::new("private".as_bytes().to_vec())),
1797      Ok(Visibility::Private)
1798    );
1799    assert_eq!(
1800      Visibility::try_from(&BString::new("private(get)".as_bytes().to_vec())),
1801      Ok(Visibility::PrivateGet)
1802    );
1803    assert_eq!(
1804      Visibility::try_from(&BString::new("private(set)".as_bytes().to_vec())),
1805      Ok(Visibility::PrivateSet)
1806    );
1807    assert_eq!(
1808      Visibility::try_from(&BString::new("protected".as_bytes().to_vec())),
1809      Ok(Visibility::Protected)
1810    );
1811    assert_eq!(
1812      Visibility::try_from(&BString::new("protected(get)".as_bytes().to_vec())),
1813      Ok(Visibility::ProtectedGet)
1814    );
1815    assert_eq!(
1816      Visibility::try_from(&BString::new("protected(set)".as_bytes().to_vec())),
1817      Ok(Visibility::ProtectedSet)
1818    );
1819    assert_eq!(
1820      Visibility::try_from(&BString::new("public".as_bytes().to_vec())),
1821      Ok(Visibility::Public)
1822    );
1823    assert_eq!(
1824      Visibility::try_from(&BString::new("public(get)".as_bytes().to_vec())),
1825      Ok(Visibility::PublicGet)
1826    );
1827    assert_eq!(
1828      Visibility::try_from(&BString::new("public(set)".as_bytes().to_vec())),
1829      Ok(Visibility::PublicSet)
1830    );
1831    assert!(Visibility::try_from(&BString::new("none".as_bytes().to_vec())).is_err());
1832
1833    assert_eq!("private", format!("{}", Visibility::Private));
1834    assert_eq!("private(get)", format!("{}", Visibility::PrivateGet));
1835    assert_eq!("private(set)", format!("{}", Visibility::PrivateSet));
1836    assert_eq!("protected", format!("{}", Visibility::Protected));
1837    assert_eq!("protected(get)", format!("{}", Visibility::ProtectedGet));
1838    assert_eq!("protected(set)", format!("{}", Visibility::ProtectedSet));
1839    assert_eq!("public", format!("{}", Visibility::Public));
1840    assert_eq!("public(get)", format!("{}", Visibility::PublicGet));
1841    assert_eq!("public(set)", format!("{}", Visibility::PublicSet));
1842  }
1843}