@@ -27,6 +27,7 @@ import { assertNamedExport } from '~src/asserts/assert_named_export'
2727import { assertNamedFunction } from '~src/asserts/assert_named_function'
2828import { extractSignature } from '~src/extracts/extract_declaration'
2929import { extractNamedFunction } from '~src/extracts/extract_named_function'
30+ import { guardLiteralCaseInsensitive } from '../../utils/guard_literal_case_insensitive'
3031
3132type Node = TSESTree . Node
3233type Program = TSESTree . Program
@@ -129,6 +130,36 @@ class Constant {
129130 return false
130131 }
131132
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+
132163 public get isObjectToArray ( ) : boolean {
133164 const { init } = this . constant
134165
@@ -179,6 +210,39 @@ class Constant {
179210 } )
180211 }
181212
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+
182246 /**
183247 * In the case that the top-level constant is constructed from Object.keys(argument),
184248 * this property holds the name of the "argument".
@@ -315,15 +379,19 @@ class Entry {
315379
316380 public get hasFor ( ) : boolean {
317381 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 )
327395 ) !== undefined
328396 )
329397 }
@@ -961,7 +1029,7 @@ class Entry {
9611029 return false
9621030 }
9631031
964- if ( constant . isOptimalArray ) {
1032+ if ( constant . isOptimalArray || constant . isNonOptimalArray ) {
9651033 logger . log ( '=> constant is optimal array' )
9661034
9671035 // Only looking for:
@@ -977,7 +1045,7 @@ class Entry {
9771045 )
9781046 }
9791047
980- if ( constant . isOptimalObject ( ) ) {
1048+ if ( constant . isOptimalObject ( ) || constant . isNonOptimalObject ( ) ) {
9811049 logger . log ( '=> constant is optimal object' )
9821050
9831051 // Only looking for:
@@ -1023,13 +1091,13 @@ export class ResistorColorDuoSolution {
10231091 this . mainExport = assertNamedExport ( EXPECTED_EXPORT , exports )
10241092
10251093 // All constants at the top level that are _not_ the main method
1026- this . fileConstants = findTopLevelConstants ( program , ( [
1094+ this . fileConstants = findTopLevelConstants ( program , [
10271095 'let' ,
10281096 'const' ,
10291097 'var' ,
10301098
10311099 // TODO upstream bug
1032- ] as unknown ) as [ 'let' ] ) . filter (
1100+ ] as unknown as [ 'let' ] ) . filter (
10331101 ( declaration ) : boolean =>
10341102 declaration &&
10351103 guardIdentifier ( declaration . id ) &&
0 commit comments