mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
Improve type resolver (#994)
This commit is contained in:
parent
598705882a
commit
0a83809b2a
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "swc_ecma_transforms"
|
||||
version = "0.21.1"
|
||||
version = "0.21.2"
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||
license = "Apache-2.0/MIT"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
|
@ -455,8 +455,16 @@ macro_rules! track_ident {
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Ref;
|
||||
let decorators = c.decorators.fold_with(self);
|
||||
|
||||
self.ident_type = IdentType::Ref;
|
||||
let super_class = c.super_class.fold_with(self);
|
||||
|
||||
self.ident_type = IdentType::Binding;
|
||||
let type_params = c.type_params.fold_with(self);
|
||||
|
||||
self.ident_type = IdentType::Ref;
|
||||
let super_type_params = c.super_type_params.fold_with(self);
|
||||
|
||||
self.ident_type = IdentType::Ref;
|
||||
let implements = c.implements.fold_with(self);
|
||||
self.ident_type = old;
|
||||
@ -470,8 +478,8 @@ macro_rules! track_ident {
|
||||
implements,
|
||||
body,
|
||||
super_class,
|
||||
type_params: c.type_params,
|
||||
super_type_params: c.super_type_params,
|
||||
type_params,
|
||||
super_type_params,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ impl<'a> Resolver<'a> {
|
||||
|
||||
/// Returns a [Mark] for an identifier reference.
|
||||
fn mark_for_ref(&self, sym: &JsWord) -> Option<Mark> {
|
||||
if self.in_type {
|
||||
if self.handle_types && self.in_type {
|
||||
let mut mark = self.mark;
|
||||
let mut scope = Some(&self.current);
|
||||
|
||||
@ -126,39 +126,36 @@ impl<'a> Resolver<'a> {
|
||||
// cur.hoisted_symbols.borrow().contains(sym) {
|
||||
if cur.declared_types.contains(sym) {
|
||||
if mark == Mark::root() {
|
||||
return None;
|
||||
break;
|
||||
}
|
||||
return Some(mark);
|
||||
}
|
||||
mark = mark.parent();
|
||||
scope = cur.parent;
|
||||
}
|
||||
|
||||
None
|
||||
} else {
|
||||
let mut mark = self.mark;
|
||||
let mut scope = Some(&self.current);
|
||||
|
||||
while let Some(cur) = scope {
|
||||
if cur.declared_symbols.contains(sym) || cur.hoisted_symbols.borrow().contains(sym)
|
||||
{
|
||||
if mark == Mark::root() {
|
||||
return None;
|
||||
}
|
||||
return Some(mark);
|
||||
}
|
||||
mark = mark.parent();
|
||||
scope = cur.parent;
|
||||
}
|
||||
|
||||
if let Some((ref c, mark)) = self.cur_defining {
|
||||
if *c == *sym {
|
||||
return Some(mark);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
let mut mark = self.mark;
|
||||
let mut scope = Some(&self.current);
|
||||
|
||||
while let Some(cur) = scope {
|
||||
if cur.declared_symbols.contains(sym) || cur.hoisted_symbols.borrow().contains(sym) {
|
||||
if mark == Mark::root() {
|
||||
return None;
|
||||
}
|
||||
return Some(mark);
|
||||
}
|
||||
mark = mark.parent();
|
||||
scope = cur.parent;
|
||||
}
|
||||
|
||||
if let Some((ref c, mark)) = self.cur_defining {
|
||||
if *c == *sym {
|
||||
return Some(mark);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn fold_binding_ident(&mut self, ident: Ident) -> Ident {
|
||||
@ -622,6 +619,7 @@ impl<'a> Fold for Resolver<'a> {
|
||||
return n;
|
||||
}
|
||||
|
||||
self.in_type = true;
|
||||
self.ident_type = IdentType::Binding;
|
||||
n.fold_children_with(self)
|
||||
}
|
||||
@ -631,6 +629,7 @@ impl<'a> Fold for Resolver<'a> {
|
||||
return n;
|
||||
}
|
||||
|
||||
self.in_type = true;
|
||||
self.ident_type = IdentType::Ref;
|
||||
TsQualifiedName {
|
||||
left: n.left.fold_with(self),
|
||||
@ -747,10 +746,13 @@ impl<'a> Fold for Resolver<'a> {
|
||||
let value = p.value.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
let type_ann = p.type_ann.fold_with(self);
|
||||
|
||||
ClassProp {
|
||||
decorators,
|
||||
key,
|
||||
value,
|
||||
type_ann,
|
||||
..p
|
||||
}
|
||||
}
|
||||
@ -773,6 +775,7 @@ impl<'a> Fold for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn fold_expr(&mut self, expr: Expr) -> Expr {
|
||||
self.in_type = false;
|
||||
let expr = validate!(expr);
|
||||
|
||||
let old = self.ident_type;
|
||||
@ -827,6 +830,11 @@ impl<'a> Fold for Resolver<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fold_decl(&mut self, decl: Decl) -> Decl {
|
||||
self.in_type = false;
|
||||
decl.fold_children_with(self)
|
||||
}
|
||||
|
||||
fn fold_fn_expr(&mut self, e: FnExpr) -> FnExpr {
|
||||
let ident = if let Some(ident) = e.ident {
|
||||
Some(self.fold_binding_ident(ident))
|
||||
@ -851,6 +859,9 @@ impl<'a> Fold for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn fold_function(&mut self, mut f: Function) -> Function {
|
||||
f.type_params = f.type_params.fold_with(self);
|
||||
|
||||
self.in_type = false;
|
||||
self.ident_type = IdentType::Ref;
|
||||
f.decorators = f.decorators.fold_with(self);
|
||||
|
||||
@ -860,17 +871,26 @@ impl<'a> Fold for Resolver<'a> {
|
||||
self.ident_type = IdentType::Ref;
|
||||
f.body = f.body.map(|stmt| stmt.fold_children_with(self));
|
||||
|
||||
f.return_type = f.return_type.fold_with(self);
|
||||
|
||||
f
|
||||
}
|
||||
|
||||
fn fold_ident(&mut self, i: Ident) -> Ident {
|
||||
fn fold_ident(&mut self, mut i: Ident) -> Ident {
|
||||
i = i.fold_children_with(self);
|
||||
|
||||
match self.ident_type {
|
||||
IdentType::Binding => self.fold_binding_ident(i),
|
||||
IdentType::Ref => {
|
||||
let Ident { span, sym, .. } = i;
|
||||
|
||||
if cfg!(debug_assertions) && LOG {
|
||||
eprintln!("resolver: IdentRef {}{:?}", sym, i.span.ctxt());
|
||||
eprintln!(
|
||||
"resolver: IdentRef (type = {}) {}{:?}",
|
||||
self.in_type,
|
||||
sym,
|
||||
i.span.ctxt()
|
||||
);
|
||||
}
|
||||
|
||||
if span.ctxt() != SyntaxContext::empty() {
|
||||
@ -922,8 +942,9 @@ impl<'a> Fold for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn fold_import_named_specifier(&mut self, s: ImportNamedSpecifier) -> ImportNamedSpecifier {
|
||||
self.in_type = false;
|
||||
let old = self.ident_type;
|
||||
self.ident_type = IdentType::Ref;
|
||||
self.ident_type = IdentType::Binding;
|
||||
let local = s.local.fold_with(self);
|
||||
self.ident_type = old;
|
||||
|
||||
@ -966,6 +987,7 @@ impl<'a> Fold for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn fold_pat(&mut self, p: Pat) -> Pat {
|
||||
self.in_type = false;
|
||||
let old = self.cur_defining.take();
|
||||
let p = p.fold_children_with(self);
|
||||
|
||||
@ -974,6 +996,8 @@ impl<'a> Fold for Resolver<'a> {
|
||||
}
|
||||
|
||||
fn fold_var_decl(&mut self, decl: VarDecl) -> VarDecl {
|
||||
self.in_type = false;
|
||||
|
||||
let old_hoist = self.hoist;
|
||||
|
||||
self.hoist = VarDeclKind::Var == decl.kind;
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
||||
};
|
||||
use swc_common::chain;
|
||||
use swc_ecma_parser::{EsConfig, Syntax, TsConfig};
|
||||
use swc_ecma_visit::{as_folder, VisitMut};
|
||||
use swc_ecma_visit::{as_folder, VisitMut, VisitMutWith};
|
||||
|
||||
struct TsHygiene {
|
||||
top_level_mark: Mark,
|
||||
@ -16,9 +16,7 @@ struct TsHygiene {
|
||||
|
||||
impl VisitMut for TsHygiene {
|
||||
fn visit_mut_ident(&mut self, i: &mut Ident) {
|
||||
if i.span.ctxt == SyntaxContext::empty()
|
||||
|| SyntaxContext::empty().apply_mark(self.top_level_mark) == i.span.ctxt
|
||||
{
|
||||
if SyntaxContext::empty().apply_mark(self.top_level_mark) == i.span.ctxt {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -26,6 +24,20 @@ impl VisitMut for TsHygiene {
|
||||
i.sym = format!("{}__{}", i.sym, ctxt).into();
|
||||
i.span = i.span.with_ctxt(SyntaxContext::empty());
|
||||
}
|
||||
|
||||
fn visit_mut_member_expr(&mut self, n: &mut MemberExpr) {
|
||||
n.obj.visit_mut_with(self);
|
||||
if n.computed {
|
||||
n.prop.visit_mut_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_ts_enum_member_id(&mut self, _: &mut TsEnumMemberId) {}
|
||||
|
||||
/// TODO: Handle tyep parameter correctly
|
||||
fn visit_mut_ts_type_param(&mut self, _: &mut TsTypeParam) {}
|
||||
|
||||
fn visit_mut_prop_name(&mut self, _: &mut PropName) {}
|
||||
}
|
||||
|
||||
fn tr() -> impl Fold {
|
||||
@ -1271,7 +1283,7 @@ class Foo {
|
||||
|
||||
}
|
||||
|
||||
new G<Foo__2>();
|
||||
new G<Foo>();
|
||||
}
|
||||
}
|
||||
",
|
||||
@ -1321,7 +1333,7 @@ const bar = {
|
||||
);
|
||||
|
||||
to_ts!(
|
||||
ts_resolver_neseted_enum,
|
||||
ts_resolver_nested_enum,
|
||||
"
|
||||
enum Foo {
|
||||
name: string
|
||||
@ -1347,7 +1359,7 @@ const bar = {} as Foo;
|
||||
string
|
||||
}
|
||||
const foo__2 = {
|
||||
} as Foo;
|
||||
} as Foo__2;
|
||||
}
|
||||
const bar = {
|
||||
} as Foo;
|
||||
@ -1377,3 +1389,74 @@ const bar = {
|
||||
} as Foo;
|
||||
"
|
||||
);
|
||||
|
||||
to_ts!(
|
||||
ts_resolver_import_and_type_ann,
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
const a: Nullable<string> = 'hello';
|
||||
console.log(a);
|
||||
",
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
const a: Nullable<string> = 'hello';
|
||||
console.log(a);
|
||||
"
|
||||
);
|
||||
|
||||
identical_ts!(
|
||||
ts_resolver_import_and_type_param,
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
import { SomeOther } from 'other';
|
||||
const a: Nullable<SomeOther> = 'hello';
|
||||
console.log(a);
|
||||
"
|
||||
);
|
||||
|
||||
identical_ts!(
|
||||
ts_resolver_import_and_implements,
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
import { Component } from 'react';
|
||||
class Foo implements Component<Nullable> {}
|
||||
new Foo();
|
||||
"
|
||||
);
|
||||
|
||||
identical_ts!(
|
||||
ts_resolver_import_and_extends,
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
import { Component } from 'react';
|
||||
class Foo extends Component<Nullable, {}> {}
|
||||
new Foo();
|
||||
"
|
||||
);
|
||||
|
||||
identical_ts!(
|
||||
ts_resolver_method_type_param,
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
import { Another } from 'some';
|
||||
class A {
|
||||
do(): Nullable<Another> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
new A();
|
||||
"
|
||||
);
|
||||
|
||||
identical_ts!(
|
||||
ts_resolver_nested_type_ref,
|
||||
"
|
||||
import { Nullable } from 'nullable';
|
||||
import { SomeOther } from 'some';
|
||||
import { Another } from 'some';
|
||||
class A extends Nullable {
|
||||
other: Nullable<Another>;
|
||||
}
|
||||
new A();
|
||||
"
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@swc/core",
|
||||
"version": "1.2.21",
|
||||
"version": "1.2.22",
|
||||
"description": "Super-fast alternative for babel",
|
||||
"main": "./index.js",
|
||||
"author": "강동윤 <kdy1997.dev@gmail.com>",
|
||||
|
Loading…
Reference in New Issue
Block a user