<?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>Basic Violations</description>
        <expected-problems>5</expected-problems>
        <expected-linenumbers>12,15,18,23,28</expected-linenumbers>
        <code><![CDATA[
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.uilt.HashMap;

public class UnnecessaryCastSample {
    private Map<Integer, String> map = new HashMap<>();

    public void localVars() {
        List<String> stringList = Arrays.asList("a");
        String element = (String) stringList.get(0);

        List<Double> doubleList = new ArrayList<>();
        Double number = (Double) doubleList.get(0);

        Map<String, String> stringMap = new HashMap<>();
        String mapData = (String) stringMap.get("a");
    }

    public void fields() {
        map.put(1, "test");
        String val = (String) map.get(1);
    }

    public void fields2() {
        this.map.put(1, "test");
        String val = (String) this.map.get(1);
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Without casts there should be no violation</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.uilt.HashMap;

public class UnnecessaryCastSample {
    private Map<Integer, String> map = new HashMap<>();

    public void localVars() {
        List<String> stringList = Arrays.asList("a");
        String element = stringList.get(0);

        List<Double> doubleList = new ArrayList<>();
        Double number = doubleList.get(0);
    }

    public void fields() {
        map.put(1, "test");
        String val = map.get(1);
    }

    public void fields2() {
        this.map.put(1, "test");
        String val = this.map.get(1);
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Unnecessary casts with iterator</description>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>8,15</expected-linenumbers>
        <code><![CDATA[
import java.util.*;

public class UnnecessaryCastSample {
    public void localVars() {
        List<String> stringList = Arrays.asList("a");
        Iterator<String> stringIt = stringList.iterator();
        while (stringIt.hasNext()) {
            String element = (String) stringIt.next();
            String element2 = stringIt.next();
        }

        List<Double> doubleList = new ArrayList<>();
        Iterator<Double> doubleIt = doubleList.iterator();
        while (doubleIt.hasNext()) {
            Double number = (Double) doubleIt.next();
            Double number2 = doubleIt.next();
        }
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Avoid cast false-positives</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.util.*;
public class UnnecessaryCastSample {
    public void localVars() {
        List<Number> numbers = Arrays.asList(1, 2, 3);
        Integer myInt = (Integer) numbers.get(0);

        List<Object> data = new ArrayList<>();
        String item = (String) data.get(0);

        Map<String, ?> map = new HashMap<>();
        String dataFromMap = (String) map.get("foo");
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Avoid clone false-positive</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.util.*;
public class UnnecessaryCastSample {
    public void localVars() {
        List<String> strings = new ArrayList<>();
        List<String> copy = (List<String>) strings.clone();
    }
}
        ]]></code>
    </test-code>

    <test-code>
        <description>Necessary Map Cast (nested generics) false-positive</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class MapCasts {
    private final Map<Class<?>, Map<String, ?>> resourceCaches = new ConcurrentHashMap<>(4);

    @SuppressWarnings("unchecked")
    public <T> Map<String, T> getResourceCache(Class<T> valueType) {
        return (Map<String, T>) this.resourceCaches.computeIfAbsent(valueType, key -> new ConcurrentHashMap<>());
    }
}
        ]]></code>
    </test-code>
    <test-code>
        <description>Unnecessary (primitive -> primitive) casts</description>
        <expected-problems>4</expected-problems>
        <expected-linenumbers>5,6,7,8</expected-linenumbers>
        <code><![CDATA[
            class Scratch {
                public static void main(String[] args) {
                    Integer integer = 2; // ok

                    long a = (int) Integer.valueOf(2);  // explicit boxing where the value would be autoboxed
                    int b = (int) 2;                    // unnecessary, it's the same type
                    long c = (int) 4;                   // widening can be implicit
                    double c = (int) 4;                 // widening can be implicit
                    double c = (int) 4.0;               // cast is narrowing so necessary
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Tests from the doc</description>
        <expected-problems>2</expected-problems>
        <code><![CDATA[
            class Scratch {
                public static void main(String[] args) {
                    Object context = (Comparable) "o";
                    Integer integer = (Integer) 1;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Context is array index</description>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>3,4</expected-linenumbers>
        <code><![CDATA[
            class Scratch {
                public static void main(String[] args, Integer i, Double d) {
                    args[(int) i] = "";   // unnecessary
                    args[(int) '0'] = ""; // unnecessary
                    args[(int) 0.5] = ""; // narrowing so necessary
                    args[(int) d] = "";   // unboxing + narrowing so necessary
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Context is invocation, no overloads</description>
        <!-- TODO for now this is explicitly disabled -->
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {
                public static void main(String[] args, Integer i, Double d) {
                    doSt((int) i); // unnecessary
                }

                static void doSt(int i) {}
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Context is invocation, some overloads</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {
                public static void main(String[] args, Integer i, Double d) {
                    doSt((int) i); // necessary
                }

                static void doSt(int i) {}
                static void doSt(Integer i) {}
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Unchecked cast FP</description>
        <!-- There's a corresponding type res unit test in UncheckedInference.kt -->
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            // Note: Enum is raw, not Enum<T>
            class StringToEnum<T extends Enum> implements Converter<String, T> {

                private final Class<T> enumType;

                public StringToEnum(Class<T> enumType) {
                    this.enumType = enumType;
                }

                @Override
                public T convert(String source) {
                    // Because `this.enumType` is raw, the expr `Enum.valueOf(...)` has its
                    // return type erased to Enum
                    // So the cast is necessary
                    return (T) Enum.valueOf(this.enumType, source.trim());
                }
            }

            interface Converter<From, To> {
                To convert(From source);
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast as target type for method reference/lambda FP</description>
        <!-- https://github.com/spring-projects/spring-framework/blob/v5.0.6.RELEASE/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/InterceptorRegistry.java#L81 -->
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            import java.util.Comparator;

            class Test {

                static {
                    Comparator<Object> comparator;
                    comparator = OrderComparator.withSourceProvider(object -> {
                        if (object instanceof InterceptorRegistration) {
                            // Context type for the return is Object.
                            // The method ref cannot target Object though
                            // it needs Ordered as a functional interface
                            return (Ordered) ((InterceptorRegistration) object)::getOrder;
                        }
                        return null;
                    });
                    // same here
                    comparator = OrderComparator.withSourceProvider(object -> {
                        return (Ordered) () -> 0;
                    });
                    // same here
                    comparator = OrderComparator.withSourceProvider(object -> (Ordered) () -> 0);
                }


            }

            interface InterceptorRegistration {
                int getOrder();
            }

            class OrderComparator implements Comparator<Object> {
                public static Comparator<Object> withSourceProvider(OrderSourceProvider sourceProvider) {
                    return (o1, o2) -> null; // body is irrelevant
                }

                @FunctionalInterface
                public interface OrderSourceProvider {
                    Object getOrderSource(Object obj);
                }
            }

            @FunctionalInterface
            interface Ordered {
                int getOrder();
            }

            ]]></code>
    </test-code>
    <test-code>
        <description>Cast as target type for method reference/lambda FP (2)</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            import java.util.Comparator;

            class Test {

                static {
                    InterceptorRegistration comparator;
                    comparator = (Ordered) Test::getAnInt;
                    comparator = (Ordered) () -> 0;
                }

                static int getAnInt() {return 0;}
            }

            interface InterceptorRegistration {
                int getOrder();
            }

            @FunctionalInterface
            interface Ordered extends InterceptorRegistration {
                int getOrder();
            }

            ]]></code>
    </test-code>
    <test-code>
        <description>Cast as target type for method reference/lambda (ok)</description>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>7,8</expected-linenumbers>
        <expected-messages>
            <message>Unnecessary cast (Ordered)</message>
            <message>Unnecessary cast (Ordered)</message>
        </expected-messages>
        <code><![CDATA[
            import java.util.Comparator;

            class Test {

                static {
                    Ordered comparator;
                    comparator = (Ordered) Test::getAnInt;
                    comparator = (Ordered) () -> 0;
                }

                static int getAnInt() {return 0;}
            }

            interface InterceptorRegistration {
                int getOrder();
            }

            @FunctionalInterface
            interface Ordered extends InterceptorRegistration {
                int getOrder();
            }

            ]]></code>
    </test-code>
    <test-code>
        <description>Cast as target type for method reference/lambda, with enclosing invoc context</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            import java.lang.reflect.Constructor;
            import java.security.AccessController;
            import java.security.PrivilegedAction;

            class Test {
                static {
                    Object beanInstance;

                    if (System.getSecurityManager() != null) {
                        // these method calls are ambiguous if the cast is omitted
                        // (there's a PrivilegedExceptionAction overload)
                        beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) () -> new Object());
                        beanInstance = AccessController.doPrivileged((PrivilegedAction<Object>) Object::new);
                    }
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast over a ternary</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>14</expected-linenumbers>
        <code><![CDATA[
            import java.lang.reflect.Constructor;
            import java.security.AccessController;
            import java.security.PrivilegedAction;

            class Test {

                void fun(boolean messageSelector) {
                    String textFromMessage = (String) (messageSelector ? methodThatReturnsObject("selectorString")
                                                                       : "string");
                    textFromMessage = (String) (messageSelector ? methodThatReturnsObject("selectorString")
                                                                : another());

                    // only this one is unnecessary
                    textFromMessage = (String) (messageSelector ? "methodThatReturnsObject(selectorString)"
                                                                : "string");
                }

                Object methodThatReturnsObject(String s) {return null;}

                Object another() {return null;}

            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast over target-dependent ternary</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            import java.util.Collection;
            import java.util.List;
            import java.util.Set;

            class Test {

                Collection<String> fun(boolean messageSelector) {
                    Collection<String> textFromMessage =
                            // compile error: a cast doesn't contribute a target type,
                            // the ternary is inferred to Collection<Object>
                            // TODO should this be a positive? If you remove the cast the code will still compile,
                            // but its typing will change
                            (Collection<String>) (messageSelector ? emptyList() : emptySet());

                    // ok
                    return (messageSelector ? emptyList() : emptySet());
                }

                <T> List<T> emptyList() {return null;}

                <T> Set<T> emptySet() {return null;}

            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast over ternary mixing boxing/null/primitive</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>4</expected-linenumbers>
        <code><![CDATA[
            class Scratch {

                public static void main(String[] args) {
                    double z = (Integer) // here
                            ((0.2 == Math.random()) ? (Integer) null + apply(null) // this one is required so that + applies
                                                    : (0.3 == Math.random()) ? (Integer) null // this one could be removed but whatever
                                                                             : (int) Math.sin(300 * (12 + 30))); // this one is narrowing
                }

                public static int apply(Object o) { return 0; }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast that determines boxing when context is Object</description>
        <expected-problems>5</expected-problems>
        <expected-linenumbers>7,10,12,14,16</expected-linenumbers>
        <code><![CDATA[
            class Scratch {
                public Object zero() {
                    switch (this) {
                    case BOOLEAN:
                        return Boolean.FALSE;
                    case INT:
                        return (Integer)0; // here
                    // in the following double casts, the first one is unnecessary
                    case BYTE:
                        return (Byte)(byte)0;
                    case CHAR:
                        return (Character)(char)0;
                    case SHORT:
                        return (Short)(short)0;
                    case LONG:
                        return (Long)(long)0;
                    case FLOAT:
                        return FLOAT_ZERO;
                    case DOUBLE:
                        return DOUBLE_ZERO;
                    case VOID:
                    case OBJECT:
                    default:
                        return null;
                    }
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Byte arithmetic</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {
                public void putTag(byte tagClass, boolean form, byte val) {
                    // result of the OR is widened to int,
                    // then needs to be narrowed
                    byte tag = (byte) (tagClass | val);
                    if (form) {
                        tag |= (byte) 0x20; // narrowing from int
                    }
                    write(tag);
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>FP, removing both casts changes program</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {

                public void putTag(boolean useLong, int n) {
                    // ONE of them is necessary, because if we remove both they'd
                    //  both be mapped to long, then boxed to Long and stored in Number

                    Number result =
                            useLong ? (Number) Long.valueOf(n)
                                    : (Number) Integer.valueOf(n);
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>TP in ternary</description>
        <!-- Note: the other is technically removable as well but that would change the type of the ternary -->
        <expected-problems>1</expected-problems>
        <expected-linenumbers>5</expected-linenumbers>
        <code><![CDATA[
            class Scratch {

                public void putTag(boolean useLong, int n) {
                    double result = useLong ? (double) 1
                                            : (int) 2;   // removable, (2 : int)
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>[java] UnnecessaryCast false positive #2748 with unchecked cast</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            import java.util.List;

            class Scratch {

                public static <T> T[] asArray(List<T> list) {
                    T[] result = (T[]) list.toArray();
                    return result;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Boxing cast needs to box to the same type to be unnecessary</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
class Scratch {
    static {
        Object o = (Long) 3; // compile time error (int cannot be converted to Long)
        o = (long) 3; // makes it box to Long
    }
}
            ]]></code>
    </test-code>
    <test-code>
        <description>Chained casts to convert int to Long</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
class Scratch {
    static m(Integer boxedInt) {
        Object o = (long)
                (int) boxedInt; // both are necessary
    }
}
            ]]></code>
    </test-code>
    <test-code>
        <description>Assignment context is more flexible than cast</description>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>3,4</expected-linenumbers>
        <code><![CDATA[
class Scratch {
    static m(Integer boxedInt) {
        long l = (int) boxedInt; // unnecessary
        l = (long)               // unnecessary
                (int) boxedInt;  // necessary
        Object l = (long) (int) boxedInt; // both necessary
    }
}
            ]]></code>
    </test-code>
    <test-code>
        <description>Assert statements</description>
        <expected-problems>3</expected-problems>
        <code><![CDATA[
            class Scratch {
                static void m(Boolean boxedBool, boolean bool, String str) {
                    assert (boolean) boxedBool;
                    assert (boolean) bool;
                    assert bool : (String) str;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Conditionals and loop statements</description>
        <expected-problems>5</expected-problems>
        <code><![CDATA[
            class Scratch {
                static void m(Boolean boxedBool, boolean bool, String str, int[] ints) {
                    if ((boolean) boxedBool);
                    while ((boolean) boxedBool);
                    for (int i = 0; (boolean) boxedBool; i++) {}
                    do; while ((boolean) boxedBool);
                    for (int i : (int[]) ints);
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Conditional expr condition</description>
        <expected-problems>1</expected-problems>
        <code><![CDATA[
            class Scratch {
                static void m(Boolean boxedBool, boolean bool, String str, int[] ints) {
                    str = (boolean) boxedBool ? "a" : "b";
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Necessary cast for condition</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {
                static void m(Object obj) {
                    // both are necessary
                    if ((Boolean) obj
                        || (boolean) obj);
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Missing context identity cast</description>
        <expected-problems>2</expected-problems>
        <code><![CDATA[
            class Scratch {

                static void m(Boolean boxedBool) {
                    ((Boolean) boxedBool).booleanValue(); // same type
                    ((Object) boxedBool).toString(); // supertype
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Casts in arithmetic</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>4</expected-linenumbers>
        <code><![CDATA[
            class Scratch {
                static void m(int i, double d) {
                    Object o;
                    o = ((double) i) * d; // unnecessary
                    o = ((double) i) * i; // necessary
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Casts in shift exprs</description>
        <expected-problems>7</expected-problems>
        <expected-linenumbers>5,8,9,10,12,13,14</expected-linenumbers>
        <code><![CDATA[
            class Scratch {
                static void m(int i, short s, long l, Integer boxedInt) {
                    l  = (long) i << 2; // "necessary"
                    l  = (long) i << 34; // definitely necessary
                    l  = (long) (i << 34); // unnecessary, l5

                    i = i << (int) l;          // necessary
                    i = i << (int) boxedInt;   // unnecessary
                    i = (int) i << boxedInt;   // unnecessary
                    i = (int) (i << boxedInt); // unnecessary

                    i = (int) s << boxedInt;   // unnecessary, widened anyway
                    i = ((int) s) << boxedInt; // unnecessary, same expression with unnecessary parens
                    i = (int) (s << boxedInt); // unnecessary

                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Casts in arithmetic smaller than int </description>
        <expected-problems>9</expected-problems>
        <code><![CDATA[
            class Scratch {
                // they're all unecessary
                static void m(int i, byte b, char c, short s) {
                    i = b * (int) b; // 4
                    i = (int) b * b;
                    i = b * (int) s; // 6
                    i = b * (int) c;
                    i = b * (short) b; // 8
                    i = i * (short) b;
                    i = i * (short) s; // 10
                    i = i * (int) c;
                    i = i * (char) c; // 11
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Casts in arithmetic with unboxing + widening</description>
        <expected-problems>4</expected-problems>
        <code><![CDATA[
            class Scratch {
                static void m(Integer i, Double d, Object lhs) {
                    lhs = (int) i * 1.0;
                    lhs = (double) d * 1.01;
                    lhs = 1.01 * (int) i;
                    lhs = 1.01 * (double) d;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>"Narrowing" cast from char to short is necessary</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {

                static void m(int i, byte b, char c, short s) {
                    i = i * (short) c;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>char cast to int in string context is ok</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            class Scratch {

                static void m(String s, char c) {
                    // the toString is different -> necessary (string contexts aren't implemented yet)
                    s = "(" + (int) c + ")" + c;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>String cast determining context</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>5</expected-linenumbers>
        <code><![CDATA[
            class Scratch {
                static void m(Object a, Object b) {
                    String s = a + (String) b   // necessary, determines context
                            + a + (String) b    // technically unnecessary, but narrowing
                            + a + (String) null // unnecessary
                            ;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast on both sides of arithmetic</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>3</expected-linenumbers>
        <expected-messages>
            <message>Unnecessary cast (int)</message>
        </expected-messages>
        <code><![CDATA[
            class Scratch {
                static void m(short s, Object b) {
                    b = (int) s
                            + (long) s;
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Cast with assertion error??</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            public class InputParenPadLeftRightAndNoSpace {
                void method(boolean status) {
                    for (int i = 0; i < (long) (2 * (4 / 2)); i++);
                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Unnecessary cast to detect invocation part 1 - #3219</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>8</expected-linenumbers>
        <code><![CDATA[
class MyClass {
     void m(int i) {}
     void m(Integer i) {}
     void m(Object o) {}

     {
         m(1); // select m(int)
         m((int) 1); // select m(int), unnecessary
         m((Integer) 1); // select m(Integer), cast is necessary
         m((Object) Integer.valueOf(2)); // select m(Object) cast is necessary
     }
}
            ]]></code>
    </test-code>

    <test-code disabled="true">
        <!-- currently disabled, the rule fails to detect the violation on line 7 -->
        <description>Unnecessary cast to detect invocation part 2 - #3219</description>
        <expected-problems>2</expected-problems>
        <expected-linenumbers>6,7</expected-linenumbers>
        <code><![CDATA[
class MyClass {
     void m(int i) {}

     {
         m(1);   // select m(int)
         m((int) 1); // unnecessary
         m((Integer) 1); // unnecessary as the selected overload is anyway `int`
     }
}
            ]]></code>
    </test-code>
    <test-code>
        <description>Boxing in ternary</description>
        <expected-problems>0</expected-problems>
        <code><![CDATA[
            public abstract class Example {

                boolean cast(boolean shouldBeLong, int n) {
                    // The first valueOf call is necessary, not the second
                    Number result = shouldBeLong ?
                                    (Number)Long.valueOf(n) // ok
                                                 : (Number)Integer.valueOf(n); // warn
                    short s = 2;
                    // here both are necessary
                    result = shouldBeLong ?
                             (Number)Long.valueOf(s) : (Number)Integer.valueOf(s);


                }
            }
            ]]></code>
    </test-code>
    <test-code>
        <description>Unboxing in lambda</description>
        <expected-problems>1</expected-problems>
        <expected-linenumbers>4</expected-linenumbers>
        <code><![CDATA[
            public abstract class Example {
                VoidSpecies<Integer> mismatch = payload -> (int) payload; // nowarn: here the cast does a null check
                RefSpecies<Integer, Object> i = t -> (int) t; // nowarn: here the cast does a null check
                IntSpecies<Integer> i = t -> (int) t; // warn: in this context t->t is equivalent because it will be unboxed

                interface VoidSpecies<T> {
                    void doSomething(T t);
                }
                interface RefSpecies<T, X> {
                    X foo(T t);
                }
                interface IntSpecies<T> {
                    int foo(T t);
                }
            }
            ]]></code>
    </test-code>
</test-data>
