Skip to content

Commit 3ff3a1e

Browse files
Global state refs (#1120)
* collect global-state refs * update prepare script (to be removed) * unit test * unit * revert prepare script change
1 parent 89c88e2 commit 3ff3a1e

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

src/expression/expression.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,18 @@ describe('createPropertyExpression', () => {
3939
expect(value[0].message).toBe('"interpolate" expressions cannot be used with this property');
4040
});
4141

42+
test('sets globalStateRefs', () => {
43+
const {value} = createPropertyExpression(['case', ['>', ['global-state','stateKey'], 0], 100, ['global-state', 'anotherStateKey']], {
44+
type: 'number',
45+
'property-type': 'data-driven',
46+
expression: {
47+
'interpolated': false,
48+
'parameters': ['zoom', 'feature']
49+
}
50+
} as any as StylePropertySpecification) as {value: StylePropertyExpression};
51+
52+
expect(value.globalStateRefs).toEqual(new Set(['stateKey', 'anotherStateKey']));
53+
});
4254
});
4355

4456
describe('evaluate expression', () => {

src/expression/index.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {NumberArray} from './types/number_array';
3838
import {ColorArray} from './types/color_array';
3939
import {VariableAnchorOffsetCollection} from './types/variable_anchor_offset_collection';
4040
import {ProjectionDefinition} from './types/projection_definition';
41+
import {GlobalState} from './definitions/global_state';
4142

4243
export type Feature = {
4344
readonly type: 0 | 1 | 2 | 3 | 'Unknown' | 'Point' | 'MultiPoint' | 'LineString' | 'MultiLineString' | 'Polygon' | 'MultiPolygon';
@@ -165,12 +166,14 @@ export function createExpression(expression: unknown, propertySpec?: StyleProper
165166
export class ZoomConstantExpression<Kind extends EvaluationKind> {
166167
kind: Kind;
167168
isStateDependent: boolean;
169+
globalStateRefs: Set<string>;
168170
_styleExpression: StyleExpression;
169171

170172
constructor(kind: Kind, expression: StyleExpression) {
171173
this.kind = kind;
172174
this._styleExpression = expression;
173175
this.isStateDependent = kind !== ('constant' as EvaluationKind) && !isStateConstant(expression.expression);
176+
this.globalStateRefs = findGlobalStateRefs(expression.expression);
174177
}
175178

176179
evaluateWithoutErrorHandling(
@@ -200,7 +203,7 @@ export class ZoomDependentExpression<Kind extends EvaluationKind> {
200203
kind: Kind;
201204
zoomStops: Array<number>;
202205
isStateDependent: boolean;
203-
206+
globalStateRefs: Set<string>;
204207
_styleExpression: StyleExpression;
205208
interpolationType: InterpolationType;
206209

@@ -209,6 +212,7 @@ export class ZoomDependentExpression<Kind extends EvaluationKind> {
209212
this.zoomStops = zoomStops;
210213
this._styleExpression = expression;
211214
this.isStateDependent = kind !== ('camera' as EvaluationKind) && !isStateConstant(expression.expression);
215+
this.globalStateRefs = findGlobalStateRefs(expression.expression);
212216
this.interpolationType = interpolationType;
213217
}
214218

@@ -249,6 +253,7 @@ export function isZoomExpression(expression: any): expression is ZoomConstantExp
249253

250254
export type ConstantExpression = {
251255
kind: 'constant';
256+
globalStateRefs: Set<string>;
252257
readonly evaluate: (
253258
globals: GlobalProperties,
254259
feature?: Feature,
@@ -261,6 +266,7 @@ export type ConstantExpression = {
261266
export type SourceExpression = {
262267
kind: 'source';
263268
isStateDependent: boolean;
269+
globalStateRefs: Set<string>;
264270
readonly evaluate: (
265271
globals: GlobalProperties,
266272
feature?: Feature,
@@ -273,6 +279,7 @@ export type SourceExpression = {
273279

274280
export type CameraExpression = {
275281
kind: 'camera';
282+
globalStateRefs: Set<string>;
276283
readonly evaluate: (
277284
globals: GlobalProperties,
278285
feature?: Feature,
@@ -288,6 +295,7 @@ export type CameraExpression = {
288295
export type CompositeExpression = {
289296
kind: 'composite';
290297
isStateDependent: boolean;
298+
globalStateRefs: Set<string>;
291299
readonly evaluate: (
292300
globals: GlobalProperties,
293301
feature?: Feature,
@@ -406,6 +414,7 @@ export function normalizePropertyExpression<T>(
406414
constant = ProjectionDefinition.parse(value);
407415
}
408416
return {
417+
globalStateRefs: new Set<string>(),
409418
kind: 'constant',
410419
evaluate: () => constant
411420
};
@@ -453,6 +462,17 @@ function findZoomCurve(expression: Expression): Step | Interpolate | ExpressionP
453462
return result;
454463
}
455464

465+
export function findGlobalStateRefs(expression: Expression, results = new Set<string>()): Set<string> {
466+
if (expression instanceof GlobalState) {
467+
results.add(expression.key);
468+
}
469+
470+
expression.eachChild(childExpression => {
471+
findGlobalStateRefs(childExpression, results);
472+
});
473+
return results;
474+
}
475+
456476
function getExpectedType(spec: StylePropertySpecification): Type {
457477
const types = {
458478
color: ColorType,

src/feature_filter/feature_filter.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ describe('filter', () => {
175175

176176
});
177177

178+
describe('getGlobalStateRefs', () => {
179+
test('returns global-state keys', () => {
180+
const filter = featureFilter(['==', ['global-state', 'x'], ['zoom']]);
181+
expect(filter.getGlobalStateRefs()).toEqual(new Set(['x']));
182+
});
183+
});
184+
178185
describe('legacy filter detection', () => {
179186
test('definitely legacy filters', () => {
180187
// Expressions with more than two arguments.

src/feature_filter/index.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {createExpression} from '../expression';
1+
import {createExpression, findGlobalStateRefs} from '../expression';
22
import type {GlobalProperties, Feature} from '../expression';
33
import {ICanonicalTileID} from '../tiles_and_coordinates';
44
import {StylePropertySpecification} from '..';
@@ -13,6 +13,7 @@ type FilterExpression = (
1313
export type FeatureFilter = {
1414
filter: FilterExpression;
1515
needGeometry: boolean;
16+
getGlobalStateRefs: () => Set<string>;
1617
};
1718

1819
export function isExpressionFilter(filter: any): filter is ExpressionFilterSpecification {
@@ -79,7 +80,7 @@ const filterSpec = {
7980
*/
8081
export function featureFilter(filter: any): FeatureFilter {
8182
if (filter === null || filter === undefined) {
82-
return {filter: () => true, needGeometry: false};
83+
return {filter: () => true, needGeometry: false, getGlobalStateRefs: () => new Set()};
8384
}
8485

8586
if (!isExpressionFilter(filter)) {
@@ -91,8 +92,11 @@ export function featureFilter(filter: any): FeatureFilter {
9192
throw new Error(compiled.value.map(err => `${err.key}: ${err.message}`).join(', '));
9293
} else {
9394
const needGeometry = geometryNeeded(filter);
94-
return {filter: (globalProperties: GlobalProperties, feature: Feature, canonical?: ICanonicalTileID) => compiled.value.evaluate(globalProperties, feature, {}, canonical),
95-
needGeometry};
95+
return {
96+
filter: (globalProperties: GlobalProperties, feature: Feature, canonical?: ICanonicalTileID) => compiled.value.evaluate(globalProperties, feature, {}, canonical),
97+
needGeometry,
98+
getGlobalStateRefs: () => findGlobalStateRefs(compiled.value.expression)
99+
};
96100
}
97101
}
98102

0 commit comments

Comments
 (0)