Skip to content

Commit 517d2f4

Browse files
l46kokcopybara-github
authored andcommitted
Add an additional messageName argument to MessageProvider interface
PiperOrigin-RevId: 748048140
1 parent ce6fe8c commit 517d2f4

File tree

7 files changed

+79
-48
lines changed

7 files changed

+79
-48
lines changed

runtime/src/main/java/dev/cel/runtime/CelValueRuntimeTypeProvider.java

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,25 +52,28 @@ public Object createMessage(String messageName, Map<String, Object> values) {
5252
}
5353

5454
@Override
55-
public Object selectField(Object message, String fieldName) {
56-
SelectableValue<CelValue> selectableValue = getSelectableValueOrThrow(message, fieldName);
55+
public Object selectField(String typeName, Object message, String fieldName) {
56+
SelectableValue<CelValue> selectableValue =
57+
getSelectableValueOrThrow(typeName, message, fieldName);
5758

5859
return unwrapCelValue(selectableValue.select(StringValue.create(fieldName)));
5960
}
6061

6162
@Override
62-
public Object hasField(Object message, String fieldName) {
63-
SelectableValue<CelValue> selectableValue = getSelectableValueOrThrow(message, fieldName);
63+
public Object hasField(String messageName, Object message, String fieldName) {
64+
SelectableValue<CelValue> selectableValue =
65+
getSelectableValueOrThrow(messageName, message, fieldName);
6466

6567
return selectableValue.find(StringValue.create(fieldName)).isPresent();
6668
}
6769

6870
@SuppressWarnings("unchecked")
69-
private SelectableValue<CelValue> getSelectableValueOrThrow(Object obj, String fieldName) {
71+
private SelectableValue<CelValue> getSelectableValueOrThrow(
72+
String typeName, Object obj, String fieldName) {
7073
CelValue convertedCelValue;
7174
if ((obj instanceof MessageLite)) {
72-
// TODO: Pass in typeName for lite messages
73-
convertedCelValue = protoCelValueConverter.fromProtoMessageToCelValue("", (MessageLite) obj);
75+
convertedCelValue =
76+
protoCelValueConverter.fromProtoMessageToCelValue(typeName, (MessageLite) obj);
7477
} else {
7578
convertedCelValue = protoCelValueConverter.fromJavaObjectToCelValue(obj);
7679
}
@@ -83,7 +86,7 @@ private SelectableValue<CelValue> getSelectableValueOrThrow(Object obj, String f
8386
}
8487

8588
@Override
86-
public Object adapt(Object message) {
89+
public Object adapt(String messageName, Object message) {
8790
if (message instanceof CelUnknownSet) {
8891
return message; // CelUnknownSet is handled specially for iterative evaluation. No need to
8992
// adapt to CelValue.
@@ -94,9 +97,8 @@ public Object adapt(Object message) {
9497
}
9598

9699
if (message instanceof MessageLite) {
97-
// TODO: Pass in typeName for lite messages
98100
return unwrapCelValue(
99-
protoCelValueConverter.fromProtoMessageToCelValue("", (MessageLite) message));
101+
protoCelValueConverter.fromProtoMessageToCelValue(messageName, (MessageLite) message));
100102
} else {
101103
return unwrapCelValue(protoCelValueConverter.fromJavaObjectToCelValue(message));
102104
}

runtime/src/main/java/dev/cel/runtime/DefaultInterpreter.java

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,9 @@ private IntermediateResult evalIdent(ExecutionFrame frame, CelExpr expr)
295295
private IntermediateResult resolveIdent(ExecutionFrame frame, CelExpr expr, String name)
296296
throws CelEvaluationException {
297297
// Check whether the type exists in the type check map as a 'type'.
298-
Optional<CelType> checkedType = ast.getType(expr.id());
299-
if (checkedType.isPresent() && checkedType.get().kind() == CelKind.TYPE) {
300-
TypeType typeValue = typeResolver.adaptType(checkedType.get());
298+
CelType checkedType = getCheckedTypeOrThrow(expr);
299+
if (checkedType.kind() == CelKind.TYPE) {
300+
TypeType typeValue = typeResolver.adaptType(checkedType);
301301
return IntermediateResult.create(typeValue);
302302
}
303303

@@ -309,7 +309,7 @@ private IntermediateResult resolveIdent(ExecutionFrame frame, CelExpr expr, Stri
309309
}
310310

311311
// Value resolved from Binding, it could be Message, PartialMessage or unbound(null)
312-
value = InterpreterUtil.strict(typeProvider.adapt(value));
312+
value = InterpreterUtil.strict(typeProvider.adapt(checkedType.name(), value));
313313
IntermediateResult result = IntermediateResult.create(rawResult.attribute(), value);
314314

315315
if (isLazyExpression) {
@@ -357,10 +357,12 @@ private IntermediateResult evalFieldSelect(
357357
return IntermediateResult.create(attribute, operand);
358358
}
359359

360+
CelType operandCheckedType = getCheckedTypeOrThrow(operandExpr);
360361
if (isTestOnly) {
361-
return IntermediateResult.create(attribute, typeProvider.hasField(operand, field));
362+
return IntermediateResult.create(
363+
attribute, typeProvider.hasField(operandCheckedType.name(), operand, field));
362364
}
363-
Object fieldValue = typeProvider.selectField(operand, field);
365+
Object fieldValue = typeProvider.selectField(operandCheckedType.name(), operand, field);
364366

365367
return IntermediateResult.create(
366368
attribute, InterpreterUtil.valueOrUnknown(fieldValue, expr.id()));
@@ -446,7 +448,8 @@ private IntermediateResult evalCall(ExecutionFrame frame, CelExpr expr, CelCall
446448
try {
447449
Object dispatchResult = overload.getDefinition().apply(argArray);
448450
if (celOptions.unwrapWellKnownTypesOnFunctionDispatch()) {
449-
dispatchResult = typeProvider.adapt(dispatchResult);
451+
CelType checkedType = getCheckedTypeOrThrow(expr);
452+
dispatchResult = typeProvider.adapt(checkedType.name(), dispatchResult);
450453
}
451454
return IntermediateResult.create(attr, dispatchResult);
452455
} catch (CelRuntimeException ce) {
@@ -665,18 +668,7 @@ private IntermediateResult evalType(ExecutionFrame frame, CelCall callExpr)
665668
return argResult;
666669
}
667670

668-
CelType checkedType =
669-
ast.getType(typeExprArg.id())
670-
.orElseThrow(
671-
() ->
672-
CelEvaluationExceptionBuilder.newBuilder(
673-
"expected a runtime type for '%s' from checked expression, but found"
674-
+ " none.",
675-
argResult.getClass().getSimpleName())
676-
.setErrorCode(CelErrorCode.TYPE_NOT_FOUND)
677-
.setMetadata(metadata, typeExprArg.id())
678-
.build());
679-
671+
CelType checkedType = getCheckedTypeOrThrow(typeExprArg);
680672
CelType checkedTypeValue = typeResolver.adaptType(checkedType);
681673
return IntermediateResult.create(
682674
typeResolver.resolveObjectType(argResult.value(), checkedTypeValue));
@@ -736,7 +728,9 @@ private Optional<IntermediateResult> maybeEvalOptionalSelectField(
736728
}
737729

738730
String field = callExpr.args().get(1).constant().stringValue();
739-
boolean hasField = (boolean) typeProvider.hasField(lhsResult.value(), field);
731+
CelType checkedType = getCheckedTypeOrThrow(expr);
732+
boolean hasField =
733+
(boolean) typeProvider.hasField(checkedType.name(), lhsResult.value(), field);
740734
if (!hasField) {
741735
// Protobuf sets default (zero) values to uninitialized fields.
742736
// In case of CEL's optional values, we want to explicitly return Optional.none()
@@ -980,6 +974,19 @@ private IntermediateResult evalCelBlock(
980974

981975
return evalInternal(frame, blockCall.args().get(1));
982976
}
977+
978+
private CelType getCheckedTypeOrThrow(CelExpr expr) throws CelEvaluationException {
979+
return ast.getType(expr.id())
980+
.orElseThrow(
981+
() ->
982+
CelEvaluationExceptionBuilder.newBuilder(
983+
"expected a runtime type for expression ID '%d' from checked expression,"
984+
+ " but found none.",
985+
expr.id())
986+
.setErrorCode(CelErrorCode.TYPE_NOT_FOUND)
987+
.setMetadata(metadata, expr.id())
988+
.build());
989+
}
983990
}
984991

985992
/** Contains a CelExpr that is to be lazily evaluated. */

runtime/src/main/java/dev/cel/runtime/DescriptorMessageProvider.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public DescriptorMessageProvider(ProtoMessageFactory protoMessageFactory, CelOpt
9898

9999
@Override
100100
@SuppressWarnings("unchecked")
101-
public @Nullable Object selectField(Object message, String fieldName) {
101+
public @Nullable Object selectField(String unusedTypeName, Object message, String fieldName) {
102102
boolean isOptionalMessage = false;
103103
if (message instanceof Optional) {
104104
isOptionalMessage = true;
@@ -139,15 +139,16 @@ public DescriptorMessageProvider(ProtoMessageFactory protoMessageFactory, CelOpt
139139

140140
/** Adapt object to its message value. */
141141
@Override
142-
public Object adapt(Object message) {
142+
public Object adapt(String messageName, Object message) {
143143
if (message instanceof Message) {
144144
return protoAdapter.adaptProtoToValue((Message) message);
145145
}
146+
146147
return message;
147148
}
148149

149150
@Override
150-
public Object hasField(Object message, String fieldName) {
151+
public Object hasField(String messageName, Object message, String fieldName) {
151152
if (message instanceof Optional<?>) {
152153
Optional<?> optionalMessage = (Optional<?>) message;
153154
if (!optionalMessage.isPresent()) {

runtime/src/main/java/dev/cel/runtime/LiteRuntimeImpl.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,17 +148,17 @@ public Object createMessage(String messageName, Map<String, Object> values) {
148148
}
149149

150150
@Override
151-
public Object selectField(Object message, String fieldName) {
151+
public Object selectField(String typeName, Object message, String fieldName) {
152152
throw new UnsupportedOperationException("Not implemented yet");
153153
}
154154

155155
@Override
156-
public Object hasField(Object message, String fieldName) {
156+
public Object hasField(String messageName, Object message, String fieldName) {
157157
throw new UnsupportedOperationException("Not implemented yet");
158158
}
159159

160160
@Override
161-
public Object adapt(Object message) {
161+
public Object adapt(String messageName, Object message) {
162162
if (message instanceof MessageLiteOrBuilder) {
163163
throw new UnsupportedOperationException("Not implemented yet");
164164
}

runtime/src/main/java/dev/cel/runtime/MessageProvider.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ public interface MessageProvider {
2929
Object createMessage(String messageName, Map<String, Object> values);
3030

3131
/** Select field from message. */
32-
Object selectField(Object message, String fieldName);
32+
Object selectField(String messageName, Object message, String fieldName);
3333

3434
/** Check whether a field is set on message. */
35-
Object hasField(Object message, String fieldName);
35+
Object hasField(String messageName, Object message, String fieldName);
3636

37-
/** Adapt object to its message value with source location metadata on failure . */
38-
Object adapt(Object message);
37+
/** Adapt object to its message value with source location metadata on failure. */
38+
Object adapt(String messageName, Object message);
3939
}

runtime/src/test/java/dev/cel/runtime/DefaultInterpreterTest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,17 +58,17 @@ public Object createMessage(String messageName, Map<String, Object> values) {
5858
}
5959

6060
@Override
61-
public Object selectField(Object message, String fieldName) {
61+
public Object selectField(String typeName, Object message, String fieldName) {
6262
return null;
6363
}
6464

6565
@Override
66-
public Object hasField(Object message, String fieldName) {
66+
public Object hasField(String messageName, Object message, String fieldName) {
6767
return null;
6868
}
6969

7070
@Override
71-
public Object adapt(Object message) {
71+
public Object adapt(String messageName, Object message) {
7272
return message;
7373
}
7474
};

runtime/src/test/java/dev/cel/runtime/DescriptorMessageProviderTest.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -140,24 +140,40 @@ public void createMessage_badFieldError() {
140140

141141
@Test
142142
public void hasField_mapKeyFound() {
143-
assertThat(provider.hasField(ImmutableMap.of("hello", "world"), "hello")).isEqualTo(true);
143+
assertThat(
144+
provider.hasField(
145+
TestAllTypes.getDescriptor().getFullName(),
146+
ImmutableMap.of("hello", "world"),
147+
"hello"))
148+
.isEqualTo(true);
144149
}
145150

146151
@Test
147152
public void hasField_mapKeyNotFound() {
148-
assertThat(provider.hasField(ImmutableMap.of(), "hello")).isEqualTo(false);
153+
assertThat(
154+
provider.hasField(
155+
TestAllTypes.getDescriptor().getFullName(), ImmutableMap.of(), "hello"))
156+
.isEqualTo(false);
149157
}
150158

151159
@Test
152160
public void selectField_mapKeyFound() {
153-
assertThat(provider.selectField(ImmutableMap.of("hello", "world"), "hello")).isEqualTo("world");
161+
assertThat(
162+
provider.selectField(
163+
TestAllTypes.getDescriptor().getFullName(),
164+
ImmutableMap.of("hello", "world"),
165+
"hello"))
166+
.isEqualTo("world");
154167
}
155168

156169
@Test
157170
public void selectField_mapKeyNotFound() {
158171
CelRuntimeException e =
159172
Assert.assertThrows(
160-
CelRuntimeException.class, () -> provider.selectField(ImmutableMap.of(), "hello"));
173+
CelRuntimeException.class,
174+
() ->
175+
provider.selectField(
176+
TestAllTypes.getDescriptor().getFullName(), ImmutableMap.of(), "hello"));
161177
assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
162178
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.ATTRIBUTE_NOT_FOUND);
163179
}
@@ -166,6 +182,7 @@ public void selectField_mapKeyNotFound() {
166182
public void selectField_unsetWrapperField() {
167183
assertThat(
168184
provider.selectField(
185+
TestAllTypes.getDescriptor().getFullName(),
169186
dev.cel.expr.conformance.proto3.TestAllTypes.getDefaultInstance(),
170187
"single_int64_wrapper"))
171188
.isEqualTo(NullValue.NULL_VALUE);
@@ -175,7 +192,10 @@ public void selectField_unsetWrapperField() {
175192
public void selectField_nonProtoObjectError() {
176193
CelRuntimeException e =
177194
Assert.assertThrows(
178-
CelRuntimeException.class, () -> provider.selectField("hello", "not_a_field"));
195+
CelRuntimeException.class,
196+
() ->
197+
provider.selectField(
198+
TestAllTypes.getDescriptor().getFullName(), "hello", "not_a_field"));
179199
assertThat(e).hasCauseThat().isInstanceOf(IllegalArgumentException.class);
180200
assertThat(e.getErrorCode()).isEqualTo(CelErrorCode.ATTRIBUTE_NOT_FOUND);
181201
}
@@ -194,6 +214,7 @@ public void selectField_extensionUsingDynamicTypes() {
194214
long result =
195215
(long)
196216
provider.selectField(
217+
TestAllTypes.getDescriptor().getFullName(),
197218
TestAllTypes.newBuilder().setExtension(TestAllTypesExtensions.int32Ext, 10).build(),
198219
TestAllTypesProto.getDescriptor().getPackage() + ".int32_ext");
199220

0 commit comments

Comments
 (0)