Skip to content

All rules

Block tag punctuation

Description of certain block tags, if present, should end with a period, question mark or exclamation mark.

Before

Before
/**
* @param num
* @return the new size of the group
*/
abstract int add(int num);
Before
/**
* @param num
* @return the new size of the group
*/
abstract def add(int num)
Before
/**
* @param num
* @return the new size of the group
*/
abstract fun add(int num): Int

After

After
/**
* @param num
* @return the new size of the group.
*/
abstract int add(int num);
After
/**
* @param num
* @return the new size of the group.
*/
abstract def add(int num)
After
/**
* @param num
* @return the new size of the group.
*/
abstract fun add(int num): Int
Configuration
Checkstyle Default value
BlockTagPunctuation#tags @param, @return
Ktlint
rulebook_punctuate_block_tags @constructor, @receiver, @property, @param, @return

Built-in types

Prefer to use built-in types provided by the language.

Before

import java.lang.String

val names = arrayListOf<String>()
val people = java.util.ArrayList<Person>()
from typing import Optional

def get_name(person) -> Optional[str]:
    return person['name']

After

val names = arrayListOf<String>()
val people = ArrayList<Person>()
def get_name(person) -> str | None:
    return person['name']

Confusing predicate

Use the positive form in a predicate call when it is a single expression and the calling function can be inverted.

Before

person.takeIf { it.name != null }

After

person.takeUnless { it.name == null }

File size

File length should not be longer than 1.000 lines of code. If a file exceeds the limit, it should be split into multiple files.

Before

final class Articles {
    static int create(Article article) { /*...*/ }

    static Article read(int articleId) { /*...*/ }

    static void update(int articleId, Article article) { /*...*/ }

    static void delete(int articleId) { /*...*/ }
}
final class Articles {
    static def create(Article article) { /*...*/ }

    static def read(int articleId) { /*...*/ }

    static def update(int articleId, Article article) { /*...*/ }

    static def delete(int articleId) { /*...*/ }
}
object Articles {
    fun create(article: Article): Int { /*...*/ }

    fun read(articleId: Int): Article { /*...*/ }

    fun update(articleId: Int, article: Article) { /*...*/ }

    fun delete(articleId: Int) { /*...*/ }
}
def create_article(article: Article) -> int:
    // ...

def read_article(article_id: int) -> Article:
    // ...

def update_article(article_id: int, article: Article):
    // ...

def delete_article(article_id: int):
    // ...

After

final class ArticleCreator {
    static int create(Article article) { /*...*/ }
}
final class ArticleReader {
    static Article read(int articleId) { /*...*/ }
}
final class ArticleUpdater {
    static void update(int articleId, Article article) { /*...*/ }
}
final class ArticleDeleter {
    static void delete(int articleId) { /*...*/ }
}

final class ArticleCreator {
    static def create(Article article) { /*...*/ }
}
final class ArticleReader {
    static def read(int articleId) { /*...*/ }
}
final class ArticleUpdater {
    static def update(int articleId, Article article) { /*...*/ }
}
final class ArticleDeleter {
    static def delete(int articleId) { /*...*/ }
}

fun Articles.create(article: Article): Int { /*...*/ }
fun Articles.read(articleId: Int): Article { /*...*/ }
fun Articles.update(articleId: Int, article: Article) { /*...*/ }
fun Articles.delete(articleId: Int) { /*...*/ }

def create_article(article: Article) -> int:
    // ...
def read_article(article_id: int) -> Article:
    // ...
def update_article(article_id: int, article: Article):
    // ...
def delete_article(article_id: int):
    // ...

Configuration
Checkstyle Default value
FileLength#max 1.000
CodeNarc
ClassSize#maxLines 1.000
Ktlint
rulebook_max_file_size 1.000
Pylint
rulebook-max-file-size 1.000

Null equality

Use structural equality instead of referential equality when comparing objects with null.

Before

user.takeUnless { it.name === null }

After

user.takeUnless { it.name == null }

Redundant qualifier

Strip fully qualified names when they are already imported.

Before

import java.io.FileInputStream;

void read(java.io.FileInputStream stream) {}
import java.io.FileInputStream

def read(java.io.FileInputStream stream) {}

After

import java.io.FileInputStream;

void read(FileInputStream stream) {}
import java.io.FileInputStream

def read(FileInputStream stream) {}

TODO comment

TODO comment keywords should be uppercase and followed by exactly one space.

Before

// todo add tests
//
// FIXME: memory leak
// todo add tests
//
// FIXME: memory leak
// todo add tests
//
// FIXME: memory leak
# todo add tests
#
# FIXME: memory leak

After

// TODO add tests
//
// FIXME memory leak
// TODO add tests
//
// FIXME memory leak
// TODO add tests
//
// FIXME memory leak
# TODO add tests
#
# FIXME memory leak

Trailing comma in call

Put a trailing comma in a multiline call site, omit when it is a single line.

Before

def items =
    Arrays.asList(
        'milks',
        'eggs'
    )

println(items,)
val items =
    listOf(
        "milks",
        "eggs"
    )

println(items,)
items = \
    set(
        'milks',
        'eggs'
    )

print(items,)

After

def items =
    Arrays.asList(
        'milks',
        'eggs',
    )

println(items)
val items =
    listOf(
        "milks",
        "eggs",
    )

