or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-compilation.mdcollections-utilities.mdconfig-data.mdcore-language.mddependency-management.mdindex.mdio-file-processing.mdjson-processing.mdsql-database.mdtemplate-engines.mdtesting-apis.mdtime-date.mdtransform-annotations.mdxml-processing.md

transform-annotations.mddocs/

0

# Transform Annotations

1

2

Compile-time code generation annotations that automatically add common functionality like toString(), equals(), builders, immutability, and static compilation support. These AST transformations reduce boilerplate code and enhance developer productivity.

3

4

## Capabilities

5

6

### Compilation Control

7

8

Annotations that control how Groovy code is compiled and type-checked.

9

10

```java { .api }

11

@Target({ElementType.TYPE, ElementType.METHOD})

12

@Retention(RetentionPolicy.SOURCE)

13

@interface CompileStatic {

14

/**

15

* List of extensions to apply during static compilation.

16

*/

17

Class<? extends ExtensionMethodNode>[] extensions() default {};

18

19

/**

20

* Type checking mode to use.

21

*/

22

TypeCheckingMode value() default TypeCheckingMode.PASS;

23

}

24

25

@Target({ElementType.TYPE, ElementType.METHOD})

26

@Retention(RetentionPolicy.SOURCE)

27

@interface TypeChecked {

28

/**

29

* List of extensions to apply during type checking.

30

*/

31

Class<? extends TypeCheckingExtension>[] extensions() default {};

32

33

/**

34

* Type checking mode to use.

35

*/

36

TypeCheckingMode value() default TypeCheckingMode.PASS;

37

}

38

39

@Target({ElementType.LOCAL_VARIABLE, ElementType.FIELD})

40

@Retention(RetentionPolicy.SOURCE)

41

@interface Field {

42

/**

43

* Makes script variables accessible as fields.

44

*/

45

}

46

47

@Target({ElementType.TYPE})

48

@Retention(RetentionPolicy.SOURCE)

49

@interface PackageScope {

50

/**

51

* Makes a class package-private instead of public.

52

*/

53

}

54

55

@Target({ElementType.TYPE})

56

@Retention(RetentionPolicy.SOURCE)

57

@interface CompileDynamic {

58

/**

59

* Disables static compilation for this type or method.

60

*/

61

}

62

```

63

64

### Class Generation

65

66

Annotations that generate common class functionality automatically.

67

68

```java { .api }

69

@Target({ElementType.TYPE})

70

@Retention(RetentionPolicy.SOURCE)

71

@interface Immutable {

72

/**

73

* Properties to exclude from immutable treatment.

74

*/

75

String[] excludes() default {};

76

77

/**

78

* Whether to include fields in addition to properties.

79

*/

80

boolean includeFields() default false;

81

82

/**

83

* Whether to generate a copyWith method.

84

*/

85

boolean copyWith() default false;

86

87

/**

88

* Known immutable classes.

89

*/

90

Class<?>[] knownImmutableClasses() default {};

91

92

/**

93

* Known immutable classes by name.

94

*/

95

String[] knownImmutables() default {};

96

}

97

98

@Target({ElementType.TYPE})

99

@Retention(RetentionPolicy.SOURCE)

100

@interface Canonical {

101

/**

102

* Properties to exclude from generated methods.

103

*/

104

String[] excludes() default {};

105

106

/**

107

* Whether to include fields in generated methods.

108

*/

109

boolean includeFields() default false;

110

111

/**

112

* Whether to cache the hash code.

113

*/

114

boolean cache() default false;

115

116

/**

117

* Whether to use super class in equals/hashCode.

118

*/

119

boolean useCanEqual() default true;

120

}

121

122

@Target({ElementType.TYPE})

123

@Retention(RetentionPolicy.SOURCE)

124

@interface ToString {

125

/**

126

* Properties to exclude from toString.

127

*/

128

String[] excludes() default {};

129

130

/**

131

* Whether to include field names in output.

132

*/

133

boolean includeNames() default false;

134

135

/**

136

* Whether to include fields in addition to properties.

137

*/

138

boolean includeFields() default false;

139

140

/**

141

* Whether to include super class in toString.

142

*/

143

boolean includeSuper() default false;

144

145

/**

146

* Whether to ignore null values.

147

*/

148

boolean ignoreNulls() default false;

149

150

/**

151

* Whether to include package name in class name.

152

*/

153

boolean includePackage() default false;

154

155

/**

156

* Whether to cache the toString result.

157

*/

158

boolean cache() default false;

159

}

160

161

@Target({ElementType.TYPE})

162

@Retention(RetentionPolicy.SOURCE)

163

@interface EqualsAndHashCode {

164

/**

165

* Properties to exclude from equals/hashCode.

166

*/

167

String[] excludes() default {};

168

169

/**

170

* Whether to include fields in addition to properties.

171

*/

172

boolean includeFields() default false;

173

174

/**

175

* Whether to call super in equals/hashCode.

176

*/

177

boolean callSuper() default false;

178

179

/**

180

* Whether to use canEqual method.

181

*/

182

boolean useCanEqual() default true;

183

184

/**

185

* Whether to cache the hash code.

186

*/

187

boolean cache() default false;

188

}

189

```

