Skip to content

Commit 7439d03

Browse files
authored
[Resistor Duo analyzer (#127)] Add feedback to extract the constant to the top level if defined locally (#164)
* [Resistor Duo analyzer] Add feedback to extract the constant to the top level if defined locally * [Resistor Duo analyzer] Update snapshot tests * [Resistor Duo analyzer] Fix linting errors * [Resistor Duo solution] Remove unused variable * [Resistor Duo analyzer] Undo change to TSESTree import * [Resistor Duo analyzer (#127)] Rename helper method * [Resistor Duo analyzer (#127)] Implement requested changes * [Resistor Duo analyzer (#127)] Add exported method signature to the tip
1 parent 345f7a6 commit 7439d03

File tree

3 files changed

+492
-63
lines changed

3 files changed

+492
-63
lines changed

src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ExtractedVariable,
55
extractExports,
66
extractFunctions,
7+
extractVariables,
78
findAll,
89
findFirst,
910
findTopLevelConstants,
@@ -480,6 +481,18 @@ class Entry {
480481
return parameterName(this.params[0])
481482
}
482483

484+
public get nameOfConstantDefinedInBody(): string | null {
485+
const localConstants = extractVariables(this.body).filter(
486+
(constant) =>
487+
constant.init?.type === AST_NODE_TYPES.ArrayExpression ||
488+
constant.init?.type === AST_NODE_TYPES.ObjectExpression
489+
)
490+
if (localConstants.length) {
491+
return localConstants[0].name || 'COLORS'
492+
}
493+
return null
494+
}
495+
483496
public isOptimal(
484497
constant: Readonly<Constant> | undefined,
485498
program: Program
@@ -508,6 +521,11 @@ class Entry {
508521
}
509522
}
510523

524+
if (!constant && !!this.nameOfConstantDefinedInBody) {
525+
logger.log('~> found a constant that was not declared at the top level')
526+
return false
527+
}
528+
511529
if (this.hasOneMap) {
512530
logger.log('~> is a map solution')
513531
return this.isOptimalMapSolution(logger, this.body, constant, program)
@@ -1181,6 +1199,10 @@ export class ResistorColorDuoSolution {
11811199
return this.fileConstants.length === 1
11821200
}
11831201

1202+
public get shouldExtractTopLevelConstant(): boolean {
1203+
return !this.mainConstant && !!this.entry.nameOfConstantDefinedInBody
1204+
}
1205+
11841206
public get hasOptimalEntry(): boolean {
11851207
return this.entry.isOptimal(this.mainConstant, this.program)
11861208
}

src/analyzers/practice/resistor-color-duo/index.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,23 @@ const ISSUE_UNEXPECTED_CALL = factory<'unexpected' | 'expected'>`
120120
CommentType.Actionable
121121
)
122122

123+
const PREFER_EXTRACTED_TOP_LEVEL_CONSTANT = factory<
124+
'value' | 'name' | 'method.signature'
125+
>`
126+
📕 Instead of defining the constant _inside_ the function, consider extracting it
127+
to the top-level. Constants, functions, and classes that are not \`export\`ed,
128+
are not accessible from outside the file.
129+
130+
\`\`\`javascript
131+
const ${'name'} = ${'value'}
132+
133+
export ${'method.signature'}
134+
\`\`\`
135+
`(
136+
'javascript.resistor-color-duo.prefer_extracted_top_level_constant',
137+
CommentType.Actionable
138+
)
139+
123140
type Program = TSESTree.Program
124141

125142
export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl {
@@ -287,6 +304,16 @@ export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl {
287304
solution: ResistorColorDuoSolution,
288305
output: WritableOutput
289306
): void | never {
307+
if (solution.shouldExtractTopLevelConstant) {
308+
output.add(
309+
PREFER_EXTRACTED_TOP_LEVEL_CONSTANT({
310+
name: solution.entry.nameOfConstantDefinedInBody,
311+
value: '...',
312+
'method.signature': solution.entry.signature,
313+
})
314+
)
315+
}
316+
290317
if (solution || output) {
291318
return
292319
}

0 commit comments

Comments
 (0)