From 35f4a1f063af1ace99f72fc0218b8cd7fbc68af6 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Sun, 15 Apr 2018 10:31:23 -0400 Subject: [PATCH] add codes to errors --- src/parse/index.ts | 40 ++++++-- src/parse/read/directives.ts | 24 ++++- src/parse/read/script.ts | 5 +- src/parse/read/style.ts | 5 +- src/parse/state/mustache.ts | 56 ++++++++--- src/parse/state/tag.ts | 96 ++++++++++++------- src/validate/js/propValidators/components.ts | 2 +- src/validate/js/propValidators/computed.ts | 2 +- src/validate/js/propValidators/data.ts | 2 +- src/validate/js/propValidators/events.ts | 2 +- src/validate/js/propValidators/helpers.ts | 2 +- src/validate/js/propValidators/immutable.ts | 2 +- src/validate/js/propValidators/methods.ts | 2 +- src/validate/js/propValidators/namespace.ts | 6 +- src/validate/js/propValidators/oncreate.ts | 2 +- src/validate/js/propValidators/ondestroy.ts | 2 +- src/validate/js/propValidators/props.ts | 4 +- src/validate/js/propValidators/setup.ts | 2 +- src/validate/js/propValidators/tag.ts | 4 +- src/validate/js/propValidators/transitions.ts | 2 +- test/parser/index.js | 1 + .../attribute-unique-error/error-v2.json | 1 + .../samples/attribute-unique-error/error.json | 1 + .../error-binding-disabled/error-v2.json | 1 + .../samples/error-binding-disabled/error.json | 1 + .../error-binding-mustaches/error-v2.json | 1 + .../error-binding-mustaches/error.json | 1 + .../error-binding-rvalue/error-v2.json | 1 + .../samples/error-binding-rvalue/error.json | 1 + .../error-comment-unclosed/error-v2.json | 1 + .../samples/error-comment-unclosed/error.json | 1 + test/parser/samples/error-css/error-v2.json | 1 + test/parser/samples/error-css/error.json | 1 + .../samples/error-event-handler/error-v2.json | 1 + .../samples/error-event-handler/error.json | 1 + .../error-illegal-expression/error-v2.json | 1 + .../error-illegal-expression/error.json | 1 + .../error-multiple-styles/error-v2.json | 1 + .../samples/error-multiple-styles/error.json | 1 + .../samples/error-ref-value/error-v2.json | 1 + .../parser/samples/error-ref-value/error.json | 1 + .../error-script-unclosed/error-v2.json | 1 + .../samples/error-script-unclosed/error.json | 1 + .../error-self-reference/error-v2.json | 1 + .../samples/error-self-reference/error.json | 1 + .../error-v2.json | 1 + .../error.json | 1 + .../error-v2.json | 1 + .../error.json | 1 + .../error-v2.json | 1 + .../error.json | 1 + .../error-v2.json | 1 + .../error-unexpected-end-of-input/error.json | 1 + .../error-unmatched-closing-tag/error-v2.json | 1 + .../error-unmatched-closing-tag/error.json | 1 + .../samples/error-void-closing/error-v2.json | 1 + .../samples/error-void-closing/error.json | 1 + .../error-window-children/error-v2.json | 1 + .../samples/error-window-children/error.json | 1 + .../error-window-duplicate/error-v2.json | 1 + .../samples/error-window-duplicate/error.json | 1 + .../error-window-inside-block/error-v2.json | 1 + .../error-window-inside-block/error.json | 1 + .../error-window-inside-element/error-v2.json | 1 + .../error-window-inside-element/error.json | 1 + test/validator/index.js | 2 +- .../errors.json | 1 + .../each-block-invalid-context/errors.json | 1 + .../export-default-duplicated/errors.json | 1 + .../namespace-invalid-unguessable/errors.json | 2 +- .../samples/namespace-invalid/errors.json | 2 +- .../samples/namespace-non-literal/errors.json | 2 +- .../non-object-literal-components/errors.json | 2 +- .../non-object-literal-events/errors.json | 2 +- .../non-object-literal-helpers/errors.json | 2 +- .../non-object-literal-methods/errors.json | 2 +- .../errors.json | 2 +- .../samples/oncreate-arrow-this/errors.json | 2 +- .../samples/ondestroy-arrow-this/errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../errors.json | 2 +- .../validator/samples/tag-invalid/errors.json | 2 +- .../samples/tag-non-string/errors.json | 2 +- 85 files changed, 248 insertions(+), 96 deletions(-) diff --git a/src/parse/index.ts b/src/parse/index.ts index b7656a426a..9b3994c831 100644 --- a/src/parse/index.ts +++ b/src/parse/index.ts @@ -71,11 +71,19 @@ export class Parser { const current = this.current(); const type = current.type === 'Element' ? `<${current.name}>` : 'Block'; - this.error(`${type} was left open`, current.start); + const slug = current.type === 'Element' ? 'element' : 'block'; + + this.error({ + code: `unclosed-${slug}`, + message: `${type} was left open` + }, current.start); } if (state !== fragment) { - this.error('Unexpected end of input'); + this.error({ + code: `unexpected-eof`, + message: 'Unexpected end of input' + }); } if (this.html.children.length) { @@ -97,12 +105,16 @@ export class Parser { } acornError(err: any) { - this.error(err.message.replace(/ \(\d+:\d+\)$/, ''), err.pos); + this.error({ + code: `parse-error`, + message: err.message.replace(/ \(\d+:\d+\)$/, '') + }, err.pos); } - error(message: string, index = this.index) { + error({ code, message }: { code: string, message: string }, index = this.index) { error(message, { name: 'ParseError', + code, source: this.template, start: index, filename: this.filename @@ -116,7 +128,10 @@ export class Parser { } if (required) { - this.error(message || `Expected ${str}`); + this.error({ + code: `unexpected-${this.index === this.template.length ? 'eof' : 'token'}`, + message: message || `Expected ${str}` + }); } return false; @@ -164,7 +179,10 @@ export class Parser { const identifier = this.template.slice(this.index, this.index = i); if (reservedNames.has(identifier)) { - this.error(`'${identifier}' is a reserved word in JavaScript and cannot be used here`, start); + this.error({ + code: `unexpected-reserved-word`, + message: `'${identifier}' is a reserved word in JavaScript and cannot be used here` + }, start); } return identifier; @@ -172,7 +190,10 @@ export class Parser { readUntil(pattern: RegExp) { if (this.index >= this.template.length) - this.error('Unexpected end of input'); + this.error({ + code: `unexpected-eof`, + message: 'Unexpected end of input' + }); const start = this.index; const match = pattern.exec(this.template.slice(start)); @@ -192,7 +213,10 @@ export class Parser { requireWhitespace() { if (!whitespace.test(this.template[this.index])) { - this.error(`Expected whitespace`); + this.error({ + code: `missing-whitespace`, + message: `Expected whitespace` + }); } this.allowWhitespace(); diff --git a/src/parse/read/directives.ts b/src/parse/read/directives.ts index 77c0ffe47a..6d8fa70fc5 100644 --- a/src/parse/read/directives.ts +++ b/src/parse/read/directives.ts @@ -2,7 +2,19 @@ import { parseExpressionAt } from 'acorn'; import repeat from '../../utils/repeat'; import { Parser } from '../index'; -const DIRECTIVES = { +const DIRECTIVES: Record { start: number, end: number, type: string, name: string, value?: any, expression?: any }; + allowedExpressionTypes: string[]; + error: string; +}> = { Ref: { names: ['ref'], attribute(start, end, type, name) { @@ -143,7 +155,10 @@ export function readDirective( try { expression = readExpression(parser, expressionStart, quoteMark); if (directive.allowedExpressionTypes.indexOf(expression.type) === -1) { - parser.error(directive.error, expressionStart); + parser.error({ + code: `invalid-directive-value`, + message: directive.error + }, expressionStart); } } catch (err) { if (parser.template[expressionStart] === '{') { @@ -155,7 +170,10 @@ export function readDirective( const value = parser.template.slice(expressionStart + (parser.v2 ? 1 : 2), expressionEnd); message += ` — use '${value}', not '${parser.v2 ? `{${value}}` : `{{${value}}}`}'`; } - parser.error(message, expressionStart); + parser.error({ + code: `invalid-directive-value`, + message + }, expressionStart); } throw err; diff --git a/src/parse/read/script.ts b/src/parse/read/script.ts index 4f28200b43..0518bc51a6 100644 --- a/src/parse/read/script.ts +++ b/src/parse/read/script.ts @@ -12,7 +12,10 @@ export default function readScript(parser: Parser, start: number, attributes: No const scriptStart = parser.index; const scriptEnd = parser.template.indexOf(scriptClosingTag, scriptStart); - if (scriptEnd === -1) parser.error(`