Empty for body, else branch or do body

ID

apex.correctness.empty_statement_block

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Dead Code

Language

Apex

Description

Reports an empty for body (both the for-each and the counted form), an empty else branch, and an empty do body.

Rationale

Each of these costs something and returns nothing. An empty for still walks the whole collection and still counts every iteration against the CPU limit, so a loop over a batch scope burns time to produce no effect. An empty do body is worse: the loop re-tests a condition nothing inside it can change, so it either exits immediately or spins until the transaction is killed on the CPU limit. An empty else states that a case was considered and then leaves it unhandled, which is indistinguishable from the branch whose body was deleted during a merge - and that is usually what it is.

The following code illustrates the pattern detected by this rule:

public class BatchSummariser {

    public static Integer countAccounts(List<Account> accounts) {
        Integer total = 0;
        // FLAGGED: Empty for body, else branch or do body
        for (Account a : accounts) {
        }
        return total;
    }

    public static void warmUp(Integer rounds) {
        // FLAGGED: Empty for body, else branch or do body
        for (Integer i = 0; i < rounds; i++) {
        }
    }

    public static String label(Account a) {
        String text;
        // FLAGGED: Empty for body, else branch or do body
        if (a.Name != null) {
            text = a.Name;
        } else {
        }
        return text;
    }

    public static void drain(Integer pending) {
        // FLAGGED: Empty for body, else branch or do body
        do {
        } while (pending > 0);
    }

    public static Integer countAccountsFixed(List<Account> accounts) {
        Integer total = 0;
        for (Account a : accounts) {
            total++;
        }
        return total;
    }

    public static String labelFixed(Account a) {
        String text;
        if (a.Name != null) {
            text = a.Name;
        } else {
            text = 'unnamed';
        }
        return text;
    }

    public static void noop(Account a) {
        if (a.Name == null) {
        }
    }

    public static void spin(Boolean pending) {
        while (pending) {
        }
    }

    public static void neither(Account a) {
        if (a.Name == null) {
        } else {
        }
    }
}

Remediation

Restore the work the block was meant to do, or delete the construct entirely: drop the loop, and drop the else if the if alone says what is meant. Where a branch is deliberately a no-op, say so with a comment naming the case, so the next reader is not left deciding whether something was lost.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved