or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

code-generation.mdcore-plugin.mdgenerated-code.mdindex.mdruntime-libraries.mdvalidation-rules.md

code-generation.mddocs/

0

# Code Generation Templates

1

2

The code generation template system provides language-specific templates for generating validation code from protocol buffer files with validation rules. It uses Go's text/template package with custom functions for multi-language code generation.

3

4

## Template System Architecture

5

6

### Template Registration

7

8

```go { .api }

9

type RegisterFn func(tpl *template.Template, params pgs.Parameters)

10

```

11

12

Function type for registering language-specific template functions and helpers.

13

14

**Parameters:**

15

- `tpl *template.Template`: Template instance to register functions with

16

- `params pgs.Parameters`: PGS parameters for configuration

17

18

### File Path Generation

19

20

```go { .api }

21

type FilePathFn func(f pgs.File, ctx pgsgo.Context, tpl *template.Template) *pgs.FilePath

22

```

23

24

Function type for generating output file paths for templates.

25

26

**Parameters:**

27

- `f pgs.File`: Source proto file

28

- `ctx pgsgo.Context`: Go language context

29

- `tpl *template.Template`: Template being processed

30

31

**Returns:** `*pgs.FilePath` - Output file path for generated code

32

33

### Template Factory

34

35

```go { .api }

36

func Template(params pgs.Parameters) map[string][]*template.Template

37

```

38

39

Creates template map for all supported languages with registered functions.

40

41

**Parameters:**

42

- `params pgs.Parameters`: PGS parameters for template configuration

43

44

**Returns:** `map[string][]*template.Template` - Map of language to templates

45

46

Supported languages and their templates:

47

- `"go"`: Single Go template with validation methods

48

- `"java"`: Single Java template with validation classes

49

- `"cc"`: Header (.h) and implementation (.cc) templates

50

- `"ccnop"`: No-op C++ templates for compatibility

51

52

### File Path Resolution

53

54

```go { .api }

55

func FilePathFor(tpl *template.Template) FilePathFn

56

```

57

58

Returns appropriate file path generation function for template type.

59

60

**Parameters:**

61

- `tpl *template.Template`: Template to get path function for

62

63

**Returns:** `FilePathFn` - File path generation function

64

65

**Behavior:**

66

- `"h"` templates → C++ header file paths

67

- `"cc"` templates → C++ implementation file paths

68

- `"java"` templates → Java file paths with package structure

69

- Default → `.validate.{ext}` extension pattern

70

71

## Language-Specific Templates

72

73

### Go Templates

74

75

Go templates generate validation methods directly on protobuf message types.

76

77

**Template Name:** `"go"`

78

**Registration:** `golang.Register(tpl, params)`

79

**Output Extension:** `.pb.validate.go`

80

81

Generated code pattern:

82

```go

83

func (m *Message) Validate() error {

84

// validation logic

85

return nil

86

}

87

88

func (m *Message) ValidateAll() error {

89

// collect all validation errors

90

return errors

91

}

92

```

93

94

Features:

95

- Validates nested messages recursively

96

- Returns first error (`Validate`) or all errors (`ValidateAll`)

97

- Zero runtime dependencies

98

- Full integration with existing protobuf Go code

99

100

### Java Templates

101

102

Java templates generate validation classes with reflection-based validation.

103

104

**Template Name:** `"java"`

105

**Registration:** `java.Register(tpl, params)`

106

**Output Extension:** `.java`

107

108

Generated code pattern:

109

```java

110

public class MessageValidator implements Validator<Message> {

111

public void assertValid(Message message) throws ValidationException {

112

// validation logic

113

}

114

}

115

```

116

117

#### Java Template Functions

118

119

```go { .api }

120

func Register(tpl *template.Template, params pgs.Parameters)

121

```

122

123

Main Java template registration function with full validation template functions.

124

125

```go { .api }

126

func RegisterIndex(tpl *template.Template, params pgs.Parameters)

127

```

128

129

Index template registration for validator discovery and caching functionality.

130

131

```go { .api }

132

func JavaMultiFilePath(f pgs.File, m pgs.Message) pgs.FilePath

133

```

134

135

Generates file paths for multi-file Java generation when `java_multiple_files = true` option is set.

136

137

**Parameters:**

138

- `f pgs.File`: Source proto file

139

- `m pgs.Message`: Message to generate validator for

140

141

**Returns:** `pgs.FilePath` - Path for individual message validator class

142

143

Features:

144

- ReflectiveValidatorIndex for validator discovery

145

- gRPC interceptor support

146

- Exception-based error reporting

147

- Multi-file generation support for large proto files

148

149

### C++ Templates

150

151

C++ templates generate header and implementation files.

152

153

**Template Names:** `"h"`, `"cc"`

154

**Registration:** `cc.RegisterHeader(tpl, params)`, `cc.RegisterModule(tpl, params)`

155

