refactor(semantic): update the order of visit_function and Visit fields in the builder to be consistent (#4248)

Same as #4195
This commit is contained in:
Dunqing 2024-07-14 11:39:15 +00:00
parent 8bfeabfe6a
commit ace4f1ff77
14 changed files with 221 additions and 217 deletions

View file

@ -1439,7 +1439,7 @@ pub struct BindingRestElement<'a> {
#[scope(
// TODO: `ScopeFlags::Function` is not correct if this is a `MethodDefinition`
flags(flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function),
strict_if(self.body.as_ref().is_some_and(|body| body.has_use_strict_directive())),
strict_if(self.is_strict()),
)]
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize, Tsify))]
@ -1470,8 +1470,8 @@ pub struct Function<'a> {
/// ```
pub this_param: Option<TSThisParameter<'a>>,
pub params: Box<'a, FormalParameters<'a>>,
pub body: Option<Box<'a, FunctionBody<'a>>>,
pub return_type: Option<Box<'a, TSTypeAnnotation<'a>>>,
pub body: Option<Box<'a, FunctionBody<'a>>>,
pub scope_id: Cell<Option<ScopeId>>,
}

View file

@ -150,8 +150,8 @@ impl<'a> AstBuilder<'a> {
Option::<TSTypeParameterDeclaration>::None,
None,
params,
body,
Option::<TSTypeAnnotation>::None,
body,
))
}

View file

