Skip to content

Commit

Permalink
Address review comment
Browse files Browse the repository at this point in the history
  • Loading branch information
sosukesuzuki committed Sep 12, 2020
1 parent 53d7ce5 commit 8d0569d
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 18 deletions.
2 changes: 2 additions & 0 deletions packages/babel-parser/src/parser/expression.js
Expand Up @@ -2101,6 +2101,8 @@ export default class ExpressionParser extends LValParser {
node: N.BodilessFunctionOrMethodBase,
type: string,
isMethod?: boolean = false,
// eslint-disable-next-line no-unused-vars -- this is used in /plugins/typescript
isDeclare?: boolean = false,
): void {
// $FlowIgnore (node is not bodiless if we get here)
this.parseFunctionBody(node, false, isMethod);
Expand Down
24 changes: 19 additions & 5 deletions packages/babel-parser/src/parser/statement.js
Expand Up @@ -144,14 +144,22 @@ export default class StatementParser extends ExpressionParser {
// https://tc39.es/ecma262/#prod-Statement
// ImportDeclaration and ExportDeclaration are also handled here so we can throw recoverable errors
// when they are not at the top level
parseStatement(context: ?string, topLevel?: boolean): N.Statement {
parseStatement(
context: ?string,
topLevel?: boolean,
isDeclare?: boolean = false,
): N.Statement {
if (this.match(tt.at)) {
this.parseDecorators(true);
}
return this.parseStatementContent(context, topLevel);
return this.parseStatementContent(context, topLevel, isDeclare);
}

parseStatementContent(context: ?string, topLevel: ?boolean): N.Statement {
parseStatementContent(
context: ?string,
topLevel: ?boolean,
isDeclare?: boolean = false,
): N.Statement {
let starttype = this.state.type;
const node = this.startNode();
let kind;
Expand Down Expand Up @@ -185,7 +193,7 @@ export default class StatementParser extends ExpressionParser {
this.raise(this.state.start, Errors.SloppyFunction);
}
}
return this.parseFunctionStatement(node, false, !context);
return this.parseFunctionStatement(node, false, !context, isDeclare);

case tt._class:
if (context) this.unexpected();
Expand Down Expand Up @@ -541,12 +549,14 @@ export default class StatementParser extends ExpressionParser {
node: N.FunctionDeclaration,
isAsync?: boolean,
declarationPosition?: boolean,
isDeclare?: boolean = false,
): N.FunctionDeclaration {
this.next();
return this.parseFunction(
node,
FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT),
isAsync,
isDeclare,
);
}

Expand Down Expand Up @@ -856,6 +866,7 @@ export default class StatementParser extends ExpressionParser {
topLevel: boolean,
end: TokenType,
afterBlockParse?: (hasStrictModeDirective: boolean) => void,
isDeclare?: boolean = false,
): void {
const octalPositions = [];
const oldStrict = this.state.strict;
Expand All @@ -868,7 +879,7 @@ export default class StatementParser extends ExpressionParser {
octalPositions.push(...this.state.octalPositions);
}

const stmt = this.parseStatement(null, topLevel);
const stmt = this.parseStatement(null, topLevel, isDeclare);

if (directives && !parsedNonDirective && this.isValidDirective(stmt)) {
const directive = this.stmtToDirective(stmt);
Expand Down Expand Up @@ -1054,6 +1065,7 @@ export default class StatementParser extends ExpressionParser {
node: T,
statement?: number = FUNC_NO_FLAGS,
isAsync?: boolean = false,
isDeclare?: boolean = false,
): T {
const isStatement = statement & FUNC_STATEMENT;
const isHangingStatement = statement & FUNC_HANGING_STATEMENT;
Expand Down Expand Up @@ -1093,6 +1105,8 @@ export default class StatementParser extends ExpressionParser {
this.parseFunctionBodyAndFinish(
node,
isStatement ? "FunctionDeclaration" : "FunctionExpression",
/* method */ false,
isDeclare,
);
});

Expand Down
46 changes: 33 additions & 13 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -1314,7 +1314,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.finishNode(node, "TSEnumDeclaration");
}

tsParseModuleBlock(): N.TsModuleBlock {
tsParseModuleBlock(isDeclare?: boolean = false): N.TsModuleBlock {
const node: N.TsModuleBlock = this.startNode();
this.scope.enter(SCOPE_OTHER);

Expand All @@ -1325,6 +1325,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
/* directives */ undefined,
/* topLevel */ true,
/* end */ tt.braceR,
/* afterBlockParse */ undefined,
/* declare */ isDeclare,
);
this.scope.exit();
return this.finishNode(node, "TSModuleBlock");
Expand All @@ -1333,6 +1335,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
tsParseModuleOrNamespaceDeclaration(
node: N.TsModuleDeclaration,
nested?: boolean = false,
isDeclare?: boolean = false,
): N.TsModuleDeclaration {
node.id = this.parseIdentifier();

Expand All @@ -1352,7 +1355,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} else {
this.scope.enter(SCOPE_TS_MODULE);
this.prodParam.enter(PARAM);
node.body = this.tsParseModuleBlock();
node.body = this.tsParseModuleBlock(isDeclare);
this.prodParam.exit();
this.scope.exit();
}
Expand Down Expand Up @@ -1474,6 +1477,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
nany,
/* async */ false,
/* declarationPosition */ true,
/* declare */ true,
);
case tt._class:
// While this is also set by tsParseExpressionStatement, we need to set it
Expand All @@ -1500,7 +1504,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
if (value === "global") {
return this.tsParseAmbientExternalModuleDeclaration(nany);
} else {
return this.tsParseDeclaration(nany, value, /* next */ true);
return this.tsParseDeclaration(
nany,
value,
/* next */ true,
/* declare */ true,
);
}
}
}
Expand Down Expand Up @@ -1551,6 +1560,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: any,
value: string,
next: boolean,
isDeclare?: boolean = false,
): ?N.Declaration {
switch (value) {
case "abstract":
Expand Down Expand Up @@ -1597,7 +1607,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
case "namespace":
if (this.tsCheckLineTerminatorAndMatch(tt.name, next)) {
if (next) this.next();
return this.tsParseModuleOrNamespaceDeclaration(node);
return this.tsParseModuleOrNamespaceDeclaration(
node,
/* nested */ false,
isDeclare,
);
}
break;

Expand Down Expand Up @@ -1745,6 +1759,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
node: N.BodilessFunctionOrMethodBase,
type: string,
isMethod?: boolean = false,
isDeclare?: boolean = false,
): void {
if (this.match(tt.colon)) {
node.returnType = this.tsParseTypeOrTypePredicateAnnotation(tt.colon);
Expand All @@ -1760,14 +1775,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.finishNode(node, bodilessType);
return;
}
if (
bodilessType === "TSDeclareFunction" &&
// $FlowIgnore
node.declare
) {
if (bodilessType === "TSDeclareFunction" && isDeclare) {
this.raise(node.start, TSErrors.DeclareFunctionHasImplementation);
this.finishNode(node, bodilessType);
return;
if (
// $FlowIgnore
node.declare
) {
this.finishNode(node, bodilessType);
return;
}
}

super.parseFunctionBodyAndFinish(node, type, isMethod);
Expand Down Expand Up @@ -2028,7 +2044,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return super.parseExportDefaultExpression();
}

parseStatementContent(context: ?string, topLevel: ?boolean): N.Statement {
parseStatementContent(
context: ?string,
topLevel: ?boolean,
isDeclare?: boolean = false,
): N.Statement {
if (this.state.type === tt._const) {
const ahead = this.lookahead();
if (ahead.type === tt.name && ahead.value === "enum") {
Expand All @@ -2038,7 +2058,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
return this.tsParseEnumDeclaration(node, /* isConst */ true);
}
}
return super.parseStatementContent(context, topLevel);
return super.parseStatementContent(context, topLevel, isDeclare);
}

parseAccessModifier(): ?N.Accessibility {
Expand Down
@@ -0,0 +1,3 @@
declare namespace n {
function foo() {}
}
@@ -0,0 +1,50 @@
{
"type": "File",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"errors": [
"SyntaxError: An implementation cannot be declared in ambient contexts. (2:2)"
],
"program": {
"type": "Program",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSModuleDeclaration",
"start":0,"end":43,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"id": {
"type": "Identifier",
"start":18,"end":19,"loc":{"start":{"line":1,"column":18},"end":{"line":1,"column":19},"identifierName":"n"},
"name": "n"
},
"body": {
"type": "TSModuleBlock",
"start":20,"end":43,"loc":{"start":{"line":1,"column":20},"end":{"line":3,"column":1}},
"body": [
{
"type": "FunctionDeclaration",
"start":24,"end":41,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}},
"id": {
"type": "Identifier",
"start":33,"end":36,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14},"identifierName":"foo"},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start":39,"end":41,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":19}},
"body": [],
"directives": []
}
}
]
},
"declare": true
}
],
"directives": []
}
}

0 comments on commit 8d0569d

Please sign in to comment.