php_parser/ast/
mod.rs

1use crate::lexer::token::Token;
2use crate::span::{LineInfo, Span};
3use serde::Serialize;
4
5pub mod sexpr;
6pub mod visitor;
7
8pub type ExprId<'ast> = &'ast Expr<'ast>;
9pub type StmtId<'ast> = &'ast Stmt<'ast>;
10
11#[derive(Debug, Clone, Copy, Serialize)]
12pub struct ParseError {
13    pub span: Span,
14    pub message: &'static str,
15}
16
17impl ParseError {
18    pub fn to_human_readable(&self, source: &[u8]) -> String {
19        self.to_human_readable_with_path(source, None)
20    }
21
22    pub fn to_human_readable_with_path(&self, source: &[u8], path: Option<&str>) -> String {
23        let Some(LineInfo {
24            line,
25            column,
26            line_text,
27        }) = self.span.line_info(source)
28        else {
29            return format!("error: {}", self.message);
30        };
31
32        let line_str = String::from_utf8_lossy(line_text);
33        let gutter_width = line.to_string().len();
34        let padding = std::cmp::min(line_text.len(), column.saturating_sub(1));
35        let highlight_len = std::cmp::max(
36            1,
37            std::cmp::min(self.span.len(), line_text.len().saturating_sub(padding)),
38        );
39
40        let mut marker = String::new();
41        marker.push_str(&" ".repeat(padding));
42        marker.push_str(&"^".repeat(highlight_len));
43
44        let location = match path {
45            Some(path) => format!("{path}:{line}:{column}"),
46            None => format!("line {line}, column {column}"),
47        };
48
49        format!(
50            "error: {}\n --> {}\n{gutter}|\n{line_no:>width$} | {line_src}\n{gutter}| {marker}",
51            self.message,
52            location,
53            gutter = " ".repeat(gutter_width + 1),
54            line_no = line,
55            width = gutter_width,
56            line_src = line_str,
57            marker = marker,
58        )
59    }
60}
61
62#[derive(Debug, Serialize)]
63pub struct Program<'ast> {
64    pub statements: &'ast [StmtId<'ast>],
65    pub errors: &'ast [ParseError],
66    pub span: Span,
67}
68
69#[derive(Debug, Serialize)]
70pub enum Stmt<'ast> {
71    Echo {
72        exprs: &'ast [ExprId<'ast>],
73        span: Span,
74    },
75    Return {
76        expr: Option<ExprId<'ast>>,
77        span: Span,
78    },
79    If {
80        condition: ExprId<'ast>,
81        then_block: &'ast [StmtId<'ast>],
82        else_block: Option<&'ast [StmtId<'ast>]>, // Simplified: else block is just statements for now
83        span: Span,
84    },
85    While {
86        condition: ExprId<'ast>,
87        body: &'ast [StmtId<'ast>],
88        span: Span,
89    },
90    DoWhile {
91        body: &'ast [StmtId<'ast>],
92        condition: ExprId<'ast>,
93        span: Span,
94    },
95    For {
96        init: &'ast [ExprId<'ast>],
97        condition: &'ast [ExprId<'ast>], // Can be multiple expressions separated by comma, but usually one. PHP allows empty.
98        loop_expr: &'ast [ExprId<'ast>],
99        body: &'ast [StmtId<'ast>],
100        span: Span,
101    },
102    Foreach {
103        expr: ExprId<'ast>,
104        key_var: Option<ExprId<'ast>>,
105        value_var: ExprId<'ast>,
106        body: &'ast [StmtId<'ast>],
107        span: Span,
108    },
109    Block {
110        statements: &'ast [StmtId<'ast>],
111        span: Span,
112    },
113    Function {
114        attributes: &'ast [AttributeGroup<'ast>],
115        name: &'ast Token,
116        by_ref: bool,
117        params: &'ast [Param<'ast>],
118        return_type: Option<&'ast Type<'ast>>,
119        body: &'ast [StmtId<'ast>],
120        span: Span,
121    },
122    Class {
123        attributes: &'ast [AttributeGroup<'ast>],
124        modifiers: &'ast [Token],
125        name: &'ast Token,
126        extends: Option<Name<'ast>>,
127        implements: &'ast [Name<'ast>],
128        members: &'ast [ClassMember<'ast>],
129        span: Span,
130    },
131    Interface {
132        attributes: &'ast [AttributeGroup<'ast>],
133        name: &'ast Token,
134        extends: &'ast [Name<'ast>],
135        members: &'ast [ClassMember<'ast>],
136        span: Span,
137    },
138    Trait {
139        attributes: &'ast [AttributeGroup<'ast>],
140        name: &'ast Token,
141        members: &'ast [ClassMember<'ast>],
142        span: Span,
143    },
144    Enum {
145        attributes: &'ast [AttributeGroup<'ast>],
146        name: &'ast Token,
147        backed_type: Option<&'ast Type<'ast>>,
148        implements: &'ast [Name<'ast>],
149        members: &'ast [ClassMember<'ast>],
150        span: Span,
151    },
152    Namespace {
153        name: Option<Name<'ast>>,
154        body: Option<&'ast [StmtId<'ast>]>,
155        span: Span,
156    },
157    Use {
158        uses: &'ast [UseItem<'ast>],
159        kind: UseKind,
160        span: Span,
161    },
162    Switch {
163        condition: ExprId<'ast>,
164        cases: &'ast [Case<'ast>],
165        span: Span,
166    },
167    Try {
168        body: &'ast [StmtId<'ast>],
169        catches: &'ast [Catch<'ast>],
170        finally: Option<&'ast [StmtId<'ast>]>,
171        span: Span,
172    },
173    Throw {
174        expr: ExprId<'ast>,
175        span: Span,
176    },
177    Const {
178        attributes: &'ast [AttributeGroup<'ast>],
179        consts: &'ast [ClassConst<'ast>],
180        span: Span,
181    },
182    Break {
183        level: Option<ExprId<'ast>>,
184        span: Span,
185    },
186    Continue {
187        level: Option<ExprId<'ast>>,
188        span: Span,
189    },
190    Global {
191        vars: &'ast [ExprId<'ast>],
192        span: Span,
193    },
194    Static {
195        vars: &'ast [StaticVar<'ast>],
196        span: Span,
197    },
198    Unset {
199        vars: &'ast [ExprId<'ast>],
200        span: Span,
201    },
202    Expression {
203        expr: ExprId<'ast>,
204        span: Span,
205    },
206    InlineHtml {
207        value: &'ast [u8],
208        span: Span,
209    },
210    Nop {
211        span: Span,
212    },
213    Label {
214        name: &'ast Token,
215        span: Span,
216    },
217    Goto {
218        label: &'ast Token,
219        span: Span,
220    },
221    Error {
222        span: Span,
223    },
224    Declare {
225        declares: &'ast [DeclareItem<'ast>],
226        body: &'ast [StmtId<'ast>],
227        span: Span,
228    },
229    HaltCompiler {
230        span: Span,
231    },
232}
233
234#[derive(Debug, Clone, Copy, Serialize)]
235pub struct StaticVar<'ast> {
236    pub var: ExprId<'ast>,
237    pub default: Option<ExprId<'ast>>,
238    pub span: Span,
239}
240
241#[derive(Debug, Clone, Copy, Serialize)]
242pub struct Param<'ast> {
243    pub attributes: &'ast [AttributeGroup<'ast>],
244    pub modifiers: &'ast [Token],
245    pub name: &'ast Token,
246    pub ty: Option<&'ast Type<'ast>>,
247    pub default: Option<ExprId<'ast>>,
248    pub by_ref: bool,
249    pub variadic: bool,
250    pub hooks: Option<&'ast [PropertyHook<'ast>]>,
251    pub span: Span,
252}
253
254#[derive(Debug, Serialize)]
255pub enum Expr<'ast> {
256    Assign {
257        var: ExprId<'ast>,
258        expr: ExprId<'ast>,
259        span: Span,
260    },
261    AssignRef {
262        var: ExprId<'ast>,
263        expr: ExprId<'ast>,
264        span: Span,
265    },
266    AssignOp {
267        var: ExprId<'ast>,
268        op: AssignOp,
269        expr: ExprId<'ast>,
270        span: Span,
271    },
272    Binary {
273        left: ExprId<'ast>,
274        op: BinaryOp,
275        right: ExprId<'ast>,
276        span: Span,
277    },
278    Unary {
279        op: UnaryOp,
280        expr: ExprId<'ast>,
281        span: Span,
282    },
283    Call {
284        func: ExprId<'ast>,
285        args: &'ast [Arg<'ast>],
286        span: Span,
287    },
288    Array {
289        items: &'ast [ArrayItem<'ast>],
290        span: Span,
291    },
292    ArrayDimFetch {
293        array: ExprId<'ast>,
294        dim: Option<ExprId<'ast>>, // None for $a[]
295        span: Span,
296    },
297    PropertyFetch {
298        target: ExprId<'ast>,
299        property: ExprId<'ast>, // Usually Identifier or Variable
300        span: Span,
301    },
302    MethodCall {
303        target: ExprId<'ast>,
304        method: ExprId<'ast>,
305        args: &'ast [Arg<'ast>],
306        span: Span,
307    },
308    StaticCall {
309        class: ExprId<'ast>,
310        method: ExprId<'ast>,
311        args: &'ast [Arg<'ast>],
312        span: Span,
313    },
314    ClassConstFetch {
315        class: ExprId<'ast>,
316        constant: ExprId<'ast>,
317        span: Span,
318    },
319    New {
320        class: ExprId<'ast>,
321        args: &'ast [Arg<'ast>],
322        span: Span,
323    },
324    Variable {
325        name: Span,
326        span: Span,
327    },
328    Integer {
329        value: &'ast [u8],
330        span: Span,
331    },
332    Float {
333        value: &'ast [u8],
334        span: Span,
335    },
336    Boolean {
337        value: bool,
338        span: Span,
339    },
340    Null {
341        span: Span,
342    },
343    String {
344        value: &'ast [u8],
345        span: Span,
346    },
347    InterpolatedString {
348        parts: &'ast [ExprId<'ast>],
349        span: Span,
350    },
351    ShellExec {
352        parts: &'ast [ExprId<'ast>],
353        span: Span,
354    },
355    Include {
356        kind: IncludeKind,
357        expr: ExprId<'ast>,
358        span: Span,
359    },
360    MagicConst {
361        kind: MagicConstKind,
362        span: Span,
363    },
364    PostInc {
365        var: ExprId<'ast>,
366        span: Span,
367    },
368    PostDec {
369        var: ExprId<'ast>,
370        span: Span,
371    },
372    Ternary {
373        condition: ExprId<'ast>,
374        if_true: Option<ExprId<'ast>>,
375        if_false: ExprId<'ast>,
376        span: Span,
377    },
378    Match {
379        condition: ExprId<'ast>,
380        arms: &'ast [MatchArm<'ast>],
381        span: Span,
382    },
383    AnonymousClass {
384        attributes: &'ast [AttributeGroup<'ast>],
385        modifiers: &'ast [Token],
386        args: &'ast [Arg<'ast>],
387        extends: Option<Name<'ast>>,
388        implements: &'ast [Name<'ast>],
389        members: &'ast [ClassMember<'ast>],
390        span: Span,
391    },
392    Print {
393        expr: ExprId<'ast>,
394        span: Span,
395    },
396    Yield {
397        key: Option<ExprId<'ast>>,
398        value: Option<ExprId<'ast>>,
399        from: bool,
400        span: Span,
401    },
402    Cast {
403        kind: CastKind,
404        expr: ExprId<'ast>,
405        span: Span,
406    },
407    Empty {
408        expr: ExprId<'ast>,
409        span: Span,
410    },
411    Isset {
412        vars: &'ast [ExprId<'ast>],
413        span: Span,
414    },
415    Eval {
416        expr: ExprId<'ast>,
417        span: Span,
418    },
419    Die {
420        expr: Option<ExprId<'ast>>,
421        span: Span,
422    },
423    Exit {
424        expr: Option<ExprId<'ast>>,
425        span: Span,
426    },
427    Closure {
428        attributes: &'ast [AttributeGroup<'ast>],
429        is_static: bool,
430        by_ref: bool,
431        params: &'ast [Param<'ast>],
432        uses: &'ast [ClosureUse<'ast>],
433        return_type: Option<&'ast Type<'ast>>,
434        body: &'ast [StmtId<'ast>],
435        span: Span,
436    },
437    ArrowFunction {
438        attributes: &'ast [AttributeGroup<'ast>],
439        is_static: bool,
440        by_ref: bool,
441        params: &'ast [Param<'ast>],
442        return_type: Option<&'ast Type<'ast>>,
443        expr: ExprId<'ast>,
444        span: Span,
445    },
446    Clone {
447        expr: ExprId<'ast>,
448        span: Span,
449    },
450    NullsafePropertyFetch {
451        target: ExprId<'ast>,
452        property: ExprId<'ast>,
453        span: Span,
454    },
455    NullsafeMethodCall {
456        target: ExprId<'ast>,
457        method: ExprId<'ast>,
458        args: &'ast [Arg<'ast>],
459        span: Span,
460    },
461    VariadicPlaceholder {
462        span: Span,
463    },
464    Error {
465        span: Span,
466    },
467}
468
469#[derive(Debug, Clone, Copy, Serialize)]
470pub struct ClosureUse<'ast> {
471    pub var: &'ast Token,
472    pub by_ref: bool,
473    pub span: Span,
474}
475
476#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
477pub enum CastKind {
478    Int,
479    Bool,
480    Float,
481    String,
482    Array,
483    Object,
484    Unset,
485    Void,
486}
487
488#[derive(Debug, Clone, Copy, Serialize)]
489pub struct MatchArm<'ast> {
490    pub conditions: Option<&'ast [ExprId<'ast>]>, // None for default
491    pub body: ExprId<'ast>,
492    pub span: Span,
493}
494
495#[derive(Debug, Clone, Copy, Serialize)]
496pub struct AnonymousClass<'ast> {
497    pub args: &'ast [Arg<'ast>],
498    pub extends: Option<Name<'ast>>,
499    pub implements: &'ast [Name<'ast>],
500    pub members: &'ast [ClassMember<'ast>],
501    pub span: Span,
502}
503
504#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
505pub enum UnaryOp {
506    Plus,
507    Minus,
508    Not,
509    BitNot,
510    PreInc,
511    PreDec,
512    ErrorSuppress,
513    Reference,
514}
515
516impl<'ast> Expr<'ast> {
517    pub fn span(&self) -> Span {
518        match self {
519            Expr::Assign { span, .. } => *span,
520            Expr::AssignRef { span, .. } => *span,
521            Expr::AssignOp { span, .. } => *span,
522            Expr::Binary { span, .. } => *span,
523            Expr::Unary { span, .. } => *span,
524            Expr::Call { span, .. } => *span,
525            Expr::Array { span, .. } => *span,
526            Expr::ArrayDimFetch { span, .. } => *span,
527            Expr::PropertyFetch { span, .. } => *span,
528            Expr::MethodCall { span, .. } => *span,
529            Expr::StaticCall { span, .. } => *span,
530            Expr::ClassConstFetch { span, .. } => *span,
531            Expr::New { span, .. } => *span,
532            Expr::Variable { span, .. } => *span,
533            Expr::Integer { span, .. } => *span,
534            Expr::Float { span, .. } => *span,
535            Expr::Boolean { span, .. } => *span,
536            Expr::Null { span, .. } => *span,
537            Expr::String { span, .. } => *span,
538            Expr::InterpolatedString { span, .. } => *span,
539            Expr::ShellExec { span, .. } => *span,
540            Expr::Include { span, .. } => *span,
541            Expr::MagicConst { span, .. } => *span,
542            Expr::PostInc { span, .. } => *span,
543            Expr::PostDec { span, .. } => *span,
544            Expr::Ternary { span, .. } => *span,
545            Expr::Match { span, .. } => *span,
546            Expr::AnonymousClass { span, .. } => *span,
547            Expr::Yield { span, .. } => *span,
548            Expr::Cast { span, .. } => *span,
549            Expr::Empty { span, .. } => *span,
550            Expr::Isset { span, .. } => *span,
551            Expr::Eval { span, .. } => *span,
552            Expr::Die { span, .. } => *span,
553            Expr::Exit { span, .. } => *span,
554            Expr::Closure { span, .. } => *span,
555            Expr::ArrowFunction { span, .. } => *span,
556            Expr::Clone { span, .. } => *span,
557            Expr::Print { span, .. } => *span,
558            Expr::NullsafePropertyFetch { span, .. } => *span,
559            Expr::NullsafeMethodCall { span, .. } => *span,
560            Expr::VariadicPlaceholder { span } => *span,
561            Expr::Error { span } => *span,
562        }
563    }
564}
565
566impl<'ast> Stmt<'ast> {
567    pub fn span(&self) -> Span {
568        match self {
569            Stmt::Echo { span, .. } => *span,
570            Stmt::Return { span, .. } => *span,
571            Stmt::If { span, .. } => *span,
572            Stmt::While { span, .. } => *span,
573            Stmt::DoWhile { span, .. } => *span,
574            Stmt::For { span, .. } => *span,
575            Stmt::Foreach { span, .. } => *span,
576            Stmt::Block { span, .. } => *span,
577            Stmt::Function { span, .. } => *span,
578            Stmt::Class { span, .. } => *span,
579            Stmt::Interface { span, .. } => *span,
580            Stmt::Trait { span, .. } => *span,
581            Stmt::Enum { span, .. } => *span,
582            Stmt::Namespace { span, .. } => *span,
583            Stmt::Use { span, .. } => *span,
584            Stmt::Switch { span, .. } => *span,
585            Stmt::Try { span, .. } => *span,
586            Stmt::Throw { span, .. } => *span,
587            Stmt::Const { span, .. } => *span,
588            Stmt::Break { span, .. } => *span,
589            Stmt::Continue { span, .. } => *span,
590            Stmt::Global { span, .. } => *span,
591            Stmt::Static { span, .. } => *span,
592            Stmt::Unset { span, .. } => *span,
593            Stmt::Expression { span, .. } => *span,
594            Stmt::InlineHtml { span, .. } => *span,
595            Stmt::Declare { span, .. } => *span,
596            Stmt::HaltCompiler { span } => *span,
597            Stmt::Label { span, .. } => *span,
598            Stmt::Goto { span, .. } => *span,
599            Stmt::Error { span } => *span,
600            Stmt::Nop { span } => *span,
601        }
602    }
603}
604
605#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
606pub enum BinaryOp {
607    Plus,
608    Minus,
609    Mul,
610    Div,
611    Mod,
612    Concat, // .
613    Eq,
614    EqEq,
615    EqEqEq,
616    NotEq,
617    NotEqEq,
618    Lt,
619    LtEq,
620    Gt,
621    GtEq,
622    And,
623    Or,
624    BitAnd,
625    BitOr,
626    BitXor,
627    Coalesce,
628    Spaceship,
629    Pow,
630    ShiftLeft,
631    ShiftRight,
632    LogicalAnd,
633    LogicalOr,
634    LogicalXor,
635    Instanceof,
636}
637
638#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
639pub enum AssignOp {
640    Plus,       // +=
641    Minus,      // -=
642    Mul,        // *=
643    Div,        // /=
644    Mod,        // %=
645    Concat,     // .=
646    BitAnd,     // &=
647    BitOr,      // |=
648    BitXor,     // ^=
649    ShiftLeft,  // <<=
650    ShiftRight, // >>=
651    Pow,        // **=
652    Coalesce,   // ??=
653}
654
655#[derive(Debug, Clone, Copy, Serialize)]
656pub struct Arg<'ast> {
657    pub name: Option<&'ast Token>,
658    pub value: ExprId<'ast>,
659    pub unpack: bool,
660    pub span: Span,
661}
662
663#[derive(Debug, Clone, Copy, Serialize)]
664pub struct ArrayItem<'ast> {
665    pub key: Option<ExprId<'ast>>,
666    pub value: ExprId<'ast>,
667    pub by_ref: bool,
668    pub unpack: bool,
669    pub span: Span,
670}
671
672#[derive(Debug, Clone, Copy, Serialize)]
673pub struct PropertyEntry<'ast> {
674    pub name: &'ast Token,
675    pub default: Option<ExprId<'ast>>,
676    pub span: Span,
677}
678
679#[derive(Debug, Clone, Copy, Serialize)]
680pub enum ClassMember<'ast> {
681    Property {
682        attributes: &'ast [AttributeGroup<'ast>],
683        modifiers: &'ast [Token],
684        ty: Option<&'ast Type<'ast>>,
685        entries: &'ast [PropertyEntry<'ast>],
686        span: Span,
687    },
688    PropertyHook {
689        attributes: &'ast [AttributeGroup<'ast>],
690        modifiers: &'ast [Token],
691        ty: Option<&'ast Type<'ast>>,
692        name: &'ast Token,
693        default: Option<ExprId<'ast>>,
694        hooks: &'ast [PropertyHook<'ast>],
695        span: Span,
696    },
697    Method {
698        attributes: &'ast [AttributeGroup<'ast>],
699        modifiers: &'ast [Token],
700        name: &'ast Token,
701        params: &'ast [Param<'ast>],
702        return_type: Option<&'ast Type<'ast>>,
703        body: &'ast [StmtId<'ast>],
704        span: Span,
705    },
706    Const {
707        attributes: &'ast [AttributeGroup<'ast>],
708        modifiers: &'ast [Token],
709        ty: Option<&'ast Type<'ast>>,
710        consts: &'ast [ClassConst<'ast>],
711        span: Span,
712    },
713    TraitUse {
714        attributes: &'ast [AttributeGroup<'ast>],
715        traits: &'ast [Name<'ast>],
716        adaptations: &'ast [TraitAdaptation<'ast>],
717        span: Span,
718    },
719    Case {
720        attributes: &'ast [AttributeGroup<'ast>],
721        name: &'ast Token,
722        value: Option<ExprId<'ast>>,
723        span: Span,
724    },
725}
726
727#[derive(Debug, Clone, Copy, Serialize)]
728pub struct Case<'ast> {
729    pub condition: Option<ExprId<'ast>>, // None for default
730    pub body: &'ast [StmtId<'ast>],
731    pub span: Span,
732}
733
734#[derive(Debug, Clone, Copy, Serialize)]
735pub struct ClassConst<'ast> {
736    pub name: &'ast Token,
737    pub value: ExprId<'ast>,
738    pub span: Span,
739}
740
741#[derive(Debug, Clone, Copy, Serialize)]
742pub enum PropertyHookBody<'ast> {
743    None,
744    Statements(&'ast [StmtId<'ast>]),
745    Expr(ExprId<'ast>),
746}
747
748#[derive(Debug, Clone, Copy, Serialize)]
749pub struct PropertyHook<'ast> {
750    pub attributes: &'ast [AttributeGroup<'ast>],
751    pub modifiers: &'ast [Token],
752    pub name: &'ast Token,
753    pub params: &'ast [Param<'ast>],
754    pub by_ref: bool,
755    pub body: PropertyHookBody<'ast>,
756    pub span: Span,
757}
758
759#[derive(Debug, Clone, Copy, Serialize)]
760pub struct TraitMethodRef<'ast> {
761    pub trait_name: Option<Name<'ast>>,
762    pub method: &'ast Token,
763    pub span: Span,
764}
765
766#[derive(Debug, Clone, Copy, Serialize)]
767pub enum TraitAdaptation<'ast> {
768    Precedence {
769        method: TraitMethodRef<'ast>,
770        insteadof: &'ast [Name<'ast>],
771        span: Span,
772    },
773    Alias {
774        method: TraitMethodRef<'ast>,
775        alias: Option<&'ast Token>,
776        visibility: Option<&'ast Token>,
777        span: Span,
778    },
779}
780
781#[derive(Debug, Clone, Copy, Serialize)]
782pub struct Catch<'ast> {
783    pub types: &'ast [Name<'ast>], // Multi-catch: TryCatch|Exception
784    pub var: Option<&'ast Token>,  // Variable may be omitted in PHP 8+
785    pub body: &'ast [StmtId<'ast>],
786    pub span: Span,
787}
788
789#[derive(Debug, Clone, Copy, Serialize)]
790pub struct Name<'ast> {
791    pub parts: &'ast [Token],
792    pub span: Span,
793}
794
795#[derive(Debug, Clone, Copy, Serialize)]
796pub struct UseItem<'ast> {
797    pub name: Name<'ast>,
798    pub alias: Option<&'ast Token>,
799    pub kind: UseKind,
800    pub span: Span,
801}
802
803#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
804pub enum UseKind {
805    Normal,
806    Function,
807    Const,
808}
809
810#[derive(Debug, Clone, Copy, Serialize)]
811pub struct Attribute<'ast> {
812    pub name: Name<'ast>,
813    pub args: &'ast [Arg<'ast>],
814    pub span: Span,
815}
816
817#[derive(Debug, Clone, Copy, Serialize)]
818pub struct AttributeGroup<'ast> {
819    pub attributes: &'ast [Attribute<'ast>],
820    pub span: Span,
821}
822
823#[derive(Debug, Clone, Copy, Serialize)]
824pub enum Type<'ast> {
825    Simple(&'ast Token),
826    Name(Name<'ast>),
827    Union(&'ast [Type<'ast>]),
828    Intersection(&'ast [Type<'ast>]),
829    Nullable(&'ast Type<'ast>),
830}
831
832#[derive(Debug, Clone, Copy, Serialize)]
833pub struct DeclareItem<'ast> {
834    pub key: &'ast Token,
835    pub value: ExprId<'ast>,
836    pub span: Span,
837}
838
839#[derive(Debug, Clone, Copy, Serialize)]
840pub enum IncludeKind {
841    Include,
842    IncludeOnce,
843    Require,
844    RequireOnce,
845}
846
847#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
848pub enum MagicConstKind {
849    Dir,
850    File,
851    Line,
852    Function,
853    Class,
854    Trait,
855    Method,
856    Namespace,
857    Property,
858}