1use crate::state::CheckerState;
2use crate::statements::StatementCheckCallbacks;
3use tsz_parser::parser::{NodeIndex, syntax_kind_ext};
4use tsz_solver::TypeId;
5
6impl<'a> StatementCheckCallbacks for CheckerState<'a> {
12 fn arena(&self) -> &tsz_parser::parser::node::NodeArena {
13 self.ctx.arena
14 }
15
16 fn get_type_of_node(&mut self, idx: NodeIndex) -> TypeId {
17 CheckerState::get_type_of_node(self, idx)
18 }
19
20 fn get_type_of_node_no_narrowing(&mut self, idx: NodeIndex) -> TypeId {
21 let prev = self.ctx.skip_flow_narrowing;
22 self.ctx.skip_flow_narrowing = true;
23 let ty = CheckerState::get_type_of_node(self, idx);
24 self.ctx.skip_flow_narrowing = prev;
25 ty
26 }
27
28 fn check_variable_statement(&mut self, stmt_idx: NodeIndex) {
29 CheckerState::check_variable_statement(self, stmt_idx);
30 }
31
32 fn check_variable_declaration_list(&mut self, list_idx: NodeIndex) {
33 CheckerState::check_variable_declaration_list(self, list_idx);
34 }
35
36 fn check_variable_declaration(&mut self, decl_idx: NodeIndex) {
37 CheckerState::check_variable_declaration(self, decl_idx);
38 }
39
40 fn check_return_statement(&mut self, stmt_idx: NodeIndex) {
41 CheckerState::check_return_statement(self, stmt_idx);
42 }
43
44 fn check_function_implementations(&mut self, stmts: &[NodeIndex]) {
45 CheckerState::check_function_implementations(self, stmts);
46 }
47
48 fn check_function_declaration(&mut self, func_idx: NodeIndex) {
49 let Some(node) = self.ctx.arena.get(func_idx) else {
50 return;
51 };
52
53 if node.kind == syntax_kind_ext::FUNCTION_DECLARATION {
56 let mut checker = crate::declarations::DeclarationChecker::new(&mut self.ctx);
57 checker.check_function_declaration(func_idx);
58 }
59
60 let Some(node) = self.ctx.arena.get(func_idx) else {
62 return;
63 };
64
65 let Some(func) = self.ctx.arena.get_function(node) else {
66 return;
67 };
68
69 if self.is_strict_mode_for_node(func_idx)
71 && func.name.is_some()
72 && let Some(func_name_node) = self.ctx.arena.get(func.name)
73 && let Some(ident) = self.ctx.arena.get_identifier(func_name_node)
74 {
75 if ident.escaped_text == "arguments" || ident.escaped_text == "eval" {
76 self.error_at_node_msg(
77 func.name,
78 crate::diagnostics::diagnostic_codes::INVALID_USE_OF_IN_STRICT_MODE,
79 &[&ident.escaped_text],
80 );
81 }
82
83 if crate::state_checking::is_strict_mode_reserved_name(&ident.escaped_text) {
85 use crate::diagnostics::{diagnostic_codes, diagnostic_messages, format_message};
86 if self.ctx.enclosing_class.is_some() {
87 let message = format_message(
88 diagnostic_messages::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE_CLASS_DEFINITIONS_ARE_AUTO,
89 &[&ident.escaped_text],
90 );
91 self.error_at_node(
92 func.name,
93 &message,
94 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE_CLASS_DEFINITIONS_ARE_AUTO,
95 );
96 } else if self.ctx.binder.is_external_module() {
97 let message = format_message(
98 diagnostic_messages::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE_MODULES_ARE_AUTOMATICALLY,
99 &[&ident.escaped_text],
100 );
101 self.error_at_node(
102 func.name,
103 &message,
104 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE_MODULES_ARE_AUTOMATICALLY,
105 );
106 } else {
107 let message = format_message(
108 diagnostic_messages::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE,
109 &[&ident.escaped_text],
110 );
111 self.error_at_node(
112 func.name,
113 &message,
114 diagnostic_codes::IDENTIFIER_EXPECTED_IS_A_RESERVED_WORD_IN_STRICT_MODE,
115 );
116 }
117 }
118 }
119
120 if func.body.is_some() && self.has_declare_modifier(&func.modifiers) {
124 use crate::diagnostics::diagnostic_codes;
125 self.error_at_node(
126 func.body,
127 "An implementation cannot be declared in ambient contexts.",
128 diagnostic_codes::AN_IMPLEMENTATION_CANNOT_BE_DECLARED_IN_AMBIENT_CONTEXTS,
129 );
130 }
131
132 if func.is_async && !func.asterisk_token {
136 self.check_global_promise_available();
137 }
138
139 if func.asterisk_token {
141 use crate::diagnostics::diagnostic_codes;
142 let is_ambient = self.has_declare_modifier(&func.modifiers)
143 || self.ctx.file_name.ends_with(".d.ts")
144 || self.is_ambient_declaration(func_idx);
145
146 if is_ambient {
147 self.error_at_node(
148 func_idx,
149 "Generators are not allowed in an ambient context.",
150 diagnostic_codes::GENERATORS_ARE_NOT_ALLOWED_IN_AN_AMBIENT_CONTEXT,
151 );
152 } else if func.body.is_none() {
153 self.error_at_node(
154 func_idx,
155 "An overload signature cannot be declared as a generator.",
156 diagnostic_codes::AN_OVERLOAD_SIGNATURE_CANNOT_BE_DECLARED_AS_A_GENERATOR,
157 );
158 }
159 }
160
161 let (_type_params, type_param_updates) = self.push_type_parameters(&func.type_parameters);
162
163 self.check_unused_type_params(&func.type_parameters, func_idx);
165
166 self.check_parameter_properties(&func.parameters.nodes);
169
170 self.check_duplicate_parameters(&func.parameters, func.body.is_some());
172 if !self.has_declare_modifier(&func.modifiers) && !self.ctx.file_name.ends_with(".d.ts") {
173 self.check_strict_mode_reserved_parameter_names(
174 &func.parameters.nodes,
175 func_idx,
176 false,
177 );
178 }
179
180 self.check_parameter_ordering(&func.parameters);
182 self.check_binding_pattern_optionality(&func.parameters.nodes, func.body.is_some());
183
184 self.check_rest_parameter_types(&func.parameters.nodes);
186
187 if func.type_annotation.is_some() {
189 self.check_type_for_parameter_properties(func.type_annotation);
190 self.check_type_for_missing_names(func.type_annotation);
192 }
193
194 for ¶m_idx in &func.parameters.nodes {
196 if let Some(param_node) = self.ctx.arena.get(param_idx)
197 && let Some(param) = self.ctx.arena.get_parameter(param_node)
198 && param.type_annotation.is_some()
199 {
200 self.check_type_for_parameter_properties(param.type_annotation);
201 self.check_type_for_missing_names(param.type_annotation);
203 }
204 }
205
206 let func_decl_jsdoc = self.get_jsdoc_for_function(func_idx);
208
209 let is_closure = matches!(
214 node.kind,
215 syntax_kind_ext::FUNCTION_EXPRESSION | syntax_kind_ext::ARROW_FUNCTION
216 );
217 if !is_closure {
218 for (pi, ¶m_idx) in func.parameters.nodes.iter().enumerate() {
219 let Some(param_node) = self.ctx.arena.get(param_idx) else {
220 continue;
221 };
222 let Some(param) = self.ctx.arena.get_parameter(param_node) else {
223 continue;
224 };
225 let has_jsdoc_param = if param.type_annotation.is_none() {
229 let from_func_jsdoc = if let Some(ref jsdoc) = func_decl_jsdoc {
230 let pname = self.parameter_name_for_error(param.name);
231 Self::jsdoc_has_param_type(jsdoc, &pname)
232 || Self::jsdoc_has_type_tag(jsdoc)
233 || self.ctx.arena.get(param.name).is_some_and(|n| {
234 n.kind == syntax_kind_ext::OBJECT_BINDING_PATTERN
235 || n.kind == syntax_kind_ext::ARRAY_BINDING_PATTERN
236 }) && Self::jsdoc_has_type_annotations(jsdoc)
237 } else {
238 false
239 };
240 from_func_jsdoc || self.param_has_inline_jsdoc_type(param_idx)
241 } else {
242 false
243 };
244 self.maybe_report_implicit_any_parameter(param, has_jsdoc_param, pi);
245 }
246 }
247
248 self.check_non_impl_parameter_initializers(
250 &func.parameters.nodes,
251 self.has_declare_modifier(&func.modifiers),
252 func.body.is_some(),
253 );
254
255 let has_type_annotation = func.type_annotation.is_some();
257 if func.body.is_some() {
258 let mut return_type = if has_type_annotation {
259 self.get_type_from_type_node(func.type_annotation)
260 } else {
261 TypeId::UNKNOWN
263 };
264
265 let mut pushed_this_type = false;
269 if let Some(&first_param) = func.parameters.nodes.first()
270 && let Some(param_node) = self.ctx.arena.get(first_param)
271 && let Some(param) = self.ctx.arena.get_parameter(param_node)
272 {
273 let is_this = if let Some(name_node) = self.ctx.arena.get(param.name) {
276 if name_node.kind == tsz_scanner::SyntaxKind::ThisKeyword as u16 {
277 true
278 } else if let Some(ident) = self.ctx.arena.get_identifier(name_node) {
279 ident.escaped_text == "this"
280 } else {
281 false
282 }
283 } else {
284 false
285 };
286 if is_this && param.type_annotation.is_some() {
287 let this_type = self.get_type_from_type_node(param.type_annotation);
288 self.ctx.this_type_stack.push(this_type);
289 pushed_this_type = true;
290 }
291 }
292
293 if !is_closure {
301 self.cache_parameter_types(&func.parameters.nodes, None);
302 }
303 self.infer_parameter_types_from_context(&func.parameters.nodes);
304
305 self.check_parameter_initializers(&func.parameters.nodes);
307
308 if !has_type_annotation {
309 let prev_suppress = self.ctx.suppress_definite_assignment_errors;
313 self.ctx.suppress_definite_assignment_errors = true;
314 return_type = self.infer_return_type_from_body(func_idx, func.body, None);
315 self.ctx.suppress_definite_assignment_errors = prev_suppress;
316 }
317
318 if !is_closure {
323 let has_jsdoc_return = func_decl_jsdoc
324 .as_ref()
325 .is_some_and(|j| Self::jsdoc_has_type_annotations(j));
326 if !func.is_async && !has_jsdoc_return {
327 let func_name = self.get_function_name_from_node(func_idx);
328 let name_node = (func.name.is_some()).then_some(func.name);
329 self.maybe_report_implicit_any_return(
330 func_name,
331 name_node,
332 return_type,
333 has_type_annotation,
334 false,
335 func_idx,
336 );
337 }
338 }
339
340 if func.is_async && !func.asterisk_token && has_type_annotation {
345 let should_emit_ts2705 = !self.is_promise_type(return_type)
346 && return_type != TypeId::ERROR
347 && !self.return_type_annotation_looks_like_promise(func.type_annotation);
348
349 if should_emit_ts2705 {
350 use crate::context::ScriptTarget;
351 use crate::diagnostics::diagnostic_codes;
352
353 let is_es5_or_lower = matches!(
355 self.ctx.compiler_options.target,
356 ScriptTarget::ES3 | ScriptTarget::ES5
357 );
358
359 let type_name = self.format_type(return_type);
360 if is_es5_or_lower {
361 self.error_at_node_msg(
362 func.type_annotation,
363 diagnostic_codes::TYPE_IS_NOT_A_VALID_ASYNC_FUNCTION_RETURN_TYPE_IN_ES5_BECAUSE_IT_DOES_NOT_REFER,
364 &[&type_name],
365 );
366 } else {
367 self.error_at_node_msg(
369 func.type_annotation,
370 diagnostic_codes::THE_RETURN_TYPE_OF_AN_ASYNC_FUNCTION_OR_METHOD_MUST_BE_THE_GLOBAL_PROMISE_T_TYPE,
371 &[&type_name],
372 );
373 }
374 }
375 }
376
377 if func.is_async {
379 self.ctx.enter_async_context();
380 }
381
382 let is_generator = func.asterisk_token;
386 let body_return_type = if is_generator && has_type_annotation {
387 let generator_base = if func.is_async {
389 self.resolve_lib_type_by_name("AsyncGenerator")
390 .unwrap_or(TypeId::ERROR)
391 } else {
392 self.resolve_lib_type_by_name("Generator")
393 .unwrap_or(TypeId::ERROR)
394 };
395 if generator_base != TypeId::ERROR {
396 let any_gen = self
397 .ctx
398 .types
399 .factory()
400 .application(generator_base, vec![TypeId::ANY, TypeId::ANY, TypeId::ANY]);
401
402 if self
406 .get_generator_return_type_argument(return_type)
407 .is_none()
408 {
409 self.check_assignable_or_report(any_gen, return_type, func.type_annotation);
410 }
411 }
412
413 self.get_generator_return_type_argument(return_type)
414 .unwrap_or(return_type)
415 } else if func.is_async && has_type_annotation {
416 self.unwrap_promise_type(return_type).unwrap_or(return_type)
419 } else {
420 return_type
421 };
422
423 self.push_return_type(body_return_type);
424
425 let contextual_yield_type = if is_generator && has_type_annotation {
428 self.get_generator_yield_type_argument(return_type)
429 } else {
430 None
431 };
432 self.ctx.push_yield_type(contextual_yield_type);
433
434 let saved_cf_context = (
436 self.ctx.iteration_depth,
437 self.ctx.switch_depth,
438 self.ctx.label_stack.len(),
439 self.ctx.had_outer_loop,
440 );
441 if self.ctx.iteration_depth > 0 || self.ctx.switch_depth > 0 || self.ctx.had_outer_loop
443 {
444 self.ctx.had_outer_loop = true;
445 }
446 self.ctx.iteration_depth = 0;
447 self.ctx.switch_depth = 0;
448 self.ctx.function_depth += 1;
449 self.check_statement(func.body);
452 self.ctx.iteration_depth = saved_cf_context.0;
454 self.ctx.switch_depth = saved_cf_context.1;
455 self.ctx.function_depth -= 1;
456 self.ctx.label_stack.truncate(saved_cf_context.2);
457 self.ctx.had_outer_loop = saved_cf_context.3;
458
459 let is_async = func.is_async;
462 let is_generator = func.asterisk_token;
463 let mut check_return_type =
464 self.return_type_for_implicit_return_check(return_type, is_async, is_generator);
465 if is_async
469 && check_return_type == return_type
470 && has_type_annotation
471 && self.return_type_annotation_looks_like_promise(func.type_annotation)
472 {
473 check_return_type = TypeId::VOID;
474 }
475 let check_explicit_return_paths = has_type_annotation;
476 let requires_return = if check_explicit_return_paths {
477 self.requires_return_value(check_return_type)
478 } else {
479 false
480 };
481 let check_no_implicit_returns = self.ctx.no_implicit_returns();
482 let need_return_flow_scan =
483 (check_explicit_return_paths && requires_return) || check_no_implicit_returns;
484 let (has_return, falls_through) = if need_return_flow_scan {
485 (
486 self.body_has_return_with_value(func.body),
487 self.function_body_falls_through(func.body),
488 )
489 } else {
490 (false, false)
491 };
492
493 if check_explicit_return_paths && requires_return && falls_through {
494 if !has_return {
495 use crate::diagnostics::diagnostic_codes;
496 self.error_at_node(
497 func.type_annotation,
498 "A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.",
499 diagnostic_codes::A_FUNCTION_WHOSE_DECLARED_TYPE_IS_NEITHER_UNDEFINED_VOID_NOR_ANY_MUST_RETURN_A_V,
500 );
501 } else if self.ctx.strict_null_checks() {
502 use crate::diagnostics::{diagnostic_codes, diagnostic_messages};
504 self.error_at_node(
505 func.type_annotation,
506 diagnostic_messages::FUNCTION_LACKS_ENDING_RETURN_STATEMENT_AND_RETURN_TYPE_DOES_NOT_INCLUDE_UNDEFINE,
507 diagnostic_codes::FUNCTION_LACKS_ENDING_RETURN_STATEMENT_AND_RETURN_TYPE_DOES_NOT_INCLUDE_UNDEFINE,
508 );
509 }
510 } else if check_no_implicit_returns
511 && has_return
512 && falls_through
513 && !self
514 .should_skip_no_implicit_return_check(check_return_type, has_type_annotation)
515 {
516 use crate::diagnostics::{diagnostic_codes, diagnostic_messages};
518 let error_node = if func.name.is_some() {
519 func.name
520 } else {
521 func.body
522 };
523 self.error_at_node(
524 error_node,
525 diagnostic_messages::NOT_ALL_CODE_PATHS_RETURN_A_VALUE,
526 diagnostic_codes::NOT_ALL_CODE_PATHS_RETURN_A_VALUE,
527 );
528 }
529
530 self.pop_return_type();
531 self.ctx.pop_yield_type();
532
533 if func.is_async {
535 self.ctx.exit_async_context();
536 }
537
538 if pushed_this_type {
539 self.ctx.this_type_stack.pop();
540 }
541 } else if self.ctx.no_implicit_any() && !has_type_annotation {
542 let is_ambient =
543 self.has_declare_modifier(&func.modifiers) || self.ctx.file_name.ends_with(".d.ts");
544 if let Some(func_name) = self.get_function_name_from_node(func_idx) {
545 let name_node = (func.name.is_some()).then_some(func.name);
546 if is_ambient {
547 use crate::diagnostics::diagnostic_codes;
548 self.error_at_node_msg(
549 name_node.unwrap_or(func_idx),
550 diagnostic_codes::WHICH_LACKS_RETURN_TYPE_ANNOTATION_IMPLICITLY_HAS_AN_RETURN_TYPE,
551 &[&func_name, "any"],
552 );
553 } else {
554 self.maybe_report_implicit_any_return(
557 Some(func_name),
558 name_node,
559 TypeId::ANY,
560 false,
561 false,
562 func_idx,
563 );
564 }
565 }
566 }
567
568 if func.body.is_some() {
571 self.check_overload_compatibility(func_idx);
573 }
574
575 self.pop_type_parameters(type_param_updates);
576 }
577
578 fn check_class_declaration(&mut self, class_idx: NodeIndex) {
579 CheckerState::check_class_declaration(self, class_idx);
586 }
587
588 fn check_interface_declaration(&mut self, iface_idx: NodeIndex) {
589 let mut checker = crate::declarations::DeclarationChecker::new(&mut self.ctx);
591 checker.check_interface_declaration(iface_idx);
592
593 CheckerState::check_interface_declaration(self, iface_idx);
595 }
596
597 fn check_import_declaration(&mut self, import_idx: NodeIndex) {
598 CheckerState::check_import_declaration(self, import_idx);
599 }
600
601 fn check_import_equals_declaration(&mut self, import_idx: NodeIndex) {
602 CheckerState::check_import_equals_declaration(self, import_idx);
603 }
604
605 fn check_export_declaration(&mut self, export_idx: NodeIndex) {
606 if let Some(export_decl) = self.ctx.arena.get_export_decl_at(export_idx) {
607 if export_decl.is_default_export && self.is_inside_namespace_declaration(export_idx) {
608 self.error_at_node(
609 export_idx,
610 crate::diagnostics::diagnostic_messages::A_DEFAULT_EXPORT_CAN_ONLY_BE_USED_IN_AN_ECMASCRIPT_STYLE_MODULE,
611 crate::diagnostics::diagnostic_codes::A_DEFAULT_EXPORT_CAN_ONLY_BE_USED_IN_AN_ECMASCRIPT_STYLE_MODULE,
612 );
613 return;
616 }
617
618 let is_reexport_syntax = export_decl.module_specifier.is_some()
620 || self
621 .ctx
622 .arena
623 .get(export_decl.export_clause)
624 .is_some_and(|n| n.kind == syntax_kind_ext::NAMED_EXPORTS);
625 if is_reexport_syntax && self.is_inside_namespace_declaration(export_idx) {
626 let report_idx = if export_decl.module_specifier.is_some() {
627 export_decl.module_specifier
628 } else {
629 export_idx
630 };
631 self.error_at_node(
632 report_idx,
633 crate::diagnostics::diagnostic_messages::EXPORT_DECLARATIONS_ARE_NOT_PERMITTED_IN_A_NAMESPACE,
634 crate::diagnostics::diagnostic_codes::EXPORT_DECLARATIONS_ARE_NOT_PERMITTED_IN_A_NAMESPACE,
635 );
636 }
637
638 self.check_import_attributes_module_option(export_decl.attributes);
640
641 if export_decl.module_specifier.is_some() {
643 self.check_export_module_specifier(export_idx);
644 }
645
646 if export_decl.export_clause.is_some() {
648 let clause_idx = export_decl.export_clause;
649 let mut expected_type = None;
650 let mut prev_context = None;
651 if export_decl.is_default_export {
652 expected_type = self.jsdoc_type_annotation_for_node(export_idx);
653 if let Some(et) = expected_type {
654 prev_context = self.ctx.contextual_type;
655 self.ctx.contextual_type = Some(et);
656 }
657 }
658
659 self.check_statement(clause_idx);
660
661 if let Some(et) = expected_type {
662 let actual_type = self.get_type_of_node(clause_idx);
663 self.ctx.contextual_type = prev_context;
664 self.check_assignable_or_report(actual_type, et, clause_idx);
665 if let Some(expr_node) = self.ctx.arena.get(clause_idx)
666 && expr_node.kind == syntax_kind_ext::OBJECT_LITERAL_EXPRESSION
667 {
668 self.check_object_literal_excess_properties(actual_type, et, clause_idx);
669 }
670 }
671
672 if export_decl.module_specifier.is_none()
673 && !self.is_inside_namespace_declaration(export_idx)
674 && self
675 .ctx
676 .arena
677 .get(clause_idx)
678 .is_some_and(|n| n.kind == syntax_kind_ext::NAMED_EXPORTS)
679 {
680 self.check_local_named_exports(clause_idx);
681 }
682 }
683 }
684 }
685
686 fn check_type_alias_declaration(&mut self, type_alias_idx: NodeIndex) {
687 CheckerState::check_type_alias_declaration(self, type_alias_idx);
689
690 if let Some(node) = self.ctx.arena.get(type_alias_idx) {
691 if let Some(type_alias) = self.ctx.arena.get_type_alias(node) {
693 self.check_strict_mode_reserved_name_at(type_alias.name, type_alias_idx);
695
696 if let Some(name_node) = self.ctx.arena.get(type_alias.name)
698 && let Some(ident) = self.ctx.arena.get_identifier(name_node)
699 && ident.escaped_text == "undefined"
700 {
701 use crate::diagnostics::diagnostic_codes;
702 self.error_at_node(
703 type_alias.name,
704 "Type alias name cannot be 'undefined'.",
705 diagnostic_codes::TYPE_ALIAS_NAME_CANNOT_BE,
706 );
707 }
708 let (_params, updates) = self.push_type_parameters(&type_alias.type_parameters);
709 self.check_unused_type_params(&type_alias.type_parameters, type_alias_idx);
711 self.check_type_for_missing_names(type_alias.type_node);
712 self.check_type_for_parameter_properties(type_alias.type_node);
713 self.pop_type_parameters(updates);
714 }
715 }
716 }
717 fn check_enum_duplicate_members(&mut self, enum_idx: NodeIndex) {
718 if let Some(node) = self.ctx.arena.get(enum_idx)
720 && let Some(enum_data) = self.ctx.arena.get_enum(node)
721 {
722 self.check_async_modifier_on_declaration(&enum_data.modifiers);
723 self.check_strict_mode_reserved_name_at(enum_data.name, enum_idx);
725 }
726
727 let mut checker = crate::declarations::DeclarationChecker::new(&mut self.ctx);
729 checker.check_enum_declaration(enum_idx);
730
731 CheckerState::check_enum_duplicate_members(self, enum_idx);
733 }
734
735 fn check_module_declaration(&mut self, module_idx: NodeIndex) {
736 if let Some(node) = self.ctx.arena.get(module_idx) {
737 let mut checker = crate::declarations::DeclarationChecker::new(&mut self.ctx);
739 checker.check_module_declaration(module_idx);
740
741 if let Some(module) = self.ctx.arena.get_module(node) {
743 self.check_strict_mode_reserved_name_at(module.name, module_idx);
745
746 self.check_async_modifier_on_declaration(&module.modifiers);
748
749 let is_ambient = self.has_declare_modifier(&module.modifiers);
750 if module.body.is_some() {
751 self.check_module_body(module.body);
752 }
753
754 if is_ambient && module.body.is_some() {
758 self.check_declare_modifiers_in_ambient_body(module.body);
759 self.check_initializers_in_ambient_body(module.body);
760
761 if let Some(body_node) = self.ctx.arena.get(module.body)
766 && body_node.kind == tsz_parser::parser::syntax_kind_ext::MODULE_BLOCK
767 && let Some(block) = self.ctx.arena.get_module_block(body_node)
768 && let Some(ref statements) = block.statements
769 {
770 self.check_export_assignment(&statements.nodes);
771 self.check_import_alias_duplicates(&statements.nodes);
772 for &stmt_idx in &statements.nodes {
774 if let Some(stmt_node) = self.ctx.arena.get(stmt_idx)
775 && stmt_node.kind == tsz_parser::parser::syntax_kind_ext::IMPORT_EQUALS_DECLARATION {
776 self.check_import_equals_declaration(stmt_idx);
777 }
778 }
779 }
780 }
781
782 if !is_ambient
785 && module.body.is_some()
786 && let Some(body_node) = self.ctx.arena.get(module.body)
787 && body_node.kind == tsz_parser::parser::syntax_kind_ext::MODULE_BLOCK
788 && let Some(block) = self.ctx.arena.get_module_block(body_node)
789 && let Some(ref statements) = block.statements
790 {
791 self.check_import_alias_duplicates(&statements.nodes);
792 }
793 }
794 }
795 }
796
797 fn check_await_expression(&mut self, expr_idx: NodeIndex) {
798 CheckerState::check_await_expression(self, expr_idx);
799 }
800
801 fn check_for_await_statement(&mut self, stmt_idx: NodeIndex) {
802 CheckerState::check_for_await_statement(self, stmt_idx);
803 }
804
805 fn check_truthy_or_falsy(&mut self, node_idx: NodeIndex) {
806 CheckerState::check_truthy_or_falsy(self, node_idx);
807 }
808
809 fn check_callable_truthiness(&mut self, cond_expr: NodeIndex, body: Option<NodeIndex>) {
810 CheckerState::check_callable_truthiness(self, cond_expr, body);
811 }
812
813 fn is_true_condition(&self, condition_idx: NodeIndex) -> bool {
814 CheckerState::is_true_condition(self, condition_idx)
815 }
816
817 fn is_false_condition(&self, condition_idx: NodeIndex) -> bool {
818 CheckerState::is_false_condition(self, condition_idx)
819 }
820
821 fn report_unreachable_statement(&mut self, stmt_idx: NodeIndex) {
822 if !self.ctx.is_unreachable {
823 return;
824 }
825
826 let should_skip = if let Some(node) = self.ctx.arena.get(stmt_idx) {
828 node.kind == syntax_kind_ext::EMPTY_STATEMENT
829 || node.kind == syntax_kind_ext::FUNCTION_DECLARATION
830 || node.kind == syntax_kind_ext::INTERFACE_DECLARATION
831 || node.kind == syntax_kind_ext::TYPE_ALIAS_DECLARATION
832 || node.kind == syntax_kind_ext::MODULE_DECLARATION
833 || node.kind == syntax_kind_ext::BLOCK
834 || CheckerState::is_var_without_initializer(self, stmt_idx, node)
835 } else {
836 false
837 };
838
839 if !should_skip && !self.ctx.has_reported_unreachable {
840 if self.ctx.compiler_options.allow_unreachable_code != Some(false) {
841 return;
842 }
843 self.error_at_node(
844 stmt_idx,
845 crate::diagnostics::diagnostic_messages::UNREACHABLE_CODE_DETECTED,
846 crate::diagnostics::diagnostic_codes::UNREACHABLE_CODE_DETECTED,
847 );
848 self.ctx.has_reported_unreachable = true;
849 }
850 }
851
852 fn check_for_in_expression_type(&mut self, expr_type: TypeId, expression: NodeIndex) {
853 CheckerState::check_for_in_expression_type(self, expr_type, expression);
854 }
855
856 fn assign_for_in_of_initializer_types(
857 &mut self,
858 decl_list_idx: NodeIndex,
859 loop_var_type: TypeId,
860 is_for_in: bool,
861 ) {
862 CheckerState::assign_for_in_of_initializer_types(
863 self,
864 decl_list_idx,
865 loop_var_type,
866 is_for_in,
867 );
868 }
869
870 fn for_of_element_type(&mut self, expr_type: TypeId) -> TypeId {
871 CheckerState::for_of_element_type(self, expr_type)
872 }
873
874 fn check_for_of_iterability(
875 &mut self,
876 expr_type: TypeId,
877 expr_idx: NodeIndex,
878 await_modifier: bool,
879 ) {
880 CheckerState::check_for_of_iterability(self, expr_type, expr_idx, await_modifier);
881 }
882
883 fn check_for_in_of_expression_initializer(
884 &mut self,
885 initializer: NodeIndex,
886 element_type: TypeId,
887 is_for_of: bool,
888 has_await_modifier: bool,
889 ) {
890 CheckerState::check_for_in_of_expression_initializer(
891 self,
892 initializer,
893 element_type,
894 is_for_of,
895 has_await_modifier,
896 );
897 }
898
899 fn check_for_in_destructuring_pattern(&mut self, initializer: NodeIndex) {
900 CheckerState::check_for_in_destructuring_pattern(self, initializer);
901 }
902
903 fn check_for_in_expression_destructuring(&mut self, initializer: NodeIndex) {
904 CheckerState::check_for_in_expression_destructuring(self, initializer);
905 }
906
907 fn check_statement(&mut self, stmt_idx: NodeIndex) {
908 CheckerState::check_statement(self, stmt_idx);
910 }
911
912 fn check_switch_exhaustiveness(
913 &mut self,
914 _stmt_idx: NodeIndex,
915 expression: NodeIndex,
916 _case_block: NodeIndex,
917 has_default: bool,
918 ) {
919 if has_default {
921 return;
922 }
923
924 let _ = self.get_type_of_node(expression);
926
927 }
938
939 fn check_switch_case_comparable(
940 &mut self,
941 switch_type: TypeId,
942 case_type: TypeId,
943 switch_expr: NodeIndex,
944 case_expr: NodeIndex,
945 ) {
946 if switch_type == TypeId::ERROR
948 || case_type == TypeId::ERROR
949 || switch_type == TypeId::ANY
950 || case_type == TypeId::ANY
951 || switch_type == TypeId::UNKNOWN
952 || case_type == TypeId::UNKNOWN
953 {
954 return;
955 }
956
957 let effective_switch_type = self
961 .literal_type_from_initializer(switch_expr)
962 .unwrap_or(switch_type);
963
964 let effective_case_type = self
967 .literal_type_from_initializer(case_expr)
968 .unwrap_or(case_type);
969
970 let is_comparable = effective_case_type == tsz_solver::TypeId::NULL
975 || effective_case_type == tsz_solver::TypeId::UNDEFINED
976 || self.is_type_comparable_to(effective_case_type, effective_switch_type);
977
978 if !is_comparable {
979 if let Some(loc) = self.get_source_location(case_expr) {
981 let case_str = self.format_type(effective_case_type);
982 let switch_str = self.format_type(effective_switch_type);
983 use crate::diagnostics::{
984 Diagnostic, diagnostic_codes, diagnostic_messages, format_message,
985 };
986 let message = format_message(
987 diagnostic_messages::TYPE_IS_NOT_COMPARABLE_TO_TYPE,
988 &[&case_str, &switch_str],
989 );
990 self.ctx.diagnostics.push(Diagnostic::error(
991 self.ctx.file_name.clone(),
992 loc.start,
993 loc.length(),
994 message,
995 diagnostic_codes::TYPE_IS_NOT_COMPARABLE_TO_TYPE,
996 ));
997 }
998 }
999 }
1000
1001 fn check_with_statement(&mut self, stmt_idx: NodeIndex) {
1002 CheckerState::check_with_statement(self, stmt_idx);
1003 }
1004
1005 fn check_break_statement(&mut self, stmt_idx: NodeIndex) {
1006 CheckerState::check_break_statement(self, stmt_idx);
1007 }
1008
1009 fn check_continue_statement(&mut self, stmt_idx: NodeIndex) {
1010 CheckerState::check_continue_statement(self, stmt_idx);
1011 }
1012
1013 fn is_unreachable(&self) -> bool {
1014 self.ctx.is_unreachable
1015 }
1016
1017 fn set_unreachable(&mut self, value: bool) {
1018 self.ctx.is_unreachable = value;
1019 }
1020
1021 fn has_reported_unreachable(&self) -> bool {
1022 self.ctx.has_reported_unreachable
1023 }
1024
1025 fn set_reported_unreachable(&mut self, value: bool) {
1026 self.ctx.has_reported_unreachable = value;
1027 }
1028
1029 fn statement_falls_through(&mut self, stmt_idx: NodeIndex) -> bool {
1030 CheckerState::statement_falls_through(self, stmt_idx)
1031 }
1032
1033 fn enter_iteration_statement(&mut self) {
1034 self.ctx.iteration_depth += 1;
1035 }
1036
1037 fn leave_iteration_statement(&mut self) {
1038 self.ctx.iteration_depth = self.ctx.iteration_depth.saturating_sub(1);
1039 }
1040
1041 fn enter_switch_statement(&mut self) {
1042 self.ctx.switch_depth += 1;
1043 }
1044
1045 fn leave_switch_statement(&mut self) {
1046 self.ctx.switch_depth = self.ctx.switch_depth.saturating_sub(1);
1047 }
1048
1049 fn save_and_reset_control_flow_context(&mut self) -> (u32, u32, bool) {
1050 let saved = (
1051 self.ctx.iteration_depth,
1052 self.ctx.switch_depth,
1053 self.ctx.had_outer_loop,
1054 );
1055 if self.ctx.iteration_depth > 0 || self.ctx.switch_depth > 0 || self.ctx.had_outer_loop {
1057 self.ctx.had_outer_loop = true;
1058 }
1059 self.ctx.iteration_depth = 0;
1060 self.ctx.switch_depth = 0;
1061 saved
1062 }
1063
1064 fn restore_control_flow_context(&mut self, saved: (u32, u32, bool)) {
1065 self.ctx.iteration_depth = saved.0;
1066 self.ctx.switch_depth = saved.1;
1067 self.ctx.had_outer_loop = saved.2;
1068 }
1069
1070 fn enter_labeled_statement(&mut self, label: String, is_iteration: bool) {
1071 self.ctx.label_stack.push(crate::context::LabelInfo {
1072 name: label,
1073 is_iteration,
1074 function_depth: self.ctx.function_depth,
1075 });
1076 }
1077
1078 fn leave_labeled_statement(&mut self) {
1079 self.ctx.label_stack.pop();
1080 }
1081
1082 fn get_node_text(&self, idx: NodeIndex) -> Option<String> {
1083 let ident = self.ctx.arena.get_identifier_at(idx)?;
1085 Some(self.ctx.arena.resolve_identifier_text(ident).to_string())
1087 }
1088
1089 fn check_declaration_in_statement_position(&mut self, stmt_idx: NodeIndex) {
1090 use tsz_parser::parser::node_flags;
1091
1092 let Some(node) = self.ctx.arena.get(stmt_idx) else {
1093 return;
1094 };
1095
1096 let decl_kind = match node.kind {
1100 syntax_kind_ext::INTERFACE_DECLARATION => Some("interface"),
1101 syntax_kind_ext::VARIABLE_STATEMENT => {
1102 if let Some(var_data) = self.ctx.arena.get_variable(node) {
1104 let list_idx = var_data
1105 .declarations
1106 .nodes
1107 .first()
1108 .copied()
1109 .unwrap_or(NodeIndex::NONE);
1110 if let Some(list_node) = self.ctx.arena.get(list_idx) {
1111 let flags = list_node.flags as u32;
1112 if (flags & node_flags::AWAIT_USING) == node_flags::AWAIT_USING {
1114 Some("await using")
1115 } else if flags & node_flags::USING != 0 {
1116 Some("using")
1117 } else if flags & node_flags::CONST != 0 {
1118 Some("const")
1119 } else if flags & node_flags::LET != 0 {
1120 Some("let")
1121 } else {
1122 None
1123 }
1124 } else {
1125 None
1126 }
1127 } else {
1128 None
1129 }
1130 }
1131 _ => None,
1132 };
1133
1134 if let Some(kind_name) = decl_kind {
1135 let msg = format!("'{kind_name}' declarations can only be declared inside a block.");
1136 self.error_at_node(
1137 stmt_idx,
1138 &msg,
1139 crate::diagnostics::diagnostic_codes::DECLARATIONS_CAN_ONLY_BE_DECLARED_INSIDE_A_BLOCK,
1140 );
1141 }
1142 }
1143
1144 fn check_label_on_declaration(&mut self, label_idx: NodeIndex, statement_idx: NodeIndex) {
1145 if !self.ctx.compiler_options.target.supports_es2015() {
1149 return;
1150 }
1151 if !self.is_strict_mode_for_node(label_idx) {
1152 return;
1153 }
1154
1155 let Some(stmt_node) = self.ctx.arena.get(statement_idx) else {
1156 return;
1157 };
1158
1159 let is_declaration_or_variable = matches!(
1161 stmt_node.kind,
1162 syntax_kind_ext::FUNCTION_DECLARATION
1163 | syntax_kind_ext::CLASS_DECLARATION
1164 | syntax_kind_ext::INTERFACE_DECLARATION
1165 | syntax_kind_ext::TYPE_ALIAS_DECLARATION
1166 | syntax_kind_ext::ENUM_DECLARATION
1167 | syntax_kind_ext::MODULE_DECLARATION
1168 | syntax_kind_ext::IMPORT_DECLARATION
1169 | syntax_kind_ext::EXPORT_DECLARATION
1170 | syntax_kind_ext::VARIABLE_STATEMENT
1171 );
1172
1173 if is_declaration_or_variable {
1174 self.error_at_node(
1175 label_idx,
1176 "'A label is not allowed here.",
1177 crate::diagnostics::diagnostic_codes::A_LABEL_IS_NOT_ALLOWED_HERE,
1178 );
1179 }
1180 }
1181}