@ -554,14 +554,14 @@ impl<'a> AstBuilder<'a> {
type_parameters: T1,
this_param: Option<TSThisParameter<'a>>,
params: T2,
body: T3,
return_type: T4,
return_type: T3,
body: T4,
) -> Expression<'a>
where
T1: IntoIn<'a, Option<Box<'a, TSTypeParameterDeclaration<'a>>>>,
T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>,
T3: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T3: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
{
Expression::FunctionExpression(self.alloc(self.function(
r#type,
@ -573,8 +573,8 @@ impl<'a> AstBuilder<'a> {
type_parameters,
this_param,
params,
body,
return_type,
body,
)))
}
@ -2689,14 +2689,14 @@ impl<'a> AstBuilder<'a> {
type_parameters: T1,
this_param: Option<TSThisParameter<'a>>,
params: T2,
body: T3,
return_type: T4,
return_type: T3,
body: T4,
) -> Declaration<'a>
where
T1: IntoIn<'a, Option<Box<'a, TSTypeParameterDeclaration<'a>>>>,
T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>,
T3: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T3: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
{
Declaration::FunctionDeclaration(self.alloc(self.function(
r#type,
@ -2708,8 +2708,8 @@ impl<'a> AstBuilder<'a> {
type_parameters,
this_param,
params,
body,
return_type,
body,
)))
}
@ -3720,14 +3720,14 @@ impl<'a> AstBuilder<'a> {
type_parameters: T1,
this_param: Option<TSThisParameter<'a>>,
params: T2,
body: T3,
return_type: T4,
return_type: T3,
body: T4,
) -> Function<'a>
where
T1: IntoIn<'a, Option<Box<'a, TSTypeParameterDeclaration<'a>>>>,
T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>,
T3: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T3: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
{
Function {
r#type,
@ -3739,8 +3739,8 @@ impl<'a> AstBuilder<'a> {
type_parameters: type_parameters.into_in(self.allocator),
this_param,
params: params.into_in(self.allocator),
body: body.into_in(self.allocator),
return_type: return_type.into_in(self.allocator),
body: body.into_in(self.allocator),
scope_id: Default::default(),
}
}
@ -3757,14 +3757,14 @@ impl<'a> AstBuilder<'a> {
type_parameters: T1,
this_param: Option<TSThisParameter<'a>>,
params: T2,
body: T3,
return_type: T4,
return_type: T3,
body: T4,
) -> Box<'a, Function<'a>>
where
T1: IntoIn<'a, Option<Box<'a, TSTypeParameterDeclaration<'a>>>>,
T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>,
T3: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T3: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
{
self.function(
r#type,
@ -3776,8 +3776,8 @@ impl<'a> AstBuilder<'a> {
type_parameters,
this_param,
params,
body,
return_type,
body,
)
.into_in(self.allocator)
}
@ -4901,14 +4901,14 @@ impl<'a> AstBuilder<'a> {
type_parameters: T1,
this_param: Option<TSThisParameter<'a>>,
params: T2,
body: T3,
return_type: T4,
return_type: T3,
body: T4,
) -> ExportDefaultDeclarationKind<'a>
where
T1: IntoIn<'a, Option<Box<'a, TSTypeParameterDeclaration<'a>>>>,
T2: IntoIn<'a, Box<'a, FormalParameters<'a>>>,
T3: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T3: IntoIn<'a, Option<Box<'a, TSTypeAnnotation<'a>>>>,
T4: IntoIn<'a, Option<Box<'a, FunctionBody<'a>>>>,
{
ExportDefaultDeclarationKind::FunctionDeclaration(self.alloc(self.function(
r#type,
@ -4920,8 +4920,8 @@ impl<'a> AstBuilder<'a> {
type_parameters,
this_param,
params,
body,
return_type,
body,
)))
}

View file

@ -3038,7 +3038,7 @@ pub mod walk {
visitor.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
if it.body.as_ref().is_some_and(|body| body.has_use_strict_directive()) {
if it.is_strict() {
flags |= ScopeFlags::StrictMode;
}
flags
@ -3055,12 +3055,12 @@ pub mod walk {
visitor.visit_ts_this_parameter(this_param);
}
visitor.visit_formal_parameters(&it.params);
if let Some(body) = &it.body {
visitor.visit_function_body(body);
}
if let Some(return_type) = &it.return_type {
visitor.visit_ts_type_annotation(return_type);
}
if let Some(body) = &it.body {
visitor.visit_function_body(body);
}
visitor.leave_scope();
visitor.leave_node(kind);
}

View file

@ -3171,7 +3171,7 @@ pub mod walk_mut {
visitor.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
if it.body.as_ref().is_some_and(|body| body.has_use_strict_directive()) {
if it.is_strict() {
flags |= ScopeFlags::StrictMode;
}
flags
@ -3188,12 +3188,12 @@ pub mod walk_mut {
visitor.visit_ts_this_parameter(this_param);
}
visitor.visit_formal_parameters(&mut it.params);
if let Some(body) = &mut it.body {
visitor.visit_function_body(body);
}
if let Some(return_type) = &mut it.return_type {
visitor.visit_ts_type_annotation(return_type);
}
if let Some(body) = &mut it.body {
visitor.visit_function_body(body);
}
visitor.leave_scope();
visitor.leave_node(kind);
}

View file

@ -123,8 +123,8 @@ impl<'a> IsolatedDeclarations<'a> {
self.ast.copy(&function.type_parameters),
self.ast.copy(&function.this_param),
params,
Option::<FunctionBody>::None,
return_type,
Option::<FunctionBody>::None,
);
self.ast.class_element_method_definition(

View file

@ -37,8 +37,8 @@ impl<'a> IsolatedDeclarations<'a> {
self.ast.copy(&func.type_parameters),
self.ast.copy(&func.this_param),
params,
Option::<FunctionBody>::None,
return_type,
Option::<FunctionBody>::None,
))
}
}

View file

@ -208,6 +208,14 @@ source: crates/oxc_linter/src/tester.rs
╰────
help: The `Function` type accepts any function-like value
⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead
╭─[ban_types.tsx:5:24]
4 │
5 │ arg(): Array<String> {
· ──────
6 │ const foo: String = 1 as String;
╰────
⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead
╭─[ban_types.tsx:6:24]
5 │ arg(): Array<String> {
@ -224,14 +232,6 @@ source: crates/oxc_linter/src/tester.rs
7 │ }
╰────
⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead
╭─[ban_types.tsx:5:24]
4 │
5 │ arg(): Array<String> {
· ──────
6 │ const foo: String = 1 as String;
╰────
⚠ typescript-eslint(ban-types): Don't use `Function` as a type
╭─[ban_types.tsx:3:12]
2 │ type Props = {

View file

@ -181,8 +181,8 @@ impl<'a> ParserImpl<'a> {
type_parameters,
this_param,
params,
body,
return_type,
body,
))
}

View file

@ -106,8 +106,9 @@ fn function_as_var(flags: ScopeFlags, source_type: SourceType) -> bool {
impl<'a> Binder for Function<'a> {
fn bind(&self, builder: &mut SemanticBuilder) {
let current_scope_id = builder.current_scope_id;
let scope_flags = builder.current_scope_flags();
if let Some(ident) = &self.id {
if !builder.current_scope_flags().is_strict_mode()
if !scope_flags.is_strict_mode()
&& matches!(
builder.nodes.parent_kind(builder.current_node_id),
Some(AstKind::IfStatement(_))
@ -118,12 +119,10 @@ impl<'a> Binder for Function<'a> {
} else if self.r#type == FunctionType::FunctionDeclaration {
// The visitor is already inside the function scope,
// retrieve the parent scope for the function id to bind to.
let parent_scope_id = builder.scope.get_parent_id(current_scope_id).unwrap();
let parent_flags = builder.scope.get_flags(parent_scope_id);
let (includes, excludes) =
if (parent_flags.is_strict_mode() || self.r#async || self.generator)
&& !function_as_var(parent_flags, builder.source_type)
if (scope_flags.is_strict_mode() || self.r#async || self.generator)
&& !function_as_var(scope_flags, builder.source_type)
{
(
SymbolFlags::Function | SymbolFlags::BlockScopedVariable,
@ -136,13 +135,7 @@ impl<'a> Binder for Function<'a> {
)
};
let symbol_id = builder.declare_symbol_on_scope(
ident.span,
&ident.name,
parent_scope_id,
includes,
excludes,
);
let symbol_id = builder.declare_symbol(ident.span, &ident.name, includes, excludes);
ident.symbol_id.set(Some(symbol_id));
} else if self.r#type == FunctionType::FunctionExpression {
// https://tc39.es/ecma262/#sec-runtime-semantics-instantiateordinaryfunctionexpression
@ -158,7 +151,6 @@ impl<'a> Binder for Function<'a> {
}
// bind scope flags: Constructor | GetAccessor | SetAccessor
debug_assert!(builder.current_scope_flags().contains(ScopeFlags::Function));
if let Some(kind) = builder.nodes.parent_kind(builder.current_node_id) {
match kind {
AstKind::MethodDefinition(def) => {

View file

@ -414,13 +414,21 @@ impl<'a> SemanticBuilder<'a> {
}
}
fn bind_class_expression(&mut self) {
if let AstKind::Class(class) = self.nodes.kind(self.current_node_id) {
if class.is_expression() {
// We must to bind class expression when enter BindingIdentifier,
// because we should add binding to current scope
class.bind(self);
fn bind_function_or_class_expression(&mut self) {
match self.nodes.kind(self.current_node_id) {
AstKind::Class(class) => {
if class.is_expression() {
// We need to bind class expression in the class scope,
class.bind(self);
}
}
AstKind::Function(func) => {
if func.is_expression() {
// We need to bind function expression in the function scope,
func.bind(self);
}
}
_ => {}
}
}
}
@ -461,8 +469,10 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
}
if !flags.is_top() {
self.bind_class_expression();
self.bind_function_or_class_expression();
}
self.add_current_node_id_to_current_scope();
}
fn leave_scope(&mut self) {
@ -1408,18 +1418,6 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
}
fn visit_function(&mut self, func: &Function<'a>, flags: Option<ScopeFlags>) {
let kind = AstKind::Function(self.alloc(func));
self.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
if func.is_strict() {
flags |= ScopeFlags::StrictMode;
}
flags
},
&func.scope_id,
);
/* cfg */
let (before_function_graph_ix, error_harness, function_graph_ix) =
control_flow!(|self, cfg| {
@ -1434,7 +1432,22 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
// We add a new basic block to the cfg before entering the node
// so that the correct cfg_ix is associated with the ast node.
let kind = AstKind::Function(self.alloc(func));
self.enter_node(kind);
self.enter_scope(
{
let mut flags = flags.unwrap_or(ScopeFlags::empty()) | ScopeFlags::Function;
if func.is_strict() {
flags |= ScopeFlags::StrictMode;
}
flags
},
&func.scope_id,
);
if let Some(id) = &func.id {
self.visit_binding_identifier(id);
}
/* cfg */
control_flow!(|self, cfg| cfg.add_edge(
@ -1444,10 +1457,16 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
));
/* cfg */
if let Some(ident) = &func.id {
self.visit_binding_identifier(ident);
if let Some(type_parameters) = &func.type_parameters {
self.visit_ts_type_parameter_declaration(type_parameters);
}
if let Some(this_param) = &func.this_param {
self.visit_ts_this_parameter(this_param);
}
self.visit_formal_parameters(&func.params);
if let Some(return_type) = &func.return_type {
self.visit_ts_type_annotation(return_type);
}
if let Some(body) = &func.body {
self.visit_function_body(body);
}
@ -1462,20 +1481,11 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
});
/* cfg */
if let Some(parameters) = &func.type_parameters {
self.visit_ts_type_parameter_declaration(parameters);
}
if let Some(annotation) = &func.return_type {
self.visit_ts_type_annotation(annotation);
}
self.leave_node(kind);
self.leave_scope();
self.leave_node(kind);
}
fn visit_arrow_function_expression(&mut self, expr: &ArrowFunctionExpression<'a>) {
let kind = AstKind::ArrowFunctionExpression(self.alloc(expr));
self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow, &expr.scope_id);
/* cfg */
let (current_node_ix, error_harness, function_graph_ix) = control_flow!(|self, cfg| {
let current_node_ix = cfg.current_node_ix;
@ -1489,7 +1499,9 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
// We add a new basic block to the cfg before entering the node
// so that the correct cfg_ix is associated with the ast node.
let kind = AstKind::ArrowFunctionExpression(self.alloc(expr));
self.enter_node(kind);
self.enter_scope(ScopeFlags::Function | ScopeFlags::Arrow, &expr.scope_id);
self.visit_formal_parameters(&expr.params);
@ -1582,14 +1594,14 @@ impl<'a> SemanticBuilder<'a> {
AstKind::StaticBlock(_) => self.label_builder.enter_function_or_static_block(),
AstKind::Function(func) => {
self.function_stack.push(self.current_node_id);
func.bind(self);
if func.is_declaration() {
func.bind(self);
}
self.label_builder.enter_function_or_static_block();
self.add_current_node_id_to_current_scope();
self.make_all_namespaces_valuelike();
}
AstKind::ArrowFunctionExpression(_) => {
self.function_stack.push(self.current_node_id);
self.add_current_node_id_to_current_scope();
self.make_all_namespaces_valuelike();
}
AstKind::Class(class) => {

View file

@ -143,8 +143,8 @@ pub(crate) enum AncestorType {
FunctionTypeParameters = 111,
FunctionThisParam = 112,
FunctionParams = 113,
FunctionBody = 114,
FunctionReturnType = 115,
FunctionReturnType = 114,
FunctionBody = 115,
FormalParametersItems = 116,
FormalParametersRest = 117,
FormalParameterDecorators = 118,
@ -531,8 +531,8 @@ pub enum Ancestor<'a> {
AncestorType::FunctionTypeParameters as u16,
FunctionThisParam(FunctionWithoutThisParam<'a>) = AncestorType::FunctionThisParam as u16,
FunctionParams(FunctionWithoutParams<'a>) = AncestorType::FunctionParams as u16,
FunctionBody(FunctionWithoutBody<'a>) = AncestorType::FunctionBody as u16,
FunctionReturnType(FunctionWithoutReturnType<'a>) = AncestorType::FunctionReturnType as u16,
FunctionBody(FunctionWithoutBody<'a>) = AncestorType::FunctionBody as u16,
FormalParametersItems(FormalParametersWithoutItems<'a>) =
AncestorType::FormalParametersItems as u16,
FormalParametersRest(FormalParametersWithoutRest<'a>) =
@ -1242,8 +1242,8 @@ impl<'a> Ancestor<'a> {
| Self::FunctionTypeParameters(_)
| Self::FunctionThisParam(_)
| Self::FunctionParams(_)
| Self::FunctionBody(_)
| Self::FunctionReturnType(_)
| Self::FunctionBody(_)
)
}
@ -5194,8 +5194,8 @@ 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_BODY: usize = offset_of!(Function, body);
pub(crate) const OFFSET_FUNCTION_SCOPE_ID: usize = offset_of!(Function, scope_id);
#[repr(transparent)]
@ -5252,14 +5252,6 @@ impl<'a> FunctionWithoutId<'a> {
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY)
as *const Option<Box<'a, FunctionBody<'a>>>)
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
@ -5268,6 +5260,14 @@ impl<'a> FunctionWithoutId<'a> {
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY)
as *const Option<Box<'a, FunctionBody<'a>>>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5330,14 +5330,6 @@ impl<'a> FunctionWithoutTypeParameters<'a> {
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY)
as *const Option<Box<'a, FunctionBody<'a>>>)
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
@ -5346,6 +5338,14 @@ impl<'a> FunctionWithoutTypeParameters<'a> {
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY)
as *const Option<Box<'a, FunctionBody<'a>>>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5408,14 +5408,6 @@ impl<'a> FunctionWithoutThisParam<'a> {
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY)
as *const Option<Box<'a, FunctionBody<'a>>>)
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
@ -5424,6 +5416,14 @@ impl<'a> FunctionWithoutThisParam<'a> {
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_BODY)
as *const Option<Box<'a, FunctionBody<'a>>>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5486,6 +5486,14 @@ impl<'a> FunctionWithoutParams<'a> {
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE)
as *const Option<Box<'a, TSTypeAnnotation<'a>>>)
}
}
#[inline]
pub fn body(&self) -> &Option<Box<'a, FunctionBody<'a>>> {
unsafe {
@ -5494,92 +5502,6 @@ impl<'a> FunctionWithoutParams<'a> {
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE)
as *const Option<Box<'a, TSTypeAnnotation<'a>>>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_SCOPE_ID) as *const Cell<Option<ScopeId>>)
}
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct FunctionWithoutBody<'a>(pub(crate) *const Function<'a>);
impl<'a> FunctionWithoutBody<'a> {
#[inline]
pub fn r#type(&self) -> &FunctionType {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_TYPE) as *const FunctionType) }
}
#[inline]
pub fn span(&self) -> &Span {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_SPAN) as *const Span) }
}
#[inline]
pub fn id(&self) -> &Option<BindingIdentifier<'a>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_ID)
as *const Option<BindingIdentifier<'a>>)
}
}
#[inline]
pub fn generator(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_GENERATOR) as *const bool) }
}
#[inline]
pub fn r#async(&self) -> &bool {
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 {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_TYPE_PARAMETERS)
as *const Option<Box<'a, TSTypeParameterDeclaration<'a>>>)
}
}
#[inline]
pub fn this_param(&self) -> &Option<TSThisParameter<'a>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_THIS_PARAM)
as *const Option<TSThisParameter<'a>>)
}
}
#[inline]
pub fn params(&self) -> &Box<'a, FormalParameters<'a>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_PARAMS)
as *const Box<'a, FormalParameters<'a>>)
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE)
as *const Option<Box<'a, TSTypeAnnotation<'a>>>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
@ -5666,6 +5588,84 @@ impl<'a> FunctionWithoutReturnType<'a> {
}
}
#[repr(transparent)]
#[derive(Debug)]
pub struct FunctionWithoutBody<'a>(pub(crate) *const Function<'a>);
impl<'a> FunctionWithoutBody<'a> {
#[inline]
pub fn r#type(&self) -> &FunctionType {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_TYPE) as *const FunctionType) }
}
#[inline]
pub fn span(&self) -> &Span {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_SPAN) as *const Span) }
}
#[inline]
pub fn id(&self) -> &Option<BindingIdentifier<'a>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_ID)
as *const Option<BindingIdentifier<'a>>)
}
}
#[inline]
pub fn generator(&self) -> &bool {
unsafe { &*((self.0 as *const u8).add(OFFSET_FUNCTION_GENERATOR) as *const bool) }
}
#[inline]
pub fn r#async(&self) -> &bool {
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 {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_TYPE_PARAMETERS)
as *const Option<Box<'a, TSTypeParameterDeclaration<'a>>>)
}
}
#[inline]
pub fn this_param(&self) -> &Option<TSThisParameter<'a>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_THIS_PARAM)
as *const Option<TSThisParameter<'a>>)
}
}
#[inline]
pub fn params(&self) -> &Box<'a, FormalParameters<'a>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_PARAMS)
as *const Box<'a, FormalParameters<'a>>)
}
}
#[inline]
pub fn return_type(&self) -> &Option<Box<'a, TSTypeAnnotation<'a>>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_RETURN_TYPE)
as *const Option<Box<'a, TSTypeAnnotation<'a>>>)
}
}
#[inline]
pub fn scope_id(&self) -> &Cell<Option<ScopeId>> {
unsafe {
&*((self.0 as *const u8).add(OFFSET_FUNCTION_SCOPE_ID) as *const Cell<Option<ScopeId>>)
}
}
}
pub(crate) const OFFSET_FORMAL_PARAMETERS_SPAN: usize = offset_of!(FormalParameters, span);
pub(crate) const OFFSET_FORMAL_PARAMETERS_KIND: usize = offset_of!(FormalParameters, kind);
pub(crate) const OFFSET_FORMAL_PARAMETERS_ITEMS: usize = offset_of!(FormalParameters, items);

