3232import dev .cel .common .CelMutableAst ;
3333import dev .cel .common .CelOverloadDecl ;
3434import dev .cel .common .CelProtoAbstractSyntaxTree ;
35+ import dev .cel .common .CelSource ;
3536import dev .cel .common .Operator ;
3637import dev .cel .common .annotations .Internal ;
3738import dev .cel .common .ast .CelConstant ;
5253import dev .cel .common .types .ListType ;
5354import dev .cel .common .types .MapType ;
5455import dev .cel .common .types .OptionalType ;
56+ import dev .cel .common .types .ProtoMessageType ;
5557import dev .cel .common .types .SimpleType ;
5658import dev .cel .common .types .TypeType ;
5759import java .util .ArrayList ;
5860import java .util .HashSet ;
5961import java .util .List ;
6062import java .util .Map ;
63+ import java .util .Set ;
6164import org .jspecify .annotations .Nullable ;
6265
6366/**
7073@ Internal
7174@ Deprecated
7275public final class ExprChecker {
76+ private static final CelSource .Extension JSON_NAME_EXTENSION =
77+ CelSource .Extension .create (
78+ "json_name" ,
79+ CelSource .Extension .Version .of (1 , 1 ),
80+ CelSource .Extension .Component .COMPONENT_RUNTIME );
7381
7482 /**
7583 * Deprecated type-check API.
@@ -152,7 +160,10 @@ public static CelAbstractSyntaxTree typecheck(
152160
153161 CelAbstractSyntaxTree parsedAst = mutableAst .toParsedAst (/* retainSourcePositions= */ true );
154162 return CelAbstractSyntaxTree .newCheckedAst (
155- parsedAst .getExpr (), parsedAst .getSource (), env .getRefMap (), typeMap );
163+ parsedAst .getExpr (),
164+ parsedAst .getSource ().toBuilder ().addAllExtensions (checker .extensions ).build (),
165+ env .getRefMap (),
166+ typeMap );
156167 }
157168
158169 private final Env env ;
@@ -163,6 +174,7 @@ public static CelAbstractSyntaxTree typecheck(
163174 private final boolean compileTimeOverloadResolution ;
164175 private final boolean homogeneousLiterals ;
165176 private final boolean namespacedDeclarations ;
177+ private final Set <CelSource .Extension > extensions ;
166178
167179 private ExprChecker (
168180 Env env ,
@@ -180,6 +192,7 @@ private ExprChecker(
180192 this .compileTimeOverloadResolution = compileTimeOverloadResolution ;
181193 this .homogeneousLiterals = homogeneousLiterals ;
182194 this .namespacedDeclarations = namespacedDeclarations ;
195+ this .extensions = new HashSet <>();
183196 }
184197
185198 /** Visit the {@code expr} value, routing to overloads based on the kind of expression. */
@@ -370,13 +383,13 @@ private void visit(CelMutableExpr expr, CelMutableStruct struct) {
370383
371384 env .setRef (expr , CelReference .newBuilder ().setName (decl .name ()).build ());
372385 CelType type = decl .type ();
373- if (type .kind () != CelKind .ERROR ) {
374- if (type .kind () != CelKind .TYPE ) {
386+ if (! type .kind (). equals ( CelKind .ERROR ) ) {
387+ if (! type .kind (). equals ( CelKind .TYPE ) ) {
375388 // expected type of types
376389 env .reportError (expr .id (), getPosition (expr ), "'%s' is not a type" , CelTypes .format (type ));
377390 } else {
378391 messageType = ((TypeType ) type ).type ();
379- if (messageType .kind () != CelKind .STRUCT ) {
392+ if (! messageType .kind (). equals ( CelKind .STRUCT ) ) {
380393 env .reportError (
381394 expr .id (),
382395 getPosition (expr ),
@@ -677,14 +690,18 @@ private CelType visitSelectField(
677690 }
678691
679692 if (!Types .isDynOrError (operandType )) {
680- if (operandType .kind () == CelKind .STRUCT ) {
693+ if (operandType .kind (). equals ( CelKind .STRUCT ) ) {
681694 TypeProvider .FieldType fieldType =
682695 getFieldType (expr .id (), getPosition (expr ), operandType , field );
696+ ProtoMessageType protoMessageType = resolveProtoMessageType (operandType );
697+ if (protoMessageType != null && protoMessageType .isJsonName (field )) {
698+ extensions .add (JSON_NAME_EXTENSION );
699+ }
683700 // Type of the field
684701 resultType = fieldType .celType ();
685- } else if (operandType .kind () == CelKind .MAP ) {
702+ } else if (operandType .kind (). equals ( CelKind .MAP ) ) {
686703 resultType = ((MapType ) operandType ).valueType ();
687- } else if (operandType .kind () == CelKind .TYPE_PARAM ) {
704+ } else if (operandType .kind (). equals ( CelKind .TYPE_PARAM ) ) {
688705 // Mark the operand as type DYN to avoid cases where the free type variable might take on
689706 // an incorrect type if used in multiple locations.
690707 //
@@ -714,6 +731,33 @@ private CelType visitSelectField(
714731 return resultType ;
715732 }
716733
734+ private @ Nullable ProtoMessageType resolveProtoMessageType (CelType operandType ) {
735+ if (operandType instanceof ProtoMessageType ) {
736+ return (ProtoMessageType ) operandType ;
737+ }
738+
739+ if (operandType .kind ().equals (CelKind .STRUCT )) {
740+ // This is either a StructTypeReference or just a Struct. Attempt to search for
741+ // ProtoMessageType that may exist in in the type provider.
742+ TypeType typeDef =
743+ typeProvider
744+ .lookupCelType (operandType .name ())
745+ .filter (t -> t instanceof TypeType )
746+ .map (TypeType .class ::cast )
747+ .orElse (null );
748+ if (typeDef == null || typeDef .parameters ().size () != 1 ) {
749+ return null ;
750+ }
751+
752+ CelType maybeProtoMessageType = typeDef .parameters ().get (0 );
753+ if (maybeProtoMessageType instanceof ProtoMessageType ) {
754+ return (ProtoMessageType ) maybeProtoMessageType ;
755+ }
756+ }
757+
758+ return null ;
759+ }
760+
717761 private void visitOptionalCall (CelMutableExpr expr , CelMutableCall call ) {
718762 CelMutableExpr operand = call .args ().get (0 );
719763 CelMutableExpr field = call .args ().get (1 );
0 commit comments