or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-prettier-plugin-java

Prettier plugin for formatting Java code with automatic style rules and IDE integration

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/prettier-plugin-java@2.7.x

To install, run

npx @tessl/cli install tessl/npm-prettier-plugin-java@2.7.0

index.mddocs/

Prettier Plugin Java

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.

Package Information

  • Package Name: prettier-plugin-java
  • Package Type: npm
  • Language: TypeScript
  • Installation: npm install prettier-plugin-java --save-dev
  • Peer Dependencies: prettier@^3.0.0

Core Imports

ESM Import:

import plugin from "prettier-plugin-java";

CommonJS Import:

const plugin = require("prettier-plugin-java");

Basic Usage

CLI Usage

Format Java files directly using Prettier CLI:

# Format a single file
prettier --write MyJavaFile.java

# Format all Java files in src directory
prettier --write "src/**/*.java"

# Format with specific entrypoint for code snippets
prettier --write MyJavaSnippet.java --entrypoint methodDeclaration

Programmatic Usage

Use Prettier's API with the plugin to format Java code:

import { format } from "prettier";
import plugin from "prettier-plugin-java";

const javaCode = `
public class HelloWorld {
public static void main(String[] args) {System.out.println("Hello World!");;;;;}

@Override
public String toString() {
  return "Hello World";
}
  public int sum(int argument1,int argument2,int argument3,int argument4,int argument5
  ) {
    return argument1+argument2+ argument3 +argument4  + argument5;
  }
}
`;

const formattedCode = await format(javaCode, {
  parser: "java",
  plugins: [plugin],
  tabWidth: 2,
  printWidth: 80
});

console.log(formattedCode);

Architecture

The plugin is built around the Prettier plugin architecture with these key components:

  • Parser Module: Converts Java source code to a Concrete Syntax Tree (CST) using java-parser
  • Printer Module: Transforms the CST back to formatted Java code using Prettier's document builders
  • Options System: Provides Java-specific formatting options and 250+ grammar entrypoints
  • Comment Processing: Handles Java comments, prettier-ignore directives, and @formatter:off/on regions
  • Type System: Full TypeScript integration with comprehensive type definitions

Capabilities

Plugin Configuration

The main plugin object that integrates with Prettier's formatting system.

/**
 * Main plugin export implementing Prettier's Plugin interface
 */
declare const plugin: Plugin<JavaNode>;

interface Plugin<T> {
  /** Language definitions supported by the plugin */
  languages: LanguageSupport[];
  /** Parser configurations keyed by parser name */
  parsers: Record<string, Parser<T>>;
  /** Printer configurations keyed by printer name */
  printers: Record<string, Printer<T>>;
  /** Plugin-specific formatting options */
  options: SupportOptions;
  /** Default option values for the plugin */
  defaultOptions: Record<string, any>;
}

interface LanguageSupport {
  /** Display name of the language */
  name: string;
  /** List of parser names that can handle this language */
  parsers: string[];
  /** Language group for IDE integration */
  group: string;
  /** TextMate scope identifier */
  tmScope: string;
  /** Ace editor mode */
  aceMode: string;
  /** CodeMirror mode */
  codemirrorMode: string;
  /** CodeMirror MIME type */
  codemirrorMimeType: string;
  /** File extensions handled by this language */
  extensions: string[];
  /** GitHub Linguist language ID */
  linguistLanguageId: number;
  /** VS Code language identifiers */
  vscodeLanguageIds: string[];
}

Java Parser

Parses Java source code into a Concrete Syntax Tree using the java-parser library.

/**
 * Java parser that converts source code to CST
 */
interface JavaParser extends Parser<JavaNode> {
  /** Parse Java source code to CST */
  parse(text: string, options: JavaParserOptions): JavaNonTerminal;
  /** AST format identifier */
  astFormat: "java";
  /** Check for prettier pragma comments */
  hasPragma(text: string): boolean;
  /** Get start location of a node */
  locStart(node: JavaNode): number;
  /** Get end location of a node */
  locEnd(node: JavaNode): number;
}

interface JavaParserOptions extends ParserOptions<JavaNode> {
  /** Grammar entrypoint for parsing code snippets */
  entrypoint?: string;
}

Java Printer

Converts the parsed CST back to formatted Java source code.

/**
 * Java printer that converts CST to formatted source code
 */
