Skip to content

Commit

Permalink
fix: Import local type from module and namespace (#1099)
Browse files Browse the repository at this point in the history
**Description:**
```ts

declare module "foo2" {
    namespace Bar {
        interface I {
            a: string;
            b: number;
        }
    }

    namespace Baz {
        interface J {
            a: number;
            b: string;
        }
    }

    class Bar {
        item: Bar.I;
        constructor(input: Baz.J);
    }
}

let y: import("foo2").Bar.I = { a: "", b: 0 };
```
  • Loading branch information
sunrabbit123 authored Oct 16, 2023
1 parent 9e4c9b3 commit b81ae80
Show file tree
Hide file tree
Showing 14 changed files with 84 additions and 95 deletions.
22 changes: 14 additions & 8 deletions crates/stc_ts_file_analyzer/src/analyzer/expr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3035,9 +3035,9 @@ impl Analyzer<'_, '_> {
}

Type::Module(ty::Module { name, ref exports, .. }) => {
match id_ctx {
IdCtx::Type => {
if let Key::Normal { sym, .. } = prop {
if let Key::Normal { sym, .. } = prop {
match id_ctx {
IdCtx::Type => {
if let Some(types) = exports.types.get(sym).cloned() {
if types.len() == 1 {
return Ok(types.into_iter().next().unwrap());
Expand All @@ -3053,16 +3053,22 @@ impl Analyzer<'_, '_> {
if let Some(vars) = exports.vars.get(sym).cloned() {
return Ok(vars);
}

for (id, tys) in exports.private_types.iter() {
if *id.sym() != *sym {
continue;
}

if let Some(ty) = tys.iter().find(|ty| ty.is_module() || ty.is_interface()) {
return Ok(ty.clone());
}
}
}
}
IdCtx::Var => {
if let Key::Normal { sym, .. } = prop {
IdCtx::Var => {
if let Some(item) = exports.vars.get(sym) {
return Ok(item.clone());
}
}

if let Key::Normal { sym, .. } = prop {
if let Some(types) = exports.types.get(sym) {
for ty in types.iter() {
if ty.is_module() || ty.is_interface() {
Expand Down
84 changes: 50 additions & 34 deletions crates/stc_ts_file_analyzer/src/analyzer/scope/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,12 @@ impl Analyzer<'_, '_> {
}
}

self.find_local_type_without_this(name)
}

fn find_local_type_without_this(&self, name: &Id) -> Option<ItemRef<Type>> {
let _tracing = dev_span!("find_local_type_without_this", name = tracing::field::debug(name));

if cfg!(debug_assertions) {
debug!("({}) Scope.find_type(`{}`)", self.scope.depth(), name);
}
Expand Down Expand Up @@ -2064,6 +2070,7 @@ impl Expander<'_, '_, '_> {
type_args: Option<&TypeParamInstantiation>,
was_top_level: bool,
trying_primitive_expansion: bool,
ignore_this: bool,
) -> VResult<Option<Type>> {
macro_rules! verify {
($ty:expr) => {{
Expand All @@ -2080,26 +2087,20 @@ impl Expander<'_, '_, '_> {

match type_name {
RTsEntityName::Ident(ref i) => {
if let Some(class) = &self.analyzer.scope.get_this_class_name() {
if *class == *i {
return Ok(Some(Type::This(ThisType {
span,
metadata: Default::default(),
tracker: Default::default(),
})));
}
}
if i.sym == js_word!("void") {
return Ok(Some(Type::any(span, Default::default())));
}

info!("Info: {}{:?}", i.sym, i.span.ctxt);
if !trying_primitive_expansion && self.dejavu.contains(&i.into()) {
error!("Dejavu: {}{:?}", &i.sym, i.span.ctxt);
return Ok(None);
}

if let Some(types) = self.analyzer.find_type(&i.into())? {
let tys = if ignore_this {
self.analyzer.find_local_type_without_this(&i.into())
} else {
None
}
.map_or_else(|| self.analyzer.find_type(&i.into()), |res| Ok(Some(res)))?;

if let Some(types) = tys {
info!("expand: expanding `{}` using analyzer: {}", Id::from(i), types.clone().count());

let mut stored_ref = None;
Expand Down Expand Up @@ -2247,6 +2248,11 @@ impl Expander<'_, '_, '_> {

Type::Mapped(m) => {}

Type::Namespace(..) => {
return Ok(Some(t.into_owned()));
}

Type::StaticThis(..) => stored_ref = Some(t),
_ => stored_ref = Some(t),
}
}
Expand All @@ -2258,7 +2264,7 @@ impl Expander<'_, '_, '_> {
}
}

if i.sym == *"undefined" || i.sym == *"null" {
if i.sym == *"undefined" || i.sym == *"null" || i.sym == *"void" {
return Ok(Some(Type::any(span, Default::default())));
}

Expand All @@ -2269,26 +2275,29 @@ impl Expander<'_, '_, '_> {
//
// let a: StringEnum.Foo = x;
RTsEntityName::TsQualifiedName(box RTsQualifiedName { left, ref right, .. }) => {
let left = self.expand_ts_entity_name(span, left, None, was_top_level, trying_primitive_expansion)?;

if let Some(left) = &left {
let ty = self
let prop = Key::Normal {
span,
sym: right.sym.clone(),
};
if let Some(ty) = self.expand_ts_entity_name(span, left, None, was_top_level, trying_primitive_expansion, false)? {
match self
.analyzer
.access_property(
span,
left,
&Key::Normal {
span,
sym: right.sym.clone(),
},
TypeOfMode::RValue,
IdCtx::Type,
Default::default(),
)
.access_property(span, &ty, &prop, TypeOfMode::RValue, IdCtx::Type, Default::default())
.context("tried to access property as a part of type expansion")
.report(&mut self.analyzer.storage)
.unwrap_or_else(|| Type::any(span, Default::default()));
return Ok(Some(ty));
{
Ok(t) => return Ok(Some(t)),
err => {
if let Some(left) =
self.expand_ts_entity_name(span, left, None, was_top_level, trying_primitive_expansion, true)?
{
return Ok(self
.analyzer
.access_property(span, &left, &prop, TypeOfMode::RValue, IdCtx::Type, Default::default())
.context("tried to access property as a part of type expansion(retry without this type)")
.report(&mut self.analyzer.storage));
}
}
};
}
}
}
Expand All @@ -2313,7 +2322,14 @@ impl Expander<'_, '_, '_> {
return Ok(None);
}

let mut ty = self.expand_ts_entity_name(span, &type_name, type_args.as_deref(), was_top_level, trying_primitive_expansion)?;
let mut ty = self.expand_ts_entity_name(
span,
&type_name,
type_args.as_deref(),
was_top_level,
trying_primitive_expansion,
false,
)?;

if let Some(ty) = &mut ty {
ty.reposition(r_span);
Expand Down
3 changes: 3 additions & 0 deletions crates/stc_ts_type_checker/tests/conformance.pass.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2341,7 +2341,10 @@ types/contextualTypes/partiallyAnnotatedFunction/partiallyAnnotatedFunctionWitou
types/forAwait/types.forAwait.es2018.1.ts
types/forAwait/types.forAwait.es2018.2.ts
types/forAwait/types.forAwait.es2018.3.ts
types/import/importTypeAmbient.ts
types/import/importTypeAmdBundleRewrite.ts
types/import/importTypeGenericTypes.ts
types/import/importTypeLocal.ts
types/intersection/contextualIntersectionType.ts
types/intersection/intersectionMemberOfUnionNarrowsCorrectly.ts
types/intersection/intersectionNarrowing.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
"required_errors": {},
"required_error_lines": {},
"extra_errors": {
"TS2339": 2
"TS2403": 1,
"TS2339": 1
},
"extra_error_lines": {
"TS2403": [
17
],
"TS2339": [
17,
36
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
"required_errors": {},
"required_error_lines": {},
"extra_errors": {
"TS2339": 2
"TS2339": 1,
"TS2403": 1
},
"extra_error_lines": {
"TS2339": [
13,
13
],
"TS2403": [
33
]
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Stats {
required_error: 0,
matched_error: 0,
extra_error: 1,
extra_error: 0,
panic: 0,
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Stats {
required_error: 0,
matched_error: 0,
extra_error: 1,
extra_error: 0,
panic: 0,
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Stats {
required_error: 0,
matched_error: 0,
extra_error: 1,
extra_error: 0,
panic: 0,
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@
3
]
},
"extra_errors": {
"TS0": 1
},
"extra_error_lines": {
"TS0": [
16
]
}
"extra_errors": {},
"extra_error_lines": {}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Stats {
required_error: 1,
matched_error: 3,
extra_error: 1,
extra_error: 0,
panic: 0,
}
2 changes: 1 addition & 1 deletion crates/stc_ts_type_checker/tests/tsc-stats.rust-debug
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Stats {
required_error: 2861,
matched_error: 7174,
extra_error: 1090,
extra_error: 1086,
panic: 3,
}

0 comments on commit b81ae80

Please sign in to comment.