11/**
2- * Provides predicates for identifying precondition checks like
2+ * Provides predicates for identifying precondition and assertion checks like
33 * `com.google.common.base.Preconditions` and
44 * `org.apache.commons.lang3.Validate`.
55 */
@@ -9,99 +9,150 @@ module;
99import java
1010
1111/**
12- * Holds if `m` is a non-overridable method that checks that its zero-indexed `argument`
13- * is equal to `checkTrue` and throws otherwise.
12+ * Holds if `m` is a method that checks that its argument at position `arg` is
13+ * equal to true and throws otherwise.
1414 */
15- predicate conditionCheckMethodArgument ( Method m , int argument , boolean checkTrue ) {
16- condtionCheckMethodGooglePreconditions ( m , checkTrue ) and argument = 0
17- or
18- conditionCheckMethodApacheCommonsLang3Validate ( m , checkTrue ) and argument = 0
15+ private predicate methodCheckTrue ( Method m , int arg ) {
16+ arg = 0 and
17+ (
18+ m .hasQualifiedName ( "com.google.common.base" , "Preconditions" , [ "checkArgument" , "checkState" ] ) or
19+ m .hasQualifiedName ( "com.google.common.base" , "Verify" , "verify" ) or
20+ m .hasQualifiedName ( "org.apache.commons.lang3" , "Validate" , [ "isTrue" , "validState" ] ) or
21+ m .hasQualifiedName ( "org.junit.jupiter.api" , "Assertions" , "assertTrue" ) or
22+ m .hasQualifiedName ( "org.junit.jupiter.api" , "Assumptions" , "assumeTrue" ) or
23+ m .hasQualifiedName ( "org.testng" , "Assert" , "assertTrue" )
24+ )
1925 or
20- condtionCheckMethodTestingFramework ( m , argument , checkTrue )
26+ m .getParameter ( arg ) .getType ( ) instanceof BooleanType and
27+ (
28+ m .hasQualifiedName ( "org.junit" , "Assert" , "assertTrue" ) or
29+ m .hasQualifiedName ( "org.junit" , "Assume" , "assumeTrue" ) or
30+ m .hasQualifiedName ( "junit.framework" , _, "assertTrue" )
31+ )
32+ }
33+
34+ /**
35+ * Holds if `m` is a method that checks that its argument at position `arg` is
36+ * equal to false and throws otherwise.
37+ */
38+ private predicate methodCheckFalse ( Method m , int arg ) {
39+ arg = 0 and
40+ (
41+ m .hasQualifiedName ( "org.junit.jupiter.api" , "Assertions" , "assertFalse" ) or
42+ m .hasQualifiedName ( "org.junit.jupiter.api" , "Assumptions" , "assumeFalse" ) or
43+ m .hasQualifiedName ( "org.testng" , "Assert" , "assertFalse" )
44+ )
2145 or
22- exists ( Parameter p , MethodCall ma , int argIndex , boolean ct , Expr arg |
23- p = m .getParameter ( argument ) and
24- not m .isOverridable ( ) and
25- m .getBody ( ) .getStmt ( 0 ) .( ExprStmt ) .getExpr ( ) = ma and
26- conditionCheckArgument ( ma , argIndex , ct ) and
27- ma .getArgument ( argIndex ) = arg and
28- (
29- arg .( LogNotExpr ) .getExpr ( ) .( VarAccess ) .getVariable ( ) = p and
30- checkTrue = ct .booleanNot ( )
31- or
32- arg .( VarAccess ) .getVariable ( ) = p and checkTrue = ct
33- )
46+ m .getParameter ( arg ) .getType ( ) instanceof BooleanType and
47+ (
48+ m .hasQualifiedName ( "org.junit" , "Assert" , "assertFalse" ) or
49+ m .hasQualifiedName ( "org.junit" , "Assume" , "assumeFalse" ) or
50+ m .hasQualifiedName ( "junit.framework" , _, "assertFalse" )
51+ )
52+ }
53+
54+ /**
55+ * Holds if `m` is a method that checks that its argument at position `arg` is
56+ * not null and throws otherwise.
57+ */
58+ private predicate methodCheckNotNull ( Method m , int arg ) {
59+ arg = 0 and
60+ (
61+ m .hasQualifiedName ( "com.google.common.base" , "Preconditions" , "checkNotNull" ) or
62+ m .hasQualifiedName ( "com.google.common.base" , "Verify" , "verifyNotNull" ) or
63+ m .hasQualifiedName ( "org.apache.commons.lang3" , "Validate" , "notNull" ) or
64+ m .hasQualifiedName ( "java.util" , "Objects" , "requireNonNull" ) or
65+ m .hasQualifiedName ( "org.junit.jupiter.api" , "Assertions" , "assertNotNull" ) or
66+ m .hasQualifiedName ( "org.junit" , "Assume" , "assumeNotNull" ) or // vararg
67+ m .hasQualifiedName ( "org.testng" , "Assert" , "assertNotNull" )
3468 )
3569 or
36- exists ( Parameter p , IfStmt ifstmt , Expr cond |
37- p = m .getParameter ( argument ) and
38- not m .isOverridable ( ) and
39- p .getType ( ) instanceof BooleanType and
40- m .getBody ( ) .getStmt ( 0 ) = ifstmt and
41- ifstmt .getCondition ( ) = cond and
42- (
43- cond .( LogNotExpr ) .getExpr ( ) .( VarAccess ) .getVariable ( ) = p and checkTrue = true
44- or
45- cond .( VarAccess ) .getVariable ( ) = p and checkTrue = false
46- ) and
47- (
48- ifstmt .getThen ( ) instanceof ThrowStmt or
49- ifstmt .getThen ( ) .( SingletonBlock ) .getStmt ( ) instanceof ThrowStmt
50- )
70+ arg = m .getNumberOfParameters ( ) - 1 and
71+ (
72+ m .hasQualifiedName ( "org.junit" , "Assert" , "assertNotNull" ) or
73+ m .hasQualifiedName ( "junit.framework" , _, "assertNotNull" )
5174 )
5275}
5376
54- private predicate condtionCheckMethodGooglePreconditions ( Method m , boolean checkTrue ) {
55- m .getDeclaringType ( ) .hasQualifiedName ( "com.google.common.base" , "Preconditions" ) and
56- checkTrue = true and
57- ( m .hasName ( "checkArgument" ) or m .hasName ( "checkState" ) )
77+ /**
78+ * Holds if `m` is a method that checks that its argument at position `arg`
79+ * satisfies a property specified by another argument and throws otherwise.
80+ */
81+ private predicate methodCheckThat ( Method m , int arg ) {
82+ m .getParameter ( arg ) .getType ( ) .getErasure ( ) instanceof TypeObject and
83+ (
84+ m .hasQualifiedName ( "org.hamcrest" , "MatcherAssert" , "assertThat" ) or
85+ m .hasQualifiedName ( "org.junit" , "Assert" , "assertThat" ) or
86+ m .hasQualifiedName ( "org.junit" , "Assume" , "assumeThat" )
87+ )
5888}
5989
60- private predicate conditionCheckMethodApacheCommonsLang3Validate ( Method m , boolean checkTrue ) {
61- m .getDeclaringType ( ) .hasQualifiedName ( "org.apache.commons.lang3" , "Validate" ) and
62- checkTrue = true and
63- ( m .hasName ( "isTrue" ) or m .hasName ( "validState" ) )
90+ /** Holds if `m` is a method that unconditionally throws. */
91+ private predicate methodUnconditionallyThrows ( Method m ) {
92+ m .hasQualifiedName ( "org.junit.jupiter.api" , "Assertions" , "fail" ) or
93+ m .hasQualifiedName ( "org.junit" , "Assert" , "fail" ) or
94+ m .hasQualifiedName ( "junit.framework" , _, "fail" ) or
95+ m .hasQualifiedName ( "org.testng" , "Assert" , "fail" )
6496}
6597
6698/**
67- * Holds if `m ` is a non-overridable testing framework method that checks that its first argument
68- * is equal to `checkTrue` and throws otherwise.
99+ * Holds if `mc ` is a call to a method that checks that its argument `arg` is
100+ * equal to `checkTrue` and throws otherwise.
69101 */
70- private predicate condtionCheckMethodTestingFramework ( Method m , int argument , boolean checkTrue ) {
71- argument = 0 and
72- (
73- m .getDeclaringType ( ) .hasQualifiedName ( "org.junit" , "Assume" ) and
74- checkTrue = true and
75- m .hasName ( "assumeTrue" )
102+ predicate methodCallChecksBoolean ( MethodCall mc , Expr arg , boolean checkTrue ) {
103+ exists ( int pos | mc .getArgument ( pos ) = arg |
104+ methodCheckTrue ( mc .getMethod ( ) .getSourceDeclaration ( ) , pos ) and checkTrue = true
76105 or
77- m .getDeclaringType ( ) .hasQualifiedName ( "org.junit.jupiter.api" , "Assertions" ) and
78- (
79- checkTrue = true and m .hasName ( "assertTrue" )
80- or
81- checkTrue = false and m .hasName ( "assertFalse" )
82- )
83- or
84- m .getDeclaringType ( ) .hasQualifiedName ( "org.junit.jupiter.api" , "Assumptions" ) and
85- (
86- checkTrue = true and m .hasName ( "assumeTrue" )
87- or
88- checkTrue = false and m .hasName ( "assumeFalse" )
89- )
106+ methodCheckFalse ( mc .getMethod ( ) .getSourceDeclaration ( ) , pos ) and checkTrue = false
90107 )
91- or
92- m .getDeclaringType ( ) .hasQualifiedName ( [ "org.junit" , "org.testng" ] , "Assert" ) and
93- m .getParameter ( argument ) .getType ( ) instanceof BooleanType and
94- (
95- checkTrue = true and m .hasName ( "assertTrue" )
108+ }
109+
110+ /**
111+ * Holds if `mc` is a call to a method that checks that its argument `arg` is
112+ * not null and throws otherwise.
113+ */
114+ predicate methodCallChecksNotNull ( MethodCall mc , Expr arg ) {
115+ exists ( int pos | mc .getArgument ( pos ) = arg |
116+ methodCheckNotNull ( mc .getMethod ( ) .getSourceDeclaration ( ) , pos )
96117 or
97- checkTrue = false and m .hasName ( "assertFalse" )
118+ methodCheckThat ( mc .getMethod ( ) .getSourceDeclaration ( ) , pos ) and
119+ mc .getAnArgument ( ) .( MethodCall ) .getMethod ( ) .getName ( ) = "notNullValue"
98120 )
99121}
100122
101123/**
124+ * Holds if `mc` is a call to a method that checks one of its arguments in some
125+ * way and possibly throws.
126+ */
127+ predicate methodCallChecksArgument ( MethodCall mc ) {
128+ methodCallChecksBoolean ( mc , _, _) or
129+ methodCallChecksNotNull ( mc , _)
130+ }
131+
132+ /** Holds if `mc` is a call to a method that unconditionally throws. */
133+ predicate methodCallUnconditionallyThrows ( MethodCall mc ) {
134+ methodUnconditionallyThrows ( mc .getMethod ( ) .getSourceDeclaration ( ) ) or
135+ exists ( BooleanLiteral b | methodCallChecksBoolean ( mc , b , b .getBooleanValue ( ) .booleanNot ( ) ) )
136+ }
137+
138+ /**
139+ * DEPRECATED: Use `methodCallChecksBoolean` instead.
140+ *
141+ * Holds if `m` is a non-overridable method that checks that its zero-indexed `argument`
142+ * is equal to `checkTrue` and throws otherwise.
143+ */
144+ deprecated predicate conditionCheckMethodArgument ( Method m , int argument , boolean checkTrue ) {
145+ methodCheckTrue ( m , argument ) and checkTrue = true
146+ or
147+ methodCheckFalse ( m , argument ) and checkTrue = false
148+ }
149+
150+ /**
151+ * DEPRECATED: Use `methodCallChecksBoolean` instead.
152+ *
102153 * Holds if `ma` is an access to a non-overridable method that checks that its
103154 * zero-indexed `argument` is equal to `checkTrue` and throws otherwise.
104155 */
105- predicate conditionCheckArgument ( MethodCall ma , int argument , boolean checkTrue ) {
156+ deprecated predicate conditionCheckArgument ( MethodCall ma , int argument , boolean checkTrue ) {
106157 conditionCheckMethodArgument ( ma .getMethod ( ) .getSourceDeclaration ( ) , argument , checkTrue )
107158}
0 commit comments