switch statement nested inside another switch

ID

apex.maintainability.nested_switch

Severity

high

Remediation Complexity

medium

Remediation Risk

medium

Remediation Effort

medium

Resource

Complexity

Language

Apex

Description

Reports a switch on statement declared inside a when branch of another switch on.

Rationale

Two nested switch statements express a decision table, and writing a table as nested code hides how many of its cells are actually filled in. The reader has to hold the outer value while enumerating the inner one to see which combination a line belongs to, and the combinations nobody wrote are invisible - which in an org means the new picklist value pairs with every existing one and lands in whichever branch happens to catch it. The nesting also grows badly: a third dimension doubles the indentation, and the whole block ends up recopied whenever one of the axes changes.

The following code illustrates the pattern detected by this rule:

public class ShipmentPricer {

    public static Decimal price(String country, String speed) {
        Decimal amount = 0;
        // FLAGGED: switch statement nested inside another switch
        switch on country {
            when 'ES' {
                switch on speed {
                    when 'Express' {
                        amount = 9.95;
                    }
                    when else {
                        amount = 4.95;
                    }
                }
            }
            when else {
                amount = 19.95;
            }
        }
        return amount;
    }

    public static String queue(String status, String channel) {
        String queue = 'none';
        // FLAGGED: switch statement nested inside another switch
        switch on status {
            when 'Draft' {
                queue = 'review';
            }
            when 'Activated' {
                switch on channel {
                    when 'Web' {
                        queue = 'web-fulfilment';
                    }
                    when else {
                        queue = 'fulfilment';
                    }
                }
            }
            when else {
                queue = 'none';
            }
        }
        return queue;
    }

    public static Decimal priceFlat(String country, String speed) {
        Decimal base = 0;
        switch on country {
            when 'ES' {
                base = 4.95;
            }
            when else {
                base = 19.95;
            }
        }
        switch on speed {
            when 'Express' {
                base = base + 5;
            }
            when else {
                base = base + 0;
            }
        }
        return base;
    }

    public static String label(String status, Boolean express) {
        String text = 'standard';
        switch on status {
            when 'Draft' {
                if (express) {
                    text = 'draft-express';
                } else {
                    text = 'draft';
                }
            }
            when else {
                text = 'standard';
            }
        }
        return text;
    }
}

Remediation

Move the inner switch into its own method named after the decision it makes, so the outer statement reads as one choice per branch. Where the two axes are genuinely a table, a Map keyed by the combination - or custom metadata holding the same rows - makes the missing combinations visible and lets an admin change them without a deployment.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved