or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-transforms.mdcli.mdcore-language.mdindex.mdjson.mdsql.mdswing.mdtemplates.mdxml.md

ast-transforms.mddocs/

0

# AST Transformations

1

2

Groovy's AST (Abstract Syntax Tree) transformations provide compile-time code generation and modification through annotations, enabling powerful metaprogramming capabilities without runtime overhead.

3

4

## Code Generation Transforms

5

6

### @ToString

7

8

Automatically generates toString() method implementation.

9

10

```groovy { .api }

11

@interface ToString {

12

String[] excludes() default {}

13

String[] includes() default {}

14

boolean includeNames() default false

15

boolean includeFields() default false

16

boolean includeSuper() default false

17

boolean includeSuperProperties() default false

18

boolean ignoreNulls() default false

19

boolean includePackage() default false

20

boolean cache() default false

21

boolean allProperties() default false

22

}

23

```

24

25

Usage examples:

26

```groovy

27

import groovy.transform.ToString

28

29

@ToString

30

class Person {

31

String name

32

int age

33

String email

34

}

35

36

@ToString(includeNames=true, excludes=['email'])

37

class Employee {

38

String name

39

int age

40

String email

41

String department

42

}

43

44

def person = new Person(name: 'John', age: 30, email: 'john@example.com')

45

println person.toString() // Person(John, 30, john@example.com)

46

47

def employee = new Employee(name: 'Jane', age: 25, email: 'jane@company.com', department: 'IT')

48

println employee.toString() // Employee(name:Jane, age:25, department:IT)

49

```

50

51

### @EqualsAndHashCode

52

53

Generates equals() and hashCode() methods with proper implementations.

54

55

```groovy { .api }

56

@interface EqualsAndHashCode {

57

String[] excludes() default {}

58

String[] includes() default {}

59

boolean callSuper() default false

60

boolean includeFields() default false

61

boolean cache() default false

62

boolean useCanEqual() default true

63

boolean allProperties() default false

64

}

65

```

66

67

Usage example:

68

```groovy

69

import groovy.transform.EqualsAndHashCode

70

71

@EqualsAndHashCode

72

class Point {

73

int x

74

int y

75

}

76

77

@EqualsAndHashCode(excludes=['id'])

78

class User {

79

String id

80

String name

81

String email

82

}

83

84

def p1 = new Point(x: 10, y: 20)

85

def p2 = new Point(x: 10, y: 20)

86

assert p1 == p2

87

assert p1.hashCode() == p2.hashCode()

88

```

89

90

### @TupleConstructor

91

92

Generates constructor accepting parameters for specified properties.

93

94

```groovy { .api }

95

@interface TupleConstructor {

96

String[] excludes() default {}

97

String[] includes() default {}

98

boolean includeFields() default false

99

boolean includeProperties() default true

100

boolean includeSuperFields() default false

101

boolean includeSuperProperties() default false

102

boolean callSuper() default false

103

boolean force() default false

104

boolean defaults() default true

105

boolean useSetters() default false

106

boolean allNames() default false

107

boolean allProperties() default false

108

}

109

```

110

111

Usage example:

112

```groovy

113

import groovy.transform.TupleConstructor

114

115

@TupleConstructor

116

class Book {

117

String title

118

String author

119

int year

120

}

121

122

@TupleConstructor(includes=['name', 'age'])

123

class Person {

124

String name

125

int age

126

String email = 'unknown@example.com'

127

}

128

129

def book = new Book('1984', 'George Orwell', 1949)

130

def person = new Person('John', 30)

131

```

132

133

## Design Pattern Transforms

134

135

### @Singleton

136

137

Implements the Singleton design pattern with various strategies.

138

139

```groovy { .api }

140

@interface Singleton {

141

String property() default 'instance'

142

boolean lazy() default true

143

boolean strict() default true

144

}

145

```

146

147

Usage examples:

148

```groovy

149

import groovy.transform.Singleton

150

151

@Singleton

152

class DatabaseConnection {

153

String url = 'jdbc:h2:mem:testdb'

154

155

void connect() {

156

println "Connecting to $url"

157

}

158

}

159

160

@Singleton(lazy=false, strict=false)

161

class Logger {

162

void log(String message) {

163

println "[${new Date()}] $message"

164

}

165

}

166

167

// Usage

168

DatabaseConnection.instance.connect()

169

Logger.instance.log('Application started')

170

```

