or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

ast-processing.mdcopy-paste-detection.mdcore-analysis.mdindex.mdlanguage-framework.mdproperties-system.mdrendering-system.mdreporting-system.mdrule-system.mdutilities.md

language-framework.mddocs/

0

# Language Framework

1

2

The Language Framework provides modular support for multiple programming languages within PMD. It enables language detection, version management, extension handling, and language-specific configuration through a registry-based architecture.

3

4

## Capabilities

5

6

### Language Interface

7

8

Core interface representing a programming language module with metadata, version support, and file extension handling.

9

10

```java { .api }

11

/**

12

* Core interface representing a programming language module.

13

* Provides metadata, version support, and file extension handling.

14

*/

15

public interface Language extends Comparable<Language> {

16

17

/**

18

* Get full language name (e.g., "Java", "JavaScript")

19

* @return Full descriptive name of the language

20

*/

21

String getName();

22

23

/**

24

* Get short/acronym name (e.g., "Java", "JS")

25

* @return Short name or acronym for the language

26

*/

27

String getShortName();

28

29

/**

30

* Get unique language ID (e.g., "java", "javascript")

31

* @return Unique identifier for the language (lowercase)

32

*/

33

String getId();

34

35

/**

36

* Get base language ID for dialect languages (experimental)

37

* @return Base language ID if this is a dialect, null otherwise

38

*/

39

@Nullable String getBaseLanguageId();

40

41

/**

42

* Check if this language is a dialect of another language (experimental)

43

* @param language Language to check against

44

* @return true if this language is a dialect of the given language

45

*/

46

boolean isDialectOf(Language language);

47

48

/**

49

* Get supported file extensions (without dots)

50

* @return List of file extensions this language handles

51

*/

52

List<String> getExtensions();

53

54

/**

55

* Check if language handles specific file extension

56

* @param extensionWithoutDot File extension without the dot prefix

57

* @return true if language supports the extension

58

*/

59

boolean hasExtension(String extensionWithoutDot);

60

61

/**

62

* Get all supported language versions

63

* @return List of all LanguageVersion instances for this language

64

*/

65

List<LanguageVersion> getVersions();

66

67

/**

68

* Get latest/newest language version

69

* @return Most recent LanguageVersion available

70

*/

71

LanguageVersion getLatestVersion();

72

73

/**

74

* Get all version names and aliases

75

* @return Set of all version identifiers and aliases

76

*/

77

Set<String> getVersionNamesAndAliases();

78

79

/**

80

* Check if specific version exists

81

* @param version Version string to check

82

* @return true if version is supported by this language

83

*/

84

boolean hasVersion(String version);

85

86

/**

87

* Get LanguageVersion by string identifier

88

* @param version Version identifier or alias

89

* @return LanguageVersion instance, or null if not found

90

*/

91

@Nullable LanguageVersion getVersion(String version);

92

93

/**

94

* Get default language version

95

* @return Default LanguageVersion for this language

96

*/

97

@NonNull LanguageVersion getDefaultVersion();

98

99

/**

100

* Create new property bundle for language-specific configuration

101

* @return LanguagePropertyBundle for this language

102

*/

103

LanguagePropertyBundle newPropertyBundle();

104

105

/**

106

* Get dependency language IDs

107

* @return Set of language IDs this language depends on

108

*/

109

Set<String> getDependencies();

110

}

111

```

112

113

**Usage Examples:**

114

115

