or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-processing.mdindex.mdlanguage-support.mdmetrics.mdrule-framework.mdsymbols-types.md

language-support.mddocs/

0

# Language Support

1

2

PMD Java provides comprehensive language processing capabilities as the core Java language module within the PMD framework. It supports Java versions from 1.3 through Java 24 (including preview features), with sophisticated parsing, lexical analysis, copy-paste detection, and Javadoc processing.

3

4

## Capabilities

5

6

### Language Module

7

8

The `JavaLanguageModule` serves as the main entry point and integration layer with the PMD framework.

9

10

```java { .api }

11

/**

12

* Java language module for the PMD framework

13

*/

14

public class JavaLanguageModule extends LanguageModuleBase

15

implements PmdCapableLanguage, CpdCapableLanguage {

16

17

/**

18

* Returns the singleton instance of the Java language module

19

*/

20

public static JavaLanguageModule getInstance();

21

22

/**

23

* Returns the Language instance for Java

24

*/

25

@Override

26

public Language getLanguage();

27

28

/**

29

* Creates a new property bundle for configuring Java analysis

30

*/

31

@Override

32

public LanguagePropertyBundle newPropertyBundle();

33

34

/**

35

* Creates a language processor for parsing and rule execution

36

*/

37

@Override

38

public LanguageProcessor createProcessor(LanguagePropertyBundle bundle);

39

40

/**

41

* Creates a CPD lexer for copy-paste detection

42

*/

43

@Override

44

public CpdLexer createCpdLexer(LanguagePropertyBundle bundle);

45

46

/**

47

* Returns the default file extensions for Java files

48

*/

49

@Override

50

public List<String> getExtensions();

51

}

52

```

53

54

### Language Properties

55

56

```java { .api }

57

/**

58

* Configuration properties for Java language processing

59

*/

60

public interface LanguagePropertyBundle {

61

/**

62

* Gets the language version to use for parsing

63

*/

64

LanguageVersion getLanguageVersion();

65

66

/**

67

* Sets the language version

68

*/

69

void setLanguageVersion(LanguageVersion version);

70

71

/**

72

* Gets a property value by descriptor

73

*/

74

<T> T getProperty(PropertyDescriptor<T> descriptor);

75

76

/**

77

* Sets a property value

78

*/

79

<T> void setProperty(PropertyDescriptor<T> descriptor, T value);

80

81

/**

82

* Returns true if the property is defined

83

*/

84

boolean isPropertyDefined(PropertyDescriptor<?> descriptor);

85

}

86

```

87

88

### Java Language Versions

89

90

```java { .api }

91

/**

92

* Supported Java language versions

93

*/

94

public class JavaLanguageModule extends LanguageModuleBase {

95

96

// Static version constants for all supported Java versions

97

public static final LanguageVersion JAVA_1_3;

98

public static final LanguageVersion JAVA_1_4;

99

public static final LanguageVersion JAVA_1_5; // Java 5 (generics, annotations)

100

public static final LanguageVersion JAVA_1_6; // Java 6

101

public static final LanguageVersion JAVA_1_7; // Java 7 (diamond operator, multi-catch)

102

public static final LanguageVersion JAVA_1_8; // Java 8 (lambdas, streams, default methods)

103

public static final LanguageVersion JAVA_9; // Java 9 (modules, private interface methods)

104

public static final LanguageVersion JAVA_10; // Java 10 (var keyword)

105

public static final LanguageVersion JAVA_11; // Java 11 (LTS)

106

public static final LanguageVersion JAVA_12; // Java 12 (switch expressions preview)

107

public static final LanguageVersion JAVA_13; // Java 13 (text blocks preview)

108

public static final LanguageVersion JAVA_14; // Java 14 (records preview, pattern matching)

109

public static final LanguageVersion JAVA_15; // Java 15 (text blocks, sealed classes preview)

110

public static final LanguageVersion JAVA_16; // Java 16 (records, pattern matching)

111

public static final LanguageVersion JAVA_17; // Java 17 (LTS, sealed classes)

112

public static final LanguageVersion JAVA_18; // Java 18 (UTF-8 by default)

113

public static final LanguageVersion JAVA_19; // Java 19 (virtual threads preview)

114

public static final LanguageVersion JAVA_20; // Java 20 (scoped values preview)

115

public static final LanguageVersion JAVA_21; // Java 21 (LTS, virtual threads, pattern matching)

116

public static final LanguageVersion JAVA_22; // Java 22 (unnamed patterns, string templates preview)

117

public static final LanguageVersion JAVA_23; // Java 23 (primitive types in patterns preview)

118

public static final LanguageVersion JAVA_24; // Java 24 (latest supported)

119

120

/**

121

* Returns the default Java version (latest stable LTS)

122

*/

123

@Override

124

public LanguageVersion getDefaultVersion();

125

126

/**

127

* Returns all supported language versions

128

*/

129

@Override

130

public List<LanguageVersion> getVersions();

131

}

132

```

