Support converting string literals to templates outside of concatenation (#54647)

This commit is contained in:
Jake Bailey
2023-09-21 11:16:26 -07:00
committed by GitHub
parent f3dad2a07d
commit 45a05f3475
5 changed files with 69 additions and 4 deletions

View File

@@ -7564,7 +7564,7 @@
"category": "Message",
"code": 95153
},
"Can only convert string concatenation": {
"Can only convert string concatenations and string literals": {
"category": "Message",
"code": 95154
},

View File

@@ -15,6 +15,7 @@ import {
getTokenAtPosition,
getTrailingCommentRanges,
isBinaryExpression,
isExpressionNode,
isNoSubstitutionTemplateLiteral,
isParenthesizedExpression,
isStringLiteral,
@@ -58,14 +59,19 @@ function getRefactorActionsToConvertToTemplateString(context: RefactorContext):
const { file, startPosition } = context;
const node = getNodeOrParentOfParentheses(file, startPosition);
const maybeBinary = getParentBinaryExpression(node);
const nodeIsStringLiteral = isStringLiteral(maybeBinary);
const refactorInfo: ApplicableRefactorInfo = { name: refactorName, description: refactorDescription, actions: [] };
if (isBinaryExpression(maybeBinary) && treeToArray(maybeBinary).isValidConcatenation) {
if (nodeIsStringLiteral && context.triggerReason !== "invoked") {
return emptyArray;
}
if (isExpressionNode(maybeBinary) && (nodeIsStringLiteral || isBinaryExpression(maybeBinary) && treeToArray(maybeBinary).isValidConcatenation)) {
refactorInfo.actions.push(convertStringAction);
return [refactorInfo];
}
else if (context.preferences.provideRefactorNotApplicableReason) {
refactorInfo.actions.push({ ...convertStringAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Can_only_convert_string_concatenation) });
refactorInfo.actions.push({ ...convertStringAction, notApplicableReason: getLocaleSpecificMessage(Diagnostics.Can_only_convert_string_concatenations_and_string_literals) });
return [refactorInfo];
}
return emptyArray;

View File

@@ -0,0 +1,37 @@
/// <reference path='fourslash.ts' />
//// import * as a from "/*1a*/f/*1b*/oobar";
//// export * as b from "/*2a*/f/*2b*/oobar";
//// import * as c from "foobar" assert { "/*3a*/f/*3b*/oobar": "something" };
//// import * as d from "foobar" assert { "something": "/*4a*/f/*4b*/oobar" };
////
//// let x = {
//// "/*5a*/f/*5b*/oobar": 1234,
//// };
verify.getSyntacticDiagnostics([]);
goTo.select("1a", "1b");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);
goTo.select("2a", "2b");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);
goTo.select("3a", "3b");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);
goTo.select("4a", "4b");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);
goTo.select("5a", "5b");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);

View File

@@ -3,4 +3,15 @@
//// const foo = "/*x*/f/*y*/oobar rocks"
goTo.select("x", "y");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);
edit.applyRefactor({
refactorName: "Convert to template string",
actionName: "Convert to template string",
actionDescription: ts.Diagnostics.Convert_to_template_string.message,
triggerReason: "invoked",
newContent:
`const foo = \`foobar rocks\``,
});

View File

@@ -4,3 +4,14 @@
goTo.select("x", "y");
verify.not.refactorAvailable(ts.Diagnostics.Convert_to_template_string.message);
verify.refactorAvailableForTriggerReason("invoked", ts.Diagnostics.Convert_to_template_string.message);
verify.not.refactorAvailableForTriggerReason("implicit", ts.Diagnostics.Convert_to_template_string.message);
edit.applyRefactor({
refactorName: "Convert to template string",
actionName: "Convert to template string",
actionDescription: ts.Diagnostics.Convert_to_template_string.message,
triggerReason: "invoked",
newContent:
`const foo = \`foobar rocks\``,
});