clang-format: [JS] conditional types.

Summary:
This change adds some rudimentary support for conditional types.
Specifically it avoids breaking before `extends` and `infer` keywords,
which are subject to Automatic Semicolon Insertion, so breaking before
them creates incorrect syntax.

The actual formatting of the type expression is odd, but there is as of
yet no clear idea on how to format these.

See https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types.

Reviewers: krasimir

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D52536

llvm-svn: 343179
This commit is contained in:
Martin Probst 2018-09-27 06:48:13 +00:00
parent 77708b2390
commit 3315aed44a
3 changed files with 17 additions and 0 deletions

View File

@ -680,6 +680,7 @@ struct AdditionalKeywords {
kw_function = &IdentTable.get("function");
kw_get = &IdentTable.get("get");
kw_import = &IdentTable.get("import");
kw_infer = &IdentTable.get("infer");
kw_is = &IdentTable.get("is");
kw_let = &IdentTable.get("let");
kw_module = &IdentTable.get("module");
@ -751,6 +752,7 @@ struct AdditionalKeywords {
IdentifierInfo *kw_function;
IdentifierInfo *kw_get;
IdentifierInfo *kw_import;
IdentifierInfo *kw_infer;
IdentifierInfo *kw_is;
IdentifierInfo *kw_let;
IdentifierInfo *kw_module;

View File

@ -3088,6 +3088,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line,
return Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None;
if (Right.is(Keywords.kw_as))
return false; // must not break before as in 'x as type' casts
if (Right.isOneOf(Keywords.kw_extends, Keywords.kw_infer)) {
// extends and infer can appear as keywords in conditional types:
// https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#conditional-types
// do not break before them, as the expressions are subject to ASI.
return false;
}
if (Left.is(Keywords.kw_as))
return true;
if (Left.is(TT_JsNonNullAssertion))

View File

@ -2308,5 +2308,14 @@ TEST_F(FormatTestJS, ParameterNamingComment) {
verifyFormat("callFoo(/*spaceAfterParameterNamingComment=*/ 1);");
}
TEST_F(FormatTestJS, ConditionalTypes) {
// Formatting below is not necessarily intentional, this just ensures that
// clang-format does not break the code.
verifyFormat( // wrap
"type UnionToIntersection<U> =\n"
" (U extends any ? (k: U) => void :\n"
" never) extends((k: infer I) => void) ? I : never;");
}
} // end namespace tooling
} // end namespace clang