use oxc_ast::{AstKind, ast::*, match_module_declaration};
use crate::builder::SemanticBuilder;
mod javascript;
mod typescript;
use javascript as js;
use typescript as ts;
pub use javascript::is_function_decl_part_of_if_statement;
#[expect(clippy::inline_always, reason = "enables compile-time match elimination, see doc comment")]
#[inline(always)]
pub fn check<'a>(kind: AstKind<'a>, ctx: &SemanticBuilder<'a>) {
match kind {
AstKind::Program(program) => {
js::check_duplicate_class_elements(ctx);
js::check_unresolved_exports(program, ctx);
js::check_import_value_redeclarations(ctx);
ts::check_ts_export_assignment_in_program(program, ctx);
}
AstKind::BindingIdentifier(ident) => {
js::check_identifier(&ident.name, ident.span, ident.symbol_id.get(), ctx);
js::check_binding_identifier(ident, ctx);
}
AstKind::IdentifierReference(ident) => {
js::check_identifier(&ident.name, ident.span, None, ctx);
js::check_identifier_reference(ident, ctx);
}
AstKind::LabelIdentifier(ident) => js::check_identifier(&ident.name, ident.span, None, 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::Directive(dir) => js::check_directive(dir, ctx),
match_module_declaration!(AstKind) => {
let mod_decl_kind = kind.as_module_declaration_kind().unwrap();
js::check_module_declaration(&mod_decl_kind, ctx);
}
AstKind::MetaProperty(prop) => js::check_meta_property(prop, 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, ctx),
AstKind::ContinueStatement(stmt) => js::check_continue_statement(stmt, ctx),
AstKind::LabeledStatement(stmt) => {
js::check_labeled_statement(stmt, ctx);
js::check_function_declaration_in_labeled_statement(&stmt.body, ctx);
}
AstKind::ForInStatement(stmt) => {
js::check_function_declaration(&stmt.body, false, ctx);
js::check_for_statement_left(&stmt.left, true, ctx);
ts::check_for_statement_left(&stmt.left, true, ctx);
}
AstKind::ForOfStatement(stmt) => {
js::check_function_declaration(&stmt.body, false, ctx);
js::check_for_of_statement(stmt, ctx);
js::check_for_statement_left(&stmt.left, false, ctx);
ts::check_for_statement_left(&stmt.left, false, 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, ctx);
if !ctx.source_type.is_typescript() {
js::check_class_redeclaration(class, ctx);
}
ts::check_class(class, ctx);
}
AstKind::Function(func) if !ctx.source_type.is_typescript() => {
js::check_function_redeclaration(func, ctx);
}
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);
}
AstKind::Super(sup) => js::check_super(sup, ctx),
AstKind::FormalParameters(params) => {
ts::check_formal_parameters(params, ctx);
}
AstKind::AssignmentExpression(expr) => js::check_assignment_expression(expr, ctx),
AstKind::AwaitExpression(expr) => js::check_await_expression(expr, ctx),
AstKind::PrivateFieldExpression(expr) => js::check_private_field_expression(expr, ctx),
AstKind::ObjectExpression(expr) => js::check_object_expression(expr, ctx),
AstKind::UnaryExpression(expr) => js::check_unary_expression(expr, ctx),
AstKind::YieldExpression(expr) => js::check_yield_expression(expr, ctx),
AstKind::VariableDeclaration(decl) => {
js::check_variable_declaration(decl, ctx);
}
AstKind::VariableDeclarator(decl) if !ctx.source_type.is_typescript() => {
js::check_variable_declarator_redeclaration(decl, ctx);
}
AstKind::TSTypeAnnotation(annot) => ts::check_ts_type_annotation(annot, ctx),
AstKind::TSInterfaceDeclaration(decl) => ts::check_ts_interface_declaration(decl, ctx),
AstKind::TSTypeParameter(param) => ts::check_ts_type_parameter(param, ctx),
AstKind::TSModuleDeclaration(decl) => ts::check_ts_module_declaration(decl, ctx),
AstKind::TSGlobalDeclaration(decl) => ts::check_ts_global_declaration(decl, ctx),
AstKind::TSEnumDeclaration(decl) => ts::check_ts_enum_declaration(decl, ctx),
AstKind::TSTypeAliasDeclaration(decl) => ts::check_ts_type_alias_declaration(decl, ctx),
AstKind::TSInferType(infer_type) => ts::check_ts_infer_type(infer_type, ctx),
AstKind::TSImportEqualsDeclaration(decl) => {
ts::check_ts_import_equals_declaration(decl, ctx);
}
AstKind::JSXExpressionContainer(container) => {
ts::check_jsx_expression_container(container, ctx);
}
_ => {}
}
}