171

172

### @Immutable

173

174

Creates immutable classes with defensive copying and validation.

175

176

```groovy { .api }

177

@interface Immutable {

178

String[] excludes() default {}

179

String[] includes() default {}

180

boolean copyWith() default false

181

boolean knownImmutableClasses() default false

182

String[] knownImmutables() default {}

183

}

184

```

185

186

Usage example:

187

```groovy

188

import groovy.transform.Immutable

189

190

@Immutable

191

class Point3D {

192

double x, y, z

193

}

194

195

@Immutable(copyWith=true)

196

class Person {

197

String name

198

int age

199

List<String> hobbies

200

}

201

202

def point = new Point3D(1.0, 2.0, 3.0)

203

def person = new Person('John', 30, ['reading', 'swimming'])

204

205

// Create modified copies

206

def olderPerson = person.copyWith(age: 31)

207

```

208

209

### @Builder

210

211

Implements the Builder pattern for object construction.

212

213

```groovy { .api }

214

@interface Builder {

215

String builderClassName() default ''

216

String builderMethodName() default 'builder'

217

String buildMethodName() default 'build'

218

String prefix() default ''

219

boolean includeSuperProperties() default false

220

boolean useSetters() default false

221

String[] excludes() default {}

222

String[] includes() default {}

223

boolean allNames() default false

224

boolean allProperties() default false

225

}

226

```

227

228

Usage example:

229

```groovy

230

import groovy.transform.builder.Builder

231

import groovy.transform.builder.ExternalStrategy

232

233

@Builder

234

class Computer {

235

String cpu

236

String memory

237

String storage

238

String graphics

239

}

240

241

@Builder(builderStrategy=ExternalStrategy, forClass=Person)

242

class PersonBuilder {}

243

244

// Usage

245

def computer = Computer.builder()

246

.cpu('Intel i7')

247

.memory('16GB')

248

.storage('1TB SSD')

249

.graphics('NVIDIA RTX')

250

.build()

251

```

252

253

## Behavior Modification Transforms

254

255

### @CompileStatic

256

257

Enables static compilation for improved performance and type safety.

258

259

```groovy { .api }

260

@interface CompileStatic {

261

TypeCheckingMode value() default TypeCheckingMode.PASS

262

String[] extensions() default {}

263

}

264

```

265

266

Usage example:

267

```groovy

268

import groovy.transform.CompileStatic

269

270

@CompileStatic

271

class Calculator {

272

int add(int a, int b) {

273

return a + b // Statically compiled

274

}

275

276

double multiply(double x, double y) {

277

return x * y // Type-safe operations

278

}

279

}

280

```

281

282

### @TypeChecked

283

284

Enables static type checking without full static compilation.

285

286

```groovy { .api }

287

@interface TypeChecked {

288

TypeCheckingMode value() default TypeCheckingMode.PASS

289

String[] extensions() default {}

290

}

291

```

292

293

Usage example:

294

```groovy

295

import groovy.transform.TypeChecked

296

297

@TypeChecked

298

class StringProcessor {

299

String process(String input) {

300

return input.toUpperCase().trim() // Type-checked at compile time

301

}

302

}

303

```

304

305

### @Memoized

306

307

Caches method results for improved performance with repeated calls.

308

309

```groovy { .api }

310

@interface Memoized {

311

int protectedCacheSize() default 0

312

int maxCacheSize() default 0

313

}

314

```

315

316

Usage example:

317

```groovy

318

import groovy.transform.Memoized

319

import groovy.transform.CompileStatic

320

321

@CompileStatic

322

class FibonacciCalculator {

323

@Memoized

324

long fibonacci(int n) {

325

if (n <= 1) return n

326

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

327

}

328

329

@Memoized(maxCacheSize=100)

330

double expensiveCalculation(double input) {

331

// Simulate expensive computation

332

Thread.sleep(1000)

333

return Math.pow(input, 3) + Math.sin(input)

334

}

335

}

336

```

337

338

