Skip to content

Commit

Permalink
feat(ast): align ts ast scope with typescript (#4253)
Browse files Browse the repository at this point in the history
close: #3969
close: #2023

We need to add scope according to [this](https://github.com/microsoft/TypeScript/blob/d8086f14b6b97c0df34a0cc2f56d4b5926a0c299/src/compiler/binder.ts#L3883-L3962). There are still some ASTs that need to be added to the scope.

---

Context from @Boshen:

Before this whole journey of fixing symbols and scopes I asked @Dunqing to debug through binder.ts via a debugger to fully understand how it does resolution.

We then agreed to align the implementation so that when a problem occurs, we can debug through both implementations and find where our problem is.

tsc doesn't have a specification, so we need to align with the reference implementation instead.
  • Loading branch information
Dunqing committed Jul 17, 2024
1 parent 1f8968a commit af4dc01
Show file tree
Hide file tree
Showing 15 changed files with 582 additions and 709 deletions.
30 changes: 21 additions & 9 deletions crates/oxc_ast/src/ast/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,8 @@ pub use match_ts_type;
///
/// <https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#handbook-content>
#[visited_node]
#[derive(Debug, Hash)]
#[scope]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSConditionalType<'a> {
Expand All @@ -240,6 +241,7 @@ pub struct TSConditionalType<'a> {
pub extends_type: TSType<'a>,
pub true_type: TSType<'a>,
pub false_type: TSType<'a>,
pub scope_id: Cell<Option<ScopeId>>,
}

/// string | string[] | (() => string) | { s: string }
Expand Down Expand Up @@ -579,8 +581,7 @@ pub struct TSTypeParameterInstantiation<'a> {
}

#[visited_node]
#[scope]
#[derive(Debug)]
#[derive(Debug, Hash)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSTypeParameter<'a> {
Expand All @@ -592,7 +593,6 @@ pub struct TSTypeParameter<'a> {
pub r#in: bool,
pub out: bool,
pub r#const: bool,
pub scope_id: Cell<Option<ScopeId>>,
}

#[visited_node]
Expand All @@ -606,16 +606,19 @@ pub struct TSTypeParameterDeclaration<'a> {
}

#[visited_node]
#[derive(Debug, Hash)]
#[scope]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSTypeAliasDeclaration<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub id: BindingIdentifier<'a>,
#[scope(enter_before)]
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
pub type_annotation: TSType<'a>,
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand All @@ -642,17 +645,20 @@ pub struct TSClassImplements<'a> {
///
/// interface `BindingIdentifier` `TypeParameters_opt` `InterfaceExtendsClause_opt` `ObjectType`
#[visited_node]
#[derive(Debug, Hash)]
#[scope]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSInterfaceDeclaration<'a> {
#[cfg_attr(feature = "serialize", serde(flatten))]
pub span: Span,
pub id: BindingIdentifier<'a>,
#[scope(enter_before)]
pub extends: Option<Vec<'a, TSInterfaceHeritage<'a>>>,
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
pub body: Box<'a, TSInterfaceBody<'a>>,
pub declare: bool,
pub scope_id: Cell<Option<ScopeId>>,
}

#[visited_node]
Expand Down Expand Up @@ -726,7 +732,8 @@ pub enum TSMethodSignatureKind {
}

#[visited_node]
#[derive(Debug, Hash)]
#[scope]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSMethodSignature<'a> {
Expand All @@ -740,10 +747,12 @@ pub struct TSMethodSignature<'a> {
pub params: Box<'a, FormalParameters<'a>>,
pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
pub scope_id: Cell<Option<ScopeId>>,
}

#[visited_node]
#[derive(Debug, Hash)]
#[scope]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSConstructSignatureDeclaration<'a> {
Expand All @@ -752,6 +761,7 @@ pub struct TSConstructSignatureDeclaration<'a> {
pub params: Box<'a, FormalParameters<'a>>,
pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
pub scope_id: Cell<Option<ScopeId>>,
}

#[visited_node]
Expand Down Expand Up @@ -994,7 +1004,8 @@ pub struct TSConstructorType<'a> {
}

#[visited_node]
#[derive(Debug, Hash)]
#[scope]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
#[cfg_attr(feature = "serialize", serde(tag = "type", rename_all = "camelCase"))]
pub struct TSMappedType<'a> {
Expand All @@ -1005,6 +1016,7 @@ pub struct TSMappedType<'a> {
pub type_annotation: Option<TSType<'a>>,
pub optional: TSMappedTypeModifierOperator,
pub readonly: TSMappedTypeModifierOperator,
pub scope_id: Cell<Option<ScopeId>>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
Expand Down
90 changes: 65 additions & 25 deletions crates/oxc_ast/src/ast_impl/ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,31 +103,6 @@ impl<'a> TSTypeName<'a> {
}
}