println(items)
items = \
    set(
        'milks',
        'eggs',
    )

print(items)

Trailing comma in collection

Put a trailing comma in a multiline collection site, omit when it is a single line. In Java and Groovy, this rule applies to array initializers. In Python, this rule applies to tuples.

Before

String[] games = {"chess", "checkers",};

int[][] ticTacToe = {
    {0, 0, 0,},
    {0, 0, 0,},
    {0, 0, 0,}
};
var games = ['chess', 'checkers',]

var ticTacToe = [
    [0, 0, 0,],
    [0, 0, 0,],
    [0, 0, 0,]
]
games = ('chess', 'checkers',)

tic_tac_toe = (
    (0, 0, 0,),
    (0, 0, 0,),
    (0, 0, 0,)
)

After

String[] games = {"chess", "checkers"};

int[][] ticTacToe = {
    {0, 0, 0},
    {0, 0, 0},
    {0, 0, 0},
};
var games = ['chess', 'checkers']

var ticTacToe = [
    [0, 0, 0],
    [0, 0, 0],
    [0, 0, 0],
]
games = ('chess', 'checkers')

tic_tac_toe = (
    (0, 0, 0),
    (0, 0, 0),
    (0, 0, 0),
)

Trailing comma in declaration

Put a trailing comma in a multiline declaration site, omit when it is a single line.

Before

fun updateInventory(item: String,) = TODO()

fun createInventory(
    item: String,
    quantity: Int
) = TODO()
def update_inventory(item: str,):
    pass


def create_inventory(
    item: str,
    quantity: int
):
    pass

After

fun updateInventory(item: String) = TODO()

fun createInventory(
    item: String,
    quantity: Int,
)
def update_inventory(item: str):
    pass


def create_inventory(
    item: str,
    quantity: int,
)

Unused import

Remove unused import statements.

Before

import com.example.fruit.Apple;
import com.example.fruit.Banana;

Apple apple = new Apple();
import com.example.fruit.Apple
import com.example.fruit.Banana

var apple = new Apple()
import com.example.fruit.Apple
import com.example.fruit.Banana

val apple = Apple()
from fruit import Apple, Banana

apple = Apple()

After

import com.example.fruit.Apple;

Apple apple = new Apple();
import com.example.fruit.Apple

var apple = new Apple()
import com.example.fruit.Apple

val apple = Apple()
from fruit import Apple

apple = Apple()

Wildcard import

Import directives must be single-type instead of wildcard imports.

Before

import com.example.fruit.*;

List<Fruit> fruits = Arrays.asList(new Apple(), new Banana());
import com.example.fruit.*

ArrayList<Fruit> fruits = [new Apple(), new Banana()]
import com.example.fruit.*

val fruits = listOf(Apple(), Banana())
from fruit import *

fruits = [Apple(), Banana()]

After

import com.example.fruit.Apple;
import com.example.fruit.Banana;

List<Fruit> fruits = Arrays.asList(new Apple(), new Banana());
import com.example.fruit.Apple
import com.example.fruit.Banana

ArrayList<Fruit> fruits = [new Apple(), new Banana()]
import com.example.fruit.Apple
import com.example.fruit.Banana

val fruits = listOf(Apple(), Banana())
from fruit import Apple, Banana

fruits = [Apple(), Banana()]

Declaring

Abstract class definition

Abstract classes need at least one abstract function.

Before

abstract class Vehicle {
    void start() {}
}
abstract class Vehicle {
    def start() {}
}
abstract class Vehicle {
    fun start() {}
}
from abc import ABC

class Vehicle(ABC):
    def start(self):
        pass

After

class Vehicle {
    void start();
}
class Vehicle {
    def start()
}
class Vehicle {
    fun start()
}
class Vehicle:
    def start(self):
        pass

Contract function definition

Kotlin contract functions that carry a runnable parameter should have inline modifier. Without the modifier, user cannot assign a global variable within the code block.

Before

fun action(block: () -> Unit) {
    contract { callsInPlace(block, EXACTLY_ONCE) }
    block()
}

After

inline fun action(block: () -> Unit) {
    contract { callsInPlace(block, EXACTLY_ONCE) }
    block()
}

Exception inheritance

Use Exception as superclass of custom exceptions. Most applications should not extend Error or Throwable.

Before

class PurchaseException extends Error {}
class PurchaseException extends Error {}
class PurchaseException : Error()
class PurchaseException(BaseException):
    pass

After

class PurchaseException extends Exception {}
class PurchaseException extends Exception {}
class PurchaseException : Exception()
class PurchaseException(Exception):
    pass

Number suffix for double

Double floating point literals should be suffixed with lowercase d, which is more readable than D.

Before

double quarter = 0.25D;
var quarter = 0.25D

After

double quarter = 0.25d;
var quarter = 0.25d

Number suffix for float

Floating point literals should be suffixed with lowercase f, which is more readable than F.

Before

float half = 0.5F;
var quarter = 0.25F
val half = 0.5F

After

float half = 0.5f;
var quarter = 0.25f
val half = 0.5f

Number suffix for integer

Integer literals should be suffixed with lowercase i, which is more readable than I.

Before

var ten = 10I

After

var ten = 10i

Number suffix for long

Long integer literals should be suffixed with uppercase L.

Before

long tenMillion = 10_000_000l;
var tenMillion = 10_000_000l