133

134

## Parser and Lexer Creation

135

136

### Language Processor

137

138

```java { .api }

139

/**

140

* Main language processor for Java source code analysis

141

*/

142

public class JavaLanguageProcessor implements LanguageProcessor {

143

144

/**

145

* Processes a source file through the complete analysis pipeline

146

*/

147

@Override

148

public void processSource(TextFile sourceFile, RuleSet ruleSet, RuleContext ruleContext);

149

150

/**

151

* Creates analysis services (symbol resolution, type system, etc.)

152

*/

153

@Override

154

public AnalysisServices services();

155

156

/**

157

* Returns the language version being used

158

*/

159

public LanguageVersion getLanguageVersion();

160

}

161

162

/**

163

* Services provided during language processing

164

*/

165

public interface AnalysisServices {

166

/**

167

* Gets the symbol resolver for cross-reference analysis

168

*/

169

SymbolResolver getSymbolResolver();

170

171

/**

172

* Gets the type resolver for type analysis

173

*/

174

TypeResolver getTypeResolver();

175

176

/**

177

* Gets the complete semantic model

178

*/

179

SemanticModel getSemanticModel();

180

181

/**

182

* Gets the parser for creating ASTs

183

*/

184

Parser getParser();

185

}

186

```

187

188

### Parser Interface

189

190

```java { .api }

191

/**

192

* Java parser for creating Abstract Syntax Trees

193

*/

194

public interface Parser {

195

/**

196

* Parses source text into an AST

197

*/

198

ASTCompilationUnit parse(String sourceText, TextFile textFile);

199

200

/**

201

* Parses source text with custom parsing options

202

*/

203

ASTCompilationUnit parse(String sourceText, TextFile textFile, ParserOptions options);

204

205

/**

206

* Returns the language version used by this parser

207

*/

208

LanguageVersion getLanguageVersion();

209

}

210

211

/**

212

* Options for configuring parsing behavior

213

*/

214

public interface ParserOptions {

215

/**

216

* Whether to skip parsing errors and continue

217

*/

218

boolean isRecoverFromErrors();

219

220

/**

221

* Whether to suppress parser warnings

222

*/

223

boolean isSuppressWarnings();

224

225

/**

226

* Whether to parse Javadoc comments

227

*/

228

boolean isParseJavadoc();

229

230

/**

231

* Whether to keep tokens for exact source reconstruction

232

*/

233

boolean isKeepTokens();

234

}

235

```

236

237

### Lexer Support

238

239

```java { .api }

240

/**

241

* Lexical analyzer for Java source code

242

*/

243

public interface JavaLexer {

244

/**

245

* Tokenizes the input source

246

*/

247

List<JavaToken> tokenize(String source);

248

249

/**

250

* Returns the next token from the input

251

*/

252

JavaToken nextToken();

253

254

/**

255

* Returns true if there are more tokens

256

*/

257

boolean hasMoreTokens();

258

259

/**

260

* Gets the current position in the source

261

*/

262

Position getCurrentPosition();

263

}

264

265

/**

266

* Represents a Java language token

267

*/

268

public interface JavaToken {

269

/**

270

* Gets the token type (keyword, identifier, literal, etc.)

271

*/

272

TokenKind getKind();

273

274

/**

275

* Gets the token text

276

*/

277

String getText();

278

279

/**

280

* Gets the start position in source

281

*/

282

Position getBeginPosition();

283

284

/**

285

* Gets the end position in source

286

*/

287

Position getEndPosition();

288

289

/**

290

* Returns true if this is a keyword token

291

*/

292

boolean isKeyword();

293

294

/**

295

* Returns true if this is an identifier token

296

*/

297

boolean isIdentifier();

298

299

/**

300

* Returns true if this is a literal token

301

*/

302

boolean isLiteral();

303

}

304

```