190

191

### Constructor Generation

192

193

Annotations that generate constructors automatically.

194

195

```java { .api }

196

@Target({ElementType.TYPE})

197

@Retention(RetentionPolicy.SOURCE)

198

@interface TupleConstructor {

199

/**

200

* Properties to exclude from constructor.

201

*/

202

String[] excludes() default {};

203

204

/**

205

* Properties to include in constructor.

206

*/

207

String[] includes() default {};

208

209

/**

210

* Whether to include fields in addition to properties.

211

*/

212

boolean includeFields() default false;

213

214

/**

215

* Whether to include super properties.

216

*/

217

boolean includeSuper() default false;

218

219

/**

220

* Whether to call super constructor.

221

*/

222

boolean callSuper() default false;

223

224

/**

225

* Whether to force generation even if constructors exist.

226

*/

227

boolean force() default false;

228

229

/**

230

* Default values for constructor parameters.

231

*/

232

String[] defaults() default {};

233

}

234

235

@Target({ElementType.TYPE})

236

@Retention(RetentionPolicy.SOURCE)

237

@interface InheritConstructors {

238

/**

239

* Whether to inherit constructors from parent class.

240

*/

241

boolean constructorAnnotations() default false;

242

243

/**

244

* Whether to copy parameter annotations.

245

*/

246

boolean parameterAnnotations() default false;

247

}

248

249

@Target({ElementType.TYPE})

250

@Retention(RetentionPolicy.SOURCE)

251

@interface MapConstructor {

252

/**

253

* Properties to exclude from map constructor.

254

*/

255

String[] excludes() default {};

256

257

/**

258

* Properties to include in map constructor.

259

*/

260

String[] includes() default {};

261

262

/**

263

* Whether to include fields in addition to properties.

264

*/

265

boolean includeFields() default false;

266

267

/**

268

* Whether to include super properties.

269

*/

270

boolean includeSuper() default false;

271

272

/**

273

* Whether to generate a no-arg constructor.

274

*/

275

boolean noArg() default false;

276

277

/**

278

* Post-processing closure.

279

*/

280

Class<? extends Closure> post() default Closure.class;

281

}

282

```

283

284

### Builder Pattern

285

286

Annotations for generating builder pattern implementations.

287

288

```java { .api }

289

@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR})

290

@Retention(RetentionPolicy.SOURCE)

291

@interface Builder {

292

/**

293

* Builder strategy to use.

294

*/

295

Class<?> builderStrategy() default DefaultStrategy.class;

296

297

/**

298

* Builder class name prefix.

299

*/

300

String builderClassName() default "";

301

302

/**

303

* Builder method name.

304

*/

305

String builderMethodName() default "builder";

306

307

/**

308

* Build method name.

309

*/

310

String buildMethodName() default "build";

311

312

/**

313

* Properties to exclude from builder.

314

*/

315

String[] excludes() default {};

316

317

/**

318

* Properties to include in builder.

319

*/

320

String[] includes() default {};

321

322

/**

323

* Whether to include super properties.

324

*/

325

boolean includeSuper() default false;

326

327

/**

328

* Prefix for setter methods.

329

*/

330

String prefix() default "";

331

332

/**

333

* Whether to force generation.

334

*/

335

boolean force() default false;

336

}

337

```

338

339

### Field and Method Enhancement

340

341

Annotations that enhance fields and methods with additional behavior.

342

343

