summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorMartin Probst <martin@probst.io>2017-11-25 09:33:47 +0000
committerMartin Probst <martin@probst.io>2017-11-25 09:33:47 +0000
commite8e27ca866d89a40639c8592032ca21fdf4848bf (patch)
treea55dbf88ab7e8dc9a7d5683fb1bf1177737b0f43 /clang
parent6c38ef90fdd12917d9401bbaff95ebfc12a08491 (diff)
downloadbcm5719-llvm-e8e27ca866d89a40639c8592032ca21fdf4848bf.tar.gz
bcm5719-llvm-e8e27ca866d89a40639c8592032ca21fdf4848bf.zip
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
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Format/UnwrappedLineParser.cpp17
-rw-r--r--clang/unittests/Format/FormatTestJS.cpp1
2 files changed, 11 insertions, 7 deletions
diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp
index 6dd922e4f26..b8608dcac9c 100644
--- a/clang/lib/Format/UnwrappedLineParser.cpp
+++ b/clang/lib/Format/UnwrappedLineParser.cpp
@@ -379,13 +379,16 @@ void UnwrappedLineParser::calculateBraceTypes(bool ExpectClassBody) {
switch (Tok->Tok.getKind()) {
case tok::l_brace:
if (Style.Language == FormatStyle::LK_JavaScript && PrevTok) {
- if (PrevTok->is(tok::colon))
- // A colon indicates this code is in a type, or a braced list
- // following a label in an object literal ({a: {b: 1}}). 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.
+ if (PrevTok->isOneOf(tok::colon, tok::less))
+ // A ':' indicates this code is in a type, or a braced list
+ // following a label in an object literal ({a: {b: 1}}).
+ // A '<' could be an object used in a comparison, but that is nonsense
+ // code (can never return true), so more likely it is a generic type
+ // argument (`X<{a: string; b: number}>`).
+ // 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;
else if (PrevTok->is(tok::r_paren))
// `) { }` can only occur in function or method declarations in JS.
diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp
index cfdd4b375b6..187b50221d1 100644
--- a/clang/unittests/Format/FormatTestJS.cpp
+++ b/clang/unittests/Format/FormatTestJS.cpp
@@ -1414,6 +1414,7 @@ TEST_F(FormatTestJS, TypeAnnotations) {
verifyFormat("function x(y: {a?: number;} = {}): number {\n"
" return 12;\n"
"}");
+ verifyFormat("const x: Array<{a: number; b: string;}> = [];");
verifyFormat("((a: string, b: number): string => a + b);");
verifyFormat("var x: (y: number) => string;");
verifyFormat("var x: P<string, (a: number) => string>;");
OpenPOWER on IntegriCloud