Skip to content

Commit

Permalink
Have raise() take a Position instead of an integer index so that we c…
Browse files Browse the repository at this point in the history
…an correctly and efficiently track line and column offsets. Additionally:

1. Make Errors.ElementAfterRest a recoverable error.
2. Make expectContextual throw a nicer error telling you what it expected to find.

Reviewed by @tolmasky.
  • Loading branch information
tolmasky committed Jan 14, 2022
1 parent ab2c578 commit 06a7655
Show file tree
Hide file tree
Showing 23 changed files with 1,150 additions and 1,050 deletions.
Expand Up @@ -146,7 +146,7 @@ export default {
"CallExpression[callee.type='MemberExpression'][callee.object.type='ThisExpression'][callee.property.name='raise'][arguments.length>=2]"(
node,
) {
const [, errorMsgNode] = node.arguments;
const [errorMsgNode] = node.arguments;
const nodesToCheck = findIdNodes(errorMsgNode);

if (
Expand Down

Large diffs are not rendered by default.

43 changes: 23 additions & 20 deletions packages/babel-parser/src/parser/error.js
@@ -1,8 +1,9 @@
// @flow
/* eslint sort-keys: "error" */
import { getLineInfo, type Position } from "../util/location";
import { type Position } from "../util/location";
import CommentsParser from "./comments";
import { type ErrorCode, ErrorCodes } from "./error-codes";
import { type Node } from "../types";

// This function is used to raise exceptions on parse errors. It
// takes an offset integer (into the current `input`) to indicate
Expand All @@ -28,7 +29,14 @@ export type ErrorTemplates = {
[key: string]: ErrorTemplate,
};

type SyntaxPlugin = "flow" | "typescript" | "jsx" | typeof undefined;
type Origin = {| node: Node |} | {| at: Position |};

type SyntaxPlugin =
| "flow"
| "typescript"
| "jsx"
| "placeholders"
| typeof undefined;

function keepReasonCodeCompat(reasonCode: string, syntaxPlugin: SyntaxPlugin) {
if (!process.env.BABEL_8_BREAKING) {
Expand Down Expand Up @@ -64,31 +72,26 @@ export {
SourceTypeModuleErrorMessages as SourceTypeModuleErrors,
} from "./error-message";

export type raiseFunction = (number, ErrorTemplate, ...any) => void;
export type raiseFunction = (ErrorTemplate, Origin, ...any) => void;
export type ErrorData = {| message: ErrorTemplate, loc: Position |};

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,
{ code, reasonCode, template }: ErrorTemplate,
origin: Origin,
...params: any
): Error | empty {
return this.raiseWithData(pos, { code, reasonCode }, template, ...params);
return this.raiseWithData(
origin.node ? origin.node.loc.start : origin.at,
{ code, reasonCode },
template,
...params,
);
}

/**
Expand All @@ -104,11 +107,11 @@ export default class ParserError extends CommentsParser {
* @memberof ParserError
*/
raiseOverwrite(
pos: number,
loc: Position,
{ code, template }: ErrorTemplate,
...params: any
): Error | empty {
const loc = this.getLocationForPosition(pos);
const pos = loc.index;
const message =
template.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
Expand All @@ -127,15 +130,15 @@ export default class ParserError extends CommentsParser {
}

raiseWithData(
pos: number,
loc: Position,
data?: {
missingPlugin?: Array<string>,
code?: string,
},
errorTemplate: string,
...params: any
): Error | empty {
const loc = this.getLocationForPosition(pos);
const pos = loc.index;
const message =
errorTemplate.replace(/%(\d+)/g, (_, i: number) => params[i]) +
` (${loc.line}:${loc.column})`;
Expand Down

0 comments on commit 06a7655

Please sign in to comment.