forked from OSchip/llvm-project
clang-format: [JS] handle semis in generic types.
Summary: TypeScript generic type arguments can contain object (literal) types, which in turn can contain semicolons: const x: Array<{a: number; b: string;} = []; Previously, clang-format would incorrectly categorize the braced list as a block and terminate the line at the openening `{`, and then format the entire expression badly. With this change, clang-format recognizes `<` preceding a `{` as introducing a type expression. In JS, `<` comparison with an object literal can never be true, so the chance of introducing false positives here is very low. Reviewers: djasper Subscribers: klimek, cfe-commits Differential Revision: https://reviews.llvm.org/D40424 llvm-svn: 318975
This commit is contained in:
parent
6c38ef90fd
commit
e8e27ca866
|
@ -379,13 +379,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
|
||||||
switch (Tok->Tok.getKind()) {
|
switch (Tok->Tok.getKind()) {
|
||||||
case tok::l_brace:
|
case tok::l_brace:
|
||||||
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
|
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
|
||||||
if (PrevTok->is(tok::colon))
|
if (PrevTok->isOneOf(tok::colon, tok::less))
|
||||||
// A colon indicates this code is in a type, or a braced list
|
// A ':' indicates this code is in a type, or a braced list
|
||||||
// following a label in an object literal ({a: {b: 1}}). The code
|
// following a label in an object literal ({a: {b: 1}}).
|
||||||
// below could be confused by semicolons between the individual
|
// A '<' could be an object used in a comparison, but that is nonsense
|
||||||
// members in a type member list, which would normally trigger
|
// code (can never return true), so more likely it is a generic type
|
||||||
// BK_Block. In both cases, this must be parsed as an inline braced
|
// argument (`X<{a: string; b: number}>`).
|
||||||
// init.
|
// The code below could be confused by semicolons between the
|
||||||
|
// individual members in a type member list, which would normally
|
||||||
|
// trigger BK_Block. In both cases, this must be parsed as an inline
|
||||||
|
// braced init.
|
||||||
Tok->BlockKind = BK_BracedInit;
|
Tok->BlockKind = BK_BracedInit;
|
||||||
else if (PrevTok->is(tok::r_paren))
|
else if (PrevTok->is(tok::r_paren))
|
||||||
// `) { }` can only occur in function or method declarations in JS.
|
// `) { }` can only occur in function or method declarations in JS.
|
||||||
|
|
|
@ -1414,6 +1414,7 @@ TEST_F(FormatTestJS, TypeAnnotations) {
|
||||||
verifyFormat("function x(y: {a?: number;} = {}): number {\n"
|
verifyFormat("function x(y: {a?: number;} = {}): number {\n"
|
||||||
" return 12;\n"
|
" return 12;\n"
|
||||||
"}");
|
"}");
|
||||||
|
verifyFormat("const x: Array<{a: number; b: string;}> = [];");
|
||||||
verifyFormat("((a: string, b: number): string => a + b);");
|
verifyFormat("((a: string, b: number): string => a + b);");
|
||||||
verifyFormat("var x: (y: number) => string;");
|
verifyFormat("var x: (y: number) => string;");
|
||||||
verifyFormat("var x: P<string, (a: number) => string>;");
|
verifyFormat("var x: P<string, (a: number) => string>;");
|
||||||
|
|
Loading…
Reference in New Issue