jsonParser.js 63 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. var __extends = (this && this.__extends) || (function () {
  6. var extendStatics = function (d, b) {
  7. extendStatics = Object.setPrototypeOf ||
  8. ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
  9. function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
  10. return extendStatics(d, b);
  11. };
  12. return function (d, b) {
  13. if (typeof b !== "function" && b !== null)
  14. throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
  15. extendStatics(d, b);
  16. function __() { this.constructor = d; }
  17. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  18. };
  19. })();
  20. (function (factory) {
  21. if (typeof module === "object" && typeof module.exports === "object") {
  22. var v = factory(require, exports);
  23. if (v !== undefined) module.exports = v;
  24. }
  25. else if (typeof define === "function" && define.amd) {
  26. define(["require", "exports", "jsonc-parser", "../utils/objects", "../utils/strings", "../jsonLanguageTypes", "vscode-nls"], factory);
  27. }
  28. })(function (require, exports) {
  29. "use strict";
  30. Object.defineProperty(exports, "__esModule", { value: true });
  31. exports.parse = exports.JSONDocument = exports.contains = exports.getNodePath = exports.getNodeValue = exports.newJSONDocument = exports.ValidationResult = exports.EnumMatch = exports.asSchema = exports.ObjectASTNodeImpl = exports.PropertyASTNodeImpl = exports.StringASTNodeImpl = exports.NumberASTNodeImpl = exports.ArrayASTNodeImpl = exports.BooleanASTNodeImpl = exports.NullASTNodeImpl = exports.ASTNodeImpl = void 0;
  32. var Json = require("jsonc-parser");
  33. var objects_1 = require("../utils/objects");
  34. var strings_1 = require("../utils/strings");
  35. var jsonLanguageTypes_1 = require("../jsonLanguageTypes");
  36. var nls = require("vscode-nls");
  37. var localize = nls.loadMessageBundle();
  38. var formats = {
  39. '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})$/ },
  40. '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 },
  41. '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 },
  42. '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 },
  43. '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,}))$/ }
  44. };
  45. var ASTNodeImpl = /** @class */ (function () {
  46. function ASTNodeImpl(parent, offset, length) {
  47. if (length === void 0) { length = 0; }
  48. this.offset = offset;
  49. this.length = length;
  50. this.parent = parent;
  51. }
  52. Object.defineProperty(ASTNodeImpl.prototype, "children", {
  53. get: function () {
  54. return [];
  55. },
  56. enumerable: false,
  57. configurable: true
  58. });
  59. ASTNodeImpl.prototype.toString = function () {
  60. return 'type: ' + this.type + ' (' + this.offset + '/' + this.length + ')' + (this.parent ? ' parent: {' + this.parent.toString() + '}' : '');
  61. };
  62. return ASTNodeImpl;
  63. }());
  64. exports.ASTNodeImpl = ASTNodeImpl;
  65. var NullASTNodeImpl = /** @class */ (function (_super) {
  66. __extends(NullASTNodeImpl, _super);
  67. function NullASTNodeImpl(parent, offset) {
  68. var _this = _super.call(this, parent, offset) || this;
  69. _this.type = 'null';
  70. _this.value = null;
  71. return _this;
  72. }
  73. return NullASTNodeImpl;
  74. }(ASTNodeImpl));
  75. exports.NullASTNodeImpl = NullASTNodeImpl;
  76. var BooleanASTNodeImpl = /** @class */ (function (_super) {
  77. __extends(BooleanASTNodeImpl, _super);
  78. function BooleanASTNodeImpl(parent, boolValue, offset) {
  79. var _this = _super.call(this, parent, offset) || this;
  80. _this.type = 'boolean';
  81. _this.value = boolValue;
  82. return _this;
  83. }
  84. return BooleanASTNodeImpl;
  85. }(ASTNodeImpl));
  86. exports.BooleanASTNodeImpl = BooleanASTNodeImpl;
  87. var ArrayASTNodeImpl = /** @class */ (function (_super) {
  88. __extends(ArrayASTNodeImpl, _super);
  89. function ArrayASTNodeImpl(parent, offset) {
  90. var _this = _super.call(this, parent, offset) || this;
  91. _this.type = 'array';
  92. _this.items = [];
  93. return _this;
  94. }
  95. Object.defineProperty(ArrayASTNodeImpl.prototype, "children", {
  96. get: function () {
  97. return this.items;
  98. },
  99. enumerable: false,
  100. configurable: true
  101. });
  102. return ArrayASTNodeImpl;
  103. }(ASTNodeImpl));
  104. exports.ArrayASTNodeImpl = ArrayASTNodeImpl;
  105. var NumberASTNodeImpl = /** @class */ (function (_super) {
  106. __extends(NumberASTNodeImpl, _super);
  107. function NumberASTNodeImpl(parent, offset) {
  108. var _this = _super.call(this, parent, offset) || this;
  109. _this.type = 'number';
  110. _this.isInteger = true;
  111. _this.value = Number.NaN;
  112. return _this;
  113. }
  114. return NumberASTNodeImpl;
  115. }(ASTNodeImpl));
  116. exports.NumberASTNodeImpl = NumberASTNodeImpl;
  117. var StringASTNodeImpl = /** @class */ (function (_super) {
  118. __extends(StringASTNodeImpl, _super);
  119. function StringASTNodeImpl(parent, offset, length) {
  120. var _this = _super.call(this, parent, offset, length) || this;
  121. _this.type = 'string';
  122. _this.value = '';
  123. return _this;
  124. }
  125. return StringASTNodeImpl;
  126. }(ASTNodeImpl));
  127. exports.StringASTNodeImpl = StringASTNodeImpl;
  128. var PropertyASTNodeImpl = /** @class */ (function (_super) {
  129. __extends(PropertyASTNodeImpl, _super);
  130. function PropertyASTNodeImpl(parent, offset, keyNode) {
  131. var _this = _super.call(this, parent, offset) || this;
  132. _this.type = 'property';
  133. _this.colonOffset = -1;
  134. _this.keyNode = keyNode;
  135. return _this;
  136. }
  137. Object.defineProperty(PropertyASTNodeImpl.prototype, "children", {
  138. get: function () {
  139. return this.valueNode ? [this.keyNode, this.valueNode] : [this.keyNode];
  140. },
  141. enumerable: false,
  142. configurable: true
  143. });
  144. return PropertyASTNodeImpl;
  145. }(ASTNodeImpl));
  146. exports.PropertyASTNodeImpl = PropertyASTNodeImpl;
  147. var ObjectASTNodeImpl = /** @class */ (function (_super) {
  148. __extends(ObjectASTNodeImpl, _super);
  149. function ObjectASTNodeImpl(parent, offset) {
  150. var _this = _super.call(this, parent, offset) || this;
  151. _this.type = 'object';
  152. _this.properties = [];
  153. return _this;
  154. }
  155. Object.defineProperty(ObjectASTNodeImpl.prototype, "children", {
  156. get: function () {
  157. return this.properties;
  158. },
  159. enumerable: false,
  160. configurable: true
  161. });
  162. return ObjectASTNodeImpl;
  163. }(ASTNodeImpl));
  164. exports.ObjectASTNodeImpl = ObjectASTNodeImpl;
  165. function asSchema(schema) {
  166. if (objects_1.isBoolean(schema)) {
  167. return schema ? {} : { "not": {} };
  168. }
  169. return schema;
  170. }
  171. exports.asSchema = asSchema;
  172. var EnumMatch;
  173. (function (EnumMatch) {
  174. EnumMatch[EnumMatch["Key"] = 0] = "Key";
  175. EnumMatch[EnumMatch["Enum"] = 1] = "Enum";
  176. })(EnumMatch = exports.EnumMatch || (exports.EnumMatch = {}));
  177. var SchemaCollector = /** @class */ (function () {
  178. function SchemaCollector(focusOffset, exclude) {
  179. if (focusOffset === void 0) { focusOffset = -1; }
  180. this.focusOffset = focusOffset;
  181. this.exclude = exclude;
  182. this.schemas = [];
  183. }
  184. SchemaCollector.prototype.add = function (schema) {
  185. this.schemas.push(schema);
  186. };
  187. SchemaCollector.prototype.merge = function (other) {
  188. Array.prototype.push.apply(this.schemas, other.schemas);
  189. };
  190. SchemaCollector.prototype.include = function (node) {
  191. return (this.focusOffset === -1 || contains(node, this.focusOffset)) && (node !== this.exclude);
  192. };
  193. SchemaCollector.prototype.newSub = function () {
  194. return new SchemaCollector(-1, this.exclude);
  195. };
  196. return SchemaCollector;
  197. }());
  198. var NoOpSchemaCollector = /** @class */ (function () {
  199. function NoOpSchemaCollector() {
  200. }
  201. Object.defineProperty(NoOpSchemaCollector.prototype, "schemas", {
  202. get: function () { return []; },
  203. enumerable: false,
  204. configurable: true
  205. });
  206. NoOpSchemaCollector.prototype.add = function (schema) { };
  207. NoOpSchemaCollector.prototype.merge = function (other) { };
  208. NoOpSchemaCollector.prototype.include = function (node) { return true; };
  209. NoOpSchemaCollector.prototype.newSub = function () { return this; };
  210. NoOpSchemaCollector.instance = new NoOpSchemaCollector();
  211. return NoOpSchemaCollector;
  212. }());
  213. var ValidationResult = /** @class */ (function () {
  214. function ValidationResult() {
  215. this.problems = [];
  216. this.propertiesMatches = 0;
  217. this.propertiesValueMatches = 0;
  218. this.primaryValueMatches = 0;
  219. this.enumValueMatch = false;
  220. this.enumValues = undefined;
  221. }
  222. ValidationResult.prototype.hasProblems = function () {
  223. return !!this.problems.length;
  224. };
  225. ValidationResult.prototype.mergeAll = function (validationResults) {
  226. for (var _i = 0, validationResults_1 = validationResults; _i < validationResults_1.length; _i++) {
  227. var validationResult = validationResults_1[_i];
  228. this.merge(validationResult);
  229. }
  230. };
  231. ValidationResult.prototype.merge = function (validationResult) {
  232. this.problems = this.problems.concat(validationResult.problems);
  233. };
  234. ValidationResult.prototype.mergeEnumValues = function (validationResult) {
  235. if (!this.enumValueMatch && !validationResult.enumValueMatch && this.enumValues && validationResult.enumValues) {
  236. this.enumValues = this.enumValues.concat(validationResult.enumValues);
  237. for (var _i = 0, _a = this.problems; _i < _a.length; _i++) {
  238. var error = _a[_i];
  239. if (error.code === jsonLanguageTypes_1.ErrorCode.EnumValueMismatch) {
  240. error.message = localize('enumWarning', 'Value is not accepted. Valid values: {0}.', this.enumValues.map(function (v) { return JSON.stringify(v); }).join(', '));
  241. }
  242. }
  243. }
  244. };
  245. ValidationResult.prototype.mergePropertyMatch = function (propertyValidationResult) {
  246. this.merge(propertyValidationResult);
  247. this.propertiesMatches++;
  248. if (propertyValidationResult.enumValueMatch || !propertyValidationResult.hasProblems() && propertyValidationResult.propertiesMatches) {
  249. this.propertiesValueMatches++;
  250. }
  251. if (propertyValidationResult.enumValueMatch && propertyValidationResult.enumValues && propertyValidationResult.enumValues.length === 1) {
  252. this.primaryValueMatches++;
  253. }
  254. };
  255. ValidationResult.prototype.compare = function (other) {
  256. var hasProblems = this.hasProblems();
  257. if (hasProblems !== other.hasProblems()) {
  258. return hasProblems ? -1 : 1;
  259. }
  260. if (this.enumValueMatch !== other.enumValueMatch) {
  261. return other.enumValueMatch ? -1 : 1;
  262. }
  263. if (this.primaryValueMatches !== other.primaryValueMatches) {
  264. return this.primaryValueMatches - other.primaryValueMatches;
  265. }
  266. if (this.propertiesValueMatches !== other.propertiesValueMatches) {
  267. return this.propertiesValueMatches - other.propertiesValueMatches;
  268. }
  269. return this.propertiesMatches - other.propertiesMatches;
  270. };
  271. return ValidationResult;
  272. }());
  273. exports.ValidationResult = ValidationResult;
  274. function newJSONDocument(root, diagnostics) {
  275. if (diagnostics === void 0) { diagnostics = []; }
  276. return new JSONDocument(root, diagnostics, []);
  277. }
  278. exports.newJSONDocument = newJSONDocument;
  279. function getNodeValue(node) {
  280. return Json.getNodeValue(node);
  281. }
  282. exports.getNodeValue = getNodeValue;
  283. function getNodePath(node) {
  284. return Json.getNodePath(node);
  285. }
  286. exports.getNodePath = getNodePath;
  287. function contains(node, offset, includeRightBound) {
  288. if (includeRightBound === void 0) { includeRightBound = false; }
  289. return offset >= node.offset && offset < (node.offset + node.length) || includeRightBound && offset === (node.offset + node.length);
  290. }
  291. exports.contains = contains;
  292. var JSONDocument = /** @class */ (function () {
  293. function JSONDocument(root, syntaxErrors, comments) {
  294. if (syntaxErrors === void 0) { syntaxErrors = []; }
  295. if (comments === void 0) { comments = []; }
  296. this.root = root;
  297. this.syntaxErrors = syntaxErrors;
  298. this.comments = comments;
  299. }
  300. JSONDocument.prototype.getNodeFromOffset = function (offset, includeRightBound) {
  301. if (includeRightBound === void 0) { includeRightBound = false; }
  302. if (this.root) {
  303. return Json.findNodeAtOffset(this.root, offset, includeRightBound);
  304. }
  305. return undefined;
  306. };
  307. JSONDocument.prototype.visit = function (visitor) {
  308. if (this.root) {
  309. var doVisit_1 = function (node) {
  310. var ctn = visitor(node);
  311. var children = node.children;
  312. if (Array.isArray(children)) {
  313. for (var i = 0; i < children.length && ctn; i++) {
  314. ctn = doVisit_1(children[i]);
  315. }
  316. }
  317. return ctn;
  318. };
  319. doVisit_1(this.root);
  320. }
  321. };
  322. JSONDocument.prototype.validate = function (textDocument, schema, severity) {
  323. if (severity === void 0) { severity = jsonLanguageTypes_1.DiagnosticSeverity.Warning; }
  324. if (this.root && schema) {
  325. var validationResult = new ValidationResult();
  326. validate(this.root, schema, validationResult, NoOpSchemaCollector.instance);
  327. return validationResult.problems.map(function (p) {
  328. var _a;
  329. var range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(p.location.offset), textDocument.positionAt(p.location.offset + p.location.length));
  330. return jsonLanguageTypes_1.Diagnostic.create(range, p.message, (_a = p.severity) !== null && _a !== void 0 ? _a : severity, p.code);
  331. });
  332. }
  333. return undefined;
  334. };
  335. JSONDocument.prototype.getMatchingSchemas = function (schema, focusOffset, exclude) {
  336. if (focusOffset === void 0) { focusOffset = -1; }
  337. var matchingSchemas = new SchemaCollector(focusOffset, exclude);
  338. if (this.root && schema) {
  339. validate(this.root, schema, new ValidationResult(), matchingSchemas);
  340. }
  341. return matchingSchemas.schemas;
  342. };
  343. return JSONDocument;
  344. }());
  345. exports.JSONDocument = JSONDocument;
  346. function validate(n, schema, validationResult, matchingSchemas) {
  347. if (!n || !matchingSchemas.include(n)) {
  348. return;
  349. }
  350. var node = n;
  351. switch (node.type) {
  352. case 'object':
  353. _validateObjectNode(node, schema, validationResult, matchingSchemas);
  354. break;
  355. case 'array':
  356. _validateArrayNode(node, schema, validationResult, matchingSchemas);
  357. break;
  358. case 'string':
  359. _validateStringNode(node, schema, validationResult, matchingSchemas);
  360. break;
  361. case 'number':
  362. _validateNumberNode(node, schema, validationResult, matchingSchemas);
  363. break;
  364. case 'property':
  365. return validate(node.valueNode, schema, validationResult, matchingSchemas);
  366. }
  367. _validateNode();
  368. matchingSchemas.add({ node: node, schema: schema });
  369. function _validateNode() {
  370. function matchesType(type) {
  371. return node.type === type || (type === 'integer' && node.type === 'number' && node.isInteger);
  372. }
  373. if (Array.isArray(schema.type)) {
  374. if (!schema.type.some(matchesType)) {
  375. validationResult.problems.push({
  376. location: { offset: node.offset, length: node.length },
  377. message: schema.errorMessage || localize('typeArrayMismatchWarning', 'Incorrect type. Expected one of {0}.', schema.type.join(', '))
  378. });
  379. }
  380. }
  381. else if (schema.type) {
  382. if (!matchesType(schema.type)) {
  383. validationResult.problems.push({
  384. location: { offset: node.offset, length: node.length },
  385. message: schema.errorMessage || localize('typeMismatchWarning', 'Incorrect type. Expected "{0}".', schema.type)
  386. });
  387. }
  388. }
  389. if (Array.isArray(schema.allOf)) {
  390. for (var _i = 0, _a = schema.allOf; _i < _a.length; _i++) {
  391. var subSchemaRef = _a[_i];
  392. validate(node, asSchema(subSchemaRef), validationResult, matchingSchemas);
  393. }
  394. }
  395. var notSchema = asSchema(schema.not);
  396. if (notSchema) {
  397. var subValidationResult = new ValidationResult();
  398. var subMatchingSchemas = matchingSchemas.newSub();
  399. validate(node, notSchema, subValidationResult, subMatchingSchemas);
  400. if (!subValidationResult.hasProblems()) {
  401. validationResult.problems.push({
  402. location: { offset: node.offset, length: node.length },
  403. message: localize('notSchemaWarning', "Matches a schema that is not allowed.")
  404. });
  405. }
  406. for (var _b = 0, _c = subMatchingSchemas.schemas; _b < _c.length; _b++) {
  407. var ms = _c[_b];
  408. ms.inverted = !ms.inverted;
  409. matchingSchemas.add(ms);
  410. }
  411. }
  412. var testAlternatives = function (alternatives, maxOneMatch) {
  413. var matches = [];
  414. // remember the best match that is used for error messages
  415. var bestMatch = undefined;
  416. for (var _i = 0, alternatives_1 = alternatives; _i < alternatives_1.length; _i++) {
  417. var subSchemaRef = alternatives_1[_i];
  418. var subSchema = asSchema(subSchemaRef);
  419. var subValidationResult = new ValidationResult();
  420. var subMatchingSchemas = matchingSchemas.newSub();
  421. validate(node, subSchema, subValidationResult, subMatchingSchemas);
  422. if (!subValidationResult.hasProblems()) {
  423. matches.push(subSchema);
  424. }
  425. if (!bestMatch) {
  426. bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };
  427. }
  428. else {
  429. if (!maxOneMatch && !subValidationResult.hasProblems() && !bestMatch.validationResult.hasProblems()) {
  430. // no errors, both are equally good matches
  431. bestMatch.matchingSchemas.merge(subMatchingSchemas);
  432. bestMatch.validationResult.propertiesMatches += subValidationResult.propertiesMatches;
  433. bestMatch.validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
  434. }
  435. else {
  436. var compareResult = subValidationResult.compare(bestMatch.validationResult);
  437. if (compareResult > 0) {
  438. // our node is the best matching so far
  439. bestMatch = { schema: subSchema, validationResult: subValidationResult, matchingSchemas: subMatchingSchemas };
  440. }
  441. else if (compareResult === 0) {
  442. // there's already a best matching but we are as good
  443. bestMatch.matchingSchemas.merge(subMatchingSchemas);
  444. bestMatch.validationResult.mergeEnumValues(subValidationResult);
  445. }
  446. }
  447. }
  448. }
  449. if (matches.length > 1 && maxOneMatch) {
  450. validationResult.problems.push({
  451. location: { offset: node.offset, length: 1 },
  452. message: localize('oneOfWarning', "Matches multiple schemas when only one must validate.")
  453. });
  454. }
  455. if (bestMatch) {
  456. validationResult.merge(bestMatch.validationResult);
  457. validationResult.propertiesMatches += bestMatch.validationResult.propertiesMatches;
  458. validationResult.propertiesValueMatches += bestMatch.validationResult.propertiesValueMatches;
  459. matchingSchemas.merge(bestMatch.matchingSchemas);
  460. }
  461. return matches.length;
  462. };
  463. if (Array.isArray(schema.anyOf)) {
  464. testAlternatives(schema.anyOf, false);
  465. }
  466. if (Array.isArray(schema.oneOf)) {
  467. testAlternatives(schema.oneOf, true);
  468. }
  469. var testBranch = function (schema) {
  470. var subValidationResult = new ValidationResult();
  471. var subMatchingSchemas = matchingSchemas.newSub();
  472. validate(node, asSchema(schema), subValidationResult, subMatchingSchemas);
  473. validationResult.merge(subValidationResult);
  474. validationResult.propertiesMatches += subValidationResult.propertiesMatches;
  475. validationResult.propertiesValueMatches += subValidationResult.propertiesValueMatches;
  476. matchingSchemas.merge(subMatchingSchemas);
  477. };
  478. var testCondition = function (ifSchema, thenSchema, elseSchema) {
  479. var subSchema = asSchema(ifSchema);
  480. var subValidationResult = new ValidationResult();
  481. var subMatchingSchemas = matchingSchemas.newSub();
  482. validate(node, subSchema, subValidationResult, subMatchingSchemas);
  483. matchingSchemas.merge(subMatchingSchemas);
  484. if (!subValidationResult.hasProblems()) {
  485. if (thenSchema) {
  486. testBranch(thenSchema);
  487. }
  488. }
  489. else if (elseSchema) {
  490. testBranch(elseSchema);
  491. }
  492. };
  493. var ifSchema = asSchema(schema.if);
  494. if (ifSchema) {
  495. testCondition(ifSchema, asSchema(schema.then), asSchema(schema.else));
  496. }
  497. if (Array.isArray(schema.enum)) {
  498. var val = getNodeValue(node);
  499. var enumValueMatch = false;
  500. for (var _d = 0, _e = schema.enum; _d < _e.length; _d++) {
  501. var e = _e[_d];
  502. if (objects_1.equals(val, e)) {
  503. enumValueMatch = true;
  504. break;
  505. }
  506. }
  507. validationResult.enumValues = schema.enum;
  508. validationResult.enumValueMatch = enumValueMatch;
  509. if (!enumValueMatch) {
  510. validationResult.problems.push({
  511. location: { offset: node.offset, length: node.length },
  512. code: jsonLanguageTypes_1.ErrorCode.EnumValueMismatch,
  513. message: schema.errorMessage || localize('enumWarning', 'Value is not accepted. Valid values: {0}.', schema.enum.map(function (v) { return JSON.stringify(v); }).join(', '))
  514. });
  515. }
  516. }
  517. if (objects_1.isDefined(schema.const)) {
  518. var val = getNodeValue(node);
  519. if (!objects_1.equals(val, schema.const)) {
  520. validationResult.problems.push({
  521. location: { offset: node.offset, length: node.length },
  522. code: jsonLanguageTypes_1.ErrorCode.EnumValueMismatch,
  523. message: schema.errorMessage || localize('constWarning', 'Value must be {0}.', JSON.stringify(schema.const))
  524. });
  525. validationResult.enumValueMatch = false;
  526. }
  527. else {
  528. validationResult.enumValueMatch = true;
  529. }
  530. validationResult.enumValues = [schema.const];
  531. }
  532. if (schema.deprecationMessage && node.parent) {
  533. validationResult.problems.push({
  534. location: { offset: node.parent.offset, length: node.parent.length },
  535. severity: jsonLanguageTypes_1.DiagnosticSeverity.Warning,
  536. message: schema.deprecationMessage,
  537. code: jsonLanguageTypes_1.ErrorCode.Deprecated
  538. });
  539. }
  540. }
  541. function _validateNumberNode(node, schema, validationResult, matchingSchemas) {
  542. var val = node.value;
  543. function normalizeFloats(float) {
  544. var _a;
  545. var parts = /^(-?\d+)(?:\.(\d+))?(?:e([-+]\d+))?$/.exec(float.toString());
  546. return parts && {
  547. value: Number(parts[1] + (parts[2] || '')),
  548. multiplier: (((_a = parts[2]) === null || _a === void 0 ? void 0 : _a.length) || 0) - (parseInt(parts[3]) || 0)
  549. };
  550. }
  551. ;
  552. if (objects_1.isNumber(schema.multipleOf)) {
  553. var remainder = -1;
  554. if (Number.isInteger(schema.multipleOf)) {
  555. remainder = val % schema.multipleOf;
  556. }
  557. else {
  558. var normMultipleOf = normalizeFloats(schema.multipleOf);
  559. var normValue = normalizeFloats(val);
  560. if (normMultipleOf && normValue) {
  561. var multiplier = Math.pow(10, Math.abs(normValue.multiplier - normMultipleOf.multiplier));
  562. if (normValue.multiplier < normMultipleOf.multiplier) {
  563. normValue.value *= multiplier;
  564. }
  565. else {
  566. normMultipleOf.value *= multiplier;
  567. }
  568. remainder = normValue.value % normMultipleOf.value;
  569. }
  570. }
  571. if (remainder !== 0) {
  572. validationResult.problems.push({
  573. location: { offset: node.offset, length: node.length },
  574. message: localize('multipleOfWarning', 'Value is not divisible by {0}.', schema.multipleOf)
  575. });
  576. }
  577. }
  578. function getExclusiveLimit(limit, exclusive) {
  579. if (objects_1.isNumber(exclusive)) {
  580. return exclusive;
  581. }
  582. if (objects_1.isBoolean(exclusive) && exclusive) {
  583. return limit;
  584. }
  585. return undefined;
  586. }
  587. function getLimit(limit, exclusive) {
  588. if (!objects_1.isBoolean(exclusive) || !exclusive) {
  589. return limit;
  590. }
  591. return undefined;
  592. }
  593. var exclusiveMinimum = getExclusiveLimit(schema.minimum, schema.exclusiveMinimum);
  594. if (objects_1.isNumber(exclusiveMinimum) && val <= exclusiveMinimum) {
  595. validationResult.problems.push({
  596. location: { offset: node.offset, length: node.length },
  597. message: localize('exclusiveMinimumWarning', 'Value is below the exclusive minimum of {0}.', exclusiveMinimum)
  598. });
  599. }
  600. var exclusiveMaximum = getExclusiveLimit(schema.maximum, schema.exclusiveMaximum);
  601. if (objects_1.isNumber(exclusiveMaximum) && val >= exclusiveMaximum) {
  602. validationResult.problems.push({
  603. location: { offset: node.offset, length: node.length },
  604. message: localize('exclusiveMaximumWarning', 'Value is above the exclusive maximum of {0}.', exclusiveMaximum)
  605. });
  606. }
  607. var minimum = getLimit(schema.minimum, schema.exclusiveMinimum);
  608. if (objects_1.isNumber(minimum) && val < minimum) {
  609. validationResult.problems.push({
  610. location: { offset: node.offset, length: node.length },
  611. message: localize('minimumWarning', 'Value is below the minimum of {0}.', minimum)
  612. });
  613. }
  614. var maximum = getLimit(schema.maximum, schema.exclusiveMaximum);
  615. if (objects_1.isNumber(maximum) && val > maximum) {
  616. validationResult.problems.push({
  617. location: { offset: node.offset, length: node.length },
  618. message: localize('maximumWarning', 'Value is above the maximum of {0}.', maximum)
  619. });
  620. }
  621. }
  622. function _validateStringNode(node, schema, validationResult, matchingSchemas) {
  623. if (objects_1.isNumber(schema.minLength) && node.value.length < schema.minLength) {
  624. validationResult.problems.push({
  625. location: { offset: node.offset, length: node.length },
  626. message: localize('minLengthWarning', 'String is shorter than the minimum length of {0}.', schema.minLength)
  627. });
  628. }
  629. if (objects_1.isNumber(schema.maxLength) && node.value.length > schema.maxLength) {
  630. validationResult.problems.push({
  631. location: { offset: node.offset, length: node.length },
  632. message: localize('maxLengthWarning', 'String is longer than the maximum length of {0}.', schema.maxLength)
  633. });
  634. }
  635. if (objects_1.isString(schema.pattern)) {
  636. var regex = strings_1.extendedRegExp(schema.pattern);
  637. if (!regex.test(node.value)) {
  638. validationResult.problems.push({
  639. location: { offset: node.offset, length: node.length },
  640. message: schema.patternErrorMessage || schema.errorMessage || localize('patternWarning', 'String does not match the pattern of "{0}".', schema.pattern)
  641. });
  642. }
  643. }
  644. if (schema.format) {
  645. switch (schema.format) {
  646. case 'uri':
  647. case 'uri-reference':
  648. {
  649. var errorMessage = void 0;
  650. if (!node.value) {
  651. errorMessage = localize('uriEmpty', 'URI expected.');
  652. }
  653. else {
  654. var match = /^(([^:/?#]+?):)?(\/\/([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/.exec(node.value);
  655. if (!match) {
  656. errorMessage = localize('uriMissing', 'URI is expected.');
  657. }
  658. else if (!match[2] && schema.format === 'uri') {
  659. errorMessage = localize('uriSchemeMissing', 'URI with a scheme is expected.');
  660. }
  661. }
  662. if (errorMessage) {
  663. validationResult.problems.push({
  664. location: { offset: node.offset, length: node.length },
  665. message: schema.patternErrorMessage || schema.errorMessage || localize('uriFormatWarning', 'String is not a URI: {0}', errorMessage)
  666. });
  667. }
  668. }
  669. break;
  670. case 'color-hex':
  671. case 'date-time':
  672. case 'date':
  673. case 'time':
  674. case 'email':
  675. var format = formats[schema.format];
  676. if (!node.value || !format.pattern.exec(node.value)) {
  677. validationResult.problems.push({
  678. location: { offset: node.offset, length: node.length },
  679. message: schema.patternErrorMessage || schema.errorMessage || format.errorMessage
  680. });
  681. }
  682. default:
  683. }
  684. }
  685. }
  686. function _validateArrayNode(node, schema, validationResult, matchingSchemas) {
  687. if (Array.isArray(schema.items)) {
  688. var subSchemas = schema.items;
  689. for (var index = 0; index < subSchemas.length; index++) {
  690. var subSchemaRef = subSchemas[index];
  691. var subSchema = asSchema(subSchemaRef);
  692. var itemValidationResult = new ValidationResult();
  693. var item = node.items[index];
  694. if (item) {
  695. validate(item, subSchema, itemValidationResult, matchingSchemas);
  696. validationResult.mergePropertyMatch(itemValidationResult);
  697. }
  698. else if (node.items.length >= subSchemas.length) {
  699. validationResult.propertiesValueMatches++;
  700. }
  701. }
  702. if (node.items.length > subSchemas.length) {
  703. if (typeof schema.additionalItems === 'object') {
  704. for (var i = subSchemas.length; i < node.items.length; i++) {
  705. var itemValidationResult = new ValidationResult();
  706. validate(node.items[i], schema.additionalItems, itemValidationResult, matchingSchemas);
  707. validationResult.mergePropertyMatch(itemValidationResult);
  708. }
  709. }
  710. else if (schema.additionalItems === false) {
  711. validationResult.problems.push({
  712. location: { offset: node.offset, length: node.length },
  713. message: localize('additionalItemsWarning', 'Array has too many items according to schema. Expected {0} or fewer.', subSchemas.length)
  714. });
  715. }
  716. }
  717. }
  718. else {
  719. var itemSchema = asSchema(schema.items);
  720. if (itemSchema) {
  721. for (var _i = 0, _a = node.items; _i < _a.length; _i++) {
  722. var item = _a[_i];
  723. var itemValidationResult = new ValidationResult();
  724. validate(item, itemSchema, itemValidationResult, matchingSchemas);
  725. validationResult.mergePropertyMatch(itemValidationResult);
  726. }
  727. }
  728. }
  729. var containsSchema = asSchema(schema.contains);
  730. if (containsSchema) {
  731. var doesContain = node.items.some(function (item) {
  732. var itemValidationResult = new ValidationResult();
  733. validate(item, containsSchema, itemValidationResult, NoOpSchemaCollector.instance);
  734. return !itemValidationResult.hasProblems();
  735. });
  736. if (!doesContain) {
  737. validationResult.problems.push({
  738. location: { offset: node.offset, length: node.length },
  739. message: schema.errorMessage || localize('requiredItemMissingWarning', 'Array does not contain required item.')
  740. });
  741. }
  742. }
  743. if (objects_1.isNumber(schema.minItems) && node.items.length < schema.minItems) {
  744. validationResult.problems.push({
  745. location: { offset: node.offset, length: node.length },
  746. message: localize('minItemsWarning', 'Array has too few items. Expected {0} or more.', schema.minItems)
  747. });
  748. }
  749. if (objects_1.isNumber(schema.maxItems) && node.items.length > schema.maxItems) {
  750. validationResult.problems.push({
  751. location: { offset: node.offset, length: node.length },
  752. message: localize('maxItemsWarning', 'Array has too many items. Expected {0} or fewer.', schema.maxItems)
  753. });
  754. }
  755. if (schema.uniqueItems === true) {
  756. var values_1 = getNodeValue(node);
  757. var duplicates = values_1.some(function (value, index) {
  758. return index !== values_1.lastIndexOf(value);
  759. });
  760. if (duplicates) {
  761. validationResult.problems.push({
  762. location: { offset: node.offset, length: node.length },
  763. message: localize('uniqueItemsWarning', 'Array has duplicate items.')
  764. });
  765. }
  766. }
  767. }
  768. function _validateObjectNode(node, schema, validationResult, matchingSchemas) {
  769. var seenKeys = Object.create(null);
  770. var unprocessedProperties = [];
  771. for (var _i = 0, _a = node.properties; _i < _a.length; _i++) {
  772. var propertyNode = _a[_i];
  773. var key = propertyNode.keyNode.value;
  774. seenKeys[key] = propertyNode.valueNode;
  775. unprocessedProperties.push(key);
  776. }
  777. if (Array.isArray(schema.required)) {
  778. for (var _b = 0, _c = schema.required; _b < _c.length; _b++) {
  779. var propertyName = _c[_b];
  780. if (!seenKeys[propertyName]) {
  781. var keyNode = node.parent && node.parent.type === 'property' && node.parent.keyNode;
  782. var location = keyNode ? { offset: keyNode.offset, length: keyNode.length } : { offset: node.offset, length: 1 };
  783. validationResult.problems.push({
  784. location: location,
  785. message: localize('MissingRequiredPropWarning', 'Missing property "{0}".', propertyName)
  786. });
  787. }
  788. }
  789. }
  790. var propertyProcessed = function (prop) {
  791. var index = unprocessedProperties.indexOf(prop);
  792. while (index >= 0) {
  793. unprocessedProperties.splice(index, 1);
  794. index = unprocessedProperties.indexOf(prop);
  795. }
  796. };
  797. if (schema.properties) {
  798. for (var _d = 0, _e = Object.keys(schema.properties); _d < _e.length; _d++) {
  799. var propertyName = _e[_d];
  800. propertyProcessed(propertyName);
  801. var propertySchema = schema.properties[propertyName];
  802. var child = seenKeys[propertyName];
  803. if (child) {
  804. if (objects_1.isBoolean(propertySchema)) {
  805. if (!propertySchema) {
  806. var propertyNode = child.parent;
  807. validationResult.problems.push({
  808. location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
  809. message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
  810. });
  811. }
  812. else {
  813. validationResult.propertiesMatches++;
  814. validationResult.propertiesValueMatches++;
  815. }
  816. }
  817. else {
  818. var propertyValidationResult = new ValidationResult();
  819. validate(child, propertySchema, propertyValidationResult, matchingSchemas);
  820. validationResult.mergePropertyMatch(propertyValidationResult);
  821. }
  822. }
  823. }
  824. }
  825. if (schema.patternProperties) {
  826. for (var _f = 0, _g = Object.keys(schema.patternProperties); _f < _g.length; _f++) {
  827. var propertyPattern = _g[_f];
  828. var regex = strings_1.extendedRegExp(propertyPattern);
  829. for (var _h = 0, _j = unprocessedProperties.slice(0); _h < _j.length; _h++) {
  830. var propertyName = _j[_h];
  831. if (regex.test(propertyName)) {
  832. propertyProcessed(propertyName);
  833. var child = seenKeys[propertyName];
  834. if (child) {
  835. var propertySchema = schema.patternProperties[propertyPattern];
  836. if (objects_1.isBoolean(propertySchema)) {
  837. if (!propertySchema) {
  838. var propertyNode = child.parent;
  839. validationResult.problems.push({
  840. location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
  841. message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
  842. });
  843. }
  844. else {
  845. validationResult.propertiesMatches++;
  846. validationResult.propertiesValueMatches++;
  847. }
  848. }
  849. else {
  850. var propertyValidationResult = new ValidationResult();
  851. validate(child, propertySchema, propertyValidationResult, matchingSchemas);
  852. validationResult.mergePropertyMatch(propertyValidationResult);
  853. }
  854. }
  855. }
  856. }
  857. }
  858. }
  859. if (typeof schema.additionalProperties === 'object') {
  860. for (var _k = 0, unprocessedProperties_1 = unprocessedProperties; _k < unprocessedProperties_1.length; _k++) {
  861. var propertyName = unprocessedProperties_1[_k];
  862. var child = seenKeys[propertyName];
  863. if (child) {
  864. var propertyValidationResult = new ValidationResult();
  865. validate(child, schema.additionalProperties, propertyValidationResult, matchingSchemas);
  866. validationResult.mergePropertyMatch(propertyValidationResult);
  867. }
  868. }
  869. }
  870. else if (schema.additionalProperties === false) {
  871. if (unprocessedProperties.length > 0) {
  872. for (var _l = 0, unprocessedProperties_2 = unprocessedProperties; _l < unprocessedProperties_2.length; _l++) {
  873. var propertyName = unprocessedProperties_2[_l];
  874. var child = seenKeys[propertyName];
  875. if (child) {
  876. var propertyNode = child.parent;
  877. validationResult.problems.push({
  878. location: { offset: propertyNode.keyNode.offset, length: propertyNode.keyNode.length },
  879. message: schema.errorMessage || localize('DisallowedExtraPropWarning', 'Property {0} is not allowed.', propertyName)
  880. });
  881. }
  882. }
  883. }
  884. }
  885. if (objects_1.isNumber(schema.maxProperties)) {
  886. if (node.properties.length > schema.maxProperties) {
  887. validationResult.problems.push({
  888. location: { offset: node.offset, length: node.length },
  889. message: localize('MaxPropWarning', 'Object has more properties than limit of {0}.', schema.maxProperties)
  890. });
  891. }
  892. }
  893. if (objects_1.isNumber(schema.minProperties)) {
  894. if (node.properties.length < schema.minProperties) {
  895. validationResult.problems.push({
  896. location: { offset: node.offset, length: node.length },
  897. message: localize('MinPropWarning', 'Object has fewer properties than the required number of {0}', schema.minProperties)
  898. });
  899. }
  900. }
  901. if (schema.dependencies) {
  902. for (var _m = 0, _o = Object.keys(schema.dependencies); _m < _o.length; _m++) {
  903. var key = _o[_m];
  904. var prop = seenKeys[key];
  905. if (prop) {
  906. var propertyDep = schema.dependencies[key];
  907. if (Array.isArray(propertyDep)) {
  908. for (var _p = 0, propertyDep_1 = propertyDep; _p < propertyDep_1.length; _p++) {
  909. var requiredProp = propertyDep_1[_p];
  910. if (!seenKeys[requiredProp]) {
  911. validationResult.problems.push({
  912. location: { offset: node.offset, length: node.length },
  913. message: localize('RequiredDependentPropWarning', 'Object is missing property {0} required by property {1}.', requiredProp, key)
  914. });
  915. }
  916. else {
  917. validationResult.propertiesValueMatches++;
  918. }
  919. }
  920. }
  921. else {
  922. var propertySchema = asSchema(propertyDep);
  923. if (propertySchema) {
  924. var propertyValidationResult = new ValidationResult();
  925. validate(node, propertySchema, propertyValidationResult, matchingSchemas);
  926. validationResult.mergePropertyMatch(propertyValidationResult);
  927. }
  928. }
  929. }
  930. }
  931. }
  932. var propertyNames = asSchema(schema.propertyNames);
  933. if (propertyNames) {
  934. for (var _q = 0, _r = node.properties; _q < _r.length; _q++) {
  935. var f = _r[_q];
  936. var key = f.keyNode;
  937. if (key) {
  938. validate(key, propertyNames, validationResult, NoOpSchemaCollector.instance);
  939. }
  940. }
  941. }
  942. }
  943. }
  944. function parse(textDocument, config) {
  945. var problems = [];
  946. var lastProblemOffset = -1;
  947. var text = textDocument.getText();
  948. var scanner = Json.createScanner(text, false);
  949. var commentRanges = config && config.collectComments ? [] : undefined;
  950. function _scanNext() {
  951. while (true) {
  952. var token_1 = scanner.scan();
  953. _checkScanError();
  954. switch (token_1) {
  955. case 12 /* LineCommentTrivia */:
  956. case 13 /* BlockCommentTrivia */:
  957. if (Array.isArray(commentRanges)) {
  958. commentRanges.push(jsonLanguageTypes_1.Range.create(textDocument.positionAt(scanner.getTokenOffset()), textDocument.positionAt(scanner.getTokenOffset() + scanner.getTokenLength())));
  959. }
  960. break;
  961. case 15 /* Trivia */:
  962. case 14 /* LineBreakTrivia */:
  963. break;
  964. default:
  965. return token_1;
  966. }
  967. }
  968. }
  969. function _accept(token) {
  970. if (scanner.getToken() === token) {
  971. _scanNext();
  972. return true;
  973. }
  974. return false;
  975. }
  976. function _errorAtRange(message, code, startOffset, endOffset, severity) {
  977. if (severity === void 0) { severity = jsonLanguageTypes_1.DiagnosticSeverity.Error; }
  978. if (problems.length === 0 || startOffset !== lastProblemOffset) {
  979. var range = jsonLanguageTypes_1.Range.create(textDocument.positionAt(startOffset), textDocument.positionAt(endOffset));
  980. problems.push(jsonLanguageTypes_1.Diagnostic.create(range, message, severity, code, textDocument.languageId));
  981. lastProblemOffset = startOffset;
  982. }
  983. }
  984. function _error(message, code, node, skipUntilAfter, skipUntil) {
  985. if (node === void 0) { node = undefined; }
  986. if (skipUntilAfter === void 0) { skipUntilAfter = []; }
  987. if (skipUntil === void 0) { skipUntil = []; }
  988. var start = scanner.getTokenOffset();
  989. var end = scanner.getTokenOffset() + scanner.getTokenLength();
  990. if (start === end && start > 0) {
  991. start--;
  992. while (start > 0 && /\s/.test(text.charAt(start))) {
  993. start--;
  994. }
  995. end = start + 1;
  996. }
  997. _errorAtRange(message, code, start, end);
  998. if (node) {
  999. _finalize(node, false);
  1000. }
  1001. if (skipUntilAfter.length + skipUntil.length > 0) {
  1002. var token_2 = scanner.getToken();
  1003. while (token_2 !== 17 /* EOF */) {
  1004. if (skipUntilAfter.indexOf(token_2) !== -1) {
  1005. _scanNext();
  1006. break;
  1007. }
  1008. else if (skipUntil.indexOf(token_2) !== -1) {
  1009. break;
  1010. }
  1011. token_2 = _scanNext();
  1012. }
  1013. }
  1014. return node;
  1015. }
  1016. function _checkScanError() {
  1017. switch (scanner.getTokenError()) {
  1018. case 4 /* InvalidUnicode */:
  1019. _error(localize('InvalidUnicode', 'Invalid unicode sequence in string.'), jsonLanguageTypes_1.ErrorCode.InvalidUnicode);
  1020. return true;
  1021. case 5 /* InvalidEscapeCharacter */:
  1022. _error(localize('InvalidEscapeCharacter', 'Invalid escape character in string.'), jsonLanguageTypes_1.ErrorCode.InvalidEscapeCharacter);
  1023. return true;
  1024. case 3 /* UnexpectedEndOfNumber */:
  1025. _error(localize('UnexpectedEndOfNumber', 'Unexpected end of number.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfNumber);
  1026. return true;
  1027. case 1 /* UnexpectedEndOfComment */:
  1028. _error(localize('UnexpectedEndOfComment', 'Unexpected end of comment.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfComment);
  1029. return true;
  1030. case 2 /* UnexpectedEndOfString */:
  1031. _error(localize('UnexpectedEndOfString', 'Unexpected end of string.'), jsonLanguageTypes_1.ErrorCode.UnexpectedEndOfString);
  1032. return true;
  1033. case 6 /* InvalidCharacter */:
  1034. _error(localize('InvalidCharacter', 'Invalid characters in string. Control characters must be escaped.'), jsonLanguageTypes_1.ErrorCode.InvalidCharacter);
  1035. return true;
  1036. }
  1037. return false;
  1038. }
  1039. function _finalize(node, scanNext) {
  1040. node.length = scanner.getTokenOffset() + scanner.getTokenLength() - node.offset;
  1041. if (scanNext) {
  1042. _scanNext();
  1043. }
  1044. return node;
  1045. }
  1046. function _parseArray(parent) {
  1047. if (scanner.getToken() !== 3 /* OpenBracketToken */) {
  1048. return undefined;
  1049. }
  1050. var node = new ArrayASTNodeImpl(parent, scanner.getTokenOffset());
  1051. _scanNext(); // consume OpenBracketToken
  1052. var count = 0;
  1053. var needsComma = false;
  1054. while (scanner.getToken() !== 4 /* CloseBracketToken */ && scanner.getToken() !== 17 /* EOF */) {
  1055. if (scanner.getToken() === 5 /* CommaToken */) {
  1056. if (!needsComma) {
  1057. _error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected);
  1058. }
  1059. var commaOffset = scanner.getTokenOffset();
  1060. _scanNext(); // consume comma
  1061. if (scanner.getToken() === 4 /* CloseBracketToken */) {
  1062. if (needsComma) {
  1063. _errorAtRange(localize('TrailingComma', 'Trailing comma'), jsonLanguageTypes_1.ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
  1064. }
  1065. continue;
  1066. }
  1067. }
  1068. else if (needsComma) {
  1069. _error(localize('ExpectedComma', 'Expected comma'), jsonLanguageTypes_1.ErrorCode.CommaExpected);
  1070. }
  1071. var item = _parseValue(node);
  1072. if (!item) {
  1073. _error(localize('PropertyExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, undefined, [], [4 /* CloseBracketToken */, 5 /* CommaToken */]);
  1074. }
  1075. else {
  1076. node.items.push(item);
  1077. }
  1078. needsComma = true;
  1079. }
  1080. if (scanner.getToken() !== 4 /* CloseBracketToken */) {
  1081. return _error(localize('ExpectedCloseBracket', 'Expected comma or closing bracket'), jsonLanguageTypes_1.ErrorCode.CommaOrCloseBacketExpected, node);
  1082. }
  1083. return _finalize(node, true);
  1084. }
  1085. var keyPlaceholder = new StringASTNodeImpl(undefined, 0, 0);
  1086. function _parseProperty(parent, keysSeen) {
  1087. var node = new PropertyASTNodeImpl(parent, scanner.getTokenOffset(), keyPlaceholder);
  1088. var key = _parseString(node);
  1089. if (!key) {
  1090. if (scanner.getToken() === 16 /* Unknown */) {
  1091. // give a more helpful error message
  1092. _error(localize('DoubleQuotesExpected', 'Property keys must be doublequoted'), jsonLanguageTypes_1.ErrorCode.Undefined);
  1093. var keyNode = new StringASTNodeImpl(node, scanner.getTokenOffset(), scanner.getTokenLength());
  1094. keyNode.value = scanner.getTokenValue();
  1095. key = keyNode;
  1096. _scanNext(); // consume Unknown
  1097. }
  1098. else {
  1099. return undefined;
  1100. }
  1101. }
  1102. node.keyNode = key;
  1103. var seen = keysSeen[key.value];
  1104. if (seen) {
  1105. _errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), jsonLanguageTypes_1.ErrorCode.DuplicateKey, node.keyNode.offset, node.keyNode.offset + node.keyNode.length, jsonLanguageTypes_1.DiagnosticSeverity.Warning);
  1106. if (typeof seen === 'object') {
  1107. _errorAtRange(localize('DuplicateKeyWarning', "Duplicate object key"), jsonLanguageTypes_1.ErrorCode.DuplicateKey, seen.keyNode.offset, seen.keyNode.offset + seen.keyNode.length, jsonLanguageTypes_1.DiagnosticSeverity.Warning);
  1108. }
  1109. keysSeen[key.value] = true; // if the same key is duplicate again, avoid duplicate error reporting
  1110. }
  1111. else {
  1112. keysSeen[key.value] = node;
  1113. }
  1114. if (scanner.getToken() === 6 /* ColonToken */) {
  1115. node.colonOffset = scanner.getTokenOffset();
  1116. _scanNext(); // consume ColonToken
  1117. }
  1118. else {
  1119. _error(localize('ColonExpected', 'Colon expected'), jsonLanguageTypes_1.ErrorCode.ColonExpected);
  1120. if (scanner.getToken() === 10 /* StringLiteral */ && textDocument.positionAt(key.offset + key.length).line < textDocument.positionAt(scanner.getTokenOffset()).line) {
  1121. node.length = key.length;
  1122. return node;
  1123. }
  1124. }
  1125. var value = _parseValue(node);
  1126. if (!value) {
  1127. return _error(localize('ValueExpected', 'Value expected'), jsonLanguageTypes_1.ErrorCode.ValueExpected, node, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
  1128. }
  1129. node.valueNode = value;
  1130. node.length = value.offset + value.length - node.offset;
  1131. return node;
  1132. }
  1133. function _parseObject(parent) {
  1134. if (scanner.getToken() !== 1 /* OpenBraceToken */) {
  1135. return undefined;
  1136. }
  1137. var node = new ObjectASTNodeImpl(parent, scanner.getTokenOffset());
  1138. var keysSeen = Object.create(null);
  1139. _scanNext(); // consume OpenBraceToken
  1140. var needsComma = false;
  1141. while (scanner.getToken() !== 2 /* CloseBraceToken */ && scanner.getToken() !== 17 /* EOF */) {
  1142. if (scanner.getToken() === 5 /* CommaToken */) {
  1143. if (!needsComma) {
  1144. _error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected);
  1145. }
  1146. var commaOffset = scanner.getTokenOffset();
  1147. _scanNext(); // consume comma
  1148. if (scanner.getToken() === 2 /* CloseBraceToken */) {
  1149. if (needsComma) {
  1150. _errorAtRange(localize('TrailingComma', 'Trailing comma'), jsonLanguageTypes_1.ErrorCode.TrailingComma, commaOffset, commaOffset + 1);
  1151. }
  1152. continue;
  1153. }
  1154. }
  1155. else if (needsComma) {
  1156. _error(localize('ExpectedComma', 'Expected comma'), jsonLanguageTypes_1.ErrorCode.CommaExpected);
  1157. }
  1158. var property = _parseProperty(node, keysSeen);
  1159. if (!property) {
  1160. _error(localize('PropertyExpected', 'Property expected'), jsonLanguageTypes_1.ErrorCode.PropertyExpected, undefined, [], [2 /* CloseBraceToken */, 5 /* CommaToken */]);
  1161. }
  1162. else {
  1163. node.properties.push(property);
  1164. }
  1165. needsComma = true;
  1166. }
  1167. if (scanner.getToken() !== 2 /* CloseBraceToken */) {
  1168. return _error(localize('ExpectedCloseBrace', 'Expected comma or closing brace'), jsonLanguageTypes_1.ErrorCode.CommaOrCloseBraceExpected, node);
  1169. }
  1170. return _finalize(node, true);
  1171. }
  1172. function _parseString(parent) {
  1173. if (scanner.getToken() !== 10 /* StringLiteral */) {
  1174. return undefined;
  1175. }
  1176. var node = new StringASTNodeImpl(parent, scanner.getTokenOffset());
  1177. node.value = scanner.getTokenValue();
  1178. return _finalize(node, true);
  1179. }
  1180. function _parseNumber(parent) {
  1181. if (scanner.getToken() !== 11 /* NumericLiteral */) {
  1182. return undefined;
  1183. }
  1184. var node = new NumberASTNodeImpl(parent, scanner.getTokenOffset());
  1185. if (scanner.getTokenError() === 0 /* None */) {
  1186. var tokenValue = scanner.getTokenValue();
  1187. try {
  1188. var numberValue = JSON.parse(tokenValue);
  1189. if (!objects_1.isNumber(numberValue)) {
  1190. return _error(localize('InvalidNumberFormat', 'Invalid number format.'), jsonLanguageTypes_1.ErrorCode.Undefined, node);
  1191. }
  1192. node.value = numberValue;
  1193. }
  1194. catch (e) {
  1195. return _error(localize('InvalidNumberFormat', 'Invalid number format.'), jsonLanguageTypes_1.ErrorCode.Undefined, node);
  1196. }
  1197. node.isInteger = tokenValue.indexOf('.') === -1;
  1198. }
  1199. return _finalize(node, true);
  1200. }
  1201. function _parseLiteral(parent) {
  1202. var node;
  1203. switch (scanner.getToken()) {
  1204. case 7 /* NullKeyword */:
  1205. return _finalize(new NullASTNodeImpl(parent, scanner.getTokenOffset()), true);
  1206. case 8 /* TrueKeyword */:
  1207. return _finalize(new BooleanASTNodeImpl(parent, true, scanner.getTokenOffset()), true);
  1208. case 9 /* FalseKeyword */:
  1209. return _finalize(new BooleanASTNodeImpl(parent, false, scanner.getTokenOffset()), true);
  1210. default:
  1211. return undefined;
  1212. }
  1213. }
  1214. function _parseValue(parent) {
  1215. return _parseArray(parent) || _parseObject(parent) || _parseString(parent) || _parseNumber(parent) || _parseLiteral(parent);
  1216. }
  1217. var _root = undefined;
  1218. var token = _scanNext();
  1219. if (token !== 17 /* EOF */) {
  1220. _root = _parseValue(_root);
  1221. if (!_root) {
  1222. _error(localize('Invalid symbol', 'Expected a JSON object, array or literal.'), jsonLanguageTypes_1.ErrorCode.Undefined);
  1223. }
  1224. else if (scanner.getToken() !== 17 /* EOF */) {
  1225. _error(localize('End of file expected', 'End of file expected.'), jsonLanguageTypes_1.ErrorCode.Undefined);
  1226. }
  1227. }
  1228. return new JSONDocument(_root, problems, commentRanges);
  1229. }
  1230. exports.parse = parse;
  1231. });