diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index ab2bfc3a..7bc70ab0 100644 --- a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts +++ b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts @@ -4,6 +4,7 @@ import { ExtractedVariable, extractExports, extractFunctions, + extractVariables, findAll, findFirst, findTopLevelConstants, @@ -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 | undefined, program: Program @@ -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) @@ -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) } diff --git a/src/analyzers/practice/resistor-color-duo/index.ts b/src/analyzers/practice/resistor-color-duo/index.ts index f2356a1b..e077cb91 100644 --- a/src/analyzers/practice/resistor-color-duo/index.ts +++ b/src/analyzers/practice/resistor-color-duo/index.ts @@ -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 { @@ -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 } diff --git a/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap b/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap index e481a05c..941ec2e9 100644 --- a/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap +++ b/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap @@ -86,6 +86,33 @@ lower cognitive complexity.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/10's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 colors = ... + +export function decodedValue(input) ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "function decodedValue(input) ...", + "name": "colors", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -588,6 +615,33 @@ call\\" with a named call, that can be documented individually.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/105's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 COLORS = ... + +export const decodedValue = (resistorColors) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = (resistorColors) => ...", + "name": "COLORS", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -1187,26 +1241,62 @@ exports[`When running analysis on resistor-color-duo fixtures and expecting matc IsolatedAnalyzerOutput { "comments": Array [ CommentImpl { - "externalTemplate": "javascript.resistor-color-duo.must_use_a_helper", - "message": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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. -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", - "template": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. +\`\`\`javascript +const COLORS = ... -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", +export const decodedValue = colorArray => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = colorArray => ...", + "name": "COLORS", + "value": "...", + }, + }, + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", + "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more +strict than the \`parseXXX\` family and applies in this exercise.", + "template": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more +strict than the \`parseXXX\` family and applies in this exercise.", "type": "actionable", "variables": Object {}, }, + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.limit_number_of_colors", + "message": "💬 Limit the number of input colors that are processed. If more than two colors +are passed in, only the first two colors should be used to calculate the total +\`colorCode\` value. + +📕 (At least) one test case inputs three colors instead of two. If the student +has not accounted for this, they might need to update their solution. Help them +find the button to update. The tests won't pass without limiting the number of +colors.", + "template": "💬 Limit the number of input colors that are processed. If more than two colors +are passed in, only the first two colors should be used to calculate the total +\`colorCode\` value. + +📕 (At least) one test case inputs three colors instead of two. If the student +has not accounted for this, they might need to update their solution. Help them +find the button to update. The tests won't pass without limiting the number of +colors.", + "type": "essential", + "variables": Object {}, + }, ], "summary": undefined, } @@ -1274,6 +1364,33 @@ The tests won't pass without it.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/143's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 CODES = ... + +export const decodedValue = (colors) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = (colors) => ...", + "name": "CODES", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.use_array_comprehensions", "message": "💬 Replace \`.forEach(...)\` with a comprehension such as \`map\`.", @@ -1820,6 +1937,33 @@ strict than the \`parseXXX\` family and applies in this exercise.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/177's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 COLORS = ... + +export const decodedValue = (args) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = (args) => ...", + "name": "COLORS", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -1872,34 +2016,66 @@ exports[`When running analysis on resistor-color-duo fixtures and expecting matc IsolatedAnalyzerOutput { "comments": Array [ CommentImpl { - "externalTemplate": "javascript.resistor-color-duo.must_use_a_helper", - "message": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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. -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", - "template": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. +\`\`\`javascript +const colorMap = ... -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", +export function decodedValue([first, second]) ... +\`\`\`", + "template": "📕 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} +\`\`\`", "type": "actionable", - "variables": Object {}, + "variables": Object { + "method.signature": "function decodedValue([first, second]) ...", + "name": "colorMap", + "value": "...", + }, }, ], - "summary": undefined, } `; exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/183's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 colors = ... + +export const decodedValue = ([colorOne, colorTwo]) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = ([colorOne, colorTwo]) => ...", + "name": "colors", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -1981,24 +2157,60 @@ exports[`When running analysis on resistor-color-duo fixtures and expecting matc IsolatedAnalyzerOutput { "comments": Array [ CommentImpl { - "externalTemplate": "javascript.resistor-color-duo.must_use_a_helper", - "message": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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. -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", - "template": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. +\`\`\`javascript +const bandColors = ... -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", +export function decodedValue (colors) ... +\`\`\`", + "template": "📕 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} +\`\`\`", "type": "actionable", + "variables": Object { + "method.signature": "function decodedValue (colors) ...", + "name": "bandColors", + "value": "...", + }, + }, + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", + "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more +strict than the \`parseXXX\` family and applies in this exercise.", + "template": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more +strict than the \`parseXXX\` family and applies in this exercise.", + "type": "actionable", + "variables": Object {}, + }, + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.limit_number_of_colors", + "message": "💬 Limit the number of input colors that are processed. If more than two colors +are passed in, only the first two colors should be used to calculate the total +\`colorCode\` value. + +📕 (At least) one test case inputs three colors instead of two. If the student +has not accounted for this, they might need to update their solution. Help them +find the button to update. The tests won't pass without limiting the number of +colors.", + "template": "💬 Limit the number of input colors that are processed. If more than two colors +are passed in, only the first two colors should be used to calculate the total +\`colorCode\` value. + +📕 (At least) one test case inputs three colors instead of two. If the student +has not accounted for this, they might need to update their solution. Help them +find the button to update. The tests won't pass without limiting the number of +colors.", + "type": "essential", "variables": Object {}, }, ], @@ -2262,6 +2474,33 @@ call\\" with a named call, that can be documented individually.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/203's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 COLORS = ... + +export function decodedValue([color1, color2]) ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "function decodedValue([color1, color2]) ...", + "name": "COLORS", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -2296,6 +2535,33 @@ strict than the \`parseXXX\` family and applies in this exercise.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/205's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 COLORS = ... + +export const decodedValue = (arr) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = (arr) => ...", + "name": "COLORS", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.use_array_comprehensions", "message": "💬 Replace \`for(...) { }\` with a comprehension such as \`map\`.", @@ -2544,6 +2810,33 @@ call\\" with a named call, that can be documented individually.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/224's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 COLORS = ... + +export const decodedValue = colors => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = colors => ...", + "name": "COLORS", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -2731,6 +3024,33 @@ IsolatedAnalyzerOutput { exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/235's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 colors = ... + +export function decodedValue([color1, color2]) ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "function decodedValue([color1, color2]) ...", + "name": "colors", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more @@ -3143,6 +3463,33 @@ call\\" with a named call, that can be documented individually.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/263's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 resistor = ... + +export const decodedValue = (colorsArr) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = (colorsArr) => ...", + "name": "resistor", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.use_array_comprehensions", "message": "💬 Replace \`.forEach(...)\` with a comprehension such as \`map\`.", @@ -3440,25 +3787,31 @@ exports[`When running analysis on resistor-color-duo fixtures and expecting matc IsolatedAnalyzerOutput { "comments": Array [ CommentImpl { - "externalTemplate": "javascript.resistor-color-duo.must_use_a_helper", - "message": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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. -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", - "template": "📕 Mentor the student to add helper function and DRY-up this solution. The -solution to \`resistor-color\` can be used as helper method here. When using an -\`Array\` as colors source, in a years time, will the student recall why it's -the _index_ in that array? When using an \`Object\`, what does the value mean? -Re-using \`colorCode\` explains this in both cases. +\`\`\`javascript +const COLORS = ... -💬 Using a helper method is good practice, because it replaces a cryptic \\"member -call\\" with a named call, that can be documented individually.", +export const decodedValue = (colorArray) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", "type": "actionable", - "variables": Object {}, + "variables": Object { + "method.signature": "const decodedValue = (colorArray) => ...", + "name": "COLORS", + "value": "...", + }, }, ], "summary": undefined, @@ -3651,6 +4004,33 @@ strict than the \`parseXXX\` family and applies in this exercise.", exports[`When running analysis on resistor-color-duo fixtures and expecting matches resistor-color-duo/289's output: output 1`] = ` IsolatedAnalyzerOutput { "comments": Array [ + CommentImpl { + "externalTemplate": "javascript.resistor-color-duo.prefer_extracted_top_level_constant", + "message": "📕 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 array = ... + +export const decodedValue = (colors) => ... +\`\`\`", + "template": "📕 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} +\`\`\`", + "type": "actionable", + "variables": Object { + "method.signature": "const decodedValue = (colors) => ...", + "name": "array", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.prefer_number_over_parse", "message": "💬 Use \`Number(...)\` when the input is expected to be a number. It's more