After

long tenMillion = 10_000_000L;
var tenMillion = 10_000_000L

String quotes

Before

var name = "John Doe"

println('G\'day, ' + name)
name = "John Doe"

print('G\'day, ' + name)

After

var name = 'John Doe'

println("G'day, " + name)
name = 'John Doe'

print("G'day, " + name)

Unnecessary parentheses in lambda

Single parameter lambdas should not have parentheses.

Before

files.forEach((file) -> System.out.println(file));
files.forEach((file) -> System.out.println(file))

After

files.forEach(file -> System.out.println(file));
files.forEach(file -> System.out.println(file))

Tip

Parentheses on lambda parameters is a syntax error in:

  • Kotlin if parameter is single
  • Groovy closures, not lambdas

Use single quotes for string literals, unless the string contains single quotes.

Utility class definition

Utility classes should have a final modifier and a private constructor to prevent instantiation.

Before

class Lists {
    static List<String> of(String... elements) {
        return Arrays.asList(elements);
    }
}
class Lists {
    static List<String> of(String... elements) {
        return Arrays.asList(elements)
    }
}

After

final class Lists {
    private Lists() {}

    static List<String> of(String... elements) {
        return Arrays.asList(elements);
    }
}
final class Lists {
    private Lists() {}

    static List<String> of(String... elements) {
        return Arrays.asList(elements)
    }
}

Naming

Class name acronym

Ensures that the first letter of acronyms longer than three characters are always capitalized.

Before

class RestAPI {
    String httpURL = "https://example.com";
}
class RestAPI {
    var httpURL = 'https://example.com'
}
class RestAPI:
    http_url = 'https://example.com'
class RestAPI {
    val httpURL = "https://example.com"
}

After

class RestApi {
    String httpUrl = "https://example.com";
}
class RestApi {
    var httpUrl = 'https://example.com'
}
class RestApi:
    http_url = 'https://example.com'
class RestApi {
    val httpUrl = "https://example.com"
}

Class name

Class, interface and object names are written in PascalCase.

Before

class train_station {}
class train_station {}
class train_station:
    pass
class train_station

After

class TrainStation {}
class TrainStation {}
class TrainStation:
    pass
class TrainStation

Constant property name

Constant fields should be written in SCREAMING_SNAKE_CASE.

Before

static final int maxValue = 99;
static final int maxValue = 99
const val maxValue = 99

After

static final int MAX_VALUE = 99;
static final int MAX_VALUE = 99
const val MAX_VALUE = 99

File name

If the file contains a single class, the file name should be the same as the root class name.

Before

└─ com.example
   ├─ UserObject.java
   └─ class User {}
└─ com.example
   ├─ UserObject.groovy
   └─ class User {}
└─ com.example
   ├─ UserObject.kt
   └─ class User

After

└─ com.example
   ├─ User.java
   └─ class User {}
└─ com.example
   ├─ User.groovy
   └─ class User {}
└─ com.example
   ├─ User.kt
   └─ class User

Identifier name

Non-constant fields, functions and parameters should be written in camelCase.

Before

void DebugUser(User User) {
    AnotherUser = User;
}
def DebugUser(User User) {
    AnotherUser = User
}
fun DebugUser(User: User) {
    AnotherUser = User
}
def DebugUser(User):
    AnotherUser = User

After

void debugUser(User user) {
    anotherUser = user;
}
def debugUser(User user) {
    anotherUser = user
}
fun debugUser(user: User) {
    anotherUser = user
}
def debug_user(user):
    another_user = user

Illegal class final name

Prohibits meaningless source names in class, interface, object and files. The name of utility classes (or files) should be the plural form of the extended class.

Before

interface AbstractRocket {}

class SpaceshipWrapper implements AbstractRocket {}
interface AbstractRocket {}

class SpaceshipWrapper implements AbstractRocket {}
interface AbstractRocket

class SpaceshipWrapper : AbstractRocket
class AbstractRocket:
    pass


class SpaceshipWrapper(AbstractRocket):
    pass

After

interface Rocket {}

class Spaceship implements Rocket {}
interface Rocket {}

class Spaceship implements Rocket {}
interface Rocket

class Spaceship : Rocket
class Rocket:
    pass


class Spaceship(Rocket):
    pass
Configuration
Checkstyle Default value
IllegalClassFinalName#names Util, Utility, Helper, Manager, Wrapper
CodeNarc
IllegalClassFinalName#names Util, Utility, Helper, Manager, Wrapper
Ktlint
rulebook_illegal_class_final_names Util, Utility, Helper, Manager, Wrapper
Pylint
rulebook-illegal-class-final-names Util, Utility, Helper, Manager, Wrapper

Illegal variable name

Prohibitprimitive type names, base Object type names and their plural forms as identifiers of properties, parameters and local variables. The name of the identifier should be descriptive and meaningful.

Before

String string;

List<Person> list;
var string

var list
val string: String

val list: List<Person>
string: str

list: list[Person]

After

String name;

List<Person> people;
var name

var people
val name: String

val people: List<Person>
name: str

people: list[Person]
Configuration
Checkstyle Default value
IllegalIdentifierName#format object, integer, string, objects, integers, strings
CodeNarc
IllegalVariableName#names object, integer, string, object, integers, strings
Ktlint
rulebook_illegal_variable_names any, boolean, byte, char, double, float, int, long, short, string, many, booleans, bytes, chars, doubles, floats, ints, longs, shorts
Pylint
bad-names objs, ints, strs