305

306

## Copy-Paste Detection (CPD)

307

308

### CPD Lexer

309

310

```java { .api }

311

/**

312

* Specialized lexer for copy-paste detection analysis

313

*/

314

public class JavaCpdLexer implements CpdLexer {

315

316

/**

317

* Tokenizes source code for CPD analysis

318

*/

319

@Override

320

public void tokenize(SourceCode sourceCode, Tokens tokens);

321

322

/**

323

* Creates CPD lexer with default settings

324

*/

325

public JavaCpdLexer();

326

327

/**

328

* Creates CPD lexer with custom properties

329

*/

330

public JavaCpdLexer(LanguagePropertyBundle bundle);

331

}

332

333

/**

334

* Configuration properties for CPD analysis

335

*/

336

public class JavaCpdLexer implements CpdLexer {

337

338

// Property descriptors for CPD configuration

339

public static final PropertyDescriptor<Boolean> IGNORE_LITERALS;

340

public static final PropertyDescriptor<Boolean> IGNORE_IDENTIFIERS;

341

public static final PropertyDescriptor<Boolean> IGNORE_ANNOTATIONS;

342

public static final PropertyDescriptor<String> ANONYMIZE_LITERALS;

343

public static final PropertyDescriptor<String> ANONYMIZE_IDENTIFIERS;

344

}

345

```

346

347

### CPD Token Processing

348

349

```java { .api }

350

/**

351

* Represents a token in CPD analysis

352

*/

353

public interface CpdToken {

354

/**

355

* Gets the token text (possibly anonymized)

356

*/

357

String getText();

358

359

/**

360

* Gets the line number

361

*/

362

int getBeginLine();

363

364

/**

365

* Gets the column number

366

*/

367

int getBeginColumn();

368

369

/**

370

* Gets the end line number

371

*/

372

int getEndLine();

373

374

/**

375

* Gets the end column number

376

*/

377

int getEndColumn();

378

379

/**

380

* Returns true if this token should be ignored for CPD

381

*/

382

boolean isIgnored();

383

}

384

385

/**

386

* Collection of tokens for CPD analysis

387

*/

388

public interface Tokens extends Iterable<CpdToken> {

389

/**

390

* Adds a new token

391

*/

392

void add(String tokenText, int beginLine, int beginColumn, int endLine, int endColumn);

393

394

/**

395

* Gets the number of tokens

396

*/

397

int size();

398

399

/**

400

* Gets token at specific index

401

*/

402

CpdToken get(int index);

403

}

404

```

405

406

### CPD Suppression

407

408

```java { .api }

409

/**

410

* Support for suppressing CPD analysis in code regions

411

*/

412

public class JavaCpdLexer implements CpdLexer {

413

414

// Annotation-based suppression

415

public static final String CPD_START = "CPD-START";

416

public static final String CPD_END = "CPD-END";

417

418

/**

419

* Checks if CPD suppression is active at the current position

420

*/

421

protected boolean isCpdSuppressed(int line);

422

423

/**

424

* Processes suppression annotations in comments

425

*/

426

protected void processCpdSuppression(String commentText, int line);

427

}

428

```

429

430

**CPD Suppression Example:**

431

```java

432

public class MyClass {

433

434

// CPD-START

435

public void templateMethod1() {

436

// This code block will be ignored by CPD

437

setup();

438

process();

439

cleanup();

440

}

441

442

public void templateMethod2() {

443

// This similar code block will also be ignored

444

setup();

445

process();

446

cleanup();

447

}

448

// CPD-END

449

450

private void setup() { /* ... */ }

451

private void process() { /* ... */ }

452

private void cleanup() { /* ... */ }

453

}

454

```

455

456

## Javadoc Processing

457

458

### Javadoc Tags Support

