Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: split locationParser into ParserErrors and error message #11653

Merged
merged 1 commit into from May 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,23 +1,8 @@
// @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,
};

// 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:
"'arguments' is not allowed in class field initializer",
AsyncFunctionInSingleStatementContext:
Expand Down Expand Up @@ -205,53 +190,3 @@ export const Errors = Object.freeze({
ZeroDigitNumericSeparator:
"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;
}
}
}
69 changes: 69 additions & 0 deletions packages/babel-parser/src/parser/error.js
@@ -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;
}
}
}
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/expression.js
Expand Up @@ -48,7 +48,7 @@ import {
PARAM,
functionFlags,
} from "../util/production-parameter";
import { Errors } from "./location";
import { Errors } from "./error";

export default class ExpressionParser extends LValParser {
// Forward-declaration: defined in statement.js
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/lval.js
Expand Up @@ -22,7 +22,7 @@ import {
import { NodeUtils } from "./node";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
import { ExpressionErrors } from "./util";
import { Errors } from "./location";
import { Errors } from "./error";

const unwrapParenthesizedExpression = (node: Node) => {
return node.type === "ParenthesizedExpression"
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/statement.js
Expand Up @@ -3,7 +3,7 @@
import * as N from "../types";
import { types as tt, type TokenType } from "../tokenizer/types";
import ExpressionParser from "./expression";
import { Errors } from "./location";
import { Errors } from "./error";
import {
isIdentifierChar,
isIdentifierStart,
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/parser/util.js
Expand Up @@ -7,7 +7,7 @@ import type { Node } from "../types";
import { lineBreak } from "../util/whitespace";
import { isIdentifierChar } from "../util/identifier";
import * as charCodes from "charcodes";
import { Errors } from "./location";
import { Errors } from "./error";

type TryParse<Node, Error, Thrown, Aborted, FailState> = {
node: Node,
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/plugins/estree.js
Expand Up @@ -6,7 +6,7 @@ import type { ExpressionErrors } from "../parser/util";
import * as N from "../types";
import type { Position } from "../util/location";
import { type BindingTypes, BIND_NONE } from "../util/scopeflags";
import { Errors } from "../parser/location";
import { Errors } from "../parser/error";

function isSimpleProperty(node: N.Node): boolean {
return (
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/plugins/flow.js
Expand Up @@ -22,7 +22,7 @@ import {
SCOPE_OTHER,
} from "../util/scopeflags";
import type { ExpressionErrors } from "../parser/util";
import { Errors } from "../parser/location";
import { Errors } from "../parser/error";

const reservedTypes = new Set([
"_",
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/plugins/jsx/index.js
Expand Up @@ -11,7 +11,7 @@ import * as N from "../../types";
import { isIdentifierChar, isIdentifierStart } from "../../util/identifier";
import type { Position } from "../../util/location";
import { isNewLine } from "../../util/whitespace";
import { Errors } from "../../parser/location";
import { Errors } from "../../parser/error";

const HEX_NUMBER = /^[\da-fA-F]+$/;
const DECIMAL_NUMBER = /^\d+$/;
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -27,7 +27,7 @@ import TypeScriptScopeHandler from "./scope";
import * as charCodes from "charcodes";
import type { ExpressionErrors } from "../../parser/util";
import { PARAM } from "../../util/production-parameter";
import { Errors } from "../../parser/location";
import { Errors } from "../../parser/error";

type TsModifier =
| "readonly"
Expand Down
4 changes: 2 additions & 2 deletions packages/babel-parser/src/tokenizer/index.js
Expand Up @@ -9,7 +9,7 @@ import * as charCodes from "charcodes";
import { isIdentifierStart, isIdentifierChar } from "../util/identifier";
import { types as tt, keywords as keywordTypes, type TokenType } from "./types";
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 {
lineBreak,
Expand Down Expand Up @@ -110,7 +110,7 @@ export class Token {

// ## Tokenizer

export default class Tokenizer extends LocationParser {
export default class Tokenizer extends ParserErrors {
// Forward-declarations
// parser/util.js
/*::
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/util/class-scope.js
Expand Up @@ -5,7 +5,7 @@ import {
CLASS_ELEMENT_FLAG_STATIC,
type ClassElementTypes,
} from "./scopeflags";
import { Errors } from "../parser/location";
import { Errors } from "../parser/error";

export class ClassScope {
// A list of private named declared in the current class
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-parser/src/util/scope.js
Expand Up @@ -16,7 +16,7 @@ import {
type BindingTypes,
} from "./scopeflags";
import * as N from "../types";
import { Errors } from "../parser/location";
import { Errors } from "../parser/error";

// Start an AST node, attaching a start offset.
export class Scope {
Expand Down