Package name

Package names should be written in lowercase with no separators.

Before

package com.example.user_management;
package com.example.user_management
package com.example.user_management
└─ user_management
   └─ UserConfig.py

After

package com.example.usermanagement;
package com.example.usermanagement
package com.example.usermanagement
└─ user_management
   └─ user_config.py

Property name interop

Kotlin field definitions that are Boolean types should be prefixed with is. Otherwise, the compiler will generate a getter method with get prefix.

Before

val active: Boolean
boolean getActive() {}

After

val isActive: Boolean
boolean isActive() {}

Required generic name

Only use common generic type names according to Oracle. Multiple generic types declaration is ignored.

Before

class Box<A> {}

void <X> rotate(Box<X> box) {}
class Box<A> {}

void <X> rotate(Box<X> box) {}
class Box<A>() {}

fun <X> rotate(box: Box<X>) {}
from typing import TypeVar

A = TypeVar('A')
X = TypeVar('X')


class Box(A):
    pass


def rotate(box: Box[X]):
    pass

After

class Box<E> {}

void <T> rotate(Box<T> box) {}
class Box<E> {}

void <T> rotate(Box<T> box) {}
class Box<E>() {}

fun <T> rotate(box: Box<T>) {}
from typing import TypeVar

E = TypeVar('E')
T = TypeVar('T')


class Box(E):
    pass


def rotate(box: Box[T]):
    pass
Configuration
Checkstyle Default value
ClassTypeParameterName#format E, K, N, T, V
InterfaceTypeParameterName#format E, K, N, T, V
MethodTypeParameterName#format E, K, N, T, V
RecordTypeParameterName#format E, K, N, T, V
TypeParameterName#format E, K, N, T, V
CodeNarc
RequiredGenericName#names E, K, N, T, V
Ktlint
rulebook_required_generic_names E, K, N, T, V
Pylint
rulebook-required-generic-names E, K, N, T, V

Ordering

Block tag order

Block tags should be ordered in the following sequence: @constructor, @receiver, @param, @property, @return, @throws, @see.

Before

/**
 * @see User
 * @return The user object.
 * @param name The name of the user.
 */
abstract User createUser(String name);
/**
 * @see User
 * @return The user object.
 * @param name The name of the user.
 */
abstract def createUser(String name)
/**
 * @see User
 * @return The user object.
 * @param name The name of the user.
 */
abstract fun createUser(name: String): User

After

/**
 * @param name The name of the user.
 * @return The user object.
 * @see User
 */
abstract User createUser(String name);
/**
 * @param name The name of the user.
 * @return The user object.
 * @see User
 */
abstract def createUser(String name)
/**
 * @param name The name of the user.
 * @return The user object.
 * @see User
 */
abstract fun createUser(name: String): User

Built-in function position

Place Object built-in methods such as toString(), hashCode() and equals() at the end of the class.

Before

class Notification {
    @Override
    public String toString() {
        return String.format("%d: %s", id, message);
    }

    final String message;
    final int id;

    Notification(String message) {
        this.message = message;
        this.id = randomize();
    }
}
class Notification {
    String toString() {
        return "${id}: ${message}"
    }

    final String message
    final int id

    Notification(String message) {
        this.message = message
        this.id = randomize()
    }
}
class Notification(val message: String) {
    override fun toString(): String = "$id: $message"

    val id: Int = randomize()
}
class Notification:
    def __str__(self):
        return f'{self.id}: {self.message}'

    def __init__(self, message):
        self.message = message
        self.id = randomize()

After

class Notification {
    final String message;
    final int id;

    Notification(String message) {
        this.message = message;
        this.id = randomize();
    }

    @Override
    public String toString() {
        return String.format("%d: %s", id, message);
    }
}
class Notification {
    final String message
    final int id

    Notification(String message) {
        this.message = message
        this.id = randomize()
    }

    String toString() {
        return "${id}: ${message}"
    }
}
class Notification(val message: String) {
    val id: Int = randomize()

    override fun toString(): String = "$id: $message"
}
class Notification:
    def __init__(self, message):
        self.message = message
        self.id = randomize()

    def __str__(self):
        return f'{self.id}: {self.message}'

Import order

Import directives should be ordered alphabetically without any blank lines.

Before

import java.util.List;

import com.example.User;
import java.util.List

import com.example.User
import java.util.List

import com.example.User
import utils

import user

After

import com.example.User;
import java.util.List;
import com.example.User
import java.util.List
import com.example.User
import java.util.List
import user
import utils

Inner class position

Place inner classes at the end of the class.

Before

class Article {
    class Author {}

    Article(String content, Author author) {}

    Article(String content) {}
}
class Article {
    class Author {}

    Article(String content, Author author) {}

    Article(String content) {}
}
class Article(content: String, author: Author) {
    class Author(name: String)

    constructor(content: String) : this(content, null)
}
class Article:
    class Author:
        pass

    def __init__(self, content, author = None):
        pass

After

class Article {
    Article(String content, Author author) {}

    Article(String content) {}

    class Author {}
}
class Article {
    Article(String content, Author author) {}

    Article(String content) {}

    class Author {}
}
class Article(content: String, author: Author) {
    constructor(content: String) : this(content, null)

