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.
This commit is contained in:
TRCYX 2022-06-01 07:03:17 +08:00 committed by GitHub
parent bf5acb5c4d
commit 44b9745942
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 159 additions and 2 deletions

View File

@ -617,7 +617,6 @@ namespace ts.formatting {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxClosingElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.ExpressionWithTypeArguments:
return false;
}
break;
@ -835,7 +834,7 @@ namespace ts.formatting {
const listEndToken = getCloseTokenForOpenToken(listStartToken);
if (listEndToken !== SyntaxKind.Unknown && formattingScanner.isOnToken() && formattingScanner.getStartPos() < originalRange.end) {
let tokenInfo: TokenInfo | undefined = formattingScanner.readTokenInfo(parent);
if (tokenInfo.token.kind === SyntaxKind.CommaToken && isCallLikeExpression(parent)) {
if (tokenInfo.token.kind === SyntaxKind.CommaToken) {
// consume the comma
consumeTokenAndAdvanceScanner(tokenInfo, parent, listDynamicIndentation, parent);
tokenInfo = formattingScanner.isOnToken() ? formattingScanner.readTokenInfo(parent) : undefined;
@ -1311,6 +1310,12 @@ namespace ts.formatting {
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.ArrowFunction:
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
if ((node as FunctionDeclaration).typeParameters === list) {
return SyntaxKind.LessThanToken;
}
@ -1327,7 +1332,19 @@ namespace ts.formatting {
return SyntaxKind.OpenParenToken;
}
break;
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
if ((node as ClassDeclaration).typeParameters === list) {
return SyntaxKind.LessThanToken;
}
break;
case SyntaxKind.TypeReference:
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.TypeQuery:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.ImportType:
if ((node as TypeReferenceNode).typeArguments === list) {
return SyntaxKind.LessThanToken;
}

View File

@ -0,0 +1,140 @@
/// <reference path='fourslash.ts' />
////
//// class Foo <
//// T1 extends unknown,
//// T2
//// > {
//// public method <
//// T3,
//// > (a: T1, b: Array <
//// string
//// > ): Map <
//// T1 ,
//// Array < T3 >
//// > { throw new Error(); }
//// }
////
//// interface IFoo<
//// T,
//// > {
//// new < T
//// > ( a: T);
//// op?<
//// T,
//// M
//// > (a: T, b : M );
//// <
//// T,
//// >(x: T): T;
//// }
////
//// type foo<
//// T
//// > = Foo <
//// number, Array < number > > ;
////
//// function bar <
//// T, U extends T
//// > () {
//// return class <
//// T2,
//// > {
//// }
//// }
////
//// bar<
//// string,
//// "s"
//// > ();
////
//// declare const func: <
//// T extends number[],
//// > (x: T) => new <
//// U
//// > () => U;
////
//// class A < T > extends bar <
//// T,number
//// >( ) < T
//// > {
//// }
////
//// function s<T, U>(x: TemplateStringsArray, ...args: any[]) { return x.join(); }
////
//// const t = s<
//// number ,
//// string[] & ArrayLike<any>
//// >`abc${1}def` ;
////
format.document();
verify.currentFileContentIs(`
class Foo<
T1 extends unknown,
T2
> {
public method<
T3,
>(a: T1, b: Array<
string
>): Map<
T1,
Array<T3>
> { throw new Error(); }
}
interface IFoo<
T,
> {
new <T
>(a: T);
op?<
T,
M
>(a: T, b: M);
<
T,
>(x: T): T;
}
type foo<
T
> = Foo<
number, Array<number>>;
function bar<
T, U extends T
>() {
return class <
T2,
> {
}
}
bar<
string,
"s"
>();
declare const func: <
T extends number[],
> (x: T) => new <
U
> () => U;
class A<T> extends bar<
T, number
>()<T
> {
}
function s<T, U>(x: TemplateStringsArray, ...args: any[]) { return x.join(); }
const t = s<
number,
string[] & ArrayLike<any>
>\`abc\${1}def\`;
`);