Skip to content

Commit 44b9745

Browse files
authored
fix(49151): format type parameters/arguments (#49165)
Before, the formatter did not consider these constructs as comma separated lists in general, leading to wrong indentation of '>' after the list.
1 parent bf5acb5 commit 44b9745

File tree

2 files changed

+159
-2
lines changed

2 files changed

+159
-2
lines changed

src/services/formatting/formatting.ts

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,6 @@ namespace ts.formatting {
617617
case SyntaxKind.JsxOpeningElement:
618618
case SyntaxKind.JsxClosingElement:
619619
case SyntaxKind.JsxSelfClosingElement:
620-
case SyntaxKind.ExpressionWithTypeArguments:
621620
return false;
622621
}
623622
break;
@@ -835,7 +834,7 @@ namespace ts.formatting {
835834
const listEndToken = getCloseTokenForOpenToken(listStartToken);
836835
if (listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) {
837836
let tokenInfo: TokenInfo | undefined = formattingScanner.readTokenInfo(parent);
838-
if (tokenInfo.token.kind === SyntaxKind.CommaToken && isCallLikeExpression(parent)) {
837+
if (tokenInfo.token.kind === SyntaxKind.CommaToken) {
839838
// consume the comma
840839
consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent);
841840
tokenInfo = formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(parent) : undefined;
@@ -1311,6 +1310,12 @@ namespace ts.formatting {
13111310
case SyntaxKind.MethodDeclaration:
13121311
case SyntaxKind.MethodSignature:
13131312
case SyntaxKind.ArrowFunction:
1313+
case SyntaxKind.CallSignature:
1314+
case SyntaxKind.ConstructSignature:
1315+
case SyntaxKind.FunctionType:
1316+
case SyntaxKind.ConstructorType:
1317+
case SyntaxKind.GetAccessor:
1318+
case SyntaxKind.SetAccessor:
13141319
if ((node as FunctionDeclaration).typeParameters === list) {
13151320
return SyntaxKind.LessThanToken;
13161321
}
@@ -1327,7 +1332,19 @@ namespace ts.formatting {
13271332
return SyntaxKind.OpenParenToken;
13281333
}
13291334
break;
1335+
case SyntaxKind.ClassDeclaration:
1336+
case SyntaxKind.ClassExpression:
1337+
case SyntaxKind.InterfaceDeclaration:
1338+
case SyntaxKind.TypeAliasDeclaration:
1339+
if ((node as ClassDeclaration).typeParameters === list) {
1340+
return SyntaxKind.LessThanToken;
1341+
}
1342+
break;
13301343
case SyntaxKind.TypeReference:
1344+
case SyntaxKind.TaggedTemplateExpression:
1345+
case SyntaxKind.TypeQuery:
1346+
case SyntaxKind.ExpressionWithTypeArguments:
1347+
case SyntaxKind.ImportType:
13311348
if ((node as TypeReferenceNode).typeArguments === list) {
13321349
return SyntaxKind.LessThanToken;
13331350
}
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////
4+
//// class Foo <
5+
//// T1 extends unknown,
6+
//// T2
7+
//// > {
8+
//// public method <
9+
//// T3,
10+
//// > (a: T1, b: Array <
11+
//// string
12+
//// > ): Map <
13+
//// T1 ,
14+
//// Array < T3 >
15+
//// > { throw new Error(); }
16+
//// }
17+
////
18+
//// interface IFoo<
19+
//// T,
20+
//// > {
21+
//// new < T
22+
//// > ( a: T);
23+
//// op?<
24+
//// T,
25+
//// M
26+
//// > (a: T, b : M );
27+
//// <
28+
//// T,
29+
//// >(x: T): T;
30+
//// }
31+
////
32+
//// type foo<
33+
//// T
34+
//// > = Foo <
35+
//// number, Array < number > > ;
36+
////
37+
//// function bar <
38+
//// T, U extends T
39+
//// > () {
40+
//// return class <
41+
//// T2,
42+
//// > {
43+
//// }
44+
//// }
45+
////
46+
//// bar<
47+
//// string,
48+
//// "s"
49+
//// > ();
50+
////
51+
//// declare const func: <
52+
//// T extends number[],
53+
//// > (x: T) => new <
54+
//// U
55+
//// > () => U;
56+
////
57+
//// class A < T > extends bar <
58+
//// T,number
59+
//// >( ) < T
60+
//// > {
61+
//// }
62+
////
63+
//// function s<T, U>(x: TemplateStringsArray, ...args: any[]) { return x.join(); }
64+
////
65+
//// const t = s<
66+
//// number ,
67+
//// string[] & ArrayLike<any>
68+
//// >`abc${1}def` ;
69+
////
70+
71+
72+
format.document();
73+
74+
verify.currentFileContentIs(`
75+
class Foo<
76+
T1 extends unknown,
77+
T2
78+
> {
79+
public method<
80+
T3,
81+
>(a: T1, b: Array<
82+
string
83+
>): Map<
84+
T1,
85+
Array<T3>
86+
> { throw new Error(); }
87+
}
88+
89+
interface IFoo<
90+
T,
91+
> {
92+
new <T
93+
>(a: T);
94+
op?<
95+
T,
96+
M
97+
>(a: T, b: M);
98+
<
99+
T,
100+
>(x: T): T;
101+
}
102+
103+
type foo<
104+
T
105+
> = Foo<
106+
number, Array<number>>;
107+
108+
function bar<
109+
T, U extends T
110+
>() {
111+
return class <
112+
T2,
113+
> {
114+
}
115+
}
116+
117+
bar<
118+
string,
119+
"s"
120+
>();
121+
122+
declare const func: <
123+
T extends number[],
124+
> (x: T) => new <
125+
U
126+
> () => U;
127+
128+
class A<T> extends bar<
129+
T, number
130+
>()<T
131+
> {
132+
}
133+
134+
function s<T, U>(x: TemplateStringsArray, ...args: any[]) { return x.join(); }
135+
136+
const t = s<
137+
number,
138+
string[] & ArrayLike<any>
139+
>\`abc\${1}def\`;
140+
`);

0 commit comments

Comments
 (0)