From d9cc429d4a23c55330dbee0f7d353a3195737156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arnaud=20Barr=C3=A9?= Date: Sun, 3 Mar 2024 14:59:17 +0100 Subject: [PATCH] fix(parser): parse empty method declaration as TSEmptyBodyFunctionExpression (#2574) That a tricky one, because it's time to decide what does ESTree compliant means in the TS world (re #2463) This code: ```ts export declare class ByteBuffer { clear(): void; // ^^ } ``` - Is parsed by [Babel](https://astexplorer.net/#/gist/9f43cf0fe91760e11f1572934681c92f/d38530204eaa6e12dbd14f3ef2d7d2fcb7da7bc2) as `FunctionExpression` with an empty body - By [TS-ESLint](https://astexplorer.net/#/gist/626dd346956a02c221d4e128450652af/4ea4e2feb5ae7bb8787f8c7e452d442c935c1f09) as [TSEmptyBodyFunctionExpression](https://github.com/typescript-eslint/typescript-eslint/pull/1289) - By [OXC](https://oxc-project.github.io/oxc/playground/?code=3YCAAIC1gICAgICAgICyHorESipoTXPdvBaE9wxzlOraoWs19SUxDvdcwSVU0kbBO2b7ppX3x2P5IhQlpGHOYEHNCEfLf38HUICA) as `TSDeclareFunction` I'm going the easy way to fix this to the Babel way, but I think following TS-ESLint would make sense. There is an [open babel issue](https://github.com/babel/babel/issues/13878) about that. Edit: Ok that not so easy and require updating some logic. --------- Co-authored-by: Boshen --- crates/oxc_ast/src/ast/js.rs | 2 ++ crates/oxc_parser/src/js/function.rs | 20 +++++++++++++------- tasks/coverage/parser_typescript.snap | 18 ++++++++---------- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index cd4ca2c64..079705c30 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -1770,6 +1770,8 @@ pub enum FunctionType { FunctionDeclaration, FunctionExpression, TSDeclareFunction, + /// + TSEmptyBodyFunctionExpression, } /// diff --git a/crates/oxc_parser/src/js/function.rs b/crates/oxc_parser/src/js/function.rs index f53f3a890..ec75f9c56 100644 --- a/crates/oxc_parser/src/js/function.rs +++ b/crates/oxc_parser/src/js/function.rs @@ -105,16 +105,22 @@ impl<'a> ParserImpl<'a> { return Err(self.unexpected()); } - let function_type = if body.is_none() { - FunctionType::TSDeclareFunction - } else { - match func_kind { - FunctionKind::Declaration { .. } | FunctionKind::DefaultExport => { + let function_type = match func_kind { + FunctionKind::Declaration { .. } | FunctionKind::DefaultExport => { + if body.is_none() { + FunctionType::TSDeclareFunction + } else { FunctionType::FunctionDeclaration } - FunctionKind::Expression { .. } => FunctionType::FunctionExpression, - FunctionKind::TSDeclaration { .. } => FunctionType::TSDeclareFunction, } + FunctionKind::Expression { .. } => { + if body.is_none() { + FunctionType::TSEmptyBodyFunctionExpression + } else { + FunctionType::FunctionExpression + } + } + FunctionKind::TSDeclaration { .. } => FunctionType::TSDeclareFunction, }; if FunctionType::TSDeclareFunction == function_type { diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index af6e2bbc0..f03f192e8 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -1326,7 +1326,6 @@ Expect Syntax Error: "compiler/objectLiteralFreshnessWithSpread.ts" Expect Syntax Error: "compiler/objectLiteralFunctionArgContextualTyping.ts" Expect Syntax Error: "compiler/objectLiteralFunctionArgContextualTyping2.ts" Expect Syntax Error: "compiler/objectLiteralIndexerErrors.ts" -Expect Syntax Error: "compiler/objectLiteralMemberWithoutBlock1.ts" Expect Syntax Error: "compiler/objectLiteralParameterResolution.ts" Expect Syntax Error: "compiler/objectLiteralPropertyImplicitlyAny.ts" Expect Syntax Error: "compiler/objectLiteralReferencingInternalProperties.ts" @@ -3550,6 +3549,7 @@ Expect Syntax Error: "conformance/types/nonPrimitive/nonPrimitiveUnionIntersecti Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/callSignatureWithOptionalParameterAndInitializer.ts" Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/callSignaturesThatDifferOnlyByReturnType2.ts" Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/callSignaturesWithParameterInitializers.ts" +Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/callSignaturesWithParameterInitializers2.ts" Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/specializedSignatureIsNotSubtypeOfNonSpecializedSignature.ts" Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/stringLiteralTypesInImplementationSignatures2.ts" Expect Syntax Error: "conformance/types/objectTypeLiteral/callSignatures/typeParameterUsedAsTypeParameterConstraint4.ts" @@ -7941,6 +7941,13 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" · ╰── `,` expected ╰──── + × Expected `,` but found `;` + ╭─[compiler/objectLiteralMemberWithoutBlock1.ts:1:16] + 1 │ var v = { foo(); } + · ┬ + · ╰── `,` expected + ╰──── + × Expected `,` but found `;` ╭─[compiler/objectLiteralWithSemicolons1.ts:1:12] 1 │ var v = { a; b; c } @@ -19577,15 +19584,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" 38 │ } ╰──── - × Expected a semicolon or an implicit semicolon after a statement, but found none - ╭─[conformance/types/objectTypeLiteral/callSignatures/callSignaturesWithParameterInitializers2.ts:20:15] - 19 │ var b = { - 20 │ foo(x = 1), // error - · ▲ - 21 │ foo(x = 1) { }, // error - ╰──── - help: Try insert a semicolon here - × A parameter property is only allowed in a constructor implementation. ╭─[conformance/types/objectTypeLiteral/callSignatures/constructSignatureWithAccessibilityModifiersOnParameters.ts:16:10] 15 │ interface I {