    class Author(name: String)
}
class Article:
    def __init__(self, content, author = None):
        pass

    class Author:
        pass

Member order

The class should be organized as follows: properties, initializer block, constructors and methods.

Before

class Car {
    Car(String brand, String model) {}

    Car(String brand) {
        this(brand, "Unknown");
    }

    int wheels = 4;

    void start() {
        log("Car created");
    }
}
class Car {
    Car(String brand, String model) {}

    Car(String brand) {
        this(brand, 'Unknown')
    }

    var wheels = 4

    def start() {
        log('Car created')
    }
}
class Car(brand: String, model: String) {
    init {
        log("Car created")
    }

    constructor(brand: String) : this(brand, "Unknown")

    val wheels = 4

    fun start() {
        log("Car started")
    }
}
class Car:
    def __init__(self, brand, model = 'Unknown'):
        pass

    wheels = 4

    def start(self):
        pass

After

class Car implements Vehicle {
    int wheels = 4;

    Car(String brand, String model) {}

    Car(String brand) {
        this(brand, "Unknown");
    }

    void start() {
        log("Car created");
    }
}
class Car implements Vehicle {
    var wheels = 4

    Car(String brand, String model) {}

    Car(String brand) {
        this(brand, 'Unknown')
    }

    def start() {
        log('Car created')
    }
}
class Car(brand: String, model: String): Vehicle {
    override val wheels = 4

    init {
        log("Car created")
    }

    constructor(brand: String) : this(brand, "Unknown")

    fun start() {
        log("Car started")
    }
}
class Car(Vehicle):
    wheels = 4

    def __init__(self, brand, model = 'Unknown'):
        pass

    def start(self):
        pass

Overload function position

Place overloaded functions next to each other.

After

int sum(int a, int b) {
    return a + b;
}

int times(int a, int b) {
    return a * b;
}

int sum(int a, int b, int c) {
    return a + b + c;
}
def sum(int a, int b) {
    return a + b
}

def times(int a, int b) {
    return a * b
}

def sum(int a, int b, int c) {
    return a + b + c
}
fun sum(a: Int, b: Int): Int = a + b

fun times(a: Int, b: Int): Int = a * b

fun sum(a: Int, b: Int, c: Int): Int = a + b + c

After

int sum(int a, int b) {
    return a + b;
}

int sum(int a, int b, int c) {
    return a + b + c;
}

int times(int a, int b) {
    return a * b;
}
def sum(int a, int b) {
    return a + b
}

def sum(int a, int b, int c) {
    return a + b + c
}

def times(int a, int b) {
    return a * b
}
fun sum(a: Int, b: Int): Int = a + b

fun sum(a: Int, b: Int, c: Int): Int = a + b + c

fun times(a: Int, b: Int): Int = a * b

Static import position

Static import directives are to be placed after normal imports, separated by a blank line.

Before

import static java.lang.Math.PI;

import java.util.List;
import static java.lang.Math.PI

import java.util.List

After

import java.util.List;

import static java.lang.Math.PI;
import java.util.List

import static java.lang.Math.PI

Spacing

Block comment spaces

Ensures that block comments starts and ends with a whitespace. In multiline comments, each line after the asterisk should be indented by a whitespace.

Before

/**Pass on user behavior.*/
void report() {}
/**Pass on user behavior.*/
def report() {}
/**Pass on user behavior.*/
fun report()

After

/** Pass on user behavior. */
void report() {}
/** Pass on user behavior. */
def report() {}
/** Pass on user behavior. */
fun report()

Block comment trim

Do not start or end block comments with whitespaces.

Before

/**
 *
 * AUTHOR: John Doe
 * LICENSE: Apache 2.0
 *
 */
/**
 *
 * AUTHOR: John Doe
 * LICENSE: Apache 2.0
 *
 */
/**
 *
 * AUTHOR: John Doe
 * LICENSE: Apache 2.0
 *
 */
"""

AUTHOR: John Doe
LICENSE: Apache 2.0

"""

After

/**
 * AUTHOR: John Doe
 * LICENSE: Apache 2.0
 */
/**
 * AUTHOR: John Doe
 * LICENSE: Apache 2.0
 */
/**
 * AUTHOR: John Doe
 * LICENSE: Apache 2.0
 */
"""
AUTHOR: John Doe
LICENSE: Apache 2.0
"""

Block tag indentation

Multi-line block tag descriptions should be indented by four spaces, or five spaces from the leading asterisk.

Before

/**
 * @param num the number to return
 * the absolute value for.
 */
void abs(int num) {}
/**
 * @param num the number to return
 * the absolute value for.
 */
def abs(int num) {}
/**
 * @param num the number to return
 * the absolute value for.
 */
fun abs(num: Int): Int

After

/**
 * @param num the number to return
 *     the absolute value for.
 */
void abs(int num) {}
/**
 * @param num the number to return
 *     the absolute value for.
 */
def abs(int num) {}
/**
 * @param num the number to return
 *     the absolute value for.
 */
fun abs(num: Int): Int

Case separator

Multiline switch-case entries end with a blank line while short entries are joined.

Before

