1919#include < memory>
2020#include < optional>
2121#include < string>
22+ #include < type_traits>
2223#include < utility>
2324#include < variant>
2425#include < vector>
@@ -157,11 +158,19 @@ class IntermediateCompiledPolicy {
157158 void set_semantics (RuleSemantics semantics) { semantics_ = semantics; }
158159 RuleSemantics semantics () const { return semantics_; }
159160
161+ void set_policy_source (const CelPolicySource* absl_nullable src) {
162+ policy_source_ = src;
163+ }
164+ const CelPolicySource* absl_nullable policy_source () const {
165+ return policy_source_;
166+ }
167+
160168 private:
161169 std::string name_;
162170 std::string display_name_;
163171 std::string description_;
164172 RuleSemantics semantics_ = RuleSemantics::kFirstMatch ;
173+ const CelPolicySource* absl_nullable policy_source_ = nullptr ;
165174
166175 CompiledRule root_rule_;
167176};
@@ -315,6 +324,33 @@ class PolicyCompiler {
315324 return src_->content ()->description ();
316325 }
317326
327+ absl::StatusOr<ValidationResult> CompileExpression (CelPolicyElementId id,
328+ absl::string_view val,
329+ const Compiler* env) {
330+ std::unique_ptr<cel::Source> source;
331+ if (src_ != nullptr && src_->content () != nullptr ) {
332+ std::optional<SourceRange> range;
333+ range = src_->GetSourceRange (id);
334+ bool use_subrange = !(src_->IsQuoted (id).value_or (true ));
335+ if (range.has_value () && use_subrange) {
336+ source = std::make_unique<SourceSubrange>(*src_->content (), *range);
337+ }
338+ }
339+
340+ if (source == nullptr ) {
341+ // For quoted strings, the source should be generated from the interpreted
342+ // YAML value.
343+ CEL_ASSIGN_OR_RETURN (
344+ source, cel::NewSource (val, std::string (GetSourceDescription ())));
345+ }
346+ auto result = env->Compile (*source, &arena_);
347+ if (!result.ok ()) {
348+ return result;
349+ }
350+ result->SetSource (std::move (source));
351+ return result;
352+ }
353+
318354 void AdaptTypeCheckIssues (CelPolicyElementId id, const ValidationResult& r) {
319355 const Source* source = r.GetSource ();
320356
@@ -336,8 +372,8 @@ class PolicyCompiler {
336372 const cel::OutputBlock& output_block, const Compiler* env) {
337373 CompiledOutputBlock output;
338374 CEL_ASSIGN_OR_RETURN (auto output_validation,
339- env-> Compile (output_block.output ().value (),
340- GetSourceDescription (), &arena_ ));
375+ CompileExpression (output_block.output ().id (),
376+ output_block. output (). value (), env ));
341377 AdaptTypeCheckIssues (output_block.output ().id (), output_validation);
342378
343379 cel::Type result_type = DynType ();
@@ -352,9 +388,10 @@ class PolicyCompiler {
352388 }
353389 }
354390 if (output_block.explanation ().has_value ()) {
355- CEL_ASSIGN_OR_RETURN (auto explanation_validation,
356- env->Compile (output_block.explanation ()->value (),
357- GetSourceDescription (), &arena_));
391+ CEL_ASSIGN_OR_RETURN (
392+ auto explanation_validation,
393+ CompileExpression (output_block.explanation ()->id (),
394+ output_block.explanation ()->value (), env));
358395 AdaptTypeCheckIssues (output_block.explanation ()->id (),
359396 explanation_validation);
360397 if (explanation_validation.IsValid ()) {
@@ -378,8 +415,8 @@ class PolicyCompiler {
378415 c_match.id = match.id ();
379416 if (match.condition ().has_value ()) {
380417 CEL_ASSIGN_OR_RETURN (auto validation,
381- env-> Compile (match.condition ()->value (),
382- GetSourceDescription (), &arena_ ));
418+ CompileExpression (match.condition ()->id (),
419+ match. condition ()-> value (), env ));
383420 AdaptTypeCheckIssues (match.condition ()->id (), validation);
384421 if (validation.IsValid ()) {
385422 CEL_ASSIGN_OR_RETURN (auto ast, validation.ReleaseAst ());
@@ -422,9 +459,10 @@ class PolicyCompiler {
422459 continue ;
423460 }
424461 std::string ident = absl::StrCat (" variables." , name);
425- CEL_ASSIGN_OR_RETURN (auto validation,
426- env->Compile (variable.expression ().value (),
427- GetSourceDescription (), &arena_));
462+ CEL_ASSIGN_OR_RETURN (
463+ auto validation,
464+ CompileExpression (variable.expression ().id (),
465+ variable.expression ().value (), env));
428466 AdaptTypeCheckIssues (variable.expression ().id (), validation);
429467 if (!validation.IsValid ()) {
430468 continue ;
@@ -480,6 +518,7 @@ class PolicyCompiler {
480518 absl::Status CompilePolicy (const CelPolicy& policy,
481519 IntermediateCompiledPolicy* out) {
482520 src_ = policy.source ();
521+ out->set_policy_source (src_);
483522 out->set_semantics (RuleSemantics::kFirstMatch );
484523 out->set_name (policy.name ().value ());
485524 out->set_display_name (
@@ -513,6 +552,21 @@ class FirstMatchComposer {
513552 std::unique_ptr<cel::Ast> ReleaseAst () { return std::move (ast_); }
514553
515554 private:
555+ SourcePosition GetAstOffset (CelPolicyElementId id) const {
556+ if (icp_.policy_source () == nullptr ) {
557+ return 0 ;
558+ }
559+ if (auto range = icp_.policy_source ()->GetSourceRange (id);
560+ range.has_value ()) {
561+ return range->begin ;
562+ }
563+ if (auto pos = icp_.policy_source ()->GetSourcePosition (id);
564+ pos.has_value ()) {
565+ return *pos;
566+ }
567+ return 0 ;
568+ }
569+
516570 using VariableScope = absl::flat_hash_map<std::string, int >;
517571
518572 std::optional<int > ResolvePolicyVariable (absl::string_view reference);
@@ -733,7 +787,8 @@ absl::StatusOr<bool> FirstMatchComposer::ComposeRule(const CompiledRule& rule,
733787 MapVariables (condition);
734788 factory_.StartCopyContext ();
735789 auto copy = factory_.Copy (condition.root_expr ());
736- auto source_info = factory_.RemapSourceInfo (condition.source_info ());
790+ auto source_info = factory_.RemapSourceInfo (
791+ condition.source_info (), GetAstOffset (match.condition ->id ));
737792 factory_.MergeSourceInfo (source_info);
738793 *insertion_point = factory_.NewCall (" _?_:_" , std::move (copy));
739794 insertion_point->mutable_call_expr ().mutable_args ().push_back (
@@ -792,7 +847,8 @@ absl::StatusOr<bool> FirstMatchComposer::ComposeProduction(
792847 MapVariables (ast);
793848 factory_.StartCopyContext ();
794849 Expr to_insert = factory_.Copy (ast.root_expr ());
795- auto source_info = factory_.RemapSourceInfo (ast.source_info ());
850+ auto source_info =
851+ factory_.RemapSourceInfo (ast.source_info (), GetAstOffset (output_ast.id ));
796852 factory_.MergeSourceInfo (source_info);
797853 insertion_expr = std::move (to_insert);
798854
@@ -832,8 +888,9 @@ void FirstMatchComposer::ComposeRuleVariables(const CompiledRule& rule,
832888 MapVariables (ast);
833889 factory_.StartCopyContext ();
834890 auto insertion = factory_.Copy (ast.root_expr ());
835- // TODO(b/506179116): apply the position offsets here.
836- auto info = factory_.RemapSourceInfo (ast.source_info ());
891+ auto info = factory_.RemapSourceInfo (ast.source_info (),
892+ GetAstOffset (variable.ast .id ));
893+ factory_.MergeSourceInfo (info);
837894 ABSL_DCHECK (init.has_list_expr ());
838895 int index = init.mutable_list_expr ().elements ().size ();
839896 init.mutable_list_expr ().mutable_elements ().push_back (
0 commit comments