Skip to content

Commit 72144e9

Browse files
committed
fix(formatter): missing trailing semicolon in TSSignature (#13823)
* Fixes: #13837
1 parent f643093 commit 72144e9

File tree

4 files changed

+81
-107
lines changed

4 files changed

+81
-107
lines changed

crates/oxc_formatter/src/write/mod.rs

Lines changed: 47 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1547,8 +1547,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSInterfaceDeclaration<'a>> {
15471547

15481548
impl<'a> FormatWrite<'a> for AstNode<'a, TSInterfaceBody<'a>> {
15491549
fn write(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
1550-
let source_text = f.context().source_text();
1551-
f.join_nodes_with_soft_line().entries(self.body()).finish()
1550+
self.body().fmt(f)
15521551
}
15531552
}
15541553

@@ -1572,9 +1571,50 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSPropertySignature<'a>> {
15721571
}
15731572
}
15741573

1574+
struct FormatTSSignature<'a, 'b> {
1575+
last: bool,
1576+
signature: &'b AstNode<'a, TSSignature<'a>>,
1577+
}
1578+
1579+
impl GetSpan for FormatTSSignature<'_, '_> {
1580+
fn span(&self) -> Span {
1581+
self.signature.span()
1582+
}
1583+
}
1584+
1585+
impl<'a> Format<'a> for FormatTSSignature<'a, '_> {
1586+
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
1587+
self.signature.fmt(f)?;
1588+
1589+
match f.options().semicolons {
1590+
Semicolons::Always => {
1591+
if self.last {
1592+
write!(f, [if_group_breaks(&text(";"))])?;
1593+
} else {
1594+
text(";").fmt(f)?;
1595+
}
1596+
}
1597+
Semicolons::AsNeeded => {
1598+
if !self.last {
1599+
write!(f, [if_group_fits_on_line(&text(";"))])?;
1600+
}
1601+
}
1602+
}
1603+
1604+
Ok(())
1605+
}
1606+
}
1607+
15751608
impl<'a> Format<'a> for AstNode<'a, Vec<'a, TSSignature<'a>>> {
15761609
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
1577-
f.join_nodes_with_soft_line().entries(self).finish()
1610+
let last_index = self.len().saturating_sub(1);
1611+
f.join_nodes_with_soft_line()
1612+
.entries(
1613+
self.iter()
1614+
.enumerate()
1615+
.map(|(i, signature)| FormatTSSignature { last: i == last_index, signature }),
1616+
)
1617+
.finish()
15781618
}
15791619
}
15801620

@@ -1584,16 +1624,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSIndexSignature<'a>> {
15841624
write!(f, ["readonly", space()])?;
15851625
}
15861626
// TODO: parameters only have one element for now.
1587-
write!(
1588-
f,
1589-
[
1590-
"[",
1591-
self.parameters().first().unwrap(),
1592-
"]",
1593-
self.type_annotation(),
1594-
OptionalSemicolon
1595-
]
1596-
)
1627+
write!(f, ["[", self.parameters().first().unwrap(), "]", self.type_annotation(),])
15971628
}
15981629
}
15991630

@@ -1610,7 +1641,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSCallSignatureDeclaration<'a>> {
16101641
if let Some(return_type) = &self.return_type() {
16111642
write!(f, return_type)?;
16121643
}
1613-
write!(f, OptionalSemicolon)
1644+
Ok(())
16141645
}
16151646
}
16161647

@@ -1656,7 +1687,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSMethodSignature<'a>> {
16561687
if let Some(return_type) = &self.return_type() {
16571688
write!(f, return_type)?;
16581689
}
1659-
write!(f, OptionalSemicolon)
1690+
Ok(())
16601691
}
16611692
}
16621693

@@ -1670,7 +1701,7 @@ impl<'a> FormatWrite<'a> for AstNode<'a, TSConstructSignatureDeclaration<'a>> {
16701701
if let Some(return_type) = self.return_type() {
16711702
write!(f, return_type)?;
16721703
}
1673-
write!(f, OptionalSemicolon)
1704+
Ok(())
16741705
}
16751706
}
16761707

