Skip to main content

elm_ast/
declaration.rs

1use crate::comment::Comment;
2use crate::expr::{Function, Signature};
3use crate::ident::Ident;
4use crate::node::Spanned;
5use crate::operator::{InfixDirection, Precedence};
6use crate::pattern::Pattern;
7use crate::type_annotation::TypeAnnotation;
8
9/// A top-level declaration in an Elm module.
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[derive(Clone, Debug, PartialEq, Eq)]
12pub enum Declaration {
13    /// A function or value definition.
14    ///
15    /// ```elm
16    /// add : Int -> Int -> Int
17    /// add x y = x + y
18    /// ```
19    FunctionDeclaration(Box<Function>),
20
21    /// A type alias declaration.
22    ///
23    /// ```elm
24    /// type alias Model =
25    ///     { count : Int
26    ///     , name : String
27    ///     }
28    /// ```
29    AliasDeclaration(TypeAlias),
30
31    /// A custom type (ADT / tagged union) declaration.
32    ///
33    /// ```elm
34    /// type Msg
35    ///     = Increment
36    ///     | Decrement
37    ///     | SetName String
38    /// ```
39    CustomTypeDeclaration(CustomType),
40
41    /// A port declaration.
42    ///
43    /// ```elm
44    /// port sendMessage : String -> Cmd msg
45    /// ```
46    PortDeclaration(Signature),
47
48    /// An infix operator declaration (only in core packages).
49    ///
50    /// ```elm
51    /// infix left 6 (+) = add
52    /// ```
53    InfixDeclaration(InfixDef),
54
55    /// A top-level destructuring (rare, but valid).
56    ///
57    /// ```elm
58    /// { name, age } = person
59    /// ```
60    Destructuring {
61        pattern: Spanned<Pattern>,
62        body: Spanned<crate::expr::Expr>,
63    },
64}
65
66/// A type alias definition.
67#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
68#[derive(Clone, Debug, PartialEq, Eq)]
69pub struct TypeAlias {
70    /// Optional documentation comment.
71    pub documentation: Option<Spanned<String>>,
72
73    /// The alias name: `Model`
74    pub name: Spanned<Ident>,
75
76    /// Type parameters: `a`, `b` in `type alias Result a b = ...`
77    pub generics: Vec<Spanned<Ident>>,
78
79    /// The type being aliased.
80    pub type_annotation: Spanned<TypeAnnotation>,
81}
82
83/// A custom type (ADT / tagged union) definition.
84#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
85#[derive(Clone, Debug, PartialEq, Eq)]
86pub struct CustomType {
87    /// Optional documentation comment.
88    pub documentation: Option<Spanned<String>>,
89
90    /// The type name: `Msg`
91    pub name: Spanned<Ident>,
92
93    /// Type parameters: `a` in `type Maybe a = ...`
94    pub generics: Vec<Spanned<Ident>>,
95
96    /// Comments that appear between the type name/generics and the `=`.
97    /// elm-format preserves these by wrapping the `type` header over two
98    /// lines:
99    ///     type
100    ///         Sequence value
101    ///         -- repeat, delay, duration
102    ///         = Sequence ...
103    #[cfg_attr(
104        feature = "serde",
105        serde(default, skip_serializing_if = "Vec::is_empty")
106    )]
107    pub pre_equals_comments: Vec<Spanned<Comment>>,
108
109    /// The constructors: `Just a | Nothing`
110    pub constructors: Vec<Spanned<ValueConstructor>>,
111}
112
113/// A value constructor in a custom type definition.
114///
115/// `Just a` → `ValueConstructor { name: "Just", args: [a] }`
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117#[derive(Clone, Debug, PartialEq, Eq)]
118pub struct ValueConstructor {
119    pub name: Spanned<Ident>,
120    pub args: Vec<Spanned<TypeAnnotation>>,
121    /// Comments that appeared BEFORE the preceding `|` separator (or for the
122    /// first constructor, before `=`). elm-format preserves these as
123    /// "trailing on previous constructor" style: they appear on their own
124    /// line(s) at the constructor-name column, with the `|` for THIS
125    /// constructor coming afterward on a new line. Leave empty for the
126    /// first constructor.
127    #[cfg_attr(feature = "serde", serde(default))]
128    pub pre_pipe_comments: Vec<Spanned<Comment>>,
129    /// Optional trailing inline comment on the same source line as the
130    /// constructor: `| Ctor args -- comment`. elm-format keeps the comment
131    /// on the same line after the last arg.
132    #[cfg_attr(
133        feature = "serde",
134        serde(default, skip_serializing_if = "Option::is_none")
135    )]
136    pub trailing_comment: Option<Spanned<Comment>>,
137}
138
139/// An infix operator definition.
140///
141/// `infix left 6 (+) = add`
142#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
143#[derive(Clone, Debug, PartialEq, Eq)]
144pub struct InfixDef {
145    pub direction: Spanned<InfixDirection>,
146    pub precedence: Spanned<Precedence>,
147    pub operator: Spanned<Ident>,
148    pub function: Spanned<Ident>,
149}