| import java.lang.reflect.Field; |
| import org.checkerframework.checker.testchecker.wholeprograminference.qual.Parent; |
| import org.checkerframework.checker.testchecker.wholeprograminference.qual.Sibling1; |
| import org.checkerframework.checker.testchecker.wholeprograminference.qual.Sibling2; |
| import org.checkerframework.checker.testchecker.wholeprograminference.qual.ToIgnore; |
| import org.checkerframework.checker.testchecker.wholeprograminference.qual.Top; |
| import org.checkerframework.checker.testchecker.wholeprograminference.qual.WholeProgramInferenceBottom; |
| import org.checkerframework.framework.qual.IgnoreInWholeProgramInference; |
| |
| /** |
| * This file contains expected errors that should exist even after the jaif type inference occurs. |
| */ |
| public class ExpectedErrors { |
| |
| // Case where the declared type is a supertype of the refined type. |
| private @Top int privateDeclaredField; |
| public @Top int publicDeclaredField; |
| |
| // The type of both privateDeclaredField and publicDeclaredField are |
| // not refined to @WholeProgramInferenceBottom. |
| void assignFieldsToSibling1() { |
| privateDeclaredField = getSibling1(); |
| publicDeclaredField = getSibling1(); |
| } |
| |
| void testFields() { |
| // :: warning: (argument) |
| expectsSibling1(privateDeclaredField); |
| // :: warning: (argument) |
| expectsSibling1(publicDeclaredField); |
| } |
| |
| // Case where the declared type is a subtype of the refined type. |
| private @WholeProgramInferenceBottom int privateDeclaredField2; |
| public @WholeProgramInferenceBottom int publicDeclaredField2; |
| |
| // The refinement cannot happen and an assignemnt type incompatible error occurs. |
| void assignFieldsToTop() { |
| // :: warning: (assignment) |
| privateDeclaredField2 = getTop(); |
| // :: warning: (assignment) |
| publicDeclaredField2 = getTop(); |
| } |
| |
| // No errors should be issued below: |
| void assignFieldsToBot() { |
| privateDeclaredField2 = getBottom(); |
| publicDeclaredField2 = getBottom(); |
| } |
| |
| // Testing that the types above were not widened. |
| void testFields2() { |
| expectsBottom(privateDeclaredField2); |
| expectsBottom(publicDeclaredField2); |
| } |
| |
| // LUB TEST |
| // The default type for fields is @Top. |
| private static int lubPrivateField; |
| public static int lubPublicField; |
| |
| void assignLubFieldsToSibling1() { |
| lubPrivateField = getSibling1(); |
| lubPublicField = getSibling1(); |
| } |
| |
| static { |
| lubPrivateField = getSibling2(); |
| lubPublicField = getSibling2(); |
| } |
| |
| void testLUBFields1() { |
| // :: warning: (argument) |
| expectsSibling1(lubPrivateField); |
| // :: warning: (argument) |
| expectsSibling1(lubPublicField); |
| } |
| |
| void testLUBFields2() { |
| // :: warning: (argument) |
| expectsSibling2(lubPrivateField); |
| // :: warning: (argument) |
| expectsSibling2(lubPublicField); |
| } |
| |
| private static boolean bool = false; |
| |
| public static int lubTest() { |
| if (bool) { |
| return (@Sibling1 int) 0; |
| } else { |
| return (@Sibling2 int) 0; |
| } |
| } |
| |
| public @Sibling1 int getSibling1Wrong() { |
| int x = lubTest(); |
| // :: warning: (return) |
| return x; |
| } |
| |
| public @Sibling2 int getSibling2Wrong() { |
| int x = lubTest(); |
| // :: warning: (return) |
| return x; |
| } |
| |
| void expectsSibling1(@Sibling1 int t) {} |
| |
| void expectsSibling2(@Sibling2 int t) {} |
| |
| void expectsBottom(@WholeProgramInferenceBottom int t) {} |
| |
| void expectsBottom(@WholeProgramInferenceBottom String t) {} |
| |
| void expectsTop(@Top int t) {} |
| |
| void expectsParent(@Parent int t) {} |
| |
| static @Sibling1 int getSibling1() { |
| return 0; |
| } |
| |
| static @Sibling2 int getSibling2() { |
| return 0; |
| } |
| |
| @WholeProgramInferenceBottom int getBottom() { |
| return 0; |
| } |
| |
| @Top int getTop() { |
| return 0; |
| } |
| |
| // Method Field.setBoolean != ExpectedErrors.setBoolean. |
| // No refinement should happen. |
| void test(Field f) throws Exception { |
| f.setBoolean(null, false); |
| } |
| |
| void setBoolean(Object o, boolean b) { |
| // :: warning: (assignment) |
| @WholeProgramInferenceBottom Object bot = o; |
| } |
| |
| public class SuppressWarningsTest { |
| // Tests that whole-program inference in a @SuppressWarnings block is ignored. |
| private int i; |
| private int i2; |
| |
| @SuppressWarnings("all") |
| public void suppressWarningsTest() { |
| i = (@Sibling1 int) 0; |
| i2 = getSibling1(); |
| } |
| |
| public void suppressWarningsTest2() { |
| SuppressWarningsInner.i = (@Sibling1 int) 0; |
| SuppressWarningsInner.i2 = getSibling1(); |
| } |
| |
| public void suppressWarningsValidation() { |
| // :: warning: (argument) |
| expectsSibling1(i); |
| // :: warning: (argument) |
| expectsSibling1(i2); |
| // :: warning: (argument) |
| expectsSibling1(SuppressWarningsInner.i); |
| // :: warning: (argument) |
| expectsSibling1(SuppressWarningsInner.i2); |
| // :: warning: (argument) |
| expectsSibling1(suppressWarningsMethodReturn()); |
| |
| suppressWarningsMethodParams(getSibling1()); |
| } |
| |
| @SuppressWarnings("all") |
| public int suppressWarningsMethodReturn() { |
| return getSibling1(); |
| } |
| |
| // It is problematic to automatically test whole-program inference for method params when |
| // suppressing warnings. |
| // Since we must use @SuppressWarnings() for the method, we won't be able to catch any error |
| // inside the method body. Verified manually that in the "annotated" folder param's type wasn't |
| // updated. |
| @SuppressWarnings("all") |
| public void suppressWarningsMethodParams(int param) {} |
| } |
| |
| @SuppressWarnings("all") |
| static class SuppressWarningsInner { |
| public static int i; |
| public static int i2; |
| } |
| |
| class NullTest { |
| // The default type for fields is @DefaultType. |
| private String privateField; |
| public String publicField; |
| |
| // The types of both fields are not refined to @WholeProgramInferenceBottom, as whole-program |
| // inference never performs refinement in the presence of the null literal. |
| @SuppressWarnings("value") |
| void assignFieldsToBottom() { |
| privateField = null; |
| publicField = null; |
| } |
| |
| // Testing the refinement above. |
| void testFields() { |
| // :: warning: (argument) |
| expectsBottom(privateField); |
| // :: warning: (argument) |
| expectsBottom(publicField); |
| } |
| } |
| |
| class IgnoreMetaAnnotationTest2 { |
| @ToIgnore int field; |
| @IgnoreInWholeProgramInference int field2; |
| |
| void foo() { |
| field = getSibling1(); |
| field2 = getSibling1(); |
| } |
| |
| void test() { |
| // :: warning: (argument) |
| expectsSibling1(field); |
| // :: warning: (argument) |
| expectsSibling1(field2); |
| } |
| } |
| |
| class AssignParam { |
| public void f(@WholeProgramInferenceBottom Object param) { |
| // :: warning: assignment |
| param = ((@Top Object) null); |
| } |
| } |
| } |