Skip to content

Commit

Permalink
fix(semantic): report errors for missing class method impls (#8082)
Browse files Browse the repository at this point in the history
  • Loading branch information
camc314 committed Dec 25, 2024
1 parent de82492 commit 708e9cf
Show file tree
Hide file tree
Showing 5 changed files with 550 additions and 81 deletions.
26 changes: 22 additions & 4 deletions crates/oxc_semantic/src/checker/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,13 @@ fn constructor_implementation_missing(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Constructor implementation is missing.").with_label(span)
}

fn function_implementation_missing(span: Span) -> OxcDiagnostic {
OxcDiagnostic::error(
"Function implementation is missing or not immediately following the declaration.",
)
.with_label(span)
}

pub fn check_class<'a>(class: &Class<'a>, ctx: &SemanticBuilder<'a>) {
if !class.r#abstract {
for elem in &class.body.body {
Expand All @@ -348,13 +355,24 @@ pub fn check_class<'a>(class: &Class<'a>, ctx: &SemanticBuilder<'a>) {
if !class.r#declare && !ctx.in_declare_scope() {
for (a, b) in class.body.body.iter().map(Some).chain(vec![None]).tuple_windows() {
if let Some(ClassElement::MethodDefinition(a)) = a {
if a.kind.is_constructor()
if !a.r#type.is_abstract()
&& !a.optional
&& a.value.r#type == FunctionType::TSEmptyBodyFunctionExpression
&& b.map_or(true, |b| {
b.method_definition_kind().map_or(true, |kind| !kind.is_constructor())
&& b.map_or(true, |b| match b {
ClassElement::StaticBlock(_)
| ClassElement::PropertyDefinition(_)
| ClassElement::AccessorProperty(_)
| ClassElement::TSIndexSignature(_) => true,
ClassElement::MethodDefinition(b) => {
b.key.static_name() != a.key.static_name()
}
})
{
ctx.error(constructor_implementation_missing(a.key.span()));
if a.kind.is_constructor() {
ctx.error(constructor_implementation_missing(a.key.span()));
} else {
ctx.error(function_implementation_missing(a.key.span()));
};
}
}
}
Expand Down
104 changes: 103 additions & 1 deletion tasks/coverage/snapshots/parser_babel.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ commit: 54a8389f

parser_babel Summary:
AST Parsed : 2205/2218 (99.41%)
Positive Passed: 2190/2218 (98.74%)
Positive Passed: 2184/2218 (98.47%)
Negative Passed: 1522/1634 (93.15%)
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/annex-b/enabled/3.1-sloppy-labeled-functions-if-body/input.js
Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-fn-decl-labeled-inside-if/input.js
Expand Down Expand Up @@ -304,6 +304,91 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ╰── It can not be redeclared here
5 │ f();
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names/input.ts

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names/input.ts:2:5]
1 │ class C {
2 │ public(): void;
· ──────
3 │ public static(): void;
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names/input.ts:3:12]
2 │ public(): void;
3 │ public static(): void;
· ──────
4 │ readonly = 0;
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names/input.ts:5:5]
4 │ readonly = 0;
5 │ async<T>(): void;
· ─────
6 │ abstract!:void;
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names-babel-7/input.ts

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names-babel-7/input.ts:2:5]
1 │ class C {
2 │ public(): void;
· ──────
3 │ public static(): void;
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names-babel-7/input.ts:3:12]
2 │ public(): void;
3 │ public static(): void;
· ──────
4 │ readonly = 0;
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-modifier-names-babel-7/input.ts:5:5]
4 │ readonly = 0;
5 │ async<T>(): void;
· ─────
6 │ abstract!:void;
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/members-with-reserved-names/input.ts

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/members-with-reserved-names/input.ts:2:12]
1 │ class C {
2 │ public delete(): void;
· ──────
3 │ }
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/method-no-body/input.ts

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/method-no-body/input.ts:3:5]
2 │ f();
3 │ f(): void;
· ─
4 │ }
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/method-with-newline-without-body/input.ts

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/method-with-newline-without-body/input.ts:3:5]
2 │ {
3 │ m()
· ─
4 │ n()
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/method-with-newline-without-body/input.ts:4:5]
3 │ m()
4 │ n()
· ─
5 │ }
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/modifiers-override/input.ts

× Identifier `show` has already been declared
Expand Down Expand Up @@ -399,6 +484,15 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
· ╰── It can not be redeclared here
8 │ }
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/class/static/input.ts

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/static/input.ts:5:20]
4 │ protected static f();
5 │ private static f();
· ─
6 │ }
╰────
Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typescript/declare/eval/input.ts

× Cannot assign to 'eval' in strict mode
Expand Down Expand Up @@ -11600,6 +11694,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc
× Getters and setters must have an implementation.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/declare-accessor/input.ts:3:15]
2 │ declare get foo()
3 │ declare set foo(v)
· ───
4 │ }
╰────

× Function implementation is missing or not immediately following the declaration.
╭─[babel/packages/babel-parser/test/fixtures/typescript/class/declare-accessor/input.ts:3:15]
2 │ declare get foo()
3 │ declare set foo(v)
· ───
4 │ }
Expand Down
Loading

0 comments on commit 708e9cf

Please sign in to comment.