Files
voidraft/frontend/src/common/prettier/plugins/java/comments.js
2025-09-13 20:25:19 +08:00

200 lines
7.4 KiB
JavaScript

import { util } from "prettier";
import parser from "./parser.js";
import { isEmptyStatement, isNonTerminal, isTerminal } from "./printers/helpers.js";
const formatterOffOnRangesByCst = new WeakMap();
export function determineFormatterOffOnRanges(cst) {
const { comments } = cst;
if (!comments) {
return;
}
const ranges = comments
.filter(({ image }) => /^(\/\/\s*@formatter:(off|on)\s*|\/\*\s*@formatter:(off|on)\s*\*\/)$/.test(image))
.reduce((ranges, { image, startOffset }) => {
const previous = ranges.at(-1);
if (image.endsWith("off")) {
if ((previous === null || previous === void 0 ? void 0 : previous.on) !== Infinity) {
ranges.push({ off: startOffset, on: Infinity });
}
}
else if ((previous === null || previous === void 0 ? void 0 : previous.on) === Infinity) {
previous.on = startOffset;
}
return ranges;
}, new Array());
formatterOffOnRangesByCst.set(cst, ranges);
}
export function isFullyBetweenFormatterOffOn(path) {
var _a;
const { node, root } = path;
const start = parser.locStart(node);
const end = parser.locEnd(node);
return (((_a = formatterOffOnRangesByCst
.get(root)) === null || _a === void 0 ? void 0 : _a.some(range => range.off < start && end < range.on)) === true);
}
export function canAttachComment(node) {
var _a, _b, _c;
if (isTerminal(node)) {
const { name, CATEGORIES } = node.tokenType;
return (name === "Identifier" ||
(CATEGORIES === null || CATEGORIES === void 0 ? void 0 : CATEGORIES.find(({ name }) => name === "BinaryOperator")) !== undefined);
}
const { children, name } = node;
switch (name) {
case "argumentList":
case "blockStatements":
case "emptyStatement":
case "enumBodyDeclarations":
return false;
case "annotationInterfaceMemberDeclaration":
case "classMemberDeclaration":
case "interfaceMemberDeclaration":
case "methodBody":
return !children.Semicolon;
case "blockStatement":
return !children.statement || !isEmptyStatement(children.statement[0]);
case "classBodyDeclaration":
return !((_a = children.classMemberDeclaration) === null || _a === void 0 ? void 0 : _a[0].children.Semicolon);
case "recordBodyDeclaration":
return !((_c = (_b = children.classBodyDeclaration) === null || _b === void 0 ? void 0 : _b[0].children.classMemberDeclaration) === null || _c === void 0 ? void 0 : _c[0].children.Semicolon);
case "statement":
return !isEmptyStatement(node);
case "statementWithoutTrailingSubstatement":
return !children.emptyStatement;
default:
return true;
}
}
export function handleLineComment(commentNode, _, options) {
return [
handleBinaryExpressionComments,
handleFqnOrRefTypeComments,
handleIfStatementComments,
handleJumpStatementComments,
handleLabeledStatementComments,
handleNameComments
].some(fn => fn(commentNode, options));
}
export function handleRemainingComment(commentNode) {
return [
handleFqnOrRefTypeComments,
handleMethodDeclaratorComments,
handleNameComments,
handleJumpStatementComments
].some(fn => fn(commentNode));
}
function handleBinaryExpressionComments(commentNode, options) {
const { enclosingNode, precedingNode, followingNode } = commentNode;
if (enclosingNode &&
isNonTerminal(enclosingNode) &&
enclosingNode.name === "binaryExpression") {
if (isBinaryOperator(followingNode)) {
if (options.experimentalOperatorPosition === "start") {
util.addLeadingComment(followingNode, commentNode);
}
else {
util.addTrailingComment(followingNode, commentNode);
}
return true;
}
else if (options.experimentalOperatorPosition === "start" &&
isBinaryOperator(precedingNode)) {
util.addLeadingComment(precedingNode, commentNode);
return true;
}
}
return false;
}
function handleFqnOrRefTypeComments(commentNode) {
const { enclosingNode, followingNode } = commentNode;
if (enclosingNode &&
isNonTerminal(enclosingNode) &&
enclosingNode.name === "fqnOrRefType" &&
followingNode) {
util.addLeadingComment(followingNode, commentNode);
return true;
}
return false;
}
function handleIfStatementComments(commentNode) {
const { enclosingNode, precedingNode } = commentNode;
if (enclosingNode &&
isNonTerminal(enclosingNode) &&
enclosingNode.name === "ifStatement" &&
precedingNode &&
isNonTerminal(precedingNode) &&
precedingNode.name === "statement") {
util.addDanglingComment(enclosingNode, commentNode, undefined);
return true;
}
return false;
}
function handleJumpStatementComments(commentNode) {
const { enclosingNode, precedingNode, followingNode } = commentNode;
if (enclosingNode &&
!precedingNode &&
!followingNode &&
isNonTerminal(enclosingNode) &&
["breakStatement", "continueStatement", "returnStatement"].includes(enclosingNode.name)) {
util.addTrailingComment(enclosingNode, commentNode);
return true;
}
return false;
}
function handleLabeledStatementComments(commentNode) {
const { enclosingNode, precedingNode } = commentNode;
if (enclosingNode &&
precedingNode &&
isNonTerminal(enclosingNode) &&
enclosingNode.name === "labeledStatement" &&
isTerminal(precedingNode) &&
precedingNode.tokenType.name === "Identifier") {
util.addLeadingComment(precedingNode, commentNode);
return true;
}
return false;
}
function handleMethodDeclaratorComments(commentNode) {
const { enclosingNode } = commentNode;
if (enclosingNode &&
isNonTerminal(enclosingNode) &&
enclosingNode.name === "methodDeclarator" &&
!enclosingNode.children.receiverParameter &&
!enclosingNode.children.formalParameterList &&
enclosingNode.children.LBrace[0].startOffset < commentNode.startOffset &&
commentNode.startOffset < enclosingNode.children.RBrace[0].startOffset) {
util.addDanglingComment(enclosingNode, commentNode, undefined);
return true;
}
return false;
}
function handleNameComments(commentNode) {
const { enclosingNode, precedingNode } = commentNode;
if (enclosingNode &&
precedingNode &&
isNonTerminal(enclosingNode) &&
isTerminal(precedingNode) &&
precedingNode.tokenType.name === "Identifier" &&
[
"ambiguousName",
"classOrInterfaceTypeToInstantiate",
"expressionName",
"moduleDeclaration",
"moduleName",
"packageDeclaration",
"packageName",
"packageOrTypeName",
"typeName"
].includes(enclosingNode.name)) {
util.addTrailingComment(precedingNode, commentNode);
return true;
}
return false;
}
function isBinaryOperator(node) {
var _a;
return (node !== undefined &&
(isNonTerminal(node)
? node.name === "shiftOperator"
: (_a = node.tokenType.CATEGORIES) === null || _a === void 0 ? void 0 : _a.some(({ name }) => name === "BinaryOperator")));
}