447 lines
19 KiB
JavaScript
447 lines
19 KiB
JavaScript
import { builders } from "prettier/doc";
|
|
import { call, each, hasDeclarationAnnotations, hasLeadingComments, indentInParentheses, isBinaryExpression, lineEndWithComments, lineStartWithComments, map, onlyDefinedKey, printBlock, printClassPermits, printClassType, printDanglingComments, printList, printSingle, printWithModifiers } from "./helpers.js";
|
|
const { group, hardline, indent, indentIfBreak, join, line, softline } = builders;
|
|
export default {
|
|
classDeclaration(path, print) {
|
|
const declarationKey = onlyDefinedKey(path.node.children, [
|
|
"enumDeclaration",
|
|
"normalClassDeclaration",
|
|
"recordDeclaration"
|
|
]);
|
|
const declaration = call(path, print, declarationKey);
|
|
return printWithModifiers(path, print, "classModifier", declaration, true);
|
|
},
|
|
normalClassDeclaration(path, print) {
|
|
const { classExtends, classImplements, classPermits, typeParameters } = path.node.children;
|
|
const header = ["class ", call(path, print, "typeIdentifier")];
|
|
if (typeParameters) {
|
|
header.push(call(path, print, "typeParameters"));
|
|
}
|
|
if (classExtends) {
|
|
header.push(indent([line, call(path, print, "classExtends")]));
|
|
}
|
|
if (classImplements) {
|
|
header.push(indent([line, call(path, print, "classImplements")]));
|
|
}
|
|
if (classPermits) {
|
|
header.push(indent([line, call(path, print, "classPermits")]));
|
|
}
|
|
return [group(header), " ", call(path, print, "classBody")];
|
|
},
|
|
classModifier: printSingle,
|
|
typeParameters(path, print) {
|
|
return group([
|
|
"<",
|
|
indent([softline, call(path, print, "typeParameterList")]),
|
|
softline,
|
|
">"
|
|
]);
|
|
},
|
|
typeParameterList(path, print) {
|
|
return printList(path, print, "typeParameter");
|
|
},
|
|
classExtends(path, print) {
|
|
return ["extends ", call(path, print, "classType")];
|
|
},
|
|
classImplements(path, print) {
|
|
return group([
|
|
"implements",
|
|
indent([line, call(path, print, "interfaceTypeList")])
|
|
]);
|
|
},
|
|
classPermits: printClassPermits,
|
|
interfaceTypeList(path, print) {
|
|
return group(printList(path, print, "interfaceType"));
|
|
},
|
|
classBody(path, print) {
|
|
return printBlock(path, printClassBodyDeclarations(path, print));
|
|
},
|
|
classBodyDeclaration: printSingle,
|
|
classMemberDeclaration(path, print) {
|
|
const { children } = path.node;
|
|
return children.Semicolon
|
|
? ""
|
|
: call(path, print, onlyDefinedKey(children));
|
|
},
|
|
fieldDeclaration(path, print) {
|
|
const declaration = [
|
|
call(path, print, "unannType"),
|
|
" ",
|
|
call(path, print, "variableDeclaratorList"),
|
|
";"
|
|
];
|
|
return printWithModifiers(path, print, "fieldModifier", declaration);
|
|
},
|
|
fieldModifier: printSingle,
|
|
variableDeclaratorList(path, print) {
|
|
var _a;
|
|
const declarators = map(path, print, "variableDeclarator");
|
|
return declarators.length > 1 &&
|
|
path.node.children.variableDeclarator.some(({ children }) => children.Equals)
|
|
? group(indent(join([",", line], declarators)), {
|
|
shouldBreak: ((_a = path.getNode(4)) === null || _a === void 0 ? void 0 : _a.name) !== "forInit"
|
|
})
|
|
: join(", ", declarators);
|
|
},
|
|
variableDeclarator(path, print) {
|
|
var _a, _b;
|
|
const { children } = path.node;
|
|
const variableInitializer = (_a = children.variableInitializer) === null || _a === void 0 ? void 0 : _a[0];
|
|
const declaratorId = call(path, print, "variableDeclaratorId");
|
|
if (!variableInitializer) {
|
|
return declaratorId;
|
|
}
|
|
const expression = (_b = variableInitializer.children.expression) === null || _b === void 0 ? void 0 : _b[0];
|
|
const declarator = [declaratorId, " ", call(path, print, "Equals")];
|
|
const initializer = call(path, print, "variableInitializer");
|
|
if (hasLeadingComments(variableInitializer) ||
|
|
(expression && isBinaryExpression(expression))) {
|
|
declarator.push(group(indent([line, initializer])));
|
|
}
|
|
else {
|
|
const groupId = Symbol("assignment");
|
|
declarator.push(group(indent(line), { id: groupId }), indentIfBreak(initializer, { groupId }));
|
|
}
|
|
return group(declarator);
|
|
},
|
|
variableDeclaratorId(path, print) {
|
|
const { dims, Underscore } = path.node.children;
|
|
if (Underscore) {
|
|
return "_";
|
|
}
|
|
const identifier = call(path, print, "Identifier");
|
|
return dims ? [identifier, call(path, print, "dims")] : identifier;
|
|
},
|
|
variableInitializer: printSingle,
|
|
unannType: printSingle,
|
|
unannPrimitiveTypeWithOptionalDimsSuffix(path, print) {
|
|
const type = call(path, print, "unannPrimitiveType");
|
|
return path.node.children.dims ? [type, call(path, print, "dims")] : type;
|
|
},
|
|
unannPrimitiveType: printSingle,
|
|
unannReferenceType(path, print) {
|
|
const type = call(path, print, "unannClassOrInterfaceType");
|
|
return path.node.children.dims ? [type, call(path, print, "dims")] : type;
|
|
},
|
|
unannClassOrInterfaceType: printSingle,
|
|
unannClassType: printClassType,
|
|
unannInterfaceType: printSingle,
|
|
unannTypeVariable: printSingle,
|
|
methodDeclaration(path, print) {
|
|
const declaration = [
|
|
call(path, print, "methodHeader"),
|
|
path.node.children.methodBody[0].children.Semicolon ? "" : " ",
|
|
call(path, print, "methodBody")
|
|
];
|
|
return printWithModifiers(path, print, "methodModifier", declaration);
|
|
},
|
|
methodModifier: printSingle,
|
|
methodHeader(path, print) {
|
|
const { typeParameters, annotation, throws } = path.node.children;
|
|
const header = [];
|
|
if (typeParameters) {
|
|
header.push(call(path, print, "typeParameters"));
|
|
}
|
|
if (annotation) {
|
|
header.push(join(line, map(path, print, "annotation")));
|
|
}
|
|
header.push(call(path, print, "result"), call(path, print, "methodDeclarator"));
|
|
return throws
|
|
? group([
|
|
...join(" ", header),
|
|
group(indent([line, call(path, print, "throws")]))
|
|
])
|
|
: group(join(" ", header));
|
|
},
|
|
result: printSingle,
|
|
methodDeclarator(path, print) {
|
|
const { dims, formalParameterList, receiverParameter } = path.node.children;
|
|
const declarator = [call(path, print, "Identifier")];
|
|
const parameters = [];
|
|
if (receiverParameter) {
|
|
parameters.push(call(path, print, "receiverParameter"));
|
|
}
|
|
if (formalParameterList) {
|
|
parameters.push(call(path, print, "formalParameterList"));
|
|
}
|
|
const items = parameters.length
|
|
? join([",", line], parameters)
|
|
: printDanglingComments(path);
|
|
declarator.push(items.length ? indentInParentheses(items) : "()");
|
|
if (dims) {
|
|
declarator.push(call(path, print, "dims"));
|
|
}
|
|
return declarator;
|
|
},
|
|
receiverParameter(path, print) {
|
|
return join(" ", [
|
|
...map(path, print, "annotation"),
|
|
call(path, print, "unannType"),
|
|
path.node.children.Identifier
|
|
? [call(path, print, "Identifier"), ".this"]
|
|
: "this"
|
|
]);
|
|
},
|
|
formalParameterList(path, print) {
|
|
return printList(path, print, "formalParameter");
|
|
},
|
|
formalParameter: printSingle,
|
|
variableParaRegularParameter(path, print) {
|
|
return join(" ", [
|
|
...map(path, print, "variableModifier"),
|
|
call(path, print, "unannType"),
|
|
call(path, print, "variableDeclaratorId")
|
|
]);
|
|
},
|
|
variableArityParameter(path, print) {
|
|
const type = join(" ", [
|
|
...map(path, print, "variableModifier"),
|
|
call(path, print, "unannType"),
|
|
...map(path, print, "annotation")
|
|
]);
|
|
return [type, "... ", call(path, print, "Identifier")];
|
|
},
|
|
variableModifier: printSingle,
|
|
throws(path, print) {
|
|
return ["throws ", call(path, print, "exceptionTypeList")];
|
|
},
|
|
exceptionTypeList(path, print) {
|
|
return join(", ", map(path, print, "exceptionType"));
|
|
},
|
|
exceptionType: printSingle,
|
|
methodBody: printSingle,
|
|
instanceInitializer: printSingle,
|
|
staticInitializer(path, print) {
|
|
return ["static ", call(path, print, "block")];
|
|
},
|
|
constructorDeclaration(path, print) {
|
|
const declaration = [call(path, print, "constructorDeclarator")];
|
|
if (path.node.children.throws) {
|
|
declaration.push(group(indent([line, call(path, print, "throws")])));
|
|
}
|
|
declaration.push(" ", call(path, print, "constructorBody"));
|
|
return printWithModifiers(path, print, "constructorModifier", declaration, true);
|
|
},
|
|
constructorModifier: printSingle,
|
|
constructorDeclarator(path, print) {
|
|
const { children } = path.node;
|
|
const parameters = [];
|
|
if (children.receiverParameter) {
|
|
parameters.push(call(path, print, "receiverParameter"));
|
|
}
|
|
if (children.formalParameterList) {
|
|
parameters.push(call(path, print, "formalParameterList"));
|
|
}
|
|
const header = [call(path, print, "simpleTypeName")];
|
|
header.push(parameters.length
|
|
? indentInParentheses(join([",", line], parameters))
|
|
: "()");
|
|
return children.typeParameters
|
|
? [call(path, print, "typeParameters"), " ", ...header]
|
|
: header;
|
|
},
|
|
simpleTypeName: printSingle,
|
|
constructorBody(path, print) {
|
|
const { children } = path.node;
|
|
const statements = [];
|
|
if (children.explicitConstructorInvocation) {
|
|
statements.push(call(path, print, "explicitConstructorInvocation"));
|
|
}
|
|
if (children.blockStatements) {
|
|
statements.push(call(path, print, "blockStatements"));
|
|
}
|
|
return printBlock(path, statements);
|
|
},
|
|
explicitConstructorInvocation: printSingle,
|
|
unqualifiedExplicitConstructorInvocation(path, print) {
|
|
const { children } = path.node;
|
|
const invocation = [];
|
|
if (children.typeArguments) {
|
|
invocation.push(call(path, print, "typeArguments"));
|
|
}
|
|
invocation.push(children.Super ? "super" : "this");
|
|
if (children.argumentList) {
|
|
invocation.push(group(["(", call(path, print, "argumentList"), ")"]));
|
|
}
|
|
else {
|
|
invocation.push(indentInParentheses(printDanglingComments(path), { shouldBreak: true }));
|
|
}
|
|
invocation.push(";");
|
|
return invocation;
|
|
},
|
|
qualifiedExplicitConstructorInvocation(path, print) {
|
|
const { children } = path.node;
|
|
const invocation = [call(path, print, "expressionName"), "."];
|
|
if (children.typeArguments) {
|
|
invocation.push(call(path, print, "typeArguments"));
|
|
}
|
|
invocation.push("super");
|
|
if (children.argumentList) {
|
|
invocation.push(group(["(", call(path, print, "argumentList"), ")"]));
|
|
}
|
|
else {
|
|
invocation.push(indentInParentheses(printDanglingComments(path), { shouldBreak: true }));
|
|
}
|
|
invocation.push(";");
|
|
return invocation;
|
|
},
|
|
enumDeclaration(path, print) {
|
|
const header = ["enum", call(path, print, "typeIdentifier")];
|
|
if (path.node.children.classImplements) {
|
|
header.push(call(path, print, "classImplements"));
|
|
}
|
|
return join(" ", [...header, call(path, print, "enumBody")]);
|
|
},
|
|
enumBody(path, print, options) {
|
|
var _a;
|
|
const { children } = path.node;
|
|
const contents = [];
|
|
const hasNonEmptyDeclaration = ((_a = children.enumBodyDeclarations) !== null && _a !== void 0 ? _a : [])
|
|
.flatMap(({ children }) => { var _a; return (_a = children.classBodyDeclaration) !== null && _a !== void 0 ? _a : []; })
|
|
.some(({ children }) => { var _a; return !((_a = children.classMemberDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.Semicolon); });
|
|
if (children.enumConstantList) {
|
|
contents.push(call(path, print, "enumConstantList"));
|
|
if (!hasNonEmptyDeclaration && options.trailingComma !== "none") {
|
|
contents.push(",");
|
|
}
|
|
}
|
|
if (hasNonEmptyDeclaration) {
|
|
contents.push(";", hardline, call(path, print, "enumBodyDeclarations"));
|
|
}
|
|
return printBlock(path, contents.length ? [contents] : []);
|
|
},
|
|
enumConstantList(path, print) {
|
|
return join([",", hardline], map(path, constantPath => {
|
|
const constant = print(constantPath);
|
|
const { node, previous } = constantPath;
|
|
return !previous ||
|
|
lineStartWithComments(node) <= lineEndWithComments(previous) + 1
|
|
? constant
|
|
: [hardline, constant];
|
|
}, "enumConstant"));
|
|
},
|
|
enumConstant(path, print) {
|
|
const { argumentList, classBody } = path.node.children;
|
|
const initializer = [call(path, print, "Identifier")];
|
|
if (argumentList) {
|
|
initializer.push(group(["(", call(path, print, "argumentList"), ")"]));
|
|
}
|
|
if (classBody) {
|
|
initializer.push(" ", call(path, print, "classBody"));
|
|
}
|
|
return printWithModifiers(path, print, "enumConstantModifier", initializer);
|
|
},
|
|
enumConstantModifier: printSingle,
|
|
enumBodyDeclarations(path, print) {
|
|
return join(hardline, printClassBodyDeclarations(path, print));
|
|
},
|
|
recordDeclaration(path, print) {
|
|
const { children } = path.node;
|
|
const header = ["record ", call(path, print, "typeIdentifier")];
|
|
if (children.typeParameters) {
|
|
header.push(call(path, print, "typeParameters"));
|
|
}
|
|
header.push(call(path, print, "recordHeader"));
|
|
if (children.classImplements) {
|
|
header.push(" ", call(path, print, "classImplements"));
|
|
}
|
|
return [group(header), " ", call(path, print, "recordBody")];
|
|
},
|
|
recordHeader(path, print) {
|
|
return path.node.children.recordComponentList
|
|
? indentInParentheses(call(path, print, "recordComponentList"))
|
|
: indentInParentheses(printDanglingComments(path), { shouldBreak: true });
|
|
},
|
|
recordComponentList(path, print) {
|
|
return join([",", line], map(path, componentPath => {
|
|
const { node, previous } = componentPath;
|
|
const blankLine = previous &&
|
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1;
|
|
const component = print(componentPath);
|
|
return blankLine ? [softline, component] : component;
|
|
}, "recordComponent"));
|
|
},
|
|
recordComponent(path, print) {
|
|
const { children } = path.node;
|
|
const component = [call(path, print, "unannType")];
|
|
if (children.Identifier ||
|
|
children.variableArityRecordComponent[0].children.annotation) {
|
|
component.push(" ");
|
|
}
|
|
const suffixKey = onlyDefinedKey(children, [
|
|
"Identifier",
|
|
"variableArityRecordComponent"
|
|
]);
|
|
component.push(call(path, print, suffixKey));
|
|
return group(join(line, [...map(path, print, "recordComponentModifier"), component]));
|
|
},
|
|
variableArityRecordComponent(path, print) {
|
|
return [
|
|
...join(" ", map(path, print, "annotation")),
|
|
"... ",
|
|
call(path, print, "Identifier")
|
|
];
|
|
},
|
|
recordComponentModifier: printSingle,
|
|
recordBody(path, print) {
|
|
const declarations = [];
|
|
let previousRequiresPadding = false;
|
|
each(path, declarationPath => {
|
|
var _a, _b, _c, _d;
|
|
const declaration = print(declarationPath);
|
|
if (declaration === "") {
|
|
return;
|
|
}
|
|
const { node, previous } = declarationPath;
|
|
const fieldDeclaration = (_c = (_b = (_a = node.children.classBodyDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.classMemberDeclaration) === null || _b === void 0 ? void 0 : _b[0].children.fieldDeclaration) === null || _c === void 0 ? void 0 : _c[0].children;
|
|
const currentRequiresPadding = !fieldDeclaration ||
|
|
hasDeclarationAnnotations((_d = fieldDeclaration.fieldModifier) !== null && _d !== void 0 ? _d : []);
|
|
const blankLine = declarations.length > 0 &&
|
|
(previousRequiresPadding ||
|
|
currentRequiresPadding ||
|
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1);
|
|
declarations.push(blankLine ? [hardline, declaration] : declaration);
|
|
previousRequiresPadding = currentRequiresPadding;
|
|
}, "recordBodyDeclaration");
|
|
return printBlock(path, declarations);
|
|
},
|
|
recordBodyDeclaration: printSingle,
|
|
compactConstructorDeclaration(path, print) {
|
|
const declaration = [
|
|
call(path, print, "simpleTypeName"),
|
|
" ",
|
|
call(path, print, "constructorBody")
|
|
];
|
|
return printWithModifiers(path, print, "constructorModifier", declaration, true);
|
|
}
|
|
};
|
|
function printClassBodyDeclarations(path, print) {
|
|
var _a;
|
|
if (!path.node.children.classBodyDeclaration) {
|
|
return [];
|
|
}
|
|
const declarations = [];
|
|
let previousRequiresPadding = path.node.name === "enumBodyDeclarations" ||
|
|
((_a = path.grandparent) === null || _a === void 0 ? void 0 : _a.name) ===
|
|
"normalClassDeclaration";
|
|
each(path, declarationPath => {
|
|
var _a, _b, _c;
|
|
const declaration = print(declarationPath);
|
|
if (declaration === "") {
|
|
return;
|
|
}
|
|
const { node, previous } = declarationPath;
|
|
const fieldDeclaration = (_b = (_a = node.children.classMemberDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.fieldDeclaration) === null || _b === void 0 ? void 0 : _b[0].children;
|
|
const currentRequiresPadding = fieldDeclaration
|
|
? hasDeclarationAnnotations((_c = fieldDeclaration.fieldModifier) !== null && _c !== void 0 ? _c : [])
|
|
: true;
|
|
const blankLine = previousRequiresPadding ||
|
|
(declarations.length > 0 &&
|
|
(currentRequiresPadding ||
|
|
lineStartWithComments(node) > lineEndWithComments(previous) + 1));
|
|
declarations.push(blankLine ? [hardline, declaration] : declaration);
|
|
previousRequiresPadding = currentRequiresPadding;
|
|
}, "classBodyDeclaration");
|
|
return declarations;
|
|
}
|