Break on TypeScript parameter properties (#14402)

* add test for parameter properties

* break parameters for TypeScript parameter properties

ISSUE: #5666

* add a test pattern

* add changelog

* use getFunctionParameters

* Fix bad rebase

* Rename variables

* More tests

* Rename variable

* Fix snapshots

* Fix changelog

---------

Co-authored-by: fisker Cheung <lionkay@gmail.com>
Co-authored-by: Sosuke Suzuki <sosuke.suzuki@dr-ubie.com>
This commit is contained in:
authored and GitHub committed 2023-03-12 00:06:39 +09:00
1 parent b5210fd392
commit 921eaf4690
10 files changed
+246 -40

No files matched your search

+25
View File
@@ -0,0 +1,25 @@
#### Break on TypeScript parameter properties (#14402 by @seiyab)
<!-- prettier-ignore -->
```ts
// Input
class MyClass {
constructor(
protected x: number,
private y: string
) {}
}
// Prettier stable
class MyClass {
constructor(protected x: number, private y: string) {}
}
// Prettier main
class MyClass {
constructor(
protected x: number,
private y: string,
) {}
}
```
@@ -279,8 +279,17 @@ function isDecoratedFunction(path) {
);
}
function shouldBreakFunctionParameters(functionNode) {
const parameters = getFunctionParameters(functionNode);
return (
parameters.length > 1 &&
parameters.some((parameter) => parameter.type === "TSParameterProperty")
);
}
export {
printFunctionParameters,
shouldHugTheOnlyFunctionParameter,
shouldGroupFunctionParameters,
shouldBreakFunctionParameters,
};
+7 -1
View File
@@ -41,6 +41,7 @@ import { locEnd } from "../loc.js";
import {
printFunctionParameters,
shouldGroupFunctionParameters,
shouldBreakFunctionParameters,
} from "./function-parameters.js";
import { printPropertyKey } from "./property.js";
import { printFunctionTypeParameters, printDeclareToken } from "./misc.js";
@@ -171,6 +172,7 @@ function printMethodValue(path, options, print) {
const { node } = path;
const parametersDoc = printFunctionParameters(path, print, options);
const returnTypeDoc = printReturnType(path, print);
const shouldBreakParameters = shouldBreakFunctionParameters(node);
const shouldGroupParameters = shouldGroupFunctionParameters(
node,
returnTypeDoc
@@ -178,7 +180,11 @@ function printMethodValue(path, options, print) {
const parts = [
printFunctionTypeParameters(path, options, print),
group([
shouldGroupParameters ? group(parametersDoc) : parametersDoc,
shouldBreakParameters
? group(parametersDoc, { shouldBreak: true })
: shouldGroupParameters
? group(parametersDoc)
: parametersDoc,
returnTypeDoc,
]),
];
@@ -2213,174 +2213,222 @@ exports[`snippet: #163 [typescript] format 1`] = `
`;
exports[`snippet: #164 [babel-ts] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:28)
> 1 | class Foo {["constructor"](private parameter) {}}
| ^"
`;
exports[`snippet: #164 [typescript] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:28)
> 1 | class Foo {["constructor"](private parameter) {}}
| ^^^^^^^"
`;
exports[`snippet: #165 [babel-ts] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:28)
> 1 | class Foo {['constructor'](private parameter) {}}
| ^"
`;
exports[`snippet: #165 [typescript] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:28)
> 1 | class Foo {['constructor'](private parameter) {}}
| ^^^^^^^"
`;
exports[`snippet: #166 [babel-ts] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:28)
> 1 | class Foo {[\`constructor\`](private parameter) {}}
| ^"
`;
exports[`snippet: #166 [typescript] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:28)
> 1 | class Foo {[\`constructor\`](private parameter) {}}
| ^^^^^^^"
`;
exports[`snippet: #167 [babel-ts] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:33)
> 1 | class Foo {['const' + 'ructor'](private parameter) {}}
| ^"
`;
exports[`snippet: #167 [typescript] format 1`] = `
"A parameter property is only allowed in a constructor implementation. (1:33)
> 1 | class Foo {['const' + 'ructor'](private parameter) {}}
| ^^^^^^^"
`;
exports[`snippet: #168 [babel-ts] format 1`] = `
"'abstract' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {abstract bar};
| ^"
`;
exports[`snippet: #164 [typescript] format 1`] = `
exports[`snippet: #168 [typescript] format 1`] = `
"'abstract' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {abstract bar};
| ^^^^^^^^"
`;
exports[`snippet: #165 [babel-ts] format 1`] = `
exports[`snippet: #169 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:22)
> 1 | type Foo = {accessor bar};
| ^"
`;
exports[`snippet: #165 [typescript] format 1`] = `
exports[`snippet: #169 [typescript] format 1`] = `
"'accessor' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {accessor bar};
| ^^^^^^^^"
`;
exports[`snippet: #166 [babel-ts] format 1`] = `
exports[`snippet: #170 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:19)
> 1 | type Foo = {async bar};
| ^"
`;
exports[`snippet: #166 [typescript] format 1`] = `
exports[`snippet: #170 [typescript] format 1`] = `
"'async' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {async bar};
| ^^^^^"
`;
exports[`snippet: #167 [babel-ts] format 1`] = `
exports[`snippet: #171 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:19)
> 1 | type Foo = {const bar};
| ^"
`;
exports[`snippet: #167 [typescript] format 1`] = `
exports[`snippet: #171 [typescript] format 1`] = `
"';' expected. (1:19)
> 1 | type Foo = {const bar};
| ^"
`;
exports[`snippet: #168 [babel-ts] format 1`] = `
exports[`snippet: #172 [babel-ts] format 1`] = `
"'declare' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {declare bar};
| ^"
`;
exports[`snippet: #168 [typescript] format 1`] = `
exports[`snippet: #172 [typescript] format 1`] = `
"'declare' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {declare bar};
| ^^^^^^^"
`;
exports[`snippet: #169 [babel-ts] format 1`] = `
exports[`snippet: #173 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:21)
> 1 | type Foo = {default bar};
| ^"
`;
exports[`snippet: #169 [typescript] format 1`] = `
exports[`snippet: #173 [typescript] format 1`] = `
"';' expected. (1:21)
> 1 | type Foo = {default bar};
| ^"
`;
exports[`snippet: #170 [babel-ts] format 1`] = `
exports[`snippet: #174 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:20)
> 1 | type Foo = {export bar};
| ^"
`;
exports[`snippet: #170 [typescript] format 1`] = `
exports[`snippet: #174 [typescript] format 1`] = `
"'export' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {export bar};
| ^^^^^^"
`;
exports[`snippet: #171 [babel-ts] format 1`] = `
exports[`snippet: #175 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:16)
> 1 | type Foo = {in bar};
| ^"
`;
exports[`snippet: #171 [typescript] format 1`] = `
exports[`snippet: #175 [typescript] format 1`] = `
"'in' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {in bar};
| ^^"
`;
exports[`snippet: #172 [babel-ts] format 1`] = `
exports[`snippet: #176 [babel-ts] format 1`] = `
"Unexpected token, expected ";" (1:17)
> 1 | type Foo = {out bar};
| ^"
`;
exports[`snippet: #172 [typescript] format 1`] = `
exports[`snippet: #176 [typescript] format 1`] = `
"'out' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {out bar};
| ^^^"
`;
exports[`snippet: #173 [babel-ts] format 1`] = `
exports[`snippet: #177 [babel-ts] format 1`] = `
"'override' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {override bar};
| ^"
`;
exports[`snippet: #173 [typescript] format 1`] = `
exports[`snippet: #177 [typescript] format 1`] = `
"'override' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {override bar};
| ^^^^^^^^"
`;
exports[`snippet: #174 [babel-ts] format 1`] = `
exports[`snippet: #178 [babel-ts] format 1`] = `
"'private' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {private bar};
| ^"
`;
exports[`snippet: #174 [typescript] format 1`] = `
exports[`snippet: #178 [typescript] format 1`] = `
"'private' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {private bar};
| ^^^^^^^"
`;
exports[`snippet: #175 [babel-ts] format 1`] = `
exports[`snippet: #179 [babel-ts] format 1`] = `
"'protected' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {protected bar};
| ^"
`;
exports[`snippet: #175 [typescript] format 1`] = `
exports[`snippet: #179 [typescript] format 1`] = `
"'protected' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {protected bar};
| ^^^^^^^^^"
`;
exports[`snippet: #176 [babel-ts] format 1`] = `
exports[`snippet: #180 [babel-ts] format 1`] = `
"'public' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {public bar};
| ^"
`;
exports[`snippet: #176 [typescript] format 1`] = `
exports[`snippet: #180 [typescript] format 1`] = `
"'public' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {public bar};
| ^^^^^^"
`;
exports[`snippet: #177 [babel-ts] format 1`] = `
exports[`snippet: #181 [babel-ts] format 1`] = `
"'static' modifier cannot appear on a type member. (1:13)
> 1 | type Foo = {static bar};
| ^"
`;
exports[`snippet: #177 [typescript] format 1`] = `
exports[`snippet: #181 [typescript] format 1`] = `
"'static' modifier cannot appear on a type member (1:13)
> 1 | type Foo = {static bar};
| ^^^^^^"
`;
exports[`snippet: #178 [babel-ts] format 1`] = `
exports[`snippet: #182 [babel-ts] format 1`] = `
"Index signatures cannot have the 'declare' modifier. (2:3)
1 | class Foo {
> 2 | declare [index: string]: number
@@ -2388,7 +2436,7 @@ exports[`snippet: #178 [babel-ts] format 1`] = `
3 | }"
`;
exports[`snippet: #178 [typescript] format 1`] = `
exports[`snippet: #182 [typescript] format 1`] = `
"'declare' modifier cannot appear on an index signature (2:3)
1 | class Foo {
> 2 | declare [index: string]: number
@@ -103,6 +103,11 @@ run_spec(
).map(
(modifier) => `class Foo { constructor(${modifier} parameter) {} }`
),
'class Foo {["constructor"](private parameter) {}}',
"class Foo {['constructor'](private parameter) {}}",
"class Foo {[`constructor`](private parameter) {}}",
// cspell:disable-next-line
"class Foo {['const' + 'ructor'](private parameter) {}}",
// `TSPropertySignature`
...POSSIBLE_MODIFIERS.filter((modifier) => modifier !== "readonly").map(
@@ -450,6 +450,65 @@ class A {
================================================================================
`;
exports[`parameter-properties.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
printWidth: 80
| printWidth
=====================================input======================================
class MyClass {
constructor(protected x: number, private y: string) {
}
}
[
class {
"constructor"(protected x: number, private y: string) {
}
},
]
class Mixed {
constructor(public a: number, b: unknown) {
}
}
class OneParameterProperty {
constructor(public foobar: boolean) {
}
}
=====================================output=====================================
class MyClass {
constructor(
protected x: number,
private y: string,
) {}
}
[
class {
constructor(
protected x: number,
private y: string,
) {}
},
];
class Mixed {
constructor(
public a: number,
b: unknown,
) {}
}
class OneParameterProperty {
constructor(public foobar: boolean) {}
}
================================================================================
`;
exports[`quoted-property.ts format 1`] = `
====================================options=====================================
parsers: ["typescript"]
@@ -0,0 +1,21 @@
class MyClass {
constructor(protected x: number, private y: string) {
}
}
[
class {
"constructor"(protected x: number, private y: string) {
}
},
]
class Mixed {
constructor(public a: number, b: unknown) {
}
}
class OneParameterProperty {
constructor(public foobar: boolean) {
}
}
@@ -348,11 +348,18 @@ class Thing3 extends Thing2 {
type Constructor<T> = new (...args: any[]) => T;
class Base {
constructor(public x: number, public y: number) {}
constructor(
public x: number,
public y: number,
) {}
}
class Derived extends Base {
constructor(x: number, y: number, public z: number) {
constructor(
x: number,
y: number,
public z: number,
) {
super(x, y);
}
}
@@ -485,11 +492,18 @@ const Timestamped = <CT extends Constructor<object>>(Base: CT) => {
type Constructor<T> = new (...args: any[]) => T;
class Base {
constructor(public x: number, public y: number) {}
constructor(
public x: number,
public y: number,
) {}
}
class Derived extends Base {
constructor(x: number, y: number, public z: number) {
constructor(
x: number,
y: number,
public z: number,
) {
super(x, y);
}
}
@@ -120,7 +120,10 @@ class C {
class D<T, U> {
constructor(x: T, y: U);
constructor(x: T = 1, public y: U = x) {
constructor(
x: T = 1,
public y: U = x,
) {
var z = x;
}
}
@@ -235,7 +238,10 @@ var r4 = d.z; // error
=====================================output=====================================
class C {
y: string;
constructor(private x: string, protected z: string) {}
constructor(
private x: string,
protected z: string,
) {}
}
var c: C;
@@ -245,7 +251,11 @@ var r3 = c.z; // error
class D<T> {
y: T;
constructor(a: T, private x: T, protected z: T) {}
constructor(
a: T,
private x: T,
protected z: T,
) {}
}
var d: D<string>;
@@ -128,7 +128,10 @@ var p: M.D.Point;
module A {
export var x = "hello world";
export class Point {
constructor(public x: number, public y: number) {}
constructor(
public x: number,
public y: number,
) {}
}
export module B {
export interface Id {
@@ -153,7 +156,10 @@ module X {
export module Y {
export class Point {
constructor(public x: number, public y: number) {}
constructor(
public x: number,
public y: number,
) {}
}
}
}
@@ -261,7 +267,10 @@ var p: { x: number; y: number; };
=====================================output=====================================
module moduleA {
export class Point {
constructor(public x: number, public y: number) {}
constructor(
public x: number,
public y: number,
) {}
}
}