Skip to content

Commit d7b7a30

Browse files
l46kokcopybara-github
authored andcommitted
Add CelMutableCall
PiperOrigin-RevId: 623630568
1 parent facc16e commit d7b7a30

File tree

2 files changed

+277
-0
lines changed

2 files changed

+277
-0
lines changed

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

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
import dev.cel.common.ast.CelExpr.CelNotSet;
2121
import dev.cel.common.ast.CelExpr.ExprKind;
2222
import dev.cel.common.ast.CelExpr.ExprKind.Kind;
23+
import java.util.ArrayList;
24+
import java.util.Arrays;
25+
import java.util.Collection;
26+
import java.util.List;
27+
import java.util.Optional;
2328

2429
/**
2530
* An abstract representation of a common expression that allows mutation in any of its properties.
@@ -37,6 +42,7 @@ public final class CelMutableExpr {
3742
private CelConstant constant;
3843
private CelMutableIdent ident;
3944
private CelMutableSelect select;
45+
private CelMutableCall call;
4046
private int hash = 0;
4147

4248
public long id() {
@@ -71,6 +77,11 @@ public CelMutableSelect select() {
7177
return select;
7278
}
7379

80+
public CelMutableCall call() {
81+
checkExprKind(Kind.CALL);
82+
return call;
83+
}
84+
7485
public void setConstant(CelConstant constant) {
7586
this.exprKind = ExprKind.Kind.CONSTANT;
7687
this.constant = checkNotNull(constant);
@@ -86,6 +97,11 @@ public void setSelect(CelMutableSelect select) {
8697
this.select = checkNotNull(select);
8798
}
8899

100+
public void setCall(CelMutableCall call) {
101+
this.exprKind = ExprKind.Kind.CALL;
102+
this.call = checkNotNull(call);
103+
}
104+
89105
/** A mutable identifier expression. */
90106
public static final class CelMutableIdent {
91107
private String name = "";
@@ -196,6 +212,110 @@ private CelMutableSelect(CelMutableExpr operand, String field, boolean testOnly)
196212
}
197213
}
198214

215+
/** A mutable call expression, including calls to predefined functions and operators. */
216+
public static final class CelMutableCall {
217+
private Optional<CelMutableExpr> target;
218+
private String function;
219+
private List<CelMutableExpr> args;
220+
221+
public Optional<CelMutableExpr> target() {
222+
return target;
223+
}
224+
225+
public void setTarget(CelMutableExpr target) {
226+
this.target = Optional.of(target);
227+
}
228+
229+
public String function() {
230+
return function;
231+
}
232+
233+
public void setFunction(String function) {
234+
this.function = checkNotNull(function);
235+
}
236+
237+
public List<CelMutableExpr> args() {
238+
return args;
239+
}
240+
241+
public void clearArgs() {
242+
args.clear();
243+
}
244+
245+
public void addArgs(CelMutableExpr... exprs) {
246+
addArgs(Arrays.asList(checkNotNull(exprs)));
247+
}
248+
249+
public void addArgs(Iterable<CelMutableExpr> exprs) {
250+
exprs.forEach(e -> args.add(checkNotNull(e)));
251+
}
252+
253+
public void setArgs(Collection<CelMutableExpr> exprs) {
254+
this.args = new ArrayList<>(checkNotNull(exprs));
255+
}
256+
257+
public void setArg(int index, CelMutableExpr arg) {
258+
checkArgument(index >= 0 && index < args.size());
259+
args.set(index, checkNotNull(arg));
260+
}
261+
262+
@Override
263+
public boolean equals(Object obj) {
264+
if (obj == this) {
265+
return true;
266+
}
267+
if (obj instanceof CelMutableCall) {
268+
CelMutableCall that = (CelMutableCall) obj;
269+
return this.target.equals(that.target())
270+
&& this.function.equals(that.function())
271+
&& this.args.equals(that.args());
272+
}
273+
274+
return false;
275+
}
276+
277+
@Override
278+
public int hashCode() {
279+
int h = 1;
280+
h *= 1000003;
281+
h ^= target.hashCode();
282+
h *= 1000003;
283+
h ^= function.hashCode();
284+
h *= 1000003;
285+
h ^= args.hashCode();
286+
return h;
287+
}
288+
289+
public static CelMutableCall create(String function, CelMutableExpr... args) {
290+
return create(function, Arrays.asList(checkNotNull(args)));
291+
}
292+
293+
public static CelMutableCall create(String function, List<CelMutableExpr> args) {
294+
return new CelMutableCall(function, args);
295+
}
296+
297+
public static CelMutableCall create(
298+
CelMutableExpr target, String function, CelMutableExpr... args) {
299+
return create(target, function, Arrays.asList(checkNotNull(args)));
300+
}
301+
302+
public static CelMutableCall create(
303+
CelMutableExpr target, String function, List<CelMutableExpr> args) {
304+
return new CelMutableCall(target, function, args);
305+
}
306+
307+
private CelMutableCall(String function, List<CelMutableExpr> args) {
308+
this.target = Optional.empty();
309+
this.function = checkNotNull(function);
310+
this.args = new ArrayList<>(checkNotNull(args));
311+
}
312+
313+
private CelMutableCall(CelMutableExpr target, String function, List<CelMutableExpr> args) {
314+
this(function, args);
315+
this.target = Optional.of(target);
316+
}
317+
}
318+
199319
public static CelMutableExpr ofNotSet() {
200320
return ofNotSet(0L);
201321
}
@@ -228,6 +348,14 @@ public static CelMutableExpr ofSelect(long id, CelMutableSelect mutableSelect) {
228348
return new CelMutableExpr(id, mutableSelect);
229349
}
230350

