Skip to content

Commit adae95c

Browse files
jnthntatumcopybara-github
authored andcommitted
Add a helper for formatting errors in a ValidationResult.
PiperOrigin-RevId: 735809976
1 parent 4d19eab commit adae95c

File tree

6 files changed

+88
-9
lines changed

6 files changed

+88
-9
lines changed

checker/BUILD

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ cc_library(
2727
hdrs = ["type_check_issue.h"],
2828
deps = [
2929
"//common:source",
30-
"@com_google_absl//absl/strings",
3130
"@com_google_absl//absl/strings:str_format",
3231
"@com_google_absl//absl/strings:string_view",
3332
],
@@ -45,6 +44,7 @@ cc_test(
4544

4645
cc_library(
4746
name = "validation_result",
47+
srcs = ["validation_result.cc"],
4848
hdrs = ["validation_result.h"],
4949
deps = [
5050
":type_check_issue",
@@ -53,6 +53,7 @@ cc_library(
5353
"@com_google_absl//absl/base:nullability",
5454
"@com_google_absl//absl/status",
5555
"@com_google_absl//absl/status:statusor",
56+
"@com_google_absl//absl/strings",
5657
"@com_google_absl//absl/types:span",
5758
],
5859
)
@@ -64,6 +65,7 @@ cc_test(
6465
":type_check_issue",
6566
":validation_result",
6667
"//base/ast_internal:ast_impl",
68+
"//common:source",
6769
"//internal:testing",
6870
"@com_google_absl//absl/status",
6971
"@com_google_absl//absl/status:status_matchers",

checker/type_check_issue.cc

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616

1717
#include <string>
1818

19-
#include "absl/strings/str_cat.h"
2019
#include "absl/strings/str_format.h"
2120
#include "absl/strings/string_view.h"
2221
#include "common/source.h"
@@ -42,15 +41,19 @@ absl::string_view SeverityString(TypeCheckIssue::Severity severity) {
4241

4342
} // namespace
4443

45-
std::string TypeCheckIssue::ToDisplayString(const Source& source) const {
44+
std::string TypeCheckIssue::ToDisplayString(const Source* source) const {
4645
int column = location_.column;
4746
// convert to 1-based if it's in range.
4847
int display_column = column >= 0 ? column + 1 : column;
49-
return absl::StrCat(
50-
absl::StrFormat("%s: %s:%d:%d: %s", SeverityString(severity_),
51-
source.description(), location_.line, display_column,
52-
message_),
53-
source.DisplayErrorLocation(location_));
48+
if (source) {
49+
return absl::StrFormat("%s: %s:%d:%d: %s%s", SeverityString(severity_),
50+
source->description(), location_.line,
51+
display_column, message_,
52+
source->DisplayErrorLocation(location_));
53+
}
54+
55+
return absl::StrFormat("%s: :%d:%d: %s", SeverityString(severity_),
56+
location_.line, display_column, message_);
5457
}
5558

5659
} // namespace cel

checker/type_check_issue.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,11 @@ class TypeCheckIssue {
4848
}
4949

5050
// Format the issue highlighting the source position.
51-
std::string ToDisplayString(const Source& source) const;
51+
std::string ToDisplayString(const Source* source) const;
52+
53+
std::string ToDisplayString(const Source& source) const {
54+
return ToDisplayString(&source);
55+
}
5256

5357
absl::string_view message() const { return message_; }
5458
Severity severity() const { return severity_; }

checker/validation_result.cc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "checker/validation_result.h"
16+
17+
#include <string>
18+
19+
#include "absl/strings/str_cat.h"
20+
#include "absl/strings/str_join.h"
21+
#include "checker/type_check_issue.h"
22+
23+
namespace cel {
24+
25+
std::string ValidationResult::FormatError() const {
26+
return absl::StrJoin(
27+
issues_, "\n", [this](std::string* out, const TypeCheckIssue& issue) {
28+
absl::StrAppend(out, issue.ToDisplayString(source_.get()));
29+
});
30+
}
31+
32+
} // namespace cel

checker/validation_result.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define THIRD_PARTY_CEL_CPP_CHECKER_VALIDATION_RESULT_H_
1717

1818
#include <memory>
19+
#include <string>
1920
#include <utility>
2021
#include <vector>
2122

@@ -68,6 +69,22 @@ class ValidationResult {
6869
return std::move(source_);
6970
}
7071

72+
// Returns a string representation of the issues in the result suitable for
73+
// display.
74+
//
75+
// The result is empty if no issues are present.
76+
//
77+
// The result is formatted similarly to CEL-Java and CEL-Go, but we do not
78+
// give strong guarantees on the format or stability.
79+
//
80+
// Example:
81+
//
82+
// ERROR: <source description>:1:3: Issue1
83+
// | source.cel
84+
// | ..^
85+
// INFORMATION: <source description>:-1:-1: Issue2
86+
std::string FormatError() const;
87+
7188
private:
7289
absl::Nullable<std::unique_ptr<Ast>> ast_;
7390
std::vector<TypeCheckIssue> issues_;

checker/validation_result_test.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@
1515
#include "checker/validation_result.h"
1616

1717
#include <memory>
18+
#include <utility>
1819

1920
#include "absl/status/status.h"
2021
#include "absl/status/status_matchers.h"
2122
#include "base/ast_internal/ast_impl.h"
2223
#include "checker/type_check_issue.h"
24+
#include "common/source.h"
2325
#include "internal/testing.h"
2426

2527
namespace cel {
@@ -65,5 +67,24 @@ TEST(ValidationResultTest, GetIssues) {
6567
EXPECT_THAT(result.GetIssues()[1].severity(), Severity::kInformation);
6668
}
6769

70+
TEST(ValidationResultTest, FormatError) {
71+
ValidationResult result(
72+
{TypeCheckIssue::CreateError({1, 2}, "Issue1"),
73+
TypeCheckIssue(Severity::kInformation, {-1, -1}, "Issue2")});
74+
EXPECT_FALSE(result.IsValid());
75+
76+
ASSERT_OK_AND_ASSIGN(std::unique_ptr<Source> source,
77+
NewSource("source.cel", "<description>"));
78+
result.SetSource(std::move(source));
79+
80+
ASSERT_THAT(result.GetIssues(), SizeIs(2));
81+
82+
EXPECT_THAT(result.FormatError(),
83+
"ERROR: <description>:1:3: Issue1\n"
84+
" | source.cel\n"
85+
" | ..^\n"
86+
"INFORMATION: <description>:-1:-1: Issue2");
87+
}
88+
6889
} // namespace
6990
} // namespace cel

0 commit comments

Comments
 (0)