### @Synchronized

339

340

Provides method-level synchronization with configurable lock objects.

341

342

```groovy { .api }

343

@interface Synchronized {

344

String value() default ''

345

}

346

```

347

348

Usage example:

349

```groovy

350

import groovy.transform.Synchronized

351

352

class Counter {

353

private int count = 0

354

private final Object lockA = new Object()

355

private final Object lockB = new Object()

356

357

@Synchronized

358

void increment() {

359

count++

360

}

361

362

@Synchronized('lockA')

363

void methodA() {

364

// Uses lockA for synchronization

365

}

366

367

@Synchronized('lockB')

368

void methodB() {

369

// Uses lockB for synchronization

370

}

371

372

@Synchronized

373

int getCount() {

374

return count

375

}

376

}

377

```

378

379

## Metaprogramming Transforms

380

381

### @Delegate

382

383

Implements the Delegation pattern by forwarding method calls.

384

385

```groovy { .api }

386

@interface Delegate {

387

Class[] excludeTypes() default {}

388

String[] excludes() default {}

389

String[] includes() default {}

390

boolean deprecated() default false

391

boolean allNames() default false

392

boolean methodAnnotations() default false

393

boolean parameterAnnotations() default false

394

boolean interfaces() default true

395

}

396

```

397

398

Usage example:

399

```groovy

400

import groovy.transform.Delegate

401

402

class EventManager {

403

@Delegate List<String> events = []

404

@Delegate(excludes=['clear']) Map<String, Object> properties = [:]

405

406

void logEvent(String event) {

407

println "Event logged: $event"

408

events.add(event)

409

}

410

}

411

412

def manager = new EventManager()

413

manager.add('startup') // Delegated to List

414

manager.put('version', '1.0') // Delegated to Map

415

// manager.clear() // Not available due to excludes

416

```

417

418

### @Category

419

420

Creates category classes for adding methods to existing types.

421

422

```groovy { .api }

423

@interface Category {

424

Class value()

425

}

426

```

427

428

Usage example:

429

```groovy

430

import groovy.transform.Category

431

432

@Category(String)

433

class StringExtensions {

434

boolean isPalindrome() {

435

return this == this.reverse()

436

}

437

438

String toCamelCase() {

439

return this.tokenize('_').collect {

440

it.toLowerCase().capitalize()

441

}.join('')

442

}

443

}

444

445

// Usage

446

use(StringExtensions) {

447

assert 'racecar'.isPalindrome()

448

assert 'hello_world'.toCamelCase() == 'HelloWorld'

449

}

450

```

451

452

### @Mixin

453

454

Adds mixin capabilities to classes.

455

456

```groovy { .api }

457

@interface Mixin {

458

Class[] value()

459

}

460

```

461

462

### @Trait

463

464

Defines and uses traits for multiple inheritance of behavior.

465

466

```groovy { .api }

467

@interface Trait {}

468

```

469

470

Usage example:

471

```groovy

472

trait Flyable {

473

void fly() {

474

println "${this.class.simpleName} is flying"

475

}

476

}

477

478

trait Swimmable {

479

void swim() {

480

println "${this.class.simpleName} is swimming"

481

}

482

}

483

484

class Duck implements Flyable, Swimmable {

485

String name

486

}

487

488

class Fish implements Swimmable {

489

String species

490

}

491

492

def duck = new Duck(name: 'Donald')

493

duck.fly() // Duck is flying

494

duck.swim() // Duck is swimming

495

496

def fish = new Fish(species: 'Goldfish')

497

fish.swim() // Fish is swimming

498

```

499

500

## Utility Transforms

501

502

### @Canonical

503

504

Combines @ToString, @EqualsAndHashCode, and @TupleConstructor.

505

506

```groovy { .api }

507

@interface Canonical {

508

String[] excludes() default {}

509

String[] includes() default {}

510

boolean includeFields() default false

511

boolean includeProperties() default true

512

boolean includeSuperFields() default false

513

boolean includeSuperProperties() default false

514

boolean callSuper() default false

515

boolean force() default false

516

boolean useSetters() default false

517

boolean allNames() default false

518

boolean allProperties() default false

519

}

520

```

521

522

Usage example:

