Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions crates/oxc_semantic/src/checker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ pub fn check<'a>(kind: AstKind<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::MethodDefinition(method) => {
ts::check_method_definition(method, ctx);
}
AstKind::PropertyDefinition(prop) => {
ts::check_property_definition(prop, ctx);
}
AstKind::ObjectProperty(prop) => {
ts::check_object_property(prop, ctx);
}
Expand Down
13 changes: 13 additions & 0 deletions crates/oxc_semantic/src/checker/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,12 @@ pub fn check_method_definition<'a>(method: &MethodDefinition<'a>, ctx: &Semantic
if method.kind.is_constructor() {
ctx.error(diagnostics::illegal_abstract_modifier(method.key.span()));
}
// abstract cannot be used with private identifiers
if method.key.is_private_identifier() {
ctx.error(diagnostics::abstract_cannot_be_used_with_private_identifier(
method.key.span(),
));
}
}

let is_empty_body = method.value.r#type == FunctionType::TSEmptyBodyFunctionExpression;
Expand All @@ -289,6 +295,13 @@ pub fn check_method_definition<'a>(method: &MethodDefinition<'a>, ctx: &Semantic
}
}

pub fn check_property_definition(prop: &PropertyDefinition, ctx: &SemanticBuilder<'_>) {
// abstract cannot be used with private identifiers
if prop.r#type.is_abstract() && prop.key.is_private_identifier() {
ctx.error(diagnostics::abstract_cannot_be_used_with_private_identifier(prop.key.span()));
}
}

pub fn check_object_property(prop: &ObjectProperty, ctx: &SemanticBuilder<'_>) {
if let Expression::FunctionExpression(func) = &prop.value
&& prop.kind.is_accessor()
Expand Down
7 changes: 7 additions & 0 deletions crates/oxc_semantic/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,13 @@ pub fn illegal_abstract_modifier(span: Span) -> OxcDiagnostic {
.with_label(span)
}

/// 'abstract' modifier cannot be used with a private identifier. (18019)
#[cold]
pub fn abstract_cannot_be_used_with_private_identifier(span: Span) -> OxcDiagnostic {
ts_error("18019", "'abstract' modifier cannot be used with a private identifier.")
.with_label(span)
}

/// A parameter property is only allowed in a constructor implementation.ts(2369)
#[cold]
pub fn parameter_property_only_in_constructor_impl(span: Span) -> OxcDiagnostic {
Expand Down
34 changes: 28 additions & 6 deletions tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@ commit: fc58af40

parser_babel Summary:
AST Parsed : 2221/2227 (99.73%)
Positive Passed: 2206/2227 (99.06%)
Negative Passed: 1647/1689 (97.51%)
Positive Passed: 2205/2227 (99.01%)
Negative Passed: 1649/1689 (97.63%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026/explicit-resource-management/invalid-for-using-of-no-initializer/input.js

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/estree/class-private-property/typescript-invalid-abstract/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-assert-and-assign/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/cast/unparenthesized-type-assertion-and-assign/input.ts
Expand All @@ -30,8 +28,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/ty

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/modifiers-invalid-order/input.ts

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

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/invalid-namespace-var/input.ts

Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/module-class/input.ts
Expand Down Expand Up @@ -218,6 +214,16 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2026
· ╰── Opened here
╰────

Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/estree/class-private-method/typescript-invalid-abstract/input.ts

× TS(18019): 'abstract' modifier cannot be used with a private identifier.
╭─[babel/packages/babel-parser/test/fixtures/estree/class-private-method/typescript-invalid-abstract/input.ts:2:12]
1 │ abstract class TSAbstractClass {
2 │ abstract #foo(name: string): boolean;
· ────
3 │ }
╰────

Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/constructor-with-modifier-names/input.ts

× Multiple constructor implementations are not allowed.
Expand Down Expand Up @@ -12170,6 +12176,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
╰────
help: Add an initializer (e.g. ` = undefined`) here

× TS(18019): 'abstract' modifier cannot be used with a private identifier.
╭─[babel/packages/babel-parser/test/fixtures/estree/class-private-property/typescript-invalid-abstract/input.ts:2:12]
1 │ abstract class TSAbstractClass {
2 │ abstract #foo: boolean;
· ────
3 │ }
╰────

× A 'set' accessor must have exactly one parameter.
╭─[babel/packages/babel-parser/test/fixtures/estree/typescript/getter-setter/input.ts:3:9]
2 │ ({ get x() { return 1 } });
Expand Down Expand Up @@ -13053,6 +13067,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
8 │ // Also works on AssignmentPattern
╰────

× TS(18019): 'abstract' modifier cannot be used with a private identifier.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/private-fields-modifier-abstract/input.ts:2:12]
1 │ abstract class A {
2 │ abstract #a;
· ──
3 │ }
╰────

× TS(18010): An accessibility modifier cannot be used with a private identifier.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/private-fields-modifier-private/input.ts:2:3]
1 │ class A {
Expand Down
8 changes: 8 additions & 0 deletions tasks/coverage/snapshots/parser_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -14772,6 +14772,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/statements/Va
27 │ async get #asyncProp() { return 1; } // Error
╰────

× TS(18019): 'abstract' modifier cannot be used with a private identifier.
╭─[typescript/tests/cases/conformance/classes/members/privateNames/privateNamesIncompatibleModifiers.ts:32:14]
31 │ abstract class B {
32 │ abstract #quux = 3; // Error
· ─────
33 │ }
╰────

× Private identifier '#prop' is not allowed outside class bodies
╭─[typescript/tests/cases/conformance/classes/members/privateNames/privateNamesInterfaceExtendingClass.ts:10:7]
9 │ function func(x: I) {
Expand Down
4 changes: 1 addition & 3 deletions tasks/coverage/snapshots/semantic_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,7 @@ after transform: ScopeId(1): [ScopeId(2)]
rebuilt : ScopeId(1): []

semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/estree/class-private-method/typescript-invalid-abstract/input.ts
Scope children mismatch:
after transform: ScopeId(1): [ScopeId(2)]
rebuilt : ScopeId(1): []
'abstract' modifier cannot be used with a private identifier.

semantic Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/estree/class-private-property/typescript/input.js
Unresolved references mismatch:
Expand Down
Loading