Skip to content

Commit

Permalink
feat(es/parser): typeof on #private Fields
Browse files Browse the repository at this point in the history
  • Loading branch information
magic-akari committed Apr 11, 2022
1 parent 14ab63b commit b42bbf4
Show file tree
Hide file tree
Showing 15 changed files with 810 additions and 16 deletions.
2 changes: 1 addition & 1 deletion crates/swc_ecma_ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub use self::{
typescript::{
Accessibility, TruePlusMinus, TsArrayType, TsAsExpr, TsCallSignatureDecl,
TsConditionalType, TsConstAssertion, TsConstructSignatureDecl, TsConstructorType,
TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment,
TsEntityMember, TsEntityName, TsEnumDecl, TsEnumMember, TsEnumMemberId, TsExportAssignment,
TsExprWithTypeArgs, TsExternalModuleRef, TsFnOrConstructorType, TsFnParam, TsFnType,
TsGetterSignature, TsImportEqualsDecl, TsImportType, TsIndexSignature, TsIndexedAccessType,
TsInferType, TsInstantiation, TsInterfaceBody, TsInterfaceDecl, TsIntersectionType,
Expand Down
16 changes: 14 additions & 2 deletions crates/swc_ecma_ast/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use crate::{
lit::{Bool, Number, Str},
module::ModuleItem,
pat::{ArrayPat, AssignPat, ObjectPat, Pat, RestPat},
BigInt, BindingIdent, TplElement,
BigInt, BindingIdent, PrivateName, TplElement,
};

#[ast_node("TsTypeAnnotation")]
Expand Down Expand Up @@ -101,7 +101,7 @@ pub struct TsQualifiedName {
#[span(lo)]
pub left: TsEntityName,
#[span(hi)]
pub right: Ident,
pub right: TsEntityMember,
}

#[ast_node]
Expand All @@ -116,6 +116,18 @@ pub enum TsEntityName {
Ident(Ident),
}

#[ast_node]
#[derive(Eq, Hash, Is, EqIgnoreSpan)]
#[allow(variant_size_differences)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
pub enum TsEntityMember {
#[tag("Identifier")]
Ident(Ident),

#[tag("PrivateName")]
PrivateName(PrivateName),
}

// ================
// TypeScript type members (for type literal / interface / class)
// ================
Expand Down
10 changes: 10 additions & 0 deletions crates/swc_ecma_codegen/src/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ where
}
}

#[emitter]
fn emit_ts_entity_member(&mut self, n: &TsEntityMember) -> Result {
self.emit_leading_comments_of_span(n.span(), false)?;

match n {
TsEntityMember::Ident(n) => emit!(n),
TsEntityMember::PrivateName(n) => emit!(n),
}
}

#[emitter]
fn emit_ts_enum_decl(&mut self, n: &TsEnumDecl) -> Result {
self.emit_leading_comments_of_span(n.span(), false)?;
Expand Down
31 changes: 21 additions & 10 deletions crates/swc_ecma_parser/src/parser/typescript.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,11 @@ impl<I: Tokens> Parser<I> {
}

/// `tsParseEntityName`
fn parse_ts_entity_name(&mut self, allow_reserved_words: bool) -> PResult<TsEntityName> {
fn parse_ts_entity_name(
&mut self,
allow_reserved_words: bool,
allow_private_identifiers: bool,
) -> PResult<TsEntityName> {
debug_assert!(self.input.syntax().typescript());

let init = self.parse_ident_name()?;
Expand All @@ -194,7 +198,7 @@ impl<I: Tokens> Parser<I> {
let mut entity = TsEntityName::Ident(init);
while eat!(self, '.') {
let dot_start = cur_pos!(self);
if !is!(self, '#') && !is!(self, IdentName) {
if !allow_private_identifiers && !is!(self, '#') && !is!(self, IdentName) {
self.emit_err(
Span::new(dot_start, dot_start, Default::default()),
SyntaxError::TS1003,
Expand All @@ -203,10 +207,13 @@ impl<I: Tokens> Parser<I> {
}

let left = entity;
let right = if allow_reserved_words {
self.parse_ident_name()?
let right = if allow_private_identifiers {
self.parse_maybe_private_name()?
.either(Into::into, Into::into)
} else if allow_reserved_words {
self.parse_ident_name()?.into()
} else {
self.parse_ident(false, false)?
self.parse_ident(false, false)?.into()
};
entity = TsEntityName::TsQualifiedName(Box::new(TsQualifiedName { left, right }));
}
Expand All @@ -223,7 +230,9 @@ impl<I: Tokens> Parser<I> {

let has_modifier = self.eat_any_ts_modifier()?;

let type_name = self.parse_ts_entity_name(/* allow_reserved_words */ true)?;
let type_name = self.parse_ts_entity_name(
/* allow_reserved_words */ true, /* allow_private_identifiers */ false,
)?;
trace_cur!(self, parse_ts_type_ref__type_args);
let type_params = if !self.input.had_line_break_before_cur() && is!(self, '<') {
Some(self.parse_ts_type_args()?)
Expand Down Expand Up @@ -315,7 +324,7 @@ impl<I: Tokens> Parser<I> {
expect!(self, ')');

let qualifier = if eat!(self, '.') {
self.parse_ts_entity_name(false).map(Some)?
self.parse_ts_entity_name(false, false).map(Some)?
} else {
None
};
Expand Down Expand Up @@ -345,7 +354,7 @@ impl<I: Tokens> Parser<I> {
} else {
self.parse_ts_entity_name(
// allow_reserved_word
true,
true, true,
)
.map(From::from)?
};
Expand Down Expand Up @@ -1124,8 +1133,10 @@ impl<I: Tokens> Parser<I> {
if self.is_ts_external_module_ref()? {
self.parse_ts_external_module_ref().map(From::from)
} else {
self.parse_ts_entity_name(/* allow_reserved_words */ false)
.map(From::from)
self.parse_ts_entity_name(
/* allow_reserved_words */ false, /* allow_private_identifiers */ false,
)
.map(From::from)
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class C {
#a = 'a';

constructor() {
const a: typeof this.#a = ''; // Ok
const b: typeof this.#a = 1; // Error
}
}
Loading

0 comments on commit b42bbf4

Please sign in to comment.