0
# Prettier Plugin Java
1
2
Prettier Plugin Java provides automatic code formatting for Java source files through Prettier's extensible plugin system. It uses a JavaScript-based Java parser to format Java code without requiring a Java runtime, making it ideal for integration into modern development workflows, IDEs, and CI/CD pipelines.
3
4
## Package Information
5
6
- **Package Name**: prettier-plugin-java
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install prettier-plugin-java --save-dev`
10
- **Peer Dependencies**: prettier@^3.0.0
11
12
## Core Imports
13
14
ESM Import:
15
```typescript
16
import plugin from "prettier-plugin-java";
17
```
18
19
CommonJS Import:
20
```javascript
21
const plugin = require("prettier-plugin-java");
22
```
23
24
## Basic Usage
25
26
### CLI Usage
27
28
Format Java files directly using Prettier CLI:
29
30
```bash
31
# Format a single file
32
prettier --write MyJavaFile.java
33
34
# Format all Java files in src directory
35
prettier --write "src/**/*.java"
36
37
# Format with specific entrypoint for code snippets
38
prettier --write MyJavaSnippet.java --entrypoint methodDeclaration
39
```
40
41
### Programmatic Usage
42
43
Use Prettier's API with the plugin to format Java code:
44
45
```typescript
46
import { format } from "prettier";
47
import plugin from "prettier-plugin-java";
48
49
const javaCode = `
50
public class HelloWorld {
51
public static void main(String[] args) {System.out.println("Hello World!");;;;;}
52
53
@Override
54
public String toString() {
55
return "Hello World";
56
}
57
public int sum(int argument1,int argument2,int argument3,int argument4,int argument5
58
) {
59
return argument1+argument2+ argument3 +argument4 + argument5;
60
}
61
}
62
`;
63
64
const formattedCode = await format(javaCode, {
65
parser: "java",
66
plugins: [plugin],
67
tabWidth: 2,
68
printWidth: 80
69
});
70
71
console.log(formattedCode);
72
```
73
74
## Architecture
75
76
The plugin is built around the Prettier plugin architecture with these key components:
77
78
- **Parser Module**: Converts Java source code to a Concrete Syntax Tree (CST) using java-parser
79
- **Printer Module**: Transforms the CST back to formatted Java code using Prettier's document builders
80
- **Options System**: Provides Java-specific formatting options and 250+ grammar entrypoints
81
- **Comment Processing**: Handles Java comments, prettier-ignore directives, and @formatter:off/on regions
82
- **Type System**: Full TypeScript integration with comprehensive type definitions
83
84
## Capabilities
85
86
### Plugin Configuration
87
88
The main plugin object that integrates with Prettier's formatting system.
89
90
```typescript { .api }
91
/**
92
* Main plugin export implementing Prettier's Plugin interface
93
*/
94
declare const plugin: Plugin<JavaNode>;
95
96
interface Plugin<T> {
97
/** Language definitions supported by the plugin */
98
languages: LanguageSupport[];
99
/** Parser configurations keyed by parser name */
100
parsers: Record<string, Parser<T>>;
101
/** Printer configurations keyed by printer name */
102
printers: Record<string, Printer<T>>;
103
/** Plugin-specific formatting options */
104
options: SupportOptions;
105
/** Default option values for the plugin */
106
defaultOptions: Record<string, any>;
107
}
108
109
interface LanguageSupport {
110
/** Display name of the language */
111
name: string;
112
/** List of parser names that can handle this language */
113
parsers: string[];
114
/** Language group for IDE integration */
115
group: string;
116
/** TextMate scope identifier */
117
tmScope: string;
118
/** Ace editor mode */
119
aceMode: string;
120
/** CodeMirror mode */
121
codemirrorMode: string;
122
/** CodeMirror MIME type */
123
codemirrorMimeType: string;
124
/** File extensions handled by this language */
125
extensions: string[];
126
/** GitHub Linguist language ID */
127
linguistLanguageId: number;
128
/** VS Code language identifiers */
129
vscodeLanguageIds: string[];
130
}
131
```
132
133
### Java Parser
134
135
Parses Java source code into a Concrete Syntax Tree using the java-parser library.
136
137
```typescript { .api }
138
/**
139
* Java parser that converts source code to CST
140
*/
141
interface JavaParser extends Parser<JavaNode> {
142
/** Parse Java source code to CST */
143
parse(text: string, options: JavaParserOptions): JavaNonTerminal;
144
/** AST format identifier */
145
astFormat: "java";
146
/** Check for prettier pragma comments */
147
hasPragma(text: string): boolean;
148
/** Get start location of a node */
149
locStart(node: JavaNode): number;
150
/** Get end location of a node */
151
locEnd(node: JavaNode): number;
152
}
153
154
interface JavaParserOptions extends ParserOptions<JavaNode> {
155
/** Grammar entrypoint for parsing code snippets */
156
entrypoint?: string;
157
}
158
```
159
160
### Java Printer
161
162
Converts the parsed CST back to formatted Java source code.
163
164
```typescript { .api }
165
/**
166
* Java printer that converts CST to formatted source code
167
*/
168
interface JavaPrinter extends Printer<JavaNode> {
169
/** Main printing function for formatting nodes */
170
print(
171
path: AstPath<JavaNode>,
172
options: any,
173
print: (path: AstPath<JavaNode>) => Doc,
174
args?: any
175
): Doc;
176
/** Check if node should be ignored by prettier */
177
hasPrettierIgnore(path: AstPath<JavaNode>): boolean;
178
/** Determine if comments can be attached to nodes */
179
canAttachComment(node: JavaNode): boolean;
180
/** Identify block comments vs line comments */
181
isBlockComment(node: JavaNode): boolean;
182
/** Format comment nodes */
183
printComment(commentPath: AstPath<JavaNode>): string;
184
/** Get child nodes for comment processing */
185
getCommentChildNodes(node: JavaNode): JavaNode[];
186
/** Comment handling strategies */
187
handleComments: {
188
ownLine: (commentPath: AstPath<JavaNode>) => boolean;
189
endOfLine: (commentPath: AstPath<JavaNode>) => boolean;
190
remaining: (commentPath: AstPath<JavaNode>) => boolean;
191
};
192
}
193
```
194
195
### Formatting Options
196
197
Plugin-specific options for customizing Java code formatting behavior.
198
199
```typescript { .api }
200
/**
201
* Java-specific formatting options
202
*/
203
interface JavaFormattingOptions extends SupportOptions {
204
/** Grammar entrypoint for parsing code snippets */
205
entrypoint: {
206
type: "choice";
207
category: "Global";
208
default: "compilationUnit";
209
/** 250+ Java grammar rules for parsing different code constructs */
210
choices: Array<{
211
value: string;
212
description: string;
213
}>;
214
description: "Prettify from the entrypoint, allowing to use prettier on snippet";
215
};
216
217
/** Arrow function parentheses handling */
218
arrowParens: {
219
type: "choice";
220
category: "Java";
221
default: "always";
222
choices: Array<{ value: "always" | "avoid"; description: string }>;
223
description: "Include parentheses around a sole arrow function parameter";
224
};
225
226
/** Trailing comma configuration */
227
trailingComma: {
228
type: "choice";
229
category: "Java";
230
default: "all";
231
choices: Array<{ value: "all" | "es5" | "none"; description: string }>;
232
description: "Print trailing commas wherever possible when multi-line";
233
};
234
235
/** Binary operator positioning */
236
experimentalOperatorPosition: {
237
type: "choice";
238
category: "Java";
239
default: "end";
240
choices: Array<{ value: "start" | "end"; description: string }>;
241
description: "Where to print operators when binary expressions wrap lines";
242
};
243
}
244
```
245
246
**Available Entrypoints (Grammar Rules):**
247
248
The plugin supports 250+ Java grammar entrypoints for formatting code snippets. Key entrypoints include:
249
250
- `compilationUnit` (default) - Complete Java source files
251
- `classDeclaration` - Class definitions
252
- `methodDeclaration` - Method definitions
253
- `classBodyDeclaration` - Class member declarations
254
- `statement` - Individual statements
255
- `expression` - Expressions
256
- `block` - Code blocks
257
- `variableDeclaration` - Variable declarations
258
- `annotation` - Annotations
259
- `interfaceDeclaration` - Interface definitions
260
261
### Comment Processing
262
263
Handles Java comments, prettier directives, and formatter regions.
264
265
```typescript { .api }
266
/**
267
* Comment processing and formatter directive handling
268
*/
269
interface CommentProcessor {
270
/** Process @formatter:off/on comment directives */
271
determineFormatterOffOnRanges(cst: JavaNonTerminal): void;
272
273
/** Check if node is within formatter-off region */
274
isFullyBetweenFormatterOffOn(path: AstPath<JavaNode>): boolean;
275
276
/** Determine if comments can be attached to a node */
277
canAttachComment(node: JavaNode): boolean;
278
279
/** Handle line comments (// and /* */) */
280
handleLineComment(commentPath: AstPath<JavaNode>): boolean;
281
282
/** Handle remaining unprocessed comments */
283
handleRemainingComment(commentPath: AstPath<JavaNode>): boolean;
284
}
285
286
interface JavaComment {
287
/** Comment text content */
288
image: string;
289
/** Comment value (same as image) */
290
value: string;
291
/** Start position in source */
292
startOffset: number;
293
/** End position in source */
294
endOffset: number;
295
/** Whether this is a leading comment */
296
leading: boolean;
297
/** Whether this is a trailing comment */
298
trailing: boolean;
299
/** Comment token type */
300
tokenType: {
301
name: string;
302
GROUP: string;
303
};
304
}
305
```
306
307
**Supported Comment Directives:**
308
309
- `// prettier-ignore` - Skip formatting for next statement
310
- `/* prettier-ignore */` - Skip formatting for next statement
311
- `// @formatter:off` - Disable formatting until @formatter:on
312
- `/* @formatter:off */` - Disable formatting until @formatter:on
313
- `// @formatter:on` - Re-enable formatting
314
- `/* @formatter:on */` - Re-enable formatting
315
316
### AST Node Types
317
318
Core type definitions for Java AST nodes used throughout the plugin.
319
320
```typescript { .api }
321
/**
322
* Core Java AST node types
323
*/
324
type JavaNode = CstElement & {
325
/** Attached comments for this node */
326
comments?: JavaComment[]
327
};
328
329
/** Non-terminal AST nodes (containers) */
330
type JavaNonTerminal = Exclude<JavaNode, IToken>;
331
332
/** Terminal AST nodes (tokens) */
333
type JavaTerminal = Exclude<JavaNode, CstNode>;
334
335
/** Type-safe printer function */
336
type JavaPrintFn = (path: AstPath<JavaNode>, args?: unknown) => Doc;
337
338
/** Node-specific printer function */
339
type JavaNodePrinter<T> = (
340
path: AstPath<Extract<JavaNonTerminal, { name: T }>>,
341
print: JavaPrintFn,
342
options: JavaParserOptions,
343
args?: unknown
344
) => Doc;
345
346
/** Collection of all node-specific printers */
347
type JavaNodePrinters = {
348
[T in JavaNonTerminal["name"]]: JavaNodePrinter<T>;
349
};
350
```
351
352
### Utility Functions
353
354
Helper functions for AST manipulation and formatting logic.
355
356
```typescript { .api }
357
/**
358
* AST manipulation and formatting utilities
359
*/
360
interface PluginUtilities {
361
/** Extract single defined key from object */
362
onlyDefinedKey<T extends Record<string, any>>(
363
obj: T,
364
options?: string[]
365
): string;
366
367
/** Get all defined keys from object */
368
definedKeys<T extends Record<string, any>>(
369
obj: T,
370
options?: string[]
371
): string[];
372
373
/** Sort Java modifiers in standard order */
374
sortModifiers(modifiers: string[]): string[];
375
376
/** Format class type expressions with generics */
377
printClassType(
378
path: AstPath<JavaNonTerminal>,
379
print: JavaPrintFn
380
): Doc;
381
382
/** Check if expression is a binary expression */
383
isBinaryExpression(expression: ExpressionCstNode): boolean;
384
385
/** Check if statement is empty */
386
isEmptyStatement(statement: StatementCstNode): boolean;
387
388
/** Type guard for non-terminal nodes */
389
isNonTerminal(node: CstElement): node is JavaNonTerminal;
390
391
/** Type guard for terminal nodes */
392
isTerminal(node: CstElement): node is IToken;
393
394
/** Calculate base indentation for multi-line strings */
395
findBaseIndent(lines: string[]): number;
396
}
397
```
398
399
## Usage Examples
400
401
### Basic File Formatting
402
403
```bash
404
# Install the plugin
405
npm install prettier-plugin-java --save-dev
406
407
# Format a Java file
408
prettier --write src/main/java/com/example/MyClass.java
409
410
# Format all Java files in a project
411
prettier --write "src/**/*.java"
412
```
413
414
### Code Snippet Formatting
415
416
```typescript
417
import { format } from "prettier";
418
import plugin from "prettier-plugin-java";
419
420
// Format a method declaration snippet
421
const methodSnippet = `
422
public void myMethod() {
423
myObject.is().very().very().very().very().long().chain();
424
}
425
`;
426
427
const formatted = await format(methodSnippet, {
428
parser: "java",
429
plugins: [plugin],
430
entrypoint: "classBodyDeclaration",
431
printWidth: 80
432
});
433
```
434
435
### Custom Formatting Options
436
437
```typescript
438
import { format } from "prettier";
439
import plugin from "prettier-plugin-java";
440
441
const javaCode = `
442
public class Example {
443
public void method(int a,int b,int c) {
444
return a+b+c;
445
}
446
}
447
`;
448
449
const formatted = await format(javaCode, {
450
parser: "java",
451
plugins: [plugin],
452
// Java-specific options
453
entrypoint: "compilationUnit",
454
arrowParens: "always",
455
trailingComma: "all",
456
experimentalOperatorPosition: "end",
457
// Standard Prettier options
458
tabWidth: 4,
459
printWidth: 120,
460
useTabs: false
461
});
462
```
463
464
### Integration with Build Tools
465
466
**package.json scripts:**
467
```json
468
{
469
"scripts": {
470
"format": "prettier --write \"src/**/*.java\"",
471
"format:check": "prettier --check \"src/**/*.java\""
472
}
473
}
474
```
475
476
**Pre-commit hook with husky:**
477
```json
478
{
479
"husky": {
480
"hooks": {
481
"pre-commit": "prettier --write \"src/**/*.java\" && git add ."
482
}
483
}
484
}
485
```
486
487
### Error Handling
488
489
```typescript
490
import { format } from "prettier";
491
import plugin from "prettier-plugin-java";
492
493
try {
494
const formatted = await format(invalidJavaCode, {
495
parser: "java",
496
plugins: [plugin]
497
});
498
} catch (error) {
499
if (error.name === "SyntaxError") {
500
console.error("Java syntax error:", error.message);
501
} else {
502
console.error("Formatting error:", error.message);
503
}
504
}
505
```
506
507
## Types
508
509
```typescript { .api }
510
/**
511
* Complete type definitions for prettier-plugin-java
512
*/
513
import type { Plugin, Parser, Printer, AstPath, Doc, ParserOptions, SupportOptions } from "prettier";
514
import type { CstElement, CstNode, IToken } from "java-parser";
515
516
/** Main plugin interface */
517
declare const plugin: Plugin<JavaNode>;
518
519
/** Java AST node with optional comments */
520
type JavaNode = CstElement & { comments?: JavaComment[] };
521
522
/** Non-terminal nodes (containers) */
523
type JavaNonTerminal = Exclude<JavaNode, IToken>;
524
525
/** Terminal nodes (tokens) */
526
type JavaTerminal = Exclude<JavaNode, CstNode>;
527
528
/** Parser options with Java-specific entrypoint */
529
interface JavaParserOptions extends ParserOptions<JavaNode> {
530
entrypoint?: string;
531
}
532
533
/** Type-safe print function */
534
type JavaPrintFn = (path: AstPath<JavaNode>, args?: unknown) => Doc;
535
536
/** Comment attached to AST nodes */
537
interface JavaComment {
538
/** Comment text content */
539
image: string;
540
/** Comment value (same as image) */
541
value: string;
542
/** Start position in source */
543
startOffset: number;
544
/** End position in source */
545
endOffset: number;
546
/** Whether this is a leading comment */
547
leading: boolean;
548
/** Whether this is a trailing comment */
549
trailing: boolean;
550
/** Comment token type */
551
tokenType: {
552
name: string;
553
GROUP: string;
554
};
555
}
556
```
557
558
export default plugin;