@@ -45,8 +45,45 @@ class ExprOrType extends @exprortype, Documentable {
4545 )
4646 }
4747
48- /** Gets this expression or type, with any surrounding parentheses removed. */
48+ /**
49+ * Gets this expression or type, with any surrounding parentheses removed.
50+ *
51+ * Also see `getUnderlyingValue` and `getUnderlyingReference`.
52+ */
4953 ExprOrType stripParens ( ) { result = this }
54+
55+ /**
56+ * Gets the innermost reference that this expression evaluates to, if any.
57+ *
58+ * Examples:
59+ *
60+ * - a variable or property access: the access itself.
61+ * - a parenthesized expression `(e)`: the underlying reference of `e`.
62+ * - a TypeScript type assertion `e as T`: the underlying reference of `e`.
63+ *
64+ * Also see `getUnderlyingValue` and `stripParens`.
65+ */
66+ Expr getUnderlyingReference ( ) {
67+ none ( )
68+ }
69+
70+ /**
71+ * Gets the innermost expression that this expression evaluates to.
72+ *
73+ * Examples:
74+ *
75+ * - a parenthesised expression `(e)`: the underlying value of `e`.
76+ * - a sequence expression `e1, e2`: the underlying value of `e2`.
77+ * - an assignment expression `v = e`: the underlying value of `e`.
78+ * - a TypeScript type assertion `e as T`: the underlying value of `e`.
79+ * - any other expression: the expression itself.
80+ *
81+ * Also see `getUnderlyingReference` and `stripParens`.
82+ */
83+ Expr getUnderlyingValue ( ) {
84+ result = this
85+ }
86+
5087}
5188
5289/** An expression. */
@@ -210,6 +247,15 @@ class ParExpr extends @parexpr, Expr {
210247 override predicate isImpure ( ) {
211248 getExpression ( ) .isImpure ( )
212249 }
250+
251+ override Expr getUnderlyingValue ( ) {
252+ result = getExpression ( ) .getUnderlyingValue ( )
253+ }
254+
255+ override Expr getUnderlyingReference ( ) {
256+ result = getExpression ( ) .getUnderlyingReference ( )
257+ }
258+
213259}
214260
215261/** A `null` literal. */
@@ -617,6 +663,11 @@ class SeqExpr extends @seqexpr, Expr {
617663 override string getStringValue ( ) {
618664 result = getLastOperand ( ) .getStringValue ( )
619665 }
666+
667+ override Expr getUnderlyingValue ( ) {
668+ result = getLastOperand ( ) .getUnderlyingValue ( )
669+ }
670+
620671}
621672
622673/** A conditional expression. */
@@ -862,6 +913,11 @@ class PropAccess extends @propaccess, Expr {
862913 override ControlFlowNode getFirstControlFlowNode ( ) {
863914 result = getBase ( ) .getFirstControlFlowNode ( )
864915 }
916+
917+ override Expr getUnderlyingReference ( ) {
918+ result = this
919+ }
920+
865921}
866922
867923/** A dot expression. */
@@ -1284,10 +1340,17 @@ class Assignment extends @assignment, Expr {
12841340 override ControlFlowNode getFirstControlFlowNode ( ) {
12851341 result = getLhs ( ) .getFirstControlFlowNode ( )
12861342 }
1343+
12871344}
12881345
12891346/** A simple assignment expression. */
1290- class AssignExpr extends @assignexpr, Assignment { }
1347+ class AssignExpr extends @assignexpr, Assignment {
1348+
1349+ override Expr getUnderlyingValue ( ) {
1350+ result = getRhs ( ) .getUnderlyingValue ( )
1351+ }
1352+
1353+ }
12911354
12921355/** A compound assign expression. */
12931356abstract class CompoundAssignExpr extends Assignment { }
0 commit comments