Throw a syntax error for a declare function with a body (#12054)

This commit is contained in:
Sosuke Suzuki 2020-09-19 07:35:37 +09:00 committed by GitHub
parent 6182001a4c
commit ae18f9c0d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 196 additions and 33 deletions

View File

@ -69,6 +69,8 @@ const TSErrors = Object.freeze({
"Type parameters cannot appear on a constructor declaration.", "Type parameters cannot appear on a constructor declaration.",
DeclareClassFieldHasInitializer: DeclareClassFieldHasInitializer:
"'declare' class fields cannot have an initializer", "'declare' class fields cannot have an initializer",
DeclareFunctionHasImplementation:
"An implementation cannot be declared in ambient contexts.",
DuplicateModifier: "Duplicate modifier: '%0'", DuplicateModifier: "Duplicate modifier: '%0'",
EmptyHeritageClauseType: "'%0' list cannot be empty.", EmptyHeritageClauseType: "'%0' list cannot be empty.",
IndexSignatureHasAbstract: IndexSignatureHasAbstract:
@ -1469,8 +1471,13 @@ export default (superClass: Class<Parser>): Class<Parser> =>
kind = "let"; kind = "let";
} }
const oldIsDeclareContext = this.state.isDeclareContext;
this.state.isDeclareContext = true;
try {
switch (starttype) { switch (starttype) {
case tt._function: case tt._function:
nany.declare = true;
return this.parseFunctionStatement( return this.parseFunctionStatement(
nany, nany,
/* async */ false, /* async */ false,
@ -1505,6 +1512,9 @@ export default (superClass: Class<Parser>): Class<Parser> =>
} }
} }
} }
} finally {
this.state.isDeclareContext = oldIsDeclareContext;
}
} }
// Note: this won't be called unless the keyword is allowed in `shouldParseExportDeclaration`. // Note: this won't be called unless the keyword is allowed in `shouldParseExportDeclaration`.
@ -1764,6 +1774,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.finishNode(node, bodilessType); this.finishNode(node, bodilessType);
return; return;
} }
if (bodilessType === "TSDeclareFunction" && this.state.isDeclareContext) {
this.raise(node.start, TSErrors.DeclareFunctionHasImplementation);
if (
// $FlowIgnore
node.declare
) {
super.parseFunctionBodyAndFinish(node, bodilessType, isMethod);
return;
}
}
super.parseFunctionBodyAndFinish(node, type, isMethod); super.parseFunctionBodyAndFinish(node, type, isMethod);
} }

View File

@ -70,6 +70,7 @@ export default class State {
inPropertyName: boolean = false; inPropertyName: boolean = false;
hasFlowComment: boolean = false; hasFlowComment: boolean = false;
isIterator: boolean = false; isIterator: boolean = false;
isDeclareContext: boolean = false;
// For the smartPipelines plugin: // For the smartPipelines plugin:
topicContext: TopicContextState = { topicContext: TopicContextState = {

View File

@ -0,0 +1 @@
declare function foo() {}

View File

@ -0,0 +1,35 @@
{
"type": "File",
"start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}},
"errors": [
"SyntaxError: An implementation cannot be declared in ambient contexts. (1:0)"
],
"program": {
"type": "Program",
"start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSDeclareFunction",
"start":0,"end":25,"loc":{"start":{"line":1,"column":0},"end":{"line":1,"column":25}},
"declare": true,
"id": {
"type": "Identifier",
"start":17,"end":20,"loc":{"start":{"line":1,"column":17},"end":{"line":1,"column":20},"identifierName":"foo"},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start":23,"end":25,"loc":{"start":{"line":1,"column":23},"end":{"line":1,"column":25}},
"body": [],
"directives": []
}
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
declare module m {
function foo() {}
}

View File

@ -0,0 +1,50 @@
{
"type": "File",
"start":0,"end":40,"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":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "TSModuleDeclaration",
"start":0,"end":40,"loc":{"start":{"line":1,"column":0},"end":{"line":3,"column":1}},
"id": {
"type": "Identifier",
"start":15,"end":16,"loc":{"start":{"line":1,"column":15},"end":{"line":1,"column":16},"identifierName":"m"},
"name": "m"
},
"body": {
"type": "TSModuleBlock",
"start":17,"end":40,"loc":{"start":{"line":1,"column":17},"end":{"line":3,"column":1}},
"body": [
{
"type": "FunctionDeclaration",
"start":21,"end":38,"loc":{"start":{"line":2,"column":2},"end":{"line":2,"column":19}},
"id": {
"type": "Identifier",
"start":30,"end":33,"loc":{"start":{"line":2,"column":11},"end":{"line":2,"column":14},"identifierName":"foo"},
"name": "foo"
},
"generator": false,
"async": false,
"params": [],
"body": {
"type": "BlockStatement",
"start":36,"end":38,"loc":{"start":{"line":2,"column":17},"end":{"line":2,"column":19}},
"body": [],
"directives": []
}
}
]
},
"declare": true
}
],
"directives": []
}
}

View File

@ -0,0 +1,3 @@
declare namespace n {
function foo() {}
}

View File

@ -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": []
}
}