Skip to content

Commit

Permalink
refactor: cleanup string deindenation (#1575)
Browse files Browse the repository at this point in the history
  • Loading branch information
dsherret authored Oct 5, 2024
1 parent 81dc87d commit 1dcb8a7
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 28 deletions.
13 changes: 13 additions & 0 deletions packages/common/src/tests/utils/stringUtilsTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -336,9 +336,22 @@ describe("StringUtils", () => {
doTest(" test\n \n test", "test\n\ntest", { indentSizeInSpaces: 2 });
});

it("should handle lines that only have indentation with slash r slash n", () => {
doTest(" test\r\n \r\n test", "test\r\n\r\ntest", { indentSizeInSpaces: 2 });
});

it("should ignore empty lines", () => {
doTest(" test\n\n test", "test\n\ntest", { indentSizeInSpaces: 2 });
});

it("should ignore empty lines with slash r slash n", () => {
doTest(" test\r\n\r\n test", "test\r\n\r\ntest", { indentSizeInSpaces: 2 });
});

it("should handle newlines at the end", () => {
doTest("\n\n", "\n\n", { indentSizeInSpaces: 2 });
doTest(" \n test\n ", "\ntest\n ", { indentSizeInSpaces: 2 });
});
});

describe(nameof(StringUtils, "indent"), () => {
Expand Down
59 changes: 31 additions & 28 deletions packages/common/src/utils/StringUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,7 @@ export class StringUtils {

static removeIndentation(str: string, opts: { isInStringAtPos: (pos: number) => boolean; indentSizeInSpaces: number }) {
const { isInStringAtPos, indentSizeInSpaces } = opts;
const startPositions: number[] = [];
const endPositions: number[] = [];
const positions: [number, number][] = [];
let minIndentWidth: number | undefined;

analyze();
Expand All @@ -165,50 +164,57 @@ export class StringUtils {
continue;
}

startPositions.push(i);
let startPosition = i;

let spacesCount = 0;
let tabsCount = 0;

while (true) {
if (str.charCodeAt(i) === CharCodes.SPACE)
let charCode = str.charCodeAt(i);
if (charCode === CharCodes.SPACE)
spacesCount++;
else if (str.charCodeAt(i) === CharCodes.TAB)
else if (charCode === CharCodes.TAB)
tabsCount++;
else
else if (charCode === CharCodes.NEWLINE || charCode === CharCodes.CARRIAGE_RETURN && str.charCodeAt(i + 1) === CharCodes.NEWLINE) {
spacesCount = 0;
tabsCount = 0;
positions.push([startPosition, i]);
if (charCode === CharCodes.CARRIAGE_RETURN) {
startPosition = i + 2;
i++;
} else {
startPosition = i + 1;
}
} else if (charCode == null)
break;
else {
// indentation for spaces rounds up to the nearest tab size multiple
const indentWidth = Math.ceil(spacesCount / indentSizeInSpaces) * indentSizeInSpaces + tabsCount * indentSizeInSpaces;
if (minIndentWidth == null || indentWidth < minIndentWidth)
minIndentWidth = indentWidth;

positions.push([startPosition, i]);
isAtStartOfLine = false;
break;
}

i++;
}

// indentation for spaces rounds up to the nearest tab size multiple
const indentWidth = Math.ceil(spacesCount / indentSizeInSpaces) * indentSizeInSpaces + tabsCount * indentSizeInSpaces;
if (str.charCodeAt(i) !== CharCodes.NEWLINE && (minIndentWidth == null || indentWidth < minIndentWidth))
minIndentWidth = indentWidth;

endPositions.push(i);
isAtStartOfLine = false;

// this check is needed for lines that are empty or consist purely of spaces/tabs
if (str.charCodeAt(i) === CharCodes.NEWLINE)
i--;
}
}

function buildString() {
if (startPositions.length === 0)
if (positions.length === 0)
return str;
if (minIndentWidth == null || minIndentWidth === 0)
return str;

const deindentWidth = minIndentWidth;
let result = "";
result += str.substring(0, startPositions[0]);
let lastEndPos = startPositions[0];
result += str.substring(0, positions[0][0]);

for (let i = 0; i < startPositions.length; i++) {
const startPosition = startPositions[i];
const endPosition = endPositions[i];
for (let i = 0; i < positions.length; i++) {
const [startPosition, endPosition] = positions[i];
let indentCount = 0;
let pos: number;
for (pos = startPosition; pos < endPosition; pos++) {
Expand All @@ -220,12 +226,9 @@ export class StringUtils {
indentCount += indentSizeInSpaces;
}

lastEndPos = startPositions[i + 1] == null ? str.length : startPositions[i + 1];
result += str.substring(pos, lastEndPos);
result += str.substring(pos, positions[i + 1]?.[0] ?? str.length);
}

result += str.substring(lastEndPos);

return result;
}
}
Expand Down

0 comments on commit 1dcb8a7

Please sign in to comment.