-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
899 additions
and
738 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,35 +1,184 @@ | ||
use std::sync::Arc; | ||
//! References | ||
//! * </~https://github.com/oxc-project/oxc/blob/main/crates/oxc_isolated_declarations/src/diagnostics.rs> | ||
use std::{borrow::Cow, sync::Arc}; | ||
|
||
use swc_common::{FileName, Span}; | ||
|
||
use crate::fast_dts::FastDts; | ||
|
||
#[derive(Debug, Clone)] | ||
pub struct SourceRange { | ||
pub filename: Arc<FileName>, | ||
pub span: Span, | ||
} | ||
|
||
#[derive(Debug, Clone, thiserror::Error)] | ||
pub enum DtsIssue { | ||
#[error("unable to infer type from expression or declaration")] | ||
UnableToInferType { range: SourceRange }, | ||
#[error("unable to infer type, falling back to any type")] | ||
UnableToInferTypeFallbackAny { range: SourceRange }, | ||
#[error("unable to infer type from object property, skipping")] | ||
UnableToInferTypeFromProp { range: SourceRange }, | ||
#[error("unable to infer type from spread, skipping")] | ||
UnableToInferTypeFromSpread { range: SourceRange }, | ||
#[error("cannot infer type from using, skipping")] | ||
UnsupportedUsing { range: SourceRange }, | ||
#[derive(Debug, Clone)] | ||
pub struct DtsIssue { | ||
pub range: SourceRange, | ||
pub message: Cow<'static, str>, | ||
} | ||
|
||
impl DtsIssue { | ||
pub fn range(&self) -> &SourceRange { | ||
match self { | ||
DtsIssue::UnableToInferType { range } => range, | ||
DtsIssue::UnableToInferTypeFallbackAny { range } => range, | ||
DtsIssue::UnableToInferTypeFromProp { range } => range, | ||
DtsIssue::UnableToInferTypeFromSpread { range } => range, | ||
DtsIssue::UnsupportedUsing { range } => range, | ||
} | ||
impl FastDts { | ||
pub fn function_must_have_explicit_return_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9007: Function must have an explicit return type annotation with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn method_must_have_explicit_return_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9008: Method must have an explicit return type annotation with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn accessor_must_have_explicit_return_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9009: At least one accessor must have an explicit return type annotation with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn variable_must_have_explicit_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9010: Variable must have an explicit type annotation with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn parameter_must_have_explicit_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9011: Parameter must have an explicit type annotation with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn property_must_have_explicit_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9012: Property must have an explicit type annotation with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn inferred_type_of_expression(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9013: Expression type can't be inferred with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn signature_computed_property_name(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9014: Computed properties must be number or string literals, variables or dotted \ | ||
expressions with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn object_with_spread_assignments(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9015: Objects that contain spread assignments can't be inferred with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn shorthand_property(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9016: Objects that contain shorthand properties can't be inferred with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn array_inferred(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9017: Only const arrays can be inferred with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn arrays_with_spread_elements(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9018: Arrays with spread elements can't inferred with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn binding_element_export(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9019: Binding elements can't be exported directly with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn enum_member_initializers(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9020: Enum member initializers must be computable without references to external \ | ||
symbols with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn extends_clause_expression(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9021: Extends clause can't contain an expression with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn inferred_type_of_class_expression(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9022: Inference from class expressions is not supported with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn implicitly_adding_undefined_to_type(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9025: Declaration emit for this parameter requires implicitly adding undefined to \ | ||
it's type. This is not supported with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn function_with_assigning_properties(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9023: Assigning properties to functions without declaring them is not supported \ | ||
with --isolatedDeclarations. Add an explicit declaration for the properties assigned \ | ||
to this function.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn default_export_inferred(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9037: Default exports can't be inferred with --isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn computed_property_name(&mut self, span: Span) { | ||
self.mark_diagnostic( | ||
"TS9038: Computed property names on class or object literals cannot be inferred with \ | ||
--isolatedDeclarations.", | ||
span, | ||
); | ||
} | ||
|
||
pub fn type_containing_private_name(&mut self, name: &str, span: Span) { | ||
self.mark_diagnostic( | ||
format!( | ||
"TS9039: Type containing private name '{name}' can't be used with \ | ||
--isolatedDeclarations." | ||
), | ||
span, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
use swc_common::util::take::Take; | ||
use swc_ecma_ast::{Class, ClassMember, MethodKind}; | ||
|
||
use super::{any_type_ann, type_ann, valid_prop_name, FastDts}; | ||
|
||
impl FastDts { | ||
pub(crate) fn transform_class(&mut self, class: &mut Class) { | ||
// Track if the previous member was an overload signature or not. | ||
// When overloads are present the last item has the implementation | ||
// body. For declaration files the implementation always needs to | ||
// be dropped. Needs to be unique for each class because another | ||
// class could be created inside a class method. | ||
let mut prev_is_overload = false; | ||
|
||
let new_body = class | ||
.body | ||
.take() | ||
.into_iter() | ||
.filter(|member| match member { | ||
ClassMember::Constructor(class_constructor) => { | ||
let is_overload = | ||
class_constructor.body.is_none() && !class_constructor.is_optional; | ||
if !prev_is_overload || is_overload { | ||
prev_is_overload = is_overload; | ||
true | ||
} else { | ||
prev_is_overload = false; | ||
false | ||
} | ||
} | ||
ClassMember::Method(method) => { | ||
let is_overload = method.function.body.is_none() | ||
&& !(method.is_abstract || method.is_optional); | ||
if !prev_is_overload || is_overload { | ||
prev_is_overload = is_overload; | ||
true | ||
} else { | ||
prev_is_overload = false; | ||
false | ||
} | ||
} | ||
ClassMember::TsIndexSignature(_) | ||
| ClassMember::ClassProp(_) | ||
| ClassMember::PrivateProp(_) | ||
| ClassMember::Empty(_) | ||
| ClassMember::StaticBlock(_) | ||
| ClassMember::AutoAccessor(_) | ||
| ClassMember::PrivateMethod(_) => { | ||
prev_is_overload = false; | ||
true | ||
} | ||
}) | ||
.filter_map(|member| match member { | ||
ClassMember::Constructor(mut class_constructor) => { | ||
class_constructor.body = None; | ||
self.handle_ts_param_props(&mut class_constructor.params); | ||
Some(ClassMember::Constructor(class_constructor)) | ||
} | ||
ClassMember::Method(mut method) => { | ||
if let Some(new_prop_name) = valid_prop_name(&method.key) { | ||
method.key = new_prop_name; | ||
} else { | ||
return None; | ||
} | ||
|
||
method.function.body = None; | ||
if method.kind == MethodKind::Setter { | ||
method.function.return_type = None; | ||
} | ||
self.transform_fn_params(&mut method.function.params); | ||
Some(ClassMember::Method(method)) | ||
} | ||
ClassMember::ClassProp(mut prop) => { | ||
if let Some(new_prop_name) = valid_prop_name(&prop.key) { | ||
prop.key = new_prop_name; | ||
} else { | ||
return None; | ||
} | ||
|
||
if prop.type_ann.is_none() { | ||
if let Some(value) = prop.value { | ||
prop.type_ann = self | ||
.infer_type_from_expr(&value, false, false) | ||
.map(type_ann) | ||
.or_else(|| Some(any_type_ann())); | ||
} | ||
} | ||
prop.value = None; | ||
prop.definite = false; | ||
prop.declare = false; | ||
|
||
Some(ClassMember::ClassProp(prop)) | ||
} | ||
ClassMember::TsIndexSignature(index_sig) => { | ||
Some(ClassMember::TsIndexSignature(index_sig)) | ||
} | ||
|
||
// These can be removed as they are not relevant for types | ||
ClassMember::PrivateMethod(_) | ||
| ClassMember::PrivateProp(_) | ||
| ClassMember::Empty(_) | ||
| ClassMember::StaticBlock(_) | ||
| ClassMember::AutoAccessor(_) => None, | ||
}) | ||
.collect(); | ||
|
||
class.body = new_body; | ||
} | ||
} |
Oops, something went wrong.