**Output Extensions:** `.pb.validate.h`, `.pb.validate.cc`

156

157

Generated code pattern:

158

```cpp

159

// Header

160

namespace validate {

161

bool Validate(const Message& msg, std::string* error);

162

}

163

164

// Implementation

165

bool Validate(const Message& msg, std::string* error) {

166

// validation logic

167

return true;

168

}

169

```

170

171

Features:

172

- Separate header and implementation files

173

- String-based error reporting

174

- Integration with existing C++ protobuf code

175

176

### C++ No-Op Templates

177

178

C++ no-op templates generate stub validation functions that always return valid.

179

180

**Template Names:** `"h"`, `"cc"` (ccnop variant)

181

**Registration:** `ccnop.RegisterHeader(tpl, params)`, `ccnop.RegisterModule(tpl, params)`

182

**Output Extensions:** `.pb.validate.h`, `.pb.validate.cc`

183

184

Generated code pattern:

185

```cpp

186

// No-op validation - always returns true

187

bool Validate(const Message& msg, std::string* error) {

188

return true;

189

}

190

```

191

192

**Use Cases:**

193

- Placeholder validation during development

194

- Disabling validation for performance-critical code

195

- Maintaining API compatibility while bypassing validation

196

197

Features:

198

- Same interface as full C++ templates

199

- Zero validation logic - always passes

200

- Minimal code generation overhead

201

202

### Python Runtime

203

204

Python uses runtime code generation rather than compile-time templates.

205

206

**Module:** `protoc_gen_validate.validator`

207

**Approach:** JIT code generation with caching

208

209

Generated functions are created dynamically:

210

```python

211

def validate_Message(msg):

212

# dynamically generated validation logic

213

pass

214

```

215

216

Features:

217

- JIT compilation of validation functions

218

- LRU cache for performance

219

- Dynamic code execution with `exec()`

220

- Exception-based error reporting

221

222

## Template Utilities

223

224

### Shared Functions

225

226

All templates have access to shared utility functions:

227

228

```go { .api }

229

func RegisterFunctions(tpl *template.Template, params pgs.Parameters)

230

```

231

232

Registers common template functions for:

233

- Type conversion and formatting

234

- Rule processing and validation

235

- Code generation helpers

236

- Language-specific formatting

237

238

Common template functions include:

239

- String manipulation functions

240

- Type checking functions

241

- Rule evaluation helpers

242

- Import path generation

243

244

### Template Parameters

245

246

Templates receive PGS parameters for configuration:

247

248

**Common Parameters:**

249

- `lang`: Target language

250

- `module`: Go module path for imports

251

- `paths`: Path configuration for output

252

253

**Language-Specific Parameters:**

254

- Go: Module path, import style

255

- Java: Package structure, multi-file options

256

- C++: Namespace configuration

257

- Python: Runtime validation options

258

259

## Code Generation Process

260

261

### Template Processing Flow

262

263

1. PGS framework calls `Execute()` on validator module

264

2. Module determines target language and gets templates

265

3. For each proto file with validation rules:

266

- Module calls `CheckRules()` to validate rule consistency

267

- Templates are applied to generate code

268

- File paths are determined using `FilePathFor()`

269

- Generated code is added as artifacts

270

271

### Multi-File Generation

272

273

Java supports multi-file generation for better organization:

274

275

```go { .api }

276

func JavaMultiFilePath(f pgs.File, msg pgs.Message) *pgs.FilePath

277

```

278

279

Generates separate Java files for each message with validation rules.

280

281

**Parameters:**

282

- `f pgs.File`: Source proto file

283

- `msg pgs.Message`: Message to generate validator for

284

285

**Returns:** `*pgs.FilePath` - Path for message-specific validator file

286

287

### Template Customization

288

289

Templates can be customized through:

290

- Custom `RegisterFn` implementations

291

- Parameter-based configuration

292

- Language-specific template extensions

293

- Custom file path generation

294

295

## Error Handling

296

297

Template processing includes comprehensive error handling:

298

299

- **Rule Validation Errors**: Inconsistent or contradictory rules

300

- **Template Processing Errors**: Syntax or execution errors

301

- **File Generation Errors**: Output path or permission issues

302

- **Language-Specific Errors**: Type incompatibilities or feature limitations

303

304

All errors are reported through the PGS framework and cause protoc to exit with appropriate error codes.

305

306

## Performance Considerations

307

308

### Template Caching

309

310

Templates are created once per invocation and reused across files for performance.

311

312

### Code Generation Optimization

313

314

- Go: Uses efficient validation patterns with early returns

315

- Java: Leverages reflection caching for performance

316

- C++: Generates optimized validation loops

317

- Python: Uses LRU caching for compiled validation functions

318

319

### Memory Management

320

321

Templates are designed to minimize memory usage during generation:

322

- Streaming code generation where possible

323

- Efficient data structures for rule processing

324

- Cleanup of temporary data structures