459

460

```java { .api }

461

/**

462

* Standard Javadoc tags recognized by the parser

463

*/

464

public final class JavadocTag {

465

466

// Standard block tags

467

public static final JavadocTag AUTHOR = new JavadocTag("author");

468

public static final JavadocTag SINCE = new JavadocTag("since");

469

public static final JavadocTag VERSION = new JavadocTag("version");

470

public static final JavadocTag DEPRECATED = new JavadocTag("deprecated");

471

public static final JavadocTag PARAM = new JavadocTag("param");

472

public static final JavadocTag THROWS = new JavadocTag("throws");

473

public static final JavadocTag EXCEPTION = new JavadocTag("exception");

474

public static final JavadocTag RETURN = new JavadocTag("return");

475

public static final JavadocTag RETURNS = new JavadocTag("returns");

476

public static final JavadocTag SEE = new JavadocTag("see");

477

public static final JavadocTag LINK = new JavadocTag("link");

478

public static final JavadocTag LINKPLAIN = new JavadocTag("linkplain");

479

public static final JavadocTag VALUE = new JavadocTag("value");

480

public static final JavadocTag CODE = new JavadocTag("code");

481

public static final JavadocTag LITERAL = new JavadocTag("literal");

482

483

/**

484

* Creates or retrieves a tag instance for the given identifier

485

*/

486

public static JavadocTag tagFor(String tagId);

487

488

/**

489

* Returns all known tag identifiers

490

*/

491

public static Set<String> allTagIds();

492

493

/**

494

* Gets the tag identifier without @ prefix

495

*/

496

public String getTagId();

497

}

498

```

499

500

### Javadoc AST Nodes

501

502

```java { .api }

503

/**

504

* AST node representing a Javadoc comment

505

*/

506

public final class ASTJavadocComment extends AbstractJavaNode {

507

/**

508

* Gets the description text (before any tags)

509

*/

510

String getDescription();

511

512

/**

513

* Gets all Javadoc tags in this comment

514

*/

515

List<ASTJavadocTag> getTags();

516

517

/**

518

* Gets tags of a specific type

519

*/

520

List<ASTJavadocTag> getTags(JavadocTag tagType);

521

522

/**

523

* Gets the first tag of the specified type

524

*/

525

ASTJavadocTag getFirstTag(JavadocTag tagType);

526

527

/**

528

* Returns true if this Javadoc has the specified tag

529

*/

530

boolean hasTag(JavadocTag tagType);

531

}

532

533

/**

534

* AST node representing a Javadoc tag (@param, @return, etc.)

535

*/

536

public final class ASTJavadocTag extends AbstractJavaNode {

537

/**

538

* Gets the tag type

539

*/

540

JavadocTag getTag();

541

542

/**

543

* Gets the tag arguments (parameter name for @param, etc.)

544

*/

545

List<String> getArguments();

546

547

/**

548

* Gets the description text for this tag

549

*/

550

String getDescription();

551

552

/**

553

* Returns true if this tag has arguments

554

*/

555

boolean hasArguments();

556

}

557

```

558

559

## Multi-Version Support

560

561

### Version-Specific Features

562

563

