mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
refactor(isolated-declarations): remove TransformDtsCtx (#3719)
This commit is contained in:
parent
0b8098a442
commit
3c597356e4
11 changed files with 214 additions and 239 deletions
|
|
@ -57,7 +57,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
property
|
||||
.type_annotation
|
||||
.as_ref()
|
||||
.map(|type_annotation| self.ctx.ast.copy(type_annotation))
|
||||
.map(|type_annotation| self.ast.copy(type_annotation))
|
||||
.or_else(|| {
|
||||
let new_type = property
|
||||
.value
|
||||
|
|
@ -65,17 +65,17 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
.and_then(|expr| self.infer_type_from_expression(expr))
|
||||
.unwrap_or_else(|| {
|
||||
// report error for has no type annotation
|
||||
self.ctx.ast.ts_unknown_keyword(property.span)
|
||||
self.ast.ts_unknown_keyword(property.span)
|
||||
});
|
||||
|
||||
Some(self.ctx.ast.ts_type_annotation(SPAN, new_type))
|
||||
Some(self.ast.ts_type_annotation(SPAN, new_type))
|
||||
})
|
||||
};
|
||||
|
||||
self.ctx.ast.class_property(
|
||||
self.ast.class_property(
|
||||
property.r#type,
|
||||
property.span,
|
||||
self.ctx.ast.copy(&property.key),
|
||||
self.ast.copy(&property.key),
|
||||
None,
|
||||
property.computed,
|
||||
property.r#static,
|
||||
|
|
@ -86,7 +86,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
property.readonly,
|
||||
type_annotations,
|
||||
self.transform_accessibility(property.accessibility),
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.new_vec(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -107,7 +107,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
};
|
||||
return self.create_class_property(
|
||||
r#type,
|
||||
self.ctx.ast.copy(&definition.key),
|
||||
self.ast.copy(&definition.key),
|
||||
definition.r#override,
|
||||
self.transform_accessibility(definition.accessibility),
|
||||
);
|
||||
|
|
@ -115,23 +115,23 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
|
||||
let type_annotation = self.infer_function_return_type(function);
|
||||
|
||||
let value = self.ctx.ast.function(
|
||||
let value = self.ast.function(
|
||||
FunctionType::TSEmptyBodyFunctionExpression,
|
||||
function.span,
|
||||
self.ctx.ast.copy(&function.id),
|
||||
self.ast.copy(&function.id),
|
||||
function.generator,
|
||||
function.r#async,
|
||||
self.ctx.ast.copy(&function.this_param),
|
||||
self.ast.copy(&function.this_param),
|
||||
params,
|
||||
None,
|
||||
self.ctx.ast.copy(&function.type_parameters),
|
||||
self.ast.copy(&function.type_parameters),
|
||||
type_annotation,
|
||||
Modifiers::empty(),
|
||||
);
|
||||
self.ctx.ast.class_method(
|
||||
self.ast.class_method(
|
||||
definition.r#type,
|
||||
definition.span,
|
||||
self.ctx.ast.copy(&definition.key),
|
||||
self.ast.copy(&definition.key),
|
||||
definition.kind,
|
||||
value,
|
||||
definition.computed,
|
||||
|
|
@ -139,7 +139,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
definition.r#override,
|
||||
definition.optional,
|
||||
self.transform_accessibility(definition.accessibility),
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.new_vec(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -150,7 +150,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
r#override: bool,
|
||||
accessibility: Option<TSAccessibility>,
|
||||
) -> ClassElement<'a> {
|
||||
self.ctx.ast.class_property(
|
||||
self.ast.class_property(
|
||||
r#type,
|
||||
SPAN,
|
||||
key,
|
||||
|
|
@ -164,7 +164,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
false,
|
||||
None,
|
||||
accessibility,
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.new_vec(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -177,9 +177,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// A parameter property may not be declared using a binding pattern.(1187)
|
||||
return None;
|
||||
};
|
||||
let key =
|
||||
self.ctx.ast.property_key_identifier(IdentifierName::new(SPAN, ident_name.clone()));
|
||||
Some(self.ctx.ast.class_property(
|
||||
let key = self.ast.property_key_identifier(IdentifierName::new(SPAN, ident_name.clone()));
|
||||
Some(self.ast.class_property(
|
||||
PropertyDefinitionType::PropertyDefinition,
|
||||
param.span,
|
||||
key,
|
||||
|
|
@ -193,7 +192,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
param.readonly,
|
||||
type_annotation,
|
||||
self.transform_accessibility(param.accessibility),
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.new_vec(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
@ -211,11 +210,11 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
_ => true,
|
||||
};
|
||||
if is_not_allowed {
|
||||
self.ctx.error(extends_clause_expression(super_class.span()));
|
||||
self.error(extends_clause_expression(super_class.span()));
|
||||
}
|
||||
}
|
||||
|
||||
let mut elements = self.ctx.ast.new_vec();
|
||||
let mut elements = self.ast.new_vec();
|
||||
let mut has_private_key = false;
|
||||
for element in &decl.body.body {
|
||||
match element {
|
||||
|
|
@ -237,7 +236,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if param.accessibility.is_some() {
|
||||
// transformed params will definitely have type annotation
|
||||
let type_annotation =
|
||||
self.ctx.ast.copy(¶ms.items[index].pattern.type_annotation);
|
||||
self.ast.copy(¶ms.items[index].pattern.type_annotation);
|
||||
if let Some(new_element) = self
|
||||
.transform_formal_parameter_to_class_property(
|
||||
param,
|
||||
|
|
@ -275,18 +274,18 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
|
||||
// FIXME: missing many fields
|
||||
let new_element = self.ctx.ast.accessor_property(
|
||||
let new_element = self.ast.accessor_property(
|
||||
property.r#type,
|
||||
property.span,
|
||||
self.ctx.ast.copy(&property.key),
|
||||
self.ast.copy(&property.key),
|
||||
None,
|
||||
property.computed,
|
||||
property.r#static,
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.new_vec(),
|
||||
);
|
||||
elements.push(new_element);
|
||||
}
|
||||
ClassElement::TSIndexSignature(_) => elements.push(self.ctx.ast.copy(element)),
|
||||
ClassElement::TSIndexSignature(_) => elements.push(self.ast.copy(element)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -295,12 +294,11 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior
|
||||
// Prevents other classes with the same public members from being used in place of the current class
|
||||
let ident = self
|
||||
.ctx
|
||||
.ast
|
||||
.property_key_private_identifier(PrivateIdentifier::new(SPAN, "private".into()));
|
||||
let r#type = PropertyDefinitionType::PropertyDefinition;
|
||||
let decorators = self.ctx.ast.new_vec();
|
||||
let new_element = self.ctx.ast.class_property(
|
||||
let decorators = self.ast.new_vec();
|
||||
let new_element = self.ast.class_property(
|
||||
r#type, SPAN, ident, None, false, false, false, false, false, false, false, None,
|
||||
None, decorators,
|
||||
);
|
||||
|
|
@ -308,23 +306,23 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
elements.insert(0, new_element);
|
||||
}
|
||||
|
||||
let body = self.ctx.ast.class_body(decl.body.span, elements);
|
||||
let body = self.ast.class_body(decl.body.span, elements);
|
||||
|
||||
let mut modifiers = self.modifiers_declare();
|
||||
if decl.modifiers.is_contains_abstract() {
|
||||
modifiers.add_modifier(Modifier { span: SPAN, kind: ModifierKind::Abstract });
|
||||
};
|
||||
|
||||
Some(self.ctx.ast.class(
|
||||
Some(self.ast.class(
|
||||
decl.r#type,
|
||||
decl.span,
|
||||
self.ctx.ast.copy(&decl.id),
|
||||
self.ctx.ast.copy(&decl.super_class),
|
||||
self.ast.copy(&decl.id),
|
||||
self.ast.copy(&decl.super_class),
|
||||
body,
|
||||
self.ctx.ast.copy(&decl.type_parameters),
|
||||
self.ctx.ast.copy(&decl.super_type_parameters),
|
||||
self.ctx.ast.copy(&decl.implements),
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.copy(&decl.type_parameters),
|
||||
self.ast.copy(&decl.super_type_parameters),
|
||||
self.ast.copy(&decl.implements),
|
||||
self.ast.new_vec(),
|
||||
modifiers,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,27 +0,0 @@
|
|||
use std::{cell::RefCell, mem, rc::Rc};
|
||||
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_ast::AstBuilder;
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
|
||||
pub type Ctx<'a> = Rc<TransformDtsCtx<'a>>;
|
||||
|
||||
pub struct TransformDtsCtx<'a> {
|
||||
errors: RefCell<Vec<OxcDiagnostic>>,
|
||||
pub ast: AstBuilder<'a>,
|
||||
}
|
||||
|
||||
impl<'a> TransformDtsCtx<'a> {
|
||||
pub fn new(allocator: &'a Allocator) -> Self {
|
||||
Self { errors: RefCell::new(vec![]), ast: AstBuilder::new(allocator) }
|
||||
}
|
||||
|
||||
pub fn take_errors(&self) -> Vec<OxcDiagnostic> {
|
||||
mem::take(&mut self.errors.borrow_mut())
|
||||
}
|
||||
|
||||
/// Add an Error
|
||||
pub fn error(&self, error: OxcDiagnostic) {
|
||||
self.errors.borrow_mut().push(error);
|
||||
}
|
||||
}
|
||||
|
|
@ -19,7 +19,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
None
|
||||
} else {
|
||||
let declarations =
|
||||
self.ctx.ast.new_vec_from_iter(decl.declarations.iter().filter_map(|declarator| {
|
||||
self.ast.new_vec_from_iter(decl.declarations.iter().filter_map(|declarator| {
|
||||
self.transform_variable_declarator(declarator, check_binding)
|
||||
}));
|
||||
Some(self.transform_variable_declaration_with_new_declarations(decl, declarations))
|
||||
|
|
@ -31,10 +31,10 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
decl: &VariableDeclaration<'a>,
|
||||
declarations: oxc_allocator::Vec<'a, VariableDeclarator<'a>>,
|
||||
) -> Box<'a, VariableDeclaration<'a>> {
|
||||
self.ctx.ast.variable_declaration(
|
||||
self.ast.variable_declaration(
|
||||
decl.span,
|
||||
decl.kind,
|
||||
self.ctx.ast.new_vec_from_iter(declarations),
|
||||
self.ast.new_vec_from_iter(declarations),
|
||||
self.modifiers_declare(),
|
||||
)
|
||||
}
|
||||
|
|
@ -45,7 +45,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
check_binding: bool,
|
||||
) -> Option<VariableDeclarator<'a>> {
|
||||
if decl.id.kind.is_destructuring_pattern() {
|
||||
self.ctx.error(OxcDiagnostic::error(
|
||||
self.error(OxcDiagnostic::error(
|
||||
"Binding elements can't be exported directly with --isolatedDeclarations.",
|
||||
));
|
||||
return None;
|
||||
|
|
@ -65,32 +65,32 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if let Some(init_expr) = &decl.init {
|
||||
// if kind is const and it doesn't need to infer type from expression
|
||||
if decl.kind.is_const() && !Self::is_need_to_infer_type_from_expression(init_expr) {
|
||||
init = Some(self.ctx.ast.copy(init_expr));
|
||||
init = Some(self.ast.copy(init_expr));
|
||||
} else {
|
||||
// otherwise, we need to infer type from expression
|
||||
binding_type = self.infer_type_from_expression(init_expr);
|
||||
}
|
||||
}
|
||||
if init.is_none() && binding_type.is_none() {
|
||||
binding_type = Some(self.ctx.ast.ts_unknown_keyword(SPAN));
|
||||
self.ctx.error(
|
||||
binding_type = Some(self.ast.ts_unknown_keyword(SPAN));
|
||||
self.error(
|
||||
OxcDiagnostic::error("Variable must have an explicit type annotation with --isolatedDeclarations.")
|
||||
.with_label(decl.id.span()),
|
||||
);
|
||||
}
|
||||
}
|
||||
let id = binding_type.map_or_else(
|
||||
|| self.ctx.ast.copy(&decl.id),
|
||||
|| self.ast.copy(&decl.id),
|
||||
|ts_type| {
|
||||
self.ctx.ast.binding_pattern(
|
||||
self.ctx.ast.copy(&decl.id.kind),
|
||||
Some(self.ctx.ast.ts_type_annotation(SPAN, ts_type)),
|
||||
self.ast.binding_pattern(
|
||||
self.ast.copy(&decl.id.kind),
|
||||
Some(self.ast.ts_type_annotation(SPAN, ts_type)),
|
||||
decl.id.optional,
|
||||
)
|
||||
},
|
||||
);
|
||||
|
||||
Some(self.ctx.ast.variable_declarator(decl.span, decl.kind, id, init, decl.definite))
|
||||
Some(self.ast.variable_declarator(decl.span, decl.kind, id, init, decl.definite))
|
||||
}
|
||||
|
||||
pub fn transform_using_declaration(
|
||||
|
|
@ -99,7 +99,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
check_binding: bool,
|
||||
) -> Box<'a, VariableDeclaration<'a>> {
|
||||
let declarations =
|
||||
self.ctx.ast.new_vec_from_iter(decl.declarations.iter().filter_map(|declarator| {
|
||||
self.ast.new_vec_from_iter(decl.declarations.iter().filter_map(|declarator| {
|
||||
self.transform_variable_declarator(declarator, check_binding)
|
||||
}));
|
||||
self.transform_using_declaration_with_new_declarations(decl, declarations)
|
||||
|
|
@ -110,7 +110,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
decl: &UsingDeclaration<'a>,
|
||||
declarations: oxc_allocator::Vec<'a, VariableDeclarator<'a>>,
|
||||
) -> Box<'a, VariableDeclaration<'a>> {
|
||||
self.ctx.ast.variable_declaration(
|
||||
self.ast.variable_declaration(
|
||||
decl.span,
|
||||
VariableDeclarationKind::Const,
|
||||
declarations,
|
||||
|
|
@ -126,7 +126,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
self.scope.enter_scope(ScopeFlags::TsModuleBlock);
|
||||
let stmts = self.transform_statements_on_demand(&block.body);
|
||||
self.scope.leave_scope();
|
||||
self.ctx.ast.ts_module_block(SPAN, stmts)
|
||||
self.ast.ts_module_block(SPAN, stmts)
|
||||
}
|
||||
|
||||
pub fn transform_ts_module_declaration(
|
||||
|
|
@ -134,19 +134,19 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
decl: &Box<'a, TSModuleDeclaration<'a>>,
|
||||
) -> Box<'a, TSModuleDeclaration<'a>> {
|
||||
if decl.modifiers.is_contains_declare() {
|
||||
return self.ctx.ast.copy(decl);
|
||||
return self.ast.copy(decl);
|
||||
}
|
||||
|
||||
let Some(body) = &decl.body else {
|
||||
return self.ctx.ast.copy(decl);
|
||||
return self.ast.copy(decl);
|
||||
};
|
||||
|
||||
match body {
|
||||
TSModuleDeclarationBody::TSModuleDeclaration(decl) => {
|
||||
let inner = self.transform_ts_module_declaration(decl);
|
||||
return self.ctx.ast.ts_module_declaration(
|
||||
return self.ast.ts_module_declaration(
|
||||
decl.span,
|
||||
self.ctx.ast.copy(&decl.id),
|
||||
self.ast.copy(&decl.id),
|
||||
Some(TSModuleDeclarationBody::TSModuleDeclaration(inner)),
|
||||
decl.kind,
|
||||
self.modifiers_declare(),
|
||||
|
|
@ -154,9 +154,9 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
TSModuleDeclarationBody::TSModuleBlock(block) => {
|
||||
let body = self.transform_ts_module_block(block);
|
||||
return self.ctx.ast.ts_module_declaration(
|
||||
return self.ast.ts_module_declaration(
|
||||
decl.span,
|
||||
self.ctx.ast.copy(&decl.id),
|
||||
self.ast.copy(&decl.id),
|
||||
Some(TSModuleDeclarationBody::TSModuleBlock(body)),
|
||||
decl.kind,
|
||||
self.modifiers_declare(),
|
||||
|
|
@ -198,7 +198,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Declaration::TSTypeAliasDeclaration(alias_decl) => {
|
||||
self.visit_ts_type_alias_declaration(alias_decl);
|
||||
if !check_binding || self.scope.has_reference(&alias_decl.id.name) {
|
||||
Some(self.ctx.ast.copy(decl))
|
||||
Some(self.ast.copy(decl))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -206,7 +206,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Declaration::TSInterfaceDeclaration(interface_decl) => {
|
||||
self.visit_ts_interface_declaration(interface_decl);
|
||||
if !check_binding || self.scope.has_reference(&interface_decl.id.name) {
|
||||
Some(self.ctx.ast.copy(decl))
|
||||
Some(self.ast.copy(decl))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -235,7 +235,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
Declaration::TSImportEqualsDeclaration(decl) => {
|
||||
if !check_binding || self.scope.has_reference(&decl.id.name) {
|
||||
Some(Declaration::TSImportEqualsDeclaration(self.ctx.ast.copy(decl)))
|
||||
Some(Declaration::TSImportEqualsDeclaration(self.ast.copy(decl)))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -257,7 +257,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
};
|
||||
|
||||
if is_not_allowed {
|
||||
self.ctx.error(signature_computed_property_name(key.span()));
|
||||
self.error(signature_computed_property_name(key.span()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
&mut self,
|
||||
decl: &TSEnumDeclaration<'a>,
|
||||
) -> Option<Declaration<'a>> {
|
||||
let mut members = self.ctx.ast.new_vec();
|
||||
let mut members = self.ast.new_vec();
|
||||
let mut prev_initializer_value = Some(ConstantValue::Number(0.0));
|
||||
let mut prev_members = FxHashMap::default();
|
||||
for member in &decl.members {
|
||||
|
|
@ -30,7 +30,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
self.computed_constant_value(initializer, &decl.id.name, &prev_members);
|
||||
|
||||
if computed_value.is_none() {
|
||||
self.ctx.error(enum_member_initializers(member.id.span()));
|
||||
self.error(enum_member_initializers(member.id.span()));
|
||||
}
|
||||
|
||||
computed_value
|
||||
|
|
@ -55,9 +55,9 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
prev_members.insert(member_name.clone(), value.clone());
|
||||
}
|
||||
|
||||
let member = self.ctx.ast.ts_enum_member(
|
||||
let member = self.ast.ts_enum_member(
|
||||
member.span,
|
||||
self.ctx.ast.copy(&member.id),
|
||||
self.ast.copy(&member.id),
|
||||
value.map(|v| match v {
|
||||
ConstantValue::Number(v) => {
|
||||
let is_negative = v < 0.0;
|
||||
|
|
@ -65,36 +65,35 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// Infinity
|
||||
let expr = if v.is_infinite() {
|
||||
let ident =
|
||||
IdentifierReference::new(SPAN, self.ctx.ast.new_atom("Infinity"));
|
||||
self.ctx.ast.identifier_reference_expression(ident)
|
||||
IdentifierReference::new(SPAN, self.ast.new_atom("Infinity"));
|
||||
self.ast.identifier_reference_expression(ident)
|
||||
} else {
|
||||
let value = if is_negative { -v } else { v };
|
||||
self.ctx.ast.literal_number_expression(NumericLiteral {
|
||||
self.ast.literal_number_expression(NumericLiteral {
|
||||
span: SPAN,
|
||||
value,
|
||||
raw: self.ctx.ast.new_str(&value.to_string()),
|
||||
raw: self.ast.new_str(&value.to_string()),
|
||||
base: NumberBase::Decimal,
|
||||
})
|
||||
};
|
||||
|
||||
if is_negative {
|
||||
self.ctx.ast.unary_expression(SPAN, UnaryOperator::UnaryNegation, expr)
|
||||
self.ast.unary_expression(SPAN, UnaryOperator::UnaryNegation, expr)
|
||||
} else {
|
||||
expr
|
||||
}
|
||||
}
|
||||
ConstantValue::String(v) => self
|
||||
.ctx
|
||||
.ast
|
||||
.literal_string_expression(self.ctx.ast.string_literal(SPAN, &v)),
|
||||
ConstantValue::String(v) => {
|
||||
self.ast.literal_string_expression(self.ast.string_literal(SPAN, &v))
|
||||
}
|
||||
}),
|
||||
);
|
||||
|
||||
members.push(member);
|
||||
}
|
||||
Some(self.ctx.ast.ts_enum_declaration(
|
||||
Some(self.ast.ts_enum_declaration(
|
||||
decl.span,
|
||||
self.ctx.ast.copy(&decl.id),
|
||||
self.ast.copy(&decl.id),
|
||||
members,
|
||||
self.modifiers_declare(),
|
||||
))
|
||||
|
|
|
|||
|
|
@ -15,16 +15,16 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
} else {
|
||||
let return_type = self.infer_function_return_type(func);
|
||||
let params = self.transform_formal_parameters(&func.params);
|
||||
Some(self.ctx.ast.function(
|
||||
Some(self.ast.function(
|
||||
func.r#type,
|
||||
func.span,
|
||||
self.ctx.ast.copy(&func.id),
|
||||
self.ast.copy(&func.id),
|
||||
func.generator,
|
||||
func.r#async,
|
||||
self.ctx.ast.copy(&func.this_param),
|
||||
self.ast.copy(&func.this_param),
|
||||
params,
|
||||
None,
|
||||
self.ctx.ast.copy(&func.type_parameters),
|
||||
self.ast.copy(&func.type_parameters),
|
||||
return_type,
|
||||
self.modifiers_declare(),
|
||||
))
|
||||
|
|
@ -39,9 +39,9 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let is_assignment_pattern = param.pattern.kind.is_assignment_pattern();
|
||||
let mut pattern =
|
||||
if let BindingPatternKind::AssignmentPattern(pattern) = ¶m.pattern.kind {
|
||||
self.ctx.ast.copy(&pattern.left)
|
||||
self.ast.copy(&pattern.left)
|
||||
} else {
|
||||
self.ctx.ast.copy(¶m.pattern)
|
||||
self.ast.copy(¶m.pattern)
|
||||
};
|
||||
|
||||
if is_assignment_pattern || pattern.type_annotation.is_none() {
|
||||
|
|
@ -51,12 +51,12 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let type_annotation = pattern
|
||||
.type_annotation
|
||||
.as_ref()
|
||||
.map(|type_annotation| self.ctx.ast.copy(&type_annotation.type_annotation))
|
||||
.map(|type_annotation| self.ast.copy(&type_annotation.type_annotation))
|
||||
.or_else(|| {
|
||||
// report error for has no type annotation
|
||||
let new_type = self
|
||||
.infer_type_from_formal_parameter(param)
|
||||
.unwrap_or_else(|| self.ctx.ast.ts_unknown_keyword(param.span));
|
||||
.unwrap_or_else(|| self.ast.ts_unknown_keyword(param.span));
|
||||
Some(new_type)
|
||||
})
|
||||
.map(|ts_type| {
|
||||
|
|
@ -64,36 +64,36 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// we need to add undefined to it's type
|
||||
if !is_next_param_optional {
|
||||
if matches!(ts_type, TSType::TSTypeReference(_)) {
|
||||
self.ctx.error(
|
||||
self.error(
|
||||
OxcDiagnostic::error("Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations.")
|
||||
.with_label(param.span),
|
||||
);
|
||||
} else if !ts_type.is_maybe_undefined() {
|
||||
// union with undefined
|
||||
return self.ctx.ast.ts_type_annotation(SPAN,
|
||||
self.ctx.ast.ts_union_type(SPAN, self.ctx.ast.new_vec_from_iter([ts_type, self.ctx.ast.ts_undefined_keyword(SPAN)]))
|
||||
return self.ast.ts_type_annotation(SPAN,
|
||||
self.ast.ts_union_type(SPAN, self.ast.new_vec_from_iter([ts_type, self.ast.ts_undefined_keyword(SPAN)]))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.ctx.ast.ts_type_annotation(SPAN, ts_type)
|
||||
self.ast.ts_type_annotation(SPAN, ts_type)
|
||||
});
|
||||
|
||||
pattern = self.ctx.ast.binding_pattern(
|
||||
self.ctx.ast.copy(&pattern.kind),
|
||||
pattern = self.ast.binding_pattern(
|
||||
self.ast.copy(&pattern.kind),
|
||||
type_annotation,
|
||||
// if it's assignment pattern, it's optional
|
||||
pattern.optional || (is_next_param_optional && is_assignment_pattern),
|
||||
);
|
||||
}
|
||||
|
||||
self.ctx.ast.formal_parameter(
|
||||
self.ast.formal_parameter(
|
||||
param.span,
|
||||
pattern,
|
||||
None,
|
||||
param.readonly,
|
||||
false,
|
||||
self.ctx.ast.new_vec(),
|
||||
self.ast.new_vec(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -102,27 +102,27 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
params: &FormalParameters<'a>,
|
||||
) -> Box<'a, FormalParameters<'a>> {
|
||||
if params.kind.is_signature() || (params.rest.is_none() && params.items.is_empty()) {
|
||||
return self.ctx.ast.alloc(self.ctx.ast.copy(params));
|
||||
return self.ast.alloc(self.ast.copy(params));
|
||||
}
|
||||
|
||||
let items =
|
||||
self.ctx.ast.new_vec_from_iter(params.items.iter().enumerate().map(|(index, item)| {
|
||||
self.ast.new_vec_from_iter(params.items.iter().enumerate().map(|(index, item)| {
|
||||
self.transform_formal_parameter(item, params.items.get(index + 1))
|
||||
}));
|
||||
|
||||
if let Some(rest) = ¶ms.rest {
|
||||
if rest.argument.type_annotation.is_none() {
|
||||
self.ctx.error(OxcDiagnostic::error(
|
||||
self.error(OxcDiagnostic::error(
|
||||
"Parameter must have an explicit type annotation with --isolatedDeclarations.",
|
||||
).with_label(rest.span));
|
||||
}
|
||||
}
|
||||
|
||||
self.ctx.ast.formal_parameters(
|
||||
self.ast.formal_parameters(
|
||||
params.span,
|
||||
FormalParameterKind::Signature,
|
||||
items,
|
||||
self.ctx.ast.copy(¶ms.rest),
|
||||
self.ast.copy(¶ms.rest),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,23 +14,23 @@ use crate::{
|
|||
impl<'a> IsolatedDeclarations<'a> {
|
||||
pub fn infer_type_from_expression(&self, expr: &Expression<'a>) -> Option<TSType<'a>> {
|
||||
match expr {
|
||||
Expression::BooleanLiteral(_) => Some(self.ctx.ast.ts_boolean_keyword(SPAN)),
|
||||
Expression::NullLiteral(_) => Some(self.ctx.ast.ts_null_keyword(SPAN)),
|
||||
Expression::BooleanLiteral(_) => Some(self.ast.ts_boolean_keyword(SPAN)),
|
||||
Expression::NullLiteral(_) => Some(self.ast.ts_null_keyword(SPAN)),
|
||||
Expression::NumericLiteral(_) | Expression::BigintLiteral(_) => {
|
||||
Some(self.ctx.ast.ts_number_keyword(SPAN))
|
||||
Some(self.ast.ts_number_keyword(SPAN))
|
||||
}
|
||||
Expression::StringLiteral(_) | Expression::TemplateLiteral(_) => {
|
||||
Some(self.ctx.ast.ts_string_keyword(SPAN))
|
||||
Some(self.ast.ts_string_keyword(SPAN))
|
||||
}
|
||||
Expression::Identifier(ident) => match ident.name.as_str() {
|
||||
"undefined" => Some(self.ctx.ast.ts_undefined_keyword(SPAN)),
|
||||
"undefined" => Some(self.ast.ts_undefined_keyword(SPAN)),
|
||||
_ => None,
|
||||
},
|
||||
Expression::FunctionExpression(func) => {
|
||||
self.transform_function_to_ts_type(func).map(|x| self.ctx.ast.copy(&x))
|
||||
self.transform_function_to_ts_type(func).map(|x| self.ast.copy(&x))
|
||||
}
|
||||
Expression::ArrowFunctionExpression(func) => {
|
||||
self.transform_arrow_function_to_ts_type(func).map(|x| self.ctx.ast.copy(&x))
|
||||
self.transform_arrow_function_to_ts_type(func).map(|x| self.ast.copy(&x))
|
||||
}
|
||||
Expression::ObjectExpression(expr) => {
|
||||
Some(self.transform_object_expression_to_ts_type(expr, false))
|
||||
|
|
@ -39,11 +39,11 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if expr.type_annotation.is_const_type_reference() {
|
||||
Some(self.transform_expression_to_ts_type(&expr.expression))
|
||||
} else {
|
||||
Some(self.ctx.ast.copy(&expr.type_annotation))
|
||||
Some(self.ast.copy(&expr.type_annotation))
|
||||
}
|
||||
}
|
||||
Expression::ClassExpression(expr) => {
|
||||
self.ctx.error(
|
||||
self.error(
|
||||
OxcDiagnostic::error(
|
||||
"
|
||||
Inference from class expressions is not supported with --isolatedDeclarations.
|
||||
|
|
@ -51,7 +51,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
)
|
||||
.with_label(expr.span),
|
||||
);
|
||||
Some(self.ctx.ast.ts_unknown_keyword(SPAN))
|
||||
Some(self.ast.ts_unknown_keyword(SPAN))
|
||||
}
|
||||
Expression::TSNonNullExpression(expr) => {
|
||||
self.infer_type_from_expression(&expr.expression)
|
||||
|
|
@ -63,7 +63,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
unreachable!();
|
||||
// infer_type_from_expression(ctx, &expr.expression)
|
||||
}
|
||||
Expression::TSTypeAssertion(expr) => Some(self.ctx.ast.copy(&expr.type_annotation)),
|
||||
Expression::TSTypeAssertion(expr) => Some(self.ast.copy(&expr.type_annotation)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -73,15 +73,15 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
param: &FormalParameter<'a>,
|
||||
) -> Option<TSType<'a>> {
|
||||
if param.pattern.type_annotation.is_some() {
|
||||
param.pattern.type_annotation.as_ref().map(|x| self.ctx.ast.copy(&x.type_annotation));
|
||||
param.pattern.type_annotation.as_ref().map(|x| self.ast.copy(&x.type_annotation));
|
||||
}
|
||||
if let BindingPatternKind::AssignmentPattern(pattern) = ¶m.pattern.kind {
|
||||
if let Some(annotation) = pattern.left.type_annotation.as_ref() {
|
||||
Some(self.ctx.ast.copy(&annotation.type_annotation))
|
||||
Some(self.ast.copy(&annotation.type_annotation))
|
||||
} else {
|
||||
if let Expression::TSAsExpression(expr) = &pattern.right {
|
||||
if !expr.type_annotation.is_keyword_or_literal() {
|
||||
self.ctx.error(
|
||||
self.error(
|
||||
OxcDiagnostic::error("Parameter must have an explicit type annotation with --isolatedDeclarations.")
|
||||
.with_label(expr.type_annotation.span())
|
||||
);
|
||||
|
|
@ -100,11 +100,11 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
function: &Function<'a>,
|
||||
) -> Option<Box<'a, TSTypeAnnotation<'a>>> {
|
||||
if function.return_type.is_some() {
|
||||
return self.ctx.ast.copy(&function.return_type);
|
||||
return self.ast.copy(&function.return_type);
|
||||
}
|
||||
|
||||
if function.r#async || function.generator {
|
||||
self.ctx.error(function_must_have_explicit_return_type(function));
|
||||
self.error(function_must_have_explicit_return_type(function));
|
||||
}
|
||||
|
||||
let return_type = FunctionReturnType::infer(
|
||||
|
|
@ -114,12 +114,12 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
.as_ref()
|
||||
.unwrap_or_else(|| unreachable!("Only declare function can have no body")),
|
||||
)
|
||||
.map(|type_annotation| self.ctx.ast.ts_type_annotation(SPAN, type_annotation));
|
||||
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation));
|
||||
|
||||
if return_type.is_none() {
|
||||
self.ctx.error(function_must_have_explicit_return_type(function));
|
||||
self.error(function_must_have_explicit_return_type(function));
|
||||
|
||||
Some(self.ctx.ast.ts_type_annotation(SPAN, self.ctx.ast.ts_unknown_keyword(SPAN)))
|
||||
Some(self.ast.ts_type_annotation(SPAN, self.ast.ts_unknown_keyword(SPAN)))
|
||||
} else {
|
||||
return_type
|
||||
}
|
||||
|
|
@ -130,18 +130,18 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
function: &ArrowFunctionExpression<'a>,
|
||||
) -> Option<Box<'a, TSTypeAnnotation<'a>>> {
|
||||
if function.return_type.is_some() {
|
||||
return self.ctx.ast.copy(&function.return_type);
|
||||
return self.ast.copy(&function.return_type);
|
||||
}
|
||||
|
||||
if function.expression {
|
||||
if let Some(Statement::ExpressionStatement(stmt)) = function.body.statements.first() {
|
||||
return self
|
||||
.infer_type_from_expression(&stmt.expression)
|
||||
.map(|type_annotation| self.ctx.ast.ts_type_annotation(SPAN, type_annotation));
|
||||
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation));
|
||||
}
|
||||
}
|
||||
FunctionReturnType::infer(self, &function.body)
|
||||
.map(|type_annotation| self.ctx.ast.ts_type_annotation(SPAN, type_annotation))
|
||||
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation))
|
||||
}
|
||||
|
||||
pub fn is_need_to_infer_type_from_expression(expr: &Expression) -> bool {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
//! * <https://github.com/microsoft/TypeScript/blob/main/src/compiler/transformers/declarations.ts>
|
||||
|
||||
mod class;
|
||||
mod context;
|
||||
mod declaration;
|
||||
mod diagnostics;
|
||||
mod r#enum;
|
||||
|
|
@ -17,15 +16,15 @@ mod return_type;
|
|||
mod scope;
|
||||
mod types;
|
||||
|
||||
use std::{collections::VecDeque, rc::Rc};
|
||||
use std::{cell::RefCell, collections::VecDeque, mem};
|
||||
|
||||
use context::{Ctx, TransformDtsCtx};
|
||||
use oxc_allocator::Allocator;
|
||||
#[allow(clippy::wildcard_imports)]
|
||||
use oxc_ast::{ast::*, Visit};
|
||||
use oxc_ast::{ast::*, AstBuilder, Visit};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_span::{SourceType, SPAN};
|
||||
use scope::ScopeTree;
|
||||
|
||||
use crate::scope::ScopeTree;
|
||||
|
||||
pub struct IsolatedDeclarationsReturn<'a> {
|
||||
pub program: Program<'a>,
|
||||
|
|
@ -33,14 +32,19 @@ pub struct IsolatedDeclarationsReturn<'a> {
|
|||
}
|
||||
|
||||
pub struct IsolatedDeclarations<'a> {
|
||||
ctx: Ctx<'a>,
|
||||
ast: AstBuilder<'a>,
|
||||
// state
|
||||
scope: ScopeTree<'a>,
|
||||
errors: RefCell<Vec<OxcDiagnostic>>,
|
||||
}
|
||||
|
||||
impl<'a> IsolatedDeclarations<'a> {
|
||||
pub fn new(allocator: &'a Allocator) -> Self {
|
||||
let ctx = Rc::new(TransformDtsCtx::new(allocator));
|
||||
Self { ctx, scope: ScopeTree::new(allocator) }
|
||||
Self {
|
||||
ast: AstBuilder::new(allocator),
|
||||
scope: ScopeTree::new(allocator),
|
||||
errors: RefCell::new(vec![]),
|
||||
}
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
|
|
@ -48,10 +52,19 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
/// Returns `Vec<Error>` if any errors were collected during the transformation.
|
||||
pub fn build(mut self, program: &Program<'a>) -> IsolatedDeclarationsReturn<'a> {
|
||||
let source_type = SourceType::default().with_module(true).with_typescript_definition(true);
|
||||
let directives = self.ctx.ast.new_vec();
|
||||
let directives = self.ast.new_vec();
|
||||
let stmts = self.transform_program(program);
|
||||
let program = self.ctx.ast.program(SPAN, source_type, directives, None, stmts);
|
||||
IsolatedDeclarationsReturn { program, errors: self.ctx.take_errors() }
|
||||
let program = self.ast.program(SPAN, source_type, directives, None, stmts);
|
||||
IsolatedDeclarationsReturn { program, errors: self.take_errors() }
|
||||
}
|
||||
|
||||
fn take_errors(&self) -> Vec<OxcDiagnostic> {
|
||||
mem::take(&mut self.errors.borrow_mut())
|
||||
}
|
||||
|
||||
/// Add an Error
|
||||
fn error(&self, error: OxcDiagnostic) {
|
||||
self.errors.borrow_mut().push(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,7 +96,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Modifiers::empty()
|
||||
} else {
|
||||
Modifiers::new(
|
||||
self.ctx.ast.new_vec_single(Modifier { span: SPAN, kind: ModifierKind::Declare }),
|
||||
self.ast.new_vec_single(Modifier { span: SPAN, kind: ModifierKind::Declare }),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -92,13 +105,13 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
&mut self,
|
||||
program: &Program<'a>,
|
||||
) -> oxc_allocator::Vec<'a, Statement<'a>> {
|
||||
let mut new_ast_stmts = self.ctx.ast.new_vec::<Statement<'a>>();
|
||||
let mut new_ast_stmts = self.ast.new_vec::<Statement<'a>>();
|
||||
for stmt in &program.body {
|
||||
if let Some(decl) = stmt.as_declaration() {
|
||||
if let Some(decl) = self.transform_declaration(decl, false) {
|
||||
new_ast_stmts.push(Statement::from(decl));
|
||||
} else {
|
||||
new_ast_stmts.push(Statement::from(self.ctx.ast.copy(decl)));
|
||||
new_ast_stmts.push(Statement::from(self.ast.copy(decl)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -122,19 +135,19 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
match stmt.to_declaration() {
|
||||
Declaration::VariableDeclaration(decl) => {
|
||||
variables_declarations.push_back(
|
||||
self.ctx.ast.copy(&decl.declarations).into_iter().collect::<Vec<_>>(),
|
||||
self.ast.copy(&decl.declarations).into_iter().collect::<Vec<_>>(),
|
||||
);
|
||||
variable_transformed_indexes.push_back(Vec::default());
|
||||
}
|
||||
Declaration::UsingDeclaration(decl) => {
|
||||
variables_declarations.push_back(
|
||||
self.ctx.ast.copy(&decl.declarations).into_iter().collect::<Vec<_>>(),
|
||||
self.ast.copy(&decl.declarations).into_iter().collect::<Vec<_>>(),
|
||||
);
|
||||
variable_transformed_indexes.push_back(Vec::default());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
new_stmts.push(self.ctx.ast.copy(stmt));
|
||||
new_stmts.push(self.ast.copy(stmt));
|
||||
}
|
||||
match_module_declaration!(Statement) => {
|
||||
transformed_indexes.push(new_stmts.len());
|
||||
|
|
@ -145,15 +158,14 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
{
|
||||
if let Some(var_decl) = var_decl {
|
||||
self.scope.visit_variable_declaration(&var_decl);
|
||||
new_stmts.push(Statement::VariableDeclaration(
|
||||
self.ctx.ast.alloc(var_decl),
|
||||
));
|
||||
new_stmts
|
||||
.push(Statement::VariableDeclaration(self.ast.alloc(var_decl)));
|
||||
transformed_indexes.push(new_stmts.len());
|
||||
}
|
||||
|
||||
self.scope.visit_export_default_declaration(&new_decl);
|
||||
new_stmts.push(Statement::ExportDefaultDeclaration(
|
||||
self.ctx.ast.alloc(new_decl),
|
||||
self.ast.alloc(new_decl),
|
||||
));
|
||||
return;
|
||||
}
|
||||
|
|
@ -166,9 +178,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
new_decl.declaration.as_ref().unwrap_or_else(|| unreachable!()),
|
||||
);
|
||||
|
||||
new_stmts.push(Statement::ExportNamedDeclaration(
|
||||
self.ctx.ast.alloc(new_decl),
|
||||
));
|
||||
new_stmts
|
||||
.push(Statement::ExportNamedDeclaration(self.ast.alloc(new_decl)));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +188,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
module_declaration => self.scope.visit_module_declaration(module_declaration),
|
||||
}
|
||||
|
||||
new_stmts.push(self.ctx.ast.copy(stmt));
|
||||
new_stmts.push(self.ast.copy(stmt));
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
|
|
@ -231,7 +242,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
|
||||
// 6. Transform variable/using declarations, import statements, remove unused imports
|
||||
// 7. Return transformed statements
|
||||
let mut new_ast_stmts = self.ctx.ast.new_vec_with_capacity(transformed_indexes.len());
|
||||
let mut new_ast_stmts = self.ast.new_vec_with_capacity(transformed_indexes.len());
|
||||
for (index, stmt) in new_stmts.into_iter().enumerate() {
|
||||
match stmt {
|
||||
_ if transformed_indexes.contains(&index) => {
|
||||
|
|
@ -247,7 +258,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let variables_declaration = self
|
||||
.transform_variable_declaration_with_new_declarations(
|
||||
&decl,
|
||||
self.ctx.ast.new_vec_from_iter(
|
||||
self.ast.new_vec_from_iter(
|
||||
declarations
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
|
|
@ -268,7 +279,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let variable_declaration = self
|
||||
.transform_using_declaration_with_new_declarations(
|
||||
&decl,
|
||||
self.ctx.ast.new_vec_from_iter(
|
||||
self.ast.new_vec_from_iter(
|
||||
declarations
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
Some(ExportNamedDeclaration {
|
||||
span: decl.span(),
|
||||
declaration: Some(decl),
|
||||
specifiers: self.ctx.ast.new_vec(),
|
||||
specifiers: self.ast.new_vec(),
|
||||
source: None,
|
||||
export_kind: ImportOrExportKind::Value,
|
||||
with_clause: None,
|
||||
|
|
@ -37,7 +37,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
.map(|d| (None, ExportDefaultDeclarationKind::ClassDeclaration(d))),
|
||||
ExportDefaultDeclarationKind::TSInterfaceDeclaration(interface_decl) => {
|
||||
self.visit_ts_interface_declaration(interface_decl);
|
||||
Some((None, self.ctx.ast.copy(&decl.declaration)))
|
||||
Some((None, self.ast.copy(&decl.declaration)))
|
||||
}
|
||||
expr @ match_expression!(ExportDefaultDeclarationKind) => {
|
||||
let expr = expr.to_expression();
|
||||
|
|
@ -46,19 +46,18 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
} else {
|
||||
// declare const _default: Type
|
||||
let kind = VariableDeclarationKind::Const;
|
||||
let name = self.ctx.ast.new_atom("_default");
|
||||
let name = self.ast.new_atom("_default");
|
||||
let id = self
|
||||
.ctx
|
||||
.ast
|
||||
.binding_pattern_identifier(BindingIdentifier::new(SPAN, name.clone()));
|
||||
let type_annotation = self
|
||||
.infer_type_from_expression(expr)
|
||||
.map(|ts_type| self.ctx.ast.ts_type_annotation(SPAN, ts_type));
|
||||
.map(|ts_type| self.ast.ts_type_annotation(SPAN, ts_type));
|
||||
|
||||
let id = BindingPattern { kind: id, type_annotation, optional: false };
|
||||
let declarations = self.ctx.ast.new_vec_single(
|
||||
self.ctx.ast.variable_declarator(SPAN, kind, id, None, true),
|
||||
);
|
||||
let declarations = self
|
||||
.ast
|
||||
.new_vec_single(self.ast.variable_declarator(SPAN, kind, id, None, true));
|
||||
|
||||
Some((
|
||||
Some(VariableDeclaration {
|
||||
|
|
@ -68,8 +67,8 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
modifiers: self.modifiers_declare(),
|
||||
}),
|
||||
ExportDefaultDeclarationKind::from(
|
||||
self.ctx.ast.identifier_reference_expression(
|
||||
self.ctx.ast.identifier_reference(SPAN, &name),
|
||||
self.ast.identifier_reference_expression(
|
||||
self.ast.identifier_reference(SPAN, &name),
|
||||
),
|
||||
),
|
||||
))
|
||||
|
|
@ -80,7 +79,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
declaration.map(|(var_decl, declaration)| {
|
||||
let exported = ModuleExportName::Identifier(IdentifierName::new(
|
||||
SPAN,
|
||||
self.ctx.ast.new_atom("default"),
|
||||
self.ast.new_atom("default"),
|
||||
));
|
||||
(var_decl, ExportDefaultDeclaration { span: decl.span, declaration, exported })
|
||||
})
|
||||
|
|
@ -92,7 +91,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
) -> Option<Box<'a, ImportDeclaration<'a>>> {
|
||||
let specifiers = decl.specifiers.as_ref()?;
|
||||
|
||||
let mut specifiers = self.ctx.ast.copy(specifiers);
|
||||
let mut specifiers = self.ast.copy(specifiers);
|
||||
specifiers.retain(|specifier| match specifier {
|
||||
ImportDeclarationSpecifier::ImportSpecifier(specifier) => {
|
||||
self.scope.has_reference(&specifier.local.name)
|
||||
|
|
@ -101,18 +100,18 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
self.scope.has_reference(&specifier.local.name)
|
||||
}
|
||||
ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => {
|
||||
self.scope.has_reference(&self.ctx.ast.new_atom(&specifier.name()))
|
||||
self.scope.has_reference(&self.ast.new_atom(&specifier.name()))
|
||||
}
|
||||
});
|
||||
if specifiers.is_empty() {
|
||||
// We don't need to print this import statement
|
||||
None
|
||||
} else {
|
||||
Some(self.ctx.ast.import_declaration(
|
||||
Some(self.ast.import_declaration(
|
||||
decl.span,
|
||||
Some(specifiers),
|
||||
self.ctx.ast.copy(&decl.source),
|
||||
self.ctx.ast.copy(&decl.with_clause),
|
||||
self.ast.copy(&decl.source),
|
||||
self.ast.copy(&decl.with_clause),
|
||||
decl.import_kind,
|
||||
))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use oxc_ast::{
|
||||
ast::{
|
||||
BindingIdentifier, Expression, Function, FunctionBody, ReturnStatement, TSType,
|
||||
TSTypeAliasDeclaration, TSTypeName, TSTypeQueryExprName,
|
||||
},
|
||||
Visit,
|
||||
AstBuilder, Visit,
|
||||
};
|
||||
use oxc_span::{Atom, GetSpan};
|
||||
use oxc_syntax::scope::ScopeFlags;
|
||||
|
||||
use crate::{context::Ctx, diagnostics::type_containing_private_name, IsolatedDeclarations};
|
||||
use crate::{diagnostics::type_containing_private_name, IsolatedDeclarations};
|
||||
|
||||
/// Infer return type from return statement. Does not support multiple return statements.
|
||||
pub struct FunctionReturnType<'a> {
|
||||
ctx: Ctx<'a>,
|
||||
ast: AstBuilder<'a>,
|
||||
return_expression: Option<Expression<'a>>,
|
||||
value_bindings: Vec<Atom<'a>>,
|
||||
type_bindings: Vec<Atom<'a>>,
|
||||
|
|
@ -28,7 +26,7 @@ impl<'a> FunctionReturnType<'a> {
|
|||
body: &FunctionBody<'a>,
|
||||
) -> Option<TSType<'a>> {
|
||||
let mut visitor = FunctionReturnType {
|
||||
ctx: Rc::clone(&transformer.ctx),
|
||||
ast: transformer.ast,
|
||||
return_expression: None,
|
||||
return_statement_count: 0,
|
||||
scope_depth: 0,
|
||||
|
|
@ -69,7 +67,7 @@ impl<'a> FunctionReturnType<'a> {
|
|||
};
|
||||
|
||||
if is_defined_in_current_scope {
|
||||
transformer.ctx.error(type_containing_private_name(
|
||||
transformer.error(type_containing_private_name(
|
||||
&reference_name,
|
||||
expr_type
|
||||
.get_identifier_reference()
|
||||
|
|
@ -108,6 +106,6 @@ impl<'a> Visit<'a> for FunctionReturnType<'a> {
|
|||
if self.return_statement_count > 1 {
|
||||
return;
|
||||
}
|
||||
self.return_expression = self.ctx.ast.copy(&stmt.argument);
|
||||
self.return_expression = self.ast.copy(&stmt.argument);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use rustc_hash::FxHashSet;
|
||||
|
||||
use oxc_allocator::{Allocator, Vec};
|
||||
#[allow(clippy::wildcard_imports)]
|
||||
use oxc_ast::ast::*;
|
||||
|
|
@ -6,7 +8,6 @@ use oxc_ast::AstBuilder;
|
|||
use oxc_ast::{visit::walk::*, Visit};
|
||||
use oxc_span::Atom;
|
||||
use oxc_syntax::scope::ScopeFlags;
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
pub struct ScopeTree<'a> {
|
||||
type_bindings: Vec<'a, FxHashSet<Atom<'a>>>,
|
||||
|
|
|
|||
|
|
@ -14,12 +14,12 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let params = self.transform_formal_parameters(&func.params);
|
||||
|
||||
return_type.map(|return_type| {
|
||||
self.ctx.ast.ts_function_type(
|
||||
self.ast.ts_function_type(
|
||||
func.span,
|
||||
self.ctx.ast.copy(&func.this_param),
|
||||
self.ast.copy(&func.this_param),
|
||||
params,
|
||||
return_type,
|
||||
self.ctx.ast.copy(&func.type_parameters),
|
||||
self.ast.copy(&func.type_parameters),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
@ -32,12 +32,12 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
let params = self.transform_formal_parameters(&func.params);
|
||||
|
||||
return_type.map(|return_type| {
|
||||
self.ctx.ast.ts_function_type(
|
||||
self.ast.ts_function_type(
|
||||
func.span,
|
||||
None,
|
||||
params,
|
||||
return_type,
|
||||
self.ctx.ast.copy(&func.type_parameters),
|
||||
self.ast.copy(&func.type_parameters),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
@ -60,7 +60,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
is_const: bool,
|
||||
) -> TSType<'a> {
|
||||
let members =
|
||||
self.ctx.ast.new_vec_from_iter(expr.properties.iter().filter_map(|property| match property {
|
||||
self.ast.new_vec_from_iter(expr.properties.iter().filter_map(|property| match property {
|
||||
ObjectPropertyKind::ObjectProperty(object) => {
|
||||
if self.report_property_key(&object.key, object.computed) {
|
||||
return None;
|
||||
|
|
@ -70,41 +70,41 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
if !is_const && object.method {
|
||||
let return_type = self.infer_function_return_type(function);
|
||||
let params = self.transform_formal_parameters(&function.params);
|
||||
return Some(self.ctx.ast.ts_method_signature(
|
||||
return Some(self.ast.ts_method_signature(
|
||||
object.span,
|
||||
self.ctx.ast.copy(&object.key),
|
||||
self.ast.copy(&object.key),
|
||||
object.computed,
|
||||
false,
|
||||
TSMethodSignatureKind::Method,
|
||||
self.ctx.ast.copy(&function.this_param),
|
||||
self.ast.copy(&function.this_param),
|
||||
params,
|
||||
return_type,
|
||||
self.ctx.ast.copy(&function.type_parameters),
|
||||
self.ast.copy(&function.type_parameters),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let type_annotation = self.infer_type_from_expression(&object.value);
|
||||
|
||||
let property_signature = self.ctx.ast.ts_property_signature(
|
||||
let property_signature = self.ast.ts_property_signature(
|
||||
object.span,
|
||||
false,
|
||||
false,
|
||||
is_const,
|
||||
self.ctx.ast.copy(&object.key),
|
||||
self.ast.copy(&object.key),
|
||||
type_annotation
|
||||
.map(|type_annotation| self.ctx.ast.ts_type_annotation(SPAN, type_annotation)),
|
||||
.map(|type_annotation| self.ast.ts_type_annotation(SPAN, type_annotation)),
|
||||
);
|
||||
Some(property_signature)
|
||||
},
|
||||
ObjectPropertyKind::SpreadProperty(spread) => {
|
||||
self.ctx.error(OxcDiagnostic::error(
|
||||
self.error(OxcDiagnostic::error(
|
||||
"Objects that contain spread assignments can't be inferred with --isolatedDeclarations.",
|
||||
).with_label(spread.span));
|
||||
None
|
||||
}
|
||||
}));
|
||||
self.ctx.ast.ts_type_literal(SPAN, members)
|
||||
self.ast.ts_type_literal(SPAN, members)
|
||||
}
|
||||
|
||||
pub fn transform_array_expression_to_ts_type(
|
||||
|
|
@ -113,16 +113,16 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
is_const: bool,
|
||||
) -> TSType<'a> {
|
||||
let element_types =
|
||||
self.ctx.ast.new_vec_from_iter(expr.elements.iter().filter_map(|element| {
|
||||
self.ast.new_vec_from_iter(expr.elements.iter().filter_map(|element| {
|
||||
match element {
|
||||
ArrayExpressionElement::SpreadElement(spread) => {
|
||||
self.ctx.error(OxcDiagnostic::error(
|
||||
self.error(OxcDiagnostic::error(
|
||||
"Arrays with spread elements can't inferred with --isolatedDeclarations.",
|
||||
).with_label(spread.span));
|
||||
None
|
||||
},
|
||||
ArrayExpressionElement::Elision(elision) => {
|
||||
Some(TSTupleElement::from(self.ctx.ast.ts_undefined_keyword(elision.span)))
|
||||
Some(TSTupleElement::from(self.ast.ts_undefined_keyword(elision.span)))
|
||||
},
|
||||
_ => {
|
||||
Some(TSTupleElement::from(self.transform_expression_to_ts_type(element.to_expression())))
|
||||
|
|
@ -130,9 +130,9 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
}
|
||||
}));
|
||||
|
||||
let ts_type = self.ctx.ast.ts_tuple_type(SPAN, element_types);
|
||||
let ts_type = self.ast.ts_tuple_type(SPAN, element_types);
|
||||
if is_const {
|
||||
self.ctx.ast.ts_type_operator_type(SPAN, TSTypeOperatorOperator::Readonly, ts_type)
|
||||
self.ast.ts_type_operator_type(SPAN, TSTypeOperatorOperator::Readonly, ts_type)
|
||||
} else {
|
||||
ts_type
|
||||
}
|
||||
|
|
@ -141,28 +141,24 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
|
||||
pub fn transform_expression_to_ts_type(&self, expr: &Expression<'a>) -> TSType<'a> {
|
||||
match expr {
|
||||
Expression::BooleanLiteral(lit) => self
|
||||
.ctx
|
||||
.ast
|
||||
.ts_literal_type(SPAN, TSLiteral::BooleanLiteral(self.ctx.ast.copy(lit))),
|
||||
Expression::NumericLiteral(lit) => self
|
||||
.ctx
|
||||
.ast
|
||||
.ts_literal_type(SPAN, TSLiteral::NumericLiteral(self.ctx.ast.copy(lit))),
|
||||
Expression::BooleanLiteral(lit) => {
|
||||
self.ast.ts_literal_type(SPAN, TSLiteral::BooleanLiteral(self.ast.copy(lit)))
|
||||
}
|
||||
Expression::NumericLiteral(lit) => {
|
||||
self.ast.ts_literal_type(SPAN, TSLiteral::NumericLiteral(self.ast.copy(lit)))
|
||||
}
|
||||
Expression::BigintLiteral(lit) => {
|
||||
self.ctx.ast.ts_literal_type(SPAN, TSLiteral::BigintLiteral(self.ctx.ast.copy(lit)))
|
||||
self.ast.ts_literal_type(SPAN, TSLiteral::BigintLiteral(self.ast.copy(lit)))
|
||||
}
|
||||
Expression::StringLiteral(lit) => {
|
||||
self.ctx.ast.ts_literal_type(SPAN, TSLiteral::StringLiteral(self.ctx.ast.copy(lit)))
|
||||
self.ast.ts_literal_type(SPAN, TSLiteral::StringLiteral(self.ast.copy(lit)))
|
||||
}
|
||||
Expression::TemplateLiteral(lit) => {
|
||||
self.ast.ts_literal_type(SPAN, TSLiteral::TemplateLiteral(self.ast.copy(lit)))
|
||||
}
|
||||
Expression::UnaryExpression(expr) => {
|
||||
self.ast.ts_literal_type(SPAN, TSLiteral::UnaryExpression(self.ast.copy(expr)))
|
||||
}
|
||||
Expression::TemplateLiteral(lit) => self
|
||||
.ctx
|
||||
.ast
|
||||
.ts_literal_type(SPAN, TSLiteral::TemplateLiteral(self.ctx.ast.copy(lit))),
|
||||
Expression::UnaryExpression(expr) => self
|
||||
.ctx
|
||||
.ast
|
||||
.ts_literal_type(SPAN, TSLiteral::UnaryExpression(self.ctx.ast.copy(expr))),
|
||||
Expression::ArrayExpression(expr) => {
|
||||
self.transform_array_expression_to_ts_type(expr, true)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue