| 807 | }; |
| 808 | |
| 809 | absl::Status SelectOptimizer::OnPostVisit(PlannerContext& context, |
| 810 | const Expr& node) { |
| 811 | if (!node.has_call_expr()) { |
| 812 | return absl::OkStatus(); |
| 813 | } |
| 814 | |
| 815 | absl::string_view fn = node.call_expr().function(); |
| 816 | if (fn != kCelHasField && fn != kCelAttribute) { |
| 817 | return absl::OkStatus(); |
| 818 | } |
| 819 | |
| 820 | if (node.call_expr().args().size() < 2 || |
| 821 | node.call_expr().args().size() > 3) { |
| 822 | return absl::InvalidArgumentError("Invalid cel.attribute call"); |
| 823 | } |
| 824 | |
| 825 | if (node.call_expr().args().size() == 3) { |
| 826 | return absl::UnimplementedError("Optionals not yet supported"); |
| 827 | } |
| 828 | |
| 829 | CEL_ASSIGN_OR_RETURN(std::vector<SelectQualifier> instructions, |
| 830 | SelectInstructionsFromCall(node.call_expr())); |
| 831 | |
| 832 | if (instructions.empty()) { |
| 833 | return absl::InvalidArgumentError("Invalid cel.attribute no select steps."); |
| 834 | } |
| 835 | |
| 836 | bool presence_test = false; |
| 837 | |
| 838 | if (fn == kCelHasField) { |
| 839 | presence_test = true; |
| 840 | } |
| 841 | |
| 842 | const Expr& operand = node.call_expr().args()[0]; |
| 843 | absl::string_view identifier; |
| 844 | if (operand.has_ident_expr()) { |
| 845 | identifier = operand.ident_expr().name(); |
| 846 | } |
| 847 | |
| 848 | if (absl::StrContains(identifier, ".")) { |
| 849 | return absl::UnimplementedError("qualified identifiers not supported."); |
| 850 | } |
| 851 | |
| 852 | std::vector<AttributeQualifier> qualifiers; |
| 853 | qualifiers.reserve(instructions.size()); |
| 854 | for (const auto& instruction : instructions) { |
| 855 | qualifiers.push_back( |
| 856 | absl::visit(absl::Overload( |
| 857 | [](const FieldSpecifier& field) { |
| 858 | return AttributeQualifier::OfString(field.name); |
| 859 | }, |
| 860 | [](const AttributeQualifier& q) { return q; }), |
| 861 | instruction)); |
| 862 | } |
| 863 | |
| 864 | // TODO(uncreated-issue/51): If the first argument is a string literal, the custom |
| 865 | // step needs to handle variable lookup. |
| 866 | auto* subexpression = context.program_builder().GetSubexpression(&node); |
nothing calls this directly
no test coverage detected