```java

116

import net.sourceforge.pmd.lang.Language;

117

import net.sourceforge.pmd.lang.LanguageRegistry;

118

import net.sourceforge.pmd.lang.LanguageVersion;

119

120

// Getting language by ID

121

Language java = LanguageRegistry.PMD.getLanguageById("java");

122

if (java != null) {

123

System.out.printf("Language: %s (Short: %s)%n",

124

java.getName(), java.getShortName());

125

126

// Check file extension support

127

if (java.hasExtension("java")) {

128

System.out.println("Java language handles .java files");

129

}

130

131

// List all supported extensions

132

System.out.printf("Supported extensions: %s%n",

133

java.getExtensions());

134

135

// Work with versions

136

LanguageVersion defaultVersion = java.getDefaultVersion();

137

LanguageVersion latestVersion = java.getLatestVersion();

138

139

System.out.printf("Default version: %s%n", defaultVersion.getVersion());

140

System.out.printf("Latest version: %s%n", latestVersion.getVersion());

141

142

// Check specific version support

143

if (java.hasVersion("17")) {

144

LanguageVersion java17 = java.getVersion("17");

145

System.out.printf("Java 17: %s%n", java17.getName());

146

}

147

148

// List all versions

149

for (LanguageVersion version : java.getVersions()) {

150

System.out.printf(" Version: %s (%s)%n",

151

version.getVersion(), version.getName());

152

}

153

}

154

155

// Working with language properties

156

LanguagePropertyBundle javaProps = java.newPropertyBundle();

157

// Configure language-specific properties as needed

158

159

// Check dependencies

160

Set<String> dependencies = java.getDependencies();

161

if (!dependencies.isEmpty()) {

162

System.out.printf("Dependencies: %s%n", dependencies);

163

}

164

165

// Language comparison and sorting

166

List<Language> languages = new ArrayList<>(LanguageRegistry.PMD.getLanguages());

167

Collections.sort(languages); // Uses Comparable<Language> implementation

168

for (Language lang : languages) {

169

System.out.printf("Language: %s%n", lang.getName());

170

}

171

```

172

173

### Language Registry

174

175

Registry providing centralized access to supported languages with filtering, discovery, and dependency management capabilities.

176

177

```java { .api }

178

/**

179

* Registry of languages with convenient access methods and filtering capabilities.

180

* Implements Iterable<Language> for easy iteration over supported languages.

181

*/

182

public final class LanguageRegistry implements Iterable<Language> {

183

184

/**

185

* PMD-capable languages loaded from classpath

186

*/

187

public static final LanguageRegistry PMD;

188

189

/**

190

* CPD-capable languages loaded from classpath

191

*/

192

public static final LanguageRegistry CPD;

193

194

/**

195

* Create registry with specific set of languages

196

* @param languages Set of Language instances to include

197

*/

198

LanguageRegistry(Set<? extends Language> languages);

199

200

/**

201

* Create filtered registry based on predicate

202

* @param filterFun Predicate to filter languages

203

* @return New LanguageRegistry with filtered languages

204

*/

205

LanguageRegistry filter(Predicate<Language> filterFun);

206

207

/**

208

* Create registry containing single language

209

* @param l Language to include in registry

210

* @return LanguageRegistry containing only specified language

211

*/

212

static LanguageRegistry singleton(Language l);

213

214

/**

215

* Load languages from classpath using ClassLoader

216

* @param classLoader ClassLoader for discovering language implementations

217

* @return LanguageRegistry with discovered languages

218

*/

219

static @NonNull LanguageRegistry loadLanguages(ClassLoader classLoader);

220

221

/**

222

* Get registry containing language and its dependencies

223

* @param lang Language to include with dependencies

224

* @return LanguageRegistry with language and all its dependencies

225

*/

226

LanguageRegistry getDependenciesOf(Language lang);

227

228

/**

229

* Iterate over languages in registry

230

* @return Iterator for Language instances

231

*/

232

@NonNull Iterator<Language> iterator();

233

234

/**

235

* Get all languages in registry

236

* @return Set of all Language instances

237

*/

238

Set<Language> getLanguages();

239

240

/**

241

* Get language by unique ID

242

* @param langId Language identifier (e.g., "java", "javascript")

243

* @return Language instance, or null if not found

244

*/

245

@Nullable Language getLanguageById(@Nullable String langId);

246

247

/**

248

* Get language version by language ID and version string

249

* @param langId Language identifier

250

* @param version Version string or alias

251

* @return LanguageVersion instance, or null if not found

252

*/

253

@Nullable LanguageVersion getLanguageVersionById(@Nullable String langId, @Nullable String version);

254

255

/**

256

* Get language by full name

257

* @param languageName Full language name (e.g., "Java", "JavaScript")

258

* @return Language instance, or null if not found

259

*/

260

@Nullable Language getLanguageByFullName(String languageName);

261

262

/**

263

* Format languages as comma-separated list

264

* @param formatter Function to format each language

265

* @return Comma-separated string of formatted language names

266

*/

267

@NonNull String commaSeparatedList(Function<? super Language, String> formatter);

268

269

/**

270

* Get string representation of registry

271

* @return String describing registry contents

272

*/

273

String toString();

274

}

275

```

276

277

**Usage Examples:**

278

279

