Files
test-repo/src/language-graphql/printer-graphql.js
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

529 lines
13 KiB
JavaScript
Raw Normal View History

import {
group,
hardline,
ifBreak,
indent,
join,
line,
softline,
} from "../document/builders.js";
2023-02-13 10:17:39 +08:00
import isNextLineEmpty from "../utils/is-next-line-empty.js";
import isNonEmptyArray from "../utils/is-non-empty-array.js";
import UnexpectedNodeError from "../utils/unexpected-node-error.js";
2022-12-19 13:18:44 +08:00
import getVisitorKeys from "./get-visitor-keys.js";
import { locEnd, locStart } from "./loc.js";
import { insertPragma } from "./pragma.js";
2022-10-20 09:03:47 +08:00
import printDescription from "./print/description.js";
2017-06-05 15:34:08 -04:00
function genericPrint(path, options, print) {
const { node } = path;
2021-03-11 04:14:08 +08:00
switch (node.kind) {
2022-10-20 09:03:47 +08:00
case "Document":
return [
...join(hardline, printSequence(path, options, print, "definitions")),
hardline,
];
2017-06-05 15:34:08 -04:00
case "OperationDefinition": {
2021-03-11 04:14:08 +08:00
const hasOperation = options.originalText[locStart(node)] !== "{";
const hasName = Boolean(node.name);
return [
2021-03-11 04:14:08 +08:00
hasOperation ? node.operation : "",
2021-03-22 22:57:03 +08:00
hasOperation && hasName ? [" ", print("name")] : "",
hasOperation && !hasName && isNonEmptyArray(node.variableDefinitions)
? " "
: "",
printVariableDefinitions(path, print),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
!hasOperation && !hasName ? "" : " ",
2021-03-22 22:57:03 +08:00
print("selectionSet"),
];
2017-06-05 15:34:08 -04:00
}
case "FragmentDefinition":
return [
2017-06-06 12:35:40 -07:00
"fragment ",
2021-03-22 22:57:03 +08:00
print("name"),
printVariableDefinitions(path, print),
2017-06-06 12:35:40 -07:00
" on ",
2021-03-22 22:57:03 +08:00
print("typeCondition"),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
2017-06-06 12:35:40 -07:00
" ",
2021-03-22 22:57:03 +08:00
print("selectionSet"),
];
case "SelectionSet":
return [
2017-06-05 15:34:08 -04:00
"{",
indent([
hardline,
2022-03-31 21:04:12 +08:00
join(hardline, printSequence(path, options, print, "selections")),
]),
2017-06-05 15:34:08 -04:00
hardline,
"}",
];
case "Field":
return group([
2021-03-22 22:57:03 +08:00
node.alias ? [print("alias"), ": "] : "",
print("name"),
2021-03-11 04:14:08 +08:00
node.arguments.length > 0
? group([
"(",
indent([
softline,
join(
[ifBreak("", ", "), softline],
2022-03-31 21:04:12 +08:00
printSequence(path, options, print, "arguments"),
),
]),
softline,
")",
])
: "",
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
node.selectionSet ? " " : "",
2021-03-22 22:57:03 +08:00
print("selectionSet"),
]);
case "Name":
2021-03-11 04:14:08 +08:00
return node.value;
case "StringValue":
2021-03-11 04:14:08 +08:00
if (node.block) {
const lines = node.value.replaceAll('"""', '\\"""').split("\n");
if (lines.length === 1) {
lines[0] = lines[0].trim();
}
if (lines.every((line) => line === "")) {
lines.length = 0;
}
return join(hardline, ['"""', ...lines, '"""']);
2017-12-31 16:45:06 +01:00
}
return [
'"',
node.value.replaceAll(/["\\]/g, "\\$&").replaceAll("\n", "\\n"),
'"',
];
case "IntValue":
case "FloatValue":
case "EnumValue":
2021-03-11 04:14:08 +08:00
return node.value;
case "BooleanValue":
2021-03-11 04:14:08 +08:00
return node.value ? "true" : "false";
case "NullValue":
2017-06-06 18:06:15 -07:00
return "null";
case "Variable":
2021-03-22 22:57:03 +08:00
return ["$", print("name")];
case "ListValue":
return group([
"[",
indent([
2017-06-05 23:45:15 -07:00
softline,
join([ifBreak("", ", "), softline], path.map(print, "values")),
]),
softline,
"]",
]);
case "ObjectValue": {
const bracketSpace =
options.bracketSpacing && node.fields.length > 0 ? " " : "";
return group([
"{",
bracketSpace,
indent([
softline,
join([ifBreak("", ", "), softline], path.map(print, "fields")),
]),
softline,
ifBreak("", bracketSpace),
"}",
]);
}
2017-06-05 15:34:08 -04:00
case "ObjectField":
case "Argument":
return [print("name"), ": ", print("value")];
case "Directive":
return [
2017-06-06 17:42:47 -07:00
"@",
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
node.arguments.length > 0
? group([
"(",
indent([
2017-06-06 17:42:47 -07:00
softline,
join(
[ifBreak("", ", "), softline],
2022-03-31 21:04:12 +08:00
printSequence(path, options, print, "arguments"),
),
]),
softline,
")",
])
2017-06-06 17:42:47 -07:00
: "",
];
2017-06-06 17:42:47 -07:00
case "NamedType":
2021-03-22 22:57:03 +08:00
return print("name");
case "VariableDefinition":
return [
2021-03-22 22:57:03 +08:00
print("variable"),
": ",
2021-03-22 22:57:03 +08:00
print("type"),
node.defaultValue ? [" = ", print("defaultValue")] : "",
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
];
2017-12-31 16:45:06 +01:00
case "ObjectTypeExtension":
2022-08-30 22:42:58 +08:00
case "ObjectTypeDefinition":
case "InputObjectTypeExtension":
case "InputObjectTypeDefinition":
case "InterfaceTypeExtension":
case "InterfaceTypeDefinition": {
const { kind } = node;
const parts = [];
if (kind.endsWith("TypeDefinition")) {
2022-10-20 09:03:47 +08:00
parts.push(printDescription(path, options, print));
2022-08-30 22:42:58 +08:00
} else {
parts.push("extend ");
}
if (kind.startsWith("ObjectType")) {
parts.push("type");
} else if (kind.startsWith("InputObjectType")) {
parts.push("input");
} else {
parts.push("interface");
}
parts.push(" ", print("name"));
if (!kind.startsWith("InputObjectType") && node.interfaces.length > 0) {
parts.push(" implements ", ...printInterfaces(path, options, print));
}
parts.push(printDirectives(path, print, node));
if (node.fields.length > 0) {
parts.push([
" {",
indent([
hardline,
join(hardline, printSequence(path, options, print, "fields")),
]),
hardline,
"}",
]);
}
return parts;
}
case "FieldDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
node.arguments.length > 0
? group([
"(",
indent([
softline,
join(
[ifBreak("", ", "), softline],
2022-03-31 21:04:12 +08:00
printSequence(path, options, print, "arguments"),
),
]),
softline,
")",
])
: "",
": ",
2021-03-22 22:57:03 +08:00
print("type"),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
];
case "DirectiveDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
"directive ",
"@",
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
node.arguments.length > 0
? group([
"(",
indent([
softline,
join(
[ifBreak("", ", "), softline],
2022-03-31 21:04:12 +08:00
printSequence(path, options, print, "arguments"),
),
]),
softline,
")",
])
: "",
2021-03-11 04:14:08 +08:00
node.repeatable ? " repeatable" : "",
2021-01-11 10:19:13 +08:00
" on ",
2022-10-20 09:03:47 +08:00
...join(" | ", path.map(print, "locations")),
];
2017-12-31 16:45:06 +01:00
case "EnumTypeExtension":
case "EnumTypeDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
2021-03-11 04:14:08 +08:00
node.kind === "EnumTypeExtension" ? "extend " : "",
2017-06-27 19:20:53 -07:00
"enum ",
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
node.values.length > 0
? [
2017-12-31 16:45:06 +01:00
" {",
indent([
hardline,
2022-03-31 21:04:12 +08:00
join(hardline, printSequence(path, options, print, "values")),
]),
2017-12-31 16:45:06 +01:00
hardline,
"}",
]
2017-12-31 16:45:06 +01:00
: "",
];
2017-06-27 19:20:53 -07:00
case "EnumValueDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
];
2017-06-27 19:20:53 -07:00
case "InputValueDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
2021-03-22 22:57:03 +08:00
print("name"),
": ",
2021-03-22 22:57:03 +08:00
print("type"),
node.defaultValue ? [" = ", print("defaultValue")] : "",
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
];
case "SchemaExtension":
return [
"extend schema",
printDirectives(path, print, node),
...(node.operationTypes.length > 0
? [
" {",
indent([
hardline,
join(
hardline,
2022-03-31 21:04:12 +08:00
printSequence(path, options, print, "operationTypes"),
),
]),
hardline,
"}",
]
: []),
];
case "SchemaDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
"schema",
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
" {",
2021-03-11 04:14:08 +08:00
node.operationTypes.length > 0
? indent([
hardline,
join(
hardline,
2022-03-31 21:04:12 +08:00
printSequence(path, options, print, "operationTypes"),
),
])
2017-06-27 20:15:55 -07:00
: "",
hardline,
"}",
];
2017-06-27 20:15:55 -07:00
case "OperationTypeDefinition":
return [node.operation, ": ", print("type")];
2017-06-27 20:15:55 -07:00
case "FragmentSpread":
2021-03-22 22:57:03 +08:00
return ["...", print("name"), printDirectives(path, print, node)];
2017-06-06 12:35:40 -07:00
case "InlineFragment":
return [
2017-06-06 12:35:40 -07:00
"...",
2021-03-22 22:57:03 +08:00
node.typeCondition ? [" on ", print("typeCondition")] : "",
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
2017-06-06 12:35:40 -07:00
" ",
2021-03-22 22:57:03 +08:00
print("selectionSet"),
];
2017-06-06 12:35:40 -07:00
2017-12-31 16:45:06 +01:00
case "UnionTypeExtension":
case "UnionTypeDefinition":
return group([
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
group([
2021-03-11 04:14:08 +08:00
node.kind === "UnionTypeExtension" ? "extend " : "",
"union ",
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
node.types.length > 0
? [
" =",
ifBreak("", " "),
indent([
ifBreak([line, " "]),
join([line, "| "], path.map(print, "types")),
]),
]
: "",
]),
]);
2017-12-31 16:45:06 +01:00
case "ScalarTypeExtension":
case "ScalarTypeDefinition":
return [
2022-10-20 09:03:47 +08:00
printDescription(path, options, print),
2021-03-11 04:14:08 +08:00
node.kind === "ScalarTypeExtension" ? "extend " : "",
2017-06-27 19:34:25 -07:00
"scalar ",
2021-03-22 22:57:03 +08:00
print("name"),
2021-03-11 04:14:08 +08:00
printDirectives(path, print, node),
];
2017-06-27 19:34:25 -07:00
case "NonNullType":
2021-03-22 22:57:03 +08:00
return [print("type"), "!"];
2017-06-08 12:20:41 -04:00
case "ListType":
2021-03-22 22:57:03 +08:00
return ["[", print("type"), "]"];
2017-06-08 12:34:35 -04:00
2017-06-05 15:34:08 -04:00
default:
2022-10-22 23:33:08 +08:00
/* c8 ignore next */
throw new UnexpectedNodeError(node, "Graphql", "kind");
2017-06-05 15:34:08 -04:00
}
}
2021-03-11 04:14:08 +08:00
function printDirectives(path, print, node) {
if (node.directives.length === 0) {
2017-06-06 17:42:47 -07:00
return "";
}
const printed = join(line, path.map(print, "directives"));
2021-03-11 04:14:08 +08:00
if (
node.kind === "FragmentDefinition" ||
node.kind === "OperationDefinition"
) {
return group([line, printed]);
}
return [" ", group(indent([softline, printed]))];
2017-06-06 17:42:47 -07:00
}
2022-03-31 21:04:12 +08:00
function printSequence(path, options, print, property) {
2022-10-20 09:03:47 +08:00
return path.map(({ isLast, node }) => {
2021-03-22 22:57:03 +08:00
const printed = print();
if (!isLast && isNextLineEmpty(options.originalText, locEnd(node))) {
return [printed, hardline];
}
return printed;
2022-03-31 21:04:12 +08:00
}, property);
}
2017-12-27 00:04:09 +11:00
function canAttachComment(node) {
return node.kind !== "Comment";
2017-12-27 00:04:09 +11:00
}
function printComment(commentPath) {
const comment = commentPath.node;
if (comment.kind === "Comment") {
return "#" + comment.value.trimEnd();
2017-12-27 00:04:09 +11:00
}
2022-10-22 23:33:08 +08:00
/* c8 ignore next */
throw new Error("Not a comment: " + JSON.stringify(comment));
2017-12-27 00:04:09 +11:00
}
function printInterfaces(path, options, print) {
const { node } = path;
const parts = [];
const { interfaces } = node;
const printed = path.map(print, "interfaces");
for (let index = 0; index < interfaces.length; index++) {
const interfaceNode = interfaces[index];
parts.push(printed[index]);
const nextInterfaceNode = interfaces[index + 1];
if (nextInterfaceNode) {
const textBetween = options.originalText.slice(
interfaceNode.loc.end,
nextInterfaceNode.loc.start,
);
const hasComment = textBetween.includes("#");
2022-05-08 20:20:34 +08:00
parts.push(" &", hasComment ? line : " ");
}
}
return parts;
}
function printVariableDefinitions(path, print) {
const { node } = path;
if (!isNonEmptyArray(node.variableDefinitions)) {
return "";
}
return group([
"(",
indent([
softline,
join(
[ifBreak("", ", "), softline],
path.map(print, "variableDefinitions"),
),
]),
softline,
")",
]);
}
function clean(node, newNode /* , parent */) {
// We print single line `""" string """` as multiple line string,
// and the parser ignores space in multiple line string
if (node.kind === "StringValue" && node.block && !node.value.includes("\n")) {
newNode.value = newNode.value.trim();
}
}
clean.ignoredProperties = new Set(["loc", "comments"]);
function hasPrettierIgnore(path) {
const { node } = path;
2022-04-24 10:28:20 +08:00
return node?.comments?.some(
(comment) => comment.value.trim() === "prettier-ignore",
);
}
const printer = {
2017-12-26 12:23:50 +11:00
print: genericPrint,
massageAstNode: clean,
hasPrettierIgnore,
2018-06-17 14:04:48 +08:00
insertPragma,
2017-12-27 00:04:09 +11:00
printComment,
canAttachComment,
getVisitorKeys,
2017-12-26 12:23:50 +11:00
};
export default printer;