SyntaxError.cjs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. 'use strict';
  2. const createCustomError = require('../utils/create-custom-error.cjs');
  3. const MAX_LINE_LENGTH = 100;
  4. const OFFSET_CORRECTION = 60;
  5. const TAB_REPLACEMENT = ' ';
  6. function sourceFragment({ source, line, column, baseLine, baseColumn }, extraLines) {
  7. function processLines(start, end) {
  8. return lines
  9. .slice(start, end)
  10. .map((line, idx) =>
  11. String(start + idx + 1).padStart(maxNumLength) + ' |' + line
  12. ).join('\n');
  13. }
  14. const prelines = '\n'.repeat(Math.max(baseLine - 1, 0));
  15. const precolumns = ' '.repeat(Math.max(baseColumn - 1, 0));
  16. const lines = (prelines + precolumns + source).split(/\r\n?|\n|\f/);
  17. const startLine = Math.max(1, line - extraLines) - 1;
  18. const endLine = Math.min(line + extraLines, lines.length + 1);
  19. const maxNumLength = Math.max(4, String(endLine).length) + 1;
  20. let cutLeft = 0;
  21. // column correction according to replaced tab before column
  22. column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
  23. if (column > MAX_LINE_LENGTH) {
  24. cutLeft = column - OFFSET_CORRECTION + 3;
  25. column = OFFSET_CORRECTION - 2;
  26. }
  27. for (let i = startLine; i <= endLine; i++) {
  28. if (i >= 0 && i < lines.length) {
  29. lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
  30. lines[i] =
  31. (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
  32. lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
  33. (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
  34. }
  35. }
  36. return [
  37. processLines(startLine, line),
  38. new Array(column + maxNumLength + 2).join('-') + '^',
  39. processLines(line, endLine)
  40. ].filter(Boolean)
  41. .join('\n')
  42. .replace(/^(\s+\d+\s+\|\n)+/, '')
  43. .replace(/\n(\s+\d+\s+\|)+$/, '');
  44. }
  45. function SyntaxError(message, source, offset, line, column, baseLine = 1, baseColumn = 1) {
  46. const error = Object.assign(createCustomError.createCustomError('SyntaxError', message), {
  47. source,
  48. offset,
  49. line,
  50. column,
  51. sourceFragment(extraLines) {
  52. return sourceFragment({ source, line, column, baseLine, baseColumn }, isNaN(extraLines) ? 0 : extraLines);
  53. },
  54. get formattedMessage() {
  55. return (
  56. `Parse error: ${message}\n` +
  57. sourceFragment({ source, line, column, baseLine, baseColumn }, 2)
  58. );
  59. }
  60. });
  61. return error;
  62. }
  63. exports.SyntaxError = SyntaxError;