From 28daf83b19ad792866f2e4f6fdb82e0c600d287d Mon Sep 17 00:00:00 2001 From: Boshen Date: Fri, 2 Feb 2024 19:05:00 +0800 Subject: [PATCH] feat(semantic): report no class name error (#2273) closes #2144 --- crates/oxc_semantic/src/checker/javascript.rs | 20 +++++++++++++++++-- tasks/coverage/misc/fail/oxc-2144.js | 2 ++ tasks/coverage/parser_misc.snap | 16 ++++++++++++++- tasks/coverage/parser_typescript.snap | 11 ++++++++-- 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 tasks/coverage/misc/fail/oxc-2144.js diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index d52a869ac..9e49191bb 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -77,7 +77,7 @@ impl EarlyErrorJavaScript { } } - AstKind::Class(class) => check_class(class, ctx), + AstKind::Class(class) => check_class(class, node, ctx), AstKind::Super(sup) => check_super(sup, node, ctx), AstKind::ObjectProperty(prop) => check_object_property(prop, ctx), @@ -743,7 +743,7 @@ fn check_for_statement_left<'a>( } } -fn check_class(class: &Class, ctx: &SemanticBuilder<'_>) { +fn check_class(class: &Class, node: &AstNode<'_>, ctx: &SemanticBuilder<'_>) { #[derive(Debug, Error, Diagnostic)] #[error("Multiple constructor implementations are not allowed.")] #[diagnostic()] @@ -752,8 +752,24 @@ fn check_class(class: &Class, ctx: &SemanticBuilder<'_>) { #[label("it cannot be redeclared here")] Span, ); + #[derive(Debug, Error, Diagnostic)] + #[error("A class name is required.")] + #[diagnostic()] + struct RequireClassName(#[label] Span); + check_private_identifier(ctx); + if class.is_declaration() + && class.id.is_none() + && !matches!( + ctx.nodes.parent_kind(node.id()), + Some(AstKind::ModuleDeclaration(ModuleDeclaration::ExportDefaultDeclaration(_))) + ) + { + let start = class.span.start; + ctx.error(RequireClassName(Span::new(start, start + 5))); + } + // ClassBody : ClassElementList // It is a Syntax Error if PrototypePropertyNameList of ClassElementList contains more than one occurrence of "constructor". let mut prev_constructor: Option = None; diff --git a/tasks/coverage/misc/fail/oxc-2144.js b/tasks/coverage/misc/fail/oxc-2144.js new file mode 100644 index 000000000..c3d493f78 --- /dev/null +++ b/tasks/coverage/misc/fail/oxc-2144.js @@ -0,0 +1,2 @@ +class {} +export class {} diff --git a/tasks/coverage/parser_misc.snap b/tasks/coverage/parser_misc.snap index 1aecd537e..0a33d3fe1 100644 --- a/tasks/coverage/parser_misc.snap +++ b/tasks/coverage/parser_misc.snap @@ -1,7 +1,7 @@ parser_misc Summary: AST Parsed : 10/10 (100.00%) Positive Passed: 10/10 (100.00%) -Negative Passed: 6/6 (100.00%) +Negative Passed: 7/7 (100.00%) × Unexpected token ╭─[fail/oxc-169.js:1:1] @@ -24,6 +24,20 @@ Negative Passed: 6/6 (100.00%) 3 │ } ╰──── + × A class name is required. + ╭─[fail/oxc-2144.js:1:1] + 1 │ class {} + · ───── + 2 │ export class {} + ╰──── + + × A class name is required. + ╭─[fail/oxc-2144.js:2:8] + 1 │ class {} + 2 │ export class {} + · ───── + ╰──── + × Unexpected `?` operator ╭─[fail/oxc-2253.ts:1:8] 1 │ const a? = "A" diff --git a/tasks/coverage/parser_typescript.snap b/tasks/coverage/parser_typescript.snap index 33d4737d6..cdfd07ef3 100644 --- a/tasks/coverage/parser_typescript.snap +++ b/tasks/coverage/parser_typescript.snap @@ -1,7 +1,7 @@ parser_typescript Summary: AST Parsed : 5239/5243 (99.92%) Positive Passed: 5232/5243 (99.79%) -Negative Passed: 1035/4879 (21.21%) +Negative Passed: 1036/4879 (21.23%) Expect Syntax Error: "compiler/ClassDeclaration10.ts" Expect Syntax Error: "compiler/ClassDeclaration11.ts" Expect Syntax Error: "compiler/ClassDeclaration13.ts" @@ -664,7 +664,6 @@ Expect Syntax Error: "compiler/expandoFunctionContextualTypesNoValue.ts" Expect Syntax Error: "compiler/exportAlreadySeen.ts" Expect Syntax Error: "compiler/exportAsNamespaceConflict.ts" Expect Syntax Error: "compiler/exportAssignmentWithExports.ts" -Expect Syntax Error: "compiler/exportClassWithoutName.ts" Expect Syntax Error: "compiler/exportDeclarationsInAmbientNamespaces2.ts" Expect Syntax Error: "compiler/exportDeclareClass1.ts" Expect Syntax Error: "compiler/exportDefaultAlias_excludesEverything.ts" @@ -6326,6 +6325,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts" · ────── ╰──── + × A class name is required. + ╭─[compiler/exportClassWithoutName.ts:3:8] + 2 │ //@target: es2015 + 3 │ export class { + · ───── + 4 │ } + ╰──── + × Unexpected token ╭─[compiler/exportDeclarationInInternalModule.ts:17:19] 16 │