```java

280

import net.sourceforge.pmd.lang.*;

281

import java.util.Set;

282

import java.util.function.Predicate;

283

284

// Using predefined registries

285

LanguageRegistry pmdLanguages = LanguageRegistry.PMD;

286

LanguageRegistry cpdLanguages = LanguageRegistry.CPD;

287

288

System.out.printf("PMD supports %d languages%n", pmdLanguages.getLanguages().size());

289

System.out.printf("CPD supports %d languages%n", cpdLanguages.getLanguages().size());

290

291

// List all PMD languages

292

System.out.println("PMD Languages:");

293

for (Language lang : pmdLanguages) {

294

System.out.printf(" %s (%s) - Extensions: %s%n",

295

lang.getName(),

296

lang.getId(),

297

lang.getExtensions());

298

}

299

300

// Find specific languages

301

Language java = pmdLanguages.getLanguageById("java");

302

Language javascript = pmdLanguages.getLanguageByFullName("JavaScript");

303

304

if (java != null) {

305

System.out.printf("Found Java language: %s%n", java.getName());

306

}

307

308

// Get specific language version

309

LanguageVersion java11 = pmdLanguages.getLanguageVersionById("java", "11");

310

if (java11 != null) {

311

System.out.printf("Java 11: %s%n", java11.getName());

312

}

313

314

// Create filtered registry - only languages with specific extensions

315

LanguageRegistry jvmLanguages = pmdLanguages.filter(

316

lang -> lang.hasExtension("java") ||

317

lang.hasExtension("kt") ||

318

lang.hasExtension("scala")

319

);

320

321

// Create registry for single language

322

LanguageRegistry javaOnly = LanguageRegistry.singleton(java);

323

324

// Work with dependencies

325

LanguageRegistry javaWithDeps = pmdLanguages.getDependenciesOf(java);

326

System.out.printf("Java with dependencies: %d languages%n",

327

javaWithDeps.getLanguages().size());

328

329

// Custom filtering examples

330

LanguageRegistry scriptingLanguages = pmdLanguages.filter(

331

lang -> lang.getId().contains("script") ||

332

lang.getId().equals("python") ||

333

lang.getId().equals("ruby")

334

);

335

336

LanguageRegistry webLanguages = pmdLanguages.filter(

337

lang -> lang.hasExtension("js") ||

338

lang.hasExtension("ts") ||

339

lang.hasExtension("html") ||

340

lang.hasExtension("css")

341

);

342

343

// Format language list

344

String languageList = pmdLanguages.commaSeparatedList(Language::getName);

345

System.out.printf("Supported languages: %s%n", languageList);

346

347

String idList = pmdLanguages.commaSeparatedList(Language::getId);

348

System.out.printf("Language IDs: %s%n", idList);

349

350

// Load languages from custom ClassLoader

351

ClassLoader customLoader = Thread.currentThread().getContextClassLoader();

352

LanguageRegistry customLanguages = LanguageRegistry.loadLanguages(customLoader);

353

```

354

355

### Language Version Discovery

356

357

Automatic detection and management of language versions based on file characteristics and configuration.

358

359

```java { .api }

360

/**

361

* Discovers and manages language versions for files based on extensions and configuration.

362

*/

363

interface LanguageVersionDiscoverer {

364

365

/**

366

* Get default language version for specific language

367

* @param language Target language

368

* @return Default LanguageVersion for the language

369

*/

370

LanguageVersion getDefaultLanguageVersion(Language language);

371

372

/**

373

* Get language version for specific file

374

* @param fileName File name to analyze

375

* @return LanguageVersion based on file extension and configuration, or null

376

*/

377

@Nullable LanguageVersion getLanguageVersionOfFile(String fileName);

378

379

/**

380

* Set default version for specific language

381

* @param languageVersion Default version to use for language

382

*/

383

void setDefaultLanguageVersion(LanguageVersion languageVersion);

384

385

/**

386

* Set multiple default language versions

387

* @param languageVersions List of default versions for different languages

388

*/

389

void setDefaultLanguageVersions(List<LanguageVersion> languageVersions);

390

}

391

```

392

393

**Usage Examples:**

394

395

