refactor: split locationParser into ParserErrors and error message (#11653)

This commit is contained in:
Huáng Jùnliàng 2020-05-30 15:05:42 -04:00 committed by GitHub
parent 15d6da076a
commit b5c4a46a69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 82 additions and 78 deletions

View File

@ -1,23 +1,8 @@
// @flow // @flow
/* eslint sort-keys: "error" */ /* eslint sort-keys: "error" */
import { getLineInfo, type Position } from "../util/location";
import CommentsParser from "./comments";
// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.
type ErrorContext = {
pos: number,
loc: Position,
missingPlugin?: Array<string>,
code?: string,
};
// The Errors key follows https://cs.chromium.org/chromium/src/v8/src/common/message-template.h unless it does not exist // The Errors key follows https://cs.chromium.org/chromium/src/v8/src/common/message-template.h unless it does not exist
export const Errors = Object.freeze({ export const ErrorMessages = Object.freeze({
ArgumentsDisallowedInInitializer: ArgumentsDisallowedInInitializer:
"'arguments' is not allowed in class field initializer", "'arguments' is not allowed in class field initializer",
AsyncFunctionInSingleStatementContext: AsyncFunctionInSingleStatementContext:
@ -205,53 +190,3 @@ export const Errors = Object.freeze({
ZeroDigitNumericSeparator: ZeroDigitNumericSeparator:
"Numeric separator can not be used after leading 0", "Numeric separator can not be used after leading 0",
}); });
export default class LocationParser extends CommentsParser {
// Forward-declaration: defined in tokenizer/index.js
/*::
+isLookahead: boolean;
*/
getLocationForPosition(pos: number): Position {
let loc;
if (pos === this.state.start) loc = this.state.startLoc;
else if (pos === this.state.lastTokStart) loc = this.state.lastTokStartLoc;
else if (pos === this.state.end) loc = this.state.endLoc;
else if (pos === this.state.lastTokEnd) loc = this.state.lastTokEndLoc;
else loc = getLineInfo(this.input, pos);
return loc;
}
raise(pos: number, errorTemplate: string, ...params: any): Error | empty {
return this.raiseWithData(pos, undefined, errorTemplate, ...params);
}
raiseWithData(
pos: number,
data?: {
missingPlugin?: Array<string>,
code?: string,
},
errorTemplate: string,
...params: any
): Error | empty {
const loc = this.getLocationForPosition(pos);
const message =
errorTemplate.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
return this._raise(Object.assign(({ loc, pos }: Object), data), message);
}
_raise(errorContext: ErrorContext, message: string): Error | empty {
// $FlowIgnore
const err: SyntaxError & ErrorContext = new SyntaxError(message);
Object.assign(err, errorContext);
if (this.options.errorRecovery) {
if (!this.isLookahead) this.state.errors.push(err);
return err;
} else {
throw err;
}
}
}

View File

@ -0,0 +1,69 @@
// @flow
/* eslint sort-keys: "error" */
import { getLineInfo, type Position } from "../util/location";
import CommentsParser from "./comments";
// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
// the location of the error, attaches the position to the end
// of the error message, and then raises a `SyntaxError` with that
// message.
type ErrorContext = {
pos: number,
loc: Position,
missingPlugin?: Array<string>,
code?: string,
};
export { ErrorMessages as Errors } from "./error-message.js";
export default class ParserError extends CommentsParser {
// Forward-declaration: defined in tokenizer/index.js
/*::
+isLookahead: boolean;
*/
getLocationForPosition(pos: number): Position {
let loc;
if (pos === this.state.start) loc = this.state.startLoc;
else if (pos === this.state.lastTokStart) loc = this.state.lastTokStartLoc;
else if (pos === this.state.end) loc = this.state.endLoc;
else if (pos === this.state.lastTokEnd) loc = this.state.lastTokEndLoc;
else loc = getLineInfo(this.input, pos);
return loc;
}
raise(pos: number, errorTemplate: string, ...params: any): Error | empty {
return this.raiseWithData(pos, undefined, errorTemplate, ...params);
}
raiseWithData(
pos: number,
data?: {
missingPlugin?: Array<string>,
code?: string,
},
errorTemplate: string,
...params: any
): Error | empty {
const loc = this.getLocationForPosition(pos);
const message =
errorTemplate.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
return this._raise(Object.assign(({ loc, pos }: Object), data), message);
}
_raise(errorContext: ErrorContext, message: string): Error | empty {
// $FlowIgnore
const err: SyntaxError & ErrorContext = new SyntaxError(message);
Object.assign(err, errorContext);
if (this.options.errorRecovery) {
if (!this.isLookahead) this.state.errors.push(err);
return err;
} else {
throw err;
}
}
}

View File

@ -48,7 +48,7 @@ import {
PARAM, PARAM,
functionFlags, functionFlags,
} from "../util/production-parameter"; } from "../util/production-parameter";
import { Errors } from "./location"; import { Errors } from "./error";
export default class ExpressionParser extends LValParser { export default class ExpressionParser extends LValParser {
// Forward-declaration: defined in statement.js // Forward-declaration: defined in statement.js

View File

@ -22,7 +22,7 @@ import {
import { NodeUtils } from "./node"; import { NodeUtils } from "./node";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags"; import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
import { ExpressionErrors } from "./util"; import { ExpressionErrors } from "./util";
import { Errors } from "./location"; import { Errors } from "./error";
const unwrapParenthesizedExpression = (node: Node) => { const unwrapParenthesizedExpression = (node: Node) => {
return node.type === "ParenthesizedExpression" return node.type === "ParenthesizedExpression"

View File

@ -3,7 +3,7 @@
import * as N from "../types"; import * as N from "../types";
import { types as tt, type TokenType } from "../tokenizer/types"; import { types as tt, type TokenType } from "../tokenizer/types";
import ExpressionParser from "./expression"; import ExpressionParser from "./expression";
import { Errors } from "./location"; import { Errors } from "./error";
import { import {
isIdentifierChar, isIdentifierChar,
isIdentifierStart, isIdentifierStart,

View File

@ -7,7 +7,7 @@ import type { Node } from "../types";
import { lineBreak } from "../util/whitespace"; import { lineBreak } from "../util/whitespace";
import { isIdentifierChar } from "../util/identifier"; import { isIdentifierChar } from "../util/identifier";
import * as charCodes from "charcodes"; import * as charCodes from "charcodes";
import { Errors } from "./location"; import { Errors } from "./error";
type TryParse<Node, Error, Thrown, Aborted, FailState> = { type TryParse<Node, Error, Thrown, Aborted, FailState> = {
node: Node, node: Node,

View File

@ -6,7 +6,7 @@ import type { ExpressionErrors } from "../parser/util";
import * as N from "../types"; import * as N from "../types";
import type { Position } from "../util/location"; import type { Position } from "../util/location";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags"; import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
import { Errors } from "../parser/location"; import { Errors } from "../parser/error";
function isSimpleProperty(node: N.Node): boolean { function isSimpleProperty(node: N.Node): boolean {
return ( return (

View File

@ -22,7 +22,7 @@ import {
SCOPE_OTHER, SCOPE_OTHER,
} from "../util/scopeflags"; } from "../util/scopeflags";
import type { ExpressionErrors } from "../parser/util"; import type { ExpressionErrors } from "../parser/util";
import { Errors } from "../parser/location"; import { Errors } from "../parser/error";
const reservedTypes = new Set([ const reservedTypes = new Set([
"_", "_",

View File

@ -11,7 +11,7 @@ import * as N from "../../types";
import { isIdentifierChar, isIdentifierStart } from "../../util/identifier"; import { isIdentifierChar, isIdentifierStart } from "../../util/identifier";
import type { Position } from "../../util/location"; import type { Position } from "../../util/location";
import { isNewLine } from "../../util/whitespace"; import { isNewLine } from "../../util/whitespace";
import { Errors } from "../../parser/location"; import { Errors } from "../../parser/error";
const HEX_NUMBER = /^[\da-fA-F]+$/; const HEX_NUMBER = /^[\da-fA-F]+$/;
const DECIMAL_NUMBER = /^\d+$/; const DECIMAL_NUMBER = /^\d+$/;

View File

@ -27,7 +27,7 @@ import TypeScriptScopeHandler from "./scope";
import * as charCodes from "charcodes"; import * as charCodes from "charcodes";
import type { ExpressionErrors } from "../../parser/util"; import type { ExpressionErrors } from "../../parser/util";
import { PARAM } from "../../util/production-parameter"; import { PARAM } from "../../util/production-parameter";
import { Errors } from "../../parser/location"; import { Errors } from "../../parser/error";
type TsModifier = type TsModifier =
| "readonly" | "readonly"

View File

@ -9,7 +9,7 @@ import * as charCodes from "charcodes";
import { isIdentifierStart, isIdentifierChar } from "../util/identifier"; import { isIdentifierStart, isIdentifierChar } from "../util/identifier";
import { types as tt, keywords as keywordTypes, type TokenType } from "./types"; import { types as tt, keywords as keywordTypes, type TokenType } from "./types";
import { type TokContext, types as ct } from "./context"; import { type TokContext, types as ct } from "./context";
import LocationParser, { Errors } from "../parser/location"; import ParserErrors, { Errors } from "../parser/error";
import { SourceLocation } from "../util/location"; import { SourceLocation } from "../util/location";
import { import {
lineBreak, lineBreak,
@ -110,7 +110,7 @@ export class Token {
// ## Tokenizer // ## Tokenizer
export default class Tokenizer extends LocationParser { export default class Tokenizer extends ParserErrors {
// Forward-declarations // Forward-declarations
// parser/util.js // parser/util.js
/*:: /*::

View File

@ -5,7 +5,7 @@ import {
CLASS_ELEMENT_FLAG_STATIC, CLASS_ELEMENT_FLAG_STATIC,
type ClassElementTypes, type ClassElementTypes,
} from "./scopeflags"; } from "./scopeflags";
import { Errors } from "../parser/location"; import { Errors } from "../parser/error";
export class ClassScope { export class ClassScope {
// A list of private named declared in the current class // A list of private named declared in the current class

View File

@ -16,7 +16,7 @@ import {
type BindingTypes, type BindingTypes,
} from "./scopeflags"; } from "./scopeflags";
import * as N from "../types"; import * as N from "../types";
import { Errors } from "../parser/location"; import { Errors } from "../parser/error";
// Start an AST node, attaching a start offset. // Start an AST node, attaching a start offset.
export class Scope { export class Scope {