1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
//! Compiler option accessors for `CheckerContext`.
//!
//! These methods provide convenient access to the `CheckerOptions` flags
//! and derive solver configuration (`JudgeConfig`, `CompatChecker`) from them.
use tsz_solver::judge::JudgeConfig;
use super::CheckerContext;
impl<'a> CheckerContext<'a> {
// =========================================================================
// Compiler Option Accessors
// =========================================================================
/// Check if strict mode is enabled.
pub const fn is_strict_mode(&self) -> bool {
self.compiler_options.strict
}
/// Check if noImplicitAny is enabled for the current file.
/// For JavaScript files, noImplicitAny only applies when checkJs is also enabled.
/// This allows TS7006 to fire in .js files with --checkJs --strict.
pub fn no_implicit_any(&self) -> bool {
if !self.compiler_options.no_implicit_any {
return false;
}
let is_js_file = self.file_name.ends_with(".js")
|| self.file_name.ends_with(".jsx")
|| self.file_name.ends_with(".mjs")
|| self.file_name.ends_with(".cjs");
// JS files get noImplicitAny errors only when checkJs is enabled
if is_js_file {
self.compiler_options.check_js
} else {
true
}
}
/// Check if noImplicitReturns is enabled.
pub const fn no_implicit_returns(&self) -> bool {
self.compiler_options.no_implicit_returns
}
/// Check if noImplicitThis is enabled.
pub const fn no_implicit_this(&self) -> bool {
self.compiler_options.no_implicit_this
}
/// Check if noImplicitOverride is enabled.
pub const fn no_implicit_override(&self) -> bool {
self.compiler_options.no_implicit_override
}
/// Check if strictNullChecks is enabled.
pub const fn strict_null_checks(&self) -> bool {
self.compiler_options.strict_null_checks
}
/// Check if strictFunctionTypes is enabled.
pub const fn strict_function_types(&self) -> bool {
self.compiler_options.strict_function_types
}
/// Check if strictPropertyInitialization is enabled.
pub const fn strict_property_initialization(&self) -> bool {
self.compiler_options.strict_property_initialization
}
/// Check if useUnknownInCatchVariables is enabled.
pub const fn use_unknown_in_catch_variables(&self) -> bool {
self.compiler_options.use_unknown_in_catch_variables
}
/// Check if isolatedModules is enabled.
pub const fn isolated_modules(&self) -> bool {
self.compiler_options.isolated_modules
}
/// Check if noUncheckedIndexedAccess is enabled.
/// When enabled, index signature access adds `| undefined` to the result type.
pub const fn no_unchecked_indexed_access(&self) -> bool {
self.compiler_options.no_unchecked_indexed_access
}
/// Check if strictBindCallApply is enabled.
/// When enabled, bind/call/apply use strict function signatures.
pub const fn strict_bind_call_apply(&self) -> bool {
self.compiler_options.strict_bind_call_apply
}
/// Check if exactOptionalPropertyTypes is enabled.
/// When enabled, optional properties are `T | undefined` not `T | undefined | missing`.
pub const fn exact_optional_property_types(&self) -> bool {
self.compiler_options.exact_optional_property_types
}
/// Check if sound mode is enabled.
pub const fn sound_mode(&self) -> bool {
self.compiler_options.sound_mode
}
/// Pack the checker's compiler options into a `u16` bitmask for use as a
/// `RelationCacheKey` flags field. This is the single source of truth for
/// flag packing — call this instead of manually constructing the bitmask.
pub const fn pack_relation_flags(&self) -> u16 {
use tsz_solver::RelationCacheKey;
let mut flags: u16 = 0;
if self.strict_null_checks() {
flags |= RelationCacheKey::FLAG_STRICT_NULL_CHECKS;
}
if self.strict_function_types() {
flags |= RelationCacheKey::FLAG_STRICT_FUNCTION_TYPES;
}
if self.exact_optional_property_types() {
flags |= RelationCacheKey::FLAG_EXACT_OPTIONAL_PROPERTY_TYPES;
}
if self.no_unchecked_indexed_access() {
flags |= RelationCacheKey::FLAG_NO_UNCHECKED_INDEXED_ACCESS;
}
flags
}
/// Convert `CheckerOptions` to `JudgeConfig` for the `CompatChecker`.
const fn as_judge_config(&self) -> JudgeConfig {
JudgeConfig {
strict_function_types: self.strict_function_types(),
strict_null_checks: self.strict_null_checks(),
exact_optional_property_types: self.exact_optional_property_types(),
no_unchecked_indexed_access: self.no_unchecked_indexed_access(),
sound_mode: self.sound_mode(),
}
}
/// Apply standard compiler options to a `CompatChecker`, including `query_db`.
/// This wires the `CompilerOptions` (via `JudgeConfig`) and the `QueryDatabase`.
pub fn configure_compat_checker<'b, R: tsz_solver::TypeResolver>(
&'b self,
checker: &mut tsz_solver::CompatChecker<'b, R>,
) {
// Apply configuration from options
checker.apply_config(&self.as_judge_config());
// Set the query database for memoization/interning
checker.set_query_db(self.types);
// Set the inheritance graph for nominal class subtype checking
checker.set_inheritance_graph(Some(&self.inheritance_graph));
// Configure strict subtype checking if Sound Mode is enabled
if self.compiler_options.sound_mode {
checker.set_strict_subtype_checking(true);
checker.set_strict_any_propagation(true);
}
}
/// Check if noUnusedLocals is enabled.
pub const fn no_unused_locals(&self) -> bool {
self.compiler_options.no_unused_locals
}
/// Check if noUnusedParameters is enabled.
pub const fn no_unused_parameters(&self) -> bool {
self.compiler_options.no_unused_parameters
}
/// Check if noLib is enabled.
/// When enabled, no library files (including lib.d.ts) are included.
/// TS2318 errors are emitted when referencing global types with this option enabled.
pub const fn no_lib(&self) -> bool {
self.compiler_options.no_lib
}
/// Check if lib files are loaded (lib.d.ts, etc.).
/// Returns false when noLib is enabled or when no actual lib files are loaded.
/// Uses `actual_lib_file_count` instead of `lib_contexts.is_empty()` because `lib_contexts`
/// may also contain user file contexts for cross-file resolution in multi-file tests.
/// Used to determine whether to emit TS2304/TS2318/TS2583 for missing global types.
pub const fn has_lib_loaded(&self) -> bool {
!self.compiler_options.no_lib && self.actual_lib_file_count > 0
}
/// Check if esModuleInterop is enabled.
/// When enabled, synthesizes default exports for `CommonJS` modules.
pub const fn es_module_interop(&self) -> bool {
self.compiler_options.es_module_interop
}
/// Check if allowSyntheticDefaultImports is enabled.
/// When enabled, allows `import x from 'y'` when module doesn't have default export.
/// This is implied by esModuleInterop.
pub const fn allow_synthetic_default_imports(&self) -> bool {
self.compiler_options.allow_synthetic_default_imports
}
}