Skip to content

Commit

Permalink
Get rid of regexp and handle cursor in trim in doc printer (prettier#…
Browse files Browse the repository at this point in the history
  • Loading branch information
thorn0 authored and medikoo committed Feb 1, 2024
1 parent 20e26e1 commit b7b6616
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 14 deletions.
40 changes: 28 additions & 12 deletions src/document/printer.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,27 +144,43 @@ function generateInd(ind, newPart, options) {
}
}

// TODO: Skip cursor placeholder
// Trim `Tab(U+0009)` and `Space(U+0020)` at the end of line
function trim(out) {
let trimCount = 0;
let cursorCount = 0;
let outIndex = out.length;

while (out.length > 0) {
const last = getLast(out);
if (typeof last !== "string") {
break;
outer: while (outIndex--) {
const last = out[outIndex];

if (last === CURSOR_PLACEHOLDER) {
cursorCount++;
continue;
}

const trimmed = last.replace(/[\t ]*$/, "");
trimCount += last.length - trimmed.length;
if (process.env.NODE_ENV !== "production" && typeof last !== "string") {
throw new Error(`Unexpected value in trim: '${typeof last}'`);
}

if (trimmed !== "") {
out[out.length - 1] = trimmed;
break;
// Not using a regexp here because regexps for trimming off trailing
// characters are known to have performance issues.
for (let charIndex = last.length - 1; charIndex >= 0; charIndex--) {
const char = last[charIndex];
if (char === " " || char === "\t") {
trimCount++;
} else {
out[outIndex] = last.slice(0, charIndex + 1);
break outer;
}
}
}

if (trimCount > 0 || cursorCount > 0) {
out.length = outIndex + 1;

// All `Tab` or `Space`
out.length -= 1;
while (cursorCount-- > 0) {
out.push(CURSOR_PLACEHOLDER);
}
}

return trimCount;
Expand Down
25 changes: 23 additions & 2 deletions tests/unit/print-doc-to-string.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import { cursor } from "../../src/document/builders.js";
import { cursor, hardline } from "../../src/document/builders.js";
import { printDocToString } from "../../src/document/printer.js";

const options = { printWidth: 80, tabWidth: 2 };

test("Should reject if too many cursor in doc", () => {
expect(() => {
printDocToString([cursor, cursor, cursor], { printWidth: 80, tabWidth: 2 });
printDocToString([cursor, cursor, cursor], options);
}).toThrow({ message: "There are too many 'cursor' in doc." });
});

test("Should trim blank first line", () => {
expect(
printDocToString([" ", hardline, "Prettier", hardline], options).formatted
).toBe("\nPrettier\n");
});

test("Should properly trim with cursor", () => {
expect(
printDocToString(
[cursor, "Prettier \t", cursor, "\t \t", hardline],
options
)
).toEqual({
formatted: "Prettier\n",
cursorNodeStart: 0,
cursorNodeText: "Prettier",
});
});

0 comments on commit b7b6616

Please sign in to comment.