error.cjs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. 'use strict';
  2. const createCustomError = require('../utils/create-custom-error.cjs');
  3. const generate = require('../definition-syntax/generate.cjs');
  4. const defaultLoc = { offset: 0, line: 1, column: 1 };
  5. function locateMismatch(matchResult, node) {
  6. const tokens = matchResult.tokens;
  7. const longestMatch = matchResult.longestMatch;
  8. const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null;
  9. const badNode = mismatchNode !== node ? mismatchNode : null;
  10. let mismatchOffset = 0;
  11. let mismatchLength = 0;
  12. let entries = 0;
  13. let css = '';
  14. let start;
  15. let end;
  16. for (let i = 0; i < tokens.length; i++) {
  17. const token = tokens[i].value;
  18. if (i === longestMatch) {
  19. mismatchLength = token.length;
  20. mismatchOffset = css.length;
  21. }
  22. if (badNode !== null && tokens[i].node === badNode) {
  23. if (i <= longestMatch) {
  24. entries++;
  25. } else {
  26. entries = 0;
  27. }
  28. }
  29. css += token;
  30. }
  31. if (longestMatch === tokens.length || entries > 1) { // last
  32. start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css);
  33. end = buildLoc(start);
  34. } else {
  35. start = fromLoc(badNode, 'start') ||
  36. buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset));
  37. end = fromLoc(badNode, 'end') ||
  38. buildLoc(start, css.substr(mismatchOffset, mismatchLength));
  39. }
  40. return {
  41. css,
  42. mismatchOffset,
  43. mismatchLength,
  44. start,
  45. end
  46. };
  47. }
  48. function fromLoc(node, point) {
  49. const value = node && node.loc && node.loc[point];
  50. if (value) {
  51. return 'line' in value ? buildLoc(value) : value;
  52. }
  53. return null;
  54. }
  55. function buildLoc({ offset, line, column }, extra) {
  56. const loc = {
  57. offset,
  58. line,
  59. column
  60. };
  61. if (extra) {
  62. const lines = extra.split(/\n|\r\n?|\f/);
  63. loc.offset += extra.length;
  64. loc.line += lines.length - 1;
  65. loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1;
  66. }
  67. return loc;
  68. }
  69. const SyntaxReferenceError = function(type, referenceName) {
  70. const error = createCustomError.createCustomError(
  71. 'SyntaxReferenceError',
  72. type + (referenceName ? ' `' + referenceName + '`' : '')
  73. );
  74. error.reference = referenceName;
  75. return error;
  76. };
  77. const SyntaxMatchError = function(message, syntax, node, matchResult) {
  78. const error = createCustomError.createCustomError('SyntaxMatchError', message);
  79. const {
  80. css,
  81. mismatchOffset,
  82. mismatchLength,
  83. start,
  84. end
  85. } = locateMismatch(matchResult, node);
  86. error.rawMessage = message;
  87. error.syntax = syntax ? generate.generate(syntax) : '<generic>';
  88. error.css = css;
  89. error.mismatchOffset = mismatchOffset;
  90. error.mismatchLength = mismatchLength;
  91. error.message = message + '\n' +
  92. ' syntax: ' + error.syntax + '\n' +
  93. ' value: ' + (css || '<empty string>') + '\n' +
  94. ' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
  95. Object.assign(error, start);
  96. error.loc = {
  97. source: (node && node.loc && node.loc.source) || '<unknown>',
  98. start,
  99. end
  100. };
  101. return error;
  102. };
  103. exports.SyntaxMatchError = SyntaxMatchError;
  104. exports.SyntaxReferenceError = SyntaxReferenceError;