refactor creation of template expression

This commit is contained in:
BigAru 2019-03-24 15:24:04 +01:00
parent 29fc8c30ba
commit 2a15acbbfd
34 changed files with 54 additions and 29 deletions

View file

@ -14,19 +14,21 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
const { file, startPosition } = context;
const node = getNodeOrParentOfParentheses(file, startPosition);
const maybeBinary = getParentBinaryExpression(node);
const actions: RefactorActionInfo[] = [];
const refactorInfo: ApplicableRefactorInfo = { name: refactorName, description: refactorDescription, actions: [] };
if ((isBinaryExpression(maybeBinary) || isStringLiteral(maybeBinary)) && isStringConcatenationValid(maybeBinary)) {
actions.push({ name: toTemplateLiteralActionName, description: toTemplateLiteralDescription });
refactorInfo.actions.push({ name: toTemplateLiteralActionName, description: toTemplateLiteralDescription });
return [refactorInfo];
}
const templateLiteral = findAncestor(node, n => isTemplateLiteral(n));
if (templateLiteral && !isTaggedTemplateExpression(templateLiteral.parent)) {
actions.push({ name: toStringConcatenationActionName, description: toStringConcatenationDescription });
refactorInfo.actions.push({ name: toStringConcatenationActionName, description: toStringConcatenationDescription });
return [refactorInfo];
}
return [{ name: refactorName, description: refactorDescription, actions }];
return emptyArray;
}
function getNodeOrParentOfParentheses(file: SourceFile, startPosition: number) {
@ -137,46 +139,35 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
return { nodes: [node as Expression], containsString: isStringLiteral(node), areOperatorsValid: true };
}
function createHead(nodes: ReadonlyArray<Expression>): [number, TemplateHead] {
let begin = 0;
function concatConsecutiveString(index: number, nodes: ReadonlyArray<Expression>): [number, string] {
let text = "";
while (begin < nodes.length && isStringLiteral(nodes[begin])) {
const next = nodes[begin] as StringLiteral;
text = text + decodeRawString(next.getText());
begin++;
while (index < nodes.length && isStringLiteral(nodes[index])) {
text = text + decodeRawString(nodes[index].getText());
index++;
}
text = escapeText(text);
return [begin, createTemplateHead(text)];
return [index, text];
}
function nodesToTemplate(nodes: ReadonlyArray<Expression>) {
const templateSpans: TemplateSpan[] = [];
const [begin, head] = createHead(nodes);
const [begin, headText] = concatConsecutiveString(0, nodes);
const templateHead = createTemplateHead(headText);
if (begin === nodes.length) {
return createNoSubstitutionTemplateLiteral(head.text);
}
if (begin === nodes.length) return createNoSubstitutionTemplateLiteral(headText);
for (let i = begin; i < nodes.length; i++) {
let current = nodes[i];
let text = "";
const expression = isParenthesizedExpression(nodes[i]) ? (nodes[i] as ParenthesizedExpression).expression : nodes[i];
const [newIndex, subsequentText] = concatConsecutiveString(i + 1, nodes);
i = newIndex - 1;
while (i + 1 < nodes.length && isStringLiteral(nodes[i + 1])) {
const next = nodes[i + 1] as StringLiteral;
text = text + decodeRawString(next.getText());
i++;
}
text = escapeText(text);
const templatePart = i === nodes.length - 1 ? createTemplateTail(text) : createTemplateMiddle(text);
if (isParenthesizedExpression(current)) current = current.expression;
templateSpans.push(createTemplateSpan(current, templatePart));
const templatePart = i === nodes.length - 1 ? createTemplateTail(subsequentText) : createTemplateMiddle(subsequentText);
templateSpans.push(createTemplateSpan(expression, templatePart));
}
return createTemplateExpression(head, templateSpans);
return createTemplateExpression(templateHead, templateSpans);
}
const octalToUnicode = (_match: string, grp: string) => String.fromCharCode(parseInt(grp, 8));
@ -196,3 +187,4 @@ namespace ts.refactor.convertStringOrTemplateLiteral {
}
}

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`console.log("foobar is " + 32 + " years old")`,
});

View file

@ -27,3 +27,4 @@ verify.not.refactorAvailable("Convert string concatenation or template literal",
goTo.select("p", "o");
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

View file

@ -15,3 +15,4 @@ verify.not.refactorAvailable("Convert string concatenation or template literal",
goTo.select("v", "u");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = "foobar is " + (42 + 6) + " years old"`,
});

View file

@ -14,3 +14,4 @@ edit.applyRefactor({
const name = "Eddy"
const foo = name + " is " + age + " years old"`,
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = \`foobar is a \${ age < 18 ? 'child' : "grown-up " + (age > 40 ? 'who needs probably assistance' : '') }\``,
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = \`foobar is a \${ "34" }\``,
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = "foobar is a " + (age < 18 ? 'child' : \`grown-up \${age > 40 ? 'who needs probaply assistance' : ''}\`)`,
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = "foobar is " + age + " years old"`,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = "foobar is " + 42 * 6 % 4 + " years old"`,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = "foobar is " + 42 + 6 + " years old"`,
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = "foobar is " + age + " years old"`,
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = "foobar is " + age + " years old " + false`,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = "foobar rocks"`,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`console.log(\`foobar is \${32} years old\`)`,
});

View file

@ -23,3 +23,4 @@ verify.not.refactorAvailable("Convert string concatenation or template literal",
goTo.select("r", "q");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

View file

@ -17,3 +17,4 @@ verify.not.refactorAvailable("Convert string concatenation or template literal",
goTo.select("t", "s");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

View file

@ -22,3 +22,4 @@ verify.refactorAvailable("Convert string concatenation or template literal", "Co
goTo.select("r", "q");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

View file

@ -14,3 +14,4 @@ verify.refactorAvailable("Convert string concatenation or template literal", "Co
goTo.select("v", "u");
verify.not.refactorAvailable("Convert string concatenation or template literal", "Convert to string concatenation");
verify.refactorAvailable("Convert string concatenation or template literal", "Convert to template literal");

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
"const foo = `with back\\`tick`",
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar is \${42 + 6} years old\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
"const foo = `foobar is \${42 + 6}`",
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar is \${42} years old and \${6} cars are missing\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar is \${42 + 6} years old\``,
});

View file

@ -14,3 +14,4 @@ edit.applyRefactor({
const name = "Eddy"
const foo = \`\${name} is \${age} years old\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
"const foo = `Octal #`;",
});

View file

@ -12,3 +12,4 @@ edit.applyRefactor({
`const age = 42
const foo = \`foobar is \${age} years old\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
"const foo = `foobar rocks fantastically`",
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar is \${42 * 6 / 4} years old\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar is \${42}\${6} years old\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`\${42 - 6 * 4 + 23 / 12} years old\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar rocks\``,
});

View file

@ -10,3 +10,4 @@ edit.applyRefactor({
newContent:
`const foo = \`foobar rocks\``,
});