impl<'a> TSTypeParameter<'a> {
pub fn new(
span: Span,
name: BindingIdentifier<'a>,
constraint: Option<TSType<'a>>,
default: Option<TSType<'a>>,
r#in: bool,
out: bool,
r#const: bool,
) -> Self {
Self { span, name, constraint, default, r#in, out, r#const, scope_id: Cell::default() }
}
}

impl<'a> Hash for TSTypeParameter<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.name.hash(state);
self.constraint.hash(state);
self.default.hash(state);
self.r#in.hash(state);
self.out.hash(state);
self.r#const.hash(state);
}
}

impl<'a> TSType<'a> {
/// Remove nested parentheses from this type.
pub fn without_parenthesized(&self) -> &Self {
Expand Down Expand Up @@ -233,3 +208,68 @@ impl ImportOrExportKind {
matches!(self, Self::Type)
}
}

impl<'a> Hash for TSMappedType<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.type_parameter.hash(state);
self.name_type.hash(state);
self.type_annotation.hash(state);
self.optional.hash(state);
self.readonly.hash(state);
}
}

impl<'a> Hash for TSConditionalType<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.check_type.hash(state);
self.extends_type.hash(state);
self.true_type.hash(state);
self.false_type.hash(state);
}
}

impl<'a> Hash for TSInterfaceDeclaration<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.id.hash(state);
self.type_parameters.hash(state);
self.extends.hash(state);
self.body.hash(state);
self.declare.hash(state);
}
}

impl<'a> Hash for TSTypeAliasDeclaration<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.id.hash(state);
self.type_parameters.hash(state);
self.type_annotation.hash(state);
self.declare.hash(state);
}
}

impl<'a> Hash for TSMethodSignature<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.key.hash(state);
self.computed.hash(state);
self.optional.hash(state);
self.kind.hash(state);
self.this_param.hash(state);
self.params.hash(state);
self.return_type.hash(state);
self.type_parameters.hash(state);
}
}

impl<'a> Hash for TSConstructSignatureDeclaration<'a> {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.span.hash(state);
self.params.hash(state);
self.return_type.hash(state);
self.type_parameters.hash(state);
}
}
3 changes: 3 additions & 0 deletions crates/oxc_ast/src/ast_kind_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ impl<'a> AstKind<'a> {
Self::TSNamedTupleMember(_) => "TSNamedTupleMember".into(),

Self::TSPropertySignature(_) => "TSPropertySignature".into(),
Self::TSConditionalType(_) => "TSConditionalType".into(),
Self::TSMappedType(_) => "TSMappedType".into(),
Self::TSConstructSignatureDeclaration(_) => "TSConstructSignatureDeclaration".into(),
}
}
}
25 changes: 14 additions & 11 deletions crates/oxc_ast/src/generated/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6062,7 +6062,14 @@ impl<'a> AstBuilder<'a> {
true_type: TSType<'a>,
false_type: TSType<'a>,
) -> TSConditionalType<'a> {
TSConditionalType { span, check_type, extends_type, true_type, false_type }
TSConditionalType {
span,
check_type,
extends_type,
true_type,
false_type,
scope_id: Default::default(),
}
}

#[inline]
Expand Down Expand Up @@ -6542,16 +6549,7 @@ impl<'a> AstBuilder<'a> {
out: bool,
r#const: bool,
) -> TSTypeParameter<'a> {
TSTypeParameter {
span,
name,
constraint,
default,
r#in,
out,
r#const,
scope_id: Default::default(),
}
TSTypeParameter { span, name, constraint, default, r#in, out, r#const }
}

#[inline]
Expand Down Expand Up @@ -6605,6 +6603,7 @@ impl<'a> AstBuilder<'a> {
type_parameters: type_parameters.into_in(self.allocator),
type_annotation,
declare,
scope_id: Default::default(),
}
}

Expand Down Expand Up @@ -6675,6 +6674,7 @@ impl<'a> AstBuilder<'a> {
type_parameters: type_parameters.into_in(self.allocator),
body: body.into_in(self.allocator),
declare,
scope_id: Default::default(),
}
}

Expand Down Expand Up @@ -7013,6 +7013,7 @@ impl<'a> AstBuilder<'a> {
params: params.into_in(self.allocator),
return_type: return_type.into_in(self.allocator),
type_parameters: type_parameters.into_in(self.allocator),
scope_id: Default::default(),
}
}