351+
public static CelMutableExpr ofCall(CelMutableCall mutableCall) {
352+
return ofCall(0, mutableCall);
353+
}
354+
355+
public static CelMutableExpr ofCall(long id, CelMutableCall mutableCall) {
356+
return new CelMutableExpr(id, mutableCall);
357+
}
358+
231359
private CelMutableExpr(long id, CelConstant mutableConstant) {
232360
this.id = id;
233361
setConstant(mutableConstant);
@@ -243,6 +371,11 @@ private CelMutableExpr(long id, CelMutableSelect mutableSelect) {
243371
setSelect(mutableSelect);
244372
}
245373

374+
private CelMutableExpr(long id, CelMutableCall mutableCall) {
375+
this.id = id;
376+
setCall(mutableCall);
377+
}
378+
246379
private CelMutableExpr(long id) {
247380
this();
248381
this.id = id;
@@ -264,6 +397,7 @@ private Object exprValue() {
264397
case SELECT:
265398
return select();
266399
case CALL:
400+
return call();
267401
case CREATE_LIST:
268402
case CREATE_STRUCT:
269403
case CREATE_MAP:

common/src/test/java/dev/cel/common/ast/CelMutableExprTest.java

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@
1717
import static com.google.common.truth.Truth.assertThat;
1818
import static org.junit.Assert.assertThrows;
1919

20+
import com.google.common.collect.ImmutableList;
2021
import com.google.common.testing.EqualsTester;
2122
import com.google.testing.junit.testparameterinjector.TestParameter;
2223
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
2324
import dev.cel.common.ast.CelExpr.ExprKind.Kind;
25+
import dev.cel.common.ast.CelMutableExpr.CelMutableCall;
2426
import dev.cel.common.ast.CelMutableExpr.CelMutableIdent;
2527
import dev.cel.common.ast.CelMutableExpr.CelMutableSelect;
28+
import java.util.ArrayList;
2629
import org.junit.Test;
2730
import org.junit.runner.RunWith;
2831

@@ -124,6 +127,41 @@ public void mutableSelect_setters() {
124127
assertThat(select.testOnly()).isFalse();
125128
}
126129

130+
@Test
131+
public void ofCall() {
132+
CelMutableExpr mutableExpr =
133+
CelMutableExpr.ofCall(
134+
CelMutableCall.create(
135+
CelMutableExpr.ofConstant(CelConstant.ofValue("target")),
136+
"function",
137+
CelMutableExpr.ofConstant(CelConstant.ofValue("arg"))));
138+
139+
assertThat(mutableExpr.id()).isEqualTo(0L);
140+
assertThat(mutableExpr.call().target())
141+
.hasValue(CelMutableExpr.ofConstant(CelConstant.ofValue("target")));
142+
assertThat(mutableExpr.call().function()).isEqualTo("function");
143+
assertThat(mutableExpr.call().args())
144+
.containsExactly(CelMutableExpr.ofConstant(CelConstant.ofValue("arg")));
145+
}
146+
147+
@Test
148+
public void ofCall_withId() {
149+
CelMutableExpr mutableExpr =
150+
CelMutableExpr.ofCall(
151+
1L,
152+
CelMutableCall.create(
153+
CelMutableExpr.ofConstant(CelConstant.ofValue("target")),
154+
"function",
155+
CelMutableExpr.ofConstant(CelConstant.ofValue("arg"))));
156+
157+
assertThat(mutableExpr.id()).isEqualTo(1L);
158+
assertThat(mutableExpr.call().target())
159+
.hasValue(CelMutableExpr.ofConstant(CelConstant.ofValue("target")));
160+
assertThat(mutableExpr.call().function()).isEqualTo("function");
161+
assertThat(mutableExpr.call().args())
162+
.containsExactly(CelMutableExpr.ofConstant(CelConstant.ofValue("arg")));
163+
}
164+
127165
@Test
128166
public void setId_success() {
129167
CelMutableExpr mutableExpr = CelMutableExpr.ofConstant(CelConstant.ofValue(5L));
@@ -133,6 +171,85 @@ public void setId_success() {
133171
assertThat(mutableExpr.id()).isEqualTo(2L);
134172
}
135173

174+
@Test
175+
public void mutableCall_setArgumentAtIndex() {
176+
CelMutableCall call =
177+
CelMutableCall.create("function", CelMutableExpr.ofConstant(CelConstant.ofValue(1L)));
178+
179+
call.setArg(0, CelMutableExpr.ofConstant(CelConstant.ofValue("hello")));
180+
181+
assertThat(call.args())
182+
.containsExactly(CelMutableExpr.ofConstant(CelConstant.ofValue("hello")));
183+
assertThat(call.args()).isInstanceOf(ArrayList.class);
184+
}
185+
186+
@Test
187+
public void mutableCall_setArguments() {
188+
CelMutableCall call =
189+
CelMutableCall.create("function", CelMutableExpr.ofConstant(CelConstant.ofValue(1L)));
190+
191+
call.setArgs(
192+
ImmutableList.of(
193+
CelMutableExpr.ofConstant(CelConstant.ofValue(2)),
194+
CelMutableExpr.ofConstant(CelConstant.ofValue(3))));
195+
196+
assertThat(call.args())
197+
.containsExactly(
198+
CelMutableExpr.ofConstant(CelConstant.ofValue(2)),
199+
CelMutableExpr.ofConstant(CelConstant.ofValue(3)))
200+
.inOrder();
201+
assertThat(call.args()).isInstanceOf(ArrayList.class);
202+
}
203+
204+
@Test
205+
public void mutableCall_addArguments() {
206+
CelMutableCall call =
207+
CelMutableCall.create("function", CelMutableExpr.ofConstant(CelConstant.ofValue(1L)));
208+
209+
call.addArgs(
210+
CelMutableExpr.ofConstant(CelConstant.ofValue(2)),
211+
CelMutableExpr.ofConstant(CelConstant.ofValue(3)));
212+
213+
assertThat(call.args())
214+
.containsExactly(
215+
CelMutableExpr.ofConstant(CelConstant.ofValue(1)),
216+
CelMutableExpr.ofConstant(CelConstant.ofValue(2)),
217+
CelMutableExpr.ofConstant(CelConstant.ofValue(3)))
218+
.inOrder();
219+
assertThat(call.args()).isInstanceOf(ArrayList.class);
220+
}
221+
222+
@Test
223+
public void mutableCall_clearArguments() {
224+
CelMutableCall call =
225+
CelMutableCall.create(
226+
"function",
227+
CelMutableExpr.ofConstant(CelConstant.ofValue(1L)),
228+
CelMutableExpr.ofConstant(CelConstant.ofValue(2L)));
229+
230+
call.clearArgs();
231+
232+
assertThat(call.args()).isEmpty();
233+
}
234+
235+
@Test
236+
public void mutableCall_setTarget() {
237+
CelMutableCall call = CelMutableCall.create("function");
238+
239+
call.setTarget(CelMutableExpr.ofConstant(CelConstant.ofValue("hello")));
240+
241+
assertThat(call.target()).hasValue(CelMutableExpr.ofConstant(CelConstant.ofValue("hello")));
242+
}
243+
244+
@Test
245+
public void mutableCall_setFunction() {
246+
CelMutableCall call = CelMutableCall.create("function");
247+
248+
call.setFunction("function2");
249+
250+
assertThat(call.function()).isEqualTo("function2");
251+
}
252+
136253
@Test
137254
public void equalityTest() {
138255
new EqualsTester()
@@ -151,6 +268,20 @@ public void equalityTest() {
151268
4L, CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "test")),
152269
CelMutableExpr.ofSelect(
153270
4L, CelMutableSelect.create(CelMutableExpr.ofIdent("x"), "test")))
271+
.addEqualityGroup(CelMutableExpr.ofCall(CelMutableCall.create("function")))
272+
.addEqualityGroup(
273+
CelMutableExpr.ofCall(
274+
5L,
275+
CelMutableCall.create(
276+
CelMutableExpr.ofConstant(CelConstant.ofValue("target")),
277+
"function",
278+
CelMutableExpr.ofConstant(CelConstant.ofValue("arg")))),
279+
CelMutableExpr.ofCall(
280+
5L,
281+
CelMutableCall.create(
282+
CelMutableExpr.ofConstant(CelConstant.ofValue("target")),
283+
"function",
284+
CelMutableExpr.ofConstant(CelConstant.ofValue("arg")))))
154285
.testEquals();
155286
}
156287

@@ -160,6 +291,7 @@ private enum MutableExprKindTestCase {
160291
CONSTANT(CelMutableExpr.ofConstant(CelConstant.ofValue(2L))),
161292
IDENT(CelMutableExpr.ofIdent("test")),
162293
SELECT(CelMutableExpr.ofSelect(CelMutableSelect.create(CelMutableExpr.ofNotSet(), "field"))),
294+
CALL(CelMutableExpr.ofCall(CelMutableCall.create("call"))),
163295
;
164296

165297
private final CelMutableExpr mutableExpr;
@@ -184,6 +316,9 @@ public void getExprValue_invalidKind_throws(@TestParameter MutableExprKindTestCa
184316
if (!testCaseKind.equals(Kind.SELECT)) {
185317
assertThrows(IllegalArgumentException.class, testCase.mutableExpr::select);
186318
}
319+
if (!testCaseKind.equals(Kind.CALL)) {
320+
assertThrows(IllegalArgumentException.class, testCase.mutableExpr::call);
321+
}
187322
}
188323

189324
@SuppressWarnings("Immutable") // Mutable by design
@@ -196,6 +331,14 @@ private enum HashCodeTestCase {
196331
4L,
197332
CelMutableSelect.create(CelMutableExpr.ofIdent("y"), "field", /* testOnly= */ true)),
198333
1458249843),
334+
CALL(
335+
CelMutableExpr.ofCall(
336+
5L,
337+
CelMutableCall.create(
338+
CelMutableExpr.ofConstant(CelConstant.ofValue("target")),
339+
"function",
340+
CelMutableExpr.ofConstant(CelConstant.ofValue("arg")))),
341+
-1735261193),
199342
;
200343

201344
private final CelMutableExpr mutableExpr;

0 commit comments

Comments
 (0)