Skip to content

Commit

Permalink
Implement "in" expression
Browse files Browse the repository at this point in the history
Co-authored-by: Ádám Barancsuk <[email protected]>
Co-authored-by: Ryan Hamley <[email protected]>
  • Loading branch information
ryanhamley and brncsk committed Oct 15, 2019
1 parent 61a61a1 commit 75201f6
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 0 deletions.
55 changes: 55 additions & 0 deletions src/style-spec/expression/definitions/in.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// @flow

import {array, ValueType, BooleanType} from '../types';

import type {Expression} from '../expression';
import type ParsingContext from '../parsing_context';
import type EvaluationContext from '../evaluation_context';
import type {Type} from '../types';
import type {Value} from '../values';

class In implements Expression {
type: Type;
needle: Expression;
haystack: Expression;

constructor(needle: Expression, haystack: Expression) {
this.type = BooleanType;
this.needle = needle;
this.haystack = haystack;
}

static parse(args: $ReadOnlyArray<mixed>, context: ParsingContext) {
if (args.length !== 3)
return context.error(`Expected 2 arguments, but found ${args.length - 1} instead.`);

const needle = context.parse(args[1], 1, ValueType);
const haystack = context.parse(args[2], 2, array(ValueType));

if (!needle || !haystack) return null;

return new In(needle, haystack);
}

evaluate(ctx: EvaluationContext) {
const needle = (this.needle.evaluate(ctx): any);
const haystack = ((this.haystack.evaluate(ctx): any): Array<Value>);

return haystack.indexOf(needle) >= 0;
}

eachChild(fn: (Expression) => void) {
fn(this.needle);
fn(this.haystack);
}

possibleOutputs() {
return [true, false];
}

serialize() {
return ["in", this.needle.serialize(), this.haystack.serialize()];
}
}

export default In;
2 changes: 2 additions & 0 deletions src/style-spec/expression/definitions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Literal from './literal';
import Assertion from './assertion';
import Coercion from './coercion';
import At from './at';
import In from './in';
import Match from './match';
import Case from './case';
import Step from './step';
Expand Down Expand Up @@ -61,6 +62,7 @@ const expressions: ExpressionRegistry = {
'collator': CollatorExpression,
'format': FormatExpression,
'image': Image,
'in': In,
'interpolate': Interpolate,
'interpolate-hcl': Interpolate,
'interpolate-lab': Interpolate,
Expand Down
1 change: 1 addition & 0 deletions src/style-spec/feature_filter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ function isExpressionFilter(filter: any) {
return filter.length >= 2 && filter[1] !== '$id' && filter[1] !== '$type';

case 'in':
return filter.length >= 3 && Array.isArray(filter[2]);
case '!in':
case '!has':
case 'none':
Expand Down
9 changes: 9 additions & 0 deletions src/style-spec/reference/v8.json
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,15 @@
}
}
},
"in": {
"doc": "Determines whether an item exists in an array.",
"group": "Lookup",
"sdk-support": {
"basic functionality": {
"js": "1.6.0"
}
}
},
"case": {
"doc": "Selects the first output whose corresponding test condition evaluates to true, or the fallback value otherwise.",
"group": "Decision",
Expand Down
30 changes: 30 additions & 0 deletions test/integration/expression-tests/in/basic/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"expression": [
"boolean",
["in", ["get", "i"], ["array", ["get", "arr"]]]
],
"inputs": [
[{}, {"properties": {"i": null, "arr": [9, 8, 7]}}],
[{}, {"properties": {"i": 1, "arr": [9, 8, 7]}}],
[{}, {"properties": {"i": 9, "arr": [9, 8, 7]}}],
[{}, {"properties": {"i": 1, "arr": null}}]
],
"expected": {
"compiled": {
"result": "success",
"isFeatureConstant": false,
"isZoomConstant": true,
"type": "boolean"
},
"outputs": [
false,
false,
true,
{"error":"Expected value to be of type array, but found null instead."}
],
"serialized": [
"boolean",
["in", ["get", "i"], ["array", ["get", "arr"]]]
]
}
}

0 comments on commit 75201f6

Please sign in to comment.