crates/oxc_formatter/src/write/semicolon.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl<'a, 'b> ClassPropertySemicolon<'a, 'b> {
7373
ClassElement::AccessorProperty(def) => {
7474
def.computed && !(def.accessibility.is_some() || def.r#static || def.r#override)
7575
}
76+
ClassElement::TSIndexSignature(_) => true,
7677
_ => false,
7778
}
7879
}
@@ -82,9 +83,7 @@ impl<'a> Format<'a> for ClassPropertySemicolon<'a, '_> {
8283
fn fmt(&self, f: &mut Formatter<'_, 'a>) -> FormatResult<()> {
8384
if matches!(
8485
self.element.as_ref(),
85-
ClassElement::StaticBlock(_)
86-
| ClassElement::MethodDefinition(_)
87-
| ClassElement::TSIndexSignature(_)
86+
ClassElement::StaticBlock(_) | ClassElement::MethodDefinition(_)
8887
) {
8988
return Ok(());
9089
}

tasks/coverage/snapshots/formatter_typescript.snap

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@ commit: 261630d6
22

33
formatter_typescript Summary:
44
AST Parsed : 8816/8816 (100.00%)
5-
Positive Passed: 8763/8816 (99.40%)
6-
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/APISample_jsdoc.ts
7-
Expected `]` but found `:`
5+
Positive Passed: 8774/8816 (99.52%)
86
Mismatch: tasks/coverage/typescript/tests/cases/compiler/amdLikeInputDeclarationEmit.ts
97

108
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/arrayFromAsync.ts
@@ -21,8 +19,6 @@ Mismatch: tasks/coverage/typescript/tests/cases/compiler/complexNarrowingWithAny
2119

2220
Mismatch: tasks/coverage/typescript/tests/cases/compiler/declarationEmitCastReusesTypeNode4.ts
2321

24-
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/declarationEmitPartialReuseComputedProperty.ts
25-
Unexpected token
2622
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/declarationEmitPromise.ts
2723
Expected a semicolon or an implicit semicolon after a statement, but found none
2824
Mismatch: tasks/coverage/typescript/tests/cases/compiler/declarationEmitRecursiveConditionalAliasPreserved.ts
@@ -37,16 +33,12 @@ Mismatch: tasks/coverage/typescript/tests/cases/compiler/jsxNamespaceGlobalReexp
3733

3834
Mismatch: tasks/coverage/typescript/tests/cases/compiler/jsxNamespaceImplicitImportJSXNamespace.tsx
3935

40-
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/keyRemappingKeyofResult.ts
41-
Unexpected token
4236
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/narrowingByTypeofInSwitch.ts
4337
Expected a semicolon or an implicit semicolon after a statement, but found none
4438
Mismatch: tasks/coverage/typescript/tests/cases/compiler/propertyAccessExpressionInnerComments.ts
4539

4640
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/readonlyAssignmentInSubclassOfClassExpression.ts
4741
Expected `{` but found `as`
48-
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/reducibleIndexedAccessTypes.ts
49-
Expected `]` but found `:`
5042
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/reverseMappedTypeInferenceSameSource1.ts
5143
An implementation cannot be declared in ambient contexts.
5244
Mismatch: tasks/coverage/typescript/tests/cases/compiler/sourceMapValidationClasses.ts
@@ -59,8 +51,6 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/superAccessCaste
5951
Expected a semicolon or an implicit semicolon after a statement, but found none
6052
Mismatch: tasks/coverage/typescript/tests/cases/compiler/tryStatementInternalComments.ts
6153
62-
Expect to Parse: tasks/coverage/typescript/tests/cases/compiler/typeName1.ts
63-
Expected `]` but found `:`
6454
Mismatch: tasks/coverage/typescript/tests/cases/compiler/unionSignaturesWithThisParameter.ts
6555
6656
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/classes/propertyMemberDeclarations/overrideInterfaceProperty.ts
@@ -93,19 +83,7 @@ Mismatch: tasks/coverage/typescript/tests/cases/conformance/interfaces/interface
9383
9484
Mismatch: tasks/coverage/typescript/tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClassWithProtecteds2.ts
9585
96-
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts
97-
Expected `]` but found `:`
9886
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/statements/returnStatements/returnStatementNoAsiAfterTransform.ts
9987
Expected `,` but found `(`
100-
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/types/mapped/mappedTypeModifiers.ts
101-
Expected `]` but found `:`
102-
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/types/objectTypeLiteral/propertySignatures/propertyNamesOfReservedWords.ts
103-
'static' modifier cannot appear on a type member.'static' modifier cannot appear on a type member.
104-
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/types/rest/genericObjectRest.ts
105-
Unexpected token
10688
Mismatch: tasks/coverage/typescript/tests/cases/conformance/types/tuple/named/namedTupleMembers.ts
10789
108-
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/types/uniqueSymbol/uniqueSymbols.ts
109-
Unexpected token
110-
Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/types/uniqueSymbol/uniqueSymbolsDeclarations.ts
111-
Unexpected token

0 commit comments

Comments
 (0)