@@ -28,6 +28,34 @@ module;
2828
2929private import codeql.util.Boolean
3030
31+ private newtype TConditionKind =
32+ TBooleanCondition( ) or
33+ TNullnessCondition( ) or
34+ TMatchingCondition( ) or
35+ TEmptinessCondition( )
36+
37+ /** A condition kind. This is used to classify different `ConditionalSuccessor`s. */
38+ class ConditionKind extends TConditionKind {
39+ /** Gets a textual representation of this condition kind. */
40+ string toString ( ) {
41+ this instanceof TBooleanCondition and result = "Boolean"
42+ or
43+ this instanceof TNullnessCondition and result = "Nullness"
44+ or
45+ this instanceof TMatchingCondition and result = "Matching"
46+ or
47+ this instanceof TEmptinessCondition and result = "Emptiness"
48+ }
49+
50+ predicate isBoolean ( ) { this instanceof TBooleanCondition }
51+
52+ predicate isNullness ( ) { this instanceof TNullnessCondition }
53+
54+ predicate isMatching ( ) { this instanceof TMatchingCondition }
55+
56+ predicate isEmptiness ( ) { this instanceof TEmptinessCondition }
57+ }
58+
3159private newtype TSuccessorType =
3260 TDirectSuccessor ( ) or
3361 TBooleanSuccessor ( Boolean branch ) or
@@ -83,6 +111,18 @@ private class TConditionalSuccessor =
83111abstract private class ConditionalSuccessorImpl extends NormalSuccessorImpl , TConditionalSuccessor {
84112 /** Gets the Boolean value of this successor. */
85113 abstract boolean getValue ( ) ;
114+
115+ /** Gets the condition kind of this conditional successor. */
116+ abstract ConditionKind getKind ( ) ;
117+
118+ /**
119+ * Gets the dual of this conditional successor. That is, the conditional
120+ * successor of the same kind but with the opposite value.
121+ */
122+ ConditionalSuccessor getDual ( ) {
123+ this .getValue ( ) .booleanNot ( ) = result .getValue ( ) and
124+ this .getKind ( ) = result .getKind ( )
125+ }
86126}
87127
88128final class ConditionalSuccessor = ConditionalSuccessorImpl ;
@@ -116,6 +156,8 @@ final class ConditionalSuccessor = ConditionalSuccessorImpl;
116156class BooleanSuccessor extends ConditionalSuccessorImpl , TBooleanSuccessor {
117157 override boolean getValue ( ) { this = TBooleanSuccessor ( result ) }
118158
159+ override ConditionKind getKind ( ) { result = TBooleanCondition ( ) }
160+
119161 override string toString ( ) { result = this .getValue ( ) .toString ( ) }
120162}
121163
@@ -151,6 +193,8 @@ class NullnessSuccessor extends ConditionalSuccessorImpl, TNullnessSuccessor {
151193
152194 override boolean getValue ( ) { this = TNullnessSuccessor ( result ) }
153195
196+ override ConditionKind getKind ( ) { result = TNullnessCondition ( ) }
197+
154198 override string toString ( ) { if this .isNull ( ) then result = "null" else result = "non-null" }
155199}
156200
@@ -192,6 +236,8 @@ class MatchingSuccessor extends ConditionalSuccessorImpl, TMatchingSuccessor {
192236
193237 override boolean getValue ( ) { this = TMatchingSuccessor ( result ) }
194238
239+ override ConditionKind getKind ( ) { result = TMatchingCondition ( ) }
240+
195241 override string toString ( ) { if this .isMatch ( ) then result = "match" else result = "no-match" }
196242}
197243
@@ -233,6 +279,8 @@ class EmptinessSuccessor extends ConditionalSuccessorImpl, TEmptinessSuccessor {
233279
234280 override boolean getValue ( ) { this = TEmptinessSuccessor ( result ) }
235281
282+ override ConditionKind getKind ( ) { result = TEmptinessCondition ( ) }
283+
236284 override string toString ( ) { if this .isEmpty ( ) then result = "empty" else result = "non-empty" }
237285}
238286
0 commit comments