<?xml version="1.0" encoding="UTF-8"?>
<test-data
    xmlns="http://pmd.sourceforge.net/rule-tests"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://pmd.sourceforge.net/rule-tests http://pmd.sourceforge.net/rule-tests_1_0_0.xsd">

    <test-code>
        <description>one case, which is not empty</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>6</expected-linenumbers>
        <code><![CDATA[
public class Foo {
    void main() {
        switch(i) {
        case 1:
            doSomething();
        default:
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>just skip empty switch</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    void main() {
        switch(i) {
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>one break, but two cases + one default case. But there is an intentional fall through -
because there are no statemenets between case 1 and case 2.</description>
        <!--
        Indeed if there is no statement between the two cases, then no break
        should be expected between those cases.
        In C, there is a MISRA rule 15.2 which states:

        "An unconditional break statement shall terminate every non-empty
        switch clause"
        -->
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    void main() {
        switch(i) {
        case 1:
        case 2:
            break;
        default:
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>each case stmt has a return</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    int main() {
        switch(i) {
        case '1':
            return 1;
        case '2':
            return 2;
        default:
            return 3;
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>all cases have return or throw</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    int main() {
        switch(i) {
        case '1':
            return 1;
        case '2':
            return 2;
        default:
            throw new Exception("bad number");
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>3496028: False-</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
public class Foo {
    public void m() {
        switch (s) {
            case 0 :
                s2 = s ;
                // missing break here!
            case 1 :
                s2 = (short)(s + 1);
                break;
            default :
                s2 = (short)(s + 2);
                // and missing break here!
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1246 False positive from MissingBreakInSwitch</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public static final int x1 = 1;
    public static final int x2 = 2;
    public static final int x3 = 3;

    public Object bar(int x, boolean condition) {
        switch (x)
        {
            case x1:
            case x2:
                if (condition)
                    return new Object();
                else
                    return null;
            case x3:
                if (condition)
                    return new Object();
                else
                    return null;
            default:
                return null;
        }
    }
}
        ]]></code>
    </test-code>


    <test-code>
        <description>#550 False +: MissingBreakInSwitch</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    public String bar() {
        switch (sign) {
        case  1:
            return "+";
        case  0:
            return "0";
        case -1:
            return "-";
        default:
            throw new IllegalArgumentException();
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1262 False positive for MissingBreakInSwitch</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Foo {
    private boolean isAorB(MyEnum value)
    {
      switch (value)
      {
        case A:
        case B:
        {
          return true;
        }
        default:
        {
          return false;
        }
      }
    }

    enum MyEnum { A, B; }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#1552  MissingBreakInSwitch - False positive for continue</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class DemoMissingBreakContinue {
    public DemoMissingBreakContinue() {
        method();
    }

    private void method() {
        for (int i = 0; i < 10; i = i + 1) {
            switch (i) {
            case 1:
                break;
            case 2:
                continue; //PMD complains about missing break which would be unreachable code
            default:
                break;
            }
        }
    }
}
        ]]></code>
    </test-code>
    <test-code>
        <description>Possible fallthrough</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>8</expected-linenumbers>
        <code><![CDATA[
public class DemoMissingBreakContinue {

    private void method() {
        for (int i = 0; i < 10; i = i + 1) {
            switch (i) {
            case 1: break;
            case 2: if (i != 4) continue;
            default: break;
            }
        }
    }
}
        ]]></code>
    </test-code>
    <test-code>
        <description>Possible fallthrough, commented so ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class DemoMissingBreakContinue {

    private void method() {
        for (int i = 0; i < 10; i = i + 1) {
            switch (i) {
            case 1: break;
            case 2: if (i != 4) continue;
            // fallthrough
            default: break;
            }
        }
    }
}
        ]]></code>
    </test-code>
    <test-code>
        <description>[java] Recognize @SuppressWanings("fallthrough") for MissingBreakInSwitch #1899</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class DemoMissingBreakContinue {

    @SuppressWarnings("fallthrough")
    private void method() {
        for (int i = 0; i < 10; i = i + 1) {
            switch (i) {
            case 1: break;
            case 2: if (i != 4) continue;
            default: break;
            }
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>[java] MissingBreakInSwitch detects the lack of break in the last case #2579</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class DemoMissingBreak {
    private double a, b, c, d, e, tmin, tmax;

    public void foo(int paramInt, double paramDouble) {
        switch (paramInt) {
            case 0:
              this.a = paramDouble; break;
            case 1:
              this.b = paramDouble; break;
            case 2:
              this.c = paramDouble; break;
            case 3:
              this.d = paramDouble; break;
            case 4:
              this.e = paramDouble; break;
            case 5:
              this.tmin = paramDouble; break;
            case 6:
              this.tmax = paramDouble;
        }
    }

    public void bar(int type) {
        switch (type) {
            case 1:
                System.out.println("one");
                break;
            default:
                System.out.println("def");
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>[java] MissingBreakInSwitch - last default case does not contain a break #659</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.math.MathContext;
public class DemoMissingBreak {
    public MathContext foo(int precission) {
        MathContext mc = null;
        switch (precission) {
            case 32:
                mc = MathContext.DECIMAL32;
                break;
            case 64: 
                mc = MathContext.DECIMAL64;
                break;
            case 128:
                mc = MathContext.DECIMAL128;
                break;
            default:
                mc = new MathContext(precission);
        }
        return mc;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>[java] MissingBreakInSwitch - last default case does not contain a break #659</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>14</expected-linenumbers>
        <code><![CDATA[
import java.math.MathContext;
public class DemoMissingBreak {
    public MathContext foo(int precission) {
        MathContext mc = null;
        switch (precission) {
            case 32:
                mc = MathContext.DECIMAL32;
                break;
            case 64:
                mc = MathContext.DECIMAL64;
                break;
            default:
                mc = new MathContext(precission);
            case 128: // violation!!
                mc = MathContext.DECIMAL128;
                break;
        }
        return mc;
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>NPE with Switch in record constructor</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>16</expected-linenumbers>
        <code><![CDATA[
record MyRecord(boolean b) {
    public MyRecord {
        int n = 8;
        // no fallthrough
        switch (n) {
            case 1:
                doSomething();
                break;
            default:
                break;
        }
        // implicit fallthrough
        switch (n) {
            case 1:
                doSomething();
            default:
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>#4505 NPE with Switch in enum constant body</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>7</expected-linenumbers>
        <code><![CDATA[
            enum Foo {
                A {
                    void foo() {
                        switch (A) {
                        case A:
                            if (A != null) {}
                        default:
                            throw new UnsupportedOperationException();
                        }
                    }
                }
            }

            ]]></code>
    </test-code>
    <test-code>
        <description>#4948 FP with nested switch stmt</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            public class Test {
                boolean foo(String a, String b) {

                    switch (a) {
                    case "a1":
                        return true;
                    case "a2":
                        switch (b) {
                        case "b1":
                            return true;
                        default:
                            return false;
                        }
                    default:
                        return false;
                    }
                }

            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Switch with loop with break</description>
        <expected-problems>3</expected-problems>
        <expected-linenumbers>11,14,18</expected-linenumbers>
        <code><![CDATA[
            public class Test {
                boolean foo(String a, String b) {

                    switch (a) {
                    case "a1":
                        switch (b) {
                        case "b1":
                            for (int i = 0; i < 4; i++) {
                                break;
                            } // this loop completes normally
                        default: // warn
                            return false;
                        }
                    case "a2": // warn
                        for (int i = 0; i < 4; i++) {
                            break;
                        } // this loop completes normally
                    default: // warn
                        return false;
                    }
                }

            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Switch with loop with break</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>6</expected-linenumbers>
        <code><![CDATA[
            public class Test {
                boolean foo(int a) {
                    switch (a) {
                    case 1:
                        switch(hashCode()){}
                    case 2: // violation
                        System.lineSeparator();
                    break;
                    }
                }

            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Switch with break to enclosing block</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Test {
    boolean foo(int a) {
        parsing:
        {
            if (method()) {

            }
            int index;
            switch (a) {
            case 1:
                if (method()) {
                    if (method()) {
                        return true;
                    }
                } else {
                    if (method()) {
                        return true;
                    }
                }
                break parsing;
            case 2:
            case 3:
                System.lineSeparator();
                break;
            }
        }
    }



}
            ]]></code>
    </test-code>
    <test-code>
        <description>Switch expr</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
public class Test {

    private String print2(int i, int j, int k) {
        return switch (i) {
            case 0:
                String r;
                OUTER: switch (j) {
                case 0:
                    String res;
                    INNER: switch (k) {
                    case 0: res = "0-0-0"; break;
                    case 1: res = "0-0-1"; break;
                    case 2: res = "0-0-2"; break INNER;
                    default: r = "0-0-X"; break OUTER;
                    }
                    r = res;
                    break;
                case 1:
                    r = "0-1";
                    break;
                default:
                    r = "0-X";
                    break;
                }
                yield r;
            case 1:
                yield "1";
            case 2:
                LOP: while (j-- > 0) {
                    if (k == 5) {
                        k--;
                        continue;
                    }
                    break LOP;
                }
                Supplier<String> getter = () -> { return "2-X-5"; };
                yield getter.get();
            default:
                yield "X";
        };
    }
}
            ]]></code>
    </test-code>

    <test-code>
        <description>switch expression with one case, which is not empty</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>6</expected-linenumbers>
        <code><![CDATA[
public class Foo {
  public static void main(String[] args) {
    int i = 1;
    String result = switch(i) {
      case 1: doSomething();
      default: yield "default case fall through";
    };
    System.out.println(result);
  }

  private static void doSomething() {}
}
]]></code>
    </test-code>
</test-data>
