@@ -225,12 +225,12 @@ class CompileTimeConstantExpr extends Expr {
225225 )
226226 or
227227 (
228- b instanceof EQExpr and
228+ b instanceof AnyEqualsExpr and
229229 if left = right then result = true else result = false
230230 )
231231 or
232232 (
233- b instanceof NEExpr and
233+ b instanceof AnyNotEqualsExpr and
234234 if left != right then result = true else result = false
235235 )
236236 )
@@ -242,12 +242,12 @@ class CompileTimeConstantExpr extends Expr {
242242 right = b .getRightOperand ( ) .( CompileTimeConstantExpr ) .getBooleanValue ( )
243243 |
244244 (
245- b instanceof EQExpr and
245+ b instanceof AnyEqualsExpr and
246246 if left = right then result = true else result = false
247247 )
248248 or
249249 (
250- b instanceof NEExpr and
250+ b instanceof AnyNotEqualsExpr and
251251 if left != right then result = true else result = false
252252 )
253253 or
@@ -269,15 +269,18 @@ class CompileTimeConstantExpr extends Expr {
269269 /*
270270 * JLS 15.28 specifies that compile-time `String` constants are interned. Therefore `==`
271271 * equality can be interpreted as equality over the constant values, not the references.
272+ *
273+ * Kotlin's `==` and `===` operators will return the same result for `String`s, so they
274+ * can be handled alike:
272275 */
273276
274277 (
275- b instanceof EQExpr and
278+ b instanceof AnyEqualsExpr and
276279 if left = right then result = true else result = false
277280 )
278281 or
279282 (
280- b instanceof NEExpr and
283+ b instanceof AnyNotEqualsExpr and
281284 if left != right then result = true else result = false
282285 )
283286 )
@@ -359,7 +362,7 @@ class CompileTimeConstantExpr extends Expr {
359362 or
360363 b instanceof XorBitwiseExpr and result = v1 .bitXor ( v2 )
361364 // No `int` value for `AndLogicalExpr` or `OrLogicalExpr`.
362- // No `int` value for `LTExpr`, `GTExpr`, `LEExpr`, `GEExpr`, `EQExpr ` or `NEExpr `.
365+ // No `int` value for `LTExpr`, `GTExpr`, `LEExpr`, `GEExpr`, `AnyEqualsExpr ` or `AnyNotEqualsExpr `.
363366 )
364367 or
365368 // Ternary conditional, with compile-time constant condition.
@@ -952,7 +955,7 @@ class GEExpr extends BinaryExpr, @geexpr {
952955 override string getAPrimaryQlClass ( ) { result = "GEExpr" }
953956}
954957
955- /** A binary expression using the ` ==` operator. */
958+ /** A binary expression using Java's `==` or Kotlin's `= ==` operator. */
956959class EQExpr extends BinaryExpr , @eqexpr {
957960 override string getOp ( ) { result = " == " }
958961
@@ -961,12 +964,12 @@ class EQExpr extends BinaryExpr, @eqexpr {
961964
962965/** A binary expression using the Kotlin `==` operator, semantically equivalent to `Objects.equals`. */
963966class ValueEQExpr extends BinaryExpr , @valueeqexpr {
964- override string getOp ( ) { result = " == " }
967+ override string getOp ( ) { result = " (value equals) " }
965968
966969 override string getAPrimaryQlClass ( ) { result = "ValueEQExpr" }
967970}
968971
969- /** A binary expression using the `!=` operator. */
972+ /** A binary expression using Java's `!=` or Kotlin's `!= =` operator. */
970973class NEExpr extends BinaryExpr , @neexpr {
971974 override string getOp ( ) { result = " != " }
972975
@@ -975,11 +978,35 @@ class NEExpr extends BinaryExpr, @neexpr {
975978
976979/** A binary expression using the Kotlin `!=` operator, semantically equivalent to `Objects.equals`. */
977980class ValueNEExpr extends BinaryExpr , @valueneexpr {
978- override string getOp ( ) { result = " != " }
981+ override string getOp ( ) { result = " (value not-equals) " }
979982
980983 override string getAPrimaryQlClass ( ) { result = "ValueNEExpr" }
981984}
982985
986+ /**
987+ * A binary expression using either Java or Kotlin's `==` operator.
988+ *
989+ * This might test for reference equality or might function like `Objects.equals`. If you
990+ * need to distinguish them, use `EQExpr` or `ValueEQExpr` instead.
991+ */
992+ class AnyEqualsExpr extends BinaryExpr {
993+ AnyEqualsExpr ( ) {
994+ this instanceof EQExpr or this instanceof ValueEQExpr
995+ }
996+ }
997+
998+ /**
999+ * A binary expression using either Java or Kotlin's `!=` operator.
1000+ *
1001+ * This might test for reference equality or might function like `Objects.equals`. If you
1002+ * need to distinguish them, use `EQExpr` or `ValueEQExpr` instead.
1003+ */
1004+ class AnyNotEqualsExpr extends BinaryExpr {
1005+ AnyNotEqualsExpr ( ) {
1006+ this instanceof NEExpr or this instanceof ValueNEExpr
1007+ }
1008+ }
1009+
9831010/**
9841011 * A bitwise expression.
9851012 *
@@ -1068,19 +1095,40 @@ class GreaterThanComparison extends ComparisonExpr {
10681095
10691096/**
10701097 * An equality test is a binary expression using
1071- * the `==` or `!=` operator.
1098+ * Java's `==` or `!=` operators, or Kotlin's `==`, `!=`, `===` or `!==` operators.
1099+ *
1100+ * This could be a reference- or a value-in/equality test.
10721101 */
1073- class EqualityTest extends BinaryExpr {
1074- EqualityTest ( ) {
1102+ class AnyEqualityTest extends BinaryExpr {
1103+ AnyEqualityTest ( ) {
10751104 this instanceof EQExpr or
1076- this instanceof NEExpr
1105+ this instanceof NEExpr or
1106+ this instanceof ValueEQExpr or
1107+ this instanceof ValueNEExpr
10771108 }
10781109
10791110 /** Gets a boolean indicating whether this is `==` (true) or `!=` (false). */
10801111 boolean polarity ( ) {
10811112 result = true and this instanceof EQExpr
10821113 or
10831114 result = false and this instanceof NEExpr
1115+ or
1116+ result = true and this instanceof ValueEQExpr
1117+ or
1118+ result = false and this instanceof ValueNEExpr
1119+ }
1120+ }
1121+
1122+ /**
1123+ * An equality test is a binary expression using
1124+ * Java's `==` or `!=` operator.
1125+ *
1126+ * If either operand is a reference type, this is a reference-in/equality test.
1127+ */
1128+ class EqualityTest extends AnyEqualityTest {
1129+ EqualityTest ( ) {
1130+ this instanceof EQExpr or
1131+ this instanceof NEExpr
10841132 }
10851133}
10861134
0 commit comments