From 85fce0183a9d2423c17c1289b1bc6f485db45982 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Thu, 13 Sep 2018 16:47:02 -0700 Subject: [PATCH] Fix implicit conversions for "formatted" type --- .../expression/definitions/coercion.js | 10 ---- src/style-spec/expression/index.js | 9 ++-- src/style-spec/expression/parsing_context.js | 8 ++- .../format/implicit/test.json | 53 +++++++++++++++++++ 4 files changed, 64 insertions(+), 16 deletions(-) create mode 100644 test/integration/expression-tests/format/implicit/test.json diff --git a/src/style-spec/expression/definitions/coercion.js b/src/style-spec/expression/definitions/coercion.js index 58f062551b5..17ba74b043f 100644 --- a/src/style-spec/expression/definitions/coercion.js +++ b/src/style-spec/expression/definitions/coercion.js @@ -11,7 +11,6 @@ import type ParsingContext from '../parsing_context'; import type EvaluationContext from '../evaluation_context'; import type { Value } from '../values'; import type { Type } from '../types'; -import { Formatted, FormattedSection } from './formatted'; const types = { 'to-boolean': BooleanType, @@ -84,15 +83,6 @@ class Coercion implements Expression { } } throw new RuntimeError(error || `Could not parse color from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`); - } else if (this.type.kind === 'formatted') { - let input; - for (const arg of this.args) { - input = arg.evaluate(ctx); - if (typeof input === 'string') { - return new Formatted([new FormattedSection(input, null, null)]); - } - } - throw new RuntimeError(`Could not parse formatted text from value '${typeof input === 'string' ? input : JSON.stringify(input)}'`); } else if (this.type.kind === 'number') { let value = null; for (const arg of this.args) { diff --git a/src/style-spec/expression/index.js b/src/style-spec/expression/index.js index 69781b3d5f7..5b9f07c3d86 100644 --- a/src/style-spec/expression/index.js +++ b/src/style-spec/expression/index.js @@ -351,22 +351,23 @@ function findZoomCurve(expression: Expression): Step | Interpolate | ParsingErro return result; } -import { ColorType, StringType, NumberType, BooleanType, ValueType, array } from './types'; +import { ColorType, StringType, NumberType, BooleanType, ValueType, FormattedType, array } from './types'; -function getExpectedType(spec: StylePropertySpecification): Type | null { +function getExpectedType(spec: StylePropertySpecification): Type { const types = { color: ColorType, string: StringType, number: NumberType, enum: StringType, - boolean: BooleanType + boolean: BooleanType, + formatted: FormattedType }; if (spec.type === 'array') { return array(types[spec.value] || ValueType, spec.length); } - return types[spec.type] || null; + return types[spec.type]; } function getDefaultValue(spec: StylePropertySpecification): Value { diff --git a/src/style-spec/expression/parsing_context.js b/src/style-spec/expression/parsing_context.js index d35777c77bd..646c2a39da2 100644 --- a/src/style-spec/expression/parsing_context.js +++ b/src/style-spec/expression/parsing_context.js @@ -1,7 +1,7 @@ // @flow +import assert from 'assert'; import Scope from './scope'; - import { checkSubtype } from './types'; import ParsingError from './parsing_error'; import Literal from './definitions/literal'; @@ -16,6 +16,7 @@ import Var from './definitions/var'; import type {Expression, ExpressionRegistry} from './expression'; import type {Type} from './types'; +import {FormatExpression} from './definitions/formatted'; /** * State associated parsing at a given point in an expression tree. @@ -114,8 +115,11 @@ class ParsingContext { // if ((expected.kind === 'string' || expected.kind === 'number' || expected.kind === 'boolean' || expected.kind === 'object' || expected.kind === 'array') && actual.kind === 'value') { parsed = annotate(parsed, expected, options.typeAnnotation || 'assert'); - } else if ((expected.kind === 'color' || expected.kind === 'formatted') && (actual.kind === 'value' || actual.kind === 'string')) { + } else if (expected.kind === 'color' && (actual.kind === 'value' || actual.kind === 'string')) { parsed = annotate(parsed, expected, options.typeAnnotation || 'coerce'); + } else if (expected.kind === 'formatted' && actual.kind !== 'formatted') { + assert(!options.typeAnnotation); + parsed = new FormatExpression([{text: parsed, scale: null, font: null}]); } else if (this.checkSubtype(expected, actual)) { return null; } diff --git a/test/integration/expression-tests/format/implicit/test.json b/test/integration/expression-tests/format/implicit/test.json new file mode 100644 index 00000000000..19485f2d658 --- /dev/null +++ b/test/integration/expression-tests/format/implicit/test.json @@ -0,0 +1,53 @@ +{ + "expression": ["get", "p"], + "propertySpec": { + "type": "formatted" + }, + "inputs": [ + [{}, {"properties": {}}], + [{}, {"properties": {"p": 0}}], + [{}, {"properties": {"p": "a"}}] + ], + "expected": { + "compiled": { + "result": "success", + "isFeatureConstant": false, + "isZoomConstant": true, + "type": "formatted" + }, + "outputs": [ + { + "sections": [ + { + "text": "", + "scale": null, + "fontStack": null + } + ] + }, + { + "sections": [ + { + "text": "0", + "scale": null, + "fontStack": null + } + ] + }, + { + "sections": [ + { + "text": "a", + "scale": null, + "fontStack": null + } + ] + } + ], + "serialized": [ + "format", + ["get", "p"], + {} + ] + } +}