@@ -138,6 +138,54 @@ private module Cached {
138138 )
139139 else expr_parent ( child , i , parent )
140140 }
141+
142+ private Expr getAChildExpr ( ExprOrStmtParent parent ) {
143+ result = parent .getAChildExpr ( ) or
144+ result = parent .( AssignOperation ) .getExpandedAssignment ( )
145+ }
146+
147+ private ControlFlowElement getAChild ( ExprOrStmtParent parent ) {
148+ result = getAChildExpr ( parent )
149+ or
150+ result = parent .getAChildStmt ( )
151+ }
152+
153+ pragma [ inline]
154+ private ControlFlowElement enclosingStart ( ControlFlowElement cfe ) {
155+ result = cfe
156+ or
157+ getAChild ( result ) .( AnonymousFunctionExpr ) = cfe
158+ }
159+
160+ private predicate parent ( ControlFlowElement child , ExprOrStmtParent parent ) {
161+ child = getAChild ( parent ) and
162+ not child instanceof Callable
163+ }
164+
165+ /** Holds if the enclosing body of `cfe` is `body`. */
166+ cached
167+ predicate enclosingBody ( ControlFlowElement cfe , ControlFlowElement body ) {
168+ body = any ( Callable c ) .getBody ( ) and
169+ parent * ( enclosingStart ( cfe ) , body )
170+ }
171+
172+ /** Holds if the enclosing callable of `cfe` is `c`. */
173+ cached
174+ predicate enclosingCallable ( ControlFlowElement cfe , Callable c ) {
175+ enclosingBody ( cfe , c .getBody ( ) )
176+ or
177+ parent * ( enclosingStart ( cfe ) , c .( Constructor ) .getInitializer ( ) )
178+ }
179+
180+ /** Holds if the enclosing statement of expression `e` is `s`. */
181+ cached
182+ predicate enclosingStmt ( Expr e , Stmt s ) {
183+ // Compute the enclosing statement for an expression. Note that this need
184+ // not exist, since expressions can occur in contexts where they have no
185+ // enclosing statement (examples include field initialisers, both inline
186+ // and explicit on constructor definitions, and annotation arguments).
187+ getAChildExpr + ( s ) = e
188+ }
141189}
142190
143191import Cached
0 commit comments