diff --git a/src/style-spec/error/parsing_error.js b/src/style-spec/error/parsing_error.js index d5c20f58583..cd2cb6bce7f 100644 --- a/src/style-spec/error/parsing_error.js +++ b/src/style-spec/error/parsing_error.js @@ -1,9 +1,13 @@ +// @flow -function ParsingError(error) { - this.error = error; - this.message = error.message; - const match = error.message.match(/line (\d+)/); - this.line = match ? parseInt(match[1], 10) : 0; -} +export default class ParsingError extends Error { + error: Error; + line: number; -export default ParsingError; + constructor(error: Error) { + super(error.message); + this.error = error; + const match = error.message.match(/line (\d+)/); + this.line = match ? parseInt(match[1], 10) : 0; + } +} diff --git a/src/style-spec/error/validation_error.js b/src/style-spec/error/validation_error.js index 0ab246138a7..b57ad89b854 100644 --- a/src/style-spec/error/validation_error.js +++ b/src/style-spec/error/validation_error.js @@ -1,7 +1,11 @@ +// @flow -export default class ValidationError { - constructor(key, value, message, identifier) { - this.message = (key ? `${key}: ` : '') + message; +export default class ValidationError extends Error { + identifier: ?string; + line: ?number; + + constructor(key: string | null, value?: any, message?: string, identifier?: string) { + super([key, message].filter(a => a).join(': ')); if (identifier) this.identifier = identifier; if (value !== null && value !== undefined && value.__line__) { diff --git a/src/style-spec/expression/types/formatted.js b/src/style-spec/expression/types/formatted.js index 224594f5360..726242ea30f 100644 --- a/src/style-spec/expression/types/formatted.js +++ b/src/style-spec/expression/types/formatted.js @@ -60,14 +60,14 @@ export default class Formatted { } serialize(): Array { - const serialized = ["format"]; + const serialized: Array = ["format"]; for (const section of this.sections) { if (section.image) { serialized.push(["image", section.image.name]); continue; } serialized.push(section.text); - const options = {}; + const options: { [key: string]: mixed } = {}; if (section.fontStack) { options["text-font"] = ["literal", section.fontStack.split(',')]; } @@ -75,7 +75,7 @@ export default class Formatted { options["font-scale"] = section.scale; } if (section.textColor) { - options["text-color"] = ["rgba"].concat(section.textColor.toArray()); + options["text-color"] = (["rgba"]: Array).concat(section.textColor.toArray()); } serialized.push(options); } diff --git a/src/style-spec/expression/types/resolved_image.js b/src/style-spec/expression/types/resolved_image.js index 2919b1e8a5b..b5f31ed55bb 100644 --- a/src/style-spec/expression/types/resolved_image.js +++ b/src/style-spec/expression/types/resolved_image.js @@ -22,7 +22,7 @@ export default class ResolvedImage { return new ResolvedImage({name, available: false}); } - serialize(): Array { + serialize(): Array { return ["image", this.name]; } } diff --git a/src/style-spec/expression/values.js b/src/style-spec/expression/values.js index 6b5539f89fa..6c5e5407dc9 100644 --- a/src/style-spec/expression/values.js +++ b/src/style-spec/expression/values.js @@ -10,7 +10,7 @@ import {NullType, NumberType, StringType, BooleanType, ColorType, ObjectType, Va import type {Type} from './types'; -export function validateRGBA(r: mixed, g: mixed, b: mixed, a?: mixed): ?string { +export function validateRGBA(r: mixed, g: mixed, b: mixed, a?: mixed): string | null { if (!( typeof r === 'number' && r >= 0 && r <= 255 && typeof g === 'number' && g >= 0 && g <= 255 && @@ -86,7 +86,7 @@ export function typeOf(value: Value): Type { return ResolvedImageType; } else if (Array.isArray(value)) { const length = value.length; - let itemType: ?Type; + let itemType: Type | typeof undefined; for (const item of value) { const t = typeOf(item); diff --git a/src/style-spec/util/color.js b/src/style-spec/util/color.js index 57e56165dd3..a8e59b74f05 100644 --- a/src/style-spec/util/color.js +++ b/src/style-spec/util/color.js @@ -35,7 +35,7 @@ class Color { * Parses valid CSS color strings and returns a `Color` instance. * @returns A `Color` instance, or `undefined` if the input is not a valid color string. */ - static parse(input: ?string): Color | void { + static parse(input?: string | Color | null): Color | void { if (!input) { return undefined; } diff --git a/src/style-spec/util/color_spaces.js b/src/style-spec/util/color_spaces.js index 954de5c93a5..21ee75b0c69 100644 --- a/src/style-spec/util/color_spaces.js +++ b/src/style-spec/util/color_spaces.js @@ -30,19 +30,19 @@ const Xn = 0.950470, // D65 standard referent rad2deg = 180 / Math.PI; // Utilities -function xyz2lab(t) { +function xyz2lab(t: number) { return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0; } -function lab2xyz(t) { +function lab2xyz(t: number) { return t > t1 ? t * t * t : t2 * (t - t0); } -function xyz2rgb(x) { +function xyz2rgb(x: number) { return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055); } -function rgb2xyz(x) { +function rgb2xyz(x: number) { x /= 255; return x <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4); } diff --git a/src/style-spec/util/extend.js b/src/style-spec/util/extend.js index 3f041cc63b0..076b6f278a4 100644 --- a/src/style-spec/util/extend.js +++ b/src/style-spec/util/extend.js @@ -1,5 +1,6 @@ +// @flow -export default function (output, ...inputs) { +export default function (output: any, ...inputs: Array) { for (const input of inputs) { for (const k in input) { output[k] = input[k]; diff --git a/src/style-spec/util/get_type.js b/src/style-spec/util/get_type.js index c31925f35a3..18b03eb625e 100644 --- a/src/style-spec/util/get_type.js +++ b/src/style-spec/util/get_type.js @@ -1,5 +1,6 @@ +// @flow -export default function getType(val) { +export default function getType(val: mixed): string { if (val instanceof Number) { return 'number'; } else if (val instanceof String) { diff --git a/src/style-spec/util/unbundle_jsonlint.js b/src/style-spec/util/unbundle_jsonlint.js index 0fd78107892..72eb2d92645 100644 --- a/src/style-spec/util/unbundle_jsonlint.js +++ b/src/style-spec/util/unbundle_jsonlint.js @@ -1,21 +1,19 @@ -function isPrimitive(value) { - return value instanceof Number || value instanceof String || value instanceof Boolean; -} +// @flow // Turn jsonlint-lines-primitives objects into primitive objects -export function unbundle(value) { - if (isPrimitive(value)) { +export function unbundle(value: mixed) { + if (value instanceof Number || value instanceof String || value instanceof Boolean) { return value.valueOf(); } else { return value; } } -export function deepUnbundle(value) { +export function deepUnbundle(value: mixed): mixed { if (Array.isArray(value)) { return value.map(deepUnbundle); - } else if (value instanceof Object && !isPrimitive(value)) { - const unbundledValue = {}; + } else if (value instanceof Object && !(value instanceof Number || value instanceof String || value instanceof Boolean)) { + const unbundledValue: { [key: string]: mixed } = {}; for (const key in value) { unbundledValue[key] = deepUnbundle(value[key]); } @@ -24,4 +22,3 @@ export function deepUnbundle(value) { return unbundle(value); } - diff --git a/test/unit/style-spec/validate.test.js b/test/unit/style-spec/validate.test.js index 64fd3080d92..2e37799d656 100644 --- a/test/unit/style-spec/validate.test.js +++ b/test/unit/style-spec/validate.test.js @@ -6,6 +6,15 @@ import validate from '../../../src/style-spec/validate_style'; const UPDATE = !!process.env.UPDATE; +function sanitizeError(error) { + const sanitized = {}; + sanitized.message = error.message; + for (const key in error) { + sanitized[key] = error[key]; + } + return sanitized; +} + glob.sync(`${__dirname}/fixture/*.input.json`).forEach((file) => { test(path.basename(file), (t) => { const outputfile = file.replace('.input', '.output'); @@ -13,7 +22,7 @@ glob.sync(`${__dirname}/fixture/*.input.json`).forEach((file) => { const result = validate(style); if (UPDATE) fs.writeFileSync(outputfile, JSON.stringify(result, null, 2)); const expect = JSON.parse(fs.readFileSync(outputfile)); - t.deepEqual(result, expect); + t.deepEqual(result.map(sanitizeError), expect); t.end(); }); }); diff --git a/test/unit/style-spec/validate_mapbox_api_supported.test.js b/test/unit/style-spec/validate_mapbox_api_supported.test.js index 810eb111cb6..37bd5e808ed 100644 --- a/test/unit/style-spec/validate_mapbox_api_supported.test.js +++ b/test/unit/style-spec/validate_mapbox_api_supported.test.js @@ -6,6 +6,15 @@ import validateMapboxApiSupported from '../../../src/style-spec/validate_mapbox_ const UPDATE = !!process.env.UPDATE; +function sanitizeError(error) { + const sanitized = {}; + sanitized.message = error.message; + for (const key in error) { + sanitized[key] = error[key]; + } + return sanitized; +} + glob.sync(`${__dirname}/fixture/*.input.json`).forEach((file) => { test(path.basename(file), (t) => { const outputfile = file.replace('.input', '.output-api-supported'); @@ -13,7 +22,7 @@ glob.sync(`${__dirname}/fixture/*.input.json`).forEach((file) => { const result = validateMapboxApiSupported(style); if (UPDATE) fs.writeFileSync(outputfile, JSON.stringify(result, null, 2)); const expect = JSON.parse(fs.readFileSync(outputfile)); - t.deepEqual(result, expect); + t.deepEqual(result.map(sanitizeError), expect); t.end(); }); });