Skip to content

Commit ae425ca

Browse files
committed
add more typings and display notices
1 parent 9a78a60 commit ae425ca

File tree

2 files changed

+194
-52
lines changed

2 files changed

+194
-52
lines changed

src/rules/converters/tests/trailing-comma.test.ts

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ describe(convertTrailingComma, () => {
102102
functions: "always",
103103
imports: "always",
104104
exports: "always",
105-
typeLiterals: "ignore",
106105
},
107106
},
108107
expectedRuleArguments: [
@@ -124,7 +123,6 @@ describe(convertTrailingComma, () => {
124123
functions: "always",
125124
imports: "always",
126125
exports: "always",
127-
typeLiterals: "ignore",
128126
},
129127
},
130128
expectedRuleArguments: [
@@ -145,7 +143,6 @@ describe(convertTrailingComma, () => {
145143
functions: "never",
146144
imports: "never",
147145
exports: "never",
148-
typeLiterals: "ignore",
149146
},
150147
},
151148
expectedRuleArguments: [
@@ -164,13 +161,11 @@ describe(convertTrailingComma, () => {
164161
objects: "never",
165162
arrays: "never",
166163
functions: "never",
167-
typeLiterals: "ignore",
168164
},
169165
multiline: {
170166
objects: "never",
171167
arrays: "never",
172168
functions: "never",
173-
typeLiterals: "ignore",
174169
},
175170
},
176171
expectedRuleArguments: [
@@ -189,7 +184,6 @@ describe(convertTrailingComma, () => {
189184
functions: "always",
190185
imports: "always",
191186
exports: "always",
192-
typeLiterals: "ignore",
193187
},
194188
},
195189
expectedRuleArguments: [
@@ -210,15 +204,13 @@ describe(convertTrailingComma, () => {
210204
functions: "always",
211205
imports: "always",
212206
exports: "always",
213-
typeLiterals: "ignore",
214207
},
215208
multiline: {
216209
objects: "always",
217210
arrays: "always",
218211
functions: "always",
219212
imports: "always",
220213
exports: "always",
221-
typeLiterals: "ignore",
222214
},
223215
},
224216
expectedRuleArguments: [
@@ -263,9 +255,101 @@ describe(convertTrailingComma, () => {
263255
rules: [
264256
{
265257
ruleName: "comma-dangle",
266-
...(testCase.expectedRuleArguments.length !== 0 && {
258+
...(testCase.expectedRuleArguments.length && {
259+
ruleArguments: testCase.expectedRuleArguments,
260+
}),
261+
},
262+
],
263+
});
264+
});
265+
});
266+
});
267+
268+
describe("conversion with not supported config", () => {
269+
const testCases = [
270+
{
271+
argument: {
272+
esSpecCompliant: true,
273+
},
274+
expectedRuleArguments: [],
275+
expectedNotices: ["ESLint does not support config property esSpecCompliant"],
276+
},
277+
{
278+
argument: {
279+
singleline: {
280+
typeLiterals: "ignore",
281+
},
282+
},
283+
expectedRuleArguments: [{}],
284+
expectedNotices: ["ESLint does not support config property typeLiterals"],
285+
},
286+
{
287+
argument: {
288+
multiline: {
289+
typeLiterals: "ignore",
290+
},
291+
},
292+
expectedRuleArguments: [{}],
293+
expectedNotices: ["ESLint does not support config property typeLiterals"],
294+
},
295+
{
296+
argument: {
297+
esSpecCompliant: true,
298+
singleline: {
299+
typeLiterals: "always",
300+
},
301+
},
302+
expectedRuleArguments: [{}],
303+
expectedNotices: [
304+
"ESLint does not support config property esSpecCompliant",
305+
"ESLint does not support config property typeLiterals",
306+
],
307+
},
308+
{
309+
argument: {
310+
esSpecCompliant: false,
311+
multiline: {
312+
typeLiterals: "always-multiline",
313+
},
314+
},
315+
expectedRuleArguments: [{}],
316+
expectedNotices: [
317+
"ESLint does not support config property esSpecCompliant",
318+
"ESLint does not support config property typeLiterals",
319+
],
320+
},
321+
{
322+
argument: {
323+
esSpecCompliant: false,
324+
singleline: {
325+
typeLiterals: "ignore",
326+
},
327+
multiline: {
328+
typeLiterals: "ignore",
329+
},
330+
},
331+
expectedRuleArguments: [{}],
332+
expectedNotices: [
333+
"ESLint does not support config property esSpecCompliant",
334+
"ESLint does not support config property typeLiterals",
335+
],
336+
},
337+
];
338+
339+
testCases.forEach(testCase => {
340+
test(`conversion with arguments ${JSON.stringify(testCase.argument)}`, () => {
341+
const result = convertTrailingComma({
342+
ruleArguments: [testCase.argument],
343+
});
344+
345+
expect(result).toEqual({
346+
rules: [
347+
{
348+
ruleName: "comma-dangle",
349+
...(testCase.expectedRuleArguments.length && {
267350
ruleArguments: testCase.expectedRuleArguments,
268351
}),
352+
notices: testCase.expectedNotices,
269353
},
270354
],
271355
});
Lines changed: 101 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,110 @@
11
import { RuleConverter } from "../converter";
22

3+
const unsupportedKeyInEsLint = "typeLiterals";
4+
35
export const convertTrailingComma: RuleConverter = tslintRule => {
4-
const eslintArgs =
5-
tslintRule.ruleArguments.length !== 0
6-
? collectArguments(tslintRule.ruleArguments)
7-
: undefined;
6+
const eslintArgs = tslintRule.ruleArguments.length
7+
? collectArguments(tslintRule.ruleArguments)
8+
: undefined;
9+
10+
const notices = tslintRule.ruleArguments.length
11+
? collectNotices(tslintRule.ruleArguments)
12+
: undefined;
813

914
return {
1015
rules: [
1116
{
1217
ruleName: "comma-dangle",
1318
...(eslintArgs && { ruleArguments: [eslintArgs] }),
19+
...(notices && notices.length && { notices }),
1420
},
1521
],
1622
};
1723
};
1824

19-
function collectArguments(args: any[]) {
20-
const tslintArg: any = args[0];
21-
const { multiline, singleline } = tslintArg;
25+
function collectArguments(args: TSLintArg[]): ESLintArgValue | undefined {
26+
const tslintArg = args[0];
27+
const { singleline, multiline } = tslintArg;
2228

23-
if (typeof multiline === "object" || typeof singleline === "object") {
24-
const fields = mergePropertyKeys(singleline, multiline);
25-
const single = getFieldValue(singleline);
26-
const multi = getFieldValue(multiline);
29+
if (typeof singleline === "object" || typeof multiline === "object") {
30+
const keys = mergePropertyKeys(singleline, multiline);
31+
const single = singleline && mapToObjectConfig(singleline);
32+
const multi = multiline && mapToObjectConfig(multiline);
2733

28-
return fields.reduce(
29-
(acc, field) => ({
34+
return keys.reduce(
35+
(acc, key) => ({
3036
...acc,
31-
...collectFields(field, single, multi),
37+
...collectKeys(key as TSLintObjectKey, single, multi),
3238
}),
3339
{},
3440
);
3541
}
3642

37-
if (
38-
multiline === TSLintValue.Always &&
39-
(singleline === undefined || singleline === TSLintValue.Never)
40-
) {
41-
return ESLintValue.AlwaysMultiline;
43+
if ((singleline === undefined || singleline === "never") && multiline === "always") {
44+
return "always-multiline";
4245
}
4346

44-
if (multiline === TSLintValue.Always && singleline === TSLintValue.Always) {
45-
return ESLintValue.Always;
47+
if (singleline === "always" && multiline === "always") {
48+
return "always";
4649
}
4750

4851
return;
4952
}
5053

51-
function mergePropertyKeys(singleline: any, multiline: any) {
52-
const getKeysIfObject = (field: any) => (typeof field === "object" ? Object.keys(field) : []);
54+
function mergePropertyKeys(
55+
singleline: TSLintArgValue | undefined,
56+
multiline: TSLintArgValue | undefined,
57+
): string[] {
58+
const getKeysIfObject = (field: TSLintArgValue | undefined): string[] =>
59+
typeof field === "object" ? Object.keys(field) : [];
5360
const singlelineKeys = getKeysIfObject(singleline);
5461
const multilineKeys = getKeysIfObject(multiline);
5562

5663
const uniqueKeys = [...new Set([...singlelineKeys, ...multilineKeys])];
57-
const unsupportedKeyInEsLint = "typeLiterals";
5864

5965
return uniqueKeys.filter(field => field !== unsupportedKeyInEsLint);
6066
}
6167

62-
function collectFields(fieldName: string, singleline: any, multiline: any) {
68+
function collectKeys(
69+
key: TSLintObjectKey,
70+
singleline: TSLintObject | undefined,
71+
multiline: TSLintObject | undefined,
72+
): { [key: string]: ESLintStringValue } {
6373
const hasSingleline = Boolean(singleline);
64-
const hasSinglelineAndFieldExist = Boolean(singleline && singleline[fieldName]);
65-
const hasSinglelineAlways = Boolean(singleline && singleline[fieldName] === TSLintValue.Always);
66-
const hasMultilineAlways = Boolean(multiline && multiline[fieldName] === TSLintValue.Always);
74+
const hasSinglelineAndFieldExist = Boolean(singleline && singleline[key]);
75+
const hasSinglelineAlways = Boolean(singleline && singleline[key] === "always");
76+
const hasMultilineAlways = Boolean(multiline && multiline[key] === "always");
6777

6878
if (!hasSingleline && hasMultilineAlways) {
6979
return {
70-
[fieldName]: ESLintValue.AlwaysMultiline,
80+
[key]: "always-multiline",
7181
};
7282
}
7383

7484
if (!hasSinglelineAndFieldExist && hasMultilineAlways) {
7585
return {
76-
[fieldName]: ESLintValue.AlwaysMultiline,
86+
[key]: "always-multiline",
7787
};
7888
}
7989

8090
if (!hasSinglelineAlways && hasMultilineAlways) {
8191
return {
82-
[fieldName]: ESLintValue.AlwaysMultiline,
92+
[key]: "always-multiline",
8393
};
8494
}
8595

8696
if (hasSinglelineAlways && hasMultilineAlways) {
8797
return {
88-
[fieldName]: ESLintValue.Always,
98+
[key]: "always",
8999
};
90100
}
91101

92102
return {
93-
[fieldName]: ESLintValue.Never,
103+
[key]: "never",
94104
};
95105
}
96106

97-
function getFieldValue(value: string | object) {
107+
function mapToObjectConfig(value: TSLintArgValue): TSLintObject {
98108
return typeof value === "string"
99109
? {
100110
arrays: value,
@@ -106,15 +116,63 @@ function getFieldValue(value: string | object) {
106116
: value;
107117
}
108118

109-
enum TSLintValue {
110-
Always = "always",
111-
Never = "never",
119+
function collectNotices(args: TSLintArg[]): string[] {
120+
const tslintArg = args[0];
121+
122+
return [buildNoticeForEsSpecCompliant(tslintArg), buildNoticeForTypeLiterals(tslintArg)].filter(
123+
Boolean,
124+
);
112125
}
113126

114-
enum ESLintValue {
115-
Never = "never",
116-
Always = "always",
117-
AlwaysMultiline = "always-multiline",
118-
OnlyMultiline = "only-multiline",
119-
Ignore = "ignore",
127+
function buildNoticeForEsSpecCompliant(arg: TSLintArg): string {
128+
const unsupportedConfigKey = "esSpecCompliant";
129+
130+
if (Object.keys(arg).includes(unsupportedConfigKey)) {
131+
return `ESLint does not support config property ${unsupportedConfigKey}`;
132+
}
133+
134+
return "";
135+
}
136+
137+
function buildNoticeForTypeLiterals(arg: TSLintArg): string {
138+
const { singleline, multiline } = arg;
139+
const hasTypeLiterals = (field: any) =>
140+
typeof field === "object" && Object.keys(field).includes(unsupportedKeyInEsLint);
141+
142+
if (hasTypeLiterals(singleline) || hasTypeLiterals(multiline)) {
143+
return `ESLint does not support config property ${unsupportedKeyInEsLint}`;
144+
}
145+
146+
return "";
147+
}
148+
149+
interface TSLintArg {
150+
singleline?: TSLintArgValue;
151+
multiline?: TSLintArgValue;
152+
esSpecCompliant?: boolean;
153+
}
154+
155+
type TSLintArgValue = TSLintStringValue | TSLintObject;
156+
type TSLintObjectKey = keyof TSLintObject;
157+
158+
interface TSLintObject {
159+
arrays?: TSLintStringValueForObject;
160+
objects?: TSLintStringValueForObject;
161+
functions?: TSLintStringValueForObject;
162+
imports?: TSLintStringValueForObject;
163+
exports?: TSLintStringValueForObject;
164+
typeLiterals?: TSLintStringValueForObject;
165+
}
166+
type TSLintStringValue = "always" | "never";
167+
type TSLintStringValueForObject = TSLintStringValue | "ignore";
168+
169+
// ESLint
170+
type ESLintArgValue = ESLintStringValue | ESLintObject;
171+
type ESLintStringValue = "never" | "always" | "always-multiline" | "only-multiline" | "ignore";
172+
interface ESLintObject {
173+
arrays?: ESLintStringValue;
174+
objects?: ESLintStringValue;
175+
functions?: ESLintStringValue;
176+
imports?: ESLintStringValue;
177+
exports?: ESLintStringValue;
120178
}

0 commit comments

Comments
 (0)