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
2 changes: 1 addition & 1 deletion tools/bend-fmt-lsp/src/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,11 +210,11 @@ function indentDepths(lines: Line[], loose = looseLines(lines), anchors: (Token
while (level.parent && width < level.col) level = level.parent;
if (width > level.col) level = { col: width, depth: level.depth + 1, parent: level };
const head = line.tokens[0];
if (width === 0 && head && ["def", "type", "law", "@"].includes(head.text)) scopes.length = 0;
for (const token of line.tokens) {
if (token.kind === "symbol" && ["(", "[", "{"].includes(token.text)) brackets++;
else if (token.kind === "symbol" && [")", "]", "}"].includes(token.text)) brackets--;
else if (brackets === 0 && head?.text !== "import" && token.kind === "word") {
if (["def", "type", "law"].includes(token.text)) scopes.length = 0;
if (token.text === "match") {
scopes.push({ parent: scopes.at(-1)?.current ?? -1, current: -1, anchor: scopes.at(-1)?.anchor });
} else if (token.text === "case") {
Expand Down
6 changes: 5 additions & 1 deletion tools/bend-fmt-lsp/src/test/formatter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,12 +303,16 @@ test("mixed line endings and the final-newline state survive formatting", () =>
}
});

test("nested cases keep their owner and inline anchors after a dedented body", { skip: !runnable && "needs bun and bend2/main.ts" }, () => {
test("match scopes survive body dedents and reset at declarations", { skip: !runnable && "needs bun and bend2/main.ts" }, () => {
const cases = [
["import Base\ndef g(a:Bool,b:Bool)->Nat:\n match a:\n case True{}:\n match b:\n case True{}:\n 10n\n case False{}:\n 20n\n case False{}:\n 30n\ndef main()->Nat:\n g(True{},False{})\n", "20n\n"],
["import Base\ndef g(a: Bool, b: Bool) -> Nat:\n match a:\n case True{}:\n match b:case True{}:\n 10n\n case False{}:\n 20n\n case False{}:\n 30n\ndef main() -> Nat:\n g(True{}, False{})\n", "20n\n"],
["import Base\ndef g(a: Bool, b: Bool) -> IO(Unit):\n match a:\n case True{}:\n match b: case True{}:\n IO.print(\"10\")\n case False{}:\n do IO<Unit>:\n IO.print(\"20\")\n IO.print(\"21\")\n case False{}:\n IO.print(\"30\")\ndef main() -> IO(Unit):\n g(True{}, False{})\n", "20\n21\n"],
["import Base\ndef g(a: Bool, b: Bool, c: Bool) -> Nat:\n match a:\n case True{}:\n match b: case True{}:\n 10n\n case False{}:\n match c:\n case True{}:\n 20n\n case False{}:\n 21n\n case False{}:\n 30n\ndef main() -> Nat:\n g(True{}, False{}, True{})\n", "20n\n"],
["import Base\ndef g(b:Bool)->Type:\n match b:\n case True{}:\n@x: U32 -> U32\n case False{}:\nU32\ndef main() -> g(False{}):\n 7\n", "7\n"],
["import Base\ndef g(a:Bool,b:Bool)->Type:\n match a:\n case True{}:\n match b:\n case True{}:\n(\n@unsafe: U32 -> U32\n)\n case False{}:\n U32\n case False{}:\n U32\ndef main() -> g(True{}, False{}):\n 7\n", "7\n"],
["import Base\ndef old(a: Bool) -> U32:\n match a:\n case True{}: 1\n case False{}: 2\n@\n unsafe def newer(b: Bool) -> U32:\n match b:\n case True{}:\n10\n case False{}:\n20\ndef main() -> U32:\n newer(False{})\n", "20\n"],
["import Base\ndef old(a: Bool) -> U32:\n match a:\n case True{}: 1\n case False{}: 2\n@ # decorator\nunsafe # qualifier\n def newer(b: Bool) -> U32:\n match b:\n case True{}:\n10\n case False{}:\n20\ndef main() -> U32:\n newer(False{})\n", "20\n"],
];
const directory = mkdtempSync(join(tmpdir(), "bend-fmt-cases-"));
const file = join(directory, "main.bend");
Expand Down