@@ -195,6 +195,76 @@ public void isVariableShadowed_comprehensionResultBranch() throws Exception {
195195 .isFalse ();
196196 }
197197
198+ @ Test
199+ public void isVariableShadowed_twoVarComprehension_resultBranch () throws Exception {
200+ CelAbstractSyntaxTree ast =
201+ COMPILER .compile ("{'k1': 1, 'k2': 2}.all(k, v, k != '' && v > 0)" ).getAst ();
202+ CelNavigableMutableAst navigableAst =
203+ CelNavigableMutableAst .fromAst (CelMutableAst .fromCelAst (ast ));
204+
205+ CelNavigableMutableExpr comprehensionNode =
206+ navigableAst
207+ .getRoot ()
208+ .allNodes ()
209+ .filter (node -> node .getKind () == Kind .COMPREHENSION )
210+ .findFirst ()
211+ .get ();
212+
213+ CelMutableComprehension comprehension = comprehensionNode .expr ().comprehension ();
214+ long resultId = comprehension .result ().id ();
215+
216+ CelNavigableMutableExpr resultNode =
217+ comprehensionNode .allNodes ().filter (node -> node .id () == resultId ).findFirst ().get ();
218+
219+ // In result branch of two-var comprehension: accuVar is in scope, but iterVar and iterVar2 are
220+ // not
221+ assertThat (CelNavigableExprUtil .isVariableShadowed (resultNode , comprehension .accuVar ()))
222+ .isTrue ();
223+ assertThat (CelNavigableExprUtil .isVariableShadowed (resultNode , comprehension .iterVar ()))
224+ .isFalse ();
225+ assertThat (CelNavigableExprUtil .isVariableShadowed (resultNode , comprehension .iterVar2 ()))
226+ .isFalse ();
227+ }
228+
229+ @ Test
230+ public void isVariableShadowed_accuInit_notShadowed () {
231+ CelMutableExpr iterRange = CelMutableExpr .ofList (0 , CelMutableList .create ());
232+ CelMutableExpr accuInitIdent = CelMutableExpr .ofIdent (1 , "x" );
233+ CelMutableExpr loopCond = CelMutableExpr .ofConstant (2 , CelConstant .ofValue (true ));
234+ CelMutableExpr loopStep = CelMutableExpr .ofConstant (3 , CelConstant .ofValue (true ));
235+ CelMutableExpr result = CelMutableExpr .ofIdent (4 , "accu" );
236+
237+ CelMutableExpr comp =
238+ CelMutableExpr .ofComprehension (
239+ 5 ,
240+ CelMutableComprehension .create (
241+ "x" , iterRange , "accu" , accuInitIdent , loopCond , loopStep , result ));
242+
243+ CelNavigableMutableExpr root = CelNavigableMutableExpr .fromExpr (comp );
244+ CelNavigableMutableExpr navAccuInit =
245+ root .allNodes ().filter (node -> node .id () == 1 ).findFirst ().get ();
246+
247+ assertThat (CelNavigableExprUtil .isVariableShadowed (navAccuInit , "x" )).isFalse ();
248+ assertThat (CelNavigableExprUtil .isVariableShadowed (navAccuInit , "accu" )).isFalse ();
249+ }
250+
251+ @ Test
252+ public void findDeclaringComprehension_emptyVariableName_returnsEmpty () throws Exception {
253+ CelAbstractSyntaxTree ast = COMPILER .compile ("[1, 2].all(x, x > 0)" ).getAst ();
254+ CelNavigableAst navigableAst = CelNavigableAst .fromAst (ast );
255+
256+ CelNavigableExpr identX =
257+ navigableAst
258+ .getRoot ()
259+ .allNodes ()
260+ .filter (node -> node .expr ().identOrDefault ().name ().equals ("x" ))
261+ .findFirst ()
262+ .get ();
263+
264+ assertThat (CelNavigableExprUtil .findDeclaringComprehension (identX , "" )).isEmpty ();
265+ assertThat (CelNavigableExprUtil .isVariableShadowed (identX , "" )).isFalse ();
266+ }
267+
198268 @ Test
199269 public void areVariablesShadowed_multipleVariables () throws Exception {
200270 CelAbstractSyntaxTree ast = COMPILER .compile ("[1, 2].all(x, x > 0)" ).getAst ();
@@ -345,4 +415,64 @@ public void isVariableShadowed_zeroedOutIds_scopedCorrectly() {
345415 assertThat (CelNavigableExprUtil .isVariableShadowed (navResult , "x" )).isFalse ();
346416 assertThat (CelNavigableExprUtil .isVariableShadowed (navResult , "accu" )).isTrue ();
347417 }
418+
419+ @ Test
420+ public void
421+ findDeclaringComprehension_nestedComprehensions_resolvesToInnermostDeclaringComprehension ()
422+ throws Exception {
423+ CelAbstractSyntaxTree ast =
424+ COMPILER
425+ .compile ("[1, 2].all(x, {'k': 1}.exists(k, v, x > 0 && k != '' && v > 0))" )
426+ .getAst ();
427+ CelNavigableAst navigableAst = CelNavigableAst .fromAst (ast );
428+
429+ CelNavigableExpr outerComp =
430+ navigableAst
431+ .getRoot ()
432+ .allNodes ()
433+ .filter (
434+ node ->
435+ node .getKind () == Kind .COMPREHENSION
436+ && node .expr ().comprehension ().iterVar ().equals ("x" ))
437+ .findFirst ()
438+ .get ();
439+
440+ CelNavigableExpr innerComp =
441+ navigableAst
442+ .getRoot ()
443+ .allNodes ()
444+ .filter (
445+ node ->
446+ node .getKind () == Kind .COMPREHENSION
447+ && node .expr ().comprehension ().iterVar ().equals ("k" ))
448+ .findFirst ()
449+ .get ();
450+
451+ CelNavigableExpr identX =
452+ navigableAst
453+ .getRoot ()
454+ .allNodes ()
455+ .filter (node -> node .expr ().identOrDefault ().name ().equals ("x" ))
456+ .findFirst ()
457+ .get ();
458+ CelNavigableExpr identK =
459+ navigableAst
460+ .getRoot ()
461+ .allNodes ()
462+ .filter (node -> node .expr ().identOrDefault ().name ().equals ("k" ))
463+ .findFirst ()
464+ .get ();
465+ CelNavigableExpr identV =
466+ navigableAst
467+ .getRoot ()
468+ .allNodes ()
469+ .filter (node -> node .expr ().identOrDefault ().name ().equals ("v" ))
470+ .findFirst ()
471+ .get ();
472+
473+ assertThat (CelNavigableExprUtil .findDeclaringComprehension (identX , "x" )).hasValue (outerComp );
474+ assertThat (CelNavigableExprUtil .findDeclaringComprehension (identK , "k" )).hasValue (innerComp );
475+ assertThat (CelNavigableExprUtil .findDeclaringComprehension (identV , "v" )).hasValue (innerComp );
476+ assertThat (CelNavigableExprUtil .findDeclaringComprehension (identX , "unknown" )).isEmpty ();
477+ }
348478}
0 commit comments