interface JavaPrinter extends Printer<JavaNode> {
  /** Main printing function for formatting nodes */
  print(
    path: AstPath<JavaNode>,
    options: any,
    print: (path: AstPath<JavaNode>) => Doc,
    args?: any
  ): Doc;
  /** Check if node should be ignored by prettier */
  hasPrettierIgnore(path: AstPath<JavaNode>): boolean;
  /** Determine if comments can be attached to nodes */
  canAttachComment(node: JavaNode): boolean;
  /** Identify block comments vs line comments */
  isBlockComment(node: JavaNode): boolean;
  /** Format comment nodes */
  printComment(commentPath: AstPath<JavaNode>): string;
  /** Get child nodes for comment processing */
  getCommentChildNodes(node: JavaNode): JavaNode[];
  /** Comment handling strategies */
  handleComments: {
    ownLine: (commentPath: AstPath<JavaNode>) => boolean;
    endOfLine: (commentPath: AstPath<JavaNode>) => boolean;
    remaining: (commentPath: AstPath<JavaNode>) => boolean;
  };
}

Formatting Options

Plugin-specific options for customizing Java code formatting behavior.

/**
 * Java-specific formatting options
 */
interface JavaFormattingOptions extends SupportOptions {
  /** Grammar entrypoint for parsing code snippets */
  entrypoint: {
    type: "choice";
    category: "Global";
    default: "compilationUnit";
    /** 250+ Java grammar rules for parsing different code constructs */
    choices: Array<{
      value: string;
      description: string;
    }>;
    description: "Prettify from the entrypoint, allowing to use prettier on snippet";
  };
  
  /** Arrow function parentheses handling */
  arrowParens: {
    type: "choice";
    category: "Java";
    default: "always";
    choices: Array<{ value: "always" | "avoid"; description: string }>;
    description: "Include parentheses around a sole arrow function parameter";
  };
  
  /** Trailing comma configuration */
  trailingComma: {
    type: "choice";
    category: "Java";
    default: "all";
    choices: Array<{ value: "all" | "es5" | "none"; description: string }>;
    description: "Print trailing commas wherever possible when multi-line";
  };
  
  /** Binary operator positioning */
  experimentalOperatorPosition: {
    type: "choice";
    category: "Java";
    default: "end";
    choices: Array<{ value: "start" | "end"; description: string }>;
    description: "Where to print operators when binary expressions wrap lines";
  };
}

Available Entrypoints (Grammar Rules):

The plugin supports 250+ Java grammar entrypoints for formatting code snippets. Key entrypoints include:

  • compilationUnit (default) - Complete Java source files
  • classDeclaration - Class definitions
  • methodDeclaration - Method definitions
  • classBodyDeclaration - Class member declarations
  • statement - Individual statements
  • expression - Expressions
  • block - Code blocks
  • variableDeclaration - Variable declarations
  • annotation - Annotations
  • interfaceDeclaration - Interface definitions

Comment Processing

Handles Java comments, prettier directives, and formatter regions.

/**
 * Comment processing and formatter directive handling
 */
interface CommentProcessor {
  /** Process @formatter:off/on comment directives */
  determineFormatterOffOnRanges(cst: JavaNonTerminal): void;
  
  /** Check if node is within formatter-off region */
  isFullyBetweenFormatterOffOn(path: AstPath<JavaNode>): boolean;
  
  /** Determine if comments can be attached to a node */
  canAttachComment(node: JavaNode): boolean;
  
  /** Handle line comments (// and /* */) */
  handleLineComment(commentPath: AstPath<JavaNode>): boolean;
  
  /** Handle remaining unprocessed comments */
  handleRemainingComment(commentPath: AstPath<JavaNode>): boolean;
}

interface JavaComment {
  /** Comment text content */
  image: string;
  /** Comment value (same as image) */
  value: string;
  /** Start position in source */
  startOffset: number;
  /** End position in source */
  endOffset: number;
  /** Whether this is a leading comment */
  leading: boolean;
  /** Whether this is a trailing comment */
  trailing: boolean;
  /** Comment token type */
  tokenType: {
    name: string;
    GROUP: string;
  };
}

Supported Comment Directives:

  • // prettier-ignore - Skip formatting for next statement
  • /* prettier-ignore */ - Skip formatting for next statement
  • // @formatter:off - Disable formatting until @formatter:on
  • /* @formatter:off */ - Disable formatting until @formatter:on
  • // @formatter:on - Re-enable formatting
  • /* @formatter:on */ - Re-enable formatting

AST Node Types

Core type definitions for Java AST nodes used throughout the plugin.

/**
 * Core Java AST node types
 */
type JavaNode = CstElement & { 
  /** Attached comments for this node */
  comments?: JavaComment[] 
};

/** Non-terminal AST nodes (containers) */
type JavaNonTerminal = Exclude<JavaNode, IToken>;

/** Terminal AST nodes (tokens) */  
type JavaTerminal = Exclude<JavaNode, CstNode>;

/** Type-safe printer function */
type JavaPrintFn = (path: AstPath<JavaNode>, args?: unknown) => Doc;

/** Node-specific printer function */
type JavaNodePrinter<T> = (
  path: AstPath<Extract<JavaNonTerminal, { name: T }>>,
  print: JavaPrintFn,
  options: JavaParserOptions,
  args?: unknown
) => Doc;