switch (event) {
    case CANCELLED:
        return;

    case PAST:
        String message = "Event is in the past";
        throw new IllegalStateException(message);
    default:
        createEvent(event);
}
switch (event) {
    case CANCELLED:
        return;

    case PAST:
        var message = 'Event is in the past';
        throw new IllegalStateException(message);
    default:
        createEvent(event);
}
when {
    event.isCancelled() -> return

    event.date < now -> {
        val message = "Event is in the past"
        throw IllegalStateException(message)
    }
    else -> createEvent(event)
}
match event:
    case CANCELLED:
        return

    case PAST:
        message = 'Event is in the past'
        raise ValueError(message)
    case _:
        create_event(event)

After

switch (event) {
    case CANCELLED:
        return;
    case PAST:
        String message = "Event is in the past";
        throw new IllegalStateException(message);

    default:
        createEvent(event);
}
switch (event) {
    case CANCELLED:
        return;
    case PAST:
        var message = 'Event is in the past';
        throw new IllegalStateException(message);

    default:
        createEvent(event);
}
when {
    event.isCancelled() -> return
    event.date < now -> {
        val message = "Event is in the past"
        throw IllegalStateException(message)
    }

    else -> createEvent(event)
}
match event:
    case CANCELLED:
        return
    case PAST:
        message = 'Event is in the past'
        raise ValueError(message)

    case _:
        create_event(event)

Code block trim

Prohibits empty first and last lines in code blocks.

Before

void onReceive(Integer value) {

    if (value != null) {
        total += value;

    }
}
def onReceive(Integer value) {

    if (value != null) {
        total += value

    }
}
fun onReceive(value: Int?) {

    if (value != null) {
        total += value

    }
}
def on_receive(value):

    if value is not None:
        total += value

After

void onReceive(Integer value) {
    if (value != null) {
        total += value;
    }
}
def onReceive(Integer value) {
    if (value != null) {
        total += value
    }
}
fun onReceive(value: Int?) {
    if (value != null) {
        total += value
    }
}
def on_receive(value):
    if value is not None:
        total += value

Comment spaces

End-of-file comments should be separated by a single whitespace from the preceding code, and start with a single whitespace.

Before

System.out.println("This is a code");//This is a comment
println('This is a code')//This is a comment
println("This is a code")//This is a comment
print('This is a code')#This is a comment

After

System.out.println("This is a code"); // This is a comment
println('This is a code') // This is a comment
println("This is a code") // This is a comment
print('This is a code')  # This is a comment

Warning

PEP8 requires leading two spaces for comments.

Comment trim

Prohibits empty first and last lines in EOL comments.

Before

//
// This is a
// multiline comment
//
//
// This is a
// multiline comment
//
//
// This is a
// multiline comment
//
#
# This is a
# multiline comment
#

After

// This is a
// multiline comment
// This is a
// multiline comment
// This is a
// multiline comment
# This is a
# multiline comment

Duplicate blank line

Prohibits consecutive blank lines in the code.

Before

String message = "Hello";


System.out.println(message);
var message = 'Hello'


println(message)
val message = "Hello"


println(message)
message = 'Hello'


print(message)

Warning

PEP8 allows two blank lines between top-level functions and class definitions.

After

String message = "Hello";

System.out.println(message);
var message = 'Hello'

println(message)
val message = "Hello"

println(message)
message = 'Hello'

print(message)

Duplicate blank line in block comment

Prohibits consecutive blank lines in block comments.

Before

/**
 * This is a
 *
 *
 * very long comment
 */
/**
 * This is a
 *
 *
 * very long comment
 */
/**
 * This is a
 *
 *
 * very long comment
 */
"""
This is a


very long comment
"""

After

/**
 * This is a
 *
 * very long comment
 */
/**
 * This is a
 *
 * very long comment
 */
/**
 * This is a
 *
 * very long comment
 */
"""
This is a

very long comment
"""

Duplicate blank line in comment

Prohibits consecutive blank lines in comments.

Before

// This is a
//
//
// very long comment
// This is a
//
//
// very long comment
// This is a
//
//
// very long comment
# This is a
#
#
# very long comment

After

// This is a
//
// very long comment
// This is a
//
// very long comment
// This is a
//
// very long comment
# This is a
#
# very long comment

Member separator

Class, function and property declarations should be separated by a blank line. There is an exception for single-line properties.

Before

interface Vehicle {
    int getWheels();
    void start();
}
interface Vehicle {
    int getWheels();
    def start();
}
interface Vehicle {
    val wheels: Int
    fun start()
}
class Vehicle:
    wheels: int
    def start(self):
        pass

After

interface Vehicle {
    int getWheels();

    void start();
}
interface Vehicle {
    int getWheels();

    void start();
}
interface Vehicle {
    val wheels: Int

    fun start()
}
class Vehicle:
    wheels: int

    def start(self):
        pass

Missing blank line before block tags

Separate block tag group from the summary with a blank line.

Before

/**
 * Returns the absolute value of the given number.
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
void abs(int number) {}
/**
 * Returns the absolute value of the given number.
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
def abs(int number) {}
/**
 * Returns the absolute value of the given number.
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
fun abs(number: Int): Int

After

/**
 * Returns the absolute value of the given number.
 *
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
void abs(int number) {}
/**
 * Returns the absolute value of the given number.
 *
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
def abs(int number) {}
/**
 * Returns the absolute value of the given number.
 *
 * @param number The number to return the absolute value for.
 * @return The absolute value.
 */
fun abs(number: Int): Int

