Skip to content

Commit 844a8a8

Browse files
committed
feat(parser): produce syntax error for declare function foo() {} (#11606)
closes #11590
1 parent b7b0dc3 commit 844a8a8

File tree

5 files changed

+44
-15
lines changed

5 files changed

+44
-15
lines changed

crates/oxc_linter/src/rules/oxc/only_used_in_recursion.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -540,8 +540,6 @@ fn test() {
540540
return _get(target, property, receiver || target);
541541
}
542542
"#,
543-
"function foo() {}
544-
declare function foo() {}",
545543
r#"
546544
var validator = function validator(node, key, val) {
547545
var validator = node.operator === "in" ? inOp : expression;

crates/oxc_parser/src/diagnostics.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,3 +690,8 @@ pub fn parameter_modifiers_in_ts(modifier: &Modifier) -> OxcDiagnostic {
690690
ts_error("8012", "Parameter modifiers can only be used in TypeScript files.")
691691
.with_label(modifier.span)
692692
}
693+
694+
#[cold]
695+
pub fn implementation_in_ambient(span: Span) -> OxcDiagnostic {
696+
ts_error("1183", "An implementation cannot be declared in ambient contexts.").with_label(span)
697+
}

crates/oxc_parser/src/js/function.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -109,23 +109,16 @@ impl<'a> ParserImpl<'a> {
109109
) -> Box<'a, Function<'a>> {
110110
let ctx = self.ctx;
111111
self.ctx = self.ctx.and_in(true).and_await(r#async).and_yield(generator);
112-
113112
let type_parameters = self.parse_ts_type_parameters();
114-
115113
let (this_param, params) = self.parse_formal_parameters(param_kind);
116-
117114
let return_type =
118115
self.parse_ts_return_type_annotation(Kind::Colon, /* is_type */ true);
119-
120116
let body = if self.at(Kind::LCurly) { Some(self.parse_function_body()) } else { None };
121-
122117
self.ctx =
123118
self.ctx.and_in(ctx.has_in()).and_await(ctx.has_await()).and_yield(ctx.has_yield());
124-
125119
if !self.is_ts && body.is_none() {
126120
return self.unexpected();
127121
}
128-
129122
let function_type = match func_kind {
130123
FunctionKind::Declaration | FunctionKind::DefaultExport => {
131124
if body.is_none() {
@@ -150,6 +143,14 @@ impl<'a> ParserImpl<'a> {
150143
self.asi();
151144
}
152145

146+
if ctx.has_ambient() && modifiers.contains_declare() {
147+
if let Some(body) = &body {
148+
self.error(diagnostics::implementation_in_ambient(Span::new(
149+
body.span.start,
150+
body.span.start,
151+
)));
152+
}
153+
}
153154
self.verify_modifiers(
154155
modifiers,
155156
ModifierFlags::DECLARE | ModifierFlags::ASYNC,

tasks/coverage/snapshots/parser_babel.snap

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commit: 1d4546bc
33
parser_babel Summary:
44
AST Parsed : 2351/2362 (99.53%)
55
Positive Passed: 2330/2362 (98.65%)
6-
Negative Passed: 1587/1698 (93.46%)
6+
Negative Passed: 1588/1698 (93.52%)
77
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js
88

99
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-and-startcolumn-specified/input.js
@@ -82,8 +82,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/ty
8282

8383
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/private-fields-modifier-abstract/input.ts
8484

85-
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/function/input.ts
86-
8785
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/module-class/input.ts
8886

8987
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/module-function/input.ts
@@ -12449,6 +12447,12 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
1244912447
· ──────────────────────────────────
1245012448
╰────
1245112449

12450+
× TS(1183): An implementation cannot be declared in ambient contexts.
12451+
╭─[babel/packages/babel-parser/test/fixtures/typescript/declare/function/input.ts:1:24]
12452+
1 │ declare function foo() {}
12453+
· ▲
12454+
╰────
12455+
1245212456
× Unexpected exponentiation expression
1245312457
╭─[babel/packages/babel-parser/test/fixtures/typescript/exponentiation/await-non-null-before-exponential/input.ts:1:14]
1245412458
1 │ async (a) => await a! ** 6;

tasks/coverage/snapshots/parser_typescript.snap

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ commit: 81c95189
33
parser_typescript Summary:
44
AST Parsed : 6530/6537 (99.89%)
55
Positive Passed: 6519/6537 (99.72%)
6-
Negative Passed: 1403/5763 (24.34%)
6+
Negative Passed: 1404/5763 (24.36%)
77
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration24.ts
88

99
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ExportAssignment7.ts
@@ -7282,8 +7282,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ec
72827282

72837283
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.d.ts
72847284

7285-
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.ts
7286-
72877285
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration3.ts
72887286

72897287
Expect Syntax Error: tasks/coverage/typescript/tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration4.ts
@@ -12843,6 +12841,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
1284312841
154 │ }
1284412842
╰────
1284512843

12844+
× TS(1183): An implementation cannot be declared in ambient contexts.
12845+
╭─[typescript/tests/cases/compiler/functionsWithModifiersInBlocks1.ts:2:25]
12846+
1 │ {
12847+
2 │ declare function f() { }
12848+
· ▲
12849+
3 │ export function f() { }
12850+
╰────
12851+
1284612852
× Unexpected token
1284712853
╭─[typescript/tests/cases/compiler/functionsWithModifiersInBlocks1.ts:4:12]
1284812854
3 │ export function f() { }
@@ -18383,6 +18389,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
1838318389
3 │ }
1838418390
╰────
1838518391

18392+
× TS(1183): An implementation cannot be declared in ambient contexts.
18393+
╭─[typescript/tests/cases/conformance/ambient/ambientErrors.ts:20:24]
18394+
19 │ // Ambient function with function body
18395+
20 │ declare function fn4() { };
18396+
· ▲
18397+
21 │
18398+
╰────
18399+
1838618400
× TS(1039): Initializers are not allowed in ambient contexts.
1838718401
╭─[typescript/tests/cases/conformance/ambient/ambientErrors.ts:2:17]
1838818402
1 │ // Ambient variable with an initializer
@@ -27265,6 +27279,13 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/private
2726527279
· ─────────
2726627280
╰────
2726727281

27282+
× TS(1183): An implementation cannot be declared in ambient contexts.
27283+
╭─[typescript/tests/cases/conformance/parser/ecmascript5/FunctionDeclarations/parserFunctionDeclaration2.ts:1:24]
27284+
1 │ declare function Foo() {
27285+
· ▲
27286+
2 │ }
27287+
╰────
27288+
2726827289
× Unexpected token
2726927290
╭─[typescript/tests/cases/conformance/parser/ecmascript5/Fuzz/parser0_004152.ts:2:45]
2727027291
1 │ export class Game {

0 commit comments

Comments
 (0)