2222import static dev .cel .common .formats .YamlHelper .newString ;
2323import static dev .cel .common .formats .YamlHelper .parseYamlSource ;
2424import static dev .cel .common .formats .YamlHelper .validateYamlType ;
25- import static java .util .Collections .singletonList ;
2625
2726import com .google .common .collect .ImmutableList ;
2827import com .google .common .collect .ImmutableSet ;
2928import com .google .errorprone .annotations .CanIgnoreReturnValue ;
29+ import com .google .errorprone .annotations .CheckReturnValue ;
3030import dev .cel .bundle .CelEnvironment .Alias ;
3131import dev .cel .bundle .CelEnvironment .ContextVariable ;
3232import dev .cel .bundle .CelEnvironment .ExtensionConfig ;
6060 */
6161public final class CelEnvironmentYamlParser {
6262 // Sentinel values to be returned for various declarations when parsing failure is encountered.
63- private static final TypeDecl ERROR_TYPE_DECL = TypeDecl . create ( ERROR ) ;
63+ static final TypeDecl ERROR_TYPE_DECL = TypeSpecifierParser . ERROR_TYPE_DECL ;
6464 private static final VariableDecl ERROR_VARIABLE_DECL =
6565 VariableDecl .create (ERROR , ERROR_TYPE_DECL );
6666 private static final FunctionDecl ERROR_FUNCTION_DECL =
@@ -71,9 +71,44 @@ public final class CelEnvironmentYamlParser {
7171 private static final Alias ERROR_ALIAS =
7272 Alias .newBuilder ().setAlias (ERROR ).setQualifiedName (ERROR ).build ();
7373
74- /** Generates a new instance of {@code CelEnvironmentYamlParser}. */
74+ private final boolean enableTypeSpecifiers ;
75+
76+ /** Generates a new instance of {@code CelEnvironmentYamlParser} with default options. */
7577 public static CelEnvironmentYamlParser newInstance () {
76- return new CelEnvironmentYamlParser ();
78+ return newBuilder ().build ();
79+ }
80+
81+ /** Creates a new builder to configure and construct a {@link CelEnvironmentYamlParser}. */
82+ public static Builder newBuilder () {
83+ return new Builder ();
84+ }
85+
86+ /** Builder for {@link CelEnvironmentYamlParser}. */
87+ public static final class Builder {
88+ private boolean enableTypeSpecifiers = false ;
89+
90+ /**
91+ * Configures the parser to allow for shorthand type specifiers (e.g. {@code "list<int>"},
92+ * {@code "map<string, dyn>"}, {@code "list<~T>"}) in addition to structured mapping
93+ * declarations.
94+ */
95+ @ CanIgnoreReturnValue
96+ public Builder enableTypeSpecifiers (boolean enable ) {
97+ this .enableTypeSpecifiers = enable ;
98+ return this ;
99+ }
100+
101+ /** Builds a new instance of {@link CelEnvironmentYamlParser}. */
102+ @ CheckReturnValue
103+ public CelEnvironmentYamlParser build () {
104+ return new CelEnvironmentYamlParser (enableTypeSpecifiers );
105+ }
106+
107+ private Builder () {}
108+ }
109+
110+ private CelEnvironmentYamlParser (boolean enableTypeSpecifiers ) {
111+ this .enableTypeSpecifiers = enableTypeSpecifiers ;
77112 }
78113
79114 /** Parsers the input {@code environmentYamlSource} and returns a {@link CelEnvironment}. */
@@ -335,6 +370,7 @@ private ContextVariable parseContextVariable(ParserContext<Node> ctx, Node node)
335370 Node valueNode = nodeTuple .getValueNode ();
336371 String keyName = ((ScalarNode ) keyNode ).getValue ();
337372 switch (keyName ) {
373+ case "type" :
338374 case "type_name" :
339375 typeName = newString (ctx , valueNode );
340376 break ;
@@ -478,7 +514,7 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
478514 return builder .build ();
479515 }
480516
481- private static ImmutableSet <OverloadDecl > parseOverloads (ParserContext <Node > ctx , Node node ) {
517+ private ImmutableSet <OverloadDecl > parseOverloads (ParserContext <Node > ctx , Node node ) {
482518 long listId = ctx .collectMetadata (node );
483519 ImmutableSet .Builder <OverloadDecl > overloadSetBuilder = ImmutableSet .builder ();
484520 if (!assertYamlType (ctx , listId , node , YamlNodeType .LIST )) {
@@ -553,8 +589,7 @@ private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> c
553589 return builder .build ();
554590 }
555591
556- private static ImmutableList <TypeDecl > parseOverloadArguments (
557- ParserContext <Node > ctx , Node node ) {
592+ private ImmutableList <TypeDecl > parseOverloadArguments (ParserContext <Node > ctx , Node node ) {
558593 long listValueId = ctx .collectMetadata (node );
559594 if (!assertYamlType (ctx , listValueId , node , YamlNodeType .LIST )) {
560595 return ImmutableList .of ();
@@ -791,7 +826,7 @@ private static ImmutableSet<OverloadSelector> parseFunctionOverloadsSelector(
791826 }
792827
793828 @ CanIgnoreReturnValue
794- private static TypeDecl .Builder parseInlinedTypeDecl (
829+ private TypeDecl .Builder parseInlinedTypeDecl (
795830 ParserContext <Node > ctx , long keyId , Node keyNode , Node valueNode , TypeDecl .Builder builder ) {
796831 if (!assertYamlType (ctx , keyId , keyNode , YamlNodeType .STRING , YamlNodeType .TEXT )) {
797832 return builder ;
@@ -800,24 +835,38 @@ private static TypeDecl.Builder parseInlinedTypeDecl(
800835 // Create a synthetic node to make this behave as if a `type: ` parent node actually exists.
801836 MappingNode mapNode =
802837 new MappingNode (
803- Tag .MAP , /* value= */ singletonList (new NodeTuple (keyNode , valueNode )), FlowStyle .AUTO );
838+ Tag .MAP ,
839+ /* value= */ ImmutableList .of (new NodeTuple (keyNode , valueNode )),
840+ FlowStyle .AUTO );
804841
805842 return parseTypeDeclFields (ctx , mapNode , builder );
806843 }
807844
808- private static TypeDecl parseTypeDecl (ParserContext <Node > ctx , Node node ) {
809- TypeDecl .Builder builder = TypeDecl .newBuilder ();
845+ private TypeDecl parseTypeDecl (ParserContext <Node > ctx , Node node ) {
810846 long id = ctx .collectMetadata (node );
847+ if (enableTypeSpecifiers ) {
848+ if (validateYamlType (node , YamlNodeType .STRING , YamlNodeType .TEXT )) {
849+ return TypeSpecifierParser .parse (ctx , id , newString (ctx , node ));
850+ }
851+ if (validateYamlType (node , YamlNodeType .MAP )) {
852+ TypeDecl .Builder builder = TypeDecl .newBuilder ();
853+ return parseTypeDeclFields (ctx , (MappingNode ) node , builder ).build ();
854+ }
855+ assertYamlType (ctx , id , node , YamlNodeType .STRING , YamlNodeType .TEXT , YamlNodeType .MAP );
856+ return ERROR_TYPE_DECL ;
857+ }
858+
811859 if (!assertYamlType (ctx , id , node , YamlNodeType .MAP )) {
812860 return ERROR_TYPE_DECL ;
813861 }
814862
863+ TypeDecl .Builder builder = TypeDecl .newBuilder ();
815864 MappingNode mapNode = (MappingNode ) node ;
816865 return parseTypeDeclFields (ctx , mapNode , builder ).build ();
817866 }
818867
819868 @ CanIgnoreReturnValue
820- private static TypeDecl .Builder parseTypeDeclFields (
869+ private TypeDecl .Builder parseTypeDeclFields (
821870 ParserContext <Node > ctx , MappingNode mapNode , TypeDecl .Builder builder ) {
822871 for (NodeTuple nodeTuple : mapNode .getValue ()) {
823872 Node keyNode = nodeTuple .getKeyNode ();
@@ -943,6 +992,4 @@ private CelEnvironment.Builder parseConfig(ParserContext<Node> ctx, Node node) {
943992 return builder ;
944993 }
945994 }
946-
947- private CelEnvironmentYamlParser () {}
948995}
0 commit comments