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}