diff --git a/cel/env.go b/cel/env.go
index 7139e415..dac84140 100644
--- a/cel/env.go
+++ b/cel/env.go
@@ -1009,6 +1009,41 @@ func (i *Issues) Errors() []*Error {
return i.errs.GetErrors()
}
+// Source returns the source associated with the issues.
+func (i *Issues) Source() Source {
+ if i == nil {
+ return nil
+ }
+ return i.errs.Source()
+}
+
+// ErrorOffset returns the start character offset for the error, if available.
+func (i *Issues) ErrorOffset(err *Error) (int32, bool) {
+ offsetRange, found := i.ErrorOffsetRange(err)
+ if found {
+ return offsetRange.Start, true
+ }
+ return 0, false
+}
+
+// ErrorOffsetRange returns the character offset range for the error, if available.
+func (i *Issues) ErrorOffsetRange(err *Error) (celast.OffsetRange, bool) {
+ if i == nil || err == nil {
+ return celast.OffsetRange{}, false
+ }
+ if i.info != nil {
+ if offsetRange, found := i.info.GetOffsetRange(err.ExprID); found {
+ return offsetRange, true
+ }
+ }
+ if src := i.Source(); src != nil {
+ if offset, found := src.LocationOffset(err.Location); found {
+ return celast.OffsetRange{Start: offset, Stop: offset}, true
+ }
+ }
+ return celast.OffsetRange{}, false
+}
+
// Append collects the issues from another Issues struct into a new Issues object.
func (i *Issues) Append(other *Issues) *Issues {
if i == nil {
diff --git a/cel/env_test.go b/cel/env_test.go
index 6dbc1369..0b3ca48c 100644
--- a/cel/env_test.go
+++ b/cel/env_test.go
@@ -140,6 +140,38 @@ ERROR: :1:2: Syntax error: mismatched input '' expecting {'[', '{',
}
}
+func TestIssuesErrorOffsetRange(t *testing.T) {
+ e, err := NewEnv()
+ if err != nil {
+ t.Fatalf("NewEnv() failed: %v", err)
+ }
+ _, iss := e.Compile("missing")
+ if len(iss.Errors()) != 1 {
+ t.Fatalf("iss.Errors() got %v, wanted 1 error", iss.Errors())
+ }
+ errInfo := iss.Errors()[0]
+
+ offset, found := iss.ErrorOffset(errInfo)
+ if !found {
+ t.Fatal("ErrorOffset() got found false, wanted true")
+ }
+ if offset != 0 {
+ t.Errorf("ErrorOffset() got %d, wanted 0", offset)
+ }
+
+ offsetRange, found := iss.ErrorOffsetRange(errInfo)
+ if !found {
+ t.Fatal("ErrorOffsetRange() got found false, wanted true")
+ }
+ if offsetRange != (ast.OffsetRange{Start: 0, Stop: 7}) {
+ t.Errorf("ErrorOffsetRange() got %v, wanted [0, 7]", offsetRange)
+ }
+
+ if iss.Source() == nil {
+ t.Fatal("Source() got nil, wanted source")
+ }
+}
+
func TestFormatCELTypeEquivalence(t *testing.T) {
values := []*Type{
AnyType,
diff --git a/common/errors.go b/common/errors.go
index c8865df8..f39f7572 100644
--- a/common/errors.go
+++ b/common/errors.go
@@ -70,6 +70,11 @@ func (e *Errors) GetErrors() []*Error {
return e.errors[:]
}
+// Source returns the source associated with the errors.
+func (e *Errors) Source() Source {
+ return e.source
+}
+
// Append creates a new Errors object with the current and input errors.
func (e *Errors) Append(errs []*Error) *Errors {
return &Errors{