8000 fix(eslint-plugin): [no-unnecessary-template-expression] add missing … · jakebailey/typescript-eslint@90655d1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 90655d1

Browse files
fix(eslint-plugin): [no-unnecessary-template-expression] add missing parentheses in autofix (typescript-eslint#8673)
* fix: precedence concider with parentheses * refactor: seperate replaceNodeText fn * refactor: make getWrappingCode fn * fix: make new fn * fix: revert getWrappingFixer and make getWrappingCode * fix: lint error fix * fix: lint error fix * fix: lint error fix * fix: lint error fix * refactor: change getMovedNodeCode function * fix: confict resolve * feat: copy work to no-unnessary-template-expression --------- Co-authored-by: Kirk Waiblinger <kirk.waiblinger@gmail.com>
1 parent 7440e14 commit 90655d1

File tree

3 files changed

+49
-17
lines changed

3 files changed

+49
-17
lines changed

packages/eslint-plugin/src/rules/no-unnecessary-template-expression.ts

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import * as ts from 'typescript';
55
import {
66
createRule,
77
getConstrainedTypeAtLocation,
8+
getMovedNodeCode,
89
getParserServices,
910
isTypeFlagSet,
1011
isUndefinedIdentifier,
@@ -106,21 +107,14 @@ export default createRule<[], MessageId>({
106107
context.report({
107108
node: node.expressions[0],
108109
messageId: 'noUnnecessaryTemplateExpression',
109-
fix(fixer): TSESLint.RuleFix[] {
110-
const [prevQuasi, nextQuasi] = node.quasis;
111-
112-
// Remove the quasis and backticks.
113-
return [
114-
fixer.removeRange([
115-
prevQuasi.range[1] - 3,
116-
node.expressions[0].range[0],
117-
]),
118-
119-
fixer.removeRange([
120-
node.expressions[0].range[1],
121-
nextQuasi.range[0] + 2,
122-
]),
123-
];
110+
fix(fixer): TSESLint.RuleFix | null {
111+
const wrappingCode = getMovedNodeCode({
112+
sourceCode: context.sourceCode,
113+
nodeToMove: node.expressions[0],
114+
destinationNode: node,
115+
});
116+
117+
return fixer.replaceText(node, wrappingCode);
124118
},
125119
});
126120

packages/eslint-plugin/src/util/getWrappingFixer.ts

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,33 @@ export function getWrappingFixer(
7474
return fixer.replaceText(node, code);
7575
};
7676
}
77+
/**
78+
* If the node to be moved and the destination node require parentheses, include parentheses in the node to be moved.
79+
* @param sourceCode Source code of current file
80+
* @param nodeToMove Nodes that need to be moved
81+
* @param destinationNode Final destination node with nodeToMove
82+
* @returns If parentheses are required, code for the nodeToMove node is returned with parentheses at both ends of the code.
83+
*/
84+
export function getMovedNodeCode(params: {
85+
sourceCode: Readonly<TSESLint.SourceCode>;
86+
nodeToMove: TSESTree.Node;
87+
destinationNode: TSESTree.Node;
88+
}): string {
89+
const { sourceCode, nodeToMove: existingNode, destinationNode } = params;
90+
const code = sourceCode.getText(existingNode);
91+
if (isStrongPrecedenceNode(existingNode)) {
92+
// Moved node never needs parens
93+
return code;
94+
}
95+
96+
if (!isWeakPrecedenceParent(destinationNode)) {
97+
// Destination would never needs parens, regardless what node moves there
98+
return code;
99+
}
100+
101+
// Parens may be necessary
102+
return `(${code})`;
103+
}
77104

78105
/**
79106
* Check if a node will always have the same precedence if it's parent changes.
@@ -98,8 +125,10 @@ export function isStrongPrecedenceNode(innerNode: TSESTree.Node): boolean {
98125
* Check if a node's parent could have different precedence if the node changes.
99126
*/
100127
function isWeakPrecedenceParent(node: TSESTree.Node): boolean {
101-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
102-
const parent = node.parent!;
128+
const parent = node.parent;
129+
if (!parent) {
130+
return false;
131+
}
103132

104133
if (
105134
parent.type === AST_NODE_TYPES.UpdateExpression ||

packages/eslint-plugin/tests/rules/no-unnecessary-template-expression.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,5 +1127,14 @@ declare const nested: string, interpolation: string;
11271127
},
11281128
],
11291129
},
1130+
{
1131+
code: "true ? `${'test' || ''}`.trim() : undefined;",
1132+
output: "true ? ('test' || '').trim() : undefined;",
1133+
errors: [
1134+
{
1135+
messageId: 'noUnnecessaryTemplateExpression',
1136+
},
1137+
],
1138+
},
11301139
],
11311140
});

0 commit comments

Comments
 (0)
0