Improve super class (or single heritage) breaking (#18325)
This commit is contained in:
1 parent
bbdec54a41
commit
6ba133e80c
10 files changed
+337
-12
No files matched your search
@@ -0,0 +1,15 @@
|
|||||||
|
#### Improve super class format (#18325 by @fisker)
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
```jsx
|
||||||
|
// Input
|
||||||
|
class EnsureNoDisposablesAreLeakedInTestSuiteSuite extends eslint.Rule.RuleModule {};
|
||||||
|
|
||||||
|
// Prettier stable
|
||||||
|
class EnsureNoDisposablesAreLeakedInTestSuiteSuite extends eslint.Rule
|
||||||
|
.RuleModule {}
|
||||||
|
|
||||||
|
// Prettier main
|
||||||
|
class EnsureNoDisposablesAreLeakedInTestSuiteSuite
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
```
|
||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
CommentCheckFlags,
|
CommentCheckFlags,
|
||||||
createTypeCheckFunction,
|
createTypeCheckFunction,
|
||||||
hasComment,
|
hasComment,
|
||||||
|
isMemberExpression,
|
||||||
} from "../utils/index.js";
|
} from "../utils/index.js";
|
||||||
import { printAssignment } from "./assignment.js";
|
import { printAssignment } from "./assignment.js";
|
||||||
import { printClassMemberDecorators } from "./decorators.js";
|
import { printClassMemberDecorators } from "./decorators.js";
|
||||||
@@ -67,11 +68,7 @@ function printClass(path, options, print) {
|
|||||||
|
|
||||||
// Keep old behaviour of extends in same line
|
// Keep old behaviour of extends in same line
|
||||||
// If there is only on extends and there are not comments
|
// If there is only on extends and there are not comments
|
||||||
const groupMode =
|
const groupMode = shouldPrintClassInGroupMode(path);
|
||||||
hasComment(node.id, CommentCheckFlags.Trailing) ||
|
|
||||||
hasComment(node.typeParameters, CommentCheckFlags.Trailing) ||
|
|
||||||
hasComment(node.superClass) ||
|
|
||||||
hasMultipleHeritage(node);
|
|
||||||
|
|
||||||
const partsGroup = [];
|
const partsGroup = [];
|
||||||
const extendsParts = [];
|
const extendsParts = [];
|
||||||
@@ -110,14 +107,12 @@ function printClass(path, options, print) {
|
|||||||
extendsParts.push(" ", printedWithComments);
|
extendsParts.push(" ", printedWithComments);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
extendsParts.push(
|
extendsParts.push(printHeritageClauses(path, options, print, "extends"));
|
||||||
printHeritageClauses(path, options, print, "extends", groupMode),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extendsParts.push(
|
extendsParts.push(
|
||||||
printHeritageClauses(path, options, print, "mixins", groupMode),
|
printHeritageClauses(path, options, print, "mixins"),
|
||||||
printHeritageClauses(path, options, print, "implements", groupMode),
|
printHeritageClauses(path, options, print, "implements"),
|
||||||
);
|
);
|
||||||
|
|
||||||
let heritageGroupId;
|
let heritageGroupId;
|
||||||
@@ -170,7 +165,65 @@ function hasMultipleHeritage(node) {
|
|||||||
return count > 1;
|
return count > 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function printHeritageClauses(path, options, print, listName, groupMode) {
|
/**
|
||||||
|
@returns {boolean}
|
||||||
|
*/
|
||||||
|
function shouldPrintClassInGroupModeWithoutCache(path) {
|
||||||
|
const { node } = path;
|
||||||
|
if (
|
||||||
|
hasComment(node.id, CommentCheckFlags.Trailing) ||
|
||||||
|
hasComment(node.typeParameters, CommentCheckFlags.Trailing) ||
|
||||||
|
hasComment(node.superClass) ||
|
||||||
|
hasMultipleHeritage(node)
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.superClass) {
|
||||||
|
if (path.parent.type === "AssignmentExpression") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const superTypeArguments =
|
||||||
|
node.superTypeArguments ?? node.superTypeParameters;
|
||||||
|
|
||||||
|
return !superTypeArguments && isMemberExpression(node.superClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
const heritage =
|
||||||
|
node.extends?.[0] ?? node.mixins?.[0] ?? node.implements?.[0];
|
||||||
|
|
||||||
|
if (!heritage) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const groupMode =
|
||||||
|
// `ClassImplements` seem not allow `QualifiedTypeIdentifier`
|
||||||
|
(heritage.type === "InterfaceExtends" &&
|
||||||
|
heritage.id.type === "QualifiedTypeIdentifier" &&
|
||||||
|
!heritage.typeParameters) ||
|
||||||
|
((heritage.type === "TSClassImplements" ||
|
||||||
|
heritage.type === "TSInterfaceHeritage") &&
|
||||||
|
isMemberExpression(heritage.expression) &&
|
||||||
|
!heritage.typeArguments);
|
||||||
|
|
||||||
|
return groupMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldPrintClassInGroupModeCache = new WeakMap();
|
||||||
|
function shouldPrintClassInGroupMode(path) {
|
||||||
|
const { node } = path;
|
||||||
|
if (!shouldPrintClassInGroupModeCache.has(node)) {
|
||||||
|
shouldPrintClassInGroupModeCache.set(
|
||||||
|
node,
|
||||||
|
shouldPrintClassInGroupModeWithoutCache(path),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return shouldPrintClassInGroupModeCache.get(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
function printHeritageClauses(path, options, print, listName) {
|
||||||
const { node } = path;
|
const { node } = path;
|
||||||
if (!isNonEmptyArray(node[listName])) {
|
if (!isNonEmptyArray(node[listName])) {
|
||||||
return "";
|
return "";
|
||||||
@@ -189,7 +242,7 @@ function printHeritageClauses(path, options, print, listName, groupMode) {
|
|||||||
printedLeadingComments,
|
printedLeadingComments,
|
||||||
heritageClausesDoc,
|
heritageClausesDoc,
|
||||||
];
|
];
|
||||||
if (groupMode) {
|
if (shouldPrintClassInGroupMode(path)) {
|
||||||
return [line, group(printed)];
|
return [line, group(printed)];
|
||||||
}
|
}
|
||||||
return [" ", printed];
|
return [" ", printed];
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||||
|
|
||||||
|
exports[`member-expression-like.js format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["flow"]
|
||||||
|
printWidth: 80
|
||||||
|
| printWidth
|
||||||
|
=====================================input======================================
|
||||||
|
class A_long_long_long_long_long_long_long_long_name1
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class Short
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name12
|
||||||
|
extends eslint.Rule?.RuleModule {}
|
||||||
|
|
||||||
|
interface A_long_long_long_long_long_long_long_long_name2
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
declare class A_long_long_long_long_long_long_long_long_name2
|
||||||
|
mixins eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
declare class A_long_long_long_long_long_long_long_long_name3
|
||||||
|
extends eslint.Rule.RuleModule
|
||||||
|
mixins eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
class A_long_long_long_long_long_long_long_long_name1
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class Short extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name12
|
||||||
|
extends eslint.Rule?.RuleModule {}
|
||||||
|
|
||||||
|
interface A_long_long_long_long_long_long_long_long_name2
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
declare class A_long_long_long_long_long_long_long_long_name2
|
||||||
|
mixins eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
declare class A_long_long_long_long_long_long_long_long_name3
|
||||||
|
extends eslint.Rule.RuleModule
|
||||||
|
mixins eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`type-arguments.js format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["flow"]
|
||||||
|
printWidth: 80
|
||||||
|
| printWidth
|
||||||
|
=====================================input======================================
|
||||||
|
class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
interface CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox mixins React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
class CommentBox extends React.Component<
|
||||||
|
{ url: string, pollInterval: number },
|
||||||
|
CommentData,
|
||||||
|
> {}
|
||||||
|
|
||||||
|
interface CommentBox extends React.Component<
|
||||||
|
{ url: string, pollInterval: number },
|
||||||
|
CommentData,
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox extends React.Component<
|
||||||
|
{ url: string, pollInterval: number },
|
||||||
|
CommentData,
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox mixins React.Component<
|
||||||
|
{ url: string, pollInterval: number },
|
||||||
|
CommentData,
|
||||||
|
> {}
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
runFormatTest(import.meta, ["flow"]);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class A_long_long_long_long_long_long_long_long_name1
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class Short
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name12
|
||||||
|
extends eslint.Rule?.RuleModule {}
|
||||||
|
|
||||||
|
interface A_long_long_long_long_long_long_long_long_name2
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
declare class A_long_long_long_long_long_long_long_long_name2
|
||||||
|
mixins eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
declare class A_long_long_long_long_long_long_long_long_name3
|
||||||
|
extends eslint.Rule.RuleModule
|
||||||
|
mixins eslint.Rule.RuleModule {}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
interface CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox mixins React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||||
|
|
||||||
|
exports[`member-expression-like.ts format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["typescript"]
|
||||||
|
printWidth: 80
|
||||||
|
| printWidth
|
||||||
|
=====================================input======================================
|
||||||
|
class A_long_long_long_long_long_long_long_long_name1
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class Short
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name12
|
||||||
|
extends eslint.Rule?.RuleModule {}
|
||||||
|
|
||||||
|
interface A_long_long_long_long_long_long_long_long_name2
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name2
|
||||||
|
implements eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name3
|
||||||
|
extends eslint.Rule.RuleModule
|
||||||
|
implements eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
class A_long_long_long_long_long_long_long_long_name1
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class Short extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name12
|
||||||
|
extends eslint.Rule?.RuleModule {}
|
||||||
|
|
||||||
|
interface A_long_long_long_long_long_long_long_long_name2
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name2
|
||||||
|
implements eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name3
|
||||||
|
extends eslint.Rule.RuleModule
|
||||||
|
implements eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`type-arguments.ts format 1`] = `
|
||||||
|
====================================options=====================================
|
||||||
|
parsers: ["typescript"]
|
||||||
|
printWidth: 80
|
||||||
|
| printWidth
|
||||||
|
=====================================input======================================
|
||||||
|
class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
interface CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox implements React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
=====================================output=====================================
|
||||||
|
class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
interface CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox implements React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
================================================================================
|
||||||
|
`;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
runFormatTest(import.meta, ["typescript"]);
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
class A_long_long_long_long_long_long_long_long_name1
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class Short
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name12
|
||||||
|
extends eslint.Rule?.RuleModule {}
|
||||||
|
|
||||||
|
interface A_long_long_long_long_long_long_long_long_name2
|
||||||
|
extends eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name2
|
||||||
|
implements eslint.Rule.RuleModule {}
|
||||||
|
|
||||||
|
class A_long_long_long_long_long_long_long_long_name3
|
||||||
|
extends eslint.Rule.RuleModule
|
||||||
|
implements eslint.Rule.RuleModule {}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
interface CommentBox extends React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
|
|
||||||
|
declare class CommentBox implements React.Component<
|
||||||
|
{ url: string; pollInterval: number },
|
||||||
|
CommentData
|
||||||
|
> {}
|
||||||
Reference in new issue
Block a user