Unnecessary blank line before package

The first line of a file cannot be a blank line.

Before

\n

package com.example;

void execute() {}
\n

package com.example

def execute() {}
\n

package com.example

fun execute() {}
\n

def execute():
    pass

After

package com.example;

void execute() {}
package com.example

def execute() {}
package com.example

fun execute() {}
def execute():
    pass

Stating

Illegal catch

Catch specific exception subclass instead of the generic Throwable, Exception or Error.

Before

try {
    unsafeOperation();
} catch (Throwable e) {
    e.printStackTrace();
}
try {
    unsafeOperation()
} catch (Throwable e) {
    e.printStackTrace()
}
try:
    unsafe_operation()
except Exception as e:
    print(e)

After

try {
    unsafeOperation();
} catch (IOException | SQLException e) {
    e.printStackTrace();
}
try {
    unsafeOperation()
} catch (IOException | SQLException e) {
    e.printStackTrace()
}
try:
    unsafe_operation()
except (IOError, OSError) as e:
    print(e)

Illegal throw

Throw a narrower exception type instead of Exception, Error or Throwable.

Before

throw new Exception();
throw new Exception()
throw Exception()
raise Exception()

After

throw new IllegalStateException();
throw new IllegalStateException()
throw IllegalStateException()
raise ValueError()

Missing braces

Enforces the use of braces for multiline if, else, for, while and do statements.

Before

if (validateCart(cart))
    processPayment(credentials);
else
    showError();
if (validateCart(cart))
    processPayment(credentials)
else
    showError()
if (validateCart(cart))
    processPayment(credentials)
else
    showError()

After

if (validateCart(cart)) {
    processPayment(credentials);
} else {
    showError();
}
if (validateCart(cart)) {
    processPayment(credentials)
} else {
    showError()
}
if (validateCart(cart)) {
    processPayment(credentials)
} else {
    showError()
}

Nested if-else

If a block ends with an if statement without else and the body is at least 2 lines, it should be inverted to avoid nesting and unnecessary indentation.

Before

void login(User user) {
    if (user.isValid()) {
        if (!isLoggedIn(user)) {
            updateProfile(user);
            displayDashboard();
        }
    }
}
def login(User user) {
    if (user.isValid()) {
        if (!isLoggedIn(user)) {
            updateProfile(user)
            displayDashboard()
        }
    }
}
fun login(user: User) {
    if (user.isValid()) {
        if (!isLoggedIn(user)) {
            updateProfile(user)
            displayDashboard()
        }
    }
}
def login(user: User):
    if user.is_valid():
        if not is_logged_in(user):
            update_profile(user)
            display_dashboard()

After

void login(User user) {
    if (!user.isValid()) {
        return;
    }
    if (isLoggedIn(user)) {
        return;
    }
    updateProfile(user);
    displayDashboard();
}
def login(User user) {
    if (!user.isValid()) {
        return
    }
    if (isLoggedIn(user)) {
        return
    }
    updateProfile(user)
    displayDashboard()
}
fun login(user: User) {
    if (!user.isValid()) {
        return
    }
    if (isLoggedIn(user)) {
        return
    }
    updateProfile(user)
    displayDashboard()
}
def login(user: User):
    if not user.is_valid():
        return
    if is_logged_in(user):
        return
    update_profile(user)
    display_dashboard()

Redundant default

If every branch of a switch statement has a return or throw statement, the default branch can be lifted.

Before

void park(Car car) {
    switch (car) {
        case MOVING:
            throw new IllegalStateException();
        case PARKED:
            return;
        default:
            findParking(car);
    }
}
def park(Car car) {
    switch (car) {
        case MOVING:
            throw new IllegalStateException()
        case PARKED:
            return
        default:
            findParking(car)
    }
}
fun park(car: Car) {
    when {
        car.isMoving() -> throw IllegalStateException()
        car.isParked() -> return
        else -> findParking(car)
    }
}
def park(car: Car):
    match car:
        case Car.MOVING:
            raise ValueError()
        case Car.PARKED:
            return
        case _:
            find_parking(car)

After

void park(Car car) {
    switch (car) {
        case MOVING:
            throw new IllegalStateException();
        case PARKED:
            return;
    }
    findParking(car);
}
def park(Car car) {
    switch (car) {
        case MOVING:
            throw new IllegalStateException()
        case PARKED:
            return
    }
    findParking(car)
}
fun park(car: Car) {
    when {
        car.isMoving() -> throw IllegalStateException()
        car.isParked() -> return
    }
    findParking(car)
}
def park(car: Car):
    match car:
        case Car.MOVING:
            raise ValueError()
        case Car.PARKED:
            return
    find_parking(car)

Redundant else

When every if and else-if block has a return or throw statement, the else block can be lifted.

Before

void park(Car car) {
    if (car.isMoving()) {
        throw new IllegalStateException();
    } else if (car.isParked()) {
        return;
    } else {
        findParking(car);
    }
}
def park(Car car) {
    if (car.isMoving()) {
        throw new IllegalStateException()
    } else if (car.isParked()) {
        return
    } else {
        findParking(car)
    }
}
fun park(car: Car) {
    if (car.isMoving()) {
        throw IllegalStateException()
    } else if (car.isParked()) {
        return
    } else {
        findParking(car)
    }
}
def park(car: Car):
    if car.is_moving():
        raise ValueError()
    elif car.is_parked():
        return
    else:
        find_parking(car)

