| // Test case for issue #951: |
| // https://github.com/typetools/checker-framework/issues/951 |
| |
| import org.checkerframework.dataflow.qual.Deterministic; |
| import org.checkerframework.dataflow.qual.Pure; |
| import org.checkerframework.dataflow.qual.SideEffectFree; |
| |
| public class Issue951 { |
| |
| @Pure |
| public static int min(int[] a) { |
| if (a.length == 0) { |
| throw new MyExceptionSefConstructor("Empty array passed to min(int[])"); |
| } |
| int result = a[0]; |
| for (int i = 1; i < a.length; i++) { |
| result = min(result, a[i]); |
| } |
| return result; |
| } |
| |
| @Pure |
| public static int arbitraryExceptionArg1() { |
| // :: error: (purity.not.deterministic.not.sideeffectfree.call) |
| // :: error: (purity.not.sideeffectfree.call) |
| throw new MyException("" + arbitraryMethod()); |
| } |
| |
| @Pure |
| public static int arbitraryExceptionArg2() { |
| // :: error: (purity.not.deterministic.not.sideeffectfree.call) |
| throw new MyExceptionSefConstructor("" + arbitraryMethod()); |
| } |
| |
| @Pure |
| public static int sefExceptionArg1() { |
| // The method is safe, so this is a false positive warning; |
| // in the future the Purity Checker may not issue this warning. |
| // :: error: (purity.not.deterministic.call) |
| // :: error: (purity.not.sideeffectfree.call) |
| throw new MyException("" + sefMethod()); |
| } |
| |
| @Pure |
| public static int sefExceptionArg2() { |
| // The method is safe, so this is a false positive warning; |
| // in the future the Purity Checker may not issue this warning. |
| // :: error: (purity.not.deterministic.call) |
| throw new MyExceptionSefConstructor("" + sefMethod()); |
| } |
| |
| @Pure |
| public static int detExceptionArg1() { |
| // :: error: (purity.not.sideeffectfree.call) |
| // :: error: (purity.not.sideeffectfree.call) |
| throw new MyException("" + detMethod()); |
| } |
| |
| @Pure |
| public static int detExceptionArg2() { |
| // :: error: (purity.not.sideeffectfree.call) |
| throw new MyExceptionSefConstructor("" + detMethod()); |
| } |
| |
| @Pure |
| public static int pureExceptionArg1(int a, int b) { |
| // :: error: (purity.not.sideeffectfree.call) |
| throw new MyException("" + min(a, b)); |
| } |
| |
| @Pure |
| public static int pureExceptionArg2(int a, int b) { |
| throw new MyExceptionSefConstructor("" + min(a, b)); |
| } |
| |
| @Pure |
| int throwNewWithinTry() { |
| for (int i = 0; i < 10; i++) { |
| try { |
| for (int j = 0; j < 10; j++) { |
| throw new MyExceptionSefConstructor("foo"); |
| } |
| // :: error: (purity.not.deterministic.catch) |
| } catch (MyExceptionSefConstructor e) { |
| return -1; |
| } |
| } |
| return 22; |
| } |
| |
| // Helper methods |
| |
| // Not deterministic or side-effect-free |
| static int arbitraryMethod() { |
| return 22; |
| } |
| |
| // Not deterministic |
| @SideEffectFree |
| static int sefMethod() { |
| return 22; |
| } |
| |
| @Deterministic |
| // Not side-effect-free |
| static int detMethod() { |
| return 22; |
| } |
| |
| @Pure |
| static int min(int a, int b) { |
| if (a < b) { |
| return a; |
| } else { |
| return b; |
| } |
| } |
| |
| // Constructors |
| |
| static class MyException extends Error { |
| // Not side-effect-free |
| MyException(String message) {} |
| } |
| |
| static class MyExceptionSefConstructor extends Error { |
| // Side-effect-free |
| @SuppressWarnings("purity.not.sideeffectfree.call") // until java.util.Error is annotated |
| @SideEffectFree |
| MyExceptionSefConstructor(String message) {} |
| } |
| } |