```java { .api }

564

/**

565

* Version capability checking for language features

566

*/

567

public interface LanguageVersion {

568

/**

569

* Gets the version string (e.g., "1.8", "11", "17")

570

*/

571

String getVersion();

572

573

/**

574

* Gets the short name (e.g., "Java 8", "Java 17")

575

*/

576

String getShortName();

577

578

/**

579

* Gets the full name (e.g., "Java 1.8", "Java 17")

580

*/

581

String getName();

582

583

/**

584

* Compares version ordering

585

*/

586

int compareToVersion(String version);

587

588

/**

589

* Returns true if this version supports the specified feature

590

*/

591

boolean supportsFeature(JavaFeature feature);

592

}

593

594

/**

595

* Java language features by version

596

*/

597

public enum JavaFeature {

598

// Java 5 features

599

GENERICS(JavaLanguageModule.JAVA_1_5),

600

ANNOTATIONS(JavaLanguageModule.JAVA_1_5),

601

ENHANCED_FOR(JavaLanguageModule.JAVA_1_5),

602

VARARGS(JavaLanguageModule.JAVA_1_5),

603

AUTOBOXING(JavaLanguageModule.JAVA_1_5),

604

605

// Java 7 features

606

DIAMOND_OPERATOR(JavaLanguageModule.JAVA_1_7),

607

MULTI_CATCH(JavaLanguageModule.JAVA_1_7),

608

TRY_WITH_RESOURCES(JavaLanguageModule.JAVA_1_7),

609

610

// Java 8 features

611

LAMBDA_EXPRESSIONS(JavaLanguageModule.JAVA_1_8),

612

METHOD_REFERENCES(JavaLanguageModule.JAVA_1_8),

613

DEFAULT_METHODS(JavaLanguageModule.JAVA_1_8),

614

STREAMS(JavaLanguageModule.JAVA_1_8),

615

616

// Java 9 features

617

MODULES(JavaLanguageModule.JAVA_9),

618

PRIVATE_INTERFACE_METHODS(JavaLanguageModule.JAVA_9),

619

620

// Java 10 features

621

LOCAL_VARIABLE_TYPE_INFERENCE(JavaLanguageModule.JAVA_10), // var keyword

622

623

// Java 14 features

624

SWITCH_EXPRESSIONS(JavaLanguageModule.JAVA_14),

625

RECORDS_PREVIEW(JavaLanguageModule.JAVA_14),

626

PATTERN_MATCHING_INSTANCEOF_PREVIEW(JavaLanguageModule.JAVA_14),

627

628

// Java 15 features

629

TEXT_BLOCKS(JavaLanguageModule.JAVA_15),

630

SEALED_CLASSES_PREVIEW(JavaLanguageModule.JAVA_15),

631

632

// Java 16 features

633

RECORDS(JavaLanguageModule.JAVA_16),

634

PATTERN_MATCHING_INSTANCEOF(JavaLanguageModule.JAVA_16),

635

636

// Java 17 features (LTS)

637

SEALED_CLASSES(JavaLanguageModule.JAVA_17),

638

639

// Java 21 features (LTS)

640

PATTERN_MATCHING_SWITCH(JavaLanguageModule.JAVA_21),

641

RECORD_PATTERNS(JavaLanguageModule.JAVA_21),

642

VIRTUAL_THREADS(JavaLanguageModule.JAVA_21),

643

644

// Java 22+ preview features

645

STRING_TEMPLATES_PREVIEW(JavaLanguageModule.JAVA_22),

646

UNNAMED_PATTERNS_PREVIEW(JavaLanguageModule.JAVA_22);

647

648

private final LanguageVersion introducedIn;

649

650

JavaFeature(LanguageVersion version) {

651

this.introducedIn = version;

652

}

653

654

public LanguageVersion getIntroducedIn() {

655

return introducedIn;

656

}

657

}

658

```

659

660

### Version-Aware Parsing

661

662

```java { .api }

663

/**

664

* Parser factory that creates version-specific parsers

665

*/

666

public class JavaParserFactory {

667

668

/**

669

* Creates a parser for the specified Java version

670

*/

671

public static Parser createParser(LanguageVersion version);

672

673

/**

674

* Creates a parser with custom options

675

*/

676

public static Parser createParser(LanguageVersion version, ParserOptions options);

677

678

/**

679

* Returns the default parser for the latest Java version

680

*/

681

public static Parser createDefaultParser();

682

}

683

```

684

685

## Usage Examples

686

687

### Basic Language Module Setup

688

689

```java

690

// Get the Java language module instance

691

JavaLanguageModule javaModule = JavaLanguageModule.getInstance();

692

693

// Create property bundle for Java 17

694

LanguagePropertyBundle bundle = javaModule.newPropertyBundle();

695

bundle.setLanguageVersion(JavaLanguageModule.JAVA_17);

696

697

// Create language processor

698

LanguageProcessor processor = javaModule.createProcessor(bundle);

699

700

// Create CPD lexer

701

CpdLexer cpdLexer = javaModule.createCpdLexer(bundle);

702

```

703

704

### Version-Specific Feature Detection

705

706

