Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TypeScript] format TSAsExpression with same logic as BinaryExpression #7869

Merged
merged 17 commits into from Mar 31, 2020
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions changelog_unreleased/typescript/pr-7869.md
@@ -0,0 +1,14 @@
#### Wrap TSAsExpression ([#7869](https://github.com/prettier/prettier/pull/7869) by [@sosukesuzuki](https://github.com/sosukesuzuki))

<!-- prettier-ignore -->
```ts
// Input
const varibale = foooooooooooooooooooooooooooooooooooooooooooooooooooo as SomeType;

// Prettier stable
const varibale = foooooooooooooooooooooooooooooooooooooooooooooooooooo as SomeType;

// Prettier master
const varibale =
foooooooooooooooooooooooooooooooooooooooooooooooooooo as SomeType;
```
56 changes: 34 additions & 22 deletions src/language-js/printer-estree.js
Expand Up @@ -553,7 +553,11 @@ function printPathNoParens(path, options, print, args) {
);
case "BinaryExpression":
case "LogicalExpression":
case "NGPipeExpression": {
case "NGPipeExpression":
case "TSAsExpression": {
const leftNodeName = n.type === "TSAsExpression" ? "expression" : "left";
const rightNodeName =
n.type === "TSAsExpression" ? "typeAnnotation" : "right";
thorn0 marked this conversation as resolved.
Show resolved Hide resolved
const parent = path.getParentNode();
const parentParent = path.getParentNode(1);
const isInsideParenthesis =
Expand Down Expand Up @@ -639,7 +643,8 @@ function printPathNoParens(path, options, print, args) {
parent.type === "Property";

const samePrecedenceSubExpression =
isBinaryish(n.left) && shouldFlatten(n.operator, n.left.operator);
isBinaryish(n[leftNodeName]) &&
shouldFlatten(n.operator, n[leftNodeName].operator);

if (
shouldNotIndent ||
Expand All @@ -662,7 +667,7 @@ function printPathNoParens(path, options, print, args) {
// </Foo>
// )

const hasJSX = isJSXNode(n.right);
const hasJSX = isJSXNode(n[rightNodeName]);
const rest = concat(hasJSX ? parts.slice(1, -1) : parts.slice(1));

const groupId = Symbol("logicalChain-" + ++uid);
Expand Down Expand Up @@ -2491,7 +2496,6 @@ function printPathNoParens(path, options, print, args) {
n.expressions[i].type === "OptionalMemberExpression" ||
n.expressions[i].type === "ConditionalExpression" ||
n.expressions[i].type === "SequenceExpression" ||
n.expressions[i].type === "TSAsExpression" ||
isBinaryish(n.expressions[i])
) {
printed = concat([indent(concat([softline, printed])), softline]);
Expand Down Expand Up @@ -3192,12 +3196,6 @@ function printPathNoParens(path, options, print, args) {
return "unknown";
case "TSVoidKeyword":
return "void";
case "TSAsExpression":
return concat([
path.call(print, "expression"),
" as ",
path.call(print, "typeAnnotation"),
]);
case "TSArrayType":
return concat([path.call(print, "elementType"), "[]"]);
case "TSPropertySignature": {
Expand Down Expand Up @@ -5715,8 +5713,12 @@ function printBinaryishExpressions(
let parts = [];
const node = path.getValue();

// We treat BinaryExpression and LogicalExpression nodes the same.
// We treat BinaryExpression, LogicalExpression, NGPipeExpression and TSAsExpression the same.
if (isBinaryish(node)) {
const leftNodeName = node.type === "TSAsExpression" ? "expression" : "left";
const rightNodeName =
node.type === "TSAsExpression" ? "typeAnnotation" : "right";
thorn0 marked this conversation as resolved.
Show resolved Hide resolved

// Put all operators with the same precedence level in the same
// group. The reason we only need to do this with the `left`
// expression is because given an expression like `1 + 2 - 3`, it
Expand All @@ -5726,7 +5728,7 @@ function printBinaryishExpressions(
// precedence level and should be treated as a separate group, so
// print them normally. (This doesn't hold for the `**` operator,
// which is unique in that it is right-associative.)
if (shouldFlatten(node.operator, node.left.operator)) {
if (shouldFlatten(node.operator, node[leftNodeName].operator)) {
// Flatten them out by recursively calling this function.
parts = parts.concat(
path.call(
Expand All @@ -5738,21 +5740,31 @@ function printBinaryishExpressions(
/* isNested */ true,
isInsideParenthesis
),
"left"
leftNodeName
)
);
} else {
parts.push(path.call(print, "left"));
parts.push(path.call(print, leftNodeName));
}

const operator =
node.type === "NGPipeExpression"
? "|"
: node.type === "TSAsExpression"
? "as"
: node.operator;

const shouldInline = shouldInlineLogicalExpression(node);
const lineBeforeOperator =
(node.operator === "|>" ||
(operator === "|>" ||
node.type === "NGPipeExpression" ||
(node.operator === "|" && options.parser === "__vue_expression")) &&
!hasLeadingOwnLineComment(options.originalText, node.right, options);
(operator === "|" && options.parser === "__vue_expression")) &&
!hasLeadingOwnLineComment(
options.originalText,
node[rightNodeName],
options
);

const operator = node.type === "NGPipeExpression" ? "|" : node.operator;
const rightSuffix =
node.type === "NGPipeExpression" && node.arguments.length !== 0
? group(
Expand All @@ -5772,12 +5784,12 @@ function printBinaryishExpressions(
: "";

const right = shouldInline
? concat([operator, " ", path.call(print, "right"), rightSuffix])
? concat([operator, " ", path.call(print, rightNodeName), rightSuffix])
: concat([
lineBeforeOperator ? softline : "",
operator,
lineBeforeOperator ? " " : line,
path.call(print, "right"),
path.call(print, rightNodeName),
rightSuffix,
]);

Expand All @@ -5787,8 +5799,8 @@ function printBinaryishExpressions(
const shouldGroup =
!(isInsideParenthesis && node.type === "LogicalExpression") &&
parent.type !== node.type &&
node.left.type !== node.type &&
node.right.type !== node.type;
node[leftNodeName].type !== node.type &&
node[rightNodeName].type !== node.type;

parts.push(" ", shouldGroup ? group(right) : right);

Expand Down
1 change: 1 addition & 0 deletions src/language-js/utils.js
Expand Up @@ -289,6 +289,7 @@ const binaryishNodeTypes = new Set([
"BinaryExpression",
"LogicalExpression",
"NGPipeExpression",
"TSAsExpression",
]);
function isBinaryish(node) {
return binaryishNodeTypes.has(node.type);
Expand Down
Expand Up @@ -41,7 +41,7 @@ const bar8 = [1,2,3].reduce((carry, value) => {
=====================================output=====================================
const bar1 = [1, 2, 3].reduce((carry, value) => {
return [...carry, value];
}, ([] as unknown) as number[]);
}, [] as unknown as number[]);

const bar2 = [1, 2, 3].reduce((carry, value) => {
return [...carry, value];
Expand All @@ -51,7 +51,7 @@ const bar3 = [1, 2, 3].reduce(
(carry, value) => {
return [...carry, value];
},
([1, 2, 3] as unknown) as number[]
[1, 2, 3] as unknown as number[]
thorn0 marked this conversation as resolved.
Show resolved Hide resolved
);

const bar4 = [1, 2, 3].reduce(
Expand All @@ -63,7 +63,7 @@ const bar4 = [1, 2, 3].reduce(

const bar5 = [1, 2, 3].reduce((carry, value) => {
return { ...carry, [value]: true };
}, ({} as unknown) as { [key: number]: boolean });
}, {} as unknown as { [key: number]: boolean });

const bar6 = [1, 2, 3].reduce((carry, value) => {
return { ...carry, [value]: true };
Expand All @@ -73,7 +73,7 @@ const bar7 = [1, 2, 3].reduce(
(carry, value) => {
return { ...carry, [value]: true };
},
({ 1: true } as unknown) as { [key: number]: boolean }
{ 1: true } as unknown as { [key: number]: boolean }
);

const bar8 = [1, 2, 3].reduce(
Expand Down
65 changes: 52 additions & 13 deletions tests/typescript_as/__snapshots__/jsfmt.spec.js.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`as.js 1`] = `
exports[`as.ts 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
Expand All @@ -9,9 +9,12 @@ printWidth: 80
const name = (description as DescriptionObject).name || (description as string);
this.isTabActionBar((e.target || e.srcElement) as HTMLElement);
(originalError ? wrappedError(errMsg, originalError) : Error(errMsg)) as InjectionError;
'current' in (props.pagination as Object)
start + (yearSelectTotal as number)
scrollTop > (visibilityHeight as number)
'current' in (props.pagination as Object);
('current' in props.pagination) as Object;
start + (yearSelectTotal as number);
(start + yearSelectTotal) as number;
scrollTop > (visibilityHeight as number);
(scrollTop > visibilityHeight) as number;
export default class Column<T> extends (RcTable.Column as React.ComponentClass<ColumnProps<T>,ColumnProps<T>,ColumnProps<T>,ColumnProps<T>>) {}
export const MobxTypedForm = class extends (Form as { new (): any }) {}
export abstract class MobxTypedForm1 extends (Form as { new (): any }) {}
Expand All @@ -35,22 +38,33 @@ const state = JSON.stringify({
(bValue as boolean) ? 0 : -1;
<boolean>bValue ? 0 : -1;
const value1 = thisIsAReallyReallyReallyReallyReallyLongIdentifier as SomeInterface;
const value2 = thisIsAnIdentifier as thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongInterface;
const value3 = thisIsAReallyLongIdentifier as (SomeInterface | SomeOtherInterface);
const value4 = thisIsAReallyLongIdentifier as { prop1: string, prop2: number, prop3: number }[];
const value5 = thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyLongIdentifier as [string, number];
const iter1 = createIterator(this.controller, child, this.tag as SyncFunctionComponent);
const iter2 = createIterator(self.controller, child, self.tag as SyncFunctionComponent);
=====================================output=====================================
const name = (description as DescriptionObject).name || (description as string);
this.isTabActionBar((e.target || e.srcElement) as HTMLElement);
(originalError
? wrappedError(errMsg, originalError)
: Error(errMsg)) as InjectionError;
(originalError ? wrappedError(errMsg, originalError) : Error(errMsg)) as
InjectionError;
"current" in (props.pagination as Object);
("current" in props.pagination) as Object;
start + (yearSelectTotal as number);
(start + yearSelectTotal) as number;
scrollTop > (visibilityHeight as number);
export default class Column<T> extends (RcTable.Column as React.ComponentClass<
ColumnProps<T>,
ColumnProps<T>,
ColumnProps<T>,
ColumnProps<T>
>) {}
(scrollTop > visibilityHeight) as number;
export default class Column<T> extends (RcTable.Column as
React.ComponentClass<
ColumnProps<T>,
ColumnProps<T>,
ColumnProps<T>,
ColumnProps<T>
>) {}
export const MobxTypedForm = class extends (Form as { new (): any }) {};
export abstract class MobxTypedForm1 extends (Form as { new (): any }) {}
({} as {});
Expand All @@ -73,6 +87,31 @@ const state = JSON.stringify({
(bValue as boolean) ? 0 : -1;
<boolean>bValue ? 0 : -1;
const value1 =
thisIsAReallyReallyReallyReallyReallyLongIdentifier as SomeInterface;
const value2 =
thisIsAnIdentifier as
thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongInterface;
const value3 =
thisIsAReallyLongIdentifier as SomeInterface | SomeOtherInterface;
const value4 =
thisIsAReallyLongIdentifier as
{ prop1: string; prop2: number; prop3: number }[];
const value5 =
thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyLongIdentifier as
[string, number];
const iter1 = createIterator(
this.controller,
child,
this.tag as SyncFunctionComponent
);
const iter2 = createIterator(
self.controller,
child,
self.tag as SyncFunctionComponent
);
================================================================================
`;
Expand Down
29 changes: 0 additions & 29 deletions tests/typescript_as/as.js

This file was deleted.

40 changes: 40 additions & 0 deletions tests/typescript_as/as.ts
@@ -0,0 +1,40 @@
const name = (description as DescriptionObject).name || (description as string);
this.isTabActionBar((e.target || e.srcElement) as HTMLElement);
(originalError ? wrappedError(errMsg, originalError) : Error(errMsg)) as InjectionError;
'current' in (props.pagination as Object);
('current' in props.pagination) as Object;
start + (yearSelectTotal as number);
(start + yearSelectTotal) as number;
scrollTop > (visibilityHeight as number);
(scrollTop > visibilityHeight) as number;
export default class Column<T> extends (RcTable.Column as React.ComponentClass<ColumnProps<T>,ColumnProps<T>,ColumnProps<T>,ColumnProps<T>>) {}
export const MobxTypedForm = class extends (Form as { new (): any }) {}
export abstract class MobxTypedForm1 extends (Form as { new (): any }) {}
({}) as {};
function*g() {
const test = (yield 'foo') as number;
}
async function g1() {
const test = (await 'foo') as number;
}
({}) as X;
() => ({}) as X;
const state = JSON.stringify({
next: window.location.href,
nonce,
} as State);

(foo.bar as Baz) = [bar];
(foo.bar as any)++;

(bValue as boolean) ? 0 : -1;
<boolean>bValue ? 0 : -1;

const value1 = thisIsAReallyReallyReallyReallyReallyLongIdentifier as SomeInterface;
const value2 = thisIsAnIdentifier as thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyReallyLongInterface;
const value3 = thisIsAReallyLongIdentifier as (SomeInterface | SomeOtherInterface);
const value4 = thisIsAReallyLongIdentifier as { prop1: string, prop2: number, prop3: number }[];
const value5 = thisIsAReallyReallyReallyReallyReallyReallyReallyReallyReallyLongIdentifier as [string, number];

const iter1 = createIterator(this.controller, child, this.tag as SyncFunctionComponent);
const iter2 = createIterator(self.controller, child, self.tag as SyncFunctionComponent);
Expand Up @@ -25,7 +25,8 @@ const b = \`\${
}\`;
const b = \`\${
(veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongFoo +
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongBar) as veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongBaz
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongBar) as
veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongBaz
}\`;

================================================================================
Expand Down
6 changes: 2 additions & 4 deletions tests/typescript_union/__snapshots__/jsfmt.spec.js.snap
Expand Up @@ -379,10 +379,8 @@ type State = {
| { discriminant: "BAZ"; baz: any }
);

const foo1 = [abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (
| string
| undefined
)[];
const foo1 =
[abc, def, ghi, jkl, mno, pqr, stu, vwx, yz] as (string | undefined)[];

const foo2: (
| AAAAAAAAAAAAAAAAAAAAAA
Expand Down