Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 43 additions & 14 deletions bundle/src/main/java/dev/cel/bundle/CelEnvironment.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,6 +43,7 @@
import dev.cel.common.types.OptionalType;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeParamType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerBuilder;
import dev.cel.compiler.CelCompilerLibrary;
Expand DownExpand Up@@ -71,38 +72,37 @@ public abstract class CelEnvironment {
"math", CanonicalCelExtension.MATH,
"optional", CanonicalCelExtension.OPTIONAL,
"protos", CanonicalCelExtension.PROTOS,
"regex", CanonicalCelExtension.REGEX,
"sets", CanonicalCelExtension.SETS,
"strings", CanonicalCelExtension.STRINGS,
"comprehensions", CanonicalCelExtension.COMPREHENSIONS);
"two-var-comprehensions", CanonicalCelExtension.COMPREHENSIONS);

private static final ImmutableMap<String, ObjIntConsumer<CelOptions.Builder>> LIMIT_HANDLERS =
ImmutableMap.of(
"cel.limit.expression_code_points",
(options, value) -> options.maxExpressionCodePointSize(value),
CelOptions.Builder::maxExpressionCodePointSize,
"cel.limit.parse_error_recovery",
(options, value) -> options.maxParseErrorRecoveryLimit(value),
CelOptions.Builder::maxParseErrorRecoveryLimit,
"cel.limit.parse_recursion_depth",
(options, value) -> options.maxParseRecursionDepth(value));
CelOptions.Builder::maxParseRecursionDepth);

private static final ImmutableMap<String, BooleanOptionConsumer> FEATURE_HANDLERS =
ImmutableMap.of(
"cel.feature.macro_call_tracking",
(options, enabled) -> options.populateMacroCalls(enabled),
CelOptions.Builder::populateMacroCalls,
"cel.feature.backtick_escape_syntax",
(options, enabled) -> options.enableQuotedIdentifierSyntax(enabled),
CelOptions.Builder::enableQuotedIdentifierSyntax,
"cel.feature.cross_type_numeric_comparisons",
(options, enabled) -> options.enableHeterogeneousNumericComparisons(enabled));
CelOptions.Builder::enableHeterogeneousNumericComparisons);

/** Environment source in textual format (ex: textproto, YAML). */
public abstract Optional<Source> source();

/** Name of the environment. */
public abstract String name();

/**
* Container, which captures default namespace and aliases for value resolution.
*/
public abstract CelContainer container();
/** Container, which captures default namespace and aliases for value resolution. */
public abstract Optional<CelContainer> container();

/**
* An optional description of the environment (example: location of the file containing the config
Expand DownExpand Up@@ -226,7 +226,6 @@ public static Builder newBuilder() {
return new AutoValue_CelEnvironment.Builder()
.setName("")
.setDescription("")
.setContainer(CelContainer.ofName(""))
.setVariables(ImmutableSet.of())
.setFunctions(ImmutableSet.of())
.setFeatures(ImmutableSet.of())
Expand All@@ -242,7 +241,6 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
CelCompilerBuilder compilerBuilder =
celCompiler
.toCompilerBuilder()
.setContainer(container())
.setOptions(celOptions)
.setTypeProvider(celTypeProvider)
.addVarDeclarations(
Expand All@@ -254,6 +252,8 @@ public CelCompiler extend(CelCompiler celCompiler, CelOptions celOptions)
.map(f -> f.toCelFunctionDecl(celTypeProvider))
.collect(toImmutableList()));

container().ifPresent(compilerBuilder::setContainer);

addAllCompilerExtensions(compilerBuilder, celOptions);

applyStandardLibrarySubset(compilerBuilder);
Expand DownExpand Up@@ -416,6 +416,8 @@ public abstract static class VariableDecl {
/** The type of the variable. */
public abstract TypeDecl type();

public abstract Optional<String> description();

