Skip to content

Commit

Permalink
Extract printClass and printTypeParameters (#9713)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed Nov 19, 2020
1 parent b12e869 commit 87dab58
Show file tree
Hide file tree
Showing 3 changed files with 288 additions and 235 deletions.
143 changes: 143 additions & 0 deletions src/language-js/print/class.js
@@ -0,0 +1,143 @@
"use strict";

const { printComments, printDanglingComments } = require("../../main/comments");
const {
builders: { concat, join, line, hardline, softline, group, indent, ifBreak },
} = require("../../document");
const { hasTrailingComment, hasTrailingLineComment } = require("../utils");
const { getTypeParametersGroupId } = require("./type-parameters");

function printClass(path, options, print) {
const n = path.getValue();
const parts = [];

if (n.abstract) {
parts.push("abstract ");
}

parts.push("class");

// Keep old behaviour of extends in same line
// If there is only on extends and there are not comments
const groupMode =
(n.id && hasTrailingComment(n.id)) ||
(n.superClass &&
n.superClass.comments &&
n.superClass.comments.length !== 0) ||
(n.extends && n.extends.length !== 0) || // DeclareClass
(n.mixins && n.mixins.length !== 0) ||
(n.implements && n.implements.length !== 0);

const partsGroup = [];
const extendsParts = [];

if (n.id) {
partsGroup.push(" ", path.call(print, "id"));
}

partsGroup.push(path.call(print, "typeParameters"));

if (n.superClass) {
const printed = concat([
"extends ",
printSuperClass(path, options, print),
path.call(print, "superTypeParameters"),
]);
const printedWithComments = path.call(
(superClass) => printComments(superClass, () => printed, options),
"superClass"
);
if (groupMode) {
extendsParts.push(line, group(printedWithComments));
} else {
extendsParts.push(" ", printedWithComments);
}
} else {
extendsParts.push(printList(path, options, print, "extends"));
}

extendsParts.push(printList(path, options, print, "mixins"));
extendsParts.push(printList(path, options, print, "implements"));

if (groupMode) {
const printedExtends = concat(extendsParts);
if (shouldIndentOnlyHeritageClauses(n)) {
parts.push(
group(
concat(
partsGroup.concat(ifBreak(indent(printedExtends), printedExtends))
)
)
);
} else {
parts.push(group(indent(concat(partsGroup.concat(printedExtends)))));
}
} else {
parts.push(...partsGroup, ...extendsParts);
}

parts.push(" ", path.call(print, "body"));

return concat(parts);
}

function hasMultipleHeritage(node) {
return (
["superClass", "extends", "mixins", "implements"].filter(
(key) => !!node[key]
).length > 1
);
}

function shouldIndentOnlyHeritageClauses(node) {
return (
node.typeParameters &&
!hasTrailingLineComment(node.typeParameters) &&
!hasMultipleHeritage(node)
);
}

function printList(path, options, print, listName) {
const n = path.getValue();
if (!n[listName] || n[listName].length === 0) {
return "";
}

const printedLeadingComments = printDanglingComments(
path,
options,
/* sameIndent */ true,
({ marker }) => marker === listName
);
return concat([
shouldIndentOnlyHeritageClauses(n)
? ifBreak(" ", line, {
groupId: getTypeParametersGroupId(n.typeParameters),
})
: line,
printedLeadingComments,
printedLeadingComments && hardline,
listName,
group(
indent(
concat([line, join(concat([",", line]), path.map(print, listName))])
)
),
]);
}

function printSuperClass(path, options, print) {
const printed = path.call(print, "superClass");
const parent = path.getParentNode();
if (parent && parent.type === "AssignmentExpression") {
return concat([
ifBreak("("),
indent(concat([softline, printed])),
softline,
ifBreak(")"),
]);
}
return printed;
}

module.exports = { printClass };
100 changes: 100 additions & 0 deletions src/language-js/print/type-parameters.js
@@ -0,0 +1,100 @@
"use strict";

const { printDanglingComments } = require("../../main/comments");
const {
builders: { concat, join, line, hardline, softline, group, indent, ifBreak },
} = require("../../document");
const {
hasDanglingComments,
isTestCall,
isBlockComment,
shouldPrintComma,
} = require("../utils");
const { shouldHugType } = require("./type-annotation");

const typeParametersGroupIds = new WeakMap();
function getTypeParametersGroupId(node) {
if (!typeParametersGroupIds.has(node)) {
typeParametersGroupIds.set(node, Symbol("typeParameters"));
}
return typeParametersGroupIds.get(node);
}

function printTypeParameters(path, options, print, paramsKey) {
const n = path.getValue();

if (!n[paramsKey]) {
return "";
}

// for TypeParameterDeclaration typeParameters is a single node
if (!Array.isArray(n[paramsKey])) {
return path.call(print, paramsKey);
}

const grandparent = path.getNode(2);
const isParameterInTestCall = grandparent != null && isTestCall(grandparent);

const shouldInline =
isParameterInTestCall ||
n[paramsKey].length === 0 ||
(n[paramsKey].length === 1 &&
(shouldHugType(n[paramsKey][0]) ||
(n[paramsKey][0].type === "GenericTypeAnnotation" &&
shouldHugType(n[paramsKey][0].id)) ||
(n[paramsKey][0].type === "TSTypeReference" &&
shouldHugType(n[paramsKey][0].typeName)) ||
n[paramsKey][0].type === "NullableTypeAnnotation"));

if (shouldInline) {
return concat([
"<",
join(", ", path.map(print, paramsKey)),
printDanglingCommentsForInline(path, options),
">",
]);
}

return group(
concat([
"<",
indent(
concat([
softline,
join(concat([",", line]), path.map(print, paramsKey)),
])
),
ifBreak(
options.parser !== "typescript" &&
options.parser !== "babel-ts" &&
shouldPrintComma(options, "all")
? ","
: ""
),
softline,
">",
]),
{ id: getTypeParametersGroupId(n) }
);
}

function printDanglingCommentsForInline(path, options) {
const n = path.getValue();
if (!hasDanglingComments(n)) {
return "";
}
const hasOnlyBlockComments = n.comments.every((comment) =>
isBlockComment(comment)
);
const printed = printDanglingComments(
path,
options,
/* sameIndent */ hasOnlyBlockComments
);
if (hasOnlyBlockComments) {
return printed;
}
return concat([printed, hardline]);
}

module.exports = { printTypeParameters, getTypeParametersGroupId };

0 comments on commit 87dab58

Please sign in to comment.