Dashboard sipadu mbip
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

parseMap.js 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.default = parseMap;
  6. var _constants = require("../constants");
  7. var _PlainValue = _interopRequireDefault(require("../cst/PlainValue"));
  8. var _errors = require("../errors");
  9. var _Map = _interopRequireDefault(require("./Map"));
  10. var _Merge = _interopRequireWildcard(require("./Merge"));
  11. var _Pair = _interopRequireDefault(require("./Pair"));
  12. var _parseUtils = require("./parseUtils");
  13. var _Alias = _interopRequireDefault(require("./Alias"));
  14. var _Collection = _interopRequireDefault(require("./Collection"));
  15. function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
  16. function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; if (obj != null) { var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  17. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  18. function parseMap(doc, cst) {
  19. if (cst.type !== _constants.Type.MAP && cst.type !== _constants.Type.FLOW_MAP) {
  20. const msg = `A ${cst.type} node cannot be resolved as a mapping`;
  21. doc.errors.push(new _errors.YAMLSyntaxError(cst, msg));
  22. return null;
  23. }
  24. const {
  25. comments,
  26. items
  27. } = cst.type === _constants.Type.FLOW_MAP ? resolveFlowMapItems(doc, cst) : resolveBlockMapItems(doc, cst);
  28. const map = new _Map.default();
  29. map.items = items;
  30. (0, _parseUtils.resolveComments)(map, comments);
  31. let hasCollectionKey = false;
  32. for (let i = 0; i < items.length; ++i) {
  33. const {
  34. key: iKey
  35. } = items[i];
  36. if (iKey instanceof _Collection.default) hasCollectionKey = true;
  37. if (doc.schema.merge && iKey && iKey.value === _Merge.MERGE_KEY) {
  38. items[i] = new _Merge.default(items[i]);
  39. const sources = items[i].value.items;
  40. let error = null;
  41. sources.some(node => {
  42. if (node instanceof _Alias.default) {
  43. // During parsing, alias sources are CST nodes; to account for
  44. // circular references their resolved values can't be used here.
  45. const {
  46. type
  47. } = node.source;
  48. if (type === _constants.Type.MAP || type === _constants.Type.FLOW_MAP) return false;
  49. return error = 'Merge nodes aliases can only point to maps';
  50. }
  51. return error = 'Merge nodes can only have Alias nodes as values';
  52. });
  53. if (error) doc.errors.push(new _errors.YAMLSemanticError(cst, error));
  54. } else {
  55. for (let j = i + 1; j < items.length; ++j) {
  56. const {
  57. key: jKey
  58. } = items[j];
  59. if (iKey === jKey || iKey && jKey && Object.prototype.hasOwnProperty.call(iKey, 'value') && iKey.value === jKey.value) {
  60. const msg = `Map keys must be unique; "${iKey}" is repeated`;
  61. doc.errors.push(new _errors.YAMLSemanticError(cst, msg));
  62. break;
  63. }
  64. }
  65. }
  66. }
  67. if (hasCollectionKey && !doc.options.mapAsMap) {
  68. const warn = 'Keys with collection values will be stringified as YAML due to JS Object restrictions. Use mapAsMap: true to avoid this.';
  69. doc.warnings.push(new _errors.YAMLWarning(cst, warn));
  70. }
  71. cst.resolved = map;
  72. return map;
  73. }
  74. const valueHasPairComment = ({
  75. context: {
  76. lineStart,
  77. node,
  78. src
  79. },
  80. props
  81. }) => {
  82. if (props.length === 0) return false;
  83. const {
  84. start
  85. } = props[0];
  86. if (node && start > node.valueRange.start) return false;
  87. if (src[start] !== _constants.Char.COMMENT) return false;
  88. for (let i = lineStart; i < start; ++i) if (src[i] === '\n') return false;
  89. return true;
  90. };
  91. function resolvePairComment(item, pair) {
  92. if (!valueHasPairComment(item)) return;
  93. const comment = item.getPropValue(0, _constants.Char.COMMENT, true);
  94. let found = false;
  95. const cb = pair.value.commentBefore;
  96. if (cb && cb.startsWith(comment)) {
  97. pair.value.commentBefore = cb.substr(comment.length + 1);
  98. found = true;
  99. } else {
  100. const cc = pair.value.comment;
  101. if (!item.node && cc && cc.startsWith(comment)) {
  102. pair.value.comment = cc.substr(comment.length + 1);
  103. found = true;
  104. }
  105. }
  106. if (found) pair.comment = comment;
  107. }
  108. function resolveBlockMapItems(doc, cst) {
  109. const comments = [];
  110. const items = [];
  111. let key = undefined;
  112. let keyStart = null;
  113. for (let i = 0; i < cst.items.length; ++i) {
  114. const item = cst.items[i];
  115. switch (item.type) {
  116. case _constants.Type.BLANK_LINE:
  117. comments.push({
  118. afterKey: !!key,
  119. before: items.length
  120. });
  121. break;
  122. case _constants.Type.COMMENT:
  123. comments.push({
  124. afterKey: !!key,
  125. before: items.length,
  126. comment: item.comment
  127. });
  128. break;
  129. case _constants.Type.MAP_KEY:
  130. if (key !== undefined) items.push(new _Pair.default(key));
  131. if (item.error) doc.errors.push(item.error);
  132. key = doc.resolveNode(item.node);
  133. keyStart = null;
  134. break;
  135. case _constants.Type.MAP_VALUE:
  136. {
  137. if (key === undefined) key = null;
  138. if (item.error) doc.errors.push(item.error);
  139. if (!item.context.atLineStart && item.node && item.node.type === _constants.Type.MAP && !item.node.context.atLineStart) {
  140. const msg = 'Nested mappings are not allowed in compact mappings';
  141. doc.errors.push(new _errors.YAMLSemanticError(item.node, msg));
  142. }
  143. let valueNode = item.node;
  144. if (!valueNode && item.props.length > 0) {
  145. // Comments on an empty mapping value need to be preserved, so we
  146. // need to construct a minimal empty node here to use instead of the
  147. // missing `item.node`. -- eemeli/yaml#19
  148. valueNode = new _PlainValue.default(_constants.Type.PLAIN, []);
  149. valueNode.context = {
  150. parent: item,
  151. src: item.context.src
  152. };
  153. const pos = item.range.start + 1;
  154. valueNode.range = {
  155. start: pos,
  156. end: pos
  157. };
  158. valueNode.valueRange = {
  159. start: pos,
  160. end: pos
  161. };
  162. if (typeof item.range.origStart === 'number') {
  163. const origPos = item.range.origStart + 1;
  164. valueNode.range.origStart = valueNode.range.origEnd = origPos;
  165. valueNode.valueRange.origStart = valueNode.valueRange.origEnd = origPos;
  166. }
  167. }
  168. const pair = new _Pair.default(key, doc.resolveNode(valueNode));
  169. resolvePairComment(item, pair);
  170. items.push(pair);
  171. (0, _parseUtils.checkKeyLength)(doc.errors, cst, i, key, keyStart);
  172. key = undefined;
  173. keyStart = null;
  174. }
  175. break;
  176. default:
  177. if (key !== undefined) items.push(new _Pair.default(key));
  178. key = doc.resolveNode(item);
  179. keyStart = item.range.start;
  180. if (item.error) doc.errors.push(item.error);
  181. next: for (let j = i + 1;; ++j) {
  182. const nextItem = cst.items[j];
  183. switch (nextItem && nextItem.type) {
  184. case _constants.Type.BLANK_LINE:
  185. case _constants.Type.COMMENT:
  186. continue next;
  187. case _constants.Type.MAP_VALUE:
  188. break next;
  189. default:
  190. doc.errors.push(new _errors.YAMLSemanticError(item, 'Implicit map keys need to be followed by map values'));
  191. break next;
  192. }
  193. }
  194. if (item.valueRangeContainsNewline) {
  195. const msg = 'Implicit map keys need to be on a single line';
  196. doc.errors.push(new _errors.YAMLSemanticError(item, msg));
  197. }
  198. }
  199. }
  200. if (key !== undefined) items.push(new _Pair.default(key));
  201. return {
  202. comments,
  203. items
  204. };
  205. }
  206. function resolveFlowMapItems(doc, cst) {
  207. const comments = [];
  208. const items = [];
  209. let key = undefined;
  210. let keyStart = null;
  211. let explicitKey = false;
  212. let next = '{';
  213. for (let i = 0; i < cst.items.length; ++i) {
  214. (0, _parseUtils.checkKeyLength)(doc.errors, cst, i, key, keyStart);
  215. const item = cst.items[i];
  216. if (typeof item.char === 'string') {
  217. const {
  218. char,
  219. offset
  220. } = item;
  221. if (char === '?' && key === undefined && !explicitKey) {
  222. explicitKey = true;
  223. next = ':';
  224. continue;
  225. }
  226. if (char === ':') {
  227. if (key === undefined) key = null;
  228. if (next === ':') {
  229. next = ',';
  230. continue;
  231. }
  232. } else {
  233. if (explicitKey) {
  234. if (key === undefined && char !== ',') key = null;
  235. explicitKey = false;
  236. }
  237. if (key !== undefined) {
  238. items.push(new _Pair.default(key));
  239. key = undefined;
  240. keyStart = null;
  241. if (char === ',') {
  242. next = ':';
  243. continue;
  244. }
  245. }
  246. }
  247. if (char === '}') {
  248. if (i === cst.items.length - 1) continue;
  249. } else if (char === next) {
  250. next = ':';
  251. continue;
  252. }
  253. const msg = `Flow map contains an unexpected ${char}`;
  254. const err = new _errors.YAMLSyntaxError(cst, msg);
  255. err.offset = offset;
  256. doc.errors.push(err);
  257. } else if (item.type === _constants.Type.BLANK_LINE) {
  258. comments.push({
  259. afterKey: !!key,
  260. before: items.length
  261. });
  262. } else if (item.type === _constants.Type.COMMENT) {
  263. comments.push({
  264. afterKey: !!key,
  265. before: items.length,
  266. comment: item.comment
  267. });
  268. } else if (key === undefined) {
  269. if (next === ',') doc.errors.push(new _errors.YAMLSemanticError(item, 'Separator , missing in flow map'));
  270. key = doc.resolveNode(item);
  271. keyStart = explicitKey ? null : item.range.start; // TODO: add error for non-explicit multiline plain key
  272. } else {
  273. if (next !== ',') doc.errors.push(new _errors.YAMLSemanticError(item, 'Indicator : missing in flow map entry'));
  274. items.push(new _Pair.default(key, doc.resolveNode(item)));
  275. key = undefined;
  276. explicitKey = false;
  277. }
  278. }
  279. (0, _parseUtils.checkFlowCollectionEnd)(doc.errors, cst);
  280. if (key !== undefined) items.push(new _Pair.default(key));
  281. return {
  282. comments,
  283. items
  284. };
  285. }