diff --git a/src/error-handlers/multipleOf.js b/src/error-handlers/multipleOf.js index 22a4418..5589929 100644 --- a/src/error-handlers/multipleOf.js +++ b/src/error-handlers/multipleOf.js @@ -11,6 +11,11 @@ const multipleOfErrorHandler = async (normalizedErrors, instance, localization) /** @type ErrorObject[] */ const errors = []; + /** @type (number | null) */ + let combinedMultipleOf = null; + /** @type string[] */ + const schemaLocations = []; + for (const schemaLocation in normalizedErrors["https://json-schema.org/keyword/multipleOf"]) { if (normalizedErrors["https://json-schema.org/keyword/multipleOf"][schemaLocation]) { continue; @@ -19,14 +24,42 @@ const multipleOfErrorHandler = async (normalizedErrors, instance, localization) const keyword = await getSchema(schemaLocation); const multipleOf = /** @type number */ (Schema.value(keyword)); + combinedMultipleOf = combinedMultipleOf === null ? multipleOf : lcm(combinedMultipleOf, multipleOf); + schemaLocations.push(schemaLocation); + } + + if (combinedMultipleOf !== null) { errors.push({ - message: localization.getMultipleOfErrorMessage(multipleOf), + message: localization.getMultipleOfErrorMessage(combinedMultipleOf), instanceLocation: Instance.uri(instance), - schemaLocations: [schemaLocation] + schemaLocations }); } return errors; }; +/** + * @param {number} a + * @param {number} b + * @returns {number} + */ +const gcd = (a, b) => { + while (b !== 0) { + const temp = b; + b = a % b; + a = temp; + } + return Math.abs(a); +}; + +/** + * @param {number} a + * @param {number} b + * @returns {number} + */ +const lcm = (a, b) => { + return Math.abs(a * b) / gcd(a, b); +}; + export default multipleOfErrorHandler; diff --git a/src/test-suite/tests/multipleOf.json b/src/test-suite/tests/multipleOf.json index 53f0dfe..766f089 100644 --- a/src/test-suite/tests/multipleOf.json +++ b/src/test-suite/tests/multipleOf.json @@ -25,6 +25,25 @@ }, "instance": 6, "errors": [] + }, + { + "description": "multiple multipleOf constraints (LCM of 4, 6, and 8)", + "schema": { + "allOf": [ + { "multipleOf": 4 }, + { "multipleOf": 6 }, + { "multipleOf": 8 } + ] + }, + "instance": 10, + "errors": [ + { + "messageId": "multipleOf-message", + "messageParams": { "multipleOf": "24" }, + "instanceLocation": "#", + "schemaLocations": ["#/allOf/0/multipleOf", "#/allOf/1/multipleOf", "#/allOf/2/multipleOf"] + } + ] } ] }