From 4d1887cb73ad7b799f73f57e211a9f2b97f32933 Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Mon, 23 Sep 2024 19:48:19 +0300 Subject: [PATCH 1/3] fix no-unnecessary-template-expression to include template syntax with a squiggly --- .../rules/explicit-member-accessibility.ts | 11 +- .../no-unnecessary-template-expression.ts | 19 +-- packages/eslint-plugin/src/util/rangeToLoc.ts | 11 ++ .../no-unnecessary-template-expression.shot | 18 +-- ...no-unnecessary-template-expression.test.ts | 115 +++++++++--------- 5 files changed, 91 insertions(+), 83 deletions(-) create mode 100644 packages/eslint-plugin/src/util/rangeToLoc.ts diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index 2661949b57d7..3bf70eb8bb74 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -11,6 +11,7 @@ import { getMemberHeadLoc, getParameterPropertyHeadLoc, } from '../util/getMemberHeadLoc'; +import { rangeToLoc } from '../util/rangeToLoc'; type AccessibilityLevel = | 'explicit' // require an accessor (including public) @@ -387,13 +388,3 @@ export default createRule({ }; }, }); - -function rangeToLoc( - sourceCode: TSESLint.SourceCode, - range: TSESLint.AST.Range, -): TSESTree.SourceLocation { - return { - start: sourceCode.getLocFromIndex(range[0]), - end: sourceCode.getLocFromIndex(range[1]), - }; -} diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts b/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts index dc15a9bbcd06..a637c0a67deb 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts @@ -10,6 +10,7 @@ import { isTypeFlagSet, isUndefinedIdentifier, } from '../util'; +import { rangeToLoc } from '../util/rangeToLoc'; type MessageId = 'noUnnecessaryTemplateExpression'; @@ -106,6 +107,10 @@ export default createRule<[], MessageId>({ if (hasSingleStringVariable) { context.report({ node: node.expressions[0], + loc: rangeToLoc(context.sourceCode, [ + node.expressions[0].range[0] - 2, + node.expressions[0].range[1] + 1, + ]), messageId: 'noUnnecessaryTemplateExpression', fix(fixer): TSESLint.RuleFix | null { const wrappingCode = getMovedNodeCode({ @@ -245,20 +250,18 @@ export default createRule<[], MessageId>({ ]); } + const warnLocStart = prevQuasi.range[1] - 2; + const warnLocEnd = nextQuasi.range[0] + 1; + context.report({ node: expression, + loc: rangeToLoc(context.sourceCode, [warnLocStart, warnLocEnd]), messageId: 'noUnnecessaryTemplateExpression', fix(fixer): TSESLint.RuleFix[] { return [ // Remove the quasis' parts that are related to the current expression. - fixer.removeRange([ - prevQuasi.range[1] - 2, - expression.range[0], - ]), - fixer.removeRange([ - expression.range[1], - nextQuasi.range[0] + 1, - ]), + fixer.removeRange([warnLocStart, expression.range[0]]), + fixer.removeRange([expression.range[1], warnLocEnd]), ...fixers.flatMap(cb => cb(fixer)), ]; diff --git a/packages/eslint-plugin/src/util/rangeToLoc.ts b/packages/eslint-plugin/src/util/rangeToLoc.ts new file mode 100644 index 000000000000..893362d3a722 --- /dev/null +++ b/packages/eslint-plugin/src/util/rangeToLoc.ts @@ -0,0 +1,11 @@ +import type { TSESLint, TSESTree } from '@typescript-eslint/utils'; + +export function rangeToLoc( + sourceCode: TSESLint.SourceCode, + range: TSESLint.AST.Range, +): TSESTree.SourceLocation { + return { + start: sourceCode.getLocFromIndex(range[0]), + end: sourceCode.getLocFromIndex(range[1]), + }; +} diff --git a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-template-expression.shot b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-template-expression.shot index d6062501d837..47aa863d7203 100644 --- a/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-template-expression.shot +++ b/packages/eslint-plugin/tests/docs-eslint-output-snapshots/no-unnecessary-template-expression.shot @@ -6,29 +6,29 @@ exports[`Validating rule docs no-unnecessary-template-expression.mdx code exampl // Static values can be incorporated into the surrounding template. const ab1 = \`\${'a'}\${'b'}\`; - ~~~ Template literal expression is unnecessary and can be simplified. - ~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~ Template literal expression is unnecessary and can be simplified. const ab2 = \`a\${'b'}\`; - ~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~ Template literal expression is unnecessary and can be simplified. const stringWithNumber = \`\${'1 + 1 = '}\${2}\`; - ~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. - ~ Template literal expression is unnecessary and can be simplified. + ~~~~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~ Template literal expression is unnecessary and can be simplified. const stringWithBoolean = \`\${'true is '}\${true}\`; - ~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. - ~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~~ Template literal expression is unnecessary and can be simplified. // Some simple expressions that are already strings // can be rewritten without a template at all. const text = 'a'; const wrappedText = \`\${text}\`; - ~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~~ Template literal expression is unnecessary and can be simplified. declare const intersectionWithString: string & { _brand: 'test-brand' }; const wrappedIntersection = \`\${intersectionWithString}\`; - ~~~~~~~~~~~~~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. + ~~~~~~~~~~~~~~~~~~~~~~~~~ Template literal expression is unnecessary and can be simplified. " `; diff --git a/packages/eslint-plugin/tests/rules/no-unnecessary-template-expression.test.ts b/packages/eslint-plugin/tests/rules/no-unnecessary-template-expression.test.ts index 3902b404d9ec..d37c24f5c193 100644 --- a/packages/eslint-plugin/tests/rules/no-unnecessary-template-expression.test.ts +++ b/packages/eslint-plugin/tests/rules/no-unnecessary-template-expression.test.ts @@ -26,8 +26,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 5, + column: 2, + endColumn: 6, }, ], }, @@ -38,8 +38,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 6, + column: 2, + endColumn: 7, }, ], }, @@ -50,8 +50,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 8, + column: 2, + endColumn: 9, }, ], }, @@ -62,14 +62,14 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 10, + column: 2, + endColumn: 11, }, { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 14, - endColumn: 20, + column: 12, + endColumn: 21, }, ], }, @@ -80,8 +80,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 8, + column: 2, + endColumn: 9, }, ], }, @@ -92,8 +92,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 7, + column: 2, + endColumn: 8, }, ], }, @@ -104,8 +104,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 10, + column: 2, + endColumn: 11, }, ], }, @@ -157,8 +157,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 8, + column: 2, + endColumn: 9, }, ], }, @@ -180,8 +180,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 8, + column: 2, + endColumn: 9, }, ], }, @@ -203,8 +203,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 13, + column: 2, + endColumn: 14, }, ], }, @@ -226,8 +226,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 12, + column: 2, + endColumn: 13, }, ], }, @@ -239,8 +239,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 7, + column: 2, + endColumn: 8, }, ], }, @@ -252,14 +252,14 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 7, + column: 2, + endColumn: 8, }, { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 11, - endColumn: 14, + column: 9, + endColumn: 15, }, ], }, @@ -321,19 +321,21 @@ const invalidCases: readonly InvalidTestCase< errors: [ { messageId: 'noUnnecessaryTemplateExpression', - line: 4, + line: 2, }, { messageId: 'noUnnecessaryTemplateExpression', - line: 7, - column: 3, - endLine: 7, + line: 6, + column: 2, + endLine: 8, + endColumn: 2, }, { messageId: 'noUnnecessaryTemplateExpression', line: 7, - column: 10, + column: 6, endLine: 7, + endColumn: 17, }, ], }, @@ -349,9 +351,10 @@ const invalidCases: readonly InvalidTestCase< errors: [ { messageId: 'noUnnecessaryTemplateExpression', - line: 3, - column: 3, - endColumn: 9, + line: 2, + column: 5, + endLine: 4, + endColumn: 2, }, ], }, @@ -363,14 +366,14 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 13, + column: 2, + endColumn: 14, }, { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 17, - endColumn: 18, + column: 15, + endColumn: 19, }, ], }, @@ -382,14 +385,14 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 7, + column: 2, + endColumn: 8, }, { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 11, - endColumn: 15, + column: 9, + endColumn: 16, }, ], }, @@ -401,8 +404,8 @@ const invalidCases: readonly InvalidTestCase< { messageId: 'noUnnecessaryTemplateExpression', line: 1, - column: 4, - endColumn: 30, + column: 2, + endColumn: 31, }, ], }, @@ -1038,8 +1041,8 @@ ruleTester.run('no-unnecessary-template-expression', rule, { { messageId: 'noUnnecessaryTemplateExpression', line: 3, - column: 14, - endColumn: 17, + column: 12, + endColumn: 18, }, ], }, @@ -1056,8 +1059,8 @@ ruleTester.run('no-unnecessary-template-expression', rule, { { messageId: 'noUnnecessaryTemplateExpression', line: 3, - column: 17, - endColumn: 20, + column: 15, + endColumn: 21, }, ], }, @@ -1104,8 +1107,8 @@ declare const nested: string, interpolation: string; { messageId: 'noUnnecessaryTemplateExpression', line: 3, - column: 12, - endColumn: 18, + column: 10, + endColumn: 19, }, ], }, @@ -1122,8 +1125,8 @@ declare const nested: string, interpolation: string; { messageId: 'noUnnecessaryTemplateExpression', line: 3, - column: 12, - endColumn: 24, + column: 10, + endColumn: 25, }, ], }, From 904386fbcce247e39434a9fc48d53d526b5d839d Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Mon, 23 Sep 2024 20:57:45 +0300 Subject: [PATCH 2/3] Update packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts Co-authored-by: Kirk Waiblinger --- .../src/rules/no-unnecessary-template-expression.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts b/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts index a637c0a67deb..a45cade4c9a7 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts @@ -106,7 +106,6 @@ export default createRule<[], MessageId>({ if (hasSingleStringVariable) { context.report({ - node: node.expressions[0], loc: rangeToLoc(context.sourceCode, [ node.expressions[0].range[0] - 2, node.expressions[0].range[1] + 1, From 61492e378934e4f2c4fda42f9830e1b74cdae289 Mon Sep 17 00:00:00 2001 From: Ronen Amiel Date: Mon, 23 Sep 2024 21:35:57 +0300 Subject: [PATCH 3/3] Update packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts Co-authored-by: Kirk Waiblinger --- .../src/rules/no-unnecessary-template-expression.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts b/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts index a45cade4c9a7..212e44dfdadb 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts @@ -253,7 +253,6 @@ export default createRule<[], MessageId>({ const warnLocEnd = nextQuasi.range[0] + 1; context.report({ - node: expression, loc: rangeToLoc(context.sourceCode, [warnLocStart, warnLocEnd]), messageId: 'noUnnecessaryTemplateExpression', fix(fixer): TSESLint.RuleFix[] { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy