refactor(ast)!: replace Modifiers with declare on Function (#3844)

This commit is contained in:
Boshen 2024-06-23 10:34:54 +00:00
parent ee6ec4ee57
commit 0673677317
13 changed files with 97 additions and 106 deletions

View file

@ -1436,6 +1436,7 @@ pub struct Function<'a> {
pub id: Option<BindingIdentifier<'a>>,
pub generator: bool,
pub r#async: bool,
pub declare: bool,
pub type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
/// Declaring `this` in a Function <https://www.typescriptlang.org/docs/handbook/2/functions.html#declaring-this-in-a-function>
///
@ -1456,8 +1457,6 @@ pub struct Function<'a> {
pub params: Box<'a, FormalParameters<'a>>,
pub body: Option<Box<'a, FunctionBody<'a>>>,
pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
/// Valid modifiers: `export`, `default`, `async`
pub modifiers: Modifiers<'a>,
pub scope_id: Cell<Option<ScopeId>>,
}

View file

@ -953,19 +953,7 @@ impl<'a> AstBuilder<'a> {
params: Box<'a, FormalParameters<'a>>,
body: Option<Box<'a, FunctionBody<'a>>>,
) -> Box<'a, Function<'a>> {
self.function(
r#type,
span,
id,
false,
false,
None,
params,
body,
None,
None,
Modifiers::empty(),
)
self.function(r#type, span, id, false, false, false, None, params, body, None, None)
}
#[inline]
@ -976,12 +964,12 @@ impl<'a> AstBuilder<'a> {
id: Option<BindingIdentifier<'a>>,
generator: bool,
r#async: bool,
declare: bool,
this_param: Option<TSThisParameter<'a>>,
params: Box<'a, FormalParameters<'a>>,
body: Option<Box<'a, FunctionBody<'a>>>,
type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
modifiers: Modifiers<'a>,
) -> Box<'a, Function<'a>> {
self.alloc(Function::new(
r#type,
@ -989,12 +977,12 @@ impl<'a> AstBuilder<'a> {
id,
generator,
r#async,
declare,
this_param,
params,
body,
type_parameters,
return_type,
modifiers,
))
}

View file

@ -708,7 +708,7 @@ impl<'a> Declaration<'a> {
pub fn declare(&self) -> bool {
match self {
Declaration::VariableDeclaration(decl) => decl.declare,
Declaration::FunctionDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::FunctionDeclaration(decl) => decl.declare,
Declaration::ClassDeclaration(decl) => decl.declare,
Declaration::TSEnumDeclaration(decl) => decl.modifiers.is_contains_declare(),
Declaration::TSTypeAliasDeclaration(decl) => decl.modifiers.is_contains_declare(),
@ -946,12 +946,12 @@ impl<'a> Function<'a> {
id: Option<BindingIdentifier<'a>>,
generator: bool,
r#async: bool,
declare: bool,
this_param: Option<TSThisParameter<'a>>,
params: Box<'a, FormalParameters<'a>>,
body: Option<Box<'a, FunctionBody<'a>>>,
type_parameters: Option<Box<'a, TSTypeParameterDeclaration<'a>>>,
return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
modifiers: Modifiers<'a>,
) -> Self {
Self {
r#type,
@ -959,12 +959,12 @@ impl<'a> Function<'a> {
id,
generator,
r#async,
declare,
this_param,
params,
body,
type_parameters,
return_type,
modifiers,
scope_id: Cell::default(),
}
}
@ -974,7 +974,7 @@ impl<'a> Function<'a> {
self.r#type,
FunctionType::TSDeclareFunction | FunctionType::TSEmptyBodyFunctionExpression
) || self.body.is_none()
|| self.modifiers.contains(ModifierKind::Declare)
|| self.declare
}
pub fn is_expression(&self) -> bool {
@ -1004,12 +1004,12 @@ impl<'a> Hash for Function<'a> {
self.id.hash(state);
self.generator.hash(state);
self.r#async.hash(state);
self.declare.hash(state);
self.this_param.hash(state);
self.params.hash(state);
self.body.hash(state);
self.type_parameters.hash(state);
self.return_type.hash(state);
self.modifiers.hash(state);
}
}

View file

@ -628,7 +628,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Function<'a> {
let n = p.code_len();
let wrap = self.is_expression() && (p.start_of_stmt == n || p.start_of_default_export == n);
p.wrap(wrap, |p| {
if self.modifiers.contains(ModifierKind::Declare) {
if self.declare {
p.print_str(b"declare ");
}
if self.r#async {

View file

@ -108,12 +108,12 @@ impl<'a> IsolatedDeclarations<'a> {
self.ast.copy(&function.id),
function.generator,
function.r#async,
false,
self.ast.copy(&function.this_param),
params,
None,
self.ast.copy(&function.type_parameters),
return_type,
Modifiers::empty(),
);
self.ast.class_method(

View file

@ -18,7 +18,7 @@ impl<'a> IsolatedDeclarations<'a> {
func: &Function<'a>,
modifiers: Option<Modifiers<'a>>,
) -> Option<Box<'a, Function<'a>>> {
if func.modifiers.is_contains_declare() {
if func.declare {
None
} else {
let return_type = self.infer_function_return_type(func);
@ -32,12 +32,12 @@ impl<'a> IsolatedDeclarations<'a> {
self.ast.copy(&func.id),
false,
false,
modifiers.unwrap_or_else(|| self.modifiers_declare()).is_contains_declare(),
self.ast.copy(&func.this_param),
params,
None,
self.ast.copy(&func.type_parameters),
return_type,
modifiers.unwrap_or_else(|| self.modifiers_declare()),
))
}
}

View file

@ -57,7 +57,7 @@ impl<'a> ParserImpl<'a> {
r#async: bool,
generator: bool,
func_kind: FunctionKind,
modifiers: Modifiers<'a>,
modifiers: &Modifiers<'a>,
) -> Result<Box<'a, Function<'a>>> {
let ctx = self.ctx;
self.ctx = self.ctx.and_in(true).and_await(r#async).and_yield(generator);
@ -102,18 +102,27 @@ impl<'a> ParserImpl<'a> {
self.asi()?;
}
for modifier in modifiers.iter() {
if !matches!(modifier.kind, ModifierKind::Declare | ModifierKind::Async) {
self.error(diagnostics::modifiers_cannot_appear(
modifier.span,
modifier.kind.as_str(),
));
}
}
Ok(self.ast.function(
function_type,
self.end_span(span),
id,
generator,
r#async,
modifiers.is_contains_declare(),
this_param,
params,
body,
type_parameters,
return_type,
modifiers,
))
}
@ -152,7 +161,7 @@ impl<'a> ParserImpl<'a> {
self.expect(Kind::Function)?;
let generator = self.eat(Kind::Star);
let id = self.parse_function_id(func_kind, r#async, generator)?;
self.parse_function(span, id, r#async, generator, func_kind, Modifiers::empty())
self.parse_function(span, id, r#async, generator, func_kind, &Modifiers::empty())
}
/// Parse function implementation in Typescript, cursor
@ -161,7 +170,7 @@ impl<'a> ParserImpl<'a> {
&mut self,
start_span: Span,
func_kind: FunctionKind,
modifiers: Modifiers<'a>,
modifiers: &Modifiers<'a>,
) -> Result<Box<'a, Function<'a>>> {
let r#async = modifiers.contains(ModifierKind::Async);
self.expect(Kind::Function)?;
@ -182,7 +191,7 @@ impl<'a> ParserImpl<'a> {
let generator = self.eat(Kind::Star);
let id = self.parse_function_id(func_kind, r#async, generator)?;
let function =
self.parse_function(span, id, r#async, generator, func_kind, Modifiers::empty())?;
self.parse_function(span, id, r#async, generator, func_kind, &Modifiers::empty())?;
Ok(self.ast.function_expression(function))
}
@ -207,7 +216,7 @@ impl<'a> ParserImpl<'a> {
r#async,
generator,
FunctionKind::Expression,
Modifiers::empty(),
&Modifiers::empty(),
)
}

View file

@ -310,10 +310,10 @@ impl<'a> ParserImpl<'a> {
_ if self.at_function_with_async() => {
let declare = modifiers.contains(ModifierKind::Declare);
if declare {
self.parse_ts_declare_function(start_span, modifiers)
self.parse_ts_declare_function(start_span, &modifiers)
.map(Declaration::FunctionDeclaration)
} else if self.ts_enabled() {
self.parse_ts_function_impl(start_span, FunctionKind::Declaration, modifiers)
self.parse_ts_function_impl(start_span, FunctionKind::Declaration, &modifiers)
.map(Declaration::FunctionDeclaration)
} else {
self.parse_function_impl(FunctionKind::Declaration)
@ -327,7 +327,7 @@ impl<'a> ParserImpl<'a> {
pub(crate) fn parse_ts_declare_function(
&mut self,
start_span: Span,
modifiers: Modifiers<'a>,
modifiers: &Modifiers<'a>,
) -> Result<Box<'a, Function<'a>>> {
let r#async = modifiers.contains(ModifierKind::Async);
self.expect(Kind::Function)?;

View file

@ -34,7 +34,6 @@ pub fn check<'a>(node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
AstKind::RegExpLiteral(lit) => js::check_regexp_literal(lit, ctx),
AstKind::Directive(dir) => js::check_directive(dir, ctx),
AstKind::Function(func) => ts::check_function(func, node, ctx),
AstKind::ModuleDeclaration(decl) => {
js::check_module_declaration(decl, node, ctx);
}

View file

@ -173,10 +173,6 @@ fn check_declaration_modifiers<'a>(
}
}
pub fn check_function<'a>(function: &Function<'a>, node: &AstNode<'a>, ctx: &SemanticBuilder<'a>) {
check_declaration_modifiers(&function.modifiers, node, ctx);
}
pub fn check_ts_type_alias_declaration<'a>(
decl: &TSTypeAliasDeclaration<'a>,
node: &AstNode<'a>,

View file

@ -219,12 +219,12 @@ impl<'a> ArrowFunctions<'a> {
id: None,
generator: false,
r#async: arrow_function_expr.r#async,
declare: false,
this_param: None,
params: self.ctx.ast.copy(&arrow_function_expr.params),
body: Some(body),
type_parameters: self.ctx.ast.copy(&arrow_function_expr.type_parameters),
return_type: self.ctx.ast.copy(&arrow_function_expr.return_type),
modifiers: Modifiers::empty(),
scope_id: Cell::new(scope_id),
};

View file

@ -5173,12 +5173,12 @@ pub(crate) const OFFSET_FUNCTION_SPAN: usize = offset_of!(Function, span);
pub(crate) const OFFSET_FUNCTION_ID: usize = offset_of!(Function, id);
pub(crate) const OFFSET_FUNCTION_GENERATOR: usize = offset_of!(Function, generator);
pub(crate) const OFFSET_FUNCTION_ASYNC: usize = offset_of!(Function, r#async);
pub(crate) const OFFSET_FUNCTION_DECLARE: usize = offset_of!(Function, declare);
pub(crate) const OFFSET_FUNCTION_TYPE_PARAMETERS: usize = offset_of!(Function, type_parameters);
pub(crate) const OFFSET_FUNCTION_THIS_PARAM: usize = offset_of!(Function, this_param);
pub(crate) const OFFSET_FUNCTION_PARAMS: usize = offset_of!(Function, params);
pub(crate) const OFFSET_FUNCTION_BODY: usize = offset_of!(Function, body);
pub(crate) const OFFSET_FUNCTION_RETURN_TYPE: usize = offset_of!(Function, return_type);
pub(crate) const OFFSET_FUNCTION_MODIFIERS: usize = offset_of!(Function, modifiers);
pub(crate) const OFFSET_FUNCTION_SCOPE_ID: usize = offset_of!(Function, scope_id);
#[repr(transparent)]
@ -5206,6 +5206,11 @@ impl<'a> FunctionWithoutId<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_ASYNC) as *const bool) }
}
#[inline]
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_DECLARE) as *const bool) }
}
#[inline]
pub fn type_parameters(&self) -> &Option<Box<'a, TSTypeParameterDeclaration<'a>>> {
unsafe {
@ -5246,11 +5251,6 @@ impl<'a> FunctionWithoutId<'a> {
}
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_MODIFIERS) as *const Modifiers<'a>) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5292,6 +5292,11 @@ impl<'a> FunctionWithoutTypeParameters<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_ASYNC) as *const bool) }
}
#[inline]
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_DECLARE) as *const bool) }
}
#[inline]
pub fn this_param(&self) -> &Option<TSThisParameter<'a>> {
unsafe {
@ -5324,11 +5329,6 @@ impl<'a> FunctionWithoutTypeParameters<'a> {
}
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_MODIFIERS) as *const Modifiers<'a>) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5370,6 +5370,11 @@ impl<'a> FunctionWithoutThisParam<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_ASYNC) as *const bool) }
}
#[inline]
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_DECLARE) as *const bool) }
}
#[inline]
pub fn type_parameters(&self) -> &Option<Box<'a, TSTypeParameterDeclaration<'a>>> {
unsafe {
@ -5402,11 +5407,6 @@ impl<'a> FunctionWithoutThisParam<'a> {
}
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_MODIFIERS) as *const Modifiers<'a>) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5448,6 +5448,11 @@ impl<'a> FunctionWithoutParams<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_ASYNC) as *const bool) }
}
#[inline]
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_DECLARE) as *const bool) }
}
#[inline]
pub fn type_parameters(&self) -> &Option<Box<'a, TSTypeParameterDeclaration<'a>>> {
unsafe {
@ -5480,11 +5485,6 @@ impl<'a> FunctionWithoutParams<'a> {
}
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_MODIFIERS) as *const Modifiers<'a>) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5526,6 +5526,11 @@ impl<'a> FunctionWithoutBody<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_ASYNC) as *const bool) }
}
#[inline]
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_DECLARE) as *const bool) }
}
#[inline]
pub fn type_parameters(&self) -> &Option<Box<'a, TSTypeParameterDeclaration<'a>>> {
unsafe {
@ -5558,11 +5563,6 @@ impl<'a> FunctionWithoutBody<'a> {
}
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_MODIFIERS) as *const Modifiers<'a>) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5604,6 +5604,11 @@ impl<'a> FunctionWithoutReturnType<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_ASYNC) as *const bool) }
}
#[inline]
pub fn declare(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_DECLARE) as *const bool) }
}
#[inline]
pub fn type_parameters(&self) -> &Option<Box<'a, TSTypeParameterDeclaration<'a>>> {
unsafe {
@ -5636,11 +5641,6 @@ impl<'a> FunctionWithoutReturnType<'a> {
}
}
#[inline]
pub fn modifiers(&self) -> &Modifiers<'a> {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_MODIFIERS) as *const Modifiers<'a>) }
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {

View file

@ -6422,6 +6422,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
3 │ export export function f() { }
╰────
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[compiler/exportAlreadySeen.ts:3:12]
2 │ export export var x = 1;
3 │ export export function f() { }
· ──────
4 │
╰────
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[compiler/exportAlreadySeen.ts:6:16]
5 │ export export module N {
@ -6438,6 +6446,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
13 │ export export function f()
╰────
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[compiler/exportAlreadySeen.ts:13:12]
12 │ export export var x;
13 │ export export function f()
· ──────
14 │
╰────
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[compiler/exportAlreadySeen.ts:16:16]
15 │ export export module N {
@ -6446,14 +6462,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
17 │ export export interface I { }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:3:12]
2 │ export export var x = 1;
3 │ export export function f() { }
· ──────
4 │
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:7:16]
6 │ export export class C { }
@ -6470,14 +6478,6 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
6 │ export export class C { }
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:13:12]
12 │ export export var x;
13 │ export export function f()
· ──────
14 │
╰────
× Modifiers cannot be used here.
╭─[compiler/exportAlreadySeen.ts:17:16]
16 │ export export class C { }
@ -6743,7 +6743,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
154 │ }
╰────
× Modifiers cannot be used here.
× TS1044: 'export' modifier cannot appear on a module or namespace element.
╭─[compiler/functionsWithModifiersInBlocks1.ts:4:12]
3 │ export function f() { }
4 │ declare export function f() { }
@ -16381,6 +16381,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
5 │ }
╰────
× TS1044: 'public' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:8:5]
7 │ module Y2 {
8 │ public function fn(x: string) { }
· ──────
9 │ }
╰────
× TS1044: 'static' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:12:5]
11 │ module Y4 {
@ -16389,6 +16397,14 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
13 │ }
╰────
× TS1044: 'static' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:16:5]
15 │ module YY {
16 │ static function fn(x: string) { }
· ──────
17 │ }
╰────
× TS1044: 'private' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:20:5]
19 │ module YY2 {
@ -16397,23 +16413,7 @@ Expect to Parse: "conformance/salsa/plainJSRedeclare3.ts"
21 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:8:5]
7 │ module Y2 {
8 │ public function fn(x: string) { }
· ──────
9 │ }
╰────
× Modifiers cannot be used here.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:16:5]
15 │ module YY {
16 │ static function fn(x: string) { }
· ──────
17 │ }
╰────
× Modifiers cannot be used here.
× TS1044: 'private' modifier cannot appear on a module or namespace element.
╭─[conformance/internalModules/moduleBody/invalidModuleWithVarStatements.ts:25:5]
24 │ module YY3 {
25 │ private function fn(x: string) { }