Extract printClassBody (#14191)
This commit is contained in:
1 parent
9e85502107
commit
bca85bb5cd
4 files changed
+146
-130
No files matched your search
@@ -6,9 +6,7 @@ import {
|
||||
CommentCheckFlags,
|
||||
isNextLineEmpty,
|
||||
} from "../utils/index.js";
|
||||
import { printHardlineAfterHeritage } from "./class.js";
|
||||
|
||||
import { printBody } from "./statement.js";
|
||||
import { printStatementSequence } from "./statement.js";
|
||||
|
||||
/** @typedef {import("../../document/builders.js").Doc} Doc */
|
||||
|
||||
@@ -20,11 +18,6 @@ function printBlock(path, options, print) {
|
||||
parts.push("static ");
|
||||
}
|
||||
|
||||
if (node.type === "ClassBody" && isNonEmptyArray(node.body)) {
|
||||
const { parent } = path;
|
||||
parts.push(printHardlineAfterHeritage(parent));
|
||||
}
|
||||
|
||||
parts.push("{");
|
||||
const printed = printBlockBody(path, options, print);
|
||||
if (printed) {
|
||||
@@ -47,8 +40,7 @@ function printBlock(path, options, print) {
|
||||
(parent.type === "CatchClause" && !parentParent.finalizer) ||
|
||||
parent.type === "TSModuleDeclaration" ||
|
||||
parent.type === "TSDeclareFunction" ||
|
||||
node.type === "StaticBlock" ||
|
||||
node.type === "ClassBody"
|
||||
node.type === "StaticBlock"
|
||||
)
|
||||
) {
|
||||
parts.push(hardline);
|
||||
@@ -86,7 +78,7 @@ function printBlockBody(path, options, print) {
|
||||
}
|
||||
|
||||
if (nodeHasBody) {
|
||||
parts.push(printBody(path, options, print));
|
||||
parts.push(printStatementSequence(path, options, print));
|
||||
}
|
||||
|
||||
if (nodeHasComment) {
|
||||
|
||||
@@ -9,7 +9,12 @@ import {
|
||||
indent,
|
||||
ifBreak,
|
||||
} from "../../document/builders.js";
|
||||
import { hasComment, CommentCheckFlags } from "../utils/index.js";
|
||||
import {
|
||||
hasComment,
|
||||
CommentCheckFlags,
|
||||
createTypeCheckFunction,
|
||||
isNextLineEmpty,
|
||||
} from "../utils/index.js";
|
||||
import { getTypeParametersGroupId } from "./type-parameters.js";
|
||||
import { printMethod } from "./function.js";
|
||||
import {
|
||||
@@ -26,6 +31,16 @@ import { printClassMemberDecorators } from "./decorators.js";
|
||||
* @typedef {import("../../document/builders.js").Doc} Doc
|
||||
*/
|
||||
|
||||
const isClassProperty = createTypeCheckFunction([
|
||||
"ClassProperty",
|
||||
"PropertyDefinition",
|
||||
"ClassPrivateProperty",
|
||||
"ClassAccessorProperty",
|
||||
"AccessorProperty",
|
||||
"TSAbstractPropertyDefinition",
|
||||
"TSAbstractAccessorProperty",
|
||||
]);
|
||||
|
||||
/*
|
||||
- `ClassDeclaration`
|
||||
- `ClassExpression`
|
||||
@@ -250,9 +265,127 @@ function printClassProperty(path, options, print) {
|
||||
];
|
||||
}
|
||||
|
||||
function printClassBody(path, options, print) {
|
||||
const { node } = path;
|
||||
const parts = [];
|
||||
|
||||
path.each(({ node, next, isLast }) => {
|
||||
parts.push(print());
|
||||
|
||||
if (
|
||||
!options.semi &&
|
||||
isClassProperty(node) &&
|
||||
shouldPrintSemicolonAfterClassProperty(node, next)
|
||||
) {
|
||||
parts.push(";");
|
||||
}
|
||||
|
||||
if (!isLast) {
|
||||
parts.push(hardline);
|
||||
|
||||
if (isNextLineEmpty(node, options)) {
|
||||
parts.push(hardline);
|
||||
}
|
||||
}
|
||||
}, "body");
|
||||
|
||||
if (hasComment(node, CommentCheckFlags.Dangling)) {
|
||||
parts.push(printDanglingComments(path, options, /* sameIndent */ true));
|
||||
}
|
||||
|
||||
return [
|
||||
isNonEmptyArray(node.body) ? printHardlineAfterHeritage(path.parent) : "",
|
||||
"{",
|
||||
parts.length > 0 ? [indent([hardline, parts]), hardline] : "",
|
||||
"}",
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldPrintSemicolonAfterClassProperty(node, nextNode) {
|
||||
const { type, name } = node.key;
|
||||
if (
|
||||
!node.computed &&
|
||||
type === "Identifier" &&
|
||||
(name === "static" ||
|
||||
name === "get" ||
|
||||
name === "set" ||
|
||||
// TODO: Remove this https://github.com/microsoft/TypeScript/issues/51707 is fixed
|
||||
name === "accessor") &&
|
||||
!node.value &&
|
||||
!node.typeAnnotation
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!nextNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
nextNode.static ||
|
||||
nextNode.accessibility // TypeScript
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nextNode.computed) {
|
||||
const name = nextNode.key?.name;
|
||||
if (name === "in" || name === "instanceof") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Flow variance sigil +/- requires semi if there's no
|
||||
// "declare" or "static" keyword before it.
|
||||
if (
|
||||
isClassProperty(nextNode) &&
|
||||
nextNode.variance &&
|
||||
!nextNode.static &&
|
||||
!nextNode.declare
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (nextNode.type) {
|
||||
case "ClassProperty":
|
||||
case "PropertyDefinition":
|
||||
case "TSAbstractPropertyDefinition":
|
||||
return nextNode.computed;
|
||||
case "MethodDefinition":
|
||||
case "TSAbstractMethodDefinition":
|
||||
case "ClassMethod":
|
||||
case "ClassPrivateMethod": {
|
||||
// Babel
|
||||
const isAsync = nextNode.value ? nextNode.value.async : nextNode.async;
|
||||
if (isAsync || nextNode.kind === "get" || nextNode.kind === "set") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isGenerator = nextNode.value
|
||||
? nextNode.value.generator
|
||||
: nextNode.generator;
|
||||
if (nextNode.computed || isGenerator) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case "TSIndexSignature":
|
||||
return true;
|
||||
}
|
||||
|
||||
/* c8 ignore next */
|
||||
return false;
|
||||
}
|
||||
|
||||
export {
|
||||
printClass,
|
||||
printClassMethod,
|
||||
printClassProperty,
|
||||
printHardlineAfterHeritage,
|
||||
printClassBody,
|
||||
};
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
hasComment,
|
||||
CommentCheckFlags,
|
||||
isNextLineEmpty,
|
||||
createTypeCheckFunction,
|
||||
} from "../utils/index.js";
|
||||
import { shouldPrintParamsWithoutParens } from "./function.js";
|
||||
|
||||
@@ -17,13 +16,13 @@ import { shouldPrintParamsWithoutParens } from "./function.js";
|
||||
* @typedef {import("../../common/ast-path.js")} AstPath
|
||||
*/
|
||||
|
||||
function printStatementSequence(path, options, print, property) {
|
||||
function printStatementSequence(path, options, print) {
|
||||
const { node } = path;
|
||||
const parts = [];
|
||||
const isClassBody = node.type === "ClassBody";
|
||||
const property = node.type === "SwitchCase" ? "consequent" : "body";
|
||||
const lastStatement = getLastStatement(node[property]);
|
||||
|
||||
path.each(({ node, next }) => {
|
||||
path.each(({ node }) => {
|
||||
// Skip printing EmptyStatement nodes to avoid leaving stray
|
||||
// semicolons lying around.
|
||||
if (node.type === "EmptyStatement") {
|
||||
@@ -36,7 +35,6 @@ function printStatementSequence(path, options, print, property) {
|
||||
// don't prepend the only JSX element in a program with semicolon
|
||||
if (
|
||||
!options.semi &&
|
||||
!isClassBody &&
|
||||
!isTheOnlyJsxElementInMarkdown(options, path) &&
|
||||
statementNeedsASIProtection(path, options)
|
||||
) {
|
||||
@@ -49,17 +47,6 @@ function printStatementSequence(path, options, print, property) {
|
||||
parts.push(printed);
|
||||
}
|
||||
|
||||
if (
|
||||
!options.semi &&
|
||||
isClassBody &&
|
||||
isClassProperty(node) &&
|
||||
// `ClassBody` don't allow `EmptyStatement`,
|
||||
// so we can use `statements` to get next node
|
||||
shouldPrintSemicolonAfterClassProperty(node, next)
|
||||
) {
|
||||
parts.push(";");
|
||||
}
|
||||
|
||||
if (node !== lastStatement) {
|
||||
parts.push(hardline);
|
||||
|
||||
@@ -150,102 +137,4 @@ function expressionNeedsASIProtection(path, options) {
|
||||
);
|
||||
}
|
||||
|
||||
function printBody(path, options, print) {
|
||||
return printStatementSequence(path, options, print, "body");
|
||||
}
|
||||
|
||||
function printSwitchCaseConsequent(path, options, print) {
|
||||
return printStatementSequence(path, options, print, "consequent");
|
||||
}
|
||||
|
||||
const isClassProperty = createTypeCheckFunction([
|
||||
"ClassProperty",
|
||||
"PropertyDefinition",
|
||||
"ClassPrivateProperty",
|
||||
"ClassAccessorProperty",
|
||||
"AccessorProperty",
|
||||
"TSAbstractPropertyDefinition",
|
||||
"TSAbstractAccessorProperty",
|
||||
]);
|
||||
/**
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function shouldPrintSemicolonAfterClassProperty(node, nextNode) {
|
||||
const { type, name } = node.key;
|
||||
if (
|
||||
!node.computed &&
|
||||
type === "Identifier" &&
|
||||
(name === "static" ||
|
||||
name === "get" ||
|
||||
name === "set" ||
|
||||
// TODO: Remove this https://github.com/microsoft/TypeScript/issues/51707 is fixed
|
||||
name === "accessor") &&
|
||||
!node.value &&
|
||||
!node.typeAnnotation
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!nextNode) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
nextNode.static ||
|
||||
nextNode.accessibility // TypeScript
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!nextNode.computed) {
|
||||
const name = nextNode.key?.name;
|
||||
if (name === "in" || name === "instanceof") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Flow variance sigil +/- requires semi if there's no
|
||||
// "declare" or "static" keyword before it.
|
||||
if (
|
||||
isClassProperty(nextNode) &&
|
||||
nextNode.variance &&
|
||||
!nextNode.static &&
|
||||
!nextNode.declare
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (nextNode.type) {
|
||||
case "ClassProperty":
|
||||
case "PropertyDefinition":
|
||||
case "TSAbstractPropertyDefinition":
|
||||
return nextNode.computed;
|
||||
case "MethodDefinition": // Flow
|
||||
case "TSAbstractMethodDefinition": // TypeScript
|
||||
case "ClassMethod":
|
||||
case "ClassPrivateMethod": {
|
||||
// Babel
|
||||
const isAsync = nextNode.value ? nextNode.value.async : nextNode.async;
|
||||
if (isAsync || nextNode.kind === "get" || nextNode.kind === "set") {
|
||||
return false;
|
||||
}
|
||||
|
||||
const isGenerator = nextNode.value
|
||||
? nextNode.value.generator
|
||||
: nextNode.generator;
|
||||
if (nextNode.computed || isGenerator) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
case "TSIndexSignature":
|
||||
return true;
|
||||
}
|
||||
|
||||
/* c8 ignore next */
|
||||
return false;
|
||||
}
|
||||
|
||||
export { printBody, printSwitchCaseConsequent };
|
||||
export { printStatementSequence };
|
||||
@@ -69,6 +69,7 @@ import {
|
||||
printClass,
|
||||
printClassMethod,
|
||||
printClassProperty,
|
||||
printClassBody,
|
||||
} from "./print/class.js";
|
||||
import { printProperty } from "./print/property.js";
|
||||
import {
|
||||
@@ -84,7 +85,7 @@ import {
|
||||
printAssignmentExpression,
|
||||
} from "./print/assignment.js";
|
||||
import { printBinaryishExpression } from "./print/binaryish.js";
|
||||
import { printSwitchCaseConsequent } from "./print/statement.js";
|
||||
import { printStatementSequence } from "./print/statement.js";
|
||||
import { printMemberExpression } from "./print/member.js";
|
||||
import { printBlock, printBlockBody } from "./print/block.js";
|
||||
import { printLiteral } from "./print/literal.js";
|
||||
@@ -355,8 +356,9 @@ function printPathNoParens(path, options, print, args) {
|
||||
return "import";
|
||||
case "BlockStatement":
|
||||
case "StaticBlock":
|
||||
case "ClassBody":
|
||||
return printBlock(path, options, print);
|
||||
case "ClassBody":
|
||||
return printClassBody(path, options, print);
|
||||
case "ThrowStatement":
|
||||
return printThrowStatement(path, options, print);
|
||||
case "ReturnStatement":
|
||||
@@ -715,7 +717,7 @@ function printPathNoParens(path, options, print, args) {
|
||||
);
|
||||
|
||||
if (consequent.length > 0) {
|
||||
const cons = printSwitchCaseConsequent(path, options, print);
|
||||
const cons = printStatementSequence(path, options, print);
|
||||
|
||||
parts.push(
|
||||
consequent.length === 1 && consequent[0].type === "BlockStatement"
|
||||
|
||||
Reference in new issue
Block a user