From 55c94759382dc300f48edeaababd78728e5bcf30 Mon Sep 17 00:00:00 2001 From: Steffe-Dev Date: Thu, 13 Feb 2025 20:28:51 +0200 Subject: [PATCH 1/8] [Resistor Duo analyzer] Add feedback to extract the constant to the top level if defined locally --- .../ResistorColorDuoSolution.ts | 32 ++++++++++++++++++- .../practice/resistor-color-duo/index.ts | 23 +++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index ab2bfc3a..ec892b3c 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, @@ -20,7 +21,7 @@ import { SpecificObjectPropertyCall, SpecificPropertyCall, } from '@exercism/static-analysis' -import type { TSESTree } from '@typescript-eslint/typescript-estree' +import { TSESTree } from '@typescript-eslint/typescript-estree' import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree' import { Source } from '~src/analyzers/SourceImpl' import { parameterName } from '~src/analyzers/utils/extract_parameter' @@ -73,6 +74,10 @@ export class UnexpectedCallFound { ) {} } +export class ShouldDefineTopLevelConstant { + constructor(public readonly name: string, public readonly value: string) {} +} + type Issue = | undefined | MissingExpectedCall @@ -80,6 +85,7 @@ type Issue = | MethodNotFound | HelperCallNotFound | UnexpectedCallFound + | ShouldDefineTopLevelConstant class Constant { public readonly name: string @@ -508,6 +514,15 @@ class Entry { } } + if (!constant) { + const issue = this.checkForShouldDefineTopLevelConstantIssue() + if (issue instanceof ShouldDefineTopLevelConstant) { + logger.log('~> found a constant that was not declared at the top level') + this.lastIssue_ = issue + return false + } + } + if (this.hasOneMap) { logger.log('~> is a map solution') return this.isOptimalMapSolution(logger, this.body, constant, program) @@ -1111,6 +1126,20 @@ class Entry { logger.log(`~> constant is not optimal`) return false } + + private checkForShouldDefineTopLevelConstantIssue(): + | ShouldDefineTopLevelConstant + | undefined { + const localConstants = extractVariables(this.body).filter( + (constant) => + constant.init?.type === TSESTree.AST_NODE_TYPES.ArrayExpression || + constant.init?.type === TSESTree.AST_NODE_TYPES.ObjectExpression + ) + if (localConstants.length) { + const nameOfFirstConstant = localConstants[0].name || 'COLORS' + return new ShouldDefineTopLevelConstant(nameOfFirstConstant, '...') + } + } } export class ResistorColorDuoSolution { @@ -1120,6 +1149,7 @@ export class ResistorColorDuoSolution { private mainExport: ExtractedExport private fileConstants: ProgramConstants private mainConstant: Constant | undefined + private _hasLocalConstant = false constructor(public readonly program: Program, source: string) { this.source = new Source(source) diff --git a/src/analyzers/practice/resistor-color-duo/index.ts b/src/analyzers/practice/resistor-color-duo/index.ts index f2356a1b..a3ac651d 100644 --- a/src/analyzers/practice/resistor-color-duo/index.ts +++ b/src/analyzers/practice/resistor-color-duo/index.ts @@ -21,6 +21,7 @@ import { MethodNotFound, MissingExpectedCall, ResistorColorDuoSolution, + ShouldDefineTopLevelConstant, UnexpectedCallFound, } from './ResistorColorDuoSolution' @@ -120,6 +121,21 @@ const ISSUE_UNEXPECTED_CALL = factory<'unexpected' | 'expected'>` CommentType.Actionable ) +const PREFER_EXTRACTED_TOP_LEVEL_CONSTANT = factory<'value' | 'name'>` +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 const decodedValue = (...) +\`\`\` +`( + 'javascript.resistor-color-duo.prefer_extracted_top_level_constant', + CommentType.Actionable +) + type Program = TSESTree.Program export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl { @@ -275,6 +291,13 @@ export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl { } output.disapprove() + } else if (lastIssue instanceof ShouldDefineTopLevelConstant) { + output.add( + PREFER_EXTRACTED_TOP_LEVEL_CONSTANT({ + name: lastIssue.name, + value: lastIssue.value, + }) + ) } else { this.logger.error( 'The analyzer did not handle the issue: ' + JSON.stringify(lastIssue) From 49e36641f8c9f68541998c545dbb945fe4b59de2 Mon Sep 17 00:00:00 2001 From: Steffe-Dev Date: Thu, 13 Feb 2025 20:45:58 +0200 Subject: [PATCH 2/8] [Resistor Duo analyzer] Update snapshot tests --- .../__snapshots__/snapshot.ts.snap | 491 +++++++++++++++--- 1 file changed, 428 insertions(+), 63 deletions(-) diff --git a/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap b/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap index e481a05c..20fdbb03 100644 --- a/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap +++ b/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap @@ -86,6 +86,32 @@ 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 const decodedValue = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 +614,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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,24 +1239,59 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", "type": "actionable", + "variables": Object { + "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 {}, }, ], @@ -1274,6 +1361,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "name": "CODES", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.use_array_comprehensions", "message": "💬 Replace \`.forEach(...)\` with a comprehension such as \`map\`.", @@ -1820,6 +1933,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 +2011,64 @@ 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 const decodedValue = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", "type": "actionable", - "variables": Object {}, + "variables": Object { + "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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 +2150,59 @@ 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 const decodedValue = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", "type": "actionable", + "variables": Object { + "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 +2466,32 @@ 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 const decodedValue = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 +2526,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "name": "COLORS", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.use_array_comprehensions", "message": "💬 Replace \`for(...) { }\` with a comprehension such as \`map\`.", @@ -2544,6 +2800,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 +3013,32 @@ 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 const decodedValue = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 +3451,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "name": "resistor", + "value": "...", + }, + }, CommentImpl { "externalTemplate": "javascript.resistor-color-duo.use_array_comprehensions", "message": "💬 Replace \`.forEach(...)\` with a comprehension such as \`map\`.", @@ -3440,25 +3774,30 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", "type": "actionable", - "variables": Object {}, + "variables": Object { + "name": "COLORS", + "value": "...", + }, }, ], "summary": undefined, @@ -3651,6 +3990,32 @@ 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 = (...) +\`\`\`", + "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 const decodedValue = (...) +\`\`\`", + "type": "actionable", + "variables": Object { + "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 From aab6d9f67abe9ef09f3544c88273cbcce496c495 Mon Sep 17 00:00:00 2001 From: Steffe-Dev Date: Thu, 13 Feb 2025 20:48:13 +0200 Subject: [PATCH 3/8] [Resistor Duo analyzer] Fix linting errors --- .../practice/resistor-color-duo/ResistorColorDuoSolution.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index ec892b3c..241a4f77 100644 --- a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts +++ b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts @@ -21,8 +21,7 @@ import { SpecificObjectPropertyCall, SpecificPropertyCall, } from '@exercism/static-analysis' -import { TSESTree } from '@typescript-eslint/typescript-estree' -import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree' +import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree' import { Source } from '~src/analyzers/SourceImpl' import { parameterName } from '~src/analyzers/utils/extract_parameter' import { assertNamedExport } from '~src/asserts/assert_named_export' From 5d5076c5c5c2235c40f4479eb45a0a3119e3611b Mon Sep 17 00:00:00 2001 From: Steffe-Dev Date: Thu, 13 Feb 2025 20:57:51 +0200 Subject: [PATCH 4/8] [Resistor Duo solution] Remove unused variable --- .../practice/resistor-color-duo/ResistorColorDuoSolution.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index 241a4f77..84f3a6e9 100644 --- a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts +++ b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts @@ -1148,7 +1148,6 @@ export class ResistorColorDuoSolution { private mainExport: ExtractedExport private fileConstants: ProgramConstants private mainConstant: Constant | undefined - private _hasLocalConstant = false constructor(public readonly program: Program, source: string) { this.source = new Source(source) From b6180501e3baccd4ae4d3350da0868431bd31020 Mon Sep 17 00:00:00 2001 From: Frans Date: Wed, 19 Feb 2025 16:51:30 +0200 Subject: [PATCH 5/8] [Resistor Duo analyzer] Undo change to TSESTree import --- .../resistor-color-duo/ResistorColorDuoSolution.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index 84f3a6e9..84716200 100644 --- a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts +++ b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts @@ -21,7 +21,8 @@ import { SpecificObjectPropertyCall, SpecificPropertyCall, } from '@exercism/static-analysis' -import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/typescript-estree' +import type { TSESTree } from '@typescript-eslint/typescript-estree' +import { AST_NODE_TYPES } from '@typescript-eslint/typescript-estree' import { Source } from '~src/analyzers/SourceImpl' import { parameterName } from '~src/analyzers/utils/extract_parameter' import { assertNamedExport } from '~src/asserts/assert_named_export' @@ -1131,8 +1132,8 @@ class Entry { | undefined { const localConstants = extractVariables(this.body).filter( (constant) => - constant.init?.type === TSESTree.AST_NODE_TYPES.ArrayExpression || - constant.init?.type === TSESTree.AST_NODE_TYPES.ObjectExpression + constant.init?.type === AST_NODE_TYPES.ArrayExpression || + constant.init?.type === AST_NODE_TYPES.ObjectExpression ) if (localConstants.length) { const nameOfFirstConstant = localConstants[0].name || 'COLORS' From 11cd9bec4e482927385eee61d2b1ca1a204f57c1 Mon Sep 17 00:00:00 2001 From: Frans Date: Thu, 20 Feb 2025 19:33:51 +0200 Subject: [PATCH 6/8] [Resistor Duo analyzer (#127)] Rename helper method --- .../practice/resistor-color-duo/ResistorColorDuoSolution.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index 84716200..f7f82bef 100644 --- a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts +++ b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts @@ -515,7 +515,7 @@ class Entry { } if (!constant) { - const issue = this.checkForShouldDefineTopLevelConstantIssue() + const issue = this.hasConstantDefinedInBody() if (issue instanceof ShouldDefineTopLevelConstant) { logger.log('~> found a constant that was not declared at the top level') this.lastIssue_ = issue @@ -1127,9 +1127,7 @@ class Entry { return false } - private checkForShouldDefineTopLevelConstantIssue(): - | ShouldDefineTopLevelConstant - | undefined { + private hasConstantDefinedInBody(): ShouldDefineTopLevelConstant | undefined { const localConstants = extractVariables(this.body).filter( (constant) => constant.init?.type === AST_NODE_TYPES.ArrayExpression || From 1b7b12051357dde570cfb0df5ae68a3d3c2825d8 Mon Sep 17 00:00:00 2001 From: Frans Stefanus Bothma Date: Wed, 5 Mar 2025 21:07:13 +0200 Subject: [PATCH 7/8] [Resistor Duo analyzer (#127)] Implement requested changes --- .../ResistorColorDuoSolution.ts | 43 ++++++++----------- .../practice/resistor-color-duo/index.ts | 17 ++++---- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts index f7f82bef..7bc70ab0 100644 --- a/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts +++ b/src/analyzers/practice/resistor-color-duo/ResistorColorDuoSolution.ts @@ -74,10 +74,6 @@ export class UnexpectedCallFound { ) {} } -export class ShouldDefineTopLevelConstant { - constructor(public readonly name: string, public readonly value: string) {} -} - type Issue = | undefined | MissingExpectedCall @@ -85,7 +81,6 @@ type Issue = | MethodNotFound | HelperCallNotFound | UnexpectedCallFound - | ShouldDefineTopLevelConstant class Constant { public readonly name: string @@ -486,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 @@ -514,13 +521,9 @@ class Entry { } } - if (!constant) { - const issue = this.hasConstantDefinedInBody() - if (issue instanceof ShouldDefineTopLevelConstant) { - logger.log('~> found a constant that was not declared at the top level') - this.lastIssue_ = issue - return false - } + if (!constant && !!this.nameOfConstantDefinedInBody) { + logger.log('~> found a constant that was not declared at the top level') + return false } if (this.hasOneMap) { @@ -1126,18 +1129,6 @@ class Entry { logger.log(`~> constant is not optimal`) return false } - - private hasConstantDefinedInBody(): ShouldDefineTopLevelConstant | undefined { - const localConstants = extractVariables(this.body).filter( - (constant) => - constant.init?.type === AST_NODE_TYPES.ArrayExpression || - constant.init?.type === AST_NODE_TYPES.ObjectExpression - ) - if (localConstants.length) { - const nameOfFirstConstant = localConstants[0].name || 'COLORS' - return new ShouldDefineTopLevelConstant(nameOfFirstConstant, '...') - } - } } export class ResistorColorDuoSolution { @@ -1208,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 a3ac651d..685fe161 100644 --- a/src/analyzers/practice/resistor-color-duo/index.ts +++ b/src/analyzers/practice/resistor-color-duo/index.ts @@ -21,7 +21,6 @@ import { MethodNotFound, MissingExpectedCall, ResistorColorDuoSolution, - ShouldDefineTopLevelConstant, UnexpectedCallFound, } from './ResistorColorDuoSolution' @@ -291,13 +290,6 @@ export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl { } output.disapprove() - } else if (lastIssue instanceof ShouldDefineTopLevelConstant) { - output.add( - PREFER_EXTRACTED_TOP_LEVEL_CONSTANT({ - name: lastIssue.name, - value: lastIssue.value, - }) - ) } else { this.logger.error( 'The analyzer did not handle the issue: ' + JSON.stringify(lastIssue) @@ -310,6 +302,15 @@ 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: '...', + }) + ) + } + if (solution || output) { return } From 53eef20b5bf17effe87f6dd0105d7b4724004113 Mon Sep 17 00:00:00 2001 From: Frans Stefanus Bothma Date: Thu, 6 Mar 2025 18:45:35 +0200 Subject: [PATCH 8/8] [Resistor Duo analyzer (exercism#127)] Add exported method signature to the tip --- .../practice/resistor-color-duo/index.ts | 9 +- .../__snapshots__/snapshot.ts.snap | 135 ++++++++++-------- 2 files changed, 81 insertions(+), 63 deletions(-) diff --git a/src/analyzers/practice/resistor-color-duo/index.ts b/src/analyzers/practice/resistor-color-duo/index.ts index 685fe161..e077cb91 100644 --- a/src/analyzers/practice/resistor-color-duo/index.ts +++ b/src/analyzers/practice/resistor-color-duo/index.ts @@ -120,15 +120,17 @@ const ISSUE_UNEXPECTED_CALL = factory<'unexpected' | 'expected'>` CommentType.Actionable ) -const PREFER_EXTRACTED_TOP_LEVEL_CONSTANT = factory<'value' | 'name'>` -Instead of defining the constant _inside_ the function, consider extracting it +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 const decodedValue = (...) +export ${'method.signature'} \`\`\` `( 'javascript.resistor-color-duo.prefer_extracted_top_level_constant', @@ -307,6 +309,7 @@ export class ResistorColorDuoAnalyzer extends IsolatedAnalyzerImpl { PREFER_EXTRACTED_TOP_LEVEL_CONSTANT({ name: solution.entry.nameOfConstantDefinedInBody, value: '...', + 'method.signature': solution.entry.signature, }) ) } diff --git a/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap b/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap index 20fdbb03..941ec2e9 100644 --- a/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap +++ b/test/analyzers/resistor-color-duo/__snapshots__/snapshot.ts.snap @@ -88,26 +88,27 @@ 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 + "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 = (...) +export function decodedValue(input) ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "function decodedValue(input) ...", "name": "colors", "value": "...", }, @@ -616,26 +617,27 @@ 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 + "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 = (...) +export const decodedValue = (resistorColors) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (resistorColors) => ...", "name": "COLORS", "value": "...", }, @@ -1240,26 +1242,27 @@ 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 + "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 = (...) +export const decodedValue = colorArray => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = colorArray => ...", "name": "COLORS", "value": "...", }, @@ -1363,26 +1366,27 @@ 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 + "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 = (...) +export const decodedValue = (colors) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (colors) => ...", "name": "CODES", "value": "...", }, @@ -1935,26 +1939,27 @@ 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 + "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 = (...) +export const decodedValue = (args) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (args) => ...", "name": "COLORS", "value": "...", }, @@ -2012,26 +2017,27 @@ 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 + "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 colorMap = ... -export const decodedValue = (...) +export function decodedValue([first, second]) ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "function decodedValue([first, second]) ...", "name": "colorMap", "value": "...", }, @@ -2045,26 +2051,27 @@ 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 + "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 = (...) +export const decodedValue = ([colorOne, colorTwo]) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = ([colorOne, colorTwo]) => ...", "name": "colors", "value": "...", }, @@ -2151,26 +2158,27 @@ 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 + "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 bandColors = ... -export const decodedValue = (...) +export function decodedValue (colors) ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "function decodedValue (colors) ...", "name": "bandColors", "value": "...", }, @@ -2468,26 +2476,27 @@ 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 + "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 = (...) +export function decodedValue([color1, color2]) ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "function decodedValue([color1, color2]) ...", "name": "COLORS", "value": "...", }, @@ -2528,26 +2537,27 @@ 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 + "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 = (...) +export const decodedValue = (arr) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (arr) => ...", "name": "COLORS", "value": "...", }, @@ -2802,26 +2812,27 @@ 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 + "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 = (...) +export const decodedValue = colors => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = colors => ...", "name": "COLORS", "value": "...", }, @@ -3015,26 +3026,27 @@ 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 + "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 = (...) +export function decodedValue([color1, color2]) ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "function decodedValue([color1, color2]) ...", "name": "colors", "value": "...", }, @@ -3453,26 +3465,27 @@ 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 + "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 = (...) +export const decodedValue = (colorsArr) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (colorsArr) => ...", "name": "resistor", "value": "...", }, @@ -3775,26 +3788,27 @@ 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 + "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 = (...) +export const decodedValue = (colorArray) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (colorArray) => ...", "name": "COLORS", "value": "...", }, @@ -3992,26 +4006,27 @@ 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 + "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 = (...) +export const decodedValue = (colors) => ... \`\`\`", - "template": "Instead of defining the constant _inside_ the function, consider extracting it + "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 const decodedValue = (...) +export %{method.signature} \`\`\`", "type": "actionable", "variables": Object { + "method.signature": "const decodedValue = (colors) => ...", "name": "array", "value": "...", },