diff --git a/src/services/refactors/inlineVariable.ts b/src/services/refactors/inlineVariable.ts index 2b0b43bf426..7595387b3e8 100644 --- a/src/services/refactors/inlineVariable.ts +++ b/src/services/refactors/inlineVariable.ts @@ -20,6 +20,9 @@ import { isFunctionLike, isIdentifier, isInitializedVariable, + isNumericLiteral, + isObjectLiteralExpression, + isPropertyAccessExpression, isTypeQueryNode, isVariableDeclarationInVariableStatement, isVariableStatement, @@ -228,7 +231,13 @@ function getReplacementExpression(reference: Node, replacement: Expression): Exp // Functions also need to be parenthesized. // E.g.: const f = () => {}; f(); -> (() => {})(); - if (isFunctionLike(replacement) && isCallLikeExpression(parent)) { + if (isFunctionLike(replacement) && (isCallLikeExpression(parent) || isPropertyAccessExpression(parent))) { + return factory.createParenthesizedExpression(replacement); + } + + // Property access of numeric literals and objects need parentheses. + // E.g.: const x = 1; x.toString(); -> (1).toString(); + if (isPropertyAccessExpression(parent) && (isNumericLiteral(replacement) || isObjectLiteralExpression(replacement))) { return factory.createParenthesizedExpression(replacement); } diff --git a/tests/cases/fourslash/inlineVariableNoParensPropertyAccess.ts b/tests/cases/fourslash/inlineVariableNoParensPropertyAccess.ts new file mode 100644 index 00000000000..f4b2cc56817 --- /dev/null +++ b/tests/cases/fourslash/inlineVariableNoParensPropertyAccess.ts @@ -0,0 +1,27 @@ +/// + +////const /*a1*/foo/*b1*/ = "foo"; +////console.log(foo.length); +////const /*a2*/notTrue/*b2*/ = false; +////notTrue.valueOf(); + +goTo.select("a1", "b1"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: `console.log("foo".length); +const notTrue = false; +notTrue.valueOf();` +}); + +goTo.select("a2", "b2"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: `console.log("foo".length); +false.valueOf();` +}); diff --git a/tests/cases/fourslash/inlineVariableParensBinExpression.ts b/tests/cases/fourslash/inlineVariableParensBinExpression.ts new file mode 100644 index 00000000000..a83d34a7630 --- /dev/null +++ b/tests/cases/fourslash/inlineVariableParensBinExpression.ts @@ -0,0 +1,13 @@ +/// + +////const /*a*/x/*b*/ = 1 + 2; +////const y = x * 3; + +goTo.select("a", "b"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: "const y = (1 + 2) * 3;" +}); \ No newline at end of file diff --git a/tests/cases/fourslash/inlineVariableNeedsParens.ts b/tests/cases/fourslash/inlineVariableParensFunctions.ts similarity index 62% rename from tests/cases/fourslash/inlineVariableNeedsParens.ts rename to tests/cases/fourslash/inlineVariableParensFunctions.ts index 6d4edfa1288..5b85e64b61a 100644 --- a/tests/cases/fourslash/inlineVariableNeedsParens.ts +++ b/tests/cases/fourslash/inlineVariableParensFunctions.ts @@ -1,9 +1,9 @@ /// -////const /*a1*/x/*b1*/ = 1 + 2; -////const y = x * 3; -////const /*a2*/f/*b2*/ = () => { }; -////f(); +////const /*a1*/foo/*b1*/ = () => { }; +////foo(); +////const /*a2*/bar/*b2*/ = function() { }; +////bar.call(null); goTo.select("a1", "b1"); verify.refactorAvailable("Inline variable"); @@ -11,9 +11,9 @@ edit.applyRefactor({ refactorName: "Inline variable", actionName: "Inline variable", actionDescription: "Inline variable", - newContent: `const y = (1 + 2) * 3; -const f = () => { }; -f();` + newContent: `(() => { })(); +const bar = function() { }; +bar.call(null);` }); goTo.select("a2", "b2"); @@ -22,6 +22,6 @@ edit.applyRefactor({ refactorName: "Inline variable", actionName: "Inline variable", actionDescription: "Inline variable", - newContent: `const y = (1 + 2) * 3; -(() => { })();` + newContent: `(() => { })(); +(function() { }).call(null);` }); \ No newline at end of file diff --git a/tests/cases/fourslash/inlineVariableParensNewExpression.ts b/tests/cases/fourslash/inlineVariableParensNewExpression.ts new file mode 100644 index 00000000000..4c63051c6a2 --- /dev/null +++ b/tests/cases/fourslash/inlineVariableParensNewExpression.ts @@ -0,0 +1,23 @@ +/// + +// @Filename: /a.ts +////export function foo() { +//// class Foo { function bar() { } } +//// return Foo; +////} + +// @Filename: /b.ts +////import * as a from "./a"; +////const /*a*/foo/*b*/ = a.foo(); +////new foo.bar(); + +goTo.file("/b.ts"); +goTo.select("a", "b"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: `import * as a from "./a"; +new (a.foo()).bar();` +}); diff --git a/tests/cases/fourslash/inlineVariableParensPropertyAccess.ts b/tests/cases/fourslash/inlineVariableParensPropertyAccess.ts new file mode 100644 index 00000000000..e8e53c502d5 --- /dev/null +++ b/tests/cases/fourslash/inlineVariableParensPropertyAccess.ts @@ -0,0 +1,44 @@ +/// + +////const /*a1*/foo/*b1*/ = {}; +////foo.toString(); +////const /*a2*/bar/*b2*/ = 0; +////bar.toFixed().toString(); +////const /*a3*/pi/*b3*/ = 3.1416; +////pi.toPrecision(2); + +goTo.select("a1", "b1"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: `({}).toString(); +const bar = 0; +bar.toFixed().toString(); +const pi = 3.1416; +pi.toPrecision(2);` +}); + +goTo.select("a2", "b2"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: `({}).toString(); +(0).toFixed().toString(); +const pi = 3.1416; +pi.toPrecision(2);` +}); + +goTo.select("a3", "b3"); +verify.refactorAvailable("Inline variable"); +edit.applyRefactor({ + refactorName: "Inline variable", + actionName: "Inline variable", + actionDescription: "Inline variable", + newContent: `({}).toString(); +(0).toFixed().toString(); +(3.1416).toPrecision(2);` +});