1
1
import { RuleConverter } from "../converter" ;
2
2
3
+ const unsupportedKeyInEsLint = "typeLiterals" ;
4
+
3
5
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 ;
8
13
9
14
return {
10
15
rules : [
11
16
{
12
17
ruleName : "comma-dangle" ,
13
18
...( eslintArgs && { ruleArguments : [ eslintArgs ] } ) ,
19
+ ...( notices && notices . length && { notices } ) ,
14
20
} ,
15
21
] ,
16
22
} ;
17
23
} ;
18
24
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 ;
22
28
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 ) ;
27
33
28
- return fields . reduce (
29
- ( acc , field ) => ( {
34
+ return keys . reduce (
35
+ ( acc , key ) => ( {
30
36
...acc ,
31
- ...collectFields ( field , single , multi ) ,
37
+ ...collectKeys ( key as TSLintObjectKey , single , multi ) ,
32
38
} ) ,
33
39
{ } ,
34
40
) ;
35
41
}
36
42
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" ;
42
45
}
43
46
44
- if ( multiline === TSLintValue . Always && singleline === TSLintValue . Always ) {
45
- return ESLintValue . Always ;
47
+ if ( singleline === "always" && multiline === "always" ) {
48
+ return "always" ;
46
49
}
47
50
48
51
return ;
49
52
}
50
53
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 ) : [ ] ;
53
60
const singlelineKeys = getKeysIfObject ( singleline ) ;
54
61
const multilineKeys = getKeysIfObject ( multiline ) ;
55
62
56
63
const uniqueKeys = [ ...new Set ( [ ...singlelineKeys , ...multilineKeys ] ) ] ;
57
- const unsupportedKeyInEsLint = "typeLiterals" ;
58
64
59
65
return uniqueKeys . filter ( field => field !== unsupportedKeyInEsLint ) ;
60
66
}
61
67
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 } {
63
73
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" ) ;
67
77
68
78
if ( ! hasSingleline && hasMultilineAlways ) {
69
79
return {
70
- [ fieldName ] : ESLintValue . AlwaysMultiline ,
80
+ [ key ] : "always-multiline" ,
71
81
} ;
72
82
}
73
83
74
84
if ( ! hasSinglelineAndFieldExist && hasMultilineAlways ) {
75
85
return {
76
- [ fieldName ] : ESLintValue . AlwaysMultiline ,
86
+ [ key ] : "always-multiline" ,
77
87
} ;
78
88
}
79
89
80
90
if ( ! hasSinglelineAlways && hasMultilineAlways ) {
81
91
return {
82
- [ fieldName ] : ESLintValue . AlwaysMultiline ,
92
+ [ key ] : "always-multiline" ,
83
93
} ;
84
94
}
85
95
86
96
if ( hasSinglelineAlways && hasMultilineAlways ) {
87
97
return {
88
- [ fieldName ] : ESLintValue . Always ,
98
+ [ key ] : "always" ,
89
99
} ;
90
100
}
91
101
92
102
return {
93
- [ fieldName ] : ESLintValue . Never ,
103
+ [ key ] : "never" ,
94
104
} ;
95
105
}
96
106
97
- function getFieldValue ( value : string | object ) {
107
+ function mapToObjectConfig ( value : TSLintArgValue ) : TSLintObject {
98
108
return typeof value === "string"
99
109
? {
100
110
arrays : value ,
@@ -106,15 +116,63 @@ function getFieldValue(value: string | object) {
106
116
: value ;
107
117
}
108
118
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
+ ) ;
112
125
}
113
126
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 ;
120
178
}
0 commit comments