Skip to content

Commit

Permalink
feat(semantic): check for non-declared, non-abstract object accessors…
Browse files Browse the repository at this point in the history
… without bodies (#5461)
  • Loading branch information
DonIsaac committed Sep 5, 2024
1 parent 5407143 commit 62f7fff
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 4 deletions.
11 changes: 11 additions & 0 deletions crates/oxc_ast/src/ast_impl/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,15 @@ impl<'a> PropertyKey<'a> {
}
}

impl PropertyKind {
/// Returns `true` if this property is a getter or setter.
///
/// Analogous to [`MethodDefinitionKind::is_accessor`].
pub fn is_accessor(self) -> bool {
matches!(self, Self::Get | Self::Set)
}
}

impl<'a> TemplateLiteral<'a> {
pub fn is_no_substitution_template(&self) -> bool {
self.expressions.is_empty() && self.quasis.len() == 1
Expand Down Expand Up @@ -1424,6 +1433,8 @@ impl MethodDefinitionKind {
}

/// Returns `true` if this method is a getter or a setter.
///
/// Analogous to [`PropertyKind::is_accessor`].
pub fn is_accessor(&self) -> bool {
matches!(self, Self::Get | Self::Set)
}
Expand Down
5 changes: 4 additions & 1 deletion crates/oxc_semantic/src/checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
ts::check_method_definition(method, ctx);
}
AstKind::PropertyDefinition(prop) => ts::check_property_definition(prop, ctx),
AstKind::ObjectProperty(prop) => js::check_object_property(prop, ctx),
AstKind::ObjectProperty(prop) => {
js::check_object_property(prop, ctx);
ts::check_object_property(prop, ctx);
}
AstKind::Super(sup) => js::check_super(sup, node, ctx),

AstKind::FormalParameters(params) => {
Expand Down
10 changes: 10 additions & 0 deletions crates/oxc_semantic/src/checker/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -359,3 +359,13 @@ pub fn check_property_definition<'a>(prop: &PropertyDefinition<'a>, ctx: &Semant
ctx.error(abstract_property_cannot_have_initializer(prop_name, span));
}
}

pub fn check_object_property(prop: &ObjectProperty, ctx: &SemanticBuilder<'_>) {
if let Expression::FunctionExpression(func) = &prop.value {
if prop.kind.is_accessor()
&& matches!(func.r#type, FunctionType::TSEmptyBodyFunctionExpression)
{
ctx.error(accessor_without_body(prop.key.span()));
}
}
}
16 changes: 13 additions & 3 deletions tasks/coverage/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ commit: a709f989
parser_typescript Summary:
AST Parsed : 6470/6479 (99.86%)
Positive Passed: 6445/6479 (99.48%)
Negative Passed: 1201/5715 (21.01%)
Negative Passed: 1203/5715 (21.05%)
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration10.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration11.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/ClassDeclaration13.ts
Expand Down Expand Up @@ -31,8 +31,6 @@ Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorAcci
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorDeclarationEmitVisibilityErrors.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorInferredReturnTypeErrorInReturnStatement.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorWithInitializer.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorWithoutBody1.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorWithoutBody2.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessorsInAmbientContext.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/accessors_spec_section-4.5_error-cases.ts
Expect Syntax Error: tasks/coverage/typescript/tests/cases/compiler/addMoreOverloadsToBaseSignature.ts
Expand Down Expand Up @@ -5077,6 +5075,18 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/salsa/typeFro
4 │ }
╰────

× Getters and setters must have an implementation.
╭─[typescript/tests/cases/compiler/accessorWithoutBody1.ts:1:15]
1 │ var v = { get foo() }
· ───
╰────

× Getters and setters must have an implementation.
╭─[typescript/tests/cases/compiler/accessorWithoutBody2.ts:1:15]
1 │ var v = { set foo(a) }
· ───
╰────

× Unexpected token
╭─[typescript/tests/cases/compiler/aliasErrors.ts:13:12]
12 │ import m2 = no.mod;
Expand Down

0 comments on commit 62f7fff

Please sign in to comment.