523

```groovy

524

import groovy.transform.Canonical

525

526

@Canonical

527

class Product {

528

String name

529

BigDecimal price

530

String category

531

}

532

533

def product1 = new Product('Laptop', 999.99, 'Electronics')

534

def product2 = new Product('Laptop', 999.99, 'Electronics')

535

536

assert product1 == product2

537

println product1.toString()

538

```

539

540

### @InheritConstructors

541

542

Inherits constructors from the superclass.

543

544

```groovy { .api }

545

@interface InheritConstructors {

546

boolean constructorAnnotations() default false

547

boolean parameterAnnotations() default false

548

}

549

```

550

551

Usage example:

552

```groovy

553

import groovy.transform.InheritConstructors

554

555

class CustomException extends RuntimeException {

556

// Inherits all RuntimeException constructors

557

}

558

559

@InheritConstructors

560

class MyList extends ArrayList {

561

// Inherits all ArrayList constructors

562

563

void customMethod() {

564

println "Custom functionality"

565

}

566

}

567

```

568

569

## Custom AST Transformations

570

571

### Creating Custom Transforms

572

573

```groovy

574

import org.codehaus.groovy.transform.GroovyASTTransformation

575

import org.codehaus.groovy.transform.ASTTransformation

576

import org.codehaus.groovy.control.CompilePhase

577

import org.codehaus.groovy.control.SourceUnit

578

import org.codehaus.groovy.ast.ASTNode

579

import org.codehaus.groovy.ast.ClassNode

580

import org.codehaus.groovy.ast.MethodNode

581

582

@GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)

583

class LogMethodCallsTransformation implements ASTTransformation {

584

585

void visit(ASTNode[] nodes, SourceUnit source) {

586

// Custom transformation logic

587

nodes.each { node ->

588

if (node instanceof ClassNode) {

589

addLoggingToMethods(node)

590

}

591

}

592

}

593

594

private void addLoggingToMethods(ClassNode classNode) {

595

classNode.methods.each { MethodNode method ->

596

// Add logging statements to method bodies

597

// Implementation details...

598

}

599

}

600

}

601

602

// Usage annotation

603

@interface LogMethodCalls {}

604

```

605

606

### Local AST Transformations

607

608

```groovy

609

import org.codehaus.groovy.transform.GroovyASTTransformationClass

610

import java.lang.annotation.ElementType

611

import java.lang.annotation.Target

612

import java.lang.annotation.Retention

613

import java.lang.annotation.RetentionPolicy

614

615

@Retention(RetentionPolicy.SOURCE)

616

@Target([ElementType.TYPE])

617

@GroovyASTTransformationClass(["com.example.LogMethodCallsTransformation"])

618

@interface LogMethodCalls {}

619

620

// Apply to classes

621

@LogMethodCalls

622

class MyService {

623

void processData() {

624

// Method calls will be logged automatically

625

}

626

}

627

```

628

629

## Error Handling and Debugging

630

631

### Compilation Errors

632

633

```groovy

634

// Common AST transformation errors and solutions

635

636

// 1. Conflicting transformations

637

@ToString

638

@CompileStatic

639

class Example {

640

// Some combinations may cause issues

641

}

642

643

// 2. Missing dependencies

644

@Builder // Requires specific dependencies

645

class MyClass {

646

String property

647

}

648

649

// 3. Incorrect annotation usage

650

@Singleton(property="wrongType") // Should be String

651

class BadSingleton {}

652

```

653

654

### Debugging AST Transformations

655

656

```groovy

657

// Enable AST transformation debugging

658

System.setProperty("groovy.ast.debug", "true")

659

660

// Use AST viewer tools to inspect generated code

661

import org.codehaus.groovy.ast.ClassNode

662

import org.codehaus.groovy.control.CompilerConfiguration

663

664

def config = new CompilerConfiguration()

665

config.debug = true

666

config.verbose = true

667

668

// Examine generated bytecode

669

import groovy.transform.ToString

670

671

@ToString

672

class DebugExample {

673

String name

674

int value

675

}

676

677

// The generated toString method can be inspected

678

def example = new DebugExample(name: 'test', value: 42)

679

println example.toString()

680

```