Expand Down Expand Up @@ -7066,6 +7067,7 @@ impl<'a> AstBuilder<'a> {
params: params.into_in(self.allocator),
return_type: return_type.into_in(self.allocator),
type_parameters: type_parameters.into_in(self.allocator),
scope_id: Default::default(),
}
}

Expand Down Expand Up @@ -7678,6 +7680,7 @@ impl<'a> AstBuilder<'a> {
type_annotation,
optional,
readonly,
scope_id: Default::default(),
}
}

Expand Down
9 changes: 9 additions & 0 deletions crates/oxc_ast/src/generated/ast_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ pub enum AstType {
TSEnumMember,
TSTypeAnnotation,
TSLiteralType,
TSConditionalType,
TSUnionType,
TSIntersectionType,
TSParenthesizedType,
Expand Down Expand Up @@ -137,13 +138,15 @@ pub enum AstType {
TSInterfaceDeclaration,
TSPropertySignature,
TSMethodSignature,
TSConstructSignatureDeclaration,
TSInterfaceHeritage,
TSModuleDeclaration,
TSModuleBlock,
TSTypeLiteral,
TSInferType,
TSTypeQuery,
TSImportType,
TSMappedType,
TSTemplateLiteralType,
TSAsExpression,
TSSatisfiesExpression,
Expand Down Expand Up @@ -273,6 +276,7 @@ pub enum AstKind<'a> {
TSEnumMember(&'a TSEnumMember<'a>),
TSTypeAnnotation(&'a TSTypeAnnotation<'a>),
TSLiteralType(&'a TSLiteralType<'a>),
TSConditionalType(&'a TSConditionalType<'a>),
TSUnionType(&'a TSUnionType<'a>),
TSIntersectionType(&'a TSIntersectionType<'a>),
TSParenthesizedType(&'a TSParenthesizedType<'a>),
Expand Down Expand Up @@ -303,13 +307,15 @@ pub enum AstKind<'a> {
TSInterfaceDeclaration(&'a TSInterfaceDeclaration<'a>),
TSPropertySignature(&'a TSPropertySignature<'a>),
TSMethodSignature(&'a TSMethodSignature<'a>),
TSConstructSignatureDeclaration(&'a TSConstructSignatureDeclaration<'a>),
TSInterfaceHeritage(&'a TSInterfaceHeritage<'a>),
TSModuleDeclaration(&'a TSModuleDeclaration<'a>),
TSModuleBlock(&'a TSModuleBlock<'a>),
TSTypeLiteral(&'a TSTypeLiteral<'a>),
TSInferType(&'a TSInferType<'a>),
TSTypeQuery(&'a TSTypeQuery<'a>),
TSImportType(&'a TSImportType<'a>),
TSMappedType(&'a TSMappedType<'a>),
TSTemplateLiteralType(&'a TSTemplateLiteralType<'a>),
TSAsExpression(&'a TSAsExpression<'a>),
TSSatisfiesExpression(&'a TSSatisfiesExpression<'a>),
Expand Down Expand Up @@ -440,6 +446,7 @@ impl<'a> GetSpan for AstKind<'a> {
Self::TSEnumMember(it) => it.span(),
Self::TSTypeAnnotation(it) => it.span(),
Self::TSLiteralType(it) => it.span(),
Self::TSConditionalType(it) => it.span(),
Self::TSUnionType(it) => it.span(),
Self::TSIntersectionType(it) => it.span(),
Self::TSParenthesizedType(it) => it.span(),
Expand Down Expand Up @@ -470,13 +477,15 @@ impl<'a> GetSpan for AstKind<'a> {
Self::TSInterfaceDeclaration(it) => it.span(),
Self::TSPropertySignature(it) => it.span(),
Self::TSMethodSignature(it) => it.span(),
Self::TSConstructSignatureDeclaration(it) => it.span(),
Self::TSInterfaceHeritage(it) => it.span(),
Self::TSModuleDeclaration(it) => it.span(),
Self::TSModuleBlock(it) => it.span(),
Self::TSTypeLiteral(it) => it.span(),
Self::TSInferType(it) => it.span(),
Self::TSTypeQuery(it) => it.span(),
Self::TSImportType(it) => it.span(),
Self::TSMappedType(it) => it.span(),
Self::TSTemplateLiteralType(it) => it.span(),
Self::TSAsExpression(it) => it.span(),
Self::TSSatisfiesExpression(it) => it.span(),
Expand Down
Loading

0 comments on commit af4dc01

Please sign in to comment.