CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-prettier-plugin-java

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

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

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;

Install with Tessl CLI

npx tessl i tessl/npm-prettier-plugin-java

docs

index.md

tile.json