feat(lint): Format else conditions on own line if they had line break previously
ADD
internal/ast-utils/compareLines.test.ts
+import {test} from "rome";
+import {parseJS} from "@internal/js-parser";
+import {LineComparison, compareLines} from "./compareLines";
+import {jsStringLiteral} from "@internal/ast";
+
+test(
+ "different lines",
+ async (t) => {
+ const jsNode = parseJS({
+ input: "var a;\nvar b;",
+ });
+
+ let nodeA = jsNode.body[0];
+ let nodeB = jsNode.body[1];
+
+ t.is(compareLines(nodeA, nodeB), LineComparison.After);
+ t.is(compareLines(nodeB, nodeA), LineComparison.Before);
+ },
+);
+
+test(
+ "same line",
+ async (t) => {
+ const jsNode = parseJS({
+ input: "var a; var b;",
+ });
+
+ let nodeA = jsNode.body[0];
+ let nodeB = jsNode.body[1];
+
+ t.is(compareLines(nodeA, nodeB), LineComparison.Same);
+ },
+);
+
+test(
+ "unknown lines",
+ async (t) => {
+ let nodeA = jsStringLiteral.quick("a");
+ let nodeB = jsStringLiteral.quick("b");
+
+ t.is(compareLines(nodeA, nodeB), LineComparison.Unknown);
+ },
+);

ADD
internal/ast-utils/compareLines.ts
+import {AnyNode} from "@internal/ast";
+
+export enum LineComparison {
+ Unknown,
+ Same,
+ Before,
+ After,
+}
+
+export function compareLines(aNode: AnyNode, bNode: AnyNode): LineComparison {
+ if (aNode.loc != null && bNode.loc != null) {
+ const aLine = aNode.loc.end.line.valueOf();
+ const bLine = bNode.loc.start.line.valueOf();
+ if (aLine === bLine) {
+ return LineComparison.Same;
+ } else if (aLine > bLine) {
+ return LineComparison.Before;
+ } else {
+ return LineComparison.After;
+ }
+ } else {
+ return LineComparison.Unknown;
+ }
+}

MODIFY
internal/ast-utils/index.ts
internal/ast-utils/index.ts
export {isRoot} from "./isRoot";
export {assertRoot} from "./assertRoot";
export {removeLoc} from "./removeLoc";
+export {LineComparison, compareLines} from "./compareLines";

MODIFY
internal/compiler/lint/rules/js/noUnnecessaryContinue.test.rjson
internal/compiler/lint/rules/js/noUnnecessaryContinue.test.rjson
@@ -20,11 +20,9 @@ invalid: [
if (i > 5) {
console.log('foo');
continue;
- }
- else if (i >= 5 && i < 8) {
+ } else if (i >= 5 && i < 8) {
console.log('test');
- }
- else {
+ } else {
console.log('test');
}
}

MODIFY
internal/formatter/builders/js/statements/JSIfStatement.ts
internal/formatter/builders/js/statements/JSIfStatement.ts
@@ -17,6 +17,7 @@ import {
} from "@internal/formatter";
import {AnyNode, JSIfStatement} from "@internal/ast";
+import {LineComparison, compareLines} from "@internal/ast-utils";
import {isStatement} from "@internal/js-ast-utils";
export default function JSIfStatement(
@@ -53,12 +54,24 @@ export default function JSIfStatement(
hardline,
"}",
);
- } else {
+ }
+ else {
tokens.push(builder.tokenize(node.consequent, node));
}
if (node.alternate) {
- tokens.push(space, "else", space, builder.tokenize(node.alternate, node));
+ let separator: Token = space;
+
+ if (compareLines(node.consequent, node.alternate) === LineComparison.After) {
+ separator = hardline;
+ }
+
+ tokens.push(
+ separator,
+ "else",
+ space,
+ builder.tokenize(node.alternate, node),
+ );
}
return concat(tokens);

MODIFY
internal/formatter/node/index.ts
internal/formatter/node/index.ts
@@ -65,11 +65,3 @@ export function needsParens(
const fn = parentheses.get(node.type);
return fn ? fn(node, parent, printStack) : false;
}
-
-export function isOnSameLine(aNode: AnyNode, bNode: AnyNode): boolean {
- if (aNode.loc && bNode.loc) {
- return aNode.loc.end.line.equal(bNode.loc.start.line);
- } else {
- return false;
- }
-}

ADD
internal/formatter/test-fixtures/js/statements/if-else/input.test.md
+# `index.test.ts`
+
+**DO NOT MODIFY**. This file has been autogenerated. Run `rome test internal/formatter/index.test.ts --update-snapshots` to update.
+
+## `js > statements > if-else`
+
+### `Diagnostics`
+
+```
+
+```
+
+### `Input`
+
+```ts
+if (Math.random() > 0.5) {
+ console.log(1)
+} else if (Math.random() > 0.5) {
+ console.log(2)
+} else {
+ console.log(3)
+}
+
+if (Math.random() > 0.5) {
+ console.log(1)
+}
+else if (Math.random() > 0.5) {
+ console.log(2)
+}
+else {
+ console.log(3)
+}
+
+if (Math.random() > 0.5) {
+ console.log(1)
+}
+// wow
+else if (Math.random() > 0.5) {
+ console.log(2)
+}
+// so cool
+else {
+ console.log(3)
+}
+
+```
+
+### `Output`
+
+```ts
+if (Math.random() > 0.5) {
+ console.log(1);
+} else if (Math.random() > 0.5) {
+ console.log(2);
+} else {
+ console.log(3);
+}
+
+if (Math.random() > 0.5) {
+ console.log(1);
+}
+else if (Math.random() > 0.5) {
+ console.log(2);
+}
+else {
+ console.log(3);
+}
+
+if (Math.random() > 0.5) {
+ console.log(1);
+}
+// wow
+else if (Math.random() > 0.5) {
+ console.log(2);
+}
+// so cool
+else {
+ console.log(3);
+}
+
+```

ADD
internal/formatter/test-fixtures/js/statements/if-else/input.ts
+if (Math.random() > 0.5) {
+ console.log(1)
+} else if (Math.random() > 0.5) {
+ console.log(2)
+} else {
+ console.log(3)
+}
+
+if (Math.random() > 0.5) {
+ console.log(1)
+}
+else if (Math.random() > 0.5) {
+ console.log(2)
+}
+else {
+ console.log(3)
+}
+
+if (Math.random() > 0.5) {
+ console.log(1)
+}
+// wow
+else if (Math.random() > 0.5) {
+ console.log(2)
+}
+// so cool
+else {
+ console.log(3)
+}

feat(lint): Format else conditions on own line if they had line break previously (#1507)