Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ExtractedVariable,
extractExports,
extractFunctions,
extractVariables,
findAll,
findFirst,
findTopLevelConstants,
Expand Down Expand Up @@ -480,6 +481,18 @@ class Entry {
return parameterName(this.params[0])
}

public get nameOfConstantDefinedInBody(): string | null {
const localConstants = extractVariables(this.body).filter(
(constant) =>
constant.init?.type === AST_NODE_TYPES.ArrayExpression ||
constant.init?.type === AST_NODE_TYPES.ObjectExpression
)
if (localConstants.length) {
return localConstants[0].name || 'COLORS'
}
return null
}

public isOptimal(
constant: Readonly<Constant> | undefined,
program: Program
Expand Down Expand Up @@ -508,6 +521,11 @@ class Entry {
}
}

if (!constant && !!this.nameOfConstantDefinedInBody) {
logger.log('~> found a constant that was not declared at the top level')
return false
}

if (this.hasOneMap) {
logger.log('~> is a map solution')
return this.isOptimalMapSolution(logger, this.body, constant, program)
Expand Down Expand Up @@ -1181,6 +1199,10 @@ export class ResistorColorDuoSolution {
return this.fileConstants.length === 1
}

public get shouldExtractTopLevelConstant(): boolean {
return !this.mainConstant && !!this.entry.nameOfConstantDefinedInBody
}

public get hasOptimalEntry(): boolean {
return this.entry.isOptimal(this.mainConstant, this.program)
}
Expand Down
27 changes: 27 additions & 0 deletions src/analyzers/practice/resistor-color-duo/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,23 @@ const ISSUE_UNEXPECTED_CALL = factory<'unexpected' | 'expected'>`
CommentType.Actionable
)

const PREFER_EXTRACTED_TOP_LEVEL_CONSTANT = factory<
'value' | 'name' | 'method.signature'
>`
📕 Instead of defining the constant _inside_ the function, consider extracting it
to the top-level. Constants, functions, and classes that are not \`export\`ed,
are not accessible from outside the file.

\`\`\`javascript
const ${'name'} = ${'value'}

export ${'method.signature'}
\`\`\`
`(
'javascript.resistor-color-duo.prefer_extracted_top_level_constant',
CommentType.Actionable
)

type Program = TSESTree.Program

export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl {
Expand Down Expand Up @@ -287,6 +304,16 @@ export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl {
solution: ResistorColorDuoSolution,
output: WritableOutput
): void | never {
if (solution.shouldExtractTopLevelConstant) {
output.add(
PREFER_EXTRACTED_TOP_LEVEL_CONSTANT({
name: solution.entry.nameOfConstantDefinedInBody,
value: '...',
'method.signature': solution.entry.signature,
})
)
}

if (solution || output) {
return
}
Expand Down
Loading