Skip to content

Add align rule converter + indent merger #248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 22, 2019
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: 2 additions & 0 deletions src/rules/converters.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { convertAdjacentOverloadSignatures } from "./converters/adjacent-overload-signatures";
import { convertAlign } from "./converters/align";
import { convertArrayType } from "./converters/array-type";
import { convertArrowParens } from "./converters/arrow-parens";
import { convertArrowReturnShorthand } from "./converters/arrow-return-shorthand";
Expand Down Expand Up @@ -130,6 +131,7 @@ import { convertVariableName } from "./converters/variable-name";
*/
export const converters = new Map([
["adjacent-overload-signatures", convertAdjacentOverloadSignatures],
["align", convertAlign],
["array-type", convertArrayType],
["arrow-parens", convertArrowParens],
["arrow-return-shorthand", convertArrowReturnShorthand],
Expand Down
38 changes: 38 additions & 0 deletions src/rules/converters/align.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { RuleConverter } from "../converter";

export const convertAlign: RuleConverter = tslintRule => {
const alignArguments = tslintRule.ruleArguments.includes("arguments");
const alignElements = tslintRule.ruleArguments.includes("elements");
const alignMembers = tslintRule.ruleArguments.includes("members");
const alignParameters = tslintRule.ruleArguments.includes("parameters");
// "statements" alignment is enforced by base indent rule

const objectOption = {
...(alignArguments && {
CallExpression: { arguments: "first" },
}),
...(alignElements && {
ArrayExpression: "first",
}),
...(alignMembers && {
ObjectExpression: "first",
}),
...(alignParameters && {
FunctionDeclaration: { parameters: "first" },
FunctionExpression: { parameters: "first" },
}),
};

// TSLint's "align" rule doesn't care about indent size but "indent" rule requires
// specifying the indent size before the object option. Use the default value of 4.
const ruleArguments = tslintRule.ruleArguments.length === 0 ? undefined : [4, objectOption];

return {
rules: [
{
ruleName: "@typescript-eslint/indent",
...{ ruleArguments },
},
],
};
};
122 changes: 122 additions & 0 deletions src/rules/converters/tests/align.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { convertAlign } from "../align";

describe(convertAlign, () => {
test("conversion without arguments", () => {
const result = convertAlign({
ruleArguments: [],
});

expect(result).toEqual({
rules: [
{
ruleName: "@typescript-eslint/indent",
},
],
});
});

test("conversion with align arguments", () => {
const result = convertAlign({
ruleArguments: ["arguments"],
});

expect(result).toEqual({
rules: [
{
ruleName: "@typescript-eslint/indent",
ruleArguments: [
4,
{
CallExpression: { arguments: "first" },
},
],
},
],
});
});

test("conversion with align elements", () => {
const result = convertAlign({
ruleArguments: ["elements"],
});

expect(result).toEqual({
rules: [
{
ruleName: "@typescript-eslint/indent",
ruleArguments: [
4,
{
ArrayExpression: "first",
},
],
},
],
});
});

test("conversion with align members", () => {
const result = convertAlign({
ruleArguments: ["members"],
});

expect(result).toEqual({
rules: [
{
ruleName: "@typescript-eslint/indent",
ruleArguments: [
4,
{
ObjectExpression: "first",
},
],
},
],
});
});

test("conversion with align parameters", () => {
const result = convertAlign({
ruleArguments: ["parameters"],
});

expect(result).toEqual({
rules: [
{
ruleName: "@typescript-eslint/indent",
ruleArguments: [
4,
{
FunctionDeclaration: { parameters: "first" },
FunctionExpression: { parameters: "first" },
},
],
},
],
});
});

test("conversion with align all", () => {
const result = convertAlign({
ruleArguments: ["parameters", "elements", "arguments", "members"],
});

expect(result).toEqual({
rules: [
{
ruleName: "@typescript-eslint/indent",
ruleArguments: [
4,
{
ArrayExpression: "first",
CallExpression: { arguments: "first" },
FunctionDeclaration: { parameters: "first" },
FunctionExpression: { parameters: "first" },
ObjectExpression: "first",
},
],
},
],
});
});
});
2 changes: 2 additions & 0 deletions src/rules/mergers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { mergeBanTypes } from "./mergers/ban-types";
import { mergeIndent } from "./mergers/indent";
import { mergeNoCaller } from "./mergers/no-caller";
import { mergeNoEval } from "./mergers/no-eval";
import { mergeNoUnnecessaryTypeAssertion } from "./mergers/no-unnecessary-type-assertion";

export const mergers = new Map([
["@typescript-eslint/ban-types", mergeBanTypes],
["@typescript-eslint/indent", mergeIndent],
["@typescript-eslint/no-unnecessary-type-assertion", mergeNoUnnecessaryTypeAssertion],
["no-caller", mergeNoCaller],
["no-eval", mergeNoEval],
Expand Down
42 changes: 42 additions & 0 deletions src/rules/mergers/indent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { RuleMerger } from "../merger";

const ESLINT_INDENT_DEFAULT = 4;

export const mergeIndent: RuleMerger = (existingOptions, newOptions) => {
if (existingOptions === undefined && newOptions === undefined) {
return [];
}

// Resolve indent size
let indentSize = ESLINT_INDENT_DEFAULT; // default
for (const options of [existingOptions, newOptions]) {
if (
options === undefined ||
options.length === 0 ||
options[0] === ESLINT_INDENT_DEFAULT // ignore default
) {
continue;
}
indentSize = options[0];
}

// Resolve object option
let objectOption = null;
for (const options of [existingOptions, newOptions]) {
if (options === undefined || options.length < 2 || options[1] === undefined) {
continue;
}
objectOption = {
...(objectOption || {}),
...options[1],
};
}

if (indentSize === ESLINT_INDENT_DEFAULT && objectOption === null) {
return [];
} else if (objectOption === null) {
return [indentSize];
}

return [indentSize, objectOption];
};
60 changes: 60 additions & 0 deletions src/rules/mergers/tests/indent.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { mergeIndent } from "../indent";

describe(mergeIndent, () => {
test("neither options existing", () => {
const result = mergeIndent(undefined, undefined);

expect(result).toEqual([]);
});

test("original indent size existing", () => {
const result = mergeIndent([2], undefined);

expect(result).toEqual([2]);
});

test("new indent size existing", () => {
const result = mergeIndent(undefined, [2]);

expect(result).toEqual([2]);
});

test("both indent sizes existing", () => {
const result = mergeIndent([1], [2]);

expect(result).toEqual([2]);
});

test("default indent sizes existing", () => {
const result = mergeIndent([4], [4]);

expect(result).toEqual([]);
});

test("original object option existing", () => {
const result = mergeIndent([4, { ArrayExpression: "first" }], [2]);

expect(result).toEqual([2, { ArrayExpression: "first" }]);
});

test("new object option existing", () => {
const result = mergeIndent([2], [4, { ArrayExpression: "first" }]);

expect(result).toEqual([2, { ArrayExpression: "first" }]);
});

test("both object option existing", () => {
const result = mergeIndent(
[4, { ObjectExpression: "first" }],
[4, { ArrayExpression: "first" }],
);

expect(result).toEqual([
4,
{
ArrayExpression: "first",
ObjectExpression: "first",
},
]);
});
});