Skip to content

Commit 6f8a7c9

Browse files
l46kokcopybara-github
authored andcommitted
Add a string formatter for CelExpr
PiperOrigin-RevId: 589479093
1 parent 782d995 commit 6f8a7c9

File tree

6 files changed

+646
-2
lines changed

6 files changed

+646
-2
lines changed

WORKSPACE

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
3131

3232
bazel_skylib_workspace()
3333

34-
RULES_JVM_EXTERNAL_TAG = "4.5"
34+
RULES_JVM_EXTERNAL_TAG = "aa44247b3913da0da606e9c522313b6a9396a571"
3535

36-
RULES_JVM_EXTERNAL_SHA = "b17d7388feb9bfa7f2fa09031b32707df529f26c91ab9e5d909eb1676badd9a6"
36+
RULES_JVM_EXTERNAL_SHA = "87378580865af690a78230e04eba1cd6d9c60d0db303ea129dc717705d711d9c"
3737

38+
# rules_jvm_external as of 12/11/2023
3839
http_archive(
3940
name = "rules_jvm_external",
4041
sha256 = RULES_JVM_EXTERNAL_SHA,

common/src/main/java/dev/cel/common/ast/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ package(
1111
AST_SOURCES = [
1212
"CelConstant.java",
1313
"CelExpr.java",
14+
"CelExprFormatter.java",
1415
"CelReference.java",
1516
]
1617

common/src/main/java/dev/cel/common/ast/CelExpr.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1175,4 +1175,9 @@ public static CelExpr ofComprehension(
11751175
.build()))
11761176
.build();
11771177
}
1178+
1179+
@Override
1180+
public final String toString() {
1181+
return CelExprFormatter.format(this);
1182+
}
11781183
}
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
// Copyright 2023 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+
package dev.cel.common.ast;
16+
17+
/** Provides string formatting support for {@link CelExpr}. */
18+
final class CelExprFormatter {
19+
private final StringBuilder indent = new StringBuilder();
20+
private final StringBuilder exprBuilder = new StringBuilder();
21+
22+
static String format(CelExpr celExpr) {
23+
CelExprFormatter formatter = new CelExprFormatter();
24+
formatter.formatExpr(celExpr);
25+
return formatter.exprBuilder.toString();
26+
}
27+
28+
private void formatExpr(CelExpr celExpr) {
29+
append(String.format("%s [%d] {", celExpr.exprKind().getKind(), celExpr.id()));
30+
CelExpr.ExprKind.Kind exprKind = celExpr.exprKind().getKind();
31+
if (!exprKind.equals(CelExpr.ExprKind.Kind.CONSTANT)) {
32+
appendNewline();
33+
}
34+
35+
switch (exprKind) {
36+
case CONSTANT:
37+
appendConst(celExpr.constant());
38+
break;
39+
case IDENT:
40+
appendIdent(celExpr.ident());
41+
break;
42+
case SELECT:
43+
appendSelect(celExpr.select());
44+
break;
45+
case CALL:
46+
appendCall(celExpr.call());
47+
break;
48+
case CREATE_LIST:
49+
appendCreateList(celExpr.createList());
50+
break;
51+
case CREATE_STRUCT:
52+
appendCreateStruct(celExpr.createStruct());
53+
break;
54+
case CREATE_MAP:
55+
appendCreateMap(celExpr.createMap());
56+
break;
57+
case COMPREHENSION:
58+
appendComprehension(celExpr.comprehension());
59+
break;
60+
default:
61+
append("Unknown kind: " + exprKind);
62+
break;
63+
}
64+
65+
if (!exprKind.equals(CelExpr.ExprKind.Kind.CONSTANT)) {
66+
appendNewline();
67+
append("}");
68+
} else {
69+
appendWithoutIndent("}");
70+
}
71+
}
72+
73+
private void appendConst(CelConstant celConstant) {
74+
appendWithoutIndent(" value: ");
75+
switch (celConstant.getKind()) {
76+
case NULL_VALUE:
77+
appendWithoutIndent("null");
78+
break;
79+
case BOOLEAN_VALUE:
80+
appendWithoutIndent(Boolean.toString(celConstant.booleanValue()));
81+
break;
82+
case INT64_VALUE:
83+
appendWithoutIndent(Long.toString(celConstant.int64Value()));
84+
break;
85+
case UINT64_VALUE:
86+
appendWithoutIndent(celConstant.uint64Value() + "u");
87+
break;
88+
case DOUBLE_VALUE:
89+
appendWithoutIndent(Double.toString(celConstant.doubleValue()));
90+
break;
91+
case STRING_VALUE:
92+
appendWithoutIndent("\"" + celConstant.stringValue() + "\"");
93+
break;
94+
case BYTES_VALUE:
95+
appendWithoutIndent(String.format("b\"%s\"", celConstant.bytesValue().toStringUtf8()));
96+
break;
97+
default:
98+
append("Unknown kind: " + celConstant.getKind());
99+
break;
100+
}
101+
appendWithoutIndent(" ");
102+
}
103+
104+
private void appendIdent(CelExpr.CelIdent celIdent) {
105+
indent();
106+
append("name: " + celIdent.name());
107+
outdent();
108+
}
109+
110+
private void appendSelect(CelExpr.CelSelect celSelect) {
111+
indent();
112+
formatExpr(celSelect.operand());
113+
outdent();
114+
append(".");
115+
append(celSelect.field());
116+
if (celSelect.testOnly()) {
117+
appendWithoutIndent("~presence_test");
118+
}
119+
}
120+
121+
private void appendCall(CelExpr.CelCall celCall) {
122+
indent();
123+
appendWithNewline("function: " + celCall.function());
124+
if (celCall.target().isPresent()) {
125+
appendWithNewline("target: {");
126+
indent();
127+
formatExpr(celCall.target().get());
128+
outdent();
129+
appendNewline();
130+
appendWithNewline("}");
131+
}
132+
append("args: {");
133+
indent();
134+
for (CelExpr celExpr : celCall.args()) {
135+
appendNewline();
136+
formatExpr(celExpr);
137+
}
138+
outdent();
139+
appendNewline();
140+
append("}");
141+
outdent();
142+
}
143+
144+
private void appendCreateList(CelExpr.CelCreateList celCreateList) {
145+
indent();
146+
append("elements: {");
147+
indent();
148+
for (CelExpr expr : celCreateList.elements()) {
149+
appendNewline();
150+
formatExpr(expr);
151+
}
152+
outdent();
153+
appendNewline();
154+
append("}");
155+
if (!celCreateList.optionalIndices().isEmpty()) {
156+
appendNewline();
157+
append("optional_indices: [");
158+
for (int i = 0; i < celCreateList.optionalIndices().size(); i++) {
159+
appendWithoutIndent(String.valueOf(i));
160+
if (i != celCreateList.optionalIndices().size() - 1) {
161+
appendWithoutIndent(", ");
162+
}
163+
}
164+
appendWithoutIndent("]");
165+
}
166+
outdent();
167+
}
168+
169+
private void appendCreateStruct(CelExpr.CelCreateStruct celCreateStruct) {
170+
indent();
171+
appendWithNewline("name: " + celCreateStruct.messageName());
172+
append("entries: {");
173+
indent();
174+
for (CelExpr.CelCreateStruct.Entry entry : celCreateStruct.entries()) {
175+
appendNewline();
176+
appendWithNewline(String.format("ENTRY [%d] {", entry.id()));
177+
indent();
178+
appendWithNewline("field_key: " + entry.fieldKey());
179+
if (entry.optionalEntry()) {
180+
appendWithNewline("optional_entry: true");
181+
}
182+
appendWithNewline("value: {");
183+
indent();
184+
formatExpr(entry.value());
185+
outdent();
186+
appendNewline();
187+
appendWithNewline("}");
188+
outdent();
189+
append("}");
190+
}
191+
outdent();
192+
appendNewline();
193+
append("}");
194+
outdent();
195+
}
196+
197+
private void appendCreateMap(CelExpr.CelCreateMap celCreateMap) {
198+
indent();
199+
boolean firstLine = true;
200+
for (CelExpr.CelCreateMap.Entry entry : celCreateMap.entries()) {
201+
if (!firstLine) {
202+
appendNewline();
203+
} else {
204+
firstLine = false;
205+
}
206+
appendWithNewline(String.format("MAP_ENTRY [%d] {", entry.id()));
207+
indent();
208+
appendWithNewline("key: {");
209+
indent();
210+
formatExpr(entry.key());
211+
outdent();
212+
appendNewline();
213+
appendWithNewline("}");
214+
if (entry.optionalEntry()) {
215+
appendWithNewline("optional_entry: true");
216+
}
217+
appendWithNewline("value: {");
218+
indent();
219+
formatExpr(entry.value());
220+
outdent();
221+
appendNewline();
222+
appendWithNewline("}");
223+
outdent();
224+
append("}");
225+
}
226+
outdent();
227+
}
228+
229+
private void appendComprehension(CelExpr.CelComprehension celComprehension) {
230+
indent();
231+
appendWithNewline("iter_var: " + celComprehension.iterVar());
232+
// Iter range
233+
appendWithNewline("iter_range: {");
234+
indent();
235+
formatExpr(celComprehension.iterRange());
236+
outdent();
237+
appendNewline();
238+
appendWithNewline("}");
239+
240+
appendWithNewline("accu_var: " + celComprehension.accuVar());
241+
// Accu init
242+
appendWithNewline("accu_init: {");
243+
indent();
244+
formatExpr(celComprehension.accuInit());
245+
outdent();
246+
appendNewline();
247+
appendWithNewline("}");
248+
249+
// Loop condition
250+
appendWithNewline("loop_condition: {");
251+
indent();
252+
formatExpr(celComprehension.loopCondition());
253+
outdent();
254+
appendNewline();
255+
appendWithNewline("}");
256+
257+
// Loop step
258+
appendWithNewline("loop_step: {");
259+
indent();
260+
formatExpr(celComprehension.loopStep());
261+
outdent();
262+
appendNewline();
263+
appendWithNewline("}");
264+
265+
// Result
266+
appendWithNewline("result: {");
267+
indent();
268+
formatExpr(celComprehension.result());
269+
outdent();
270+
appendNewline();
271+
append("}");
272+
273+
outdent();
274+
}
275+
276+
private void append(String str) {
277+
exprBuilder.append(indent);
278+
exprBuilder.append(str);
279+
}
280+
281+
private void appendWithNewline(String str) {
282+
append(str);
283+
appendNewline();
284+
}
285+
286+
private void appendWithoutIndent(String str) {
287+
exprBuilder.append(str);
288+
}
289+
290+
private void appendNewline() {
291+
exprBuilder.append('\n');
292+
}
293+
294+
private void indent() {
295+
indent.append(" ");
296+
}
297+
298+
private void outdent() {
299+
indent.setLength(indent.length() - 2);
300+
}
301+
302+
private CelExprFormatter() {}
303+
}

common/src/test/java/dev/cel/common/ast/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ java_library(
1212
"//:auto_value",
1313
"//:java_truth",
1414
"//common",
15+
"//common:compiler_common",
1516
"//common/ast",
1617
"//common/ast:cel_expr_visitor",
1718
"//common/ast:expr_converter",
@@ -21,6 +22,7 @@ java_library(
2122
"//common/types",
2223
"//compiler",
2324
"//compiler:compiler_builder",
25+
"//extensions:optional_library",
2426
"//parser:macro",
2527
"//parser:operator",
2628
"@cel_spec//proto/cel/expr:expr_java_proto",

0 commit comments

Comments
 (0)