Skip to content

Commit 7d9e8f4

Browse files
committed
treat corner cases
1 parent 882e616 commit 7d9e8f4

5 files changed

+85
-11
lines changed

src/services/refactors/convertStringOrTemplateLiteral.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
88
const toTemplateLiteralDescription = getLocaleSpecificMessage(Diagnostics.Convert_to_template_literal);
99
const toStringConcatenationDescription = getLocaleSpecificMessage(Diagnostics.Convert_to_string_concatenation);
1010

11-
// TODO let a = 45 - 45 + " ee" - 33;
12-
1311
registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
1412

1513
function getAvailableActions(context: RefactorContext): ReadonlyArray<ApplicableRefactorInfo> {
@@ -19,7 +17,7 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
1917
const maybeTemplateExpression = findAncestor(node, n => isTemplateExpression(n));
2018
const actions: RefactorActionInfo[] = [];
2119

22-
if ((isBinaryExpression(maybeBinary) || isStringLiteral(maybeBinary)) && containsString(maybeBinary)) {
20+
if ((isBinaryExpression(maybeBinary) || isStringLiteral(maybeBinary)) && isStringConcatenationValid(maybeBinary)) {
2321
actions.push({ name: toTemplateLiteralActionName, description: toTemplateLiteralDescription });
2422
}
2523

@@ -39,7 +37,6 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
3937
const maybeBinary = getParentBinaryExpression(node);
4038
const arrayOfNodes = treeToArray(maybeBinary)[0];
4139
const templateLiteral = nodesToTemplate(arrayOfNodes);
42-
4340
const edits = textChanges.ChangeTracker.with(context, t => t.replaceNode(file, maybeBinary, templateLiteral));
4441
return { edits };
4542

@@ -97,7 +94,7 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
9794
const left = nodes[0];
9895
const right = nodes[1];
9996

100-
const binary = createBinary (left, SyntaxKind.PlusToken, right);
97+
const binary = createBinary(left, SyntaxKind.PlusToken, right);
10198
return arrayToTree(nodes.slice(2), binary);
10299
}
103100

@@ -106,16 +103,25 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
106103
return arrayToTree(nodes.slice(1), binary);
107104
}
108105

109-
function treeToArray(node: Node): [Node[], boolean] {
106+
function isStringConcatenationValid(node: Node): boolean {
107+
const [, containsString, areOperatorsValid] = treeToArray(node);
108+
return containsString && areOperatorsValid;
109+
}
110+
111+
function treeToArray(node: Node): [Node[], /* containsString */ boolean, /* areOperatorsValid */ boolean] {
110112
if (isBinaryExpression(node)) {
111-
const [leftNodes, leftHasString] = treeToArray(node.left);
112-
const [rightNodes, rightHasString] = treeToArray(node.right);
113+
const [leftNodes, leftHasString, leftOp] = treeToArray(node.left);
114+
const [rightNodes, rightHasString, rightOp] = treeToArray(node.right);
115+
116+
if (!leftHasString && !rightHasString) return [[node], false, true];
117+
118+
const currentOp = node.operatorToken.kind === SyntaxKind.PlusToken;
119+
const isPlus = leftOp && currentOp && rightOp;
113120

114-
if (!leftHasString && !rightHasString) return [[node], false];
115-
return [leftNodes.concat(rightNodes), true];
121+
return [leftNodes.concat(rightNodes), true, isPlus];
116122
}
117123

118-
return [[node], isStringLiteral(node)];
124+
return [[node], isStringLiteral(node), true];
119125
}
120126

121127
function nodesToTemplate(nodes: Node[]) {
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const age = 22
4+
//// const name = "Eddy"
5+
//// const /*z*/f/*y*/oo = /*x*/"/*w*/M/*v*/r/*u*/ " /*t*/+/*s*/ name + " is " - /*r*/a/*q*/ge - " years old"
6+
7+
goTo.select("z", "y");
8+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
9+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
10+
11+
goTo.select("x", "w");
12+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
13+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
14+
15+
goTo.select("v", "u");
16+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
17+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
18+
19+
goTo.select("t", "s");
20+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
21+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
22+
23+
goTo.select("r", "q");
24+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
25+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const /*z*/f/*y*/oo = /*x*/4/*w*/2 /*v*/-/*u*/ 56 + /*t*/2/*s*/2 * 4 / 33
4+
5+
goTo.select("z", "y");
6+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
7+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
8+
9+
goTo.select("x", "w");
10+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
11+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
12+
13+
goTo.select("v", "u");
14+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
15+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
16+
17+
goTo.select("t", "s");
18+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
19+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// const age = 22
4+
//// const /*z*/f/*y*/oo = /*x*/a/*w*/ge * 4 /*v*/-/*u*/ 2 / 4 /*t*/+/*s*/ " /*r*/y/*q*/ears old"
5+
6+
goTo.select("z", "y");
7+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
8+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
9+
10+
goTo.select("x", "w");
11+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
12+
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
13+
14+
goTo.select("v", "u");
15+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
16+
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
17+
18+
goTo.select("t", "s");
19+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
20+
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");
21+
22+
goTo.select("r", "q");
23+
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
24+
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

0 commit comments

Comments
 (0)