@@ -27,6 +27,7 @@ import { assertNamedExport } from '~src/asserts/assert_named_export'
27
27
import { assertNamedFunction } from '~src/asserts/assert_named_function'
28
28
import { extractSignature } from '~src/extracts/extract_declaration'
29
29
import { extractNamedFunction } from '~src/extracts/extract_named_function'
30
+ import { guardLiteralCaseInsensitive } from '../../utils/guard_literal_case_insensitive'
30
31
31
32
type Node = TSESTree . Node
32
33
type Program = TSESTree . Program
@@ -129,6 +130,36 @@ class Constant {
129
130
return false
130
131
}
131
132
133
+ public get isNonOptimalArray ( ) : boolean {
134
+ const { init } = this . constant
135
+
136
+ if ( ! init ) {
137
+ return false
138
+ }
139
+
140
+ const literals = [
141
+ 'black' ,
142
+ 'brown' ,
143
+ 'red' ,
144
+ 'orange' ,
145
+ 'yellow' ,
146
+ 'green' ,
147
+ 'blue' ,
148
+ 'violet' ,
149
+ 'grey' ,
150
+ 'white' ,
151
+ ]
152
+
153
+ if ( init . type === AST_NODE_TYPES . ArrayExpression ) {
154
+ // Each literal needs to be present, and needs to be present exactly in this order
155
+ return init . elements . every ( ( value , index ) : boolean =>
156
+ guardLiteralCaseInsensitive ( value , literals [ index ] )
157
+ )
158
+ }
159
+
160
+ return false
161
+ }
162
+
132
163
public get isObjectToArray ( ) : boolean {
133
164
const { init } = this . constant
134
165
@@ -179,6 +210,39 @@ class Constant {
179
210
} )
180
211
}
181
212
213
+ public isNonOptimalObject (
214
+ node : ExtractedVariable | undefined = this . constant
215
+ ) : boolean {
216
+ if ( ! node || ! node . init ) {
217
+ return false
218
+ }
219
+
220
+ if ( node . init . type !== AST_NODE_TYPES . ObjectExpression ) {
221
+ return false
222
+ }
223
+
224
+ const keys = [
225
+ 'black' ,
226
+ 'brown' ,
227
+ 'red' ,
228
+ 'orange' ,
229
+ 'yellow' ,
230
+ 'green' ,
231
+ 'blue' ,
232
+ 'violet' ,
233
+ 'grey' ,
234
+ 'white' ,
235
+ ]
236
+
237
+ return node . init . properties . every ( ( property , index ) : boolean => {
238
+ return (
239
+ property . type === AST_NODE_TYPES . Property &&
240
+ guardLiteralCaseInsensitive ( property . key , keys [ index ] ) &&
241
+ guardLiteral ( property . value , index )
242
+ )
243
+ } )
244
+ }
245
+
182
246
/**
183
247
* In the case that the top-level constant is constructed from Object.keys(argument),
184
248
* this property holds the name of the "argument".
@@ -315,15 +379,19 @@ class Entry {
315
379
316
380
public get hasFor ( ) : boolean {
317
381
return (
318
- findFirst ( this . body , ( node ) : node is
319
- | TSESTree . ForInStatement
320
- | TSESTree . ForOfStatement
321
- | TSESTree . ForStatement =>
322
- [
323
- AST_NODE_TYPES . ForInStatement ,
324
- AST_NODE_TYPES . ForOfStatement ,
325
- AST_NODE_TYPES . ForStatement ,
326
- ] . some ( ( type ) => type === node . type )
382
+ findFirst (
383
+ this . body ,
384
+ (
385
+ node
386
+ ) : node is
387
+ | TSESTree . ForInStatement
388
+ | TSESTree . ForOfStatement
389
+ | TSESTree . ForStatement =>
390
+ [
391
+ AST_NODE_TYPES . ForInStatement ,
392
+ AST_NODE_TYPES . ForOfStatement ,
393
+ AST_NODE_TYPES . ForStatement ,
394
+ ] . some ( ( type ) => type === node . type )
327
395
) !== undefined
328
396
)
329
397
}
@@ -961,7 +1029,7 @@ class Entry {
961
1029
return false
962
1030
}
963
1031
964
- if ( constant . isOptimalArray ) {
1032
+ if ( constant . isOptimalArray || constant . isNonOptimalArray ) {
965
1033
logger . log ( '=> constant is optimal array' )
966
1034
967
1035
// Only looking for:
@@ -977,7 +1045,7 @@ class Entry {
977
1045
)
978
1046
}
979
1047
980
- if ( constant . isOptimalObject ( ) ) {
1048
+ if ( constant . isOptimalObject ( ) || constant . isNonOptimalObject ( ) ) {
981
1049
logger . log ( '=> constant is optimal object' )
982
1050
983
1051
// Only looking for:
@@ -1023,13 +1091,13 @@ export class ResistorColorDuoSolution {
1023
1091
this . mainExport = assertNamedExport ( EXPECTED_EXPORT , exports )
1024
1092
1025
1093
// All constants at the top level that are _not_ the main method
1026
- this . fileConstants = findTopLevelConstants ( program , ( [
1094
+ this . fileConstants = findTopLevelConstants ( program , [
1027
1095
'let' ,
1028
1096
'const' ,
1029
1097
'var' ,
1030
1098
1031
1099
// TODO upstream bug
1032
- ] as unknown ) as [ 'let' ] ) . filter (
1100
+ ] as unknown as [ 'let' ] ) . filter (
1033
1101
( declaration ) : boolean =>
1034
1102
declaration &&
1035
1103
guardIdentifier ( declaration . id ) &&
0 commit comments