```java { .api }

344

@Target({ElementType.FIELD, ElementType.METHOD})

345

@Retention(RetentionPolicy.SOURCE)

346

@interface Lazy {

347

/**

348

* Whether to use soft references for lazy values.

349

*/

350

boolean soft() default false;

351

}

352

353

@Target({ElementType.FIELD})

354

@Retention(RetentionPolicy.SOURCE)

355

@interface Delegate {

356

/**

357

* Interfaces to delegate to.

358

*/

359

Class<?>[] interfaces() default {};

360

361

/**

362

* Methods to exclude from delegation.

363

*/

364

String[] excludes() default {};

365

366

/**

367

* Types of methods to exclude.

368

*/

369

String[] excludeTypes() default {};

370

371

/**

372

* Whether to include deprecated methods.

373

*/

374

boolean includeDeprecated() default true;

375

376

/**

377

* Whether to use parameter names in method signatures.

378

*/

379

boolean parameterAnnotations() default false;

380

381

/**

382

* Whether to copy method annotations.

383

*/

384

boolean methodAnnotations() default false;

385

}

386

387

@Target({ElementType.METHOD})

388

@Retention(RetentionPolicy.SOURCE)

389

@interface Memoized {

390

/**

391

* Maximum cache size.

392

*/

393

int maxCacheSize() default 0;

394

395

/**

396

* Whether to protect from recursion.

397

*/

398

boolean protectedFromRecursion() default false;

399

}

400

401

@Target({ElementType.METHOD})

402

@Retention(RetentionPolicy.SOURCE)

403

@interface TailRecursive {

404

/**

405

* Optimizes tail-recursive methods.

406

*/

407

}

408

```

409

410

### Synchronization

411

412

Annotations for thread-safe method execution.

413

414

```java { .api }

415

@Target({ElementType.METHOD})

416

@Retention(RetentionPolicy.SOURCE)

417

@interface Synchronized {

418

/**

419

* Lock field name to use for synchronization.

420

*/

421

String value() default "";

422

}

423

424

@Target({ElementType.METHOD})

425

@Retention(RetentionPolicy.SOURCE)

426

@interface WithReadLock {

427

/**

428

* Lock field name to use for read locking.

429

*/

430

String value() default "$reentrantlock";

431

}

432

433

@Target({ElementType.METHOD})

434

@Retention(RetentionPolicy.SOURCE)

435

@interface WithWriteLock {

436

/**

437

* Lock field name to use for write locking.

438

*/

439

String value() default "$reentrantlock";

440

}

441

```

442

443

### Bean Properties

444

445

Annotations for property binding and change notification.

446

447

```java { .api }

448

@Target({ElementType.FIELD, ElementType.TYPE})

449

@Retention(RetentionPolicy.SOURCE)

450

@interface Bindable {

451

/**

452

* Generates PropertyChangeSupport for bindable properties.

453

*/

454

}

455

456

@Target({ElementType.FIELD, ElementType.TYPE})

457

@Retention(RetentionPolicy.SOURCE)

458

@interface Vetoable {

459

/**

460

* Generates VetoableChangeSupport for vetoable properties.

461

*/

462

}

463

464

@Target({ElementType.TYPE})

465

@Retention(RetentionPolicy.SOURCE)

466

@interface ListenerList {

467

/**

468

* Generates listener list support.

469

*/

470

}

471

```

472

473

### Category Support

474

475

Annotations for category-based extensions.

476

477

```java { .api }

478

@Target({ElementType.TYPE})

479

@Retention(RetentionPolicy.SOURCE)

480

@interface Category {

481

/**

482

* Class to add methods to.

483

*/

484

Class<?> value();

485

}

486

487

@Target({ElementType.TYPE})

488

@Retention(RetentionPolicy.SOURCE)

489

@interface Mixin {

490

/**

491

* Mixin classes to apply.

492

*/

493

Class<?>[] value();

494

}

495

```

496

497

### Singleton Pattern

498

499

Annotation for generating singleton implementations.

500

501

```java { .api }

502

@Target({ElementType.TYPE})

503

@Retention(RetentionPolicy.SOURCE)

504

@interface Singleton {

505

/**

506

* Property name for singleton instance.

507

*/

508

String property() default "instance";

509

510

/**

511

* Whether to use lazy initialization.

512

*/

513

boolean lazy() default true;

514

515

/**

516

* Whether to make singleton strict (prevent inheritance).

517

*/

518

boolean strict() default true;

519

}

520

```

521

522

## Usage Examples

523

524

### Immutable Classes

525

526

```java

527

import groovy.transform.Immutable;

528

529

@Immutable

530

class Person {

531

String name;

532

int age;

533

List<String> hobbies;

534

}

535

536

// Usage

537

Person person = new Person("John", 30, ["reading", "hiking"]);

538

// person.name = "Jane"; // This would cause a compile error

539

540

// With copyWith

541

@Immutable(copyWith = true)

542

class Address {

543

String street;

544

String city;

545

String country;

546

}

547

548

Address address = new Address("123 Main St", "Anytown", "USA");

549

Address newAddress = address.copyWith(city: "New City");

550

```

