ArrayAccess implements Predicate<TreeValues> { @Override public boolean test(TreeValues possibleValues) { for (ExpressionTree tree : possibleValues.values) { if ((tree.is(Tree.Kind.ARRAY_ACCESS) && matches(possibleValues, (ArrayAccessTree) tree)) || (tree.getParent().is(Tree.Kind.FOREACH_STATEMENT) && matches(possibleValues, tree, (ForEachStatementTree) tree.getParent()))) { return true; } } return false; } ArrayAccess(Predicate<TreeValues>... nestedPredicates); @Override boolean test(TreeValues possibleValues);  }
@Test public void test() { CompilationUnitTree unit = (CompilationUnitTree) TreeValuesTest.PARSER.parse("<?php " + "$x[0];" + "$y;" + "foreach ($arr as $value) { }" + "foreach ($arr as $key => $value) { }"); SymbolTable symbolTable = SymbolTableImpl.create(unit); TreeValues expr0 = TreeValues.of(expression(unit, 0), symbolTable); TreeValues expr1 = TreeValues.of(expression(unit, 1), symbolTable); ForEachStatementTree expr2 = (ForEachStatementTree) unit.script().statements().get(2); ForEachStatementTree expr3 = (ForEachStatementTree) unit.script().statements().get(3); TreeValues expr2value = TreeValues.of(expr2.value(), symbolTable); TreeValues expr2expression = TreeValues.of(expr2.expression(), symbolTable); TreeValues expr3value = TreeValues.of(expr3.value(), symbolTable); assertThat(new ArrayAccess(values -> true).test(expr0)).isTrue(); assertThat(new ArrayAccess(values -> false).test(expr0)).isFalse(); assertThat(new ArrayAccess(values -> true).test(expr1)).isFalse(); assertThat(new ArrayAccess(values -> true).test(expr2value)).isTrue(); assertThat(new ArrayAccess(values -> true).test(expr2expression)).isFalse(); assertThat(new ArrayAccess(values -> values.values.get(0) == expr2.expression()).test(expr2value)).isTrue(); assertThat(new ArrayAccess(values -> values.values.get(0) == expr3.expression()).test(expr2value)).isFalse(); assertThat(new ArrayAccess(values -> values.values.get(0) == expr3.expression()).test(expr3value)).isTrue(); }