```java

707

// Check if current version supports specific features

708

public class FeatureChecker {

709

710

public void checkFeatureSupport(LanguageVersion version) {

711

System.out.println("Checking features for " + version.getName());

712

713

// Check for modern features

714

if (version.supportsFeature(JavaFeature.LAMBDA_EXPRESSIONS)) {

715

System.out.println("✓ Lambda expressions supported");

716

}

717

718

if (version.supportsFeature(JavaFeature.RECORDS)) {

719

System.out.println("✓ Records supported");

720

}

721

722

if (version.supportsFeature(JavaFeature.SEALED_CLASSES)) {

723

System.out.println("✓ Sealed classes supported");

724

}

725

726

if (version.supportsFeature(JavaFeature.PATTERN_MATCHING_SWITCH)) {

727

System.out.println("✓ Pattern matching in switch supported");

728

}

729

730

// Check version comparisons

731

if (version.compareToVersion("17") >= 0) {

732

System.out.println("✓ LTS version 17+ features available");

733

}

734

}

735

}

736

```

737

738

### Custom Parser Configuration

739

740

```java

741

// Create parser with custom options

742

public class CustomParserExample {

743

744

public ASTCompilationUnit parseWithOptions(String sourceCode, String filename) {

745

// Create custom parser options

746

ParserOptions options = new ParserOptions() {

747

@Override

748

public boolean isRecoverFromErrors() {

749

return true; // Continue parsing despite errors

750

}

751

752

@Override

753

public boolean isSuppressWarnings() {

754

return false; // Show parser warnings

755

}

756

757

@Override

758

public boolean isParseJavadoc() {

759

return true; // Parse Javadoc comments

760

}

761

762

@Override

763

public boolean isKeepTokens() {

764

return true; // Keep tokens for exact reconstruction

765

}

766

};

767

768

// Create parser for Java 21

769

Parser parser = JavaParserFactory.createParser(

770

JavaLanguageModule.JAVA_21,

771

options

772

);

773

774

// Parse the source code

775

TextFile textFile = TextFile.forCharSeq(filename, sourceCode);

776

return parser.parse(sourceCode, textFile, options);

777

}

778

}

779

```

780

781

### CPD Configuration

782

783

```java

784

// Configure CPD lexer for copy-paste detection

785

public class CpdConfiguration {

786

787

public void configureCpdLexer() {

788

// Create property bundle for CPD

789

LanguagePropertyBundle bundle = JavaLanguageModule.getInstance().newPropertyBundle();

790

bundle.setLanguageVersion(JavaLanguageModule.JAVA_17);

791

792

// Configure CPD properties

793

bundle.setProperty(JavaCpdLexer.IGNORE_LITERALS, true);

794

bundle.setProperty(JavaCpdLexer.IGNORE_IDENTIFIERS, false);

795

bundle.setProperty(JavaCpdLexer.IGNORE_ANNOTATIONS, true);

796

bundle.setProperty(JavaCpdLexer.ANONYMIZE_LITERALS, "LITERAL");

797

bundle.setProperty(JavaCpdLexer.ANONYMIZE_IDENTIFIERS, "IDENTIFIER");

798

799

// Create CPD lexer with configuration

800

CpdLexer cpdLexer = JavaLanguageModule.getInstance().createCpdLexer(bundle);

801

802

// Use lexer for tokenization

803

SourceCode sourceCode = /* ... */;

804

Tokens tokens = new Tokens();

805

cpdLexer.tokenize(sourceCode, tokens);

806

807

System.out.println("Generated " + tokens.size() + " tokens for CPD analysis");

808

}

809

}

810

```

811

812

### Javadoc Processing

813

814