View file

@ -2287,18 +2287,18 @@ pub(crate) unsafe fn walk_function<'a, Tr: Traverse<'a>>(
as *mut Box<FormalParameters>)) as *mut _,
ctx,
);
if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_BODY)
as *mut Option<Box<FunctionBody>>)
{
ctx.retag_stack(AncestorType::FunctionBody);
walk_function_body(traverser, (&mut **field) as *mut _, ctx);
}
if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_RETURN_TYPE)
as *mut Option<Box<TSTypeAnnotation>>)
{
ctx.retag_stack(AncestorType::FunctionReturnType);
walk_ts_type_annotation(traverser, (&mut **field) as *mut _, ctx);
}
if let Some(field) = &mut *((node as *mut u8).add(ancestor::OFFSET_FUNCTION_BODY)
as *mut Option<Box<FunctionBody>>)
{
ctx.retag_stack(AncestorType::FunctionBody);
walk_function_body(traverser, (&mut **field) as *mut _, ctx);
}
ctx.pop_stack();
traverser.exit_function(&mut *node, ctx);
if let Some(previous_scope_id) = previous_scope_id {

View file

@ -20872,10 +20872,10 @@ Expect to Parse: "conformance/types/typeRelationships/typeAndMemberIdentity/obje
17 │ // Type parameters and top-level local types are in same declaration space
18 │ function f<T>() {
· ┬
· ╰── It can not be redeclared here
· ╰── `T` has already been declared here
19 │ interface T { }
· ┬
· ╰── `T` has already been declared here
· ╰── It can not be redeclared here
20 │ return undefined;
╰────