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}