Skip to content

Commit 9cb0a4f

Browse files
committed
wip
1 parent d7e5cbc commit 9cb0a4f

File tree

9 files changed

+93
-62
lines changed

9 files changed

+93
-62
lines changed

src/fast_check/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,8 @@ fn transform_package(
709709
.module_from_specifier(&specifier)
710710
.unwrap_or_else(|| panic!("module not found: {}", specifier));
711711
if let Some(module_info) = module_info.esm() {
712-
transform::transform(graph, module_info, &ranges, options).map(Some)
712+
transform::transform(graph, module_info, root_symbol, &ranges, options)
713+
.map(Some)
713714
} else {
714715
Ok(None) // nothing to transform
715716
}

src/fast_check/transform.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ use indexmap::IndexMap;
2828
use crate::swc_helpers::FunctionKind;
2929
use crate::symbols::EsModuleInfo;
3030
use crate::symbols::ExpandoPropertyRef;
31+
use crate::symbols::RootSymbol;
3132
use crate::symbols::Symbol;
3233
use crate::ModuleGraph;
3334
use crate::ModuleInfo;
@@ -111,12 +112,14 @@ pub struct TransformOptions<'a> {
111112
pub fn transform(
112113
graph: &ModuleGraph,
113114
es_module_info: &EsModuleInfo,
115+
root_symbol: &RootSymbol,
114116
public_ranges: &ModulePublicRanges,
115117
options: &TransformOptions,
116118
) -> Result<FastCheckModule, Vec<FastCheckDiagnostic>> {
117119
let mut transformer = FastCheckTransformer::new(
118120
graph,
119121
es_module_info,
122+
root_symbol,
120123
public_ranges,
121124
options.should_error_on_first_diagnostic,
122125
);
@@ -210,6 +213,7 @@ struct FastCheckTransformer<'a> {
210213
graph: &'a ModuleGraph,
211214
specifier: &'a ModuleSpecifier,
212215
es_module_info: &'a EsModuleInfo,
216+
root_symbol: &'a RootSymbol<'a>,
213217
public_ranges: &'a ModulePublicRanges,
214218
parsed_source: &'a ParsedSource,
215219
should_error_on_first_diagnostic: bool,
@@ -221,13 +225,15 @@ impl<'a> FastCheckTransformer<'a> {
221225
pub fn new(
222226
graph: &'a ModuleGraph,
223227
es_module_info: &'a EsModuleInfo,
228+
root_symbol: &'a RootSymbol<'a>,
224229
public_ranges: &'a ModulePublicRanges,
225230
should_error_on_first_diagnostic: bool,
226231
) -> Self {
227232
Self {
228233
graph,
229234
specifier: es_module_info.specifier(),
230235
es_module_info,
236+
root_symbol,
231237
public_ranges,
232238
parsed_source: es_module_info.source(),
233239
should_error_on_first_diagnostic,
@@ -1688,7 +1694,12 @@ impl<'a> FastCheckTransformer<'a> {
16881694
}
16891695

16901696
fn infer(&self) -> TypeInferrer<'_> {
1691-
TypeInferrer::new(self.specifier, self.parsed_source, self.es_module_info)
1697+
TypeInferrer::new(
1698+
self.specifier,
1699+
self.parsed_source,
1700+
self.es_module_info,
1701+
self.root_symbol,
1702+
)
16921703
}
16931704

16941705
fn maybe_transform_expr_if_leavable(

src/fast_check/type_infer.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use deno_ast::swc::ast::Prop;
1717
use deno_ast::swc::ast::PropOrSpread;
1818
use deno_ast::swc::ast::Str;
1919
use deno_ast::swc::ast::Tpl;
20+
use deno_ast::swc::ast::TsEntityName;
2021
use deno_ast::swc::ast::TsFnOrConstructorType;
2122
use deno_ast::swc::ast::TsFnParam;
2223
use deno_ast::swc::ast::TsFnType;
@@ -45,8 +46,14 @@ use deno_ast::SourceRangedForSpanned;
4546

4647
use crate::swc_helpers::analyze_return_stmts_in_function_body;
4748
use crate::swc_helpers::FunctionKind;
49+
use crate::swc_helpers::ts_entity_name_to_parts;
4850
use crate::swc_helpers::ReturnStatementAnalysis;
51+
use crate::symbols::DefinitionPathNode;
4952
use crate::symbols::EsModuleInfo;
53+
use crate::symbols::ModuleInfoRef;
54+
use crate::symbols::ResolvedSymbolDepEntry;
55+
use crate::symbols::RootSymbol;
56+
use crate::symbols::SymbolNodeDep;
5057
use crate::FastCheckDiagnosticRange;
5158

5259
use super::swc_helpers::is_call_expr_symbol_create;
@@ -494,18 +501,21 @@ pub struct TypeInferrer<'a> {
494501
specifier: &'a ModuleSpecifier,
495502
parsed_source: &'a ParsedSource,
496503
module_info: &'a EsModuleInfo,
504+
root_symbol: &'a RootSymbol<'a>,
497505
}
498506

499507
impl<'a> TypeInferrer<'a> {
500508
pub fn new(
501509
specifier: &'a ModuleSpecifier,
502510
parsed_source: &'a ParsedSource,
503511
module_info: &'a EsModuleInfo,
512+
root_symbol: &'a RootSymbol<'a>,
504513
) -> Self {
505514
Self {
506515
specifier,
507516
parsed_source,
508517
module_info,
518+
root_symbol,
509519
}
510520
}
511521

@@ -1125,20 +1135,38 @@ impl<'a> TypeInferrer<'a> {
11251135
ty: &TsType,
11261136
) -> Result<(), ExprInferFailCause> {
11271137
struct Visitor<'a> {
1138+
root_symbol: &'a RootSymbol<'a>,
11281139
es_module_info: &'a EsModuleInfo,
11291140
invalid_range: Option<SourceRange>,
11301141
}
11311142

11321143
impl Visit for Visitor<'_> {
1133-
fn visit_ident(&mut self, n: &Ident) {
1134-
if self.es_module_info.symbol_from_swc(&n.to_id()).is_none() {
1135-
self.invalid_range = Some(n.range());
1144+
fn visit_ts_entity_name(&mut self, n: &TsEntityName) {
1145+
let (id, parts) = ts_entity_name_to_parts(n);
1146+
1147+
let dep = SymbolNodeDep::QualifiedId(id, parts);
1148+
1149+
let entries = self
1150+
.root_symbol
1151+
.resolve_symbol_dep(ModuleInfoRef::Esm(self.es_module_info), &dep);
1152+
1153+
for entry in entries {
1154+
match entry {
1155+
ResolvedSymbolDepEntry::Path(DefinitionPathNode::Resolved(_))
1156+
| ResolvedSymbolDepEntry::ImportType(_) => {
1157+
// valid
1158+
}
1159+
ResolvedSymbolDepEntry::Path(DefinitionPathNode::Unresolved(_)) => {
1160+
self.invalid_range = Some(n.range());
1161+
}
1162+
}
11361163
}
11371164
}
11381165
}
11391166

11401167
let mut visitor = Visitor {
11411168
es_module_info: self.module_info,
1169+
root_symbol: self.root_symbol,
11421170
invalid_range: None,
11431171
};
11441172
ty.visit_with(&mut visitor);

src/swc_helpers.rs

+32
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
use std::ops::ControlFlow;
44

55
use deno_ast::swc::ast::BlockStmt;
6+
use deno_ast::swc::ast::Id;
67
use deno_ast::swc::ast::ReturnStmt;
78
use deno_ast::swc::ast::Stmt;
9+
use deno_ast::swc::ast::TsEntityName;
10+
use deno_ast::swc::ast::TsQualifiedName;
811

912
pub enum FunctionKind {
1013
/// function declarations, class method declarations (both class decl and class expr)
@@ -111,3 +114,32 @@ fn analyze_return_stmts_from_stmt(
111114
| Stmt::Empty(_) => ControlFlow::Continue(()),
112115
}
113116
}
117+
118+
pub fn ts_entity_name_to_parts(
119+
entity_name: &TsEntityName,
120+
) -> (Id, Vec<String>) {
121+
match entity_name {
122+
TsEntityName::TsQualifiedName(qualified_name) => {
123+
ts_qualified_name_parts(qualified_name)
124+
}
125+
TsEntityName::Ident(ident) => (ident.to_id(), Vec::new()),
126+
}
127+
}
128+
129+
pub fn ts_qualified_name_parts(
130+
mut qualified_name: &TsQualifiedName,
131+
) -> (Id, Vec<String>) {
132+
let mut parts = Vec::new();
133+
loop {
134+
parts.push(qualified_name.right.sym.to_string());
135+
match &qualified_name.left {
136+
TsEntityName::TsQualifiedName(n) => {
137+
qualified_name = n;
138+
}
139+
TsEntityName::Ident(n) => {
140+
parts.reverse();
141+
return (n.to_id(), parts);
142+
}
143+
}
144+
}
145+
}

src/symbols/analyzer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use indexmap::IndexMap;
2121
use indexmap::IndexSet;
2222

2323
use crate::swc_helpers::analyze_return_stmts_in_function_body;
24+
use crate::swc_helpers::ts_entity_name_to_parts;
2425
use crate::swc_helpers::FunctionKind;
2526
use crate::swc_helpers::ReturnStatementAnalysis;
2627
use crate::JsModule;
@@ -39,7 +40,6 @@ use super::cross_module::DefinitionOrUnresolved;
3940
use super::cross_module::DefinitionPathNode;
4041
use super::cross_module::ModuleExports;
4142
use super::dep_analyzer::ResolveDepsMode;
42-
use super::swc_helpers::ts_entity_name_to_parts;
4343
use super::ResolvedSymbolDepEntry;
4444
use super::SymbolNodeDep;
4545

src/symbols/dep_analyzer.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ use deno_ast::swc::visit::Visit;
4343
use deno_ast::swc::visit::VisitWith;
4444

4545
use crate::swc_helpers::analyze_return_stmts_in_function_body;
46+
use crate::swc_helpers::ts_entity_name_to_parts;
47+
use crate::swc_helpers::ts_qualified_name_parts;
4648

47-
use super::swc_helpers::ts_entity_name_to_parts;
48-
use super::swc_helpers::ts_qualified_name_parts;
4949
use super::ExportDeclRef;
5050
use super::SymbolNodeRef;
5151

src/symbols/mod.rs

-1
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,3 @@ mod analyzer;
3535
mod collections;
3636
mod cross_module;
3737
mod dep_analyzer;
38-
mod swc_helpers;

src/symbols/swc_helpers.rs

-34
This file was deleted.

tests/specs/graph/fast_check/test_test_test.txt

+13-19
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@
1616
// return {} as typeof x;
1717
// };
1818

19-
export const a = (b: string, c = {} as typeof b) => {
20-
};
21-
2219
# output
2320
{
2421
"roots": [
@@ -27,7 +24,7 @@ export const a = (b: string, c = {} as typeof b) => {
2724
"modules": [
2825
{
2926
"kind": "esm",
30-
"size": 144,
27+
"size": 179,
3128
"mediaType": "TypeScript",
3229
"specifier": "file:///mod.ts"
3330
}
@@ -36,18 +33,15 @@ export const a = (b: string, c = {} as typeof b) => {
3633
}
3734

3835
Fast check file:///mod.ts:
39-
error[unknown-var-type]: unknown type for variable in the public API
40-
--> /mod.ts:6:14
41-
|
42-
6 | export const a = (b: string, c = {} as typeof b): typeof b => {
43-
| ^ this variable's type could not be inferred because its initializer
44-
| - contains this arrow expression
45-
| - which has this parameter, which is missing an explicit type annotation
46-
| - contains this reference to a local variable or type
47-
|
48-
= hint: add an explicit type annotation to the arrow expression parameter in the variable declaration initializer
49-
50-
info: all variables in the public API must have a known type
51-
info: local variables or types can not be referenced in the public API because they are not visible at the top level of the module
52-
docs: https://jsr.io/go/slow-type-unknown-var-type
53-
36+
{}
37+
declare const Y: X;
38+
interface X {
39+
y: string;
40+
}
41+
export declare const a: (b: string, c?: typeof Y.z) => void;
42+
--- DTS ---
43+
declare const Y: X;
44+
interface X {
45+
y: string;
46+
}
47+
export declare const a: (b: string, c?: typeof Y.z) => void;

0 commit comments

Comments
 (0)