refactor(semantic): expose 1 checker function instead of 2 (#3694)

This commit is contained in:
Boshen 2024-06-16 00:24:32 +08:00 committed by GitHub
parent de0690f2e5
commit a94a72dc68
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 158 additions and 154 deletions

View file

@ -14,7 +14,7 @@ use oxc_syntax::{
use crate::{
binder::Binder,
checker::{EarlyErrorJavaScript, EarlyErrorTypeScript},
checker,
class::ClassTableBuilder,
control_flow::{
ControlFlowGraphBuilder, CtxCursor, CtxFlags, EdgeType, ErrorEdgeKind,
@ -151,7 +151,7 @@ impl<'a> SemanticBuilder<'a> {
// Checking syntax error on module record requires scope information from the previous AST pass
if self.check_syntax_error {
EarlyErrorJavaScript::check_module_record(&self);
checker::check_module_record(&self);
}
}
@ -449,8 +449,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
fn leave_node(&mut self, kind: AstKind<'a>) {
if self.check_syntax_error {
let node = self.nodes.get_node(self.current_node_id);
EarlyErrorJavaScript::run(node, self);
EarlyErrorTypeScript::run(node, self);
checker::check(node, self);
}
self.leave_kind(kind);
self.pop_ast_node();

View file

@ -16,93 +16,7 @@ use rustc_hash::FxHashMap;
use crate::{builder::SemanticBuilder, diagnostics::redeclaration, scope::ScopeFlags, AstNode};
pub struct EarlyErrorJavaScript;
impl EarlyErrorJavaScript {
pub fn run<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
let kind = node.kind();
match kind {
AstKind::Program(_) => {
check_labeled_statement(ctx);
check_duplicate_class_elements(ctx);
}
AstKind::BindingIdentifier(ident) => {
check_identifier(&ident.name, ident.span, node, ctx);
check_binding_identifier(ident, node, ctx);
}
AstKind::IdentifierReference(ident) => {
check_identifier(&ident.name, ident.span, node, ctx);
check_identifier_reference(ident, node, ctx);
}
AstKind::LabelIdentifier(ident) => check_identifier(&ident.name, ident.span, node, ctx),
AstKind::PrivateIdentifier(ident) => check_private_identifier_outside_class(ident, ctx),
AstKind::NumericLiteral(lit) => check_number_literal(lit, ctx),
AstKind::StringLiteral(lit) => check_string_literal(lit, ctx),
AstKind::RegExpLiteral(lit) => check_regexp_literal(lit, ctx),
AstKind::Directive(dir) => check_directive(dir, ctx),
AstKind::ModuleDeclaration(decl) => {
check_module_declaration(decl, node, ctx);
}
AstKind::MetaProperty(prop) => check_meta_property(prop, node, ctx),
AstKind::WithStatement(stmt) => {
check_function_declaration(&stmt.body, false, ctx);
check_with_statement(stmt, ctx);
}
AstKind::SwitchStatement(stmt) => check_switch_statement(stmt, ctx),
AstKind::BreakStatement(stmt) => check_break_statement(stmt, node, ctx),
AstKind::ContinueStatement(stmt) => check_continue_statement(stmt, node, ctx),
AstKind::LabeledStatement(stmt) => {
check_function_declaration(&stmt.body, true, ctx);
}
AstKind::ForInStatement(stmt) => {
check_function_declaration(&stmt.body, false, ctx);
check_for_statement_left(&stmt.left, true, node, ctx);
}
AstKind::ForOfStatement(stmt) => {
check_function_declaration(&stmt.body, false, ctx);
check_for_statement_left(&stmt.left, false, node, ctx);
}
AstKind::WhileStatement(WhileStatement { body, .. })
| AstKind::DoWhileStatement(DoWhileStatement { body, .. })
| AstKind::ForStatement(ForStatement { body, .. }) => {
check_function_declaration(body, false, ctx);
}
AstKind::IfStatement(stmt) => {
check_function_declaration(&stmt.consequent, true, ctx);
if let Some(alternate) = &stmt.alternate {
check_function_declaration(alternate, true, ctx);
}
}
AstKind::Class(class) => check_class(class, node, ctx),
AstKind::MethodDefinition(method) => check_method_definition(method, ctx),
AstKind::ObjectProperty(prop) => check_object_property(prop, ctx),
AstKind::Super(sup) => check_super(sup, node, ctx),
AstKind::FormalParameters(params) => check_formal_parameters(params, node, ctx),
AstKind::ArrayPattern(pat) => check_array_pattern(pat, ctx),
AstKind::AssignmentExpression(expr) => check_assignment_expression(expr, ctx),
AstKind::AwaitExpression(expr) => check_await_expression(expr, node, ctx),
AstKind::BinaryExpression(expr) => check_binary_expression(expr, ctx),
AstKind::LogicalExpression(expr) => check_logical_expression(expr, ctx),
AstKind::MemberExpression(expr) => check_member_expression(expr, ctx),
AstKind::ObjectExpression(expr) => check_object_expression(expr, ctx),
AstKind::UnaryExpression(expr) => check_unary_expression(expr, node, ctx),
AstKind::YieldExpression(expr) => check_yield_expression(expr, node, ctx),
_ => {}
}
}
pub fn check_module_record(ctx: &SemanticBuilder<'_>) {
check_module_record(ctx);
}
}
fn check_duplicate_class_elements(ctx: &SemanticBuilder<'_>) {
pub fn check_duplicate_class_elements(ctx: &SemanticBuilder<'_>) {
let classes = &ctx.class_table_builder.classes;
classes.iter_enumerated().for_each(|(class_id, _)| {
let mut defined_elements = FxHashMap::default();
@ -149,7 +63,7 @@ fn duplicate_export(x0: &str, span1: Span, span2: Span) -> OxcDiagnostic {
])
}
fn check_module_record(ctx: &SemanticBuilder<'_>) {
pub fn check_module_record(ctx: &SemanticBuilder<'_>) {
// Skip checkking for exports in TypeScript for now
if ctx.source_type.is_typescript() {
return;
@ -214,7 +128,12 @@ pub const STRICT_MODE_NAMES: Set<&'static str> = phf_set! {
"yield",
};
fn check_identifier<'a>(name: &Atom, span: Span, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_identifier<'a>(
name: &Atom,
span: Span,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
// ts module block allows revered keywords
if ctx.current_scope_flags().is_ts_module_block() {
return;
@ -248,7 +167,7 @@ fn invalid_let_declaration(x0: &str, span1: Span) -> OxcDiagnostic {
.with_labels([span1.into()])
}
fn check_binding_identifier<'a>(
pub fn check_binding_identifier<'a>(
ident: &BindingIdentifier,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -280,7 +199,7 @@ fn unexpected_arguments(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("'arguments' is not allowed in {x0}")).with_labels([span1.into()])
}
fn check_identifier_reference<'a>(
pub fn check_identifier_reference<'a>(
ident: &IdentifierReference,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -326,7 +245,10 @@ fn private_not_in_class(x0: &str, span1: Span) -> OxcDiagnostic {
.with_labels([span1.into()])
}
fn check_private_identifier_outside_class(ident: &PrivateIdentifier, ctx: &SemanticBuilder<'_>) {
pub fn check_private_identifier_outside_class(
ident: &PrivateIdentifier,
ctx: &SemanticBuilder<'_>,
) {
if ctx.class_table_builder.current_class_id.is_none() {
ctx.error(private_not_in_class(&ident.name, ident.span));
}
@ -365,7 +287,7 @@ fn leading_zero_decimal(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_number_literal(lit: &NumericLiteral, ctx: &SemanticBuilder<'_>) {
pub fn check_number_literal(lit: &NumericLiteral, ctx: &SemanticBuilder<'_>) {
// NumericLiteral :: legacy_octalIntegerLiteral
// DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
// * It is a Syntax Error if the source text matched by this production is strict mode code.
@ -398,7 +320,7 @@ fn non_octal_decimal_escape_sequence(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_string_literal(lit: &StringLiteral, ctx: &SemanticBuilder<'_>) {
pub fn check_string_literal(lit: &StringLiteral, ctx: &SemanticBuilder<'_>) {
// 12.9.4.1 Static Semantics: Early Errors
// EscapeSequence ::
// legacy_octalEscapeSequence
@ -437,7 +359,7 @@ fn illegal_use_strict(span0: Span) -> OxcDiagnostic {
// It is a Syntax Error if FunctionBodyContainsUseStrict of AsyncFunctionBody is true and IsSimpleParameterList of FormalParameters is false.
// background: https://humanwhocodes.com/blog/2016/10/the-ecmascript-2016-change-you-probably-dont-know/
fn check_directive(directive: &Directive, ctx: &SemanticBuilder<'_>) {
pub fn check_directive(directive: &Directive, ctx: &SemanticBuilder<'_>) {
if directive.directive != "use strict" {
return;
}
@ -466,7 +388,7 @@ fn module_code(x0: &str, span1: Span) -> OxcDiagnostic {
OxcDiagnostic::error(format!("Cannot use {x0} outside a module")).with_labels([span1.into()])
}
fn check_module_declaration<'a>(
pub fn check_module_declaration<'a>(
decl: &ModuleDeclaration,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -523,7 +445,7 @@ fn import_meta_property(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_meta_property<'a>(prop: &MetaProperty, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_meta_property<'a>(prop: &MetaProperty, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
match prop.meta.name.as_str() {
"import" => {
if prop.property.name == "meta" {
@ -573,7 +495,7 @@ fn function_declaration_non_strict(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_function_declaration<'a>(
pub fn check_function_declaration<'a>(
stmt: &Statement<'a>,
is_if_stmt_or_labeled_stmt: bool,
ctx: &SemanticBuilder<'a>,
@ -595,7 +517,7 @@ fn reg_exp_flag_u_and_v(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_regexp_literal(lit: &RegExpLiteral, ctx: &SemanticBuilder<'_>) {
pub fn check_regexp_literal(lit: &RegExpLiteral, ctx: &SemanticBuilder<'_>) {
let flags = lit.regex.flags;
if flags.contains(RegExpFlags::U | RegExpFlags::V) {
ctx.error(reg_exp_flag_u_and_v(lit.span));
@ -606,13 +528,13 @@ fn with_statement(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("'with' statements are not allowed").with_labels([span0.into()])
}
fn check_with_statement(stmt: &WithStatement, ctx: &SemanticBuilder<'_>) {
pub fn check_with_statement(stmt: &WithStatement, ctx: &SemanticBuilder<'_>) {
if ctx.strict_mode() || ctx.source_type.is_typescript() {
ctx.error(with_statement(Span::new(stmt.span.start, stmt.span.start + 4)));
}
}
fn check_switch_statement<'a>(stmt: &SwitchStatement<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_switch_statement<'a>(stmt: &SwitchStatement<'a>, ctx: &SemanticBuilder<'a>) {
let mut previous_default: Option<Span> = None;
for case in &stmt.cases {
if case.test.is_none() {
@ -669,7 +591,11 @@ fn invalid_break(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_break_statement<'a>(stmt: &BreakStatement, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_break_statement<'a>(
stmt: &BreakStatement,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
) {
if let Some(label) = &stmt.label {
return check_label(label, ctx, false);
}
@ -697,7 +623,7 @@ fn invalid_continue(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_continue_statement<'a>(
pub fn check_continue_statement<'a>(
stmt: &ContinueStatement,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -719,7 +645,7 @@ fn check_continue_statement<'a>(
}
#[allow(clippy::option_if_let_else)]
fn check_labeled_statement(ctx: &SemanticBuilder) {
pub fn check_labeled_statement(ctx: &SemanticBuilder) {
ctx.label_builder.labels.iter().for_each(|labels| {
let mut defined = FxHashMap::default();
for labeled in labels {
@ -744,7 +670,7 @@ fn unexpected_initializer_in_for_loop_head(x0: &str, span1: Span) -> OxcDiagnost
.with_labels([span1.into()])
}
fn check_for_statement_left<'a>(
pub fn check_for_statement_left<'a>(
left: &ForStatementLeft,
is_for_in: bool,
_node: &AstNode<'a>,
@ -790,7 +716,7 @@ fn require_class_name(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("A class name is required.").with_labels([span0.into()])
}
fn check_class(class: &Class, node: &AstNode<'_>, ctx: &SemanticBuilder<'_>) {
pub fn check_class(class: &Class, node: &AstNode<'_>, ctx: &SemanticBuilder<'_>) {
check_private_identifier(ctx);
if class.is_declaration()
@ -855,7 +781,7 @@ fn check_getter(function: &Function<'_>, ctx: &SemanticBuilder<'_>) {
}
}
fn check_method_definition(method: &MethodDefinition<'_>, ctx: &SemanticBuilder<'_>) {
pub fn check_method_definition(method: &MethodDefinition<'_>, ctx: &SemanticBuilder<'_>) {
match method.kind {
MethodDefinitionKind::Set => check_setter(&method.value, ctx),
MethodDefinitionKind::Get => check_getter(&method.value, ctx),
@ -882,7 +808,7 @@ fn unexpected_super_reference(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_super<'a>(sup: &Super, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_super<'a>(sup: &Super, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
let super_call_span = match ctx.nodes.parent_kind(node.id()) {
Some(AstKind::CallExpression(expr)) => Some(expr.span),
Some(AstKind::NewExpression(expr)) => Some(expr.span),
@ -973,7 +899,7 @@ fn cover_initialized_name(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_object_property(prop: &ObjectProperty, ctx: &SemanticBuilder<'_>) {
pub fn check_object_property(prop: &ObjectProperty, ctx: &SemanticBuilder<'_>) {
// PropertyDefinition : cover_initialized_name
// It is a Syntax Error if any source text is matched by this production.
if let Some(expr) = &prop.init {
@ -993,7 +919,7 @@ fn a_rest_parameter_cannot_have_an_initializer(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("A rest parameter cannot have an initializer").with_labels([span0.into()])
}
fn check_formal_parameters<'a>(
pub fn check_formal_parameters<'a>(
params: &FormalParameters,
_node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -1005,7 +931,7 @@ fn check_formal_parameters<'a>(
}
}
fn check_array_pattern(pattern: &ArrayPattern, ctx: &SemanticBuilder<'_>) {
pub fn check_array_pattern(pattern: &ArrayPattern, ctx: &SemanticBuilder<'_>) {
// function foo([...x = []]) { }
// ^^^^ A rest element cannot have an initializer
if let Some(rest) = &pattern.rest {
@ -1019,7 +945,7 @@ fn assignment_is_not_simple(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Invalid left-hand side in assignment").with_labels([span0.into()])
}
fn check_assignment_expression(assign_expr: &AssignmentExpression, ctx: &SemanticBuilder<'_>) {
pub fn check_assignment_expression(assign_expr: &AssignmentExpression, ctx: &SemanticBuilder<'_>) {
// AssignmentExpression :
// LeftHandSideExpression AssignmentOperator AssignmentExpression
// LeftHandSideExpression &&= AssignmentExpression
@ -1033,7 +959,7 @@ fn check_assignment_expression(assign_expr: &AssignmentExpression, ctx: &Semanti
}
}
fn check_object_expression(obj_expr: &ObjectExpression, ctx: &SemanticBuilder<'_>) {
pub fn check_object_expression(obj_expr: &ObjectExpression, ctx: &SemanticBuilder<'_>) {
// ObjectLiteral : { PropertyDefinitionList }
// It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains any duplicate entries for "__proto__"
// and at least two of those entries were obtained from productions of the form PropertyDefinition : PropertyName : AssignmentExpression
@ -1055,7 +981,7 @@ fn unexpected_exponential(x0: &str, span1: Span) -> OxcDiagnostic {
.with_labels([span1.into()])
}
fn check_binary_expression(binary_expr: &BinaryExpression, ctx: &SemanticBuilder<'_>) {
pub fn check_binary_expression(binary_expr: &BinaryExpression, ctx: &SemanticBuilder<'_>) {
if binary_expr.operator == BinaryOperator::Exponential {
match binary_expr.left {
// async () => await 5 ** 6
@ -1078,7 +1004,7 @@ fn mixed_coalesce(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_logical_expression(logical_expr: &LogicalExpression, ctx: &SemanticBuilder<'_>) {
pub fn check_logical_expression(logical_expr: &LogicalExpression, ctx: &SemanticBuilder<'_>) {
// check mixed coalesce
// a ?? b || c - a ?? (b || c)
// a ?? b && c - a ?? (b && c)
@ -1103,7 +1029,7 @@ fn super_private(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Private fields cannot be accessed on super").with_labels([span0.into()])
}
fn check_member_expression(member_expr: &MemberExpression, ctx: &SemanticBuilder<'_>) {
pub fn check_member_expression(member_expr: &MemberExpression, ctx: &SemanticBuilder<'_>) {
if let MemberExpression::PrivateFieldExpression(private_expr) = member_expr {
// super.#m
if let Expression::Super(_) = &private_expr.object {
@ -1121,7 +1047,7 @@ fn delete_private_field(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Private fields can not be deleted").with_labels([span0.into()])
}
fn check_unary_expression<'a>(
pub fn check_unary_expression<'a>(
unary_expr: &'a UnaryExpression,
_node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -1162,7 +1088,7 @@ fn await_or_yield_in_parameter(x0: &str, span1: Span) -> OxcDiagnostic {
])
}
fn check_await_expression<'a>(
pub fn check_await_expression<'a>(
expr: &AwaitExpression,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,
@ -1177,7 +1103,7 @@ fn check_await_expression<'a>(
}
}
fn check_yield_expression<'a>(
pub fn check_yield_expression<'a>(
expr: &YieldExpression,
node: &AstNode<'a>,
ctx: &SemanticBuilder<'a>,

View file

@ -1,5 +1,105 @@
mod javascript;
mod typescript;
pub use javascript::EarlyErrorJavaScript;
pub use typescript::EarlyErrorTypeScript;
use javascript as js;
use typescript as ts;
use oxc_ast::{
ast::{DoWhileStatement, ForStatement, WhileStatement},
AstKind,
};
use crate::{builder::SemanticBuilder, AstNode};
pub use javascript::check_module_record;
pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
let kind = node.kind();
match kind {
AstKind::Program(_) => {
js::check_labeled_statement(ctx);
js::check_duplicate_class_elements(ctx);
}
AstKind::BindingIdentifier(ident) => {
js::check_identifier(&ident.name, ident.span, node, ctx);
js::check_binding_identifier(ident, node, ctx);
}
AstKind::IdentifierReference(ident) => {
js::check_identifier(&ident.name, ident.span, node, ctx);
js::check_identifier_reference(ident, node, ctx);
}
AstKind::LabelIdentifier(ident) => js::check_identifier(&ident.name, ident.span, node, ctx),
AstKind::PrivateIdentifier(ident) => js::check_private_identifier_outside_class(ident, ctx),
AstKind::NumericLiteral(lit) => js::check_number_literal(lit, ctx),
AstKind::StringLiteral(lit) => js::check_string_literal(lit, ctx),
AstKind::RegExpLiteral(lit) => js::check_regexp_literal(lit, ctx),
AstKind::Directive(dir) => js::check_directive(dir, ctx),
AstKind::ModuleDeclaration(decl) => {
js::check_module_declaration(decl, node, ctx);
}
AstKind::MetaProperty(prop) => js::check_meta_property(prop, node, ctx),
AstKind::WithStatement(stmt) => {
js::check_function_declaration(&stmt.body, false, ctx);
js::check_with_statement(stmt, ctx);
}
AstKind::SwitchStatement(stmt) => js::check_switch_statement(stmt, ctx),
AstKind::BreakStatement(stmt) => js::check_break_statement(stmt, node, ctx),
AstKind::ContinueStatement(stmt) => js::check_continue_statement(stmt, node, ctx),
AstKind::LabeledStatement(stmt) => {
js::check_function_declaration(&stmt.body, true, ctx);
}
AstKind::ForInStatement(stmt) => {
js::check_function_declaration(&stmt.body, false, ctx);
js::check_for_statement_left(&stmt.left, true, node, ctx);
}
AstKind::ForOfStatement(stmt) => {
js::check_function_declaration(&stmt.body, false, ctx);
js::check_for_statement_left(&stmt.left, false, node, ctx);
}
AstKind::WhileStatement(WhileStatement { body, .. })
| AstKind::DoWhileStatement(DoWhileStatement { body, .. })
| AstKind::ForStatement(ForStatement { body, .. }) => {
js::check_function_declaration(body, false, ctx);
}
AstKind::IfStatement(stmt) => {
js::check_function_declaration(&stmt.consequent, true, ctx);
if let Some(alternate) = &stmt.alternate {
js::check_function_declaration(alternate, true, ctx);
}
}
AstKind::Class(class) => js::check_class(class, node, ctx),
AstKind::MethodDefinition(method) => js::check_method_definition(method, ctx),
AstKind::ObjectProperty(prop) => js::check_object_property(prop, ctx),
AstKind::Super(sup) => js::check_super(sup, node, ctx),
AstKind::FormalParameters(params) => {
js::check_formal_parameters(params, node, ctx);
ts::check_formal_parameters(params, ctx);
}
AstKind::ArrayPattern(pat) => {
js::check_array_pattern(pat, ctx);
ts::check_array_pattern(pat, ctx);
}
AstKind::AssignmentExpression(expr) => js::check_assignment_expression(expr, ctx),
AstKind::AwaitExpression(expr) => js::check_await_expression(expr, node, ctx),
AstKind::BinaryExpression(expr) => js::check_binary_expression(expr, ctx),
AstKind::LogicalExpression(expr) => js::check_logical_expression(expr, ctx),
AstKind::MemberExpression(expr) => js::check_member_expression(expr, ctx),
AstKind::ObjectExpression(expr) => js::check_object_expression(expr, ctx),
AstKind::UnaryExpression(expr) => js::check_unary_expression(expr, node, ctx),
AstKind::YieldExpression(expr) => js::check_yield_expression(expr, node, ctx),
AstKind::VariableDeclarator(decl) => ts::check_variable_declarator(decl, ctx),
AstKind::SimpleAssignmentTarget(target) => ts::check_simple_assignment_target(target, ctx),
AstKind::TSTypeParameterDeclaration(declaration) => {
ts::check_ts_type_parameter_declaration(declaration, ctx);
}
AstKind::TSModuleDeclaration(decl) => ts::check_ts_module_declaration(decl, ctx),
AstKind::TSEnumDeclaration(decl) => ts::check_ts_enum_declaration(decl, ctx),
_ => {}
}
}

View file

@ -5,34 +5,13 @@ use oxc_diagnostics::OxcDiagnostic;
use oxc_span::{Atom, GetSpan, Span};
use rustc_hash::FxHashMap;
use crate::{builder::SemanticBuilder, diagnostics::redeclaration, AstNode};
pub struct EarlyErrorTypeScript;
impl EarlyErrorTypeScript {
pub fn run<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
let kind = node.kind();
match kind {
AstKind::VariableDeclarator(decl) => check_variable_declarator(decl, ctx),
AstKind::SimpleAssignmentTarget(target) => check_simple_assignment_target(target, ctx),
AstKind::FormalParameters(params) => check_formal_parameters(params, ctx),
AstKind::ArrayPattern(pattern) => check_array_pattern(pattern, ctx),
AstKind::TSTypeParameterDeclaration(declaration) => {
check_ts_type_parameter_declaration(declaration, ctx);
}
AstKind::TSModuleDeclaration(decl) => check_ts_module_declaration(decl, ctx),
AstKind::TSEnumDeclaration(decl) => check_ts_enum_declaration(decl, ctx),
_ => {}
}
}
}
use crate::{builder::SemanticBuilder, diagnostics::redeclaration};
fn empty_type_parameter_list(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Type parameter list cannot be empty.").with_labels([span0.into()])
}
fn check_ts_type_parameter_declaration(
pub fn check_ts_type_parameter_declaration(
declaration: &TSTypeParameterDeclaration<'_>,
ctx: &SemanticBuilder<'_>,
) {
@ -46,7 +25,7 @@ fn unexpected_optional(span0: Span) -> OxcDiagnostic {
}
#[allow(clippy::cast_possible_truncation)]
fn check_variable_declarator(decl: &VariableDeclarator, ctx: &SemanticBuilder<'_>) {
pub fn check_variable_declarator(decl: &VariableDeclarator, ctx: &SemanticBuilder<'_>) {
if decl.id.optional {
let start = decl.id.span().end;
let Some(offset) = ctx.source_text[start as usize..].find('?') else { return };
@ -65,7 +44,7 @@ fn parameter_property_outside_constructor(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_formal_parameters(params: &FormalParameters, ctx: &SemanticBuilder<'_>) {
pub fn check_formal_parameters(params: &FormalParameters, ctx: &SemanticBuilder<'_>) {
if !params.is_empty() && params.kind == FormalParameterKind::Signature {
check_duplicate_bound_names(params, ctx);
}
@ -105,7 +84,7 @@ fn unexpected_assignment(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_simple_assignment_target<'a>(
pub fn check_simple_assignment_target<'a>(
target: &SimpleAssignmentTarget<'a>,
ctx: &SemanticBuilder<'a>,
) {
@ -125,7 +104,7 @@ fn unexpected_type_annotation(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Unexpected type annotation").with_labels([span0.into()])
}
fn check_array_pattern<'a>(pattern: &ArrayPattern<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_array_pattern<'a>(pattern: &ArrayPattern<'a>, ctx: &SemanticBuilder<'a>) {
for element in &pattern.elements {
let _ = element.as_ref().map(|element| {
if let Some(type_annotation) = &element.type_annotation {
@ -142,7 +121,7 @@ fn not_allowed_namespace_declaration(span0: Span) -> OxcDiagnostic {
.with_labels([span0.into()])
}
fn check_ts_module_declaration<'a>(decl: &TSModuleDeclaration<'a>, ctx: &SemanticBuilder<'a>) {
pub fn check_ts_module_declaration<'a>(decl: &TSModuleDeclaration<'a>, ctx: &SemanticBuilder<'a>) {
// skip current node
for node in ctx.nodes.iter_parents(ctx.current_node_id).skip(1) {
match node.kind() {
@ -165,7 +144,7 @@ fn enum_member_must_have_initializer(span0: Span) -> OxcDiagnostic {
OxcDiagnostic::error("Enum member must have initializer.").with_labels([span0.into()])
}
fn check_ts_enum_declaration(decl: &TSEnumDeclaration<'_>, ctx: &SemanticBuilder<'_>) {
pub fn check_ts_enum_declaration(decl: &TSEnumDeclaration<'_>, ctx: &SemanticBuilder<'_>) {
let mut need_initializer = false;
decl.members.iter().for_each(|member| {