551

552

### Builder Pattern

553

554

```java

555

import groovy.transform.builder.Builder;

556

557

@Builder

558

class Car {

559

String make;

560

String model;

561

int year;

562

String color;

563

boolean convertible;

564

}

565

566

// Usage

567

Car car = Car.builder()

568

.make("Toyota")

569

.model("Camry")

570

.year(2023)

571

.color("Blue")

572

.convertible(false)

573

.build();

574

```

575

576

### ToString and Equals Generation

577

578

```java

579

import groovy.transform.ToString;

580

import groovy.transform.EqualsAndHashCode;

581

582

@ToString(includeNames = true, includeFields = true)

583

@EqualsAndHashCode(includeFields = true)

584

class Book {

585

String title;

586

String author;

587

int pages;

588

private String isbn;

589

}

590

591

// Usage

592

Book book1 = new Book(title: "Groovy in Action", author: "Dierk König", pages: 500);

593

Book book2 = new Book(title: "Groovy in Action", author: "Dierk König", pages: 500);

594

595

System.out.println(book1.toString());

596

System.out.println(book1.equals(book2)); // true

597

```

598

599

### Lazy Initialization

600

601

```java

602

import groovy.transform.Lazy;

603

604

class DataProcessor {

605

@Lazy

606

private ExpensiveResource resource = new ExpensiveResource();

607

608

@Lazy(soft = true)

609

private List<String> cache = loadCacheData();

610

611

public void process() {

612

// resource is initialized only when first accessed

613

resource.doWork();

614

}

615

616

private List<String> loadCacheData() {

617

// Expensive operation

618

return Arrays.asList("data1", "data2", "data3");

619

}

620

}

621

```

622

623

### Memoization

624

625

```java

626

import groovy.transform.Memoized;

627

628

class Calculator {

629

@Memoized

630

public long fibonacci(int n) {

631

if (n <= 1) return n;

632

return fibonacci(n - 1) + fibonacci(n - 2);

633

}

634

635

@Memoized(maxCacheSize = 100)

636

public double expensiveCalculation(double x, double y) {

637

// Simulate expensive computation

638

Thread.sleep(1000);

639

return Math.pow(x, y);

640

}

641

}

642

643

// Usage

644

Calculator calc = new Calculator();

645

long fib = calc.fibonacci(40); // Calculated once, then cached

646

```

647

648

### Synchronization

649

650

```java

651

import groovy.transform.Synchronized;

652

import groovy.transform.WithReadLock;

653

import groovy.transform.WithWriteLock;

654

655

class ThreadSafeCounter {

656

private int count = 0;

657

private final Object lock = new Object();

658

659

@Synchronized("lock")

660

public void increment() {

661

count++;

662

}

663

664

@Synchronized("lock")

665

public int getCount() {

666

return count;

667

}

668

}

669

670

class ReadWriteExample {

671

private String data = "";

672

private final java.util.concurrent.locks.ReentrantReadWriteLock rwLock =

673

new java.util.concurrent.locks.ReentrantReadWriteLock();

674

675

@WithReadLock

676

public String getData() {

677

return data;

678

}

679

680

@WithWriteLock

681

public void setData(String newData) {

682

this.data = newData;

683

}

684

}

685

```

686

687

### Bindable Properties

688

689

```java

690

import groovy.transform.Bindable;

691

import java.beans.PropertyChangeListener;

692

import java.beans.PropertyChangeEvent;

693

694

@Bindable

695

class Model {

696

String name;

697

int value;

698

}

699

700

// Usage

701

Model model = new Model();

702

model.addPropertyChangeListener(new PropertyChangeListener() {

703

public void propertyChange(PropertyChangeEvent evt) {

704

System.out.println("Property " + evt.getPropertyName() +

705

" changed from " + evt.getOldValue() +

706

" to " + evt.getNewValue());

707

}

708

});

709

710

model.setName("New Name"); // Fires property change event

711

model.setValue(42); // Fires property change event

712

```

713

714

### Static Compilation

715

716

```java

717

import groovy.transform.CompileStatic;

718

import groovy.transform.TypeChecked;

719

720

@CompileStatic

721

class MathUtils {

722

public static int add(int a, int b) {

723

return a + b; // Statically compiled

724

}

725

726

@TypeChecked

727

public static double divide(double a, double b) {

728

if (b == 0) {

729

throw new IllegalArgumentException("Division by zero");

730

}

731

return a / b; // Type checked but dynamically compiled

732

}

733

}

734

```