Throw a syntax error for a declare function with a body (#12054)
This commit is contained in:
@@ -69,6 +69,8 @@ const TSErrors = Object.freeze({
|
||||
"Type parameters cannot appear on a constructor declaration.",
|
||||
DeclareClassFieldHasInitializer:
|
||||
"'declare' class fields cannot have an initializer",
|
||||
DeclareFunctionHasImplementation:
|
||||
"An implementation cannot be declared in ambient contexts.",
|
||||
DuplicateModifier: "Duplicate modifier: '%0'",
|
||||
EmptyHeritageClauseType: "'%0' list cannot be empty.",
|
||||
IndexSignatureHasAbstract:
|
||||
@@ -1469,41 +1471,49 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
kind = "let";
|
||||
}
|
||||
|
||||
switch (starttype) {
|
||||
case tt._function:
|
||||
return this.parseFunctionStatement(
|
||||
nany,
|
||||
/* async */ false,
|
||||
/* declarationPosition */ true,
|
||||
);
|
||||
case tt._class:
|
||||
// While this is also set by tsParseExpressionStatement, we need to set it
|
||||
// before parsing the class declaration to now how to register it in the scope.
|
||||
nany.declare = true;
|
||||
return this.parseClass(
|
||||
nany,
|
||||
/* isStatement */ true,
|
||||
/* optionalId */ false,
|
||||
);
|
||||
case tt._const:
|
||||
if (this.match(tt._const) && this.isLookaheadContextual("enum")) {
|
||||
// `const enum = 0;` not allowed because "enum" is a strict mode reserved word.
|
||||
this.expect(tt._const);
|
||||
this.expectContextual("enum");
|
||||
return this.tsParseEnumDeclaration(nany, /* isConst */ true);
|
||||
}
|
||||
// falls through
|
||||
case tt._var:
|
||||
kind = kind || this.state.value;
|
||||
return this.parseVarStatement(nany, kind);
|
||||
case tt.name: {
|
||||
const value = this.state.value;
|
||||
if (value === "global") {
|
||||
return this.tsParseAmbientExternalModuleDeclaration(nany);
|
||||
} else {
|
||||
return this.tsParseDeclaration(nany, value, /* next */ true);
|
||||
const oldIsDeclareContext = this.state.isDeclareContext;
|
||||
this.state.isDeclareContext = true;
|
||||
|
||||
try {
|
||||
switch (starttype) {
|
||||
case tt._function:
|
||||
nany.declare = true;
|
||||
return this.parseFunctionStatement(
|
||||
nany,
|
||||
/* async */ false,
|
||||
/* declarationPosition */ true,
|
||||
);
|
||||
case tt._class:
|
||||
// While this is also set by tsParseExpressionStatement, we need to set it
|
||||
// before parsing the class declaration to now how to register it in the scope.
|
||||
nany.declare = true;
|
||||
return this.parseClass(
|
||||
nany,
|
||||
/* isStatement */ true,
|
||||
/* optionalId */ false,
|
||||
);
|
||||
case tt._const:
|
||||
if (this.match(tt._const) && this.isLookaheadContextual("enum")) {
|
||||
// `const enum = 0;` not allowed because "enum" is a strict mode reserved word.
|
||||
this.expect(tt._const);
|
||||
this.expectContextual("enum");
|
||||
return this.tsParseEnumDeclaration(nany, /* isConst */ true);
|
||||
}
|
||||
// falls through
|
||||
case tt._var:
|
||||
kind = kind || this.state.value;
|
||||
return this.parseVarStatement(nany, kind);
|
||||
case tt.name: {
|
||||
const value = this.state.value;
|
||||
if (value === "global") {
|
||||
return this.tsParseAmbientExternalModuleDeclaration(nany);
|
||||
} else {
|
||||
return this.tsParseDeclaration(nany, value, /* next */ true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.state.isDeclareContext = oldIsDeclareContext;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1764,6 +1774,16 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.finishNode(node, bodilessType);
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user