diff --git a/bundle/src/main/java/dev/cel/bundle/BUILD.bazel b/bundle/src/main/java/dev/cel/bundle/BUILD.bazel
index ce120220e..3c7608900 100644
--- a/bundle/src/main/java/dev/cel/bundle/BUILD.bazel
+++ b/bundle/src/main/java/dev/cel/bundle/BUILD.bazel
@@ -102,6 +102,7 @@ java_library(
name = "environment",
srcs = [
"CelEnvironment.java",
+ "CelOverloadDeclParser.java",
"TypeSpecifierParser.java",
],
tags = [
@@ -115,12 +116,14 @@ java_library(
"//checker:standard_decl",
"//common:cel_function_decl",
"//common:cel_overload_decl",
+ "//common:cel_overload_decl_formatter",
"//common:cel_var_decl",
"//common:container",
"//common:options",
"//common:source",
"//common/formats:parser_context",
"//common/types",
+ "//common/types:cel_types",
"//common/types:type_providers",
"//compiler:compiler_builder",
"//extensions",
@@ -152,10 +155,13 @@ java_library(
deps = [
":environment",
":environment_exception",
+ "//common:cel_overload_decl_formatter",
"//common:compiler_common",
"//common:container",
+ "//common:type_specifier_formatter",
"//common/formats:file_source",
"//common/formats:parser_context",
+ "//common/formats:value_string",
"//common/formats:yaml_helper",
"//common/formats:yaml_parser_context_impl",
"//common/internal",
diff --git a/bundle/src/main/java/dev/cel/bundle/CelEnvironment.java b/bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
index 192f368b3..5fe2ff300 100644
--- a/bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
+++ b/bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
@@ -14,6 +14,7 @@
package dev.cel.bundle;
+import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
@@ -35,12 +36,17 @@
import dev.cel.common.CelFunctionDecl;
import dev.cel.common.CelOptions;
import dev.cel.common.CelOverloadDecl;
+import dev.cel.common.CelOverloadDeclFormatter;
import dev.cel.common.CelVarDecl;
import dev.cel.common.Source;
+import dev.cel.common.types.CelKind;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
+import dev.cel.common.types.CelTypes;
import dev.cel.common.types.ListType;
import dev.cel.common.types.MapType;
+import dev.cel.common.types.NullableType;
+import dev.cel.common.types.OpaqueType;
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
@@ -55,6 +61,7 @@
import dev.cel.runtime.CelRuntimeLibrary;
import java.util.Arrays;
import java.util.Optional;
+import java.util.function.Function;
import java.util.function.ObjIntConsumer;
/**
@@ -545,8 +552,12 @@ public CelFunctionDecl toCelFunctionDecl(CelTypeProvider celTypeProvider) {
public abstract static class OverloadDecl {
/**
- * A unique overload ID. Required. This should follow the typical naming convention used in CEL
- * (e.g: targetType_func_argType1_argType...)
+ * A unique overload ID. Required.
+ *
+ *
This can follow the typical naming convention used in CEL (e.g. {@code
+ * targetType_func_argType1_argType...}) or use a canonical overload signature (e.g. {@code
+ * targetType.func(argType1,argType2)}). When parsed from YAML with a {@code signature} field
+ * and no explicit {@code id}, this defaults to the {@code signature} string.
*/
public abstract String id();
@@ -623,21 +634,29 @@ public static OverloadDecl.Builder newBuilder() {
/** Converts this policy function overload into a {@link CelOverloadDecl}. */
public CelOverloadDecl toCelOverloadDecl(CelTypeProvider celTypeProvider) {
+ return toCelOverloadDecl(celTypeProvider::findType);
+ }
+
+ CelOverloadDecl toCelOverloadDecl() {
+ return toCelOverloadDecl(typeName -> Optional.of(OpaqueType.create(typeName)));
+ }
+
+ private CelOverloadDecl toCelOverloadDecl(Function> typeFinder) {
CelOverloadDecl.Builder builder =
CelOverloadDecl.newBuilder()
.setIsInstanceFunction(false)
.setOverloadId(id())
- .setResultType(returnType().toCelType(celTypeProvider));
+ .setResultType(returnType().toCelType(typeFinder));
target()
.ifPresent(
t ->
builder
.setIsInstanceFunction(true)
- .addParameterTypes(t.toCelType(celTypeProvider)));
+ .addParameterTypes(t.toCelType(typeFinder)));
for (TypeDecl type : arguments()) {
- builder.addParameterTypes(type.toCelType(celTypeProvider));
+ builder.addParameterTypes(type.toCelType(typeFinder));
}
return builder.build();
@@ -709,20 +728,70 @@ static TypeDecl ofTypeParam(String typeParamName) {
return newBuilder().setName(typeParamName).setIsTypeParam(true).build();
}
+ /** Converts a {@link CelType} into a {@link TypeDecl}. */
+ static TypeDecl fromCelType(CelType type) {
+ if (type.kind() == CelKind.ERROR
+ || type.kind() == CelKind.UNSPECIFIED
+ || (type.kind() == CelKind.OPAQUE && type.name().equals("function"))) {
+ throw new IllegalArgumentException("Unsupported type: " + type.name());
+ }
+ if (type instanceof NullableType) {
+ switch (((NullableType) type).targetType().kind()) {
+ case BOOL:
+ return TypeDecl.create(CelTypes.BOOL_WRAPPER_MESSAGE);
+ case BYTES:
+ return TypeDecl.create(CelTypes.BYTES_WRAPPER_MESSAGE);
+ case DOUBLE:
+ return TypeDecl.create(CelTypes.DOUBLE_WRAPPER_MESSAGE);
+ case INT:
+ return TypeDecl.create(CelTypes.INT64_WRAPPER_MESSAGE);
+ case STRING:
+ return TypeDecl.create(CelTypes.STRING_WRAPPER_MESSAGE);
+ case UINT:
+ return TypeDecl.create(CelTypes.UINT64_WRAPPER_MESSAGE);
+ default:
+ throw new IllegalArgumentException("Unsupported wrapper type: " + type.name());
+ }
+ }
+ return TypeDecl.newBuilder()
+ .setName(type.name())
+ .setIsTypeParam(type.kind() == CelKind.TYPE_PARAM)
+ .addParams(
+ type.parameters().stream().map(TypeDecl::fromCelType).collect(toImmutableList()))
+ .build();
+ }
+
public static TypeDecl.Builder newBuilder() {
return new AutoValue_CelEnvironment_TypeDecl.Builder().setIsTypeParam(false);
}
/** Converts this type declaration into a {@link CelType}. */
public CelType toCelType(CelTypeProvider celTypeProvider) {
+ return toCelType(celTypeProvider::findType);
+ }
+
+ CelType toCelType() {
+ return toCelType(typeName -> Optional.of(OpaqueType.create(typeName)));
+ }
+
+ private CelType toCelType(Function> typeFinder) {
+ if (isTypeParam()) {
+ if (!params().isEmpty()) {
+ throw new IllegalArgumentException(
+ "Type param has unexpected param count: " + params().size());
+ }
+ return TypeParamType.create(name());
+ }
switch (name()) {
+ case "*error*":
+ throw new IllegalArgumentException("Unsupported type name: " + name());
case "list":
if (params().size() != 1) {
throw new IllegalArgumentException(
"List type has unexpected param count: " + params().size());
}
- CelType elementType = params().get(0).toCelType(celTypeProvider);
+ CelType elementType = params().get(0).toCelType(typeFinder);
return ListType.create(elementType);
case "map":
if (params().size() != 2) {
@@ -730,38 +799,72 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
"Map type has unexpected param count: " + params().size());
}
- CelType keyType = params().get(0).toCelType(celTypeProvider);
- CelType valueType = params().get(1).toCelType(celTypeProvider);
+ CelType keyType = params().get(0).toCelType(typeFinder);
+ CelType valueType = params().get(1).toCelType(typeFinder);
return MapType.create(keyType, valueType);
case "type":
checkState(
params().size() == 1, "Expected 1 parameter for type, got %s", params().size());
- return TypeType.create(params().get(0).toCelType(celTypeProvider));
+ return TypeType.create(params().get(0).toCelType(typeFinder));
+ case OptionalType.NAME:
+ checkState(
+ params().size() == 1,
+ "Optional type must have exactly 1 parameter. Found %s",
+ params().size());
+ return OptionalType.create(params().get(0).toCelType(typeFinder));
default:
- if (isTypeParam()) {
- return TypeParamType.create(name());
- }
+ break;
+ }
- if (name().equals("dyn")) {
- return SimpleType.DYN;
- }
+ Optional builtinType = findCelTypeByName(name());
+ if (builtinType.isPresent()) {
+ checkArgument(
+ params().isEmpty(), "Type %s cannot have type parameters", name());
+ return builtinType.get();
+ }
- CelType simpleType = SimpleType.findByName(name()).orElse(null);
- if (simpleType != null) {
- return simpleType;
- }
+ CelType resolvedType =
+ typeFinder
+ .apply(name())
+ .orElseThrow(
+ () -> new IllegalArgumentException("Undefined type name: " + name()));
+ if (!params().isEmpty()) {
+ return resolvedType.withParameters(
+ params().stream().map(p -> p.toCelType(typeFinder)).collect(toImmutableList()));
+ }
+ return resolvedType;
+ }
- if (name().equals(OptionalType.NAME)) {
- checkState(
- params().size() == 1,
- "Optional type must have exactly 1 parameter. Found %s",
- params().size());
- return OptionalType.create(params().get(0).toCelType(celTypeProvider));
+ private static Optional findCelTypeByName(String name) {
+ switch (name) {
+ case "dyn":
+ return Optional.of(SimpleType.DYN);
+ case "null":
+ return Optional.of(SimpleType.NULL_TYPE);
+ case "any":
+ return Optional.of(SimpleType.ANY);
+ case "timestamp":
+ return Optional.of(SimpleType.TIMESTAMP);
+ case "duration":
+ return Optional.of(SimpleType.DURATION);
+ case "bool_wrapper":
+ return Optional.of(NullableType.create(SimpleType.BOOL));
+ case "bytes_wrapper":
+ return Optional.of(NullableType.create(SimpleType.BYTES));
+ case "double_wrapper":
+ return Optional.of(NullableType.create(SimpleType.DOUBLE));
+ case "int_wrapper":
+ return Optional.of(NullableType.create(SimpleType.INT));
+ case "string_wrapper":
+ return Optional.of(NullableType.create(SimpleType.STRING));
+ case "uint_wrapper":
+ return Optional.of(NullableType.create(SimpleType.UINT));
+ default:
+ Optional simpleType = SimpleType.findByName(name);
+ if (simpleType.isPresent()) {
+ return simpleType;
}
-
- return celTypeProvider
- .findType(name())
- .orElseThrow(() -> new IllegalArgumentException("Undefined type name: " + name()));
+ return CelTypes.getWellKnownCelType(name);
}
}
}
@@ -1057,6 +1160,15 @@ public static FunctionSelector.Builder newBuilder() {
.setOverloads(ImmutableSet.of());
}
+ /**
+ * Creates a new {@link FunctionSelector} matching the given function {@code name} and {@code
+ * overloads}.
+ *
+ * @param name the function name to match
+ * @param overloads the overload IDs or canonical overload signatures (e.g. {@code
+ * "add_bytes"} or {@code "_+_(bytes,bytes)"}) to match, or empty to match all overloads
+ * of the function
+ */
public static FunctionSelector create(String name, ImmutableSet overloads) {
return newBuilder()
.setName(name)
@@ -1072,6 +1184,7 @@ private static boolean matchesAny(
StandardOverload overload,
ImmutableSet selectors) {
String functionName = function.functionDecl().name();
+ String overloadSignature = null;
for (FunctionSelector functionSelector : selectors) {
if (!functionSelector.name().equals(functionName)) {
continue;
@@ -1081,12 +1194,24 @@ private static boolean matchesAny(
return true;
}
- String overloadId = overload.celOverloadDecl().overloadId();
+ CelOverloadDecl celOverload = overload.celOverloadDecl();
+ String overloadId = celOverload.overloadId();
for (OverloadSelector overloadSelector : functionSelector.overloads()) {
if (overloadSelector.id().equals(overloadId)) {
return true;
}
}
+
+ if (overloadSignature == null) {
+ overloadSignature = CelOverloadDeclFormatter.format(functionName, celOverload);
+ }
+ if (!overloadSignature.equals(overloadId)) {
+ for (OverloadSelector overloadSelector : functionSelector.overloads()) {
+ if (overloadSelector.id().equals(overloadSignature)) {
+ return true;
+ }
+ }
+ }
}
return false;
}
@@ -1096,7 +1221,10 @@ private static boolean matchesAny(
@AutoValue
public abstract static class OverloadSelector {
- /** An overload ID. Required. Follows the same format as {@link OverloadDecl#id()} */
+ /**
+ * An overload ID or canonical overload signature (e.g. {@code "add_bytes"} or {@code
+ * "_+_(bytes,bytes)"}). Required. Follows the same format as {@link OverloadDecl#id()}.
+ */
public abstract String id();
/** Builder for {@link OverloadSelector}. */
diff --git a/bundle/src/main/java/dev/cel/bundle/CelEnvironmentExporter.java b/bundle/src/main/java/dev/cel/bundle/CelEnvironmentExporter.java
index 462de653d..9c0fc3a7b 100644
--- a/bundle/src/main/java/dev/cel/bundle/CelEnvironmentExporter.java
+++ b/bundle/src/main/java/dev/cel/bundle/CelEnvironmentExporter.java
@@ -41,7 +41,6 @@
import dev.cel.common.CelVarDecl;
import dev.cel.common.internal.EnvVisitable;
import dev.cel.common.internal.EnvVisitor;
-import dev.cel.common.types.CelKind;
import dev.cel.common.types.CelType;
import dev.cel.compiler.CelCompiler;
import dev.cel.extensions.CelExtensionLibrary;
@@ -492,12 +491,7 @@ private CelEnvironment.OverloadDecl toCelEnvOverloadDecl(CelOverloadDecl overloa
}
private CelEnvironment.TypeDecl toCelEnvTypeDecl(CelType type) {
- return CelEnvironment.TypeDecl.newBuilder()
- .setName(type.name())
- .setIsTypeParam(type.kind() == CelKind.TYPE_PARAM)
- .addParams(
- type.parameters().stream().map(this::toCelEnvTypeDecl).collect(toImmutableList()))
- .build();
+ return CelEnvironment.TypeDecl.fromCelType(type);
}
/** Wrapper for CelOverloadDecl, associating it with the corresponding function name. */
diff --git a/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlParser.java b/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlParser.java
index 821ca6586..dcdec0d15 100644
--- a/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlParser.java
+++ b/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlParser.java
@@ -36,10 +36,12 @@
import dev.cel.bundle.CelEnvironment.OverloadDecl;
import dev.cel.bundle.CelEnvironment.TypeDecl;
import dev.cel.bundle.CelEnvironment.VariableDecl;
+import dev.cel.bundle.CelOverloadDeclParser.ParsedOverloadDecl;
import dev.cel.common.CelContainer;
import dev.cel.common.CelIssue;
import dev.cel.common.formats.CelFileSource;
import dev.cel.common.formats.ParserContext;
+import dev.cel.common.formats.ValueString;
import dev.cel.common.formats.YamlHelper.YamlNodeType;
import dev.cel.common.formats.YamlParserContextImpl;
import dev.cel.common.internal.CelCodePointArray;
@@ -450,6 +452,7 @@ private FunctionDecl parseFunction(ParserContext ctx, Node node) {
MappingNode functionMap = (MappingNode) node;
FunctionDecl.Builder builder = FunctionDecl.newBuilder();
+ Node overloadsNode = null;
for (NodeTuple nodeTuple : functionMap.getValue()) {
Node keyNode = nodeTuple.getKeyNode();
long keyId = ctx.collectMetadata(keyNode);
@@ -460,7 +463,7 @@ private FunctionDecl parseFunction(ParserContext ctx, Node node) {
builder.setName(newString(ctx, valueNode));
break;
case "overloads":
- builder.setOverloads(parseOverloads(ctx, valueNode));
+ overloadsNode = valueNode;
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
@@ -471,6 +474,10 @@ private FunctionDecl parseFunction(ParserContext ctx, Node node) {
}
}
+ if (overloadsNode != null) {
+ builder.setOverloads(parseOverloads(ctx, overloadsNode, builder.name().orElse("")));
+ }
+
if (!assertRequiredFields(ctx, functionId, builder.getMissingRequiredFieldNames())) {
return ERROR_FUNCTION_DECL;
}
@@ -478,7 +485,8 @@ private FunctionDecl parseFunction(ParserContext ctx, Node node) {
return builder.build();
}
- private ImmutableSet parseOverloads(ParserContext ctx, Node node) {
+ private ImmutableSet parseOverloads(
+ ParserContext ctx, Node node, String functionName) {
long listId = ctx.collectMetadata(node);
ImmutableSet.Builder overloadSetBuilder = ImmutableSet.builder();
if (!assertYamlType(ctx, listId, node, YamlNodeType.LIST)) {
@@ -494,6 +502,8 @@ private ImmutableSet parseOverloads(ParserContext ctx, Node
MappingNode mapNode = (MappingNode) overloadMapNode;
OverloadDecl.Builder overloadDeclBuilder = OverloadDecl.newBuilder();
+ boolean hasSignature = false;
+ boolean hasTargetOrArgs = false;
for (NodeTuple nodeTuple : mapNode.getValue()) {
Node keyNode = nodeTuple.getKeyNode();
long keyId = ctx.collectMetadata(keyNode);
@@ -507,15 +517,41 @@ private ImmutableSet parseOverloads(ParserContext ctx, Node
case "id":
overloadDeclBuilder.setId(newString(ctx, valueNode));
break;
+ case "signature":
+ if (hasTargetOrArgs) {
+ if (!overloadDeclBuilder.id().isPresent()) {
+ overloadDeclBuilder.setId(ERROR);
+ }
+ ctx.reportError(
+ keyId,
+ String.format(
+ "'signature' tag cannot be used together with 'target' or 'args': %s",
+ fieldName));
+ break;
+ }
+ hasSignature = true;
+ parseOverloadSignature(ctx, valueNode, functionName, overloadDeclBuilder);
+ break;
case "args":
- overloadDeclBuilder.addArguments(parseOverloadArguments(ctx, valueNode));
+ case "target":
+ if (hasSignature) {
+ ctx.reportError(
+ keyId,
+ String.format(
+ "'signature' tag cannot be used together with 'target' or 'args': %s",
+ fieldName));
+ break;
+ }
+ hasTargetOrArgs = true;
+ if (fieldName.equals("args")) {
+ overloadDeclBuilder.addArguments(parseOverloadArguments(ctx, valueNode));
+ } else {
+ overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
+ }
break;
case "return":
overloadDeclBuilder.setReturnType(parseTypeDecl(ctx, valueNode));
break;
- case "target":
- overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
- break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
@@ -534,6 +570,43 @@ private ImmutableSet parseOverloads(ParserContext ctx, Node
return overloadSetBuilder.build();
}
+ private static void parseOverloadSignature(
+ ParserContext ctx,
+ Node valueNode,
+ String functionName,
+ OverloadDecl.Builder overloadDeclBuilder) {
+ ValueString signatureValue = ctx.newYamlString(valueNode);
+ String signature = signatureValue.value();
+ if (!overloadDeclBuilder.id().isPresent()) {
+ overloadDeclBuilder.setId(signature);
+ }
+ if (signature.equals(ERROR)) {
+ return;
+ }
+
+ ParsedOverloadDecl parsedSignature;
+ try {
+ parsedSignature = CelOverloadDeclParser.parse(signature);
+ } catch (IllegalArgumentException e) {
+ ctx.reportError(signatureValue.id(), e.getMessage());
+ return;
+ }
+
+ if (!functionName.isEmpty()
+ && !functionName.equals(ERROR)
+ && !parsedSignature.functionName().equals(functionName)) {
+ ctx.reportError(
+ signatureValue.id(),
+ String.format(
+ "Function overload name '%s' does not match function name '%s'",
+ parsedSignature.functionName(), functionName));
+ return;
+ }
+
+ parsedSignature.target().ifPresent(overloadDeclBuilder::setTarget);
+ overloadDeclBuilder.addArguments(parsedSignature.arguments());
+ }
+
private static ImmutableList parseOverloadExamples(ParserContext ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
diff --git a/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlSerializer.java b/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlSerializer.java
index 9d5b4b69e..92f0b50a4 100644
--- a/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlSerializer.java
+++ b/bundle/src/main/java/dev/cel/bundle/CelEnvironmentYamlSerializer.java
@@ -21,6 +21,9 @@
import dev.cel.bundle.CelEnvironment.LibrarySubset.FunctionSelector;
import dev.cel.bundle.CelEnvironment.LibrarySubset.OverloadSelector;
import dev.cel.common.CelContainer;
+import dev.cel.common.CelOverloadDecl;
+import dev.cel.common.CelOverloadDeclFormatter;
+import dev.cel.common.TypeSpecifierFormatter;
import java.util.Comparator;
import java.util.Map;
import org.yaml.snakeyaml.DumperOptions;
@@ -42,14 +45,19 @@ private static DumperOptions initDumperOptions() {
private static final DumperOptions YAML_OPTIONS = initDumperOptions();
- private static final CelEnvironmentYamlSerializer INSTANCE = new CelEnvironmentYamlSerializer();
+ private static final CelEnvironmentYamlSerializer DEFAULT_INSTANCE =
+ new CelEnvironmentYamlSerializer(/* useTypeSignatures= */ false);
+ private static final CelEnvironmentYamlSerializer SIGNATURE_INSTANCE =
+ new CelEnvironmentYamlSerializer(/* useTypeSignatures= */ true);
- private CelEnvironmentYamlSerializer() {
+ private final boolean useTypeSignatures;
+
+ private CelEnvironmentYamlSerializer(boolean useTypeSignatures) {
super(YAML_OPTIONS);
+ this.useTypeSignatures = useTypeSignatures;
this.multiRepresenters.put(CelEnvironment.class, new RepresentCelEnvironment());
this.multiRepresenters.put(CelEnvironment.VariableDecl.class, new RepresentVariableDecl());
this.multiRepresenters.put(CelEnvironment.FunctionDecl.class, new RepresentFunctionDecl());
- this.multiRepresenters.put(CelEnvironment.OverloadDecl.class, new RepresentOverloadDecl());
this.multiRepresenters.put(CelEnvironment.TypeDecl.class, new RepresentTypeDecl());
this.multiRepresenters.put(
CelEnvironment.ExtensionConfig.class, new RepresentExtensionConfig());
@@ -64,9 +72,18 @@ private CelEnvironmentYamlSerializer() {
this.multiRepresenters.put(CelEnvironment.Limit.class, new RepresentLimit());
}
- public static String toYaml(CelEnvironment environment) {
+ /**
+ * Serializes the given {@link CelEnvironment} into a YAML string.
+ *
+ * @param environment the environment to serialize
+ * @param useTypeSignatures if true, formats variable types, function overload signatures, and
+ * return types using canonical CEL signature strings instead of verbose type maps
+ */
+ public static String toYaml(CelEnvironment environment, boolean useTypeSignatures) {
// Yaml is not thread-safe, so we create a new instance for each serialization.
- Yaml yaml = new Yaml(INSTANCE, YAML_OPTIONS);
+ CelEnvironmentYamlSerializer serializer =
+ useTypeSignatures ? SIGNATURE_INSTANCE : DEFAULT_INSTANCE;
+ Yaml yaml = new Yaml(serializer, YAML_OPTIONS);
return yaml.dump(environment);
}
@@ -159,9 +176,17 @@ private final class RepresentVariableDecl implements Represent {
public Node representData(Object data) {
CelEnvironment.VariableDecl variable = (CelEnvironment.VariableDecl) data;
ImmutableMap.Builder configMap = new ImmutableMap.Builder<>();
- configMap.put("name", variable.name()).put("type_name", variable.type().name());
- if (!variable.type().params().isEmpty()) {
- configMap.put("params", variable.type().params());
+ configMap.put("name", variable.name());
+ if (variable.description().isPresent() && !variable.description().get().isEmpty()) {
+ configMap.put("description", variable.description().get());
+ }
+ if (useTypeSignatures) {
+ configMap.put("type", TypeSpecifierFormatter.format(variable.type().toCelType()));
+ } else {
+ configMap.put("type_name", variable.type().name());
+ if (!variable.type().params().isEmpty()) {
+ configMap.put("params", variable.type().params());
+ }
}
return represent(configMap.buildOrThrow());
}
@@ -172,23 +197,45 @@ private final class RepresentFunctionDecl implements Represent {
public Node representData(Object data) {
CelEnvironment.FunctionDecl function = (CelEnvironment.FunctionDecl) data;
ImmutableMap.Builder configMap = new ImmutableMap.Builder<>();
- configMap.put("name", function.name()).put("overloads", function.overloads().asList());
+ configMap.put("name", function.name());
+ if (function.description().isPresent() && !function.description().get().isEmpty()) {
+ configMap.put("description", function.description().get());
+ }
+ ImmutableList.Builder