```java

396

import net.sourceforge.pmd.lang.*;

397

398

// Working with language version discovery

399

PMDConfiguration config = new PMDConfiguration();

400

LanguageVersionDiscoverer discoverer = config.getLanguageVersionDiscoverer();

401

402

// Set default versions for languages

403

Language java = LanguageRegistry.PMD.getLanguageById("java");

404

LanguageVersion java11 = java.getVersion("11");

405

discoverer.setDefaultLanguageVersion(java11);

406

407

// Set multiple defaults

408

List<LanguageVersion> defaults = Arrays.asList(

409

LanguageRegistry.PMD.getLanguageVersionById("java", "11"),

410

LanguageRegistry.PMD.getLanguageVersionById("javascript", "es6"),

411

LanguageRegistry.PMD.getLanguageVersionById("python", "3.9")

412

);

413

discoverer.setDefaultLanguageVersions(defaults);

414

415

// Discover language version for files

416

LanguageVersion detected = discoverer.getLanguageVersionOfFile("Example.java");

417

if (detected != null) {

418

System.out.printf("Detected %s for Java file%n", detected.getName());

419

}

420

421

// Check different file types

422

String[] testFiles = {

423

"script.js",

424

"component.ts",

425

"style.css",

426

"template.html",

427

"config.xml",

428

"data.json"

429

};

430

431

for (String fileName : testFiles) {

432

LanguageVersion version = discoverer.getLanguageVersionOfFile(fileName);

433

if (version != null) {

434

System.out.printf("%s -> %s (%s)%n",

435

fileName,

436

version.getLanguage().getName(),

437

version.getVersion());

438

} else {

439

System.out.printf("%s -> No language detected%n", fileName);

440

}

441

}

442

```

443

444

## Types

445

446

```java { .api }

447

/**

448

* Represents a specific version of a programming language

449

*/

450

interface LanguageVersion extends Comparable<LanguageVersion> {

451

452

/**

453

* Get the language this version belongs to

454

* @return Language instance

455

*/

456

Language getLanguage();

457

458

/**

459

* Get version string identifier

460

* @return Version string (e.g., "11", "ES6", "3.9")

461

*/

462

String getVersion();

463

464

/**

465

* Get full descriptive name

466

* @return Full name including language and version

467

*/

468

String getName();

469

470

/**

471

* Get short name

472

* @return Abbreviated name for the version

473

*/

474

String getShortName();

475

476

/**

477

* Get terse name (very short identifier)

478

* @return Minimal identifier for the version

479

*/

480

String getTerseName();

481

482

/**

483

* Compare versions for ordering

484

* @param other LanguageVersion to compare against

485

* @return Comparison result for ordering

486

*/

487

int compareTo(LanguageVersion other);

488

}

489

490

/**

491

* Property bundle for language-specific configuration

492

*/

493

interface LanguagePropertyBundle extends PropertySource {

494

495

/**

496

* Get the language this bundle configures

497

* @return Language instance

498

*/

499

Language getLanguage();

500

501

/**

502

* Create copy of bundle for different language

503

* @param language Target language for copy

504

* @return New LanguagePropertyBundle for specified language

505

*/

506

LanguagePropertyBundle copyForLanguage(Language language);

507

}

508

509

/**

510

* Language module providing parsing and analysis capabilities

511

*/

512

interface LanguageModule {

513

514

/**

515

* Get language metadata

516

* @return Language instance with metadata

517

*/

518

Language getLanguage();

519

520

/**

521

* Get parser for language

522

* @param languageVersion Specific version to parse

523

* @return Parser implementation for the language version

524

*/

525

Parser getParser(LanguageVersion languageVersion);

526

527

/**

528

* Get rule chain visitor for language

529

* @return RuleChainVisitor for processing rules

530

*/

531

RuleChainVisitor getRuleChainVisitor();

532

533

/**

534

* Get CPD visitor for copy-paste detection

535

* @param languageVersion Language version for CPD analysis

536

* @return CpdVisitor for tokenizing source code

537

*/

538

CpdVisitor getCpdVisitor(LanguageVersion languageVersion);

539

}

540

541

/**

542

* Service for managing language implementations

543

*/

544

interface LanguageService {

545

546

/**

547

* Get all available language modules

548

* @return Set of LanguageModule instances

549

*/

550

Set<LanguageModule> getLanguageModules();

551

552

/**

553

* Get language module by language ID

554

* @param languageId Language identifier

555

* @return LanguageModule instance, or null if not found

556

*/

557

@Nullable LanguageModule getLanguageModule(String languageId);

558

559

/**

560

* Register custom language module

561

* @param module LanguageModule to register

562

*/

563

void registerLanguageModule(LanguageModule module);

564

}

565

566

/**

567

* Exception thrown when language operations fail

568

*/

569

class LanguageException extends Exception {

570

String getLanguageId();

571

String getVersionId();

572

}

573

```