Support TypeScript 3.7 (and drop Node 6 support for direct inst… (#6657)

* WIP: Support TypeScript 3.7

* Add support for `asserts` keyword; Update snapshots

* Update typescript-estree to v2.5.0 to remove the dependency on chokidar

* Update TypeScript

* Update CHANGELOG.unreleased.md

* Add examples for TypeScript 3.7

* Update TypeScript 3.7 to latest dev version

* Correct wording

* Support `declare` keyword on class members (TypeScript 3.7 feature)

* Update Changelog and downgrade TypeScript from 3.8.0-dev to 3.7.1-rc

* Add a note regarding to dropping Node 6 support for direct installation

* tweak build config to repair build

* update CHANGELOG.unreleased.md

* TSTypePredicate microrefactoring

* fix formatting

* clean up tests

* fix parens for optional chaining inside computed properties

* update CHANGELOG.unreleased.md

* unify output across parsers for template literals

* enable more tests with optional chaining

* fix unneeded parens inside computed key of OptionalMemberExpression

* fix paren issues for OptionalCallExpression

* more fixes for OptionalCallExpression

* @typescript-eslint/typescript-estree 2.5.1-alpha.4

* fix lint

* revert build hacks

* fix one more parens issue

* @typescript-eslint/typescript-estree 2.5.1-alpha.5, remove loggerFn override

* drop node 6 for direct installing from github

* fix another parens issue, disable some tests for flow

* workaround for flow bug

* fix issues with comments


Co-authored-by: Georgii Dolzhykov <thorn.mailbox@gmail.com>
master
Zhongliang Wang 2019-10-29 00:53:57 +08:00 committed by Simon Lydell
parent 4e46f92b86
commit 2cfd8fb518
27 changed files with 572 additions and 116 deletions

View File

@ -44,6 +44,107 @@ const link = <a href="example.com">http://example.com</a>;
-->
#### TypeScript: Support for TypeScript 3.7 ([#6657] by [@cryrivers])
Prettier 1.19 adds support for the features of the upcoming TypeScript 3.7 that introduce new syntax:
- [Optional chaining](https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-rc/#optional-chaining)
- [Nullish coalescing](https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-rc/#nullish-coalescing)
- [Assertion functions](https://devblogs.microsoft.com/typescript/announcing-typescript-3-7-rc/#assertion-functions)
- [`declare` modifier on class fields](https://github.com/microsoft/TypeScript/pull/33509)
**NOTE:** A dependency upgrade for TypeScript 3.7 led to dropping Node 6 support for direct installation from GitHub. Prettier installed from NPM stays compatible with Node 4.
##### Optional Chaining
<!-- prettier-ignore -->
```ts
// Input
const longChain = obj?.a?.b?.c?.d?.e?.f?.g;
const longChainCallExpression = obj.a?.(a,b,c).b?.(a,b,c).c?.(a,b,c).d?.(a,b,c).e?.(a,b,c).f?.(a,b,c)
// Output (Prettier master)
const longChain = obj?.a?.b?.c?.d?.e?.f?.g;
const longChainCallExpression = obj
.a?.(a, b, c)
.b?.(a, b, c)
.c?.(a, b, c)
.d?.(a, b, c)
.e?.(a, b, c)
.f?.(a, b, c);
```
##### Nullish Coalescing
<!-- prettier-ignore -->
```ts
// Input
const cond = null;
const result = cond??'a';
const longChain = cond??cond??cond??'b';
// Output (Prettier master)
const cond = null;
const result = cond ?? "a";
const longChain = cond ?? cond ?? cond ?? "b";
```
##### Assertion Functions
<!-- prettier-ignore -->
```ts
// Input
function assertsString(x: any): asserts x {console.assert(typeof x === 'string');}
function assertsStringWithGuard(x: any): asserts x is string {console.assert(typeof x === 'string');}
// Output (Prettier master)
function assertsString(x: any): asserts x {
console.assert(typeof x === "string");
}
function assertsStringWithGuard(x: any): asserts x is string {
console.assert(typeof x === "string");
}
```
##### `declare` Modifier on Class Fields
<!-- prettier-ignore -->
```ts
// Input
class B {p: number;}
class C extends B {declare p: 256 | 1000;}
// Output (Prettier master)
class B {
p: number;
}
class C extends B {
declare p: 256 | 1000;
}
```
#### TypeScript: Prettier removed `?` from optional computed class fields ([#6657] by [@cryrivers])
Still happens if the field key is a complex expression, but has been fixed in this case:
<!-- prettier-ignore -->
```ts
// Input
class Foo {
[bar]?: number;
}
// Output (Prettier stable)
class Foo {
[bar]: number;
}
// Output (Prettier master)
class Foo {
[bar]?: number;
}
```
#### API: Add `resolveConfig` option to `getFileInfo()` ([#6666] by [@kaicataldo])
Add a `resolveConfig: boolean` option to `prettier.getFileInfo()` that, when set to `true`, will resolve the configuration for the given file path. This allows consumers to take any overridden parsers into account.
@ -52,6 +153,7 @@ Add a `resolveConfig: boolean` option to `prettier.getFileInfo()` that, when set
<!-- prettier-ignore -->
```js
// Input
const addOne = add(1, ?); // apply from the left
addOne(2); // 3
@ -1168,6 +1270,7 @@ new Map([
```
[#5682]: https://github.com/prettier/prettier/pull/5682
[#6657]: https://github.com/prettier/prettier/pull/6657
[#5910]: https://github.com/prettier/prettier/pull/5910
[#6033]: https://github.com/prettier/prettier/pull/6033
[#6186]: https://github.com/prettier/prettier/pull/6186
@ -1224,4 +1327,5 @@ new Map([
[@selvazhagan]: https://github.com/selvazhagan
[@chadian]: https://github.com/chadian
[@kaicataldo]: https://github.com/kaicataldo
[@cryrivers]: https://github.com/Cryrivers
[@voithos]: https://github.com/voithos

View File

@ -11,7 +11,7 @@
"license": "MIT",
"main": "./index.js",
"engines": {
"node": ">=6"
"node": ">=8"
},
"dependencies": {
"@angular/compiler": "8.2.7",
@ -19,7 +19,7 @@
"@babel/parser": "7.6.3",
"@glimmer/syntax": "0.41.0",
"@iarna/toml": "2.2.3",
"@typescript-eslint/typescript-estree": "1.13.0",
"@typescript-eslint/typescript-estree": "2.5.1-alpha.5",
"angular-estree-parser": "1.1.5",
"angular-html-parser": "1.2.0",
"camelcase": "5.3.1",
@ -67,7 +67,7 @@
"resolve": "1.12.0",
"semver": "6.3.0",
"string-width": "3.1.0",
"typescript": "3.6.4",
"typescript": "3.7.1-rc",
"unicode-regex": "3.0.0",
"unified": "6.1.6",
"vnopts": "1.0.2",

View File

@ -342,6 +342,7 @@ function startsWithNoLookaheadToken(node, forbidFunctionClassAndDoExpr) {
case "ObjectExpression":
return true;
case "MemberExpression":
case "OptionalMemberExpression":
return startsWithNoLookaheadToken(
node.object,
forbidFunctionClassAndDoExpr
@ -353,6 +354,7 @@ function startsWithNoLookaheadToken(node, forbidFunctionClassAndDoExpr) {
}
return startsWithNoLookaheadToken(node.tag, forbidFunctionClassAndDoExpr);
case "CallExpression":
case "OptionalCallExpression":
if (node.callee.type === "FunctionExpression") {
// IIFEs are always already parenthesized
return false;

View File

@ -564,6 +564,7 @@ function handleCommentInEmptyParens(text, enclosingNode, comment, options) {
enclosingNode.type === "ObjectMethod") &&
enclosingNode.params.length === 0) ||
((enclosingNode.type === "CallExpression" ||
enclosingNode.type === "OptionalCallExpression" ||
enclosingNode.type === "NewExpression") &&
enclosingNode.arguments.length === 0))
) {
@ -686,7 +687,8 @@ function handleBreakAndContinueStatementComments(enclosingNode, comment) {
function handleCallExpressionComments(precedingNode, enclosingNode, comment) {
if (
enclosingNode &&
enclosingNode.type === "CallExpression" &&
(enclosingNode.type === "CallExpression" ||
enclosingNode.type === "OptionalCallExpression") &&
precedingNode &&
enclosingNode.callee === precedingNode &&
enclosingNode.arguments.length > 0

View File

@ -254,14 +254,16 @@ function needsParens(path, options) {
return true;
case "MemberExpression":
return name === "object" && parent.object === node;
case "OptionalMemberExpression":
return name === "object";
case "TaggedTemplateExpression":
return true;
case "NewExpression":
case "CallExpression":
return name === "callee" && parent.callee === node;
case "OptionalCallExpression":
return name === "callee";
case "BinaryExpression":
return parent.operator === "**" && name === "left";
@ -306,7 +308,8 @@ function needsParens(path, options) {
case "CallExpression":
case "NewExpression":
return name === "callee" && parent.callee === node;
case "OptionalCallExpression":
return name === "callee";
case "ClassExpression":
case "ClassDeclaration":
@ -327,7 +330,7 @@ function needsParens(path, options) {
case "MemberExpression":
case "OptionalMemberExpression":
return name === "object" && parent.object === node;
return name === "object";
case "AssignmentExpression":
return (
@ -427,15 +430,16 @@ function needsParens(path, options) {
case "TSAsExpression":
case "TSNonNullExpression":
case "BindExpression":
case "OptionalMemberExpression":
return true;
case "MemberExpression":
return parent.object === node;
case "OptionalMemberExpression":
return name === "object";
case "NewExpression":
case "CallExpression":
return parent.callee === node;
case "OptionalCallExpression":
return name === "callee";
case "ConditionalExpression":
return parent.test === node;
@ -591,18 +595,19 @@ function needsParens(path, options) {
case "TypeCastExpression":
case "TSAsExpression":
case "TSNonNullExpression":
case "OptionalMemberExpression":
return true;
case "NewExpression":
case "CallExpression":
return name === "callee" && parent.callee === node;
case "OptionalCallExpression":
return name === "callee";
case "ConditionalExpression":
return name === "test" && parent.test === node;
case "MemberExpression":
return name === "object" && parent.object === node;
case "OptionalMemberExpression":
return name === "object";
default:
return false;
@ -612,7 +617,10 @@ function needsParens(path, options) {
switch (parent.type) {
case "NewExpression":
case "CallExpression":
return name === "callee"; // Not strictly necessary, but it's clearer to the reader if IIFEs are wrapped in parentheses.
case "OptionalCallExpression":
// Not always necessary, but it's clearer to the reader if IIFEs are wrapped in parentheses.
// Is necessary if it is `expression` of `ExpressionStatement`.
return name === "callee";
case "TaggedTemplateExpression":
return true; // This is basically a kind of IIFE.
default:
@ -621,13 +629,13 @@ function needsParens(path, options) {
case "ArrowFunctionExpression":
switch (parent.type) {
case "CallExpression":
return name === "callee";
case "NewExpression":
case "CallExpression":
case "OptionalCallExpression":
return name === "callee";
case "MemberExpression":
case "OptionalMemberExpression":
return name === "object";
case "TSAsExpression":
@ -656,23 +664,32 @@ function needsParens(path, options) {
}
case "OptionalMemberExpression":
return parent.type === "MemberExpression";
case "OptionalCallExpression":
if (
((parent.type === "MemberExpression" && name === "object") ||
(parent.type === "CallExpression" && name === "callee")) &&
// workaround for https://github.com/facebook/flow/issues/8159
!(options.parser === "flow" && parent.range[0] === node.range[0])
) {
return true;
}
// fallthrough
case "CallExpression":
case "MemberExpression":
case "TaggedTemplateExpression":
case "TSNonNullExpression":
if (
(parent.type === "BindExpression" || parent.type === "NewExpression") &&
name === "callee" &&
parent.callee === node
name === "callee"
) {
let object = node;
while (object) {
switch (object.type) {
case "CallExpression":
case "OptionalCallExpression":
return true;
case "MemberExpression":
case "OptionalMemberExpression":
case "BindExpression":
object = object.object;
break;
@ -692,20 +709,14 @@ function needsParens(path, options) {
return false;
case "BindExpression":
if (
(parent.type === "BindExpression" &&
name === "callee" &&
parent.callee === node) ||
(parent.type === "MemberExpression" &&
name === "object" &&
parent.object === node) ||
(parent.type === "NewExpression" &&
name === "callee" &&
parent.callee === node)
) {
return true;
}
return false;
return (
((parent.type === "BindExpression" ||
parent.type === "NewExpression") &&
name === "callee") ||
((parent.type === "MemberExpression" ||
parent.type === "OptionalMemberExpression") &&
name === "object")
);
case "NGPipeExpression":
if (
parent.type === "NGRoot" ||
@ -725,25 +736,27 @@ function needsParens(path, options) {
case "JSXFragment":
case "JSXElement":
return (
parent.type !== "ArrayExpression" &&
parent.type !== "ArrowFunctionExpression" &&
parent.type !== "AssignmentExpression" &&
parent.type !== "AssignmentPattern" &&
parent.type !== "BinaryExpression" &&
parent.type !== "CallExpression" &&
parent.type !== "ConditionalExpression" &&
parent.type !== "ExpressionStatement" &&
parent.type !== "JsExpressionRoot" &&
parent.type !== "JSXAttribute" &&
parent.type !== "JSXElement" &&
parent.type !== "JSXExpressionContainer" &&
parent.type !== "JSXFragment" &&
parent.type !== "LogicalExpression" &&
parent.type !== "ObjectProperty" &&
parent.type !== "Property" &&
parent.type !== "ReturnStatement" &&
parent.type !== "TypeCastExpression" &&
parent.type !== "VariableDeclarator"
name === "callee" ||
(parent.type !== "ArrayExpression" &&
parent.type !== "ArrowFunctionExpression" &&
parent.type !== "AssignmentExpression" &&
parent.type !== "AssignmentPattern" &&
parent.type !== "BinaryExpression" &&
parent.type !== "CallExpression" &&
parent.type !== "ConditionalExpression" &&
parent.type !== "ExpressionStatement" &&
parent.type !== "JsExpressionRoot" &&
parent.type !== "JSXAttribute" &&
parent.type !== "JSXElement" &&
parent.type !== "JSXExpressionContainer" &&
parent.type !== "JSXFragment" &&
parent.type !== "LogicalExpression" &&
parent.type !== "ObjectProperty" &&
parent.type !== "OptionalCallExpression" &&
parent.type !== "Property" &&
parent.type !== "ReturnStatement" &&
parent.type !== "TypeCastExpression" &&
parent.type !== "VariableDeclarator")
);
}

View File

@ -43,10 +43,7 @@ function tryParseTypeScript(text, jsx) {
tokens: true,
comment: true,
useJSXTextNode: true,
jsx,
// Override logger function with noop,
// to avoid unsupported version errors being logged
loggerFn: () => {}
jsx
});
}

View File

@ -570,7 +570,9 @@ function printPathNoParens(path, options, print, args) {
// c
// ).call()
if (
(parent.type === "CallExpression" && parent.callee === n) ||
((parent.type === "CallExpression" ||
parent.type === "OptionalCallExpression") &&
parent.callee === n) ||
parent.type === "UnaryExpression" ||
((parent.type === "MemberExpression" ||
parent.type === "OptionalMemberExpression") &&
@ -596,7 +598,8 @@ function printPathNoParens(path, options, print, args) {
(n !== parent.body && parent.type === "ForStatement") ||
(parent.type === "ConditionalExpression" &&
(parentParent.type !== "ReturnStatement" &&
parentParent.type !== "CallExpression"));
parentParent.type !== "CallExpression" &&
parentParent.type !== "OptionalCallExpression"));
const shouldIndentIfInlining =
parent.type === "AssignmentExpression" ||
@ -2350,6 +2353,9 @@ function printPathNoParens(path, options, print, args) {
if (n.accessibility) {
parts.push(n.accessibility + " ");
}
if (n.declare) {
parts.push("declare ");
}
if (n.static) {
parts.push("static ");
}
@ -3177,9 +3183,11 @@ function printPathNoParens(path, options, print, args) {
}
case "TSTypePredicate":
return concat([
n.asserts ? "asserts " : "",
path.call(print, "parameterName"),
" is ",
path.call(print, "typeAnnotation")
n.typeAnnotation
? concat([" is ", path.call(print, "typeAnnotation")])
: ""
]);
case "TSNonNullExpression":
return concat([path.call(print, "expression"), "!"]);
@ -5447,11 +5455,17 @@ function maybeWrapJSXElementInParens(path, elem, options) {
return elem;
}
const shouldBreak = matchAncestorTypes(path, [
"ArrowFunctionExpression",
"CallExpression",
"JSXExpressionContainer"
]);
const shouldBreak =
matchAncestorTypes(path, [
"ArrowFunctionExpression",
"CallExpression",
"JSXExpressionContainer"
]) ||
matchAncestorTypes(path, [
"ArrowFunctionExpression",
"OptionalCallExpression",
"JSXExpressionContainer"
]);
const needsParens = pathNeedsParens(path, options);
@ -5816,7 +5830,8 @@ function willPrintOwnComments(path /*, options */) {
(isJSXNode(node) ||
hasFlowShorthandAnnotationComment(node) ||
(parent &&
parent.type === "CallExpression" &&
(parent.type === "CallExpression" ||
parent.type === "OptionalCallExpression") &&
(hasFlowAnnotationComment(node.leadingComments) ||
hasFlowAnnotationComment(node.trailingComments))))) ||
(parent &&

View File

@ -425,25 +425,29 @@ function isSimpleTemplateLiteral(node) {
// Allow `a.b.c`, `a.b[c]`, and `this.x.y`
if (
(expr.type === "MemberExpression" ||
expr.type === "OptionalMemberExpression") &&
(expr.property.type === "Identifier" || expr.property.type === "Literal")
expr.type === "MemberExpression" ||
expr.type === "OptionalMemberExpression"
) {
let ancestor = expr;
let head = expr;
while (
ancestor.type === "MemberExpression" ||
ancestor.type === "OptionalMemberExpression"
head.type === "MemberExpression" ||
head.type === "OptionalMemberExpression"
) {
ancestor = ancestor.object;
if (ancestor.comments) {
if (
head.property.type !== "Identifier" &&
head.property.type !== "Literal" &&
head.property.type !== "StringLiteral" &&
head.property.type !== "NumericLiteral"
) {
return false;
}
head = head.object;
if (head.comments) {
return false;
}
}
if (
ancestor.type === "Identifier" ||
ancestor.type === "ThisExpression"
) {
if (head.type === "Identifier" || head.type === "ThisExpression") {
return true;
}

View File

@ -325,6 +325,11 @@ React.render( // Warm any cache
container
);
render?.( // Warm any cache
<ChildUpdates renderAnchor={true} anchorClassOn={true} />,
container
);
=====================================output=====================================
render(
// Warm any cache
@ -338,6 +343,12 @@ React.render(
container
);
render?.(
// Warm any cache
<ChildUpdates renderAnchor={true} anchorClassOn={true} />,
container
);
================================================================================
`;
@ -357,6 +368,7 @@ function d() {
}
new Thing(/* dangling */);
Thing(/* dangling */);
Thing?.(/* dangling */);
declare class Foo extends Qux<string> {/* dangling */}
export /* dangling */{};
@ -375,6 +387,7 @@ function d() {
}
new Thing(/* dangling */);
Thing(/* dangling */);
Thing?.(/* dangling */);
declare class Foo extends Qux<string> {
/* dangling */
}

View File

@ -7,3 +7,8 @@ React.render( // Warm any cache
<ChildUpdates renderAnchor={true} anchorClassOn={true} />,
container
);
render?.( // Warm any cache
<ChildUpdates renderAnchor={true} anchorClassOn={true} />,
container
);

View File

@ -8,5 +8,6 @@ function d() {
}
new Thing(/* dangling */);
Thing(/* dangling */);
Thing?.(/* dangling */);
declare class Foo extends Qux<string> {/* dangling */}
export /* dangling */{};

View File

@ -4093,6 +4093,10 @@ a = [
<div {...((foo || foo === null) ? {foo} : null)} />
f?.(<div/>);
(<div/>)();
(<div/>)?.();
=====================================output=====================================
a = [
<path
@ -4107,6 +4111,10 @@ a = [
<div {...(foo || foo === null ? { foo } : null)} />;
f?.(<div />);
(<div />)();
(<div />)?.();
================================================================================
`;
@ -4131,6 +4139,10 @@ a = [
<div {...((foo || foo === null) ? {foo} : null)} />
f?.(<div/>);
(<div/>)();
(<div/>)?.();
=====================================output=====================================
a = [
<path
@ -4145,6 +4157,10 @@ a = [
<div {...(foo || foo === null ? { foo } : null)} />;
f?.(<div />);
(<div />)();
(<div />)?.();
================================================================================
`;
@ -4169,6 +4185,10 @@ a = [
<div {...((foo || foo === null) ? {foo} : null)} />
f?.(<div/>);
(<div/>)();
(<div/>)?.();
=====================================output=====================================
a = [
<path
@ -4183,6 +4203,10 @@ a = [
<div {...(foo || foo === null ? { foo } : null)} />;
f?.(<div />);
(<div />)();
(<div />)?.();
================================================================================
`;
@ -4207,6 +4231,10 @@ a = [
<div {...((foo || foo === null) ? {foo} : null)} />
f?.(<div/>);
(<div/>)();
(<div/>)?.();
=====================================output=====================================
a = [
<path
@ -4221,6 +4249,10 @@ a = [
<div {...(foo || foo === null ? { foo } : null)} />;
f?.(<div />);
(<div />)();
(<div />)?.();
================================================================================
`;

View File

@ -10,3 +10,7 @@ a = [
];
<div {...((foo || foo === null) ? {foo} : null)} />
f?.(<div/>);
(<div/>)();
(<div/>)?.();

View File

@ -2,7 +2,7 @@
exports[`nullish_coalesing_operator.js 1`] = `
====================================options=====================================
parsers: ["babel", "flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================

View File

@ -1 +1 @@
run_spec(__dirname, ["babel", "flow"]);
run_spec(__dirname, ["babel", "flow", "typescript"]);

View File

@ -2,7 +2,7 @@
exports[`chaining.js 1`] = `
====================================options=====================================
parsers: ["babel", "flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
@ -35,8 +35,55 @@ a?.b[3].c?.(x).d.e?.f[3].g?.(y).h;
async function HelloWorld() {
var x = (await foo.bar.blah)?.hi;
a?.[await b];
(await x)?.();
}
a[b?.c].d();
a?.[b?.c].d();
a[b?.c]?.d();
a?.[b?.c]?.d();
(one?.fn());
(one?.two).fn();
(one.two?.fn());
(one.two?.three).fn();
(one.two?.three?.fn());
(one?.());
(one?.())();
(one?.())?.();
(one?.()).two;
a?.[b ? c : d];
(-1)?.toFixed();
(void fn)?.();
(a && b)?.();
(a ? b : c)?.();
(function(){})?.();
(() => f)?.();
(()=>f)?.x;
(a?.(x)).x;
(aaaaaaaaaaaaaaaaaaaaaaaa&&aaaaaaaaaaaaaaaaaaaaaaaa&&aaaaaaaaaaaaaaaaaaaaaaaa)?.();
let f = () => ({}?.());
let g = () => ({}?.b);
a = () => ({}?.() && a);
a = () => ({}?.()() && a);
a = () => ({}?.().b && a);
a = () => ({}?.b && a);
a = () => ({}?.b() && a);
(a) => ({}?.()?.b && 0);
(a) => ({}?.b?.b && 0);
(x) => ({}?.()());
(x) => ({}?.().b);
(x) => ({}?.b());
(x) => ({}?.b.b);
({}?.a().b());
({ a: 1 }?.entries());
=====================================output=====================================
var street = user.address?.street;
var fooValue = myForm.querySelector("input[name=foo]")?.value;
@ -67,14 +114,65 @@ a?.b?.c.d?.e;
async function HelloWorld() {
var x = (await foo.bar.blah)?.hi;
a?.[await b];
(await x)?.();
}
a[b?.c].d();
a?.[b?.c].d();
a[b?.c]?.d();
a?.[b?.c]?.d();
one?.fn();
(one?.two).fn();
one.two?.fn();
(one.two?.three).fn();
one.two?.three?.fn();
one?.();
(one?.())();
one?.()?.();
(one?.()).two;
a?.[b ? c : d];
(-1)?.toFixed();
(void fn)?.();
(a && b)?.();
(a ? b : c)?.();
(function() {})?.();
(() => f)?.();
(() => f)?.x;
(a?.(x)).x;
(
aaaaaaaaaaaaaaaaaaaaaaaa &&
aaaaaaaaaaaaaaaaaaaaaaaa &&
aaaaaaaaaaaaaaaaaaaaaaaa
)?.();
let f = () => ({}?.());
let g = () => ({}?.b);
a = () => ({}?.() && a);
a = () => ({}?.()() && a);
a = () => ({}?.().b && a);
a = () => ({}?.b && a);
a = () => ({}?.b() && a);
a => ({}?.()?.b && 0);
a => ({}?.b?.b && 0);
x => ({}?.()());
x => ({}?.().b);
x => ({}?.b());
x => ({}?.b.b);
({}?.a().b());
({ a: 1 }?.entries());
================================================================================
`;
exports[`comments.js 1`] = `
====================================options=====================================
parsers: ["babel", "flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================

View File

@ -27,4 +27,51 @@ a?.b[3].c?.(x).d.e?.f[3].g?.(y).h;
async function HelloWorld() {
var x = (await foo.bar.blah)?.hi;
a?.[await b];
(await x)?.();
}
a[b?.c].d();
a?.[b?.c].d();
a[b?.c]?.d();
a?.[b?.c]?.d();
(one?.fn());
(one?.two).fn();
(one.two?.fn());
(one.two?.three).fn();
(one.two?.three?.fn());
(one?.());
(one?.())();
(one?.())?.();
(one?.()).two;
a?.[b ? c : d];
(-1)?.toFixed();
(void fn)?.();
(a && b)?.();
(a ? b : c)?.();
(function(){})?.();
(() => f)?.();
(()=>f)?.x;
(a?.(x)).x;
(aaaaaaaaaaaaaaaaaaaaaaaa&&aaaaaaaaaaaaaaaaaaaaaaaa&&aaaaaaaaaaaaaaaaaaaaaaaa)?.();
let f = () => ({}?.());
let g = () => ({}?.b);
a = () => ({}?.() && a);
a = () => ({}?.()() && a);
a = () => ({}?.().b && a);
a = () => ({}?.b && a);
a = () => ({}?.b() && a);
(a) => ({}?.()?.b && 0);
(a) => ({}?.b?.b && 0);
(x) => ({}?.()());
(x) => ({}?.().b);
(x) => ({}?.b());
(x) => ({}?.b.b);
({}?.a().b());
({ a: 1 }?.entries());

View File

@ -1 +1 @@
run_spec(__dirname, ["babel", "flow"]);
run_spec(__dirname, ["babel", "flow", "typescript"]);

View File

@ -2,7 +2,7 @@
exports[`css-prop.js 1`] = `
====================================options=====================================
parsers: ["flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
@ -73,15 +73,15 @@ const TestComponent = ({ children, ...props }) => (
exports[`expressions.js 1`] = `
====================================options=====================================
parsers: ["flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
const long = \`long \${a//comment
const long1 = \`long \${a//comment
.b} long longlong \${a.b.c.d.e} long longlong \${a.b.c.d.e} long longlong \${a.b.c.d.e} long long\`;
const long = \`long \${a.b.c.d.e} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long long\`;
const long2 = \`long \${a.b.c.d.e} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long long\`;
const long = \`long long long long long long long long long long long \${a.b.c.d.e} long long long long long long long long long long long long long\`;
const long3 = \`long long long long long long long long long long long \${a.b.c.d.e} long long long long long long long long long long long long long\`;
const description =
\`The value of the \${cssName} css of the \${this._name} element\`;
@ -125,14 +125,14 @@ descirbe('something', () => {
throw new Error(\`pretty-format: Option "theme" has a key "\${key}" whose value "\${value}" is undefined in ansi-styles.\`,)
=====================================output=====================================
const long = \`long \${
const long1 = \`long \${
a.b //comment
} long longlong \${a.b.c.d.e} long longlong \${a.b.c.d.e} long longlong \${
a.b.c.d.e
} long long\`;
const long = \`long \${a.b.c.d.e} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long long\`;
const long2 = \`long \${a.b.c.d.e} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long longlong \${loooooooooooooooooong} long long\`;
const long = \`long long long long long long long long long long long \${a.b.c.d.e} long long long long long long long long long long long long long\`;
const long3 = \`long long long long long long long long long long long \${a.b.c.d.e} long long long long long long long long long long long long long\`;
const description = \`The value of the \${cssName} css of the \${this._name} element\`;
@ -193,7 +193,7 @@ throw new Error(
exports[`styled-components-with-expressions.js 1`] = `
====================================options=====================================
parsers: ["flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
@ -294,7 +294,7 @@ const header = css\`
exports[`styled-jsx.js 1`] = `
====================================options=====================================
parsers: ["flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
@ -484,7 +484,7 @@ const headerGlobal = css.global\`
exports[`styled-jsx-with-expressions.js 1`] = `
====================================options=====================================
parsers: ["flow"]
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================

View File

@ -1,8 +1,8 @@
const long = `long ${a//comment
const long1 = `long ${a//comment
.b} long longlong ${a.b.c.d.e} long longlong ${a.b.c.d.e} long longlong ${a.b.c.d.e} long long`;
const long = `long ${a.b.c.d.e} long longlong ${loooooooooooooooooong} long longlong ${loooooooooooooooooong} long longlong ${loooooooooooooooooong} long long`;
const long2 = `long ${a.b.c.d.e} long longlong ${loooooooooooooooooong} long longlong ${loooooooooooooooooong} long longlong ${loooooooooooooooooong} long long`;
const long = `long long long long long long long long long long long ${a.b.c.d.e} long long long long long long long long long long long long long`;
const long3 = `long long long long long long long long long long long ${a.b.c.d.e} long long long long long long long long long long long long long`;
const description =
`The value of the ${cssName} css of the ${this._name} element`;

View File

@ -1 +1 @@
run_spec(__dirname, ["flow"]);
run_spec(__dirname, ["babel", "flow", "typescript"]);

View File

@ -0,0 +1,68 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`index.ts 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
const assertString = (x: any): asserts x => {
console.assert(typeof x === 'string');
}
function assertsString(x: any): asserts x {
console.assert(typeof x === 'string');
}
const assertStringWithGuard = (x: any): asserts x is string => {
console.assert(typeof x === 'string');
}
function assertsStringWithGuard(x: any): asserts x is string {
console.assert(typeof x === 'string');
}
interface AssertFoo {
isString(node: any): asserts node;
}
class AssertsFoo {
isBar(): asserts this {
return;
}
isBaz = (): asserts this => {
return;
}
}
=====================================output=====================================
const assertString = (x: any): asserts x => {
console.assert(typeof x === "string");
};
function assertsString(x: any): asserts x {
console.assert(typeof x === "string");
}
const assertStringWithGuard = (x: any): asserts x is string => {
console.assert(typeof x === "string");
};
function assertsStringWithGuard(x: any): asserts x is string {
console.assert(typeof x === "string");
}
interface AssertFoo {
isString(node: any): asserts node;
}
class AssertsFoo {
isBar(): asserts this {
return;
}
isBaz = (): asserts this => {
return;
};
}
================================================================================
`;

View File

@ -0,0 +1,28 @@
const assertString = (x: any): asserts x => {
console.assert(typeof x === 'string');
}
function assertsString(x: any): asserts x {
console.assert(typeof x === 'string');
}
const assertStringWithGuard = (x: any): asserts x is string => {
console.assert(typeof x === 'string');
}
function assertsStringWithGuard(x: any): asserts x is string {
console.assert(typeof x === 'string');
}
interface AssertFoo {
isString(node: any): asserts node;
}
class AssertsFoo {
isBar(): asserts this {
return;
}
isBaz = (): asserts this => {
return;
}
}

View File

@ -0,0 +1 @@
run_spec(__dirname, ["typescript"]);

View File

@ -1,5 +1,25 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`declare_class_fields.ts 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
class B {p: number;}
class C extends B {declare p: 256 | 1000;}
=====================================output=====================================
class B {
p: number;
}
class C extends B {
declare p: 256 | 1000;
}
================================================================================
`;
exports[`declare_enum.ts 1`] = `
====================================options=====================================
parsers: ["typescript"]

View File

@ -0,0 +1,2 @@
class B {p: number;}
class C extends B {declare p: 256 | 1000;}

View File

@ -975,13 +975,16 @@
dependencies:
"@types/yargs-parser" "*"
"@typescript-eslint/typescript-estree@1.13.0":
version "1.13.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.13.0.tgz#8140f17d0f60c03619798f1d628b8434913dc32e"
integrity sha512-b5rCmd2e6DCC6tCTN9GSUAuxdYwCM/k/2wdjHGrIRGPSJotWMCe/dGpi66u42bhuh8q3QBzqM4TMA1GUUCJvdw==
"@typescript-eslint/typescript-estree@2.5.1-alpha.5":
version "2.5.1-alpha.5"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.5.1-alpha.5.tgz#7dc6a29bc55a89640378948894039933c9c370ea"
integrity sha512-R0bXoqvgLw2epTtCRjZZUo+vwGFqRqcQ54kd8Dcm+lVY7Mxp5Wf9CDunojkB2EGwwG0olbihJIRQI1GZaewBtg==
dependencies:
debug "^4.1.1"
glob "^7.1.4"
is-glob "^4.0.1"
lodash.unescape "4.0.1"
semver "5.5.0"
semver "^6.3.0"
"@webassemblyjs/ast@1.8.5":
version "1.8.5"
@ -2351,7 +2354,7 @@ debug@^3.1.0:
dependencies:
ms "2.0.0"
debug@^4.0.1:
debug@^4.0.1, debug@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==
@ -5254,6 +5257,7 @@ normalize-package-data@^2.3.2, normalize-package-data@^2.3.4:
normalize-path@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
normalize-path@^2.0.1, normalize-path@^2.1.1:
version "2.1.1"
@ -6477,11 +6481,7 @@ schema-utils@^2.4.1:
version "5.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004"
semver@5.5.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab"
semver@6.3.0, semver@^6.0.0, semver@^6.1.2:
semver@6.3.0, semver@^6.0.0, semver@^6.1.2, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
@ -7161,10 +7161,10 @@ typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
typescript@3.6.4:
version "3.6.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.6.4.tgz#b18752bb3792bc1a0281335f7f6ebf1bbfc5b91d"
integrity sha512-unoCll1+l+YK4i4F8f22TaNVPRHcD9PA3yCuZ8g5e0qGqlVlJ/8FSateOLLSagn+Yg5+ZwuPkL8LFUc0Jcvksg==
typescript@3.7.1-rc:
version "3.7.1-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.1-rc.tgz#2054b872d67f8dc732e36c1df397f9327f37ada0"
integrity sha512-2rMtWppLsaPvmpXsoIAXWDBQVnJMw1ITGGSnidMuayLj9iCmMRT69ncKZw/Mk5rXfJkilApKucWQZxproALoRw==
uglify-js@^3.1.4:
version "3.6.0"