diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 4b7d182e16edd..01f290b9ee7ab 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -406,6 +406,16 @@ pub enum TSTypeOperatorOperator { Readonly = 2, } +impl TSTypeOperatorOperator { + pub fn to_str(self) -> &'static str { + match self { + TSTypeOperatorOperator::Keyof => "keyof", + TSTypeOperatorOperator::Readonly => "readonly", + TSTypeOperatorOperator::Unique => "unique", + } + } +} + /// TypeScript Array Type /// /// Does not include tuple types, which are stored as [`TSTupleType`]. diff --git a/crates/oxc_prettier/src/format/class.rs b/crates/oxc_prettier/src/format/class.rs index d0adc895171f0..060cbb2bd1edf 100644 --- a/crates/oxc_prettier/src/format/class.rs +++ b/crates/oxc_prettier/src/format/class.rs @@ -17,6 +17,13 @@ pub(super) fn print_class<'a>(p: &mut Prettier<'a>, class: &Class<'a>) -> Doc<'a parts.push(ss!("class ")); if let Some(id) = &class.id { parts.push(id.format(p)); + } + + if let Some(params) = &class.type_parameters { + parts.push(params.format(p)); + } + + if class.id.is_some() || class.type_parameters.is_some() { parts.push(space!()); } diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index d997e62812837..dcc3e80990211 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -628,8 +628,17 @@ impl<'a> Format<'a> for TSTypeAliasDeclaration<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); + if self.declare { + parts.push(ss!("declare ")); + } + parts.push(ss!("type ")); parts.push(format!(p, self.id)); + + if let Some(params) = &self.type_parameters { + parts.push(params.format(p)); + } + parts.push(ss!(" = ")); parts.push(format!(p, self.type_annotation)); @@ -860,7 +869,45 @@ impl<'a> Format<'a> for TSLiteralType<'a> { impl<'a> Format<'a> for TSMappedType<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - line!() + let mut parts: Vec<'_, Doc<'_>> = p.vec(); + + match self.readonly { + TSMappedTypeModifierOperator::Plus => parts.push(ss!("+readonly ")), + TSMappedTypeModifierOperator::Minus => parts.push(ss!("-readonly ")), + TSMappedTypeModifierOperator::True => parts.push(ss!("readonly ")), + TSMappedTypeModifierOperator::None => (), + } + + parts.push(ss!("[")); + parts.push(self.type_parameter.format(p)); + + if let Some(name_type) = &self.name_type { + parts.push(ss!(" as ")); + parts.push(name_type.format(p)); + } + + parts.push(ss!("]")); + + match self.optional { + TSMappedTypeModifierOperator::Plus => parts.push(ss!("+?")), + TSMappedTypeModifierOperator::Minus => parts.push(ss!("-?")), + TSMappedTypeModifierOperator::True => parts.push(ss!("?")), + TSMappedTypeModifierOperator::None => (), + } + + if let Some(type_annotation) = &self.type_annotation { + parts.push(ss!(": ")); + parts.push(type_annotation.format(p)); + } + + let mut result = p.vec(); + result.push(ss!("{ ")); + + // ToDo: check ident/grouping in method/method-signature.ts + result.push(Doc::Group(Group::new(parts))); + result.push(ss!(" }")); + + Doc::Array(result) } } @@ -919,7 +966,13 @@ impl<'a> Format<'a> for TSTypeLiteral<'a> { impl<'a> Format<'a> for TSTypeOperator<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - line!() + let mut parts = p.vec(); + + parts.push(ss!(self.operator.to_str())); + parts.push(space!()); + parts.push(self.type_annotation.format(p)); + + Doc::Array(parts) } } @@ -999,6 +1052,11 @@ impl<'a> Format<'a> for TSInterfaceDeclaration<'a> { parts.push(ss!("interface ")); parts.push(format!(p, self.id)); + + if let Some(type_parameters) = &self.type_parameters { + parts.push(type_parameters.format(p)); + } + parts.push(space!()); if let Some(extends) = &self.extends { @@ -1207,19 +1265,63 @@ impl<'a> Format<'a> for TSExternalModuleReference<'a> { impl<'a> Format<'a> for TSTypeParameter<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - line!() + let mut parts = p.vec(); + + if self.r#in { + parts.push(ss!("in ")); + } + + if self.out { + parts.push(ss!("out ")); + } + + parts.push(self.name.format(p)); + + if let Some(constraint) = &self.constraint { + parts.push(space!()); + parts.push(constraint.format(p)); + } + + if let Some(default) = &self.default { + parts.push(ss!(" = ")); + parts.push(default.format(p)); + } + + Doc::Array(parts) } } impl<'a> Format<'a> for TSTypeParameterDeclaration<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { - line!() + let mut parts = p.vec(); + let mut print_comma = false; + + if self.params.len() == 0 { + return Doc::Array(parts); + } + + parts.push(ss!("<")); + + for param in &self.params { + if print_comma { + parts.push(ss!(", ")); + } else { + print_comma = true; + } + + parts.push(param.format(p)); + } + + parts.push(ss!(">")); + + Doc::Array(parts) } } impl<'a> Format<'a> for TSTypeParameterInstantiation<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); + let mut print_comma = false; if self.params.len() == 0 { return Doc::Array(parts); @@ -1228,6 +1330,12 @@ impl<'a> Format<'a> for TSTypeParameterInstantiation<'a> { parts.push(ss!("<")); for param in &self.params { + if print_comma { + parts.push(ss!(", ")); + } else { + print_comma = true; + } + parts.push(param.format(p)); } diff --git a/tasks/prettier_conformance/prettier.ts.snap.md b/tasks/prettier_conformance/prettier.ts.snap.md index c4415289ab8ab..f4db1f32a1a80 100644 --- a/tasks/prettier_conformance/prettier.ts.snap.md +++ b/tasks/prettier_conformance/prettier.ts.snap.md @@ -1,4 +1,4 @@ -ts compatibility: 95/526 (18.06%) +ts compatibility: 107/526 (20.34%) # Failed @@ -76,7 +76,6 @@ ts compatibility: 95/526 (18.06%) ### class * class/constructor.ts -* class/dunder.ts * class/empty-method-body.ts * class/extends_implements.ts * class/generics.ts @@ -158,7 +157,6 @@ ts compatibility: 95/526 (18.06%) * conformance/classes/classDeclarations/classAbstractKeyword/classAbstractConstructorAssignability.ts * conformance/classes/classDeclarations/classAbstractKeyword/classAbstractCrashedOnce.ts * conformance/classes/classDeclarations/classAbstractKeyword/classAbstractFactoryFunction.ts -* conformance/classes/classDeclarations/classAbstractKeyword/classAbstractGeneric.ts * conformance/classes/classDeclarations/classAbstractKeyword/classAbstractImportInstantiation.ts * conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInAModule.ts * conformance/classes/classDeclarations/classAbstractKeyword/classAbstractInstantiations2.ts @@ -175,8 +173,6 @@ ts compatibility: 95/526 (18.06%) * conformance/classes/constructorDeclarations/constructorParameters/constructorDefaultValuesReferencingThis.ts * conformance/classes/constructorDeclarations/constructorParameters/constructorImplementationWithDefaultValues.ts * conformance/classes/constructorDeclarations/constructorParameters/constructorImplementationWithDefaultValues2.ts -* conformance/classes/constructorDeclarations/constructorParameters/constructorOverloadsWithDefaultValues.ts -* conformance/classes/constructorDeclarations/constructorParameters/constructorOverloadsWithOptionalParameters.ts * conformance/classes/constructorDeclarations/constructorParameters/constructorParameterProperties.ts * conformance/classes/constructorDeclarations/constructorParameters/constructorParameterProperties2.ts * conformance/classes/constructorDeclarations/constructorParameters/declarationEmitReadonly.ts @@ -285,9 +281,6 @@ ts compatibility: 95/526 (18.06%) * conformance/types/typeParameters/typeParameterLists/staticMembersUsingClassTypeParameter.ts * conformance/types/typeParameters/typeParameterLists/typeParametersAvailableInNestedScope2.ts -### conformance/types/typeReference -* conformance/types/typeReference/typeReference.ts - ### conformance/types/union * conformance/types/union/unionTypeCallSignatures.ts * conformance/types/union/unionTypeCallSignatures3.ts @@ -297,9 +290,6 @@ ts compatibility: 95/526 (18.06%) * conformance/types/union/unionTypeFromArrayLiteral.ts * conformance/types/union/unionTypeIndexSignature.ts -### conformance/types/variableDeclarator -* conformance/types/variableDeclarator/variableDeclarator.ts - ### const * const/initializer-ambient-context.ts @@ -425,7 +415,6 @@ ts compatibility: 95/526 (18.06%) ### generic * generic/arrow-return-type.ts * generic/issue-6899.ts -* generic/object-method.ts * generic/ungrouped-parameters.ts ### import-export @@ -509,7 +498,6 @@ ts compatibility: 95/526 (18.06%) ### method * method/issue-10352-consistency.ts -* method/method-signature-with-wrapped-return-type.ts * method/method-signature.ts * method/semi.ts * method/type_literal_optional_method.ts @@ -615,9 +603,6 @@ ts compatibility: 95/526 (18.06%) ### static-blocks * static-blocks/nested.ts -### symbol -* symbol/symbol.ts - ### template-literal-types * template-literal-types/template-literal-types.ts @@ -689,10 +674,6 @@ ts compatibility: 95/526 (18.06%) * typeparams/long-function-arg.ts * typeparams/tagged-template-expression.ts -### typeparams/consistent -* typeparams/consistent/issue-9501.ts -* typeparams/consistent/template-literal-types.ts - ### typeparams/empty-parameters-with-arrow-function * typeparams/empty-parameters-with-arrow-function/issue-13817.ts @@ -718,9 +699,6 @@ ts compatibility: 95/526 (18.06%) ### union/single-type * union/single-type/single-type.ts -### unique-symbol -* unique-symbol/unique-symbol.ts - ### update-expression * update-expression/update-expressions.ts