Skip to content

Commit

Permalink
refactor: split locationParser into ParserErrors and error message (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
JLHwung committed May 30, 2020
1 parent 15d6da0 commit b5c4a46
Show file tree
Hide file tree
Showing 13 changed files with 82 additions and 78 deletions.
@@ -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

0 comments on commit b5c4a46

Please sign in to comment.