/** Builder for {@link VariableDecl}. */
@AutoValue.Builder
public abstract static class Builder implements RequiredFieldsChecker {
Expand All@@ -428,6 +430,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract VariableDecl.Builder setType(TypeDecl typeDecl);

public abstract VariableDecl.Builder setDescription(String name);

@Override
public ImmutableList<RequiredField> requiredFields() {
return ImmutableList.of(
Expand DownExpand Up@@ -459,6 +463,8 @@ public abstract static class FunctionDecl {

public abstract String name();

public abstract Optional<String> description();

public abstract ImmutableSet<OverloadDecl> overloads();

/** Builder for {@link FunctionDecl}. */
Expand All@@ -471,6 +477,8 @@ public abstract static class Builder implements RequiredFieldsChecker {

public abstract FunctionDecl.Builder setName(String name);

public abstract FunctionDecl.Builder setDescription(String description);

public abstract FunctionDecl.Builder setOverloads(ImmutableSet<OverloadDecl> overloads);

@Override
Expand DownExpand Up@@ -519,6 +527,9 @@ public abstract static class OverloadDecl {
/** List of function overload type values. */
public abstract ImmutableList<TypeDecl> arguments();

/** Examples for the overload. */
public abstract ImmutableList<String> examples();

/** Return type of the overload. Required. */
public abstract TypeDecl returnType();

Expand All@@ -537,8 +548,21 @@ public abstract static class Builder implements RequiredFieldsChecker {
// This should stay package-private to encourage add/set methods to be used instead.
abstract ImmutableList.Builder<TypeDecl> argumentsBuilder();

abstract ImmutableList.Builder<String> examplesBuilder();

public abstract OverloadDecl.Builder setArguments(ImmutableList<TypeDecl> args);

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(Iterable<String> examples) {
this.examplesBuilder().addAll(checkNotNull(examples));
return this;
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addExamples(String... examples) {
return addExamples(Arrays.asList(examples));
}

@CanIgnoreReturnValue
public OverloadDecl.Builder addArguments(Iterable<TypeDecl> args) {
this.argumentsBuilder().addAll(checkNotNull(args));
Expand DownExpand Up@@ -667,6 +691,10 @@ public CelType toCelType(CelTypeProvider celTypeProvider) {
CelType keyType = params().get(0).toCelType(celTypeProvider);
CelType valueType = params().get(1).toCelType(celTypeProvider);
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));
default:
if (isTypeParam()) {
return TypeParamType.create(name());
Expand DownExpand Up@@ -838,6 +866,7 @@ enum CanonicalCelExtension {
SETS(
(options, version) -> CelExtensions.sets(options),
(options, version) -> CelExtensions.sets(options)),
REGEX((options, version) -> CelExtensions.regex(), (options, version) -> CelExtensions.regex()),
LISTS((options, version) -> CelExtensions.lists(), (options, version) -> CelExtensions.lists()),
COMPREHENSIONS(
(options, version) -> CelExtensions.comprehensions(),
Expand DownExpand Up@@ -1054,7 +1083,7 @@ public static OverloadSelector.Builder newBuilder() {
}

@FunctionalInterface
private static interface BooleanOptionConsumer {
private interface BooleanOptionConsumer {
void accept(CelOptions.Builder options, boolean value);
}
}
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,6 +353,9 @@ private VariableDecl parseVariable(ParserContext<Node> ctx, Node node) {
case "name":
builder.setName(newString(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode));
break;
case "type":
if (typeDeclBuilder != null) {
ctx.reportError(
Expand DownExpand Up@@ -428,6 +431,9 @@ private FunctionDecl parseFunction(ParserContext<Node> ctx, Node node) {
case "overloads":
builder.setOverloads(parseOverloads(ctx, valueNode));
break;
case "description":
builder.setDescription(newString(ctx, valueNode).trim());
break;
default:
ctx.reportError(keyId, String.format("Unsupported function tag: %s", keyName));
break;
Expand DownExpand Up@@ -479,6 +485,9 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
case "target":
overloadDeclBuilder.setTarget(parseTypeDecl(ctx, valueNode));
break;
case "examples":
overloadDeclBuilder.addExamples(parseOverloadExamples(ctx, valueNode));
break;
default:
ctx.reportError(keyId, String.format("Unsupported overload tag: %s", fieldName));
break;
Expand All@@ -494,6 +503,25 @@ private static ImmutableSet<OverloadDecl> parseOverloads(ParserContext<Node> ctx
return overloadSetBuilder.build();
}

private static ImmutableList<String> parseOverloadExamples(ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
if (!assertYamlType(ctx, listValueId, node, YamlNodeType.LIST)) {
return ImmutableList.of();
}
SequenceNode paramsListNode = (SequenceNode) node;
ImmutableList.Builder<String> builder = ImmutableList.builder();
for (Node elementNode : paramsListNode.getValue()) {
long elementNodeId = ctx.collectMetadata(elementNode);
if (!assertYamlType(ctx, elementNodeId, elementNode, YamlNodeType.STRING)) {
continue;
}

builder.add(((ScalarNode) elementNode).getValue());
}

return builder.build();
}

private static ImmutableList<TypeDecl> parseOverloadArguments(
ParserContext<Node> ctx, Node node) {
long listValueId = ctx.collectMetadata(node);
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -79,10 +79,8 @@ public Node representData(Object data) {
if (!environment.description().isEmpty()) {
configMap.put("description", environment.description());
}
if (!environment.container().name().isEmpty()
|| !environment.container().abbreviations().isEmpty()
|| !environment.container().aliases().isEmpty()) {
configMap.put("container", environment.container());
if (environment.container().isPresent()) {
configMap.put("container", environment.container().get());
}
if (!environment.extensions().isEmpty()) {
configMap.put("extensions", environment.extensions().asList());
Expand Down
Original file line numberDiff line numberDiff line change
Expand Up@@ -333,7 +333,7 @@ public void container() {

CelEnvironmentExporter exporter = CelEnvironmentExporter.newBuilder().build();
CelEnvironment celEnvironment = exporter.export(cel);
CelContainer container = celEnvironment.container();
CelContainer container = celEnvironment.container().get();
assertThat(container.name()).isEqualTo("cntnr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux").inOrder();
assertThat(container.aliases()).containsAtLeast("nm", "user.name", "id", "user.id").inOrder();
Expand DownExpand Up@@ -368,4 +368,3 @@ public void options() {
CelEnvironment.Limit.create("cel.limit.parse_recursion_depth", 10));
}
}

45 changes: 37 additions & 8 deletions bundle/src/test/java/dev/cel/bundle/CelEnvironmentTest.java
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,6 +28,10 @@
import dev.cel.common.CelOptions;
import dev.cel.common.CelValidationException;
import dev.cel.common.CelValidationResult;
import dev.cel.common.types.CelType;
import dev.cel.common.types.CelTypeProvider;
import dev.cel.common.types.SimpleType;
import dev.cel.common.types.TypeType;
import dev.cel.compiler.CelCompiler;
import dev.cel.compiler.CelCompilerFactory;
import dev.cel.parser.CelStandardMacro;
Expand All@@ -44,9 +48,7 @@ public void newBuilder_defaults() {
assertThat(environment.source()).isEmpty();
assertThat(environment.name()).isEmpty();
assertThat(environment.description()).isEmpty();
assertThat(environment.container().name()).isEmpty();
assertThat(environment.container().abbreviations()).isEmpty();
assertThat(environment.container().aliases()).isEmpty();
assertThat(environment.container()).isEmpty();
assertThat(environment.extensions()).isEmpty();
assertThat(environment.variables()).isEmpty();
assertThat(environment.functions()).isEmpty();
Expand All@@ -65,10 +67,10 @@ public void container() {
.build())
.build();

assertThat(environment.container().name()).isEqualTo("cntr");
assertThat(environment.container().abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(environment.container().aliases())
.containsExactly("nm", "user.name", "id", "user.id");
CelContainer container = environment.container().get();
assertThat(container.name()).isEqualTo("cntr");
assertThat(container.abbreviations()).containsExactly("foo.Bar", "baz.Qux");
assertThat(container.aliases()).containsExactly("nm", "user.name", "id", "user.id");
}

@Test
Expand All@@ -81,9 +83,10 @@ public void extend_allExtensions() throws Exception {
ExtensionConfig.latest("math"),
ExtensionConfig.latest("optional"),
ExtensionConfig.latest("protos"),
ExtensionConfig.latest("regex"),
ExtensionConfig.latest("sets"),
ExtensionConfig.latest("strings"),
ExtensionConfig.latest("comprehensions"));
ExtensionConfig.latest("two-var-comprehensions"));
CelEnvironment environment =
CelEnvironment.newBuilder().addExtensions(extensionConfigs).build();

Expand DownExpand Up@@ -435,4 +438,30 @@ public void stdlibSubset_functionOverloadExcluded() throws Exception {
result = extendedCompiler.compile("1 == 1 && 1 != 1 + 1");
assertThat(result.getErrorString()).contains("found no matching overload for '_+_'");
}

@Test
public void typeDecl_toCelType_type() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl =
CelEnvironment.TypeDecl.newBuilder()
.setName("type")
.addParams(CelEnvironment.TypeDecl.create("int"))
.build();

CelType celType = typeDecl.toCelType(typeProvider);

assertThat(celType).isEqualTo(TypeType.create(SimpleType.INT));
}

@Test
public void typeDecl_toCelType_type_wrongParamCount_throws() {
CelTypeProvider typeProvider =
CelCompilerFactory.standardCelCompilerBuilder().build().getTypeProvider();
CelEnvironment.TypeDecl typeDecl = CelEnvironment.TypeDecl.newBuilder().setName("type").build();

IllegalStateException e =
assertThrows(IllegalStateException.class, () -> typeDecl.toCelType(typeProvider));
assertThat(e).hasMessageThat().contains("Expected 1 parameter for type, got 0");
}
}
Loading
Loading