async_codegen/java/
mod.rs

1/*
2 * Copyright © 2025 Anand Beh
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//!
18//! Java syntax elements.
19//!
20//! Note that no checking exists to make sure the elements are used correctly, i.e. the correct
21//! combination of structs. Instead, the library user is expected to have basic knowledge of how
22//! Java syntax is composed, and to combine the structs in this module likewise.
23//!
24
25mod syntax;
26#[cfg(test)]
27mod tests;
28
29/// Declares a new variable. Renders as `Type Expr;` with a new line at the end
30/// The expression can be either the variable name or an [AssignExpr].
31/// ```
32/// # use async_codegen::common::Str;
33/// # use async_codegen::context::EmptyContext;
34/// # use async_codegen::java::{AssignExpr, DeclareVarStmt};
35/// # use async_codegen::util::InMemoryOutput;
36/// let declare_var = DeclareVarStmt(Str("String"), Str("varname"));
37/// let string = InMemoryOutput::print_output(EmptyContext, &declare_var);
38/// assert_eq!("String varname;\n", string);
39///
40/// let init_var = DeclareVarStmt(Str("String"), AssignExpr(Str("varname"), Str("\"hello world\"")));
41/// let string = InMemoryOutput::print_output(EmptyContext, &init_var);
42/// assert_eq!("String varname = \"hello world\";\n", string);
43/// ```
44pub struct DeclareVarStmt<Type, Expr>(pub Type, pub Expr);
45
46/// An assertion. Renders as `assert Assert;` with a new line at the end
47#[derive(Clone, Debug)]
48pub struct AssertStmt<Assert>(pub Assert);
49
50/// A standalone statement. Renders the expression and adds a semicolon and a new line.
51#[derive(Clone, Debug)]
52pub struct Stmt<Expr>(pub Expr);
53
54/// An assignation. This statement includes the semicolon and a new line.
55#[derive(Clone, Debug)]
56pub struct AssignStmt<Variable, Expr>(pub Variable, pub Expr);
57
58/// A return statement. Renders as `return Expr;` with a new line at the end.
59#[derive(Clone, Debug)]
60pub struct ReturnStmt<Expr>(pub Expr);
61
62/// An assignation, as an expression. Renders as `Variable = Expr`. In Java, an assignation
63/// expression has the same type and value as the assigned value.
64#[derive(Clone, Debug)]
65pub struct AssignExpr<Variable, Expr>(pub Variable, pub Expr);
66
67/// An if block. The condition and body must both be writable.
68#[derive(Clone, Debug)]
69pub struct IfBlock<Cond, Body>(pub Cond, pub Body);
70
71/// Represents "else" syntactically. Renders as `Before else After`.
72///
73/// This struct requires you to specify what comes before and after the else. For example:
74/// ```
75/// # use async_codegen::common::Str;
76/// # use async_codegen::context::EmptyContext;
77/// # use async_codegen::java::{AssertStmt, Block, Else, IfBlock};
78/// # use async_codegen::util::InMemoryOutput;
79///
80/// let if_block = IfBlock(Str("true"), Str("System.out.println(\"Hello\");"));
81/// let else_block = Block(AssertStmt(Str("false")));
82/// let if_else = Else(if_block, else_block);
83///
84/// let string = InMemoryOutput::print_output(EmptyContext, &if_else);
85/// assert_eq!("if true {\nSystem.out.println(\"Hello\");\n} else {\nassert false;\n\n}", string)
86/// ```
87#[derive(Clone, Debug)]
88pub struct Else<Before, After>(pub Before, pub After);
89
90/// An unlabeled block.
91/// This can be used in many contexts, including merely organizing the code.
92#[derive(Clone, Debug)]
93pub struct Block<Body>(pub Body);
94
95/// Accesses a field or calls a method by name. Renders as `Owner.Member`.
96#[derive(Clone, Debug)]
97pub struct MemberAccess<Owner, Member>(pub Owner, pub Member);
98
99/// Declares a class.
100#[derive(Clone, Debug)]
101pub struct ClassDef<Mods, Name, Body> {
102    /// The modifiers. Must be a sequence
103    pub mods: Mods,
104    /// The class name. Must be writable.
105    ///
106    /// To declare a superclass or interfaces, use [Extends] or [Implements]
107    pub name: Name,
108    /// The body of the class
109    pub body: Body,
110}
111
112/// Declares an interface
113#[derive(Clone, Debug)]
114pub struct InterfaceDef<Mods, Name, Body> {
115    /// The modifiers. Must be a sequence
116    pub mods: Mods,
117    /// The class name. Must be writable.
118    ///
119    /// To declare a superclass or interfaces, use [Extends] or [Implements]
120    pub name: Name,
121    /// The body of the class
122    pub body: Body,
123}
124
125/// The "extends" keyword. Renders as `Expr extends Super`.
126#[derive(Clone, Debug)]
127pub struct Extends<Expr, Super>(pub Expr, pub Super);
128
129/// The "implements" keyword. Renders as `Expr implements Iface1, Iface2, Iface3, ...`.
130/// The interfaces must be a sequence. If it is empty, then only `Expr` will be rendered.
131#[derive(Clone, Debug)]
132pub struct Implements<Expr, Ifaces>(pub Expr, pub Ifaces);
133
134/// A single modifier keyword
135#[derive(Clone, Debug)]
136pub enum Modifier {
137    Abstract,
138    Default,
139    Final,
140    Native,
141    Private,
142    Protected,
143    Public,
144    Static,
145    StrictFp,
146    Synchronized,
147    Transient,
148    Volatile,
149}
150
151/// Calls a function with a name and arguments. Renders as `Name(Arg1, Arg2, Arg3, ...)`
152#[derive(Clone, Debug)]
153pub struct FunctionCall<Name, Args> {
154    /// The name of the function.
155    pub name: Name,
156    /// The arguments. Must be a sequence
157    pub args: Args,
158}
159
160/// Calls a constructor with a name and arguments. Renders as `new Name(Arg1, Arg2, Arg3, ...)`
161#[derive(Clone, Debug)]
162pub struct ConstructorCall<Name, Args> {
163    /// The name of the class being constructed
164    pub name: Name,
165    /// The arguments. Must be a sequence
166    pub args: Args,
167}
168
169/// A function parameter, constructor parameter, or record component parameter.
170///
171/// Renders as `Type Name`.
172#[derive(Clone, Debug)]
173pub struct DeclareParam<Type, Name>(pub Type, pub Name);
174
175/// A type argument-parameterized declaration. Renders as `Name<TypeArgs>`.
176///
177/// The type args must be a sequence. If they are empty, only `Name` will be rendered.
178#[derive(Clone, Debug)]
179pub struct Parameterized<Name, TypeArgs>(pub Name, pub TypeArgs);
180
181/// Applies diamond inference to the construction of a type. Renders as `Name<>`.
182#[derive(Clone, Debug)]
183pub struct WithInference<Name>(pub Name);
184
185/// An array of another type. Renders as `Component[]`
186#[derive(Clone, Debug)]
187pub struct Array<Component>(pub Component);
188
189/// An enhanced for loop in the style `for (VarName : Iter) { Body }`.
190/// All fields of this struct must be writable.
191#[derive(Clone, Debug)]
192pub struct EnhancedFor<VarName, Iter, Body> {
193    /// The variable type and name. Must be writable. [DeclareParam] will suffice in most cases
194    pub var_name: VarName,
195    /// The iterator expression
196    pub iter: Iter,
197    /// The body of the for loop
198    pub body: Body,
199}
200
201/// A traditional for loop in the style `for (Init; Predicate; Update) { Body }`.
202/// All the fields of this struct must be writable. For example:
203/// ```
204/// use async_codegen::common::{SingularSeq, Str};
205/// use async_codegen::context::EmptyContext;
206/// use async_codegen::java::{AssignExpr, DeclareParam, FunctionCall, MemberAccess, Stmt, TraditionalFor};
207/// use async_codegen::util::InMemoryOutput;
208/// let for_loop = TraditionalFor {
209///   init: AssignExpr(DeclareParam(Str("int"), Str("i")), Str("0")),
210///   predicate: Str("i < 5"),
211///   update: Str("i++"),
212///   body: Stmt(MemberAccess(Str("System.out"), FunctionCall {
213///     name: Str("println"),
214///     args: SingularSeq(Str("i"))
215///   }))
216/// };
217/// let string = InMemoryOutput::print_output(EmptyContext, &for_loop);
218/// assert_eq!("for (int i = 0; i < 5; i++) {\nSystem.out.println(i);\n}\n", string);
219/// ```
220#[derive(Clone, Debug)]
221pub struct TraditionalFor<Init, Predicate, Update, Body> {
222    /// The initial declaration of the loop variable
223    pub init: Init,
224    /// The predicate that is checked before the next iteration
225    pub predicate: Predicate,
226    /// The update that is applied after every iteration
227    pub update: Update,
228    /// The body of the for loop
229    pub body: Body,
230}
231
232/// Defines a constructor
233#[derive(Clone, Debug)]
234pub struct ConstructorDef<Mods, TypeArgs, Name, Args, Throws, Body> {
235    /// The modifiers. Must be a sequence
236    pub mods: Mods,
237    /// The type arguments. Must be a sequence
238    pub type_args: TypeArgs,
239    /// The simple name of the class
240    pub name: Name,
241    /// The constructor arguments. Must be a sequence
242    pub args: Args,
243    /// The constructor body
244    pub body: Body,
245    /// The throws declaration. Must be a sequence
246    pub throws: Throws,
247}
248
249/// Defines a function
250#[derive(Clone, Debug)]
251pub struct FunctionDef<Mods, TypeArgs, Return, Name, Args, Throws, Body> {
252    /// The modifiers. Must be a sequence
253    pub mods: Mods,
254    /// The type arguments. Must be a sequence
255    pub type_args: TypeArgs,
256    /// The return type
257    pub return_type: Return,
258    /// The simple name of the class
259    pub name: Name,
260    /// The function arguments. Must be a sequence
261    pub args: Args,
262    /// The constructor body
263    pub body: Body,
264    /// The throws declaration. Must be a sequence
265    pub throws: Throws,
266}