Extract printClassBody (#14191)

This commit is contained in:
fisker Cheung authored and GitHub committed 2023-01-17 10:27:54 +08:00
1 parent 9e85502107
commit bca85bb5cd
4 files changed
+146 -130

No files matched your search

+3 -11
View File
@@ -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) {
+134 -1
View File
@@ -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,
};
+4 -115
View File
@@ -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 };
+5 -3
View File
@@ -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"