From ab09af15fd9ad4c34a49349c666425ce100364f1 Mon Sep 17 00:00:00 2001 From: Roman Dvornov Date: Wed, 22 Jan 2020 15:58:55 +0300 Subject: [PATCH] Refactoring of custom errors, drop SyntaxError from export --- CHANGELOG.md | 2 + lib/{utils => common}/create-custom-error.js | 13 +++--- lib/definition-syntax/SyntaxError.js | 20 ++++----- lib/lexer/error.js | 45 ++++++++++---------- lib/{common => parser}/SyntaxError.js | 38 ++++++----------- lib/parser/create.js | 3 +- lib/syntax/create.js | 2 - test/parse.js | 8 +++- 8 files changed, 60 insertions(+), 71 deletions(-) rename lib/{utils => common}/create-custom-error.js (67%) rename lib/{common => parser}/SyntaxError.js (68%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2bff35b6..4cc475b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,8 @@ - Removed `element()` specific parsing rules - Changed `String` node type to store decoded string value (and auto encode a value on serialize) - Changed `Url` node type to store decoded url value (and auto encode a value on serialize) +- Removed `SyntaxError` (custom parse error class) from public API +- Removed `parseError` field in parse `SyntaxError` ## 1.0.0-alpha.39 (December 5, 2019) diff --git a/lib/utils/create-custom-error.js b/lib/common/create-custom-error.js similarity index 67% rename from lib/utils/create-custom-error.js rename to lib/common/create-custom-error.js index 10c2bbdb..97c27a96 100644 --- a/lib/utils/create-custom-error.js +++ b/lib/common/create-custom-error.js @@ -4,14 +4,11 @@ module.exports = function createCustomError(name, message) { const error = Object.create(SyntaxError.prototype); const errorStack = new Error(); - error.name = name; - error.message = message; - - Object.defineProperty(error, 'stack', { - get: function() { - return (errorStack.stack || '').replace(/^(.+\n){1,3}/, name + ': ' + message + '\n'); + return Object.assign(error, { + name, + message, + get stack() { + return (errorStack.stack || '').replace(/^(.+\n){1,3}/, `${name}: ${message}\n`); } }); - - return error; }; diff --git a/lib/definition-syntax/SyntaxError.js b/lib/definition-syntax/SyntaxError.js index 9387b1d7..4b23645b 100644 --- a/lib/definition-syntax/SyntaxError.js +++ b/lib/definition-syntax/SyntaxError.js @@ -1,14 +1,12 @@ -const createCustomError = require('../utils/create-custom-error'); +const createCustomError = require('../common/create-custom-error'); module.exports = function SyntaxError(message, input, offset) { - const error = createCustomError('SyntaxError', message); - - error.input = input; - error.offset = offset; - error.rawMessage = message; - error.message = error.rawMessage + '\n' + - ' ' + error.input + '\n' + - '--' + new Array((error.offset || error.input.length) + 1).join('-') + '^'; - - return error; + return Object.assign(createCustomError('SyntaxError', message), { + input, + offset, + rawMessage: message, + message: message + '\n' + + ' ' + input + '\n' + + '--' + new Array((offset || input.length) + 1).join('-') + '^' + }); }; diff --git a/lib/lexer/error.js b/lib/lexer/error.js index d6db36dd..05d56126 100644 --- a/lib/lexer/error.js +++ b/lib/lexer/error.js @@ -1,9 +1,8 @@ -const createCustomError = require('../utils/create-custom-error'); +const createCustomError = require('../common/create-custom-error'); const generate = require('../definition-syntax/generate'); function fromMatchResult(matchResult) { - const tokens = matchResult.tokens; - const longestMatch = matchResult.longestMatch; + const { tokens, longestMatch } = matchResult; const node = longestMatch < tokens.length ? tokens[longestMatch].node : null; let mismatchOffset = -1; let entries = 0; @@ -58,33 +57,33 @@ const SyntaxReferenceError = function(type, referenceName) { return error; }; -const MatchError = function(message, syntax, node, matchResult) { - const error = createCustomError('SyntaxMatchError', message); +const MatchError = function(message, syntaxAst, node, matchResult) { const details = fromMatchResult(matchResult); const mismatchOffset = details.mismatchOffset || 0; const badNode = details.node || node; const end = getLocation(badNode, 'end'); const start = details.last ? end : getLocation(badNode, 'start'); const css = details.css; + const syntax = syntaxAst ? generate(syntaxAst) : ''; - error.rawMessage = message; - error.syntax = syntax ? generate(syntax) : ''; - error.css = css; - error.mismatchOffset = mismatchOffset; - error.loc = { - source: (badNode && badNode.loc && badNode.loc.source) || '', - start, - end - }; - error.line = start ? start.line : undefined; - error.column = start ? start.column : undefined; - error.offset = start ? start.offset : undefined; - error.message = message + '\n' + - ' syntax: ' + error.syntax + '\n' + - ' value: ' + (error.css || '') + '\n' + - ' --------' + '-'.repeat(error.mismatchOffset) + '^'; - - return error; + return Object.assign(createCustomError('SyntaxMatchError', message), { + rawMessage: message, + syntax, + css, + mismatchOffset, + loc: { + source: (badNode && badNode.loc && badNode.loc.source) || '', + start, + end + }, + line: start ? start.line : undefined, + column: start ? start.column : undefined, + offset: start ? start.offset : undefined, + message: message + '\n' + + ' syntax: ' + syntax + '\n' + + ' value: ' + (css || '') + '\n' + + ' --------' + '-'.repeat(mismatchOffset) + '^' + }); }; module.exports = { diff --git a/lib/common/SyntaxError.js b/lib/parser/SyntaxError.js similarity index 68% rename from lib/common/SyntaxError.js rename to lib/parser/SyntaxError.js index afc8de93..09cdd2ee 100644 --- a/lib/common/SyntaxError.js +++ b/lib/parser/SyntaxError.js @@ -1,9 +1,9 @@ -const createCustomError = require('../utils/create-custom-error'); +const createCustomError = require('../common/create-custom-error'); const MAX_LINE_LENGTH = 100; const OFFSET_CORRECTION = 60; const TAB_REPLACEMENT = ' '; -function sourceFragment(error, extraLines) { +function sourceFragment({ source, line, column }, extraLines) { function processLines(start, end) { return lines .slice(start, end) @@ -12,12 +12,10 @@ function sourceFragment(error, extraLines) { ).join('\n'); } - const lines = error.source.split(/\r\n?|\n|\f/); - const line = error.line; + const lines = source.split(/\r\n?|\n|\f/); const startLine = Math.max(1, line - extraLines) - 1; const endLine = Math.min(line + extraLines, lines.length + 1); const maxNumLength = Math.max(4, String(endLine).length) + 1; - let column = error.column; let cutLeft = 0; // column correction according to replaced tab before column @@ -46,29 +44,21 @@ function sourceFragment(error, extraLines) { } module.exports = function SyntaxError(message, source, offset, line, column) { - const error = createCustomError('SyntaxError', message); - - error.source = source; - error.offset = offset; - error.line = line; - error.column = column; - - error.sourceFragment = extraLines => sourceFragment(error, isNaN(extraLines) ? 0 : extraLines); - Object.defineProperty(error, 'formattedMessage', { - get() { + const error = Object.assign(createCustomError('SyntaxError', message), { + source, + offset, + line, + column, + sourceFragment(extraLines) { + return sourceFragment({ source, line, column }, isNaN(extraLines) ? 0 : extraLines); + }, + get formattedMessage() { return ( - 'Parse error: ' + error.message + '\n' + - sourceFragment(error, 2) + `Parse error: ${message}\n` + + sourceFragment({ source, line, column }, 2) ); } }); - // for backward capability - error.parseError = { - offset, - line, - column - }; - return error; }; diff --git a/lib/parser/create.js b/lib/parser/create.js index f52f7e77..0cb6d00e 100644 --- a/lib/parser/create.js +++ b/lib/parser/create.js @@ -1,7 +1,7 @@ const OffsetToLocation = require('../common/OffsetToLocation'); -const SyntaxError = require('../common/SyntaxError'); const TokenStream = require('../common/TokenStream'); const List = require('../common/List'); +const SyntaxError = require('./SyntaxError'); const tokenize = require('../tokenizer'); const { findWhiteSpaceStart, cmpChar, cmpStr } = require('../tokenizer/utils'); const NAME = require('../tokenizer/names'); @@ -306,6 +306,7 @@ module.exports = function createParser(config) { }; return Object.assign(parse, { + SyntaxError, config: parser.config }); }; diff --git a/lib/syntax/create.js b/lib/syntax/create.js index efee3598..49604b29 100644 --- a/lib/syntax/create.js +++ b/lib/syntax/create.js @@ -1,5 +1,4 @@ const List = require('../common/List'); -const SyntaxError = require('../common/SyntaxError'); const TokenStream = require('../common/TokenStream'); const Lexer = require('../lexer/Lexer'); const definitionSyntax = require('../definition-syntax'); @@ -23,7 +22,6 @@ function createSyntax(config) { const syntax = { List, - SyntaxError, TokenStream, Lexer, diff --git a/test/parse.js b/test/parse.js index 61184137..26c87c48 100644 --- a/test/parse.js +++ b/test/parse.js @@ -12,7 +12,7 @@ function createParseErrorTest(name, test, options) { () => parse(test.source, options), (e) => { error = e; - if (e.parseError) { + if (e instanceof parse.SyntaxError === false) { return true; } }, @@ -20,7 +20,11 @@ function createParseErrorTest(name, test, options) { ); assert.equal(error.message, test.error); - assert.deepEqual(error.parseError, test.position); + assert.deepEqual({ + offset: error.offset, + line: error.line, + column: error.column + }, test.position); }); }