| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212 | /*--------------------------------------------------------------------------------------------- *  Copyright (c) Microsoft Corporation. All rights reserved. *  Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/var __extends = (this && this.__extends) || (function () {    var extendStatics = function (d, b) {        extendStatics = Object.setPrototypeOf ||            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||            function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };        return extendStatics(d, b);    };    return function (d, b) {        if (typeof b !== "function" && b !== null)            throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");        extendStatics(d, b);        function __() { this.constructor = d; }        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());    };})();import * as Json from 'jsonc-parser';import { isNumber, equals, isBoolean, isString, isDefined } from '../utils/objects';import { extendedRegExp } from '../utils/strings';import { ErrorCode, Diagnostic, DiagnosticSeverity, Range } from '../jsonLanguageTypes';import * as nls from 'vscode-nls';var localize = nls.loadMessageBundle();var formats = {    'color-hex': { errorMessage: localize('colorHexFormatWarning', 'Invalid color format. Use #RGB, #RGBA, #RRGGBB or #RRGGBBAA.'), pattern: /^#([0-9A-Fa-f]{3,4}|([0-9A-Fa-f]{2}){3,4})$/ },    'date-time': { errorMessage: localize('dateTimeFormatWarning', 'String is not a RFC3339 date-time.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])T([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },    'date': { errorMessage: localize('dateFormatWarning', 'String is not a RFC3339 date.'), pattern: /^(\d{4})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/i },    'time': { errorMessage: localize('timeFormatWarning', 'String is not a RFC3339 time.'), pattern: /^([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)([01][0-9]|2[0-3]):([0-5][0-9]))$/i },    'email': { errorMessage: localize('emailFormatWarning', 'String is not an e-mail address.'), pattern: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/ }};var ASTNodeImpl = /** @class */ (function () {    function ASTNodeImpl(parent, offset, length) {        if (length === void 0) { length = 0; }        this.offset = offset;        this.length = length;        this.parent = parent;    }    Object.defineProperty(ASTNodeImpl.prototype, "children", {        get: function () {            return [];        },        enumerable: false,        configurable: true    });    ASTNodeImpl.prototype.toString = function () {        return 'type: ' + this.type + ' (' + this.offset + '/' + this.length + ')' + (this.parent ? ' parent: {' + this.parent.toString() + '}' : '');    };    return ASTNodeImpl;}());export { ASTNodeImpl };var NullASTNodeImpl = /** @class */ (function (_super) {    __extends(NullASTNodeImpl, _super);    function NullASTNodeImpl(parent, offset) {        var _this = _super.call(this, parent, offset) || this;        _this.type = 'null';        _this.value = null;        return _this;    }    return NullASTNodeImpl;}(ASTNodeImpl));export { NullASTNodeImpl };var BooleanASTNodeImpl = /** @class */ (function (_super) {    __extends(BooleanASTNodeImpl, _super);    function BooleanASTNodeImpl(parent, boolValue, offset) {        var _this = _super.call(this, parent, offset) || this;        _this.type = 'boolean';        _this.value = boolValue;        return _this;    }    return BooleanASTNodeImpl;}(ASTNodeImpl));export { BooleanASTNodeImpl };var ArrayASTNodeImpl = /** @class */ (function (_super) {    __extends(ArrayASTNodeImpl, _super);    function ArrayASTNodeImpl(parent, offset) {        var _this = _super.call(this, parent, offset) || this;        _this.type = 'array';        _this.items = [];        return _this;    }    Object.defineProperty(ArrayASTNodeImpl.prototype, "children", {        get: function () {            return this.items;        },        enumerable: false,        configurable: true    });    return ArrayASTNodeImpl;}(ASTNodeImpl));export { ArrayASTNodeImpl };var NumberASTNodeImpl = /** @class */ (function (_super) {    __extends(NumberASTNodeImpl, _super);    function NumberASTNodeImpl(parent, offset) {        var _this = _super.call(this, parent, offset) || this;        _this.type = 'number';        _this.isInteger = true;        _this.value = Number.NaN;        return _this;    }    return NumberASTNodeImpl;}(ASTNodeImpl));export { NumberASTNodeImpl };var StringASTNodeImpl = /** @class */ (function (_super) {    __extends(StringASTNodeImpl, _super);    function StringASTNodeImpl(parent, offset, length) {        var _this = _super.call(this, parent, offset, length) || this;        _this.type = 'string';        _this.value = '';        return _this;    }    return StringASTNodeImpl;}(ASTNodeImpl));export { StringASTNodeImpl };var PropertyASTNodeImpl = /** @class */ (function (_super) {    __extends(PropertyASTNodeImpl, _super);    function PropertyASTNodeImpl(parent, offset, keyNode) {        var _this = _super.call(this, parent, offset) || this;        _this.type = 'property';        _this.colonOffset = -1;        _this.keyNode = keyNode;        return _this;    }    Object.defineProperty(PropertyASTNodeImpl.prototype, "children", {        get: function () {            return this.valueNode ? [this.keyNode, this.valueNode] : [this.keyNode];        },        enumerable: false,        configurable: true    });    return PropertyASTNodeImpl;}(ASTNodeImpl));export { PropertyASTNodeImpl };var ObjectASTNodeImpl = /** @class */ (function (_super) {    __extends(ObjectASTNodeImpl, _super);    function ObjectASTNodeImpl(parent, offset) {        var _this = _super.call(this, parent, offset) || this;        _this.type = 'object';        _this.properties = [];        return _this;    }    Object.defineProperty(ObjectASTNodeImpl.prototype, "children", {        get: function () {            return this.properties;        },        enumerable: false,        configurable: true    });    return ObjectASTNodeImpl;}(ASTNodeImpl));export { ObjectASTNodeImpl };export function asSchema(schema) {    if (isBoolean(schema)) {        return schema ? {} : { "not": {} };    }    return schema;}export var EnumMatch;(function (EnumMatch) {    EnumMatch[EnumMatch["Key"] = 0] = "Key";    EnumMatch[EnumMatch["Enum"] = 1] = "Enum";})(EnumMatch || (EnumMatch = {}));var SchemaCollector = /** @class */ (function () {    function SchemaCollector(focusOffset, exclude) {        if (focusOffset === void 0) { focusOffset = -1; }        this.focusOffset = focusOffset;        this.exclude = exclude;        this.schemas = [];    }    SchemaCollector.prototype.add = function (schema) {        this.schemas.push(schema);    };    SchemaCollector.prototype.merge = function (other) {        Array.prototype.push.apply(this.schemas, other.schemas);    };    SchemaCollector.prototype.include = function (node) {        return (this.focusOffset === -1 || contains(node, this.focusOffset)) && (node !== this.exclude);    };    SchemaCollector.prototype.newSub = function () {        return new SchemaCollector(-1, this.exclude);    };    return SchemaCollector;}());var NoOpSchemaCollector = /** @class */ (function () {    function NoOpSchemaCollector() {    }    Object.defineProperty(NoOpSchemaCollector.prototype, "schemas", {        get: function () { return []; },        enumerable: false,        configurable: true    });    NoOpSchemaCollector.prototype.add = function (schema) { };    NoOpSchemaCollector.prototype.merge = function (other) { };    NoOpSchemaCollector.prototype.include = function (node) { return true; };    NoOpSchemaCollector.prototype.newSub = function () { return this; };    NoOpSchemaCollector.instance = new NoOpSchemaCollector();    return NoOpSchemaCollector;}());var ValidationResult = /** @class */ (function () {    function ValidationResult() {        this.problems = [];        this.propertiesMatches = 0;        this.propertiesValueMatches = 0;        this.primaryValueMatches = 0;        this.enumValueMatch = false;        this.enumValues = undefined;    }    ValidationResult.prototype.hasProblems = function () {        return !!this.problems.length;    };    ValidationResult.prototype.mergeAll = function (validationResults) {        for (var _i = 0, validationResults_1 = validationResults; _i < validationResults_1.length; _i++) {            var validationResult = validationResults_1[_i];            this.merge(validationResult);        }    };    ValidationResult.prototype.merge = function (validationResult) {        this.problems = this.problems.concat(validationResult.problems);    };    ValidationResult.prototype.mergeEnumValues = function (validationResult) {        if (!this.enumValueMatch && !validationResult.enumValueMatch && this.enumValues && validationResult.enumValues) {            this.enumValues = this.enumValues.concat(validationResult.enumValues);            for (var _i = 0, _a = this.problems; _i < _a.length; _i++) {                var error = _a[_i];                if (error.code === ErrorCode.EnumValueMismatch) {                    error.message = localize('enumWarning', 'Value is not accepted. Valid values: {0}.', this.enumValues.map(function (v) { return JSON.stringify(v); }).join(', '));                }            }        }    };    ValidationResult.prototype.mergePropertyMatch = function (propertyValidationResult) {        this.merge(propertyValidationResult);        this.propertiesMatches++;        if (propertyValidationResult.enumValueMatch || !propertyValidationResult.hasProblems() && propertyValidationResult.propertiesMatches) {            this.propertiesValueMatches++;        }        if (propertyValidationResult.enumValueMatch && propertyValidationResult.enumValues && propertyValidationResult.enumValues.length === 1) {            this.primaryValueMatches++;        }    };    ValidationResult.prototype.compare = function (other) {        var hasProblems = this.hasProblems();        if (hasProblems !== other.hasProblems()) {            return hasProblems ? -1 : 1;        }        if (this.enumValueMatch !== other.enumValueMatch) {            return other.enumValueMatch ? -1 : 1;        }        if (this.primaryValueMatches !== other.primaryValueMatches) {            return this.primaryValueMatches - other.primaryValueMatches;        }        if (this.propertiesValueMatches !== other.propertiesValueMatches) {            return this.propertiesValueMatches - other.propertiesValueMatches;        }        return this.propertiesMatches - other.propertiesMatches;    };    return ValidationResult;}());export { ValidationResult };export function newJSONDocument(root, diagnostics) {    if (diagnostics === void 0) { diagnostics = []; }    return new JSONDocument(root, diagnostics, []);}export function getNodeValue(node) {    return Json.getNodeValue(node);}export function getNodePath(node) {    return Json.getNodePath(node);}export function contains(node, offset, includeRightBound) {    if (includeRightBound === void 0) { includeRightBound = false; }    return offset >= node.offset && offset < (node.offset + node.length) || includeRightBound && offset === (node.offset + node.length);}var JSONDocument = /** @class */ (function () {    function JSONDocument(root, syntaxErrors, comments) {        if (syntaxErrors === void 0) { syntaxErrors = []; }        if (comments === void 0) { comments = []; }        this.root = root;        this.syntaxErrors = syntaxErrors;        this.comments = comments;    }    JSONDocument.prototype.getNodeFromOffset = function (offset, includeRightBound) {        if (includeRightBound === void 0) { includeRightBound = false; }        if (this.root) {            return Json.findNodeAtOffset(this.root, offset, includeRightBound);        }        return undefined;    };    JSONDocument.prototype.visit = function (visitor) {        if (this.root) {            var doVisit_1 = function (node) {                var ctn = visitor(node);                var children = node.children;                if (Array.isArray(children)) {                    for (var i = 0; i < children.length && ctn; i++) {                        ctn = doVisit_1(children[i]);                    }                }                return ctn;            };            doVisit_1(this.root);        }    };    JSONDocument.prototype.validate = function (textDocument, schema, severity) {        if (severity === void 0) { severity = DiagnosticSeverity.Warning; }        if (this.root && schema) {            var validationResult = new ValidationResult();            validate(this.root, schema, validationResult, NoOpSchemaCollector.instance);            return validationResult.problems.map(function (p) {                var _a;                var range = Range.create(textDocument.positionAt(p.location.offset), textDocument.positionAt(p.location.offset + p.location.length));                return Diagnostic.create(range, p.message, (_a = p.severity) !== null && _a !== void 0 ? _a : severity, p.code);            });        }        return undefined;    };    JSONDocument.prototype.getMatchingSchemas = function (schema, focusOffset, exclude) {        if (focusOffset === void 0) { focusOffset = -1; }        var matchingSchemas = new SchemaCollector(focusOffset, exclude);        if (this.root && schema) {            validate(this.root, schema, new ValidationResult(), matchingSchemas);        }        return matchingSchemas.schemas;    };    return JSONDocument;}());export { JSONDocument };function validate(n, schema, validationResult, matchingSchemas) {    if (!n || !matchingSchemas.include(n)) {        return;    }    var node = n;    switch (node.type) {        case 'object':            _validateObjectNode(node, schema, validationResult, matchingSchemas);            break;        case 'array':            _validateArrayNode(node, schema, validationResult, matchingSchemas);            break;        case 'string':            _validateStringNode(node, schema, validationResult, matchingSchemas);            break;        case 'number':            _validateNumberNode(node, schema, validationResult, matchingSchemas);            break;        case 'property':            return validate(node.valueNode, schema, validationResult, matchingSchemas);    }    _validateNode();    matchingSchemas.add({ node: node, schema: schema });    function _validateNode() {        function matchesType(type) {            return node.type === type || (type === 'integer' && node.type === 'number' && node.isInteger);        }        if (Array.isArray(schema.type)) {            if (!schema.type.some(matchesType)) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: schema.errorMessage || localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}.', schema.type.join(', '))                });            }        }        else if (schema.type) {            if (!matchesType(schema.type)) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: schema.errorMessage || localize('typeMismatchWarning', 'Incorrect type. Expected "{0}".', schema.type)                });            }        }        if (Array.isArray(schema.allOf)) {            for (var _i = 0, _a = schema.allOf; _i < _a.length; _i++) {                var subSchemaRef = _a[_i];                validate(node, asSchema(subSchemaRef), validationResult, matchingSchemas);            }        }        var notSchema = asSchema(schema.not);        if (notSchema) {            var subValidationResult = new ValidationResult();            var subMatchingSchemas = matchingSchemas.newSub();            validate(node, notSchema, subValidationResult, subMatchingSchemas);            if (!subValidationResult.hasProblems()) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: localize('notSchemaWarning', "Matches a schema that is not allowed.")                });            }            for (var _b = 0, _c = subMatchingSchemas.schemas; _b < _c.length; _b++) {                var ms = _c[_b];                ms.inverted = !ms.inverted;                matchingSchemas.add(ms);            }        }        var testAlternatives = function (alternatives, maxOneMatch) {            var matches = [];            // remember the best match that is used for error messages            var bestMatch = undefined;            for (var _i = 0, alternatives_1 = alternatives; _i < alternatives_1.length; _i++) {                var subSchemaRef = alternatives_1[_i];                var subSchema = asSchema(subSchemaRef);                var subValidationResult = new ValidationResult();                var subMatchingSchemas = matchingSchemas.newSub();                validate(node, subSchema, subValidationResult, subMatchingSchemas);                if (!subValidationResult.hasProblems()) {                    matches.push(subSchema);                }                if (!bestMatch) {                    bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };                }                else {                    if (!maxOneMatch && !subValidationResult.hasProblems() && !bestMatch.validationResult.hasProblems()) {                        // no errors, both are equally good matches                        bestMatch.matchingSchemas.merge(subMatchingSchemas);                        bestMatch.validationResult.propertiesMatches += subValidationResult.propertiesMatches;                        bestMatch.validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;                    }                    else {                        var compareResult = subValidationResult.compare(bestMatch.validationResult);                        if (compareResult > 0) {                            // our node is the best matching so far                            bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };                        }                        else if (compareResult === 0) {                            // there's already a best matching but we are as good                            bestMatch.matchingSchemas.merge(subMatchingSchemas);                            bestMatch.validationResult.mergeEnumValues(subValidationResult);                        }                    }                }            }            if (matches.length > 1 && maxOneMatch) {                validationResult.problems.push({                    location: { offset: node.offset, length: 1 },                    message: localize('oneOfWarning', "Matches multiple schemas when only one must validate.")                });            }            if (bestMatch) {                validationResult.merge(bestMatch.validationResult);                validationResult.propertiesMatches += bestMatch.validationResult.propertiesMatches;                validationResult.propertiesValueMatches += bestMatch.validationResult.propertiesValueMatches;                matchingSchemas.merge(bestMatch.matchingSchemas);            }            return matches.length;        };        if (Array.isArray(schema.anyOf)) {            testAlternatives(schema.anyOf, false);        }        if (Array.isArray(schema.oneOf)) {            testAlternatives(schema.oneOf, true);        }        var testBranch = function (schema) {            var subValidationResult = new ValidationResult();            var subMatchingSchemas = matchingSchemas.newSub();            validate(node, asSchema(schema), subValidationResult, subMatchingSchemas);            validationResult.merge(subValidationResult);            validationResult.propertiesMatches += subValidationResult.propertiesMatches;            validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;            matchingSchemas.merge(subMatchingSchemas);        };        var testCondition = function (ifSchema, thenSchema, elseSchema) {            var subSchema = asSchema(ifSchema);            var subValidationResult = new ValidationResult();            var subMatchingSchemas = matchingSchemas.newSub();            validate(node, subSchema, subValidationResult, subMatchingSchemas);            matchingSchemas.merge(subMatchingSchemas);            if (!subValidationResult.hasProblems()) {                if (thenSchema) {                    testBranch(thenSchema);                }            }            else if (elseSchema) {                testBranch(elseSchema);            }        };        var ifSchema = asSchema(schema.if);        if (ifSchema) {            testCondition(ifSchema, asSchema(schema.then), asSchema(schema.else));        }        if (Array.isArray(schema.enum)) {            var val = getNodeValue(node);            var enumValueMatch = false;            for (var _d = 0, _e = schema.enum; _d < _e.length; _d++) {                var e = _e[_d];                if (equals(val, e)) {                    enumValueMatch = true;                    break;                }            }            validationResult.enumValues = schema.enum;            validationResult.enumValueMatch = enumValueMatch;            if (!enumValueMatch) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    code: ErrorCode.EnumValueMismatch,                    message: schema.errorMessage || localize('enumWarning', 'Value is not accepted. Valid values: {0}.', schema.enum.map(function (v) { return JSON.stringify(v); }).join(', '))                });            }        }        if (isDefined(schema.const)) {            var val = getNodeValue(node);            if (!equals(val, schema.const)) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    code: ErrorCode.EnumValueMismatch,                    message: schema.errorMessage || localize('constWarning', 'Value must be {0}.', JSON.stringify(schema.const))                });                validationResult.enumValueMatch = false;            }            else {                validationResult.enumValueMatch = true;            }            validationResult.enumValues = [schema.const];        }        if (schema.deprecationMessage && node.parent) {            validationResult.problems.push({                location: { offset: node.parent.offset, length: node.parent.length },                severity: DiagnosticSeverity.Warning,                message: schema.deprecationMessage,                code: ErrorCode.Deprecated            });        }    }    function _validateNumberNode(node, schema, validationResult, matchingSchemas) {        var val = node.value;        function normalizeFloats(float) {            var _a;            var parts = /^(-?\d+)(?:\.(\d+))?(?:e([-+]\d+))?$/.exec(float.toString());            return parts && {                value: Number(parts[1] + (parts[2] || '')),                multiplier: (((_a = parts[2]) === null || _a === void 0 ? void 0 : _a.length) || 0) - (parseInt(parts[3]) || 0)            };        }        ;        if (isNumber(schema.multipleOf)) {            var remainder = -1;            if (Number.isInteger(schema.multipleOf)) {                remainder = val % schema.multipleOf;            }            else {                var normMultipleOf = normalizeFloats(schema.multipleOf);                var normValue = normalizeFloats(val);                if (normMultipleOf && normValue) {                    var multiplier = Math.pow(10, Math.abs(normValue.multiplier - normMultipleOf.multiplier));                    if (normValue.multiplier < normMultipleOf.multiplier) {                        normValue.value *= multiplier;                    }                    else {                        normMultipleOf.value *= multiplier;                    }                    remainder = normValue.value % normMultipleOf.value;                }            }            if (remainder !== 0) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: localize('multipleOfWarning', 'Value is not divisible by {0}.', schema.multipleOf)                });            }        }        function getExclusiveLimit(limit, exclusive) {            if (isNumber(exclusive)) {                return exclusive;            }            if (isBoolean(exclusive) && exclusive) {                return limit;            }            return undefined;        }        function getLimit(limit, exclusive) {            if (!isBoolean(exclusive) || !exclusive) {                return limit;            }            return undefined;        }        var exclusiveMinimum = getExclusiveLimit(schema.minimum, schema.exclusiveMinimum);        if (isNumber(exclusiveMinimum) && val <= exclusiveMinimum) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('exclusiveMinimumWarning', 'Value is below the exclusive minimum of {0}.', exclusiveMinimum)            });        }        var exclusiveMaximum = getExclusiveLimit(schema.maximum, schema.exclusiveMaximum);        if (isNumber(exclusiveMaximum) && val >= exclusiveMaximum) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('exclusiveMaximumWarning', 'Value is above the exclusive maximum of {0}.', exclusiveMaximum)            });        }        var minimum = getLimit(schema.minimum, schema.exclusiveMinimum);        if (isNumber(minimum) && val < minimum) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('minimumWarning', 'Value is below the minimum of {0}.', minimum)            });        }        var maximum = getLimit(schema.maximum, schema.exclusiveMaximum);        if (isNumber(maximum) && val > maximum) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('maximumWarning', 'Value is above the maximum of {0}.', maximum)            });        }    }    function _validateStringNode(node, schema, validationResult, matchingSchemas) {        if (isNumber(schema.minLength) && node.value.length < schema.minLength) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('minLengthWarning', 'String is shorter than the minimum length of {0}.', schema.minLength)            });        }        if (isNumber(schema.maxLength) && node.value.length > schema.maxLength) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('maxLengthWarning', 'String is longer than the maximum length of {0}.', schema.maxLength)            });        }        if (isString(schema.pattern)) {            var regex = extendedRegExp(schema.pattern);            if (!regex.test(node.value)) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)                });            }        }        if (schema.format) {            switch (schema.format) {                case 'uri':                case 'uri-reference':                    {                        var errorMessage = void 0;                        if (!node.value) {                            errorMessage = localize('uriEmpty', 'URI expected.');                        }                        else {                            var match = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(node.value);                            if (!match) {                                errorMessage = localize('uriMissing', 'URI is expected.');                            }                            else if (!match[2] && schema.format === 'uri') {                                errorMessage = localize('uriSchemeMissing', 'URI with a scheme is expected.');                            }                        }                        if (errorMessage) {                            validationResult.problems.push({                                location: { offset: node.offset, length: node.length },                                message: schema.patternErrorMessage || schema.errorMessage || localize('uriFormatWarning', 'String is not a URI: {0}', errorMessage)                            });                        }                    }                    break;                case 'color-hex':                case 'date-time':                case 'date':                case 'time':                case 'email':                    var format = formats[schema.format];                    if (!node.value || !format.pattern.exec(node.value)) {                        validationResult.problems.push({                            location: { offset: node.offset, length: node.length },                            message: schema.patternErrorMessage || schema.errorMessage || format.errorMessage                        });                    }                default:            }        }    }    function _validateArrayNode(node, schema, validationResult, matchingSchemas) {        if (Array.isArray(schema.items)) {            var subSchemas = schema.items;            for (var index = 0; index < subSchemas.length; index++) {                var subSchemaRef = subSchemas[index];                var subSchema = asSchema(subSchemaRef);                var itemValidationResult = new ValidationResult();                var item = node.items[index];                if (item) {                    validate(item, subSchema, itemValidationResult, matchingSchemas);                    validationResult.mergePropertyMatch(itemValidationResult);                }                else if (node.items.length >= subSchemas.length) {                    validationResult.propertiesValueMatches++;                }            }            if (node.items.length > subSchemas.length) {                if (typeof schema.additionalItems === 'object') {                    for (var i = subSchemas.length; i < node.items.length; i++) {                        var itemValidationResult = new ValidationResult();                        validate(node.items[i], schema.additionalItems, itemValidationResult, matchingSchemas);                        validationResult.mergePropertyMatch(itemValidationResult);                    }                }                else if (schema.additionalItems === false) {                    validationResult.problems.push({                        location: { offset: node.offset, length: node.length },                        message: localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer.', subSchemas.length)                    });                }            }        }        else {            var itemSchema = asSchema(schema.items);            if (itemSchema) {                for (var _i = 0, _a = node.items; _i < _a.length; _i++) {                    var item = _a[_i];                    var itemValidationResult = new ValidationResult();                    validate(item, itemSchema, itemValidationResult, matchingSchemas);                    validationResult.mergePropertyMatch(itemValidationResult);                }            }        }        var containsSchema = asSchema(schema.contains);        if (containsSchema) {            var doesContain = node.items.some(function (item) {                var itemValidationResult = new ValidationResult();                validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance);                return !itemValidationResult.hasProblems();            });            if (!doesContain) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: schema.errorMessage || localize('requiredItemMissingWarning', 'Array does not contain required item.')                });            }        }        if (isNumber(schema.minItems) && node.items.length < schema.minItems) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('minItemsWarning', 'Array has too few items. Expected {0} or more.', schema.minItems)            });        }        if (isNumber(schema.maxItems) && node.items.length > schema.maxItems) {            validationResult.problems.push({                location: { offset: node.offset, length: node.length },                message: localize('maxItemsWarning', 'Array has too many items. Expected {0} or fewer.', schema.maxItems)            });        }        if (schema.uniqueItems === true) {            var values_1 = getNodeValue(node);            var duplicates = values_1.some(function (value, index) {                return index !== values_1.lastIndexOf(value);            });            if (duplicates) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: localize('uniqueItemsWarning', 'Array has duplicate items.')                });            }        }    }    function _validateObjectNode(node, schema, validationResult, matchingSchemas) {        var seenKeys = Object.create(null);        var unprocessedProperties = [];        for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {            var propertyNode = _a[_i];            var key = propertyNode.keyNode.value;            seenKeys[key] = propertyNode.valueNode;            unprocessedProperties.push(key);        }        if (Array.isArray(schema.required)) {            for (var _b = 0, _c = schema.required; _b < _c.length; _b++) {                var propertyName = _c[_b];                if (!seenKeys[propertyName]) {                    var keyNode = node.parent && node.parent.type === 'property' && node.parent.keyNode;                    var location = keyNode ? { offset: keyNode.offset, length: keyNode.length } : { offset: node.offset, length: 1 };                    validationResult.problems.push({                        location: location,                        message: localize('MissingRequiredPropWarning', 'Missing property "{0}".', propertyName)                    });                }            }        }        var propertyProcessed = function (prop) {            var index = unprocessedProperties.indexOf(prop);            while (index >= 0) {                unprocessedProperties.splice(index, 1);                index = unprocessedProperties.indexOf(prop);            }        };        if (schema.properties) {            for (var _d = 0, _e = Object.keys(schema.properties); _d < _e.length; _d++) {                var propertyName = _e[_d];                propertyProcessed(propertyName);                var propertySchema = schema.properties[propertyName];                var child = seenKeys[propertyName];                if (child) {                    if (isBoolean(propertySchema)) {                        if (!propertySchema) {                            var propertyNode = child.parent;                            validationResult.problems.push({                                location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },                                message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)                            });                        }                        else {                            validationResult.propertiesMatches++;                            validationResult.propertiesValueMatches++;                        }                    }                    else {                        var propertyValidationResult = new ValidationResult();                        validate(child, propertySchema, propertyValidationResult, matchingSchemas);                        validationResult.mergePropertyMatch(propertyValidationResult);                    }                }            }        }        if (schema.patternProperties) {            for (var _f = 0, _g = Object.keys(schema.patternProperties); _f < _g.length; _f++) {                var propertyPattern = _g[_f];                var regex = extendedRegExp(propertyPattern);                for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {                    var propertyName = _j[_h];                    if (regex.test(propertyName)) {                        propertyProcessed(propertyName);                        var child = seenKeys[propertyName];                        if (child) {                            var propertySchema = schema.patternProperties[propertyPattern];                            if (isBoolean(propertySchema)) {                                if (!propertySchema) {                                    var propertyNode = child.parent;                                    validationResult.problems.push({                                        location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },                                        message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)                                    });                                }                                else {                                    validationResult.propertiesMatches++;                                    validationResult.propertiesValueMatches++;                                }                            }                            else {                                var propertyValidationResult = new ValidationResult();                                validate(child, propertySchema, propertyValidationResult, matchingSchemas);                                validationResult.mergePropertyMatch(propertyValidationResult);                            }                        }                    }                }            }        }        if (typeof schema.additionalProperties === 'object') {            for (var _k = 0, unprocessedProperties_1 = unprocessedProperties; _k < unprocessedProperties_1.length; _k++) {                var propertyName = unprocessedProperties_1[_k];                var child = seenKeys[propertyName];                if (child) {                    var propertyValidationResult = new ValidationResult();                    validate(child, schema.additionalProperties, propertyValidationResult, matchingSchemas);                    validationResult.mergePropertyMatch(propertyValidationResult);                }            }        }        else if (schema.additionalProperties === false) {            if (unprocessedProperties.length > 0) {                for (var _l = 0, unprocessedProperties_2 = unprocessedProperties; _l < unprocessedProperties_2.length; _l++) {                    var propertyName = unprocessedProperties_2[_l];                    var child = seenKeys[propertyName];                    if (child) {                        var propertyNode = child.parent;                        validationResult.problems.push({                            location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },                            message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)                        });                    }                }            }        }        if (isNumber(schema.maxProperties)) {            if (node.properties.length > schema.maxProperties) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: localize('MaxPropWarning', 'Object has more properties than limit of {0}.', schema.maxProperties)                });            }        }        if (isNumber(schema.minProperties)) {            if (node.properties.length < schema.minProperties) {                validationResult.problems.push({                    location: { offset: node.offset, length: node.length },                    message: localize('MinPropWarning', 'Object has fewer properties than the required number of {0}', schema.minProperties)                });            }        }        if (schema.dependencies) {            for (var _m = 0, _o = Object.keys(schema.dependencies); _m < _o.length; _m++) {                var key = _o[_m];                var prop = seenKeys[key];                if (prop) {                    var propertyDep = schema.dependencies[key];                    if (Array.isArray(propertyDep)) {                        for (var _p = 0, propertyDep_1 = propertyDep; _p < propertyDep_1.length; _p++) {                            var requiredProp = propertyDep_1[_p];                            if (!seenKeys[requiredProp]) {                                validationResult.problems.push({                                    location: { offset: node.offset, length: node.length },                                    message: localize('RequiredDependentPropWarning', 'Object is missing property {0} required by property {1}.', requiredProp, key)                                });                            }                            else {                                validationResult.propertiesValueMatches++;                            }                        }                    }                    else {                        var propertySchema = asSchema(propertyDep);                        if (propertySchema) {                            var propertyValidationResult = new ValidationResult();                            validate(node, propertySchema, propertyValidationResult, matchingSchemas);                            validationResult.mergePropertyMatch(propertyValidationResult);                        }                    }                }            }        }        var propertyNames = asSchema(schema.propertyNames);        if (propertyNames) {            for (var _q = 0, _r = node.properties; _q < _r.length; _q++) {                var f = _r[_q];                var key = f.keyNode;                if (key) {                    validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance);                }            }        }    }}export function parse(textDocument, config) {    var problems = [];    var lastProblemOffset = -1;    var text = textDocument.getText();    var scanner = Json.createScanner(text, false);    var commentRanges = config && config.collectComments ? [] : undefined;    function _scanNext() {        while (true) {            var token_1 = scanner.scan();            _checkScanError();            switch (token_1) {                case 12 /* LineCommentTrivia */:                case 13 /* BlockCommentTrivia */:                    if (Array.isArray(commentRanges)) {                        commentRanges.push(Range.create(textDocument.positionAt(scanner.getTokenOffset()), textDocument.positionAt(scanner.getTokenOffset() + scanner.getTokenLength())));                    }                    break;                case 15 /* Trivia */:                case 14 /* LineBreakTrivia */:                    break;                default:                    return token_1;            }        }    }    function _accept(token) {        if (scanner.getToken() === token) {            _scanNext();            return true;        }        return false;    }    function _errorAtRange(message, code, startOffset, endOffset, severity) {        if (severity === void 0) { severity = DiagnosticSeverity.Error; }        if (problems.length === 0 || startOffset !== lastProblemOffset) {            var range = Range.create(textDocument.positionAt(startOffset), textDocument.positionAt(endOffset));            problems.push(Diagnostic.create(range, message, severity, code, textDocument.languageId));            lastProblemOffset = startOffset;        }    }    function _error(message, code, node, skipUntilAfter, skipUntil) {        if (node === void 0) { node = undefined; }        if (skipUntilAfter === void 0) { skipUntilAfter = []; }        if (skipUntil === void 0) { skipUntil = []; }        var start = scanner.getTokenOffset();        var end = scanner.getTokenOffset() + scanner.getTokenLength();        if (start === end && start > 0) {            start--;            while (start > 0 && /\s/.test(text.charAt(start))) {                start--;            }            end = start + 1;        }        _errorAtRange(message, code, start, end);        if (node) {            _finalize(node, false);        }        if (skipUntilAfter.length + skipUntil.length > 0) {            var token_2 = scanner.getToken();            while (token_2 !== 17 /* EOF */) {                if (skipUntilAfter.indexOf(token_2) !== -1) {                    _scanNext();                    break;                }                else if (skipUntil.indexOf(token_2) !== -1) {                    break;                }                token_2 = _scanNext();            }        }        return node;    }    function _checkScanError() {        switch (scanner.getTokenError()) {            case 4 /* InvalidUnicode */:                _error(localize('InvalidUnicode', 'Invalid unicode sequence in string.'), ErrorCode.InvalidUnicode);                return true;            case 5 /* InvalidEscapeCharacter */:                _error(localize('InvalidEscapeCharacter', 'Invalid escape character in string.'), ErrorCode.InvalidEscapeCharacter);                return true;            case 3 /* UnexpectedEndOfNumber */:                _error(localize('UnexpectedEndOfNumber', 'Unexpected end of number.'), ErrorCode.UnexpectedEndOfNumber);                return true;            case 1 /* UnexpectedEndOfComment */:                _error(localize('UnexpectedEndOfComment', 'Unexpected end of comment.'), ErrorCode.UnexpectedEndOfComment);                return true;            case 2 /* UnexpectedEndOfString */:                _error(localize('UnexpectedEndOfString', 'Unexpected end of string.'), ErrorCode.UnexpectedEndOfString);                return true;            case 6 /* InvalidCharacter */:                _error(localize('InvalidCharacter', 'Invalid characters in string. Control characters must be escaped.'), ErrorCode.InvalidCharacter);                return true;        }        return false;    }    function _finalize(node, scanNext) {        node.length = scanner.getTokenOffset() + scanner.getTokenLength() - node.offset;        if (scanNext) {            _scanNext();        }        return node;    }    function _parseArray(parent) {        if (scanner.getToken() !== 3 /* OpenBracketToken */) {            return undefined;        }        var node = new ArrayASTNodeImpl(parent, scanner.getTokenOffset());        _scanNext(); // consume OpenBracketToken        var count = 0;        var needsComma = false;        while (scanner.getToken() !== 4 /* CloseBracketToken */ && scanner.getToken() !== 17 /* EOF */) {            if (scanner.getToken() === 5 /* CommaToken */) {                if (!needsComma) {                    _error(localize('ValueExpected', 'Value expected'), ErrorCode.ValueExpected);                }                var commaOffset = scanner.getTokenOffset();                _scanNext(); // consume comma                if (scanner.getToken() === 4 /* CloseBracketToken */) {                    if (needsComma) {                        _errorAtRange(localize('TrailingComma', 'Trailing comma'), ErrorCode.TrailingComma, commaOffset, commaOffset + 1);                    }                    continue;                }            }            else if (needsComma) {                _error(localize('ExpectedComma', 'Expected comma'), ErrorCode.CommaExpected);            }            var item = _parseValue(node);            if (!item) {                _error(localize('PropertyExpected', 'Value expected'), ErrorCode.ValueExpected, undefined, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);            }            else {                node.items.push(item);            }            needsComma = true;        }        if (scanner.getToken() !== 4 /* CloseBracketToken */) {            return _error(localize('ExpectedCloseBracket', 'Expected comma or closing bracket'), ErrorCode.CommaOrCloseBacketExpected, node);        }        return _finalize(node, true);    }    var keyPlaceholder = new StringASTNodeImpl(undefined, 0, 0);    function _parseProperty(parent, keysSeen) {        var node = new PropertyASTNodeImpl(parent, scanner.getTokenOffset(), keyPlaceholder);        var key = _parseString(node);        if (!key) {            if (scanner.getToken() === 16 /* Unknown */) {                // give a more helpful error message                _error(localize('DoubleQuotesExpected', 'Property keys must be doublequoted'), ErrorCode.Undefined);                var keyNode = new StringASTNodeImpl(node, scanner.getTokenOffset(), scanner.getTokenLength());                keyNode.value = scanner.getTokenValue();                key = keyNode;                _scanNext(); // consume Unknown            }            else {                return undefined;            }        }        node.keyNode = key;        var seen = keysSeen[key.value];        if (seen) {            _errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), ErrorCode.DuplicateKey, node.keyNode.offset, node.keyNode.offset + node.keyNode.length, DiagnosticSeverity.Warning);            if (typeof seen === 'object') {                _errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), ErrorCode.DuplicateKey, seen.keyNode.offset, seen.keyNode.offset + seen.keyNode.length, DiagnosticSeverity.Warning);            }            keysSeen[key.value] = true; // if the same key is duplicate again, avoid duplicate error reporting        }        else {            keysSeen[key.value] = node;        }        if (scanner.getToken() === 6 /* ColonToken */) {            node.colonOffset = scanner.getTokenOffset();            _scanNext(); // consume ColonToken        }        else {            _error(localize('ColonExpected', 'Colon expected'), ErrorCode.ColonExpected);            if (scanner.getToken() === 10 /* StringLiteral */ && textDocument.positionAt(key.offset + key.length).line < textDocument.positionAt(scanner.getTokenOffset()).line) {                node.length = key.length;                return node;            }        }        var value = _parseValue(node);        if (!value) {            return _error(localize('ValueExpected', 'Value expected'), ErrorCode.ValueExpected, node, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);        }        node.valueNode = value;        node.length = value.offset + value.length - node.offset;        return node;    }    function _parseObject(parent) {        if (scanner.getToken() !== 1 /* OpenBraceToken */) {            return undefined;        }        var node = new ObjectASTNodeImpl(parent, scanner.getTokenOffset());        var keysSeen = Object.create(null);        _scanNext(); // consume OpenBraceToken        var needsComma = false;        while (scanner.getToken() !== 2 /* CloseBraceToken */ && scanner.getToken() !== 17 /* EOF */) {            if (scanner.getToken() === 5 /* CommaToken */) {                if (!needsComma) {                    _error(localize('PropertyExpected', 'Property expected'), ErrorCode.PropertyExpected);                }                var commaOffset = scanner.getTokenOffset();                _scanNext(); // consume comma                if (scanner.getToken() === 2 /* CloseBraceToken */) {                    if (needsComma) {                        _errorAtRange(localize('TrailingComma', 'Trailing comma'), ErrorCode.TrailingComma, commaOffset, commaOffset + 1);                    }                    continue;                }            }            else if (needsComma) {                _error(localize('ExpectedComma', 'Expected comma'), ErrorCode.CommaExpected);            }            var property = _parseProperty(node, keysSeen);            if (!property) {                _error(localize('PropertyExpected', 'Property expected'), ErrorCode.PropertyExpected, undefined, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);            }            else {                node.properties.push(property);            }            needsComma = true;        }        if (scanner.getToken() !== 2 /* CloseBraceToken */) {            return _error(localize('ExpectedCloseBrace', 'Expected comma or closing brace'), ErrorCode.CommaOrCloseBraceExpected, node);        }        return _finalize(node, true);    }    function _parseString(parent) {        if (scanner.getToken() !== 10 /* StringLiteral */) {            return undefined;        }        var node = new StringASTNodeImpl(parent, scanner.getTokenOffset());        node.value = scanner.getTokenValue();        return _finalize(node, true);    }    function _parseNumber(parent) {        if (scanner.getToken() !== 11 /* NumericLiteral */) {            return undefined;        }        var node = new NumberASTNodeImpl(parent, scanner.getTokenOffset());        if (scanner.getTokenError() === 0 /* None */) {            var tokenValue = scanner.getTokenValue();            try {                var numberValue = JSON.parse(tokenValue);                if (!isNumber(numberValue)) {                    return _error(localize('InvalidNumberFormat', 'Invalid number format.'), ErrorCode.Undefined, node);                }                node.value = numberValue;            }            catch (e) {                return _error(localize('InvalidNumberFormat', 'Invalid number format.'), ErrorCode.Undefined, node);            }            node.isInteger = tokenValue.indexOf('.') === -1;        }        return _finalize(node, true);    }    function _parseLiteral(parent) {        var node;        switch (scanner.getToken()) {            case 7 /* NullKeyword */:                return _finalize(new NullASTNodeImpl(parent, scanner.getTokenOffset()), true);            case 8 /* TrueKeyword */:                return _finalize(new BooleanASTNodeImpl(parent, true, scanner.getTokenOffset()), true);            case 9 /* FalseKeyword */:                return _finalize(new BooleanASTNodeImpl(parent, false, scanner.getTokenOffset()), true);            default:                return undefined;        }    }    function _parseValue(parent) {        return _parseArray(parent) || _parseObject(parent) || _parseString(parent) || _parseNumber(parent) || _parseLiteral(parent);    }    var _root = undefined;    var token = _scanNext();    if (token !== 17 /* EOF */) {        _root = _parseValue(_root);        if (!_root) {            _error(localize('Invalid symbol', 'Expected a JSON object, array or literal.'), ErrorCode.Undefined);        }        else if (scanner.getToken() !== 17 /* EOF */) {            _error(localize('End of file expected', 'End of file expected.'), ErrorCode.Undefined);        }    }    return new JSONDocument(_root, problems, commentRanges);}
 |