Improve type resolver (#994)

This commit is contained in:
강동윤 2020-08-24 18:48:54 +09:00 committed by GitHub
parent 598705882a
commit 0a83809b2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 156 additions and 41 deletions

View File

@ -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"

View File

@ -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,
}
}

View File

@ -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;

View File

@ -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();
"
);

View File

@ -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>",