Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 2 additions & 19 deletions src/printers/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ import {
printBlock,
printBlockStatements,
printBodyDeclarations,
printDanglingComments,
printDanglingCommentsInList,
printModifiers,
printTypeParameters,
printValue,
printVariableDeclaration,
type NamedNodePath,
type NamedNodePrinters
} from "./helpers.ts";

const { group, hardline, indent, join, line, softline } = builders;
const { group, hardline, indent, join, line } = builders;

export default {
class_declaration(path, print) {
Expand Down Expand Up @@ -471,19 +470,3 @@ const indexByModifier = [
"non-sealed",
"strictfp"
].reduce((map, name, index) => map.set(name, index), new Map<string, number>());

function printDanglingCommentsInList(path: NamedNodePath) {
const { node } = path;

return node.comments?.some(comment => !(comment.leading || comment.trailing))
? [
indent([softline, printDanglingComments(path)]),
node.comments.some(
({ type, leading, trailing }) =>
!(leading || trailing) && type === SyntaxType.LineComment
)
? hardline
: softline
]
: "";
}
22 changes: 16 additions & 6 deletions src/printers/expressions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import {
hasDanglingComments,
hasType,
indentInParentheses,
isConciselyPrintedArray,
isReturnOrThrowStatement,
printAssignment,
printDanglingComments,
printDanglingCommentsInList,
shouldFlatten,
type JavaParserOptions,
type NamedNodePath,
Expand Down Expand Up @@ -521,7 +523,7 @@ export default {
({ type, leading, trailing }) =>
!leading && !trailing && type === SyntaxType.LineComment
);
return group(indentInParentheses(printDanglingComments(path)), {
return group(["(", printDanglingCommentsInList(path), ")"], {
shouldBreak
});
}
Expand Down Expand Up @@ -597,7 +599,7 @@ export default {
]);
}

if (shouldExpandLastArg(args)) {
if (shouldExpandLastArg(args, options)) {
const headArgs = printedArguments.slice(0, -1);
if (headArgs.some(willBreak)) {
return allArgsBrokenOut();
Expand Down Expand Up @@ -1504,17 +1506,25 @@ function couldExpandArg(arg: NamedNode, lambdaChainRecursion = false) {
return false;
}

function shouldExpandLastArg(args: NamedNode[]) {
function shouldExpandLastArg(args: NamedNode[], options: JavaParserOptions) {
const lastArg = args.at(-1)!;
const penultimateArg = args.at(-2);
return (
!lastArg.comments?.some(({ leading }) => leading) &&
!lastArg.comments?.some(({ trailing }) => trailing) &&
!lastArg.comments?.some(({ leading, trailing }) => leading || trailing) &&
couldExpandArg(lastArg) &&
// If the last two arguments are of the same type,
// disable last element expansion.
(!penultimateArg || penultimateArg.type !== lastArg.type) &&
(args.length !== 2 || penultimateArg!.type !== SyntaxType.LambdaExpression)
// useMemo(() -> func(), [foo, bar, baz])
(args.length !== 2 ||
penultimateArg!.type !== SyntaxType.LambdaExpression ||
lastArg.type !== SyntaxType.ArrayCreationExpression) &&
!(
args.length > 1 &&
lastArg.type === SyntaxType.ArrayCreationExpression &&
lastArg.valueNode &&
isConciselyPrintedArray(lastArg.valueNode, options)
)
);
}

Expand Down
216 changes: 200 additions & 16 deletions src/printers/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import type {
AstPath,
Doc,
Options,
ParserOptions,
Plugin,
SupportLanguage
import {
util,
type AstPath,
type Doc,
type Options,
type ParserOptions,
type Plugin,
type SupportLanguage
} from "prettier";
import { builders, utils } from "prettier/doc";
import {
SyntaxType,
type ArrayInitializerNode,
type CommentNode,
type ElementValueArrayInitializerNode,
type ExpressionNode,
type NamedNode,
type NamedType,
type SyntaxNode,
type TypeString
type TypeString,
type UnaryExpressionNode
} from "../node-types.ts";
import parser from "../parser.ts";

const { hasNewline, isNextLineEmpty, skipInlineComment, skipTrailingComment } =
util;
const {
fill,
group,
hardline,
ifBreak,
Expand Down Expand Up @@ -103,7 +110,7 @@ export function lineEndWithComments(node: SyntaxNode) {
}

export function printDanglingComments(
path: NamedNodePath,
path: AstPath<SyntaxNode>,
danglingCommentsPrintOptions: { indent?: boolean } = {}
): Doc {
const { indent: shouldIndent = false } = danglingCommentsPrintOptions;
Expand All @@ -129,6 +136,22 @@ export function printDanglingComments(
return shouldIndent ? indent([hardline, doc]) : doc;
}

export function printDanglingCommentsInList(path: AstPath<SyntaxNode>) {
const { node } = path;

return node.comments?.some(({ leading, trailing }) => !leading && !trailing)
? [
indent([softline, printDanglingComments(path)]),
node.comments?.some(
({ type, leading, trailing }) =>
!leading && !trailing && type === SyntaxType.LineComment
)
? hardline
: softline
]
: "";
}

export function printComment(comment: CommentNode) {
comment.printed = true;
const lines = comment.value.split("\n").map(line => line.trim());
Expand Down Expand Up @@ -167,18 +190,179 @@ export function printArrayInitializer(
print: PrintFunction,
options: JavaParserOptions
) {
if (!path.node.namedChildren.length) {
const danglingComments = printDanglingComments(path, { indent: true });
return danglingComments ? ["{", danglingComments, hardline, "}"] : "{}";
const { node } = path;
const parts: Doc[] = [];

const elements = node.namedChildren;
if (elements.length === 0) {
parts.push(group(["{", printDanglingCommentsInList(path), "}"]));
} else {
const groupId = Symbol("array");

const shouldBreak =
(elements.length > 1 &&
elements.every((element, i, elements) => {
if (element.type !== SyntaxType.ArrayInitializer) {
return false;
}

const elementType = element.type;
const nextElement = elements[i + 1];
if (nextElement && elementType !== nextElement.type) {
return false;
}

return element.namedChildren.length > 1;
})) ||
node.comments?.some(
({ type, leading, trailing }) =>
!leading && !trailing && type === SyntaxType.LineComment
);

const shouldUseConciseFormatting = isConciselyPrintedArray(node, options);

const trailingComma =
options.trailingComma === "none"
? ""
: shouldUseConciseFormatting
? ifBreak(",", "", { groupId })
: ifBreak(",");

parts.push(
group(
[
"{",
indent([
line,
shouldUseConciseFormatting
? printArrayElementsConcisely(path, options, print, trailingComma)
: [printArrayElements(path, options, print), trailingComma],
printDanglingComments(path)
]),
line,
"}"
],
{ shouldBreak, id: groupId }
)
);
}

return parts;
}

export function isConciselyPrintedArray(
node: ArrayInitializerNode | ElementValueArrayInitializerNode,
options: JavaParserOptions
) {
return (
node.namedChildren.length > 0 &&
node.namedChildren.every(
element =>
element &&
(isNumericLiteral(element) ||
(isSignedNumericLiteral(element) && !element.operandNode.comments)) &&
!element.comments?.some(
comment =>
comment.trailing &&
comment.type === SyntaxType.LineComment &&
!hasNewline(options.originalText, parser.locStart(comment), {
backwards: true
})
)
)
);
}

const isNumericLiteral = createTypeCheckFunction([
SyntaxType.BinaryIntegerLiteral,
SyntaxType.DecimalFloatingPointLiteral,
SyntaxType.DecimalIntegerLiteral,
SyntaxType.HexFloatingPointLiteral,
SyntaxType.HexIntegerLiteral,
SyntaxType.OctalIntegerLiteral
]);

function isSignedNumericLiteral(node: SyntaxNode): node is UnaryExpressionNode {
return (
node.type === SyntaxType.UnaryExpression &&
(node.operatorNode.type === "+" || node.operatorNode.type === "-") &&
isNumericLiteral(node.operandNode)
);
}

function isLineAfterElementEmpty(
{ node }: AstPath,
{ originalText: text }: JavaParserOptions
) {
let currentIdx = parser.locEnd(node);
if (currentIdx === parser.locStart(node)) {
return false;
}

const list = join([",", line], path.map(print, "namedChildren"));
const { length } = text;
while (currentIdx < length) {
if (text[currentIdx] === ",") {
break;
}

if (list.length && options.trailingComma !== "none") {
list.push(ifBreak(","));
currentIdx = skipInlineComment(
text,
skipTrailingComment(text, currentIdx + 1)
) as number;
}

return group(["{", indent([line, ...list]), line, "}"]);
return isNextLineEmpty(text, currentIdx);
}

function printArrayElements(
path: AstPath<ArrayInitializerNode | ElementValueArrayInitializerNode>,
options: JavaParserOptions,
print: PrintFunction
) {
const parts: Doc[] = [];

path.each(element => {
parts.push(group(print(element)));

if (!element.isLast) {
parts.push([
",",
line,
isLineAfterElementEmpty(path, options) ? softline : ""
]);
}
}, "namedChildren");

return parts;
}

function printArrayElementsConcisely(
path: AstPath<ArrayInitializerNode | ElementValueArrayInitializerNode>,
options: JavaParserOptions,
print: PrintFunction,
trailingComma: Doc
) {
const parts: Doc[] = [];

path.each(element => {
const { next } = element;
parts.push([print(element), !next ? trailingComma : ","]);

if (next) {
parts.push(
isLineAfterElementEmpty(path, options)
? [hardline, hardline]
: next.comments?.some(
({ type, leading }) =>
leading && type === SyntaxType.LineComment
)
? hardline
: line
);
}
}, "namedChildren");

return fill(parts);
}

export function printBlock(path: NamedNodePath, contents: Doc[]) {
Expand Down
Loading
Loading