async-codegen 0.12.1

Minimalist async-IO code generation framework.
Documentation
/*
 * Copyright © 2025 Anand Beh
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

//!
//! Java syntax elements.
//!
//! Note that no checking exists to make sure the elements are used correctly, i.e. the correct
//! combination of structs. Instead, the library user is expected to have basic knowledge of how
//! Java syntax is composed, and to combine the structs in this module likewise.
//!

mod syntax;
#[cfg(test)]
mod tests;

/// Declares a new variable. Renders as `Type Expr;` with a new line at the end
/// The expression can be either the variable name or an [AssignExpr].
/// ```
/// # use async_codegen::common::Str;
/// # use async_codegen::context::EmptyContext;
/// # use async_codegen::java::{AssignExpr, DeclareVarStmt};
/// # use async_codegen::util::InMemoryOutput;
/// let declare_var = DeclareVarStmt(Str("String"), Str("varname"));
/// let string = InMemoryOutput::print_output(EmptyContext, &declare_var);
/// assert_eq!("String varname;\n", string);
///
/// let init_var = DeclareVarStmt(Str("String"), AssignExpr(Str("varname"), Str("\"hello world\"")));
/// let string = InMemoryOutput::print_output(EmptyContext, &init_var);
/// assert_eq!("String varname = \"hello world\";\n", string);
/// ```
pub struct DeclareVarStmt<Type, Expr>(pub Type, pub Expr);

/// An assertion. Renders as `assert Assert;` with a new line at the end
#[derive(Clone, Debug)]
pub struct AssertStmt<Assert>(pub Assert);

/// A standalone statement. Renders the expression and adds a semicolon and a new line.
#[derive(Clone, Debug)]
pub struct Stmt<Expr>(pub Expr);

/// An assignation. This statement includes the semicolon and a new line.
#[derive(Clone, Debug)]
pub struct AssignStmt<Variable, Expr>(pub Variable, pub Expr);

/// A return statement. Renders as `return Expr;` with a new line at the end.
#[derive(Clone, Debug)]
pub struct ReturnStmt<Expr>(pub Expr);

/// An assignation, as an expression. Renders as `Variable = Expr`. In Java, an assignation
/// expression has the same type and value as the assigned value.
#[derive(Clone, Debug)]
pub struct AssignExpr<Variable, Expr>(pub Variable, pub Expr);

/// An if block. The condition and body must both be writable.
#[derive(Clone, Debug)]
pub struct IfBlock<Cond, Body>(pub Cond, pub Body);

/// Represents "else" syntactically. Renders as `Before else After`.
///
/// This struct requires you to specify what comes before and after the else. For example:
/// ```
/// # use async_codegen::common::Str;
/// # use async_codegen::context::EmptyContext;
/// # use async_codegen::java::{AssertStmt, Block, Else, IfBlock};
/// # use async_codegen::util::InMemoryOutput;
///
/// let if_block = IfBlock(Str("true"), Str("System.out.println(\"Hello\");"));
/// let else_block = Block(AssertStmt(Str("false")));
/// let if_else = Else(if_block, else_block);
///
/// let string = InMemoryOutput::print_output(EmptyContext, &if_else);
/// assert_eq!("if true {\nSystem.out.println(\"Hello\");\n} else {\nassert false;\n\n}", string)
/// ```
#[derive(Clone, Debug)]
pub struct Else<Before, After>(pub Before, pub After);

/// An unlabeled block.
/// This can be used in many contexts, including merely organizing the code.
#[derive(Clone, Debug)]
pub struct Block<Body>(pub Body);

/// Accesses a field or calls a method by name. Renders as `Owner.Member`.
#[derive(Clone, Debug)]
pub struct MemberAccess<Owner, Member>(pub Owner, pub Member);

/// Declares a class.
#[derive(Clone, Debug)]
pub struct ClassDef<Mods, Name, Body> {
    /// The modifiers. Must be a sequence
    pub mods: Mods,
    /// The class name. Must be writable.
    ///
    /// To declare a superclass or interfaces, use [Extends] or [Implements]
    pub name: Name,
    /// The body of the class
    pub body: Body,
}

/// Declares an interface
#[derive(Clone, Debug)]
pub struct InterfaceDef<Mods, Name, Body> {
    /// The modifiers. Must be a sequence
    pub mods: Mods,
    /// The class name. Must be writable.
    ///
    /// To declare a superclass or interfaces, use [Extends] or [Implements]
    pub name: Name,
    /// The body of the class
    pub body: Body,
}

/// The "extends" keyword. Renders as `Expr extends Super`.
#[derive(Clone, Debug)]
pub struct Extends<Expr, Super>(pub Expr, pub Super);

/// The "implements" keyword. Renders as `Expr implements Iface1, Iface2, Iface3, ...`.
/// The interfaces must be a sequence. If it is empty, then only `Expr` will be rendered.
#[derive(Clone, Debug)]
pub struct Implements<Expr, Ifaces>(pub Expr, pub Ifaces);

/// A single modifier keyword
#[derive(Clone, Debug)]
pub enum Modifier {
    Abstract,
    Default,
    Final,
    Native,
    Private,
    Protected,
    Public,
    Static,
    StrictFp,
    Synchronized,
    Transient,
    Volatile,
}

/// Calls a function with a name and arguments. Renders as `Name(Arg1, Arg2, Arg3, ...)`
#[derive(Clone, Debug)]
pub struct FunctionCall<Name, Args> {
    /// The name of the function.
    pub name: Name,
    /// The arguments. Must be a sequence
    pub args: Args,
}

/// Calls a constructor with a name and arguments. Renders as `new Name(Arg1, Arg2, Arg3, ...)`
#[derive(Clone, Debug)]
pub struct ConstructorCall<Name, Args> {
    /// The name of the class being constructed
    pub name: Name,
    /// The arguments. Must be a sequence
    pub args: Args,
}

/// A function parameter, constructor parameter, or record component parameter.
///
/// Renders as `Type Name`.
#[derive(Clone, Debug)]
pub struct DeclareParam<Type, Name>(pub Type, pub Name);

/// A type argument-parameterized declaration. Renders as `Name<TypeArgs>`.
///
/// The type args must be a sequence. If they are empty, only `Name` will be rendered.
#[derive(Clone, Debug)]
pub struct Parameterized<Name, TypeArgs>(pub Name, pub TypeArgs);

/// Applies diamond inference to the construction of a type. Renders as `Name<>`.
#[derive(Clone, Debug)]
pub struct WithInference<Name>(pub Name);

/// An array of another type. Renders as `Component[]`
#[derive(Clone, Debug)]
pub struct Array<Component>(pub Component);

/// An enhanced for loop in the style `for (VarName : Iter) { Body }`.
/// All fields of this struct must be writable.
#[derive(Clone, Debug)]
pub struct EnhancedFor<VarName, Iter, Body> {
    /// The variable type and name. Must be writable. [DeclareParam] will suffice in most cases
    pub var_name: VarName,
    /// The iterator expression
    pub iter: Iter,
    /// The body of the for loop
    pub body: Body,
}

/// A traditional for loop in the style `for (Init; Predicate; Update) { Body }`.
/// All the fields of this struct must be writable. For example:
/// ```
/// use async_codegen::common::{SingularSeq, Str};
/// use async_codegen::context::EmptyContext;
/// use async_codegen::java::{AssignExpr, DeclareParam, FunctionCall, MemberAccess, Stmt, TraditionalFor};
/// use async_codegen::util::InMemoryOutput;
/// let for_loop = TraditionalFor {
///   init: AssignExpr(DeclareParam(Str("int"), Str("i")), Str("0")),
///   predicate: Str("i < 5"),
///   update: Str("i++"),
///   body: Stmt(MemberAccess(Str("System.out"), FunctionCall {
///     name: Str("println"),
///     args: SingularSeq(Str("i"))
///   }))
/// };
/// let string = InMemoryOutput::print_output(EmptyContext, &for_loop);
/// assert_eq!("for (int i = 0; i < 5; i++) {\nSystem.out.println(i);\n}\n", string);
/// ```
#[derive(Clone, Debug)]
pub struct TraditionalFor<Init, Predicate, Update, Body> {
    /// The initial declaration of the loop variable
    pub init: Init,
    /// The predicate that is checked before the next iteration
    pub predicate: Predicate,
    /// The update that is applied after every iteration
    pub update: Update,
    /// The body of the for loop
    pub body: Body,
}

/// Defines a constructor
#[derive(Clone, Debug)]
pub struct ConstructorDef<Mods, TypeArgs, Name, Args, Throws, Body> {
    /// The modifiers. Must be a sequence
    pub mods: Mods,
    /// The type arguments. Must be a sequence
    pub type_args: TypeArgs,
    /// The simple name of the class
    pub name: Name,
    /// The constructor arguments. Must be a sequence
    pub args: Args,
    /// The constructor body
    pub body: Body,
    /// The throws declaration. Must be a sequence
    pub throws: Throws,
}

/// Defines a function
#[derive(Clone, Debug)]
pub struct FunctionDef<Mods, TypeArgs, Return, Name, Args, Throws, Body> {
    /// The modifiers. Must be a sequence
    pub mods: Mods,
    /// The type arguments. Must be a sequence
    pub type_args: TypeArgs,
    /// The return type
    pub return_type: Return,
    /// The simple name of the class
    pub name: Name,
    /// The function arguments. Must be a sequence
    pub args: Args,
    /// The constructor body
    pub body: Body,
    /// The throws declaration. Must be a sequence
    pub throws: Throws,
}