```java

815

// Process Javadoc comments in parsed AST

816

public class JavadocProcessor extends JavaVisitorBase<Void, Void> {

817

818

@Override

819

public Void visit(ASTMethodDeclaration node, Void data) {

820

// Get Javadoc comment if present

821

ASTJavadocComment javadoc = node.getJavadocComment();

822

823

if (javadoc != null) {

824

System.out.println("Method: " + node.getName());

825

System.out.println("Description: " + javadoc.getDescription());

826

827

// Process @param tags

828

for (ASTJavadocTag paramTag : javadoc.getTags(JavadocTag.PARAM)) {

829

List<String> args = paramTag.getArguments();

830

if (!args.isEmpty()) {

831

String paramName = args.get(0);

832

String description = paramTag.getDescription();

833

System.out.println(" @param " + paramName + ": " + description);

834

}

835

}

836

837

// Process @return tag

838

ASTJavadocTag returnTag = javadoc.getFirstTag(JavadocTag.RETURN);

839

if (returnTag != null) {

840

System.out.println(" @return: " + returnTag.getDescription());

841

}

842

843

// Check for @throws tags

844

for (ASTJavadocTag throwsTag : javadoc.getTags(JavadocTag.THROWS)) {

845

List<String> args = throwsTag.getArguments();

846

if (!args.isEmpty()) {

847

String exceptionType = args.get(0);

848

String description = throwsTag.getDescription();

849

System.out.println(" @throws " + exceptionType + ": " + description);

850

}

851

}

852

}

853

854

return super.visit(node, data);

855

}

856

857

@Override

858

public Void visit(ASTClassDeclaration node, Void data) {

859

ASTJavadocComment javadoc = node.getJavadocComment();

860

861

if (javadoc != null) {

862

// Check for deprecation

863

if (javadoc.hasTag(JavadocTag.DEPRECATED)) {

864

ASTJavadocTag deprecatedTag = javadoc.getFirstTag(JavadocTag.DEPRECATED);

865

System.out.println("Class " + node.getSimpleName() + " is deprecated: " +

866

deprecatedTag.getDescription());

867

}

868

869

// Check for @since tag

870

ASTJavadocTag sinceTag = javadoc.getFirstTag(JavadocTag.SINCE);

871

if (sinceTag != null) {

872

System.out.println("Available since: " + sinceTag.getDescription());

873

}

874

}

875

876

return super.visit(node, data);

877

}

878

}

879

```

880

881

### Integration with PMD Framework

882

883

```java

884

// Complete integration example

885

public class JavaAnalysisIntegration {

886

887

public void analyzeJavaFile(String filePath, String sourceCode) {

888

try {

889

// 1. Get Java language module

890

JavaLanguageModule javaModule = JavaLanguageModule.getInstance();

891

892

// 2. Configure for Java 17

893

LanguagePropertyBundle bundle = javaModule.newPropertyBundle();

894

bundle.setLanguageVersion(JavaLanguageModule.JAVA_17);

895

896

// 3. Create language processor

897

LanguageProcessor processor = javaModule.createProcessor(bundle);

898

899

// 4. Get analysis services

900

AnalysisServices services = processor.services();

901

Parser parser = services.getParser();

902

903

// 5. Parse source code

904

TextFile textFile = TextFile.forCharSeq(filePath, sourceCode);

905

ASTCompilationUnit ast = parser.parse(sourceCode, textFile);

906

907

// 6. Access semantic information

908

JSymbolTable symbolTable = ast.getSymbolTable();

909

TypeSystem typeSystem = ast.getTypeSystem();

910

911

// 7. Analyze the AST

912

MyAnalysisVisitor visitor = new MyAnalysisVisitor(symbolTable, typeSystem);

913

ast.acceptVisitor(visitor, null);

914

915

System.out.println("Analysis completed for: " + filePath);

916

917

} catch (Exception e) {

918

System.err.println("Analysis failed: " + e.getMessage());

919

}

920

}

921

922

private static class MyAnalysisVisitor extends JavaVisitorBase<Void, Void> {

923

private final JSymbolTable symbolTable;

924

private final TypeSystem typeSystem;

925

926

public MyAnalysisVisitor(JSymbolTable symbolTable, TypeSystem typeSystem) {

927

this.symbolTable = symbolTable;

928

this.typeSystem = typeSystem;

929

}

930

931

@Override

932

public Void visit(ASTMethodCall node, Void data) {

933

// Analyze method call with full semantic information

934

JMethodSymbol method = node.getMethodType();

935

JTypeMirror returnType = node.getTypeMirror();

936

937

System.out.println("Method call: " + node.getMethodName() +

938

" returns " + returnType);

939

940

return super.visit(node, data);

941

}

942

}

943

}

944

```