After

void park(Car car) {
    if (car.isMoving()) {
        throw new IllegalStateException();
    }
    if (car.isParked()) {
        return;
    }
    findParking(car);
}
def park(Car car) {
    if (car.isMoving()) {
        throw new IllegalStateException()
    }
    if (car.isParked()) {
        return
    }
    findParking(car)
}
fun park(car: Car) {
    if (car.isMoving()) {
        throw IllegalStateException()
    }
    if (car.isParked()) {
        return
    }
    findParking(car)
}
def park(car: Car):
    if car.is_moving():
        raise ValueError()
    if car.is_parked():
        return
    find_parking(car)

Unnecessary switch

If a switch statement has single branch, it should be replaced with an if statement.

Before

switch (token) {
    case VALUE_TOKEN:
        callback(token);
}
switch (token) {
    case VALUE_TOKEN:
        callback(token)
}
when (token) {
    is Token.ValueToken -> callback(token)
}
match token:
    case Token.VALUE_TOKEN:
        callback(token)

After

if (token == Token.VALUE_TOKEN) {
    callback(token);
}
if (token == Token.VALUE_TOKEN) {
    callback(token)
}
if (token is Token.ValueToken) {
    callback(token)
}
if token == Token.VALUE_TOKEN:
    callback(token)

Wrapping

Assignment wrap

Assignee and the value of assignment spanning multiple lines should be separated by a newline.

Before

String message = new StringBuilder()
    .append("Hello")
    .toString();
val message = new StringBuilder()
    .append('Hello')
    .toString()
val message = buildString {
    append("Hello")
}

After

String message =
    new StringBuilder()
        .append("Hello")
        .toString();
var message =
    new StringBuilder()
        .append('Hello')
        .toString()
val message =
    buildString {
        append("Hello")
    }

Chain call wrap

Each method call in a chain should be aligned with the dot operator.

Before

int senderId =
    notification.getSender()
        .getId();
var senderId =
    notification.getSender()
        .getId()
val senderId =
    notification.getSender()
        .id.takeIf { it.isNotBlank() }

After

int senderId =
    notification
        .getSender()
        .getId();
var senderId =
    notification
        .getSender()
        .getId()
val senderId =
    notification
        .getSender()
        .id

Elvis wrap

In a multiline statement, the elvis operator should be separated into a new line instead of trailing the statement.

Before

user.name
    .takeIf { it.isNotBlank() } ?: "Unknown"

After

user.name
    .takeIf { it.isNotBlank() }
    ?: "Unknown"

Empty code block join

Whitespace is not allowed in empty code blocks.

Before

void main() {
}
def main() {
}
fun main() {
}

After

void main() {}
def main() {}
fun main() {}

Tip

Code blocks with comments are not considered empty.

Infix call wrap

When breaking an infix function call, the operator should be placed at the end of the line.

Before

val ages =
    mapOf(
        "Alice"
            to 25,
        "Bob"
            to 30,
    )

After

val ages =
    mapOf(
        "Alice" to
            25,
        "Bob" to
            30,
    )

Lambda wrap

When breaking a multiline lambda expression, the body should be placed on a new line.

Before

int sum =
    IntStream
        .range(0, 10)
        .map(i -> i
            * 2
        ).sum();
var sum =
    IntStream
        .range(0, 10)
        .map { i -> i
            * 2
        }.sum()

After

int sum =
    IntStream
        .range(0, 10)
        .map(i ->
            i * 2
        ).sum();
var sum =
    IntStream
        .range(0, 10)
        .map { i ->
            i * 2
        }.sum()

Operator wrap

A line break should be placed after the operator in a binary expression.

Before

int total =
    subtotal
    + tax
    - discount;
var total =
    subtotal
    + tax
    - discount
val total =
    subtotal
    + tax
    - discount

After

int total =
    subtotal +
    tax -
    discount;
var total =
    subtotal +
    tax -
    discount
val total =
    subtotal +
    tax -
    discount

Parameter wrap

When breaking a multiline parameter list, each parameter should be placed on a new line.

Before

void createUser(
    String name, String email, int age
)
def createUser(
    String name, String email, int age
)
fun createUser(
    name: String, email: String, age: Int
)
def create_user(
    name: str, email: str, age: int
)

After

void createUser(
    String name,
    String email,
    int age
)
def createUser(
    String name,
    String email,
    int age,
)
fun createUser(
    name: String,
    email: String,
    age: Int,
)
def create_user(
    name: str,
    email: str,
    age: int,
)

Short block comment join

Short block comments should be written in a single line.

Before

/**
 * The quick brown fox jumps over the lazy dog.
 */
/**
 * The quick brown fox jumps over the lazy dog.
 */
/**
 * The quick brown fox jumps over the lazy dog.
 */

After

/** The quick brown fox jumps over the lazy dog. */
/** The quick brown fox jumps over the lazy dog. */
/** The quick brown fox jumps over the lazy dog. */

Statement wrap

Compound statements are not allowed.

Before

int x = 0; int y = 0;
var x = 0; var y = 0
val x = 0; val y = 0
x = 0; y = 0

After

int x = 0;
int y = 0;
var x = 0
var y = 0
val x = 0
val y = 0
x = 0
y = 0