Get Started
Introduction
Next is an advanced Interface Definition Language (IDL) designed for efficient and flexible code generation across multiple programming languages.
Next allows developers to define constants, enums, structures, interfaces, and more in a language-agnostic manner. It then uses a powerful template system to generate code for various target languages, making it an ideal choice for projects that need to maintain consistency across different programming environments.
How It Works
- Define Once: Write your data structures, enums, and interfaces in Next.
- Annotate: Use annotations to provide language-specific details or additional metadata.
- Template: Create or use existing templates for your target languages.
- Generate: Use the Next compiler to generate code for multiple languages from your single definition.
Installation
To install Next, you can use the following command:
- Unix-like Shell
- Windows PowerShell
curl --proto '=https' --tlsv1.2 -sSf https://getnext.sh | sh
iwr -useb https://getnext.sh/ps | iex
After installing Next, run next version
to check the installed version:
next version
Editor Extensions
- VSCode
Install Visual Studio Code Extension for Next from marketplace.
This extension provides syntax highlighting, and other helpful features for Next development in Visual Studio Code. You can install it directly from the provided link or search for next lang
in the Visual Studio Code Extensions marketplace.
Write a Next source file
First of all, You need write a Next source file which has extension .next
used to define constants, enums, structures and interfaces. Here is an example Next file:
demo.next
@next(
go_package="github.com/mkideal/next/website/example/gen/go/demo",
// Import statements for go_imports:
// - "net/http" is imported for go_alias "*net/http.HandlerFunc"
// - "fmt" is imported to demonstrate importing with go type
//
// Format for go_imports:
// - path/to/pkg.Var (for functions, variables, constants, etc.)
// - *path/to/pkg.Type (for types, "*" is required for importing types)
//
// Note: Avoid duplicating import paths. Use comma separation for multiple imports.
go_imports="*net/http.HandlerFunc,*fmt.Stringer",
cpp_package="demo",
c_package="DEMO_",
java_package="com.example.demo",
csharp_package="Demo",
)
package demo;
const Version = "1.0.0"; // String constant
const MaxRetries = 3; // Integer constant
const Timeout = MaxRetries * 1000.0; // Float constant expression
// Color represents different color options
// Values: Red (1), Green (2), Blue (4), Yellow (8)
@next(type=int8)
enum Color {
Red = 1 << iota;
Green;
Blue;
Yellow;
}
// MathConstants represents mathematical constants
@next(available="!protobuf & !php")
enum MathConstants {
Pi = 3.14159265358979323846;
E = 2.71828182845904523536;
}
// User represents a user in the system
struct User {
@next(tokens="ID")
int64 id;
string username;
vector<string> tags;
map<string, int> scores;
array<float64, 3> coordinates;
array<array<int, 2>, 3> matrix;
@deprecated string email;
@deprecated(message="favoriteColor is deprecated, use tags instead")
Color favoriteColor;
// @next(tokens) applies to the node name:
// - For snake_case: "last_login_ip"
// - For camelCase: "lastLoginIP"
// - For PascalCase: "LastLoginIP"
// - For kebab-case: "last-login-ip"
string lastLoginIP;
any extra;
}
// uint64 represents a 64-bit unsigned integer.
// - In Go, it is aliased as uint64
// - In C++, it is aliased as uint64_t
// - In Java, it is aliased as long
// - In Rust, it is aliased as u64
// - In C#, it is aliased as ulong
// - In Protobuf, it is represented as uint64
// - In other languages, it is represented as a struct with low and high 32-bit integers.
@next(
go_alias="uint64",
cpp_alias="uint64_t",
java_alias="long",
rust_alias="u64",
csharp_alias="ulong",
protobuf_alias="uint64",
)
struct uint64 {
int32 low;
int32 high;
}
// uint128 represents a 128-bit unsigned integer.
// - In rust, it is aliased as u128
// - In other languages, it is represented as a struct with low and high 64-bit integers.
@next(rust_alias="u128")
struct uint128 {
uint64 low;
uint64 high;
}
// Contract represents a smart contract
struct Contract {
uint128 address;
any data;
}
// OperatingSystem represents different operating systems
@next(available="!protobuf")
enum OperatingSystem {
Windows = "windows";
Linux = "linux";
MacOS = "macos";
Android = "android";
IOS = "ios";
}
// LoginRequest represents a login request message (type 101)
// @message annotation is a custom annotation that generates message types.
@message(type=101, req)
struct LoginRequest {
string username;
string password;
// @optional annotation is a builtin annotation that marks a field as optional.
@optional string device;
@next(
available="!protobuf",
default=OperatingSystem.IOS,
)
@optional OperatingSystem os;
// @optional is not supported for array, vector, and map fields:
//
// Bad example:
// @optional array<float64, 3> coordinates;
// @optional vector<string> tags;
// @optional map<string, int> scores;
@next(protobuf_alias="fixed64")
int64 timestamp;
}
// LoginResponse represents a login response message (type 102)
@message(type=102)
struct LoginResponse {
string token;
User user;
}
// Reader provides reading functionality
interface Reader {
// @next(error) applies to the method:
// - For Go: The method may return an error
// - For C++/Java: The method throws an exception
//
// @next(mut) applies to the method:
// - For C++: The method is non-const
// - For other languages: This annotation may not have a direct effect
//
// @next(mut) applies to the parameter buffer:
// - For C++: The parameter is non-const, allowing modification
// - For other languages: This annotation may not have a direct effect,
// but indicates that the buffer content may be modified
@next(error, mut)
read(@next(mut) bytes buffer) int;
}
@next(
available="go|java",
go_alias="net/http.Handler",
java_alias="java.util.function.Function<com.sun.net.httpserver.HttpExchange, String>",
)
interface HTTPHandler {}
// HTTPServer provides HTTP server functionality.
//
// @next(available="go|java") indicates that the interface is available for Go and Java.
@next(available="go|java")
interface HTTPServer {
// @next(error) indicates that the method may return an error:
// - For Go: The method returns (LoginResponse, error)
// - For C++/Java: The method throws an exception
@next(error)
handle(string path, HTTPHandler handler);
}
// HTTPClient provides HTTP request functionality
interface HTTPClient {
// Available for all languages
request(string url, string method, string body) string;
request2(string url, string method, string body) string;
// Available for Go and Java
@next(error, available="go|java")
get(string url) string;
// Available for C++
@next(error, available="cpp")
post(string url, string body) string;
}
See Language Specification for details about next
language specification.
Write a Next template file
Then, write a Next template file which has extension .npl
used to conctrol how to generate code for specified language. Here is an example template file used to generate c++
code.
{{- /* Overrides "next/cpp/struct.fields": add method 'message_type' for each message after fields */ -}}
{{- define "cpp/struct.fields" -}}
{{super . | linespace}}
{{- with .Decl.Annotations.message.type}}
static inline int message_type() { return {{.}}; }
{{- end}}
{{- end}}
{{- head}}
{{next this}}
{{head}}
: Generate a header like this:// Code generated by "next"; DO NOT EDIT.
{{next this}}
: Generatethis
declaration. By default,this
is a file if themeta/this
not specified.
See API/Context/meta for details about meta
.
Generate code
Finally, run next
command to generate code using demo.next
and file.cpp.npl
:
next -T cpp=file.cpp.npl -O cpp=gen/cpp/ demo.next
Output
// Code generated by "next"; DO NOT EDIT
#pragma once
#include <any>
#include <array>
#include <cstdint>
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
namespace demo {
// Enums forward declarations
enum class Color;
/* enum */ class MathConstants;
/* enum */ class OperatingSystem;
// Classes forward declarations
class User;
class Uint128;
class Contract;
class LoginRequest;
class LoginResponse;
inline constexpr auto Version = "1.0.0"; // String constant
inline constexpr auto MaxRetries = 3; // Integer constant
inline constexpr auto Timeout = 3000.0F; // Float constant expression
// Color represents different color options
// Values: Red (1), Green (2), Blue (4), Yellow (8)
enum class Color : int8_t {
Red = 1,
Green = 2,
Blue = 4,
Yellow = 8,
};
/* enum */ class MathConstants {
private:
double value;
public:
static inline constexpr double Pi = 3.14159265358979323846;
static inline constexpr double E = 2.71828182845904523536;
MathConstants(const double& v) : value(v) {}
bool operator==(const MathConstants& other) const {
return value == other.value;
}
operator double() const {
return value;
}
};
/* enum */ class OperatingSystem {
private:
std::string value;
public:
static inline const std::string Windows = "windows";
static inline const std::string Linux = "linux";
static inline const std::string MacOS = "macos";
static inline const std::string Android = "android";
static inline const std::string IOS = "ios";
OperatingSystem(const std::string& v) : value(v) {}
bool operator==(const OperatingSystem& other) const {
return value == other.value;
}
operator std::string() const {
return value;
}
};
// User represents a user in the system
class User {
public:
int64_t id = {0};
std::string username = {""};
std::vector<std::string> tags;
std::unordered_map<std::string, int> scores;
std::array<double, 3> coordinates = {double};
std::array<std::array<int, 2>, 3> matrix = {std::array<int, 2>};
std::string email = {""};
Color favorite_color = {Color(0)};
// @next(tokens) applies to the node name:
// - For snake_case: "last_login_ip"
// - For camelCase: "lastLoginIP"
// - For PascalCase: "LastLoginIP"
// - For kebab-case: "last-login-ip"
std::string last_login_ip = {""};
std::any extra;
public:
User() = default;
~User() = default;
};
// uint128 represents a 128-bit unsigned integer.
// - In rust, it is aliased as u128
// - In other languages, it is represented as a struct with low and high 64-bit integers.
class Uint128 {
public:
uint64_t low;
uint64_t high;
public:
Uint128() = default;
~Uint128() = default;
};
// Contract represents a smart contract
class Contract {
public:
Uint128 address;
std::any data;
public:
Contract() = default;
~Contract() = default;
};
// LoginRequest represents a login request message (type 101)
// @message annotation is a custom annotation that generates message types.
class LoginRequest {
public:
std::string username = {""};
std::string password = {""};
// @optional annotation is a builtin annotation that marks a field as optional.
std::string device = {""};
OperatingSystem os = {OperatingSystem("")};
int64_t timestamp = {0};
static inline int message_type() { return 101; }
public:
LoginRequest() = default;
~LoginRequest() = default;
};
// LoginResponse represents a login response message (type 102)
class LoginResponse {
public:
std::string token = {""};
User user;
static inline int message_type() { return 102; }
public:
LoginResponse() = default;
~LoginResponse() = default;
};
// Reader provides reading functionality
class Reader {
public:
virtual ~Reader() = default;
// @next(error) applies to the method:
// - For Go: The method may return an error
// - For C++/Java: The method throws an exception
//
// @next(mut) applies to the method:
// - For C++: The method is non-const
// - For other languages: This annotation may not have a direct effect
//
// @next(mut) applies to the parameter buffer:
// - For C++: The parameter is non-const, allowing modification
// - For other languages: This annotation may not have a direct effect,
// but indicates that the buffer content may be modified
virtual int read(std::vector<unsigned char>& buffer) = 0;
};
// HTTPClient provides HTTP request functionality
class HTTPClient {
public:
virtual ~HTTPClient() = default;
// Available for all languages
virtual std::string request(const std::string& url, const std::string& method, const std::string& body) const = 0;
virtual std::string request2(const std::string& url, const std::string& method, const std::string& body) const = 0;
// Available for C++
virtual std::string post(const std::string& url, const std::string& body) const = 0;
};
} // namespace demo
How to generate multi-language codes?
It's easy to generate many other langauge codes by writing template files. Here is an example to generate java
code.
- constants.java.npl
- enum.java.npl
- struct.java.npl
- interface.java.npl
{{- define "meta/this"}}package{{end -}}
{{- define "meta/_class"}}Constants{{end -}}
{{- define "meta/path"}}{{render "package:name" this.Package | replace "." "/"}}/{{meta._class}}.java{{end -}}
{{- define "meta/skip"}}{{eq 0 (len this.Decls.Consts.List)}}{{end -}}
{{- define "java/package" -}}
package {{render "package:name" .}};
public class {{meta._class}} {
{{- next .Decls.Consts | indent | linespace -}}
}
{{end -}}
{{head}}
{{next this}}
This template file is used to generate all constants in a file Constants.java
which define a Constants
class to holds all constants of a package.
We add some metadata and override next/java/package
by defining java/package
. We need define meta/this
with package
.
Output
- Constants.java
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
public class Constants {
public static final String VERSION = "1.0.0"; // String constant
public static final int MAX_RETRIES = 3; // Integer constant
public static final float TIMEOUT = 3000.0F; // Float constant expression
}
{{- define "meta/this"}}enum{{end -}}
{{- define "meta/path"}}{{render "package:name" this.Package | replace "." "/"}}/{{next this.Type}}.java{{end -}}
{{- define "java/enum" -}}
package {{render "package:name" .Package}};
{{super .}}
{{- end}}
{{- head}}
{{next this}}
This template file is used to generate java file for each enum
declaration. We need define meta/this
with enum
.
Output
- Color.java
- MathConstants.java
- OperatingSystem.java
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
/**
* Color represents different color options
* Values: Red (1), Green (2), Blue (4), Yellow (8)
*/
public enum Color {
Red((byte) 1),
Green((byte) 2),
Blue((byte) 4),
Yellow((byte) 8);
private final byte value;
Color(byte value) {
this.value = value;
}
public byte getValue() {
return value;
}
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
/**
* MathConstants represents mathematical constants
*/
public enum MathConstants {
Pi((double) 3.14159265358979323846),
E((double) 2.71828182845904523536);
private final double value;
MathConstants(double value) {
this.value = value;
}
public double getValue() {
return value;
}
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
/**
* OperatingSystem represents different operating systems
*/
public enum OperatingSystem {
Windows((String) "windows"),
Linux((String) "linux"),
MacOS((String) "macos"),
Android((String) "android"),
IOS((String) "ios");
private final String value;
OperatingSystem(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
{{- define "meta/this"}}struct{{end -}}
{{- define "meta/path"}}{{render "package:name" this.Package | replace "." "/"}}/{{next this.Type}}.java{{end -}}
{{/* Overrides "next/java/struct": add package and imports before struct */}}
{{- define "java/struct" -}}
package {{render "package:name" .Package}};
{{next .File.Imports | linespace -}}
{{super .}}
{{- end -}}
{{- /* Overrides "next/java/struct.fields": add method 'MessageType' for each message after fields */ -}}
{{- define "java/struct.fields" -}}
{{- super . | linespace}}
{{- with .Decl.Annotations.message.type}}
public static int MessageType() {
return {{.}};
}
{{end}}
{{- end}}
{{- head}}
{{next this}}
This template file is used to generate java file for each struct
declaration. We need define meta/this
with struct
.
Output
- Contract.java
- LoginRequest.java
- LoginResponse.java
- Uint128.java
- User.java
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* Contract represents a smart contract
*/
public class Contract {
private Uint128 address;
public Uint128 getAddress() {
return address;
}
public void setAddress(Uint128 address) {
this.address = address;
}
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public Contract() {
}
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* LoginRequest represents a login request message (type 101)
* @message annotation is a custom annotation that generates message types.
*/
public class LoginRequest {
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
/**
* @optional annotation is a builtin annotation that marks a field as optional.
*/
private String device;
public String getDevice() {
return device;
}
public void setDevice(String device) {
this.device = device;
}
private OperatingSystem os;
public OperatingSystem getOs() {
return os;
}
public void setOs(OperatingSystem os) {
this.os = os;
}
private long timestamp;
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public static int MessageType() {
return 101;
}
public LoginRequest() {
}
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* LoginResponse represents a login response message (type 102)
*/
public class LoginResponse {
private String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public static int MessageType() {
return 102;
}
public LoginResponse() {
}
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* uint128 represents a 128-bit unsigned integer.
* - In rust, it is aliased as u128
* - In other languages, it is represented as a struct with low and high 64-bit integers.
*/
public class Uint128 {
private long low;
public long getLow() {
return low;
}
public void setLow(long low) {
this.low = low;
}
private long high;
public long getHigh() {
return high;
}
public void setHigh(long high) {
this.high = high;
}
public Uint128() {
}
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* User represents a user in the system
*/
public class User {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
private String username;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
private List<String> tags;
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
private Map<String, Integer> scores;
public Map<String, Integer> getScores() {
return scores;
}
public void setScores(Map<String, Integer> scores) {
this.scores = scores;
}
private double[] coordinates;
public double[] getCoordinates() {
return coordinates;
}
public void setCoordinates(double[] coordinates) {
this.coordinates = coordinates;
}
private int[][] matrix;
public int[][] getMatrix() {
return matrix;
}
public void setMatrix(int[][] matrix) {
this.matrix = matrix;
}
private String email;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
private Color favoriteColor;
public Color getFavoriteColor() {
return favoriteColor;
}
public void setFavoriteColor(Color favoriteColor) {
this.favoriteColor = favoriteColor;
}
/**
* @next(tokens) applies to the node name:
* - For snake_case: "last_login_ip"
* - For camelCase: "lastLoginIP"
* - For PascalCase: "LastLoginIP"
* - For kebab-case: "last-login-ip"
*/
private String lastLoginIP;
public String getLastLoginIP() {
return lastLoginIP;
}
public void setLastLoginIP(String lastLoginIP) {
this.lastLoginIP = lastLoginIP;
}
private Object extra;
public Object getExtra() {
return extra;
}
public void setExtra(Object extra) {
this.extra = extra;
}
public User() {
}
}
{{- define "meta/this"}}interface{{end -}}
{{- define "meta/path"}}{{render "package:name" this.Package | replace "." "/"}}/{{next this.Type}}.java{{end -}}
{{- /* Overrides "next/java/interface": add package and imports before interface */ -}}
{{- define "java/interface" -}}
package {{render "package:name" .Package}};
{{next .File.Imports | linespace -}}
{{super .}}
{{- end}}
{{- head}}
{{next this}}
This template file is used to generate java file for each interface
declaration. We need define meta/this
with interface
.
Output
- HTTPClient.java
- HTTPServer.java
- Reader.java
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* HTTPClient provides HTTP request functionality
*/
public interface HTTPClient {
/**
* Available for all languages
*/
String request(String url, String method, String body);
String request2(String url, String method, String body);
/**
* Available for Go and Java
*/
String get(String url) throws Exception;
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* HTTPServer provides HTTP server functionality.
*
* @next(available="go|java") indicates that the interface is available for Go and Java.
*/
public interface HTTPServer {
/**
* @next(error) indicates that the method may return an error:
* - For Go: The method returns (LoginResponse, error)
* - For C++/Java: The method throws an exception
*/
void handle(String path, java.util.function.Function<com.sun.net.httpserver.HttpExchange, String> handler) throws Exception;
}
// Code generated by "next"; DO NOT EDIT
package com.example.demo;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
/**
* Reader provides reading functionality
*/
public interface Reader {
/**
* @next(error) applies to the method:
* - For Go: The method may return an error
* - For C++/Java: The method throws an exception
*
* @next(mut) applies to the method:
* - For C++: The method is non-const
* - For other languages: This annotation may not have a direct effect
*
* @next(mut) applies to the parameter buffer:
* - For C++: The parameter is non-const, allowing modification
* - For other languages: This annotation may not have a direct effect,
* but indicates that the buffer content may be modified
*/
int read(byte[] buffer) throws Exception;
}
To generate java
code, we need write templates for each declaration types: enum
, struct
, interface
. Specially, we write a template file to generate all constants in a single file Constants.java
.
Run next
to generate multi-language codes as following(we assume *.java.npl
files placed in dir java
):
next -T cpp=file.cpp.npl -O cpp=gen/cpp/ -T java=java/ -O java=gen/java/ demo.next
When you have write templates for other langauges, you can generate codes like this:
next \
-O c=gen/c -T c=templates/c \
-O cpp=gen/cpp -T cpp=templates/cpp \
-O csharp=gen/csharp -T csharp=templates/csharp \
-O go=gen/go -T go=templates/go \
-O java=gen/java -T java=templates/java \
-O js=gen/js -T js=templates/js \
-O lua=gen/lua -T lua=templates/lua \
-O protobuf=gen/protobuf -T protobuf=templates/protobuf \
-O python=gen/python -T python=templates/python \
-O php=gen/php -T php=templates/php \
-O rust=gen/rust/src -T rust=templates/rust \
-O ts=gen/ts -T ts=templates/ts \
-M "c.vector=void*" -M "c.map=void*" \
next/source/dir/ # or source files
Builtin supported langauges
Usually, to generate code for a language, you need a Map file and at least one template file.
Currently, Next has created some builtin map
files and base templates. See builtin for more informarion.
Here is an example for C#:
- csharp.map
- csharp.npl
ext=.cs
comment=// %T%
int=int
int8=sbyte
int16=short
int32=int
int64=long
float32=float
float64=double
bool=bool
string=string
byte=byte
bytes=byte[]
any=object
map=Dictionary<%K%, %V%>
vector=List<%T%>
array=%T%[]
{{/* next/csharp/file: Generates the main structure for a C# file */}}
{{- define "next/csharp/file" -}}
using System;
using System.Collections.Generic;
namespace {{render "package:name" .Package}}
{
{{- next .Decls | indent | linespace -}}
}
{{- end}}
{{/* next/csharp/package:name: Generates the namespace name */}}
{{- define "next/csharp/package:name" -}}
{{with .Annotations.next.csharp_package}}{{.}}{{else}}{{.Name}}{{end}}
{{- end}}
{{/* next/csharp/used.type: Generates a fully qualified type name, including namespace if necessary */}}
{{- define "next/csharp/used.type" -}}
{{- if not (.File.Package.Has .Type)}}
{{- render "package:name" .Decl.File.Package}}.
{{- end}}
{{- next .Type}}
{{- end}}
{{/* next/csharp/imports: Generates using statements for imported namespaces */}}
{{- define "next/csharp/imports" -}}
{{- range .TrimmedList}}
{{- next .}}
{{- end}}
{{- end}}
{{/* next/csharp/import: Generates a using statement for a specific imported namespace */}}
{{- define "next/csharp/import"}}
using {{render "package:name" .Target.Package}};
{{- end}}
{{/* next/csharp/const: Generates a constant declaration */}}
{{- define "next/csharp/const"}}
{{next .Doc -}}
public const {{next .Type}} {{render "const:name" .}} = {{next .Value}};{{next .Comment}}
{{- end}}
{{/* next/csharp/enum: Generates an enum declaration */}}
{{- define "next/csharp/enum"}}
{{next .Doc -}}
public enum {{next .Type}}
{
{{- next .Members | indent | linespace -}}
}
{{end}}
{{/* next/csharp/enum.member: Generates an enum member */}}
{{- define "next/csharp/enum.member"}}
{{next .Doc -}}
{{- render "enum.member:name" .}} = {{next .Value}},{{next .Comment}}
{{- end}}
{{/* next/csharp/struct: Generates a class declaration (struct in C# is typically implemented as a class) */}}
{{- define "next/csharp/struct"}}
{{next .Doc -}}
public class {{next .Type}}
{
{{- next .Fields | indent | linespace -}}
}
{{end}}
{{/* next/csharp/struct.field: Generates a property declaration for a class */}}
{{- define "next/csharp/struct.field"}}
{{next .Doc -}}
public {{next .Type}} {{render "struct.field:name" .}} { get; set; }{{next .Comment}}
{{- end}}
{{/* next/csharp/struct.field.name: Generates the name for a class property */}}
{{- define "next/csharp/struct.field:name" -}}
{{- render "node:camel.case.name" .}}
{{- end}}
{{/* next/csharp/interface: Generates an interface declaration */}}
{{- define "next/csharp/interface"}}
{{next .Doc -}}
public interface {{next .Type}}
{
{{- next .Methods | indent | linespace -}}
}
{{end}}
{{/* next/csharp/interface.method: Generates a method declaration in an interface */}}
{{- define "next/csharp/interface.method"}}
{{next .Doc -}}
{{- next .Result}} {{render "interface.method:name" .}}({{next .Params}});{{next .Comment}}
{{- end}}
{{- define "next/csharp/interface.method:name" -}}
{{- render "node:pascal.case.name" .}}
{{- end}}
{{/* next/csharp/interface.method.result: Generates the return type for an interface method */}}
{{- define "next/csharp/interface.method.result" -}}
{{- if .Type}}{{next .Type}}{{else}}void{{end}}
{{- end}}
{{/* next/csharp/interface.method.parameter: Generates a parameter for an interface method */}}
{{- define "next/csharp/interface.method.parameter" -}}
{{- if .Annotations.next.mut}}ref {{end}}{{next .Type}} {{render "interface.method.parameter:name" .}}
{{- end}}