Skip to main content

flowjs_parser/
ast.rs

1//! Typed representation of the Flow parser AST.
2//!
3//! Comprehensive coverage of all Flow type system nodes. Unrecognized nodes
4//! deserialize as `Other` via `#[serde(other)]` for forward compatibility.
5//!
6//! Reference: https://github.com/facebook/flow/blob/main/src/parser/estree_translator.ml
7
8use serde::Deserialize;
9
10// ── Program ─────────────────────────────────────────────────────────────
11
12/// Root AST node returned by the Flow parser.
13#[derive(Debug, Clone, Deserialize)]
14pub struct Program {
15    pub body: Vec<Statement>,
16    #[serde(default)]
17    pub errors: Vec<ParseError>,
18}
19
20/// A parse error reported by the Flow parser.
21#[derive(Debug, Clone, Deserialize)]
22pub struct ParseError {
23    pub message: String,
24    pub loc: Option<SourceLocation>,
25}
26
27/// Source location attached to a parse error.
28#[derive(Debug, Clone, Deserialize)]
29pub struct SourceLocation {
30    pub start: Position,
31    pub end: Position,
32}
33
34/// Line and column (both 1-based for line, 0-based for column, matching Flow convention).
35#[derive(Debug, Clone, Deserialize)]
36pub struct Position {
37    pub line: u32,
38    pub column: u32,
39}
40
41// ── Statements ──────────────────────────────────────────────────────────
42
43/// Top-level statement in a Flow program.
44#[derive(Debug, Clone, Deserialize)]
45#[serde(tag = "type")]
46pub enum Statement {
47    ExportNamedDeclaration {
48        declaration: Option<Declaration>,
49    },
50    DeclareExportDeclaration {
51        declaration: Option<Declaration>,
52    },
53    ExportDefaultDeclaration {
54        #[serde(default)]
55        declaration: Option<serde_json::Value>,
56    },
57    EnumDeclaration {
58        id: Identifier,
59        body: EnumBody,
60    },
61    ImportDeclaration {
62        #[serde(default)]
63        source: Option<serde_json::Value>,
64        #[serde(default)]
65        specifiers: Vec<serde_json::Value>,
66        #[serde(rename = "importKind", default)]
67        import_kind: Option<String>,
68    },
69    DeclareModuleExports {
70        #[serde(rename = "typeAnnotation")]
71        type_annotation: Box<TypeAnnotation>,
72    },
73    /// Catch-all for statement types we don't inspect.
74    #[serde(other)]
75    Other,
76}
77
78// ── Declarations ────────────────────────────────────────────────────────
79
80/// A type-level declaration inside an export statement.
81#[derive(Debug, Clone, Deserialize)]
82#[serde(tag = "type")]
83pub enum Declaration {
84    TypeAlias {
85        id: Identifier,
86        right: TypeAnnotation,
87    },
88    OpaqueType {
89        id: Identifier,
90        supertype: Option<TypeAnnotation>,
91    },
92    DeclareOpaqueType {
93        id: Identifier,
94        supertype: Option<TypeAnnotation>,
95    },
96    EnumDeclaration {
97        id: Identifier,
98        body: EnumBody,
99    },
100    InterfaceDeclaration {
101        id: Identifier,
102        #[serde(default)]
103        extends: Vec<InterfaceExtends>,
104        body: TypeAnnotation,
105    },
106    DeclareTypeAlias {
107        id: Identifier,
108        right: TypeAnnotation,
109    },
110    DeclareClass {
111        id: Identifier,
112    },
113    DeclareFunction {
114        id: Identifier,
115    },
116    DeclareVariable {
117        id: Identifier,
118    },
119    DeclareModule {
120        #[serde(default)]
121        id: serde_json::Value,
122        #[serde(default)]
123        body: serde_json::Value,
124    },
125    #[serde(other)]
126    Other,
127}
128
129// ── Type annotations ────────────────────────────────────────────────────
130
131/// A Flow type annotation node.
132#[derive(Debug, Clone, Deserialize)]
133#[serde(tag = "type")]
134pub enum TypeAnnotation {
135    // Primitives
136    StringTypeAnnotation,
137    NumberTypeAnnotation,
138    BooleanTypeAnnotation,
139    VoidTypeAnnotation,
140    MixedTypeAnnotation,
141    AnyTypeAnnotation,
142    EmptyTypeAnnotation,
143    NullLiteralTypeAnnotation,
144    BigIntTypeAnnotation,
145    SymbolTypeAnnotation,
146
147    // Literals
148    StringLiteralTypeAnnotation {
149        value: String,
150    },
151    NumberLiteralTypeAnnotation {
152        value: f64,
153    },
154    BooleanLiteralTypeAnnotation {
155        value: bool,
156    },
157    BigIntLiteralTypeAnnotation {
158        #[serde(default)]
159        value: Option<serde_json::Value>,
160    },
161
162    // Nullable (?T)
163    NullableTypeAnnotation {
164        #[serde(rename = "typeAnnotation")]
165        type_annotation: Box<TypeAnnotation>,
166    },
167
168    // Object ({| +key: T |})
169    ObjectTypeAnnotation {
170        #[serde(default)]
171        properties: Vec<ObjectMember>,
172        #[serde(default)]
173        indexers: Vec<ObjectTypeIndexer>,
174        #[serde(rename = "callProperties", default)]
175        call_properties: Vec<ObjectTypeCallProperty>,
176        #[serde(rename = "internalSlots", default)]
177        internal_slots: Vec<ObjectTypeInternalSlot>,
178        #[serde(default)]
179        exact: bool,
180    },
181
182    // Union (A | B)
183    UnionTypeAnnotation {
184        types: Vec<TypeAnnotation>,
185    },
186
187    // Intersection (A & B)
188    IntersectionTypeAnnotation {
189        types: Vec<TypeAnnotation>,
190    },
191
192    // Named type reference (Foo, $ReadOnlyArray<T>, React.Node)
193    GenericTypeAnnotation {
194        id: TypeIdentifier,
195        #[serde(rename = "typeParameters")]
196        type_parameters: Option<TypeParameterInstantiation>,
197    },
198
199    // Tuple ([A, B, C])
200    TupleTypeAnnotation {
201        #[serde(alias = "types", default)]
202        #[serde(rename = "elementTypes")]
203        element_types: Vec<TypeAnnotation>,
204    },
205
206    // Array (T[])
207    ArrayTypeAnnotation {
208        #[serde(rename = "elementType")]
209        element_type: Box<TypeAnnotation>,
210    },
211
212    // typeof T
213    TypeofTypeAnnotation {
214        argument: Box<TypeAnnotation>,
215    },
216
217    // Function type ((x: A) => B)
218    FunctionTypeAnnotation {
219        #[serde(default)]
220        params: Vec<FunctionTypeParam>,
221        #[serde(rename = "returnType")]
222        return_type: Box<TypeAnnotation>,
223        #[serde(default)]
224        rest: Option<Box<FunctionTypeParam>>,
225        #[serde(rename = "typeParameters", default)]
226        type_parameters: Option<TypeParameterDeclaration>,
227        #[serde(rename = "this", default)]
228        this_constraint: Option<Box<FunctionTypeParam>>,
229    },
230
231    // Interface type (inline anonymous interface)
232    InterfaceTypeAnnotation {
233        #[serde(default)]
234        extends: Vec<InterfaceExtends>,
235        body: Box<TypeAnnotation>,
236    },
237
238    // Existential type (*)
239    ExistsTypeAnnotation,
240
241    // Indexed access (Obj['key'])
242    IndexedAccessType {
243        #[serde(rename = "objectType")]
244        object_type: Box<TypeAnnotation>,
245        #[serde(rename = "indexType")]
246        index_type: Box<TypeAnnotation>,
247    },
248
249    // Optional indexed access (Obj?.['key'])
250    OptionalIndexedAccessType {
251        #[serde(rename = "objectType")]
252        object_type: Box<TypeAnnotation>,
253        #[serde(rename = "indexType")]
254        index_type: Box<TypeAnnotation>,
255        #[serde(default)]
256        optional: bool,
257    },
258
259    // keyof T
260    KeyofTypeAnnotation {
261        argument: Box<TypeAnnotation>,
262    },
263
264    // Conditional type (A extends B ? C : D)
265    ConditionalTypeAnnotation {
266        #[serde(rename = "checkType")]
267        check_type: Box<TypeAnnotation>,
268        #[serde(rename = "extendsType")]
269        extends_type: Box<TypeAnnotation>,
270        #[serde(rename = "trueType")]
271        true_type: Box<TypeAnnotation>,
272        #[serde(rename = "falseType")]
273        false_type: Box<TypeAnnotation>,
274    },
275
276    // infer T
277    InferTypeAnnotation {
278        #[serde(rename = "typeParameter", default)]
279        type_parameter: Option<serde_json::Value>,
280    },
281
282    // Type operator (renders, renders?, renders*)
283    TypeOperator {
284        #[serde(default)]
285        operator: Option<String>,
286        #[serde(rename = "typeAnnotation")]
287        type_annotation: Box<TypeAnnotation>,
288    },
289
290    // Component type
291    ComponentTypeAnnotation {
292        #[serde(default)]
293        params: Vec<serde_json::Value>,
294        #[serde(default)]
295        rest: Option<serde_json::Value>,
296        #[serde(rename = "typeParameters", default)]
297        type_parameters: Option<TypeParameterDeclaration>,
298        #[serde(rename = "rendersType", default)]
299        renders_type: Option<Box<TypeAnnotation>>,
300    },
301
302    #[serde(other)]
303    Other,
304}
305
306impl TypeAnnotation {
307    /// Short type tag for assertions (e.g. `"StringTypeAnnotation"`).
308    pub fn type_name(&self) -> &'static str {
309        match self {
310            Self::StringTypeAnnotation => "StringTypeAnnotation",
311            Self::NumberTypeAnnotation => "NumberTypeAnnotation",
312            Self::BooleanTypeAnnotation => "BooleanTypeAnnotation",
313            Self::VoidTypeAnnotation => "VoidTypeAnnotation",
314            Self::MixedTypeAnnotation => "MixedTypeAnnotation",
315            Self::AnyTypeAnnotation => "AnyTypeAnnotation",
316            Self::EmptyTypeAnnotation => "EmptyTypeAnnotation",
317            Self::NullLiteralTypeAnnotation => "NullLiteralTypeAnnotation",
318            Self::BigIntTypeAnnotation => "BigIntTypeAnnotation",
319            Self::SymbolTypeAnnotation => "SymbolTypeAnnotation",
320            Self::StringLiteralTypeAnnotation { .. } => "StringLiteralTypeAnnotation",
321            Self::NumberLiteralTypeAnnotation { .. } => "NumberLiteralTypeAnnotation",
322            Self::BooleanLiteralTypeAnnotation { .. } => "BooleanLiteralTypeAnnotation",
323            Self::BigIntLiteralTypeAnnotation { .. } => "BigIntLiteralTypeAnnotation",
324            Self::NullableTypeAnnotation { .. } => "NullableTypeAnnotation",
325            Self::ObjectTypeAnnotation { .. } => "ObjectTypeAnnotation",
326            Self::UnionTypeAnnotation { .. } => "UnionTypeAnnotation",
327            Self::IntersectionTypeAnnotation { .. } => "IntersectionTypeAnnotation",
328            Self::GenericTypeAnnotation { .. } => "GenericTypeAnnotation",
329            Self::TupleTypeAnnotation { .. } => "TupleTypeAnnotation",
330            Self::ArrayTypeAnnotation { .. } => "ArrayTypeAnnotation",
331            Self::TypeofTypeAnnotation { .. } => "TypeofTypeAnnotation",
332            Self::FunctionTypeAnnotation { .. } => "FunctionTypeAnnotation",
333            Self::InterfaceTypeAnnotation { .. } => "InterfaceTypeAnnotation",
334            Self::ExistsTypeAnnotation => "ExistsTypeAnnotation",
335            Self::IndexedAccessType { .. } => "IndexedAccessType",
336            Self::OptionalIndexedAccessType { .. } => "OptionalIndexedAccessType",
337            Self::KeyofTypeAnnotation { .. } => "KeyofTypeAnnotation",
338            Self::ConditionalTypeAnnotation { .. } => "ConditionalTypeAnnotation",
339            Self::InferTypeAnnotation { .. } => "InferTypeAnnotation",
340            Self::TypeOperator { .. } => "TypeOperator",
341            Self::ComponentTypeAnnotation { .. } => "ComponentTypeAnnotation",
342            Self::Other => "Other",
343        }
344    }
345}
346
347// ── Object type members ─────────────────────────────────────────────────
348
349/// A member of an object type annotation.
350#[derive(Debug, Clone, Deserialize)]
351#[serde(tag = "type")]
352pub enum ObjectMember {
353    ObjectTypeProperty {
354        key: PropertyKey,
355        value: TypeAnnotation,
356        variance: Option<Variance>,
357        #[serde(default)]
358        optional: bool,
359    },
360    ObjectTypeSpreadProperty {
361        argument: TypeAnnotation,
362    },
363    #[serde(other)]
364    Other,
365}
366
367/// An indexer on an object type (`[key: K]: V`).
368#[derive(Debug, Clone, Deserialize)]
369pub struct ObjectTypeIndexer {
370    pub key: TypeAnnotation,
371    pub value: TypeAnnotation,
372}
373
374/// A call property on an object type (`{ (x: number): string }`).
375#[derive(Debug, Clone, Deserialize)]
376pub struct ObjectTypeCallProperty {
377    pub value: TypeAnnotation,
378    #[serde(rename = "static", default)]
379    pub is_static: bool,
380}
381
382/// An internal slot on an object type (`{ [[call]](x: number): string }`).
383#[derive(Debug, Clone, Deserialize)]
384pub struct ObjectTypeInternalSlot {
385    pub id: Identifier,
386    pub value: TypeAnnotation,
387    #[serde(default)]
388    pub optional: bool,
389    #[serde(rename = "static", default)]
390    pub is_static: bool,
391    #[serde(default)]
392    pub method: bool,
393}
394
395// ── Function type param ─────────────────────────────────────────────────
396
397/// A parameter in a function type annotation.
398#[derive(Debug, Clone, Deserialize)]
399pub struct FunctionTypeParam {
400    #[serde(default)]
401    pub name: Option<Identifier>,
402    #[serde(rename = "typeAnnotation")]
403    pub type_annotation: TypeAnnotation,
404    #[serde(default)]
405    pub optional: bool,
406}
407
408// ── Interface extends ───────────────────────────────────────────────────
409
410/// An `extends` clause in an interface declaration or type.
411#[derive(Debug, Clone, Deserialize)]
412pub struct InterfaceExtends {
413    pub id: Identifier,
414    #[serde(rename = "typeParameters", default)]
415    pub type_parameters: Option<TypeParameterInstantiation>,
416}
417
418// ── Enum types ──────────────────────────────────────────────────────────
419
420/// Body of a Flow enum declaration.
421#[derive(Debug, Clone, Deserialize)]
422#[serde(tag = "type")]
423pub enum EnumBody {
424    EnumStringBody {
425        members: Vec<EnumMember>,
426        #[serde(rename = "explicitType", default)]
427        explicit_type: bool,
428        #[serde(rename = "hasUnknownMembers", default)]
429        has_unknown_members: bool,
430    },
431    EnumNumberBody {
432        members: Vec<EnumMember>,
433        #[serde(rename = "explicitType", default)]
434        explicit_type: bool,
435        #[serde(rename = "hasUnknownMembers", default)]
436        has_unknown_members: bool,
437    },
438    EnumBooleanBody {
439        members: Vec<EnumMember>,
440        #[serde(rename = "explicitType", default)]
441        explicit_type: bool,
442        #[serde(rename = "hasUnknownMembers", default)]
443        has_unknown_members: bool,
444    },
445    EnumSymbolBody {
446        members: Vec<EnumMember>,
447        #[serde(rename = "hasUnknownMembers", default)]
448        has_unknown_members: bool,
449    },
450    EnumBigIntBody {
451        members: Vec<EnumMember>,
452        #[serde(rename = "explicitType", default)]
453        explicit_type: bool,
454        #[serde(rename = "hasUnknownMembers", default)]
455        has_unknown_members: bool,
456    },
457    #[serde(other)]
458    Other,
459}
460
461impl EnumBody {
462    /// Short type tag for assertions.
463    pub fn type_name(&self) -> &'static str {
464        match self {
465            Self::EnumStringBody { .. } => "EnumStringBody",
466            Self::EnumNumberBody { .. } => "EnumNumberBody",
467            Self::EnumBooleanBody { .. } => "EnumBooleanBody",
468            Self::EnumSymbolBody { .. } => "EnumSymbolBody",
469            Self::EnumBigIntBody { .. } => "EnumBigIntBody",
470            Self::Other => "Other",
471        }
472    }
473
474    /// Members of the enum body.
475    pub fn members(&self) -> &[EnumMember] {
476        match self {
477            Self::EnumStringBody { members, .. }
478            | Self::EnumNumberBody { members, .. }
479            | Self::EnumBooleanBody { members, .. }
480            | Self::EnumSymbolBody { members, .. }
481            | Self::EnumBigIntBody { members, .. } => members,
482            Self::Other => &[],
483        }
484    }
485}
486
487/// A member of a Flow enum body.
488#[derive(Debug, Clone, Deserialize)]
489#[serde(tag = "type")]
490pub enum EnumMember {
491    /// Defaulted member (symbol enum, or auto-initialized).
492    EnumDefaultedMember {
493        id: Identifier,
494    },
495    /// String-initialized member.
496    EnumStringMember {
497        id: Identifier,
498        init: EnumStringInit,
499    },
500    /// Number-initialized member.
501    EnumNumberMember {
502        id: Identifier,
503        init: EnumNumberInit,
504    },
505    /// Boolean-initialized member.
506    EnumBooleanMember {
507        id: Identifier,
508        init: EnumBooleanInit,
509    },
510    #[serde(other)]
511    Other,
512}
513
514impl EnumMember {
515    /// Name of the enum member, if known.
516    pub fn name(&self) -> Option<&str> {
517        match self {
518            Self::EnumDefaultedMember { id }
519            | Self::EnumStringMember { id, .. }
520            | Self::EnumNumberMember { id, .. }
521            | Self::EnumBooleanMember { id, .. } => Some(&id.name),
522            Self::Other => None,
523        }
524    }
525}
526
527/// String literal init value in a Flow enum member.
528#[derive(Debug, Clone, Deserialize)]
529pub struct EnumStringInit {
530    pub value: String,
531}
532
533/// Number literal init value in a Flow enum member.
534#[derive(Debug, Clone, Deserialize)]
535pub struct EnumNumberInit {
536    pub value: f64,
537}
538
539/// Boolean literal init value in a Flow enum member.
540#[derive(Debug, Clone, Deserialize)]
541pub struct EnumBooleanInit {
542    pub value: bool,
543}
544
545// ── Shared nodes ────────────────────────────────────────────────────────
546
547/// An identifier node.
548#[derive(Debug, Clone, Deserialize)]
549pub struct Identifier {
550    pub name: String,
551}
552
553/// A type identifier — either a simple `Identifier` or a qualified `A.B` reference.
554#[derive(Debug, Clone, Deserialize)]
555#[serde(tag = "type")]
556pub enum TypeIdentifier {
557    Identifier {
558        name: String,
559    },
560    QualifiedTypeIdentifier {
561        qualification: Box<TypeIdentifier>,
562        id: Identifier,
563    },
564    #[serde(other)]
565    Other,
566}
567
568impl TypeIdentifier {
569    /// The leaf name of this identifier (e.g. `"Node"` for `React.Node`).
570    pub fn name(&self) -> Option<&str> {
571        match self {
572            Self::Identifier { name } => Some(name),
573            Self::QualifiedTypeIdentifier { id, .. } => Some(&id.name),
574            Self::Other => None,
575        }
576    }
577
578    /// Full dotted name (e.g. `"React.Node"`).
579    pub fn full_name(&self) -> String {
580        match self {
581            Self::Identifier { name } => name.clone(),
582            Self::QualifiedTypeIdentifier { qualification, id } => {
583                format!("{}.{}", qualification.full_name(), id.name)
584            }
585            Self::Other => "?".to_owned(),
586        }
587    }
588}
589
590/// Property key — either an identifier or a string literal (for quoted keys).
591#[derive(Debug, Clone, Deserialize)]
592#[serde(tag = "type")]
593pub enum PropertyKey {
594    Identifier {
595        name: String,
596    },
597    /// Quoted key — Flow parser emits `Literal` (not `StringLiteral`) for property keys.
598    Literal {
599        value: serde_json::Value,
600    },
601    #[serde(other)]
602    Other,
603}
604
605impl PropertyKey {
606    /// The key's text regardless of representation.
607    pub fn name(&self) -> Option<&str> {
608        match self {
609            Self::Identifier { name } => Some(name),
610            Self::Literal { value } => value.as_str(),
611            Self::Other => None,
612        }
613    }
614
615    /// Whether this key is a quoted literal (non-identifier).
616    pub fn is_quoted(&self) -> bool {
617        matches!(self, Self::Literal { .. })
618    }
619}
620
621/// Variance annotation (`+` = plus, `-` = minus).
622#[derive(Debug, Clone, Deserialize)]
623pub struct Variance {
624    pub kind: VarianceKind,
625}
626
627/// Variance direction.
628#[derive(Debug, Clone, Copy, Deserialize, PartialEq, Eq)]
629#[serde(rename_all = "lowercase")]
630pub enum VarianceKind {
631    Plus,
632    Minus,
633}
634
635/// Type parameter instantiation (`<T, U>`).
636#[derive(Debug, Clone, Deserialize)]
637pub struct TypeParameterInstantiation {
638    pub params: Vec<TypeAnnotation>,
639}
640
641/// Type parameter declaration (`<T: Bound, U = Default>`).
642#[derive(Debug, Clone, Deserialize)]
643pub struct TypeParameterDeclaration {
644    pub params: Vec<TypeParameter>,
645}
646
647/// A single type parameter in a declaration.
648#[derive(Debug, Clone, Deserialize)]
649pub struct TypeParameter {
650    pub name: String,
651    /// Bound is wrapped: `{"type": "TypeAnnotation", "typeAnnotation": <actual>}`
652    #[serde(default)]
653    pub bound: Option<TypeAnnotationWrapper>,
654    #[serde(default)]
655    pub default: Option<Box<TypeAnnotation>>,
656    #[serde(default)]
657    pub variance: Option<Variance>,
658}
659
660/// Wrapper node the Flow parser emits around type annotations in certain positions
661/// (e.g., type parameter bounds, function parameter types).
662#[derive(Debug, Clone, Deserialize)]
663pub struct TypeAnnotationWrapper {
664    #[serde(rename = "typeAnnotation")]
665    pub type_annotation: TypeAnnotation,
666}