/** Collection of all node-specific printers */
type JavaNodePrinters = {
  [T in JavaNonTerminal["name"]]: JavaNodePrinter<T>;
};

Utility Functions

Helper functions for AST manipulation and formatting logic.

/**
 * AST manipulation and formatting utilities
 */
interface PluginUtilities {
  /** Extract single defined key from object */
  onlyDefinedKey<T extends Record<string, any>>(
    obj: T,
    options?: string[]
  ): string;
  
  /** Get all defined keys from object */
  definedKeys<T extends Record<string, any>>(
    obj: T,
    options?: string[]
  ): string[];
  
  /** Sort Java modifiers in standard order */
  sortModifiers(modifiers: string[]): string[];
  
  /** Format class type expressions with generics */
  printClassType(
    path: AstPath<JavaNonTerminal>,
    print: JavaPrintFn
  ): Doc;
  
  /** Check if expression is a binary expression */
  isBinaryExpression(expression: ExpressionCstNode): boolean;
  
  /** Check if statement is empty */
  isEmptyStatement(statement: StatementCstNode): boolean;
  
  /** Type guard for non-terminal nodes */
  isNonTerminal(node: CstElement): node is JavaNonTerminal;
  
  /** Type guard for terminal nodes */
  isTerminal(node: CstElement): node is IToken;
  
  /** Calculate base indentation for multi-line strings */
  findBaseIndent(lines: string[]): number;
}

Usage Examples

Basic File Formatting

# Install the plugin
npm install prettier-plugin-java --save-dev

# Format a Java file
prettier --write src/main/java/com/example/MyClass.java

# Format all Java files in a project
prettier --write "src/**/*.java"

Code Snippet Formatting

import { format } from "prettier";
import plugin from "prettier-plugin-java";

// Format a method declaration snippet
const methodSnippet = `
public void myMethod() {
    myObject.is().very().very().very().very().long().chain();
}
`;

const formatted = await format(methodSnippet, {
  parser: "java",
  plugins: [plugin],
  entrypoint: "classBodyDeclaration",
  printWidth: 80
});

Custom Formatting Options

import { format } from "prettier";
import plugin from "prettier-plugin-java";

const javaCode = `
public class Example {
    public void method(int a,int b,int c) {
        return a+b+c;
    }
}
`;

const formatted = await format(javaCode, {
  parser: "java",
  plugins: [plugin],
  // Java-specific options
  entrypoint: "compilationUnit",
  arrowParens: "always",
  trailingComma: "all",
  experimentalOperatorPosition: "end",
  // Standard Prettier options
  tabWidth: 4,
  printWidth: 120,
  useTabs: false
});

Integration with Build Tools

package.json scripts:

{
  "scripts": {
    "format": "prettier --write \"src/**/*.java\"",
    "format:check": "prettier --check \"src/**/*.java\""
  }
}

Pre-commit hook with husky:

{
  "husky": {
    "hooks": {
      "pre-commit": "prettier --write \"src/**/*.java\" && git add ."
    }
  }
}

Error Handling

import { format } from "prettier";
import plugin from "prettier-plugin-java";

try {
  const formatted = await format(invalidJavaCode, {
    parser: "java",
    plugins: [plugin]
  });
} catch (error) {
  if (error.name === "SyntaxError") {
    console.error("Java syntax error:", error.message);
  } else {
    console.error("Formatting error:", error.message);
  }
}

Types

/**
 * Complete type definitions for prettier-plugin-java
 */
import type { Plugin, Parser, Printer, AstPath, Doc, ParserOptions, SupportOptions } from "prettier";
import type { CstElement, CstNode, IToken } from "java-parser";

/** Main plugin interface */
declare const plugin: Plugin<JavaNode>;

/** Java AST node with optional comments */
type JavaNode = CstElement & { comments?: JavaComment[] };

/** Non-terminal nodes (containers) */
type JavaNonTerminal = Exclude<JavaNode, IToken>;

/** Terminal nodes (tokens) */
type JavaTerminal = Exclude<JavaNode, CstNode>;

/** Parser options with Java-specific entrypoint */
interface JavaParserOptions extends ParserOptions<JavaNode> {
  entrypoint?: string;
}

/** Type-safe print function */
type JavaPrintFn = (path: AstPath<JavaNode>, args?: unknown) => Doc;

/** Comment attached to AST nodes */
interface JavaComment {
  /** Comment text content */
  image: string;
  /** Comment value (same as image) */
  value: string;
  /** Start position in source */
  startOffset: number;
  /** End position in source */
  endOffset: number;
  /** Whether this is a leading comment */
  leading: boolean;
  /** Whether this is a trailing comment */
  trailing: boolean;
  /** Comment token type */
  tokenType: {
    